👕 크롤링 애플리케이션은 JBLY 프로젝트 요구 사항인 "파이썬 환경에서 최소 세 개 이상의 쇼핑몰을 모아볼 수 있다."를 수행하는 애플리케이션입니다. 시리즈 포스팅은 성능 개선 과정에서 겪은 문제점과 해결하는 과정을 담고 있습니다.
✒️ 첫 번째 요구사항 충족 글은 성능이 개선되기 전 요구 사항 달성 과정을 포스팅합니다. (160분 소요)
✒️ 두 번째 도구 선택의 중요성 글은 Selenium Tool 걷어내는 과정에서 성능 개선 방법에 대해 포스팅합니다. (30분대로 성능 개선)
✒️ 세 번째 병렬 처리 글은 병렬 처리를 통해 성능을 높일 수 있는 방법에 대해 포스팅합니다.(4분대로 성능 개선)
🍎 Crawling
- 지정한 임의의 세 개의 쇼핑몰을 모아볼 수 있는 기능을 구현하기 위해선 어떤 방법으로 해결해야 할까요?
- 세 개의 쇼핑몰을 매 페이지마다 들려가며 상품 정보들을 가져와야 한다면 시간이 많이 걸릴뿐더러 사람이 하는 작업이라 Human Error가 발생할 확률이 높습니다. 따라서, 이를 자동화하는 방법을 찾아야 합니다.
- Crawling을 통해 웹 사이트, 하이퍼 링크, 데이터와 같은 정보 자원을 자동화된 방법으로 수집, 분류 저장하는 것을 가져올 수 있습니다.
- Crawling 시 robots.txt를 통해 해당 Web의 정책을 확인해야 합니다.
🍏 방법을 찾았습니다. 파이썬 환경에서 Crawling을 수행하면 됩니다. 특정 웹 사이트의 정보를 가져오기 위해서 어떤 도구를 사용할 수 있을까요?
- 도구를 찾는데 선택한 방법은 웹에 Crawling Tool을 검색해 그중 자료가 많은 도구를 선택했습니다. 이런 선택을 한 이유는 처음 해보는 Crawling 개발이기 때문에 참고할 자료가 많다면 그만큼 시간을 단축시킬 수 있다고 판단했기 때문입니다.
- Crawling Tool 중 사용 빈도가 높은 두 개를 골라 프로젝트를 진행했습니다. 두 Tool은 Beautiful Soup, Selenium입니다.
🍎 Beautiful Soup
- Beautiful Soup은 HTML과 XML 문서들의 구문을 분석하기 위한 Python Package입니다. Beautifus Soup에 입력된 HTML Source를 던져주면 Beautiful Soup은 HTML DOM을 그립니다.
- Beautifus Soup이 제공하는 함수를 통해 그린 DOM에서 원하는 데이터를 긁어올 수 있습니다. Python에서 사용하려면 Beautiful Soup을 직접 다운로드해 사용해야 합니다.
- 위의 예시에서 볼 수 있듯이 원하는 사이트에 Requests Module을 통해 요청을 보낸 후 가져온 response를 BeautifulSoup Module을 사용해 파싱 하길 원하는 부분의 데이터를 가져올 수 있습니다.
- 프로젝트에선 사용될 상품 하나의 Data Schema는 [상품_id, 상품_이름, 상품_이미지, 상품_가격, 상품_타입, 상품_상세_정보, 가게_이름]으로 구성되어 진행됩니다.
⚠️ 문제가 두 가지 발생했습니다.
1️⃣ 웹 사이트마다 다르지만 일부 웹 사이트에 요청을 보낼 때, 403 Forbidden 이 발생합니다.
🍏 요청에 대한 응답값이 403일 때 해결 방법
- google.com site에 요청을 보내 응답을 가져온 것처럼 Crawling target site를 requests module에 넣어 응답을 받아왔지만 올바른 값을 가져오지 못했습니다. 대신 403 Forbidden Error Message를 쇼핑몰 site server로부터 받아왔습니다.
- HTTP 403 Forbidden 클라이언트 오류 상태 응답 코드는 서버에 요청이 전달되었지만, 권한 때문에 거절되었다는 것을 의미합니다. 이 상태는 401과 비슷하지만, 로그인 로직(틀린 비밀번호로 로그인 행위)처럼 반응하여 재인증(re-authenticating)을 하더라도 지속적으로 접속을 거절합니다.
- 403 오류 상태는 400 Bad Request처럼 "요청이 잘못되었다"라는 의미가 아니라 "요청 syntax가 잘못되어서 이해를 못 하겠다"라는 의미를 담고 있습니다. 요청을 판단하는 주체는 서버입니다. (= The server understood the request, but is refusing to fulfill it.)
- 요청 시 서버에게 이해할 수 있는 syntax를 갖는 요청을 보내면 문제를 해결할 수 있습니다. 웹 개발자 도구에서 사이트 접근할 사이트 Request Header를 보면 요청 시 필요한 값들을 알 수 있습니다. crawling 대상 사이트들은 요청 시 Header에 referer와 user-agent 값을 넣음으로 올바른 syntax 조건을 만족시켰습니다.
2️⃣ Schema에 존재하는 상품_상세_정보를 가져오기 위해선 하나의 깊이(페이지)를 더 들어가야 합니다. 또한 다음 페이지로 이동하기 위해선 동적 처리(클릭이라는 동적인 움직임으로 상세 페이지에 접근)를 해야 하는데 문제는 Beautiful Soup은 동적 페이지 처리 기능을 제공하지 않습니다.
🍏 웹 사이트에서 동적 처리를 제공해 주는 Tool을 찾아야 했습니다. 해결책으로 Selenium이란 도구를 발견했습니다. 이를 통해 웹 페이지를 사용자 요구에 맞게 처리할 수 있습니다. (동적 처리를 위해 사용했지만 다음 글에서 Selenium을 제거합니다.)
🍎 Selenium
- JBLY 프로젝트에선 Selenium을 사용해 동적 처리를 진행했습니다.
- Selenium은 웹 애플리케이션을 자동화하고 테스트하는 데 사용되는 프레임워크입니다. 웹 페이지의 텍스트, 버튼, 링크, 이미지, 폼 등을 자동으로 조작할 수 있습니다. 이처럼 다양한 방법으로 웹 페이지를 조작할 수 있으며, 확장성이 높아 다양한 작업을 수행할 수 있습니다.
- Selenium을 사용할 때, Web Driver(Web Engine)을 코드를 통해 생성해 사용하는 방법과 직접 Web Engined을 애플리케이션 구동 위치와 같은 위치에 둬 호출을 통해 사용하는 방법이 있습니다. JBLY 프로젝트의 경우, 후자의 방법을 선택했습니다. 이유는 Window 환경에서 코드를 통해 Web Engine을 생성하는 부분에 에러가 발생했기 때문입니다.
- 예제 코드를 보고 싶다면 여기를 클릭해 주세요!
✅ BeautifulSoup과 Selenium을 통해 세 개의 사이트를 크롤링하는 것을 완료할 수 있었습니다.
- 하지만, 문제가 있습니다. 세 사이트를 모두 Crawling 할 경우 160분이라는 시간이 소요됩니다.
- 실제 서비스를 진행한다고 했을 때 하루에 처리할 수 있는 사이트의 수는 많다면 30 개밖에 되지 않습니다. 1000개의 사이트 모아보기를 사용자에게 제공하는 서비스라고 한다면 한 달을 쉬지 않고 애플리케이션을 구동시켜도 모든 사이트들의 아이템을 등록시킬 수 없습니다.
- 도중 사이트에서 변경 사항이 생긴다면(상품 가격 수정, 상품 재고 없음) 해당 결과를 사용자가 알기까지 Worst Case로 한 달 이상이 걸릴 수 있다는 것을 의미합니다. 즉, 실제 사이트에서 판매되는 제품과 JBLY에서 보여주는 제품의 데이터 정합성이 일치하지 않음을 이야기합니다. 이는 JBLY Application 품질을 낮춥니다.
- 지금 개발한 대로 1000개의 모아보기 서비스를 운영한다면 1년에 들어가는 유지 비용은 다음과 같습니다.(해당 비용은 대략적인 계산결과입니다.)
- Naver Cloud Server 사용 시(최소 사양) 비용 계산을 해보자면 (245원 * 24) * (30일) * (12 개월) = 2,116,800이 서버 동작에 들어갑니다.
- 추가적으로 DB 사용할 때 추가적으로 비용이 들어갑니다.(DB 튜닝 포스팅에서 다룹니다.) 프로젝트 한 달간 세 사이트만 Crawling을 진행했을 때 발생한 비용은 100,000이었습니다. 하루에 10번의 사이클이 돌아가니 100,000 * 10 = 1,000,000이고 1년을 계산하면 12,000,000이라는 금액이 발생합니다.
- 따라서, 반드시 애플리케이션 실행 시간을 줄여야 합니다.
🔜 다음 포스팅에선 병목이 많이 발생하는 부분을 찾아보고 개선해 160분에서 30분대로 줄이는 과정을 포스팅하겠습니다.! 긴 글 읽어주셔서 감사합니다.
📚 참고 사이트
HTML 상태 코드의 의미를 자세하게 볼 수 있습니다.
Web Parser인 BeautifulSoup의 사용법을 배울 수 있습니다.
Web 동적 처리를 제공하는 Selenium의 사용법을 배울 수 있습니다.
🍎 현재까지 완료된 코드를 보고싶다면 링크된 브랜치에서 확인할 수 있습니다.
'Dev' 카테고리의 다른 글
REST API 설계 및 사용 시 참고 사항 (1) | 2024.09.01 |
---|---|
Crawling 성능 40배 올리기, 160분에서 4분대로 -병렬 처리- (4) | 2023.04.06 |
Crawling 성능 40배 올리기, 160분에서 4분대로 -도구 선택의 중요성- (3) | 2023.04.05 |
동기화와 병렬 처리 둘의 상관 관계 그리고 Java (0) | 2023.04.03 |
Process와 Thread. 다다익프? 다다익쓰? (0) | 2023.04.03 |