[Project] 날씨에 맞는 옷 추천 프로젝트: Selenium은 정말 필요한 선택이었을까? - 크롤링 삽질 기록


✍️ 작성하게 된 이유
날씨에 따라 옷을 추천해주는 서비스를 만들면서, 사용자가 입력한 구매 링크에서 옷 정보( 대표이미지, 상품명 )를 불러오는 기능이 필요했다. 처음에 해당 페이지를 동적 페이지로 판단했고, 자연스럽게 Selenium
을 도입했다.
하지만 이 결정이 과연 최선이었는지는 수많은 시행착오 끝에야 알 수 있었다.
🕸️ Selenium을 선택한 이유
동적 페이지는 Jsoup
으로 크롤링이 어렵다는 인식으로 처음부터 Selenium
을 선택했다. Selenium
은 브라우저 환경을 구동하여 실제 동작하는 것 처럼 행동할 수 있다. 대부분의 사이트들은 동적페이지라는 인식이 있어 해당 라이브러리를 사용했다.
"정적 페이지 = Jsoup, 동적 페이지 = Selenium"이라는 단순한 기준으로 접근했다.
🧪 그런데 실제 사용해보니?
1️⃣ 너무 느리다 (최소 12초)
예시로
무신사
페이지를 보면, 다른 작업이 완료되지 않고 단순히 크롤링 대상 페이지만 로드하는 데도 3초, 전체 요청은 12초 이상 소요되었다.무신사 페이지 기준 한 번 요청당 12초가 소요됨
2. 서버 환경에선 오류 발생
로컬에서는 정상적으로 작동하던 코드가 AWS 환경에 배포하자 다음과 같은 오류를 뿜기 시작했다.
→ 이는 Selenium WebDriver가 Chrome 브라우저 인스턴스를 생성하지 못해서 발생한 오류였다.
3. OOM (Out Of Memory)까지 발생
상황
t2.micro(프리티어)인스턴스의 메모리 기준 1GiB 중 70% 이상 사용됨(RAM 용량 부족)
그에 따라, OOM이 발생하여, 인스턴스가 부하를 버티지 못해 종료하게 됨
남아있는 부하로 인하여 Rolling 재배포 시도에도 OOM발생으로 문제 발생 이후 재배포 또한 실패하는 상황 발생
원인
매 요청 마다 Chrome 인스턴스를 매번 새로 생성( 밑 코드 예시 참고 ) → Chrome 브라우저 로드 후 크롤링 진행
정보를 가져오는 양이 많고 요청이 동시에 여러개 들어오게 되면서 메모리 사용량 폭증
GUI 없이 실행해도 크롬은 상당한 메모리를 사용
해결 방법
배포 인스턴스 업그레이드 ( t2.micro → t3a.medium) : vCPU 1→2(2배 증가), 메모리 1GiB→4G1B(4배증가)
Jsoup으로 변환 ( 밑 방법 참고 )
🧠 크롬이 메모리를 많이 사용하는 이유?
크롬은 각 탭마다 독립적인 프로세스를 생성해 빠른 속도를 확보하는 구조이다. 이 구조는 메모리가 넉넉할 때 다중 탭(하나의 창에 여러 탭 = 프리렌더링)을 활용하여 빠르지만, 메모리가 부족한 서버 환경에서는 오히려 느려지고 오류가 발생할 수 있다.
프리렌더링 기술은 메모리가 넉넉할 땐 빠름, 그렇지 않으면 성능 저하!
🔍 현재 프로젝트 코드로 본 문제점
매번 Chrome 브라우저를 새로 실행하므로, 메모리 낭비
Headless 모드라도 자원을 크게 소모
대량 요청 시 리소스 누수 및 OOM 위험 증가
많은 요청이 동시에 들어오면 GC 되기 전에 크롬 인스턴스가 계속 늘어남
🤔 정말 Selenium이 필요했을까?
Selenium의 장점은 분명하다.
✅ 로그인, 클릭, 스크롤 등 사용자 조작 자동화
✅ 자바스크립트 실행 이후 DOM까지 접근 가능
✅ 실제 브라우저와 유사한 환경 제공
하지만, 내가 만든 기능은?
사용자는 URL만 입력
로그인, 클릭, 스크롤 ❌
필요한 데이터( 대표이미지 URL, 상품명 )는 HTML 내 script 태그 안에 모두 존재
→ 즉, 렌더링이 완료될 때까지 기다릴 필요가 전혀 없음
📚 Jsoup으로 전환 결심
🟢 Jsoup이란?
Jsoup
은 Java 기반 HTML 파서로, 다음과 같은 특징이 있다:
간단한 API로 HTML 가져오기 (URL, 파일, 문자열 등)
DOM 탐색 / CSS 선택자로 데이터 추출
HTML 요소, 속성, 텍스트 조작 가능
깨진 HTML도 자동 보정
정제된 HTML 출력 지원
🔎 무신사 페이지 분석
구매 링크로 들어가면 대표 이미지 URL
, 상품명
등 필요한 정보는 모두 <script>
태그 내부에 정적 데이터로 존재했다.
🔎 29cm 페이지 분석
29cm도 마찬가지이다.
현재 무신사, 29cm모두
👉 즉, Jsoup
만으로도 충분히 접근 가능
👉 별도의 렌더링이나 브라우저 제어 필요 없음
🛠️ Jsoup 적용 방법
1️⃣ 의존성 추가
Gradle에서
jsoup
라이브러리 추가
2️⃣ HTML 문서 가져오기
Document
: HTML 전체 문서 객체tiemout
: 대기시간은 15초이다. 15초가 넘어가면 에러가 난다.userAgent
: 웹 브라우저가 서버에 요청을 보낼 때 자신의 정보를 담아 보내는 문자열이다.parser.extract(document)
: html문서 전체를 extranct 함수로 넘겨준다. 각 사이트에 따른 정보 추출을 진행한다.필자는 Spring Retry를 사용했기에 e 그대로 예외를 던진다.
3️⃣ 원하는 요소 파싱(무신사)
Elements
: Element들의 리스트Element
: HTML DOM 요소 하나필자는 사이트별 Parser를 따로 두고 파싱함
⚡ 결과: 속도 개선 : 기존 대비 약 40배의 크롤링 시간 감소
대상 사이트 | 기존(Selenium) | 변경 후(Jsoup) |
무신사 | 12초 | 0.3초 |
✅ 결론
이번 경험을 통해 깨달은 점
"Selenium을 쓰기 전에 진짜로 브라우저 조작이 필요한지 먼저 확인하자!"
단순히 HTML 내 데이터 추출이라면,
가벼운 도구를 사용하는 것이 속도, 안정성, 운영 효율성 모두에서 더 낫다.
출처
Subscribe to my newsletter
Read articles from Soyulia directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Soyulia
Soyulia
Nice to meet u :) Im Backend Developer