알라딘이 책 판매를 넘어서는 어떤 비전을 가지고 있는지는 모르겠지만,


자주, 정기적으로 접속하는 여러 사이트, 서비스 중에 알라딘 장바구니처럼 자주 다운되고 불안정한 페이지는 없는 것 같다.


장바구니에서 책 한 권을 지우려 해도 거의 항상, 매번 페이지가 다운된다. 수십 분씩 다운되는 일이 허다하다. 영 돌아오지 않을 것 같을 때는 '작업관리자'를 켜서 강제 종료시키는데, 오늘은 작업관리자 창마저 거듭 다운시켜 버리는 위력에 기가 찼다. 이 글을 쓰는 데도 몇 시간이 걸렸는지 모르겠다. 내 컴퓨터 사양이 아주 떨어지는 것도 아닌데 말이다.


책 한 권 한 권마다 아래와 같은 코드를 쓰고 있는데, 평소 장바구니에 책을 많이 넣어두는 사람에게는 너무 무거운 것 같다. 군더더기와 이미지 개수를 줄이고, 개별 이미지도 크기를 가볍게 했으면 좋겠다. 이미 장바구니에 넣었는데, 굳이 책 이미지를 볼 필요가 있나도 싶다. 사용자가 장바구니에 책 이미지를 표시할지 말지 고를 수 있게 해도 좋을 것 같다. 장바구니에 책을 담는 것까지는 괜찮은데, 삭제 등 장바구니 관리가 너무너무 어렵다. 페이지 전체에 정보가 너무 많다. 아무튼 무게를 확 줄여야 한다.


덧붙여, 책 검색도 너무 경직되어 있다. 아주 조금만 검색어가 어긋나도 검색 결과를 전혀 돌려주지 못한다. ChatGPT에 Clova X에 시대가 어떻게 변하고 있는데 이렇게 맹탕이다.


아마존 같은 테크 기업이 되는 건 기대도 안 한다.

대안이 마땅치 않아 의존하고는 있지만, 아무튼 심히 불만스럽다.



---------- 알라딘 장바구니의 책 한 권마다 들어가는 html 코드 ----------


<tr id="CartTr_189641292">

    <td align="center" width="46">

        <input type="checkbox" checked="" name="chkCart.K972635587" class="ShopCode_Basket_Check basket_CheckBox" pricesales="26100" qty="1" mileage="1450" dcprice="2900" itemid="189641292" onclick="BasketSalseSummary(0);">

        <input type="hidden" name="hidCart.K972635587" value="189641292">

    </td>

    <td width="48" bgcolor="#ffffff">

        <a href="https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=189641292" title="밑바닥부터 시작하는 딥러닝 2">

            <img src="https://image.aladin.co.kr/product/18964/12/covermini/k972635587_1.jpg" style="width:48px;">

        </a>

    </td>

    <td width="*" bgcolor="#ffffff" align="left">

        <span class="basket_tit">

            <a href="https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=189641292" style="color:#386DA1;">[국내도서] 밑바닥부터 시작하는 딥러닝 2</a> - 파이썬으로 직접 구현하며 배우는 순환 신경망과 자연어 처리

        </span>

        <a href="https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=189641292" target="_blank">

            <img src="//image.aladin.co.kr/img/common/btn_newwindow.gif" style="vertical-align:sub;">

        </a> 

        <a href="http://www.aladin.co.kr/events/wevent.aspx?EventId=179240">

            <span class="label_deduct">소득공제</span>

        </a><br>

        <span>

            <table cellpadding="0" cellspacing="0" border="0" width="100%">

                <tbody>

                    <tr>

                        <td>

                            <span class="expDeliveryItem">* 내일 밤 11시 잠들기전 배송</span>

                        </td>

                    </tr>

                </tbody>

            </table>

        </span>

        <font color="#f26122">스프링 분철 선택 가능</font>

        <div id="btn_189641292" class="button">

            <a class="button_small" href="javascript:void(0);" onclick="BasketOptionLayer(2, 189641292, 0);">변경</a>

        </div>

    </td>

    <td width="130" bgcolor="#ffffff" align="left">

        정가 : <s>29,000</s>원<br>

        판매가 : <span class="p1">26,100</span>원<br>

        마일리지 : <span class="p2">1,450</span>원 (<span class="p2">5%</span>)

    </td>

    <td width="90" align="center" bgcolor="#ffffff">

        <div class="ordernumber_box">

            <div class="Hleft2">

                <div class="number1">

                    <input type="text" size="2" value="1" name="OrderQty.K972635587" class="input1" onkeydown="QtyApply_Enter(event, 'K972635587', 0);" onfocusout="QtyApply_Focus('K972635587', 0);" onclick="QtyLayerOpen('K972635587');" autocomplete="off" spellcheck="false" data-ms-editor="true">

                    <img id="Arrow_K972635587" src="//image.aladin.co.kr/img/order/2019/icon_arrow_down_order.png" onclick="QtyLayerOpen('K972635587');" align="absmiddle" style="float:right;margin:6px 0px 0 0;cursor:pointer;">

                    <div style="clear:both"></div>

                </div>

            </div>

            <div id="QtyLayer_K972635587" class="list1" style="position:absolute; z-index:99;top:27px;left:5px;display:none;">

                <ul>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 1);" style="color:#222">

                        <li>1</li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 2);" style="color:#222">

                        <li>2</li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 3);" style="color:#222">

                        <li>3</li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 4);" style="color:#222">

                        <li>&4lt;/li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 5);" style="color:#222">

                        <li>5</li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 6);" style="color:#222">

                        <li>&6lt;/li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 7);" style="color:#222">

                        <li>&7lt;/li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 8);" style="color:#222">

                        <li>8</li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 9);" style="color:#222">

                        <li>&9lt;/li>

                    </a>

                    <a href="javascript:void(0);" onmousedown="QtyApply_Layer('K972635587', 0, 10);" style="color:#222">

                        <li>10</li>

                    </a>

                </ul>

            </div>

        </div>

    </td>

    <td width="90" align="center" bgcolor="#ffffff">

        <table cellspacing="0" cellpadding="1" border="0">

            <tbody>

                <tr>

                    <td align="center" width="48">

                        <div class="button_gray">

                            <a class="button_small" href="javascript:void(0);" onclick="BasketDelete(189641292, 0);">삭제</a>

                        </div>

                    </td>

                </tr>

                <tr>

                    <td align="center">

                        <div class="button_gray">

                            <a class="button_small" href="javascript:void(0);" onclick="SafeKeepSingle_Add('756067871','K972635587','False')">보관</a>

                        </div>

                    </td>

                </tr>

            </tbody>

        </table>

    </td>

</tr>



이왕 쓴 김에 ChatGPT가 제안한 해결책도 써둔다(내가 전문적으로 판단할 역량은 없지만, 답변 결과를 일부 수정하였다). + 답변 내용 수정, 추가

---------- ChatGPT가 제안한 해결방안 ----------


제시해주신 HTML 코드를 바탕으로 문제와 최적화 방안을 정리해보겠습니다.


1. JavaScript 함수 호출: 해당 코드에서는 여러 자바스크립트 함수가 호출되는데, 특히 삭제 버튼을 클릭하면 BasketDelete(189641292, 0); 함수가 실행됩니다. 이 함수는 삭제 기능을 처리하는 것으로 보이는데, 문제가 발생하면 해당 함수를 첫 번째로 살펴보아야 합니다.


2. 서버 응답: 삭제 버튼을 클릭하면 서버에 요청을 보내 해당 아이템을 장바구니에서 삭제하는 요청을 처리하게 될 것입니다. 서버의 응답이 느린 경우, 혹은 서버에서 오류 응답을 반환하는 경우 문제가 발생할 수 있습니다.


3. 코드 복잡성: 주어진 코드는 하나의 책에 대한 정보와 연관된 버튼, 이미지 등의 세부 요소를 표현합니다. 코드 자체는 복잡성이 크게 높지 않으나, 이런 형식의 코드가 1,000번 반복된다면 전체 HTML 문서의 크기가 커져 로딩 속도에 영향을 줄 수 있습니다.


3-1. DOM 구조: tr 태그 안에 있는 각각의 td는 장바구니의 한 아이템에 대한 정보나 기능을 나타냅니다. DOM의 구조나 스타일이 복잡하면 이로 인해 페이지의 반응 속도가 느려질 수 있습니다.


4. 이미지 로딩: 코드에 포함된 이미지 링크들(책 표지 이미지, 새 창 아이콘, 화살표 아이콘 등)은 페이지 로딩 시간에 큰 영향을 미칠 수 있습니다. 각 이미지의 크기가 크거나, 이미지의 수가 많을 경우 로딩 시간이 증가합니다.



해결 방안:


1. JavaScript 최적화:

  - 'BasketDelete'와 같은 관련 자바스크립트 함수의 동작을 확인합니다.

  - 필요한 경우 개발자 도구의 Network 탭과 Console 탭에서 오류나 경고 메시지를 확인합니다.

  - JavaScript 함수는 외부 파일로 분리하여 필요할 때만 로드하게 합니다.

  - 비동기 로딩: 필요한 부분만 AJAX, Fetch API, async, defer 등을 이용해 동적으로 로드합니다.

  - 이벤트 위임을 사용하여 동일한 이벤트 핸들러를 여러 요소에 적용하는 대신 상위 요소에 한 번만 적용합니다.


cf. 추가 질문 내용 보충

 (1) AJAX (Asynchronous JavaScript and XML):

   - 웹 페이지를 다시 로드하지 않고도 서버와 비동기적으로 데이터를 교환할 수 있는 방법입니다.

   - XMLHttpRequest 객체를 사용하여 구현합니다.

   - 주로 XML 혹은 JSON 데이터 형식으로 데이터를 주고 받지만, 다른 형식도 가능합니다.

   - 페이지의 일부만 업데이트 할 때 주로 사용됩니다.

  (2) Fetch API:

   - 서버와 비동기적으로 통신하는데 사용되는 모던한 API입니다.

   - XMLHttpRequest의 대체제로 생각될 수 있으며, 보다 간결하고 유연한 API를 제공합니다.

   - Promise 기반으로 동작하며, async/await와 함께 사용하여 가독성 좋은 코드를 작성할 수 있습니다.

  (3) async (attribute in script tag): 

   - HTML에서 script 태그에 사용되는 속성입니다.

   - async 속성이 있는 스크립트는 페이지의 파싱과 동시에 다운로드되며, 다운로드 완료 즉시 실행됩니다.

   - 페이지의 파싱을 막지 않기 때문에 비동기적으로 로딩되는 효과가 있습니다.

  (4) defer (attribute in script tag):

   - HTML에서 script 태그에 사용되는 속성입니다.

   - defer 속성이 있는 스크립트는 페이지의 파싱과 동시에 다운로드되지만, 파싱이 완전히 끝난 후에 실행됩니다.

   - 스크립트의 순서가 중요할 때 유용하게 사용됩니다. (즉, 여러 개의 defer 스크립트는 순서대로 실행됩니다.)


요약하면, AJAX와 Fetch API는 웹 페이지와 서버 간의 비동기 통신을 위한 방법이며, async와 defer는 script 태그의 다운로드와 실행 방식을 제어하는 속성입니다.


2. 서버 응답 문제: 삭제 버튼을 클릭했을 때 서버에서 적절한 응답을 하지 않거나 지연될 수 있습니다.

  - 서버의 로그를 확인하여 오류 메시지나 원인을 찾습니다.

  - 서버의 처리 속도가 느릴 경우, 백엔드 최적화를 고려합니다. 데이터베이스 쿼리 최적화, 서버 설정 최적화 등을 통해 서버 응답 시간을 줄입니다.

  - 서버에서 HTML을 미리 렌더링하여 클라이언트에게 전송함으로써 초기 로딩 속도를 향상시킬 수 있습니다.

  - CDN 사용: 이미지나 스크립트 파일을 분산된 서버에서 로드하여 로딩 속도를 향상시킵니다.


3. 코드 간소화, 캐싱: HTML 구조를 간단하게 만드는 것이 중요합니다.

  - 불필요한 div 또는 span 태그를 줄이는 등 불필요한 중첩된 태그 구조나 스타일을 최소화합니다.

  - CSS 스타일은 가능한 한 외부 파일로 분리합니다(이미 분리되어 있다면 중복 스타일 제거).

  - 웹페이지의 정적 리소스(CSS, JS, 이미지 등)에 대한 캐싱 정책을 설정합니다.

  - 데이터베이스 쿼리 결과에 대한 캐싱을 고려합니다. 


4. 이미지 등 페이지 성능 최적화:

  - 이미지의 크기와 해상도를 줄입니다.

  - 이미지의 포맷을 웹에 최적화된 형식으로 변경하여 로딩 시간을 줄일 수 있습니다. 예를 들면, JPEG나 PNG 이미지를 WebP 포맷으로 변경하는 것이 효과적일 수 있습니다.

  - 페이지 로딩 시 모든 이미지를 한 번에 로드하는 대신, 사용자의 스크롤 위치에 따라 필요한 이미지만 로드하는 Lazy Loading을 적용하여 초기 로딩 속도를 개선합니다.

  - 데이터 페이징: 1,000권의 책을 한 번에 표시하는 대신 페이지별로 나누어 표시합니다. 사용자가 필요한 부분만 로드하여 전체 로딩 시간을 줄입니다.


결론적으로, 웹 페이지의 성능 문제는 다양한 요인에 의해 발생할 수 있습니다. 따라서 개발자 도구의 Network 탭이나 Performance 탭을 사용하여 웹 페이지의 로딩 속도를 분석하고, 구체적인 문제점을 파악하는 것이 좋습니다.


---------------------------------------------


다음은 순서대로, (장바구니에서 책을 삭제하였을 때) 개발자 도구의 Network 탭, Performance 탭 캡쳐 화면(서재에 이미지를 첨부하려니 해상도가 떨어진다)





나도 알라딘을 이루는 일원이라는 생각이 있고, 애정이 있으니 쓴 글이다.

부디 알라딘 관계자가 진지하게 읽어주기 바란다.


읽어주시는 분들께서도 공감하시면 "좋아요" 눌러서 올려주시면 감사하겠습니다.


댓글(3) 먼댓글(0) 좋아요(23)
좋아요
북마크하기찜하기
 
 
머리쓰기&글쓰기 2023-08-26 00:34   좋아요 1 | 댓글달기 | URL
근래 북플도 며칠간 다운되었었죠...

묵향 2023-08-26 00:52   좋아요 0 | URL
그러게나 말입니다... 최근 더 느려진 것 같은 느낌적인 느낌도 듭니다...

묵향 2023-08-26 09:58   좋아요 0 | 댓글달기 | URL
글을 조금 수정하여, 해결책이 될 만한 방법을 썼습니다. ChatGPT가 제안해 준 방법들입니다.

https://blog.aladin.co.kr/SilentPaul/14856988 에도 글을 이어서 썼습니다.
 

일단 2019년에 나온 책이라는 데 높은 점수를 주고 싶다.



인간의 언어는 컴퓨터 프로그래밍 언어처럼 명확하지 않습니다. 우리는 언어의 모호성을 적극적으로 활용함으로써 의사소통의 효율을 극대화합니다. 예를 들어 우리는 정보나 단어를 생략하고 문장을 짧게 만들기도 하고, 같은 단어와 어절이라고 해도 때에 따라서는 다른 의미로 해석하기도 합니다. 더욱이 한국어의 경우에는 앞서 다루었듯이 어순이 불규칙하고 주어가 생략되는 등, 다른 언어에 비해 그 효율이 더욱 극대화되었습니다. - P305

사람의 경우에는 일반화 능력이 뛰어나므로 몇 가지 규칙만으로도 훌륭하게 적용하여 번역을 수행할 수 있지만, 컴퓨터의 경우에는 사람보다 일반화 능력이 현저히 떨어지므로 규칙 기반 기계번역은 매우 어렵습니다. 잘 만들어진 규칙 안에서는 통계 기반 기계번역에 비해 자연스러운 표현이 가능하지만, 그 규칙을 일일이 사람이 만들어내야 하므로 번역기를 만드는 데 많은 자원과 시간이 소모됩니다. 번역 언어쌍을 확장할 때도 매번 새로운 규칙을 찾아내고 적용해야 하므로 매우 불리합니다. - P306


댓글(0) 먼댓글(0) 좋아요(8)
좋아요
북마크하기찜하기 thankstoThanksTo
 
 
 

7 비지학습 -> 비지도학습(이 아닐지...)

(수시로 추가 예정)



댓글(0) 먼댓글(0) 좋아요(4)
좋아요
북마크하기찜하기 thankstoThanksTo
 
 
 

책은 매우 좋음!!!

150 앞에서와같이 -> 앞에서와 같이

432 설루션(일부러 이렇게 쓰신 게 아니라면...) -> 솔루션

558 모델링하고 자 하는 -> 모델링하고자 하는
566 관행적인으로 -> 관행적으로

(수시로 추가 예정)




댓글(0) 먼댓글(0) 좋아요(6)
좋아요
북마크하기찜하기 thankstoThanksTo
 
 
 

1999년에 나온 책을 2008년에 번역한 것.

각주가 잘 달려 있어서 좋은데...
21쪽 각주 13의 Efonomic은 Economic의,
24쪽 각주 25, 27쪽 각주 31의 Clobal은 Global의,
27쪽 각주 31, 35쪽 각주 52의 Commtssion은 Commission의 오타...

27쪽 ˝되돌릴 수 있던 없던˝은 ˝되돌릴 수 있든 없든˝의 잘못...

27쪽 각주 31, 29쪽 각주 36에서 Saskia Sassen의 이름은 왜 대문자로 써주지 않았는지...

그리고 영문에서든 국문에서든 콜론(쌍점)의 ˝앞은 붙여 쓰고˝ 뒤는 띄어 쓰는 것이 원칙이다. 문화체육관광부 고시인 한글 맞춤법 https://www.law.go.kr/%ED%96%89%EC%A0%95%EA%B7%9C%EC%B9%99/%ED%95%9C%EA%B8%80%EB%A7%9E%EC%B6%A4%EB%B2%95 의 부록 참조.

얼마 안 읽었는데도 이렇다. 책 전체에 틀린 표기가 아주 많을 것으로 예상된다...


댓글(0) 먼댓글(0) 좋아요(6)
좋아요
북마크하기찜하기 thankstoThanksTo