알라딘이 책 판매를 넘어서는 어떤 비전을 가지고 있는지는 모르겠지만,
자주, 정기적으로 접속하는 여러 사이트, 서비스 중에 알라딘 장바구니처럼 자주 다운되고 불안정한 페이지는 없는 것 같다.
장바구니에서 책 한 권을 지우려 해도 거의 항상, 매번 페이지가 다운된다. 수십 분씩 다운되는 일이 허다하다. 영 돌아오지 않을 것 같을 때는 '작업관리자'를 켜서 강제 종료시키는데, 오늘은 작업관리자 창마저 거듭 다운시켜 버리는 위력에 기가 찼다. 이 글을 쓰는 데도 몇 시간이 걸렸는지 모르겠다. 내 컴퓨터 사양이 아주 떨어지는 것도 아닌데 말이다.
책 한 권 한 권마다 아래와 같은 코드를 쓰고 있는데, 평소 장바구니에 책을 많이 넣어두는 사람에게는 너무 무거운 것 같다. 군더더기와 이미지 개수를 줄이고, 개별 이미지도 크기를 가볍게 했으면 좋겠다. 이미 장바구니에 넣었는데, 굳이 책 이미지를 볼 필요가 있나도 싶다. 사용자가 장바구니에 책 이미지를 표시할지 말지 고를 수 있게 해도 좋을 것 같다. 장바구니에 책을 담는 것까지는 괜찮은데, 삭제 등 장바구니 관리가 너무너무 어렵다. 페이지 전체에 정보가 너무 많다. 아무튼 무게를 확 줄여야 한다.
덧붙여, 책 검색도 너무 경직되어 있다. 아주 조금만 검색어가 어긋나도 검색 결과를 전혀 돌려주지 못한다. 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 탭 캡쳐 화면(서재에 이미지를 첨부하려니 해상도가 떨어진다)
나도 알라딘을 이루는 일원이라는 생각이 있고, 애정이 있으니 쓴 글이다.
부디 알라딘 관계자가 진지하게 읽어주기 바란다.
읽어주시는 분들께서도 공감하시면 "좋아요" 눌러서 올려주시면 감사하겠습니다.