쿠팡 크롤링 문제

웹 크롤러 개발 및 배포 과정의 기술적 과제와 해결 방안 분석

1. 프로젝트 개요 및 초기 구현

1.1. 목표

쿠팡(Coupang) 웹사이트의 주문 내역을 주기적으로 수집하여 자동화된 데이터 관리 시스템을 구축하는 것을 목표로 한다.

1.2. 초기 기술 스택

  • 언어: Python
  • 웹 브라우저 자동화: Selenium
  • HTML 파싱: BeautifulSoup (bs4)

1.3. 초기 구현 내용

Selenium을 사용하여 로컬 환경에서 크롬(Chrome) 브라우저를 실행하고, 사용자의 로그인 과정을 자동화한 후, 주문목록 페이지로 이동하여 BeautifulSoup으로 페이지 내의 주문 내역 데이터를 추출하는 스크립트를 개발했다. 로컬 환경 테스트 결과, 스크립트는 정상적으로 작동하여 목표한 데이터를 성공적으로 수집했다.


2. 배포 단계에서 발생한 기술적 과제

과제 1: 서버리스 환경(Google Cloud Functions)에서의 배포 실패

2.1.1. 문제 현상

개발된 스크립트를 자동화 및 스케줄링을 위해 서버리스 플랫폼인 구글 클라우드 펑션(GCF)에 배포했으나, 실행 시 다음과 같은 오류가 발생하며 실패했다.
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally.

2.1.2. 원인 분석: 아키텍처의 근본적인 비호환성

단순히 크롬 드라이버(ChromeDriver) 파일이 누락된 문제가 아니었다. 실패의 근본적인 원인은 Selenium 기반 브라우저 자동화의 특성과 서버리스 아키텍처의 제약 조건 사이의 충돌에 있었다.

  • 자원 제약: GCF는 메모리, CPU, 실행 시간에 엄격한 제한을 둔다. 크롬 브라우저와 같은 무거운 애플리케이션을 시작하고 실행하는 과정은 GCF의 제한된 자원을 초과하기 쉬우며, 이로 인해 프로세스가 강제 종료될 수 있다.
  • 상태 비저장(Stateless) 및 일시성(Ephemeral): 서버리스 함수는 각 호출이 독립적인 환경에서 실행될 수 있으며, 상태를 유지하지 않는 것을 전제로 설계되었다. 이는 로그인 세션, 쿠키 등을 유지해야 하는 웹 크롤링 작업과 상충된다.
  • 파일 시스템 제약: GCF의 파일 시스템은 기본적으로 읽기 전용이며, /tmp 디렉터리에만 제한적인 쓰기가 가능하다. 브라우저가 캐시나 프로필 데이터를 생성하려는 시도가 이러한 제약으로 인해 실패할 수 있다.
  • 콜드 스타트(Cold Start): 함수가 비활성 상태에서 처음 호출될 때 발생하는 실행 환경 초기화 지연은, 무거운 브라우저의 시작 시간과 결합되어 전체 실행 시간을 크게 증가시키고 타임아웃을 유발할 수 있다.

2.1.3. 결론

GCF와 같은 서버리스 환경은 Selenium을 이용한 웹 브라우저 자동화 작업을 실행하기에 부적합하다. 이러한 작업에는 도커(Docker) 컨테이너를 활용하는 **구글 클라우드 런(Google Cloud Run)**이나 완전한 제어가 가능한 **가상 머신(VM)**이 더 적합한 대안이다.

과제 2: 가상 머신(VM) 환경에서의 접근 차단(Access Denied)

2.2.1. 문제 현상

프로젝트 환경을 리눅스(Linux) 기반의 가상 머신으로 이전하고, 서버 환경에서의 실행을 위해 Selenium을 헤드리스(Headless) 모드로 설정했다. 다른 웹사이트(11번가, G마켓, 네이버 등)는 정상적으로 접근되었으나, 목표 사이트인 쿠팡에서는 Access Denied 페이지를 반환하며 접근이 차단되었다.

2.2.2. 당시 사용된 헤드리스 설정python

user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
options.add_argument('user-agent=' + user_agent)
options.add_argument('--disable-blink-features=AutomationControlled') # navigator.webdriver 속성 숨기기
options.add_argument("lang=ko_KR")
options.add_argument('headless') # 구형 헤드리스 모드
options.add_argument('window-size=1920x1080')
options.add_argument("disable-gpu")
options.add_argument("--no-sandbox") # 리눅스 서버 환경 필수 옵션

2.2.3. 원인 분석: 정교한 봇 탐지(Bot Detection) 시스템

Access Denied는 단순한 오류가 아니라, 웹사이트의 보안 시스템이 스크립트의 접근을 ‘봇’으로 식별하고 의도적으로 차단했음을 의미한다. 현대의 봇 탐지 시스템은 단일 지표가 아닌, 다수의 신호를 종합하여 클라이언트의 ‘지문(Fingerprint)’을 생성하고 ‘봇 점수(Bot Score)’를 매기는 방식으로 작동한다.

테이블 1: 웹사이트는 당신이 봇이라는 것을 어떻게 알까? (헤드리스 브라우저 지문)

탐지 카테고리구체적인 기술봇을 탐지하는 원리관련 자료
자바스크립트 속성$navigator.webdriver 플래그자동화 환경에서는 true로 설정된다. 실제 사용자 브라우저에서는 false이다.
$window.chrome 객체자동화된 크롬과 실제 크롬 간의 객체 속성값 불일치를 확인한다.
플러그인 부재헤드리스 브라우저는 $navigator.plugins.length가 0인 경우가 많다.
브라우저 환경캔버스 핑거프린팅보이지 않는 <canvas> 렌더링 결과가 그래픽 스택 차이로 인해 고유한 해시값을 생성한다.
WebGL 핑거프린팅3D 그래픽 렌더링 파라미터를 이용해 하드웨어 및 드라이버 수준의 고유한 지문을 생성한다.
사용 가능한 폰트서버 환경의 최소 폰트 목록과 일반 데스크톱 환경의 폰트 목록 차이를 감지한다.
네트워크 및 OS 수준HTTP 헤더 순서브라우저/OS마다 고유한 헤더 순서가 있어, User-Agent와 실제 요청 패턴의 불일치를 탐지한다.
TLS/JA3 핑거프린팅HTTPS 핸드셰이크 과정의 암호화 방식 서명을 통해 파이썬 라이브러리 사용을 간파한다.
TCP/IP 스택 핑거프린팅OS별로 다른 TTL(Time To Live) 값 등을 통해 User-Agent와 실제 OS의 불일치를 탐지한다.
행동 분석상호작용 패턴비인간적인 마우스 움직임, 즉각적인 클릭, 일정한 작업 간격 등 기계적인 패턴을 분석한다.

또한, 사용된 headless 옵션은 구형 방식이며, 크롬 109 버전부터는 전체 브라우저 기능을 지원하는 --headless=new 모드가 권장된다. 하지만 모드 변경만으로는 모든 탐지를 우회할 수 없다.


3. 해결을 위한 전략적 접근 방안

실패 원인 분석을 통해, 문제 해결을 위해서는 더 정교한 접근 방식이 필요함을 인지했다. 가능한 전략은 다음과 같다.

테이블 2: 크롤링 접근 방식 비교

접근 방식동작 원리장점단점최적의 사용 사례
표준 셀레니움실제 브라우저 UI를 자동화.작성이 간단하고 시각적 디버깅이 용이.느리고, 자원 소모가 크며, 쉽게 탐지됨.초기 개발, 간단한 사이트.
헤드리스 셀레니움브라우저를 백그라운드에서 실행.더 빠르고 서버에서 실행 가능.여전히 고급 시스템에 의해 탐지 가능.자동화된 테스트, 기본적인 스크래핑.
강화된 셀레니움 (undetected-chromedriver)드라이버를 패치하여 봇 신호를 숨김.많은 일반적인 탐지 기법을 우회.불안정할 수 있고, 헤드리스 모드에서 효과가 떨어지며, 끊임없는 기술 경쟁이 필요.중간 수준의 봇 탐지 기능을 가진 사이트.
최신 프레임워크 (Playwright)최신 프로토콜(WebSocket)을 사용하여 제어.더 빠르고 안정적이며, 자동 대기(auto-wait) 등 개발자 친화적 기능 제공.셀레니움보다 커뮤니티가 작고, 구형 브라우저 지원이 적음.최신 동적 웹 애플리케이션(SPA).
직접 API 호출 (requests)사이트의 백엔드 API와 직접 통신.극도로 빠르고, 안정적이며, 자원 소모가 적고, 모든 브라우저 수준 탐지를 우회.API를 리버스 엔지니어링해야 하며, 복잡하고, API 변경 시 코드가 깨질 수 있음.정교하고, 대규모이며, 효율적인 스크래핑.

3.1. 전략 1: 강화된 브라우저 위장 (undetected-chromedriver)

undetected-chromedriver는 런타임에 크롬 드라이버 바이너리를 동적으로 패치하여 navigator.webdriver와 같은 주요 탐지 지표를 수정하는 라이브러리다. 이를 통해 표준 Selenium보다 훨씬 인간적인 브라우저 환경을 시뮬레이션할 수 있다. 단, 헤드리스 모드에서는 그 효과가 감소하거나 작동하지 않을 수 있다는 한계가 존재한다.

3.2. 전략 2: 최신 자동화 프레임워크 도입 (Playwright)

Playwright는 Microsoft에서 개발한 최신 자동화 도구로, 다음과 같은 장점을 가진다.

  • 빠른 속도: WebDriver 프로토콜 대신 영속적인 웹소켓(WebSocket) 연결을 사용하여 더 빠르고 효율적으로 통신한다.
  • 개발자 편의성: 요소가 나타날 때까지 자동으로 대기하는 ‘자동 대기(auto-waits)’ 기능은 개발 생산성을 크게 향상시킨다.
  • 강력한 도구: Codegen, Trace Viewer와 같은 현대적인 디버깅 및 개발 지원 도구를 제공한다.

3.3. 전략 3: API 리버스 엔지니어링을 통한 직접 통신

가장 근본적이고 효율적인 해결책은 브라우저 렌더링이라는 중간 단계를 완전히 건너뛰고, 웹페이지가 데이터를 가져오는 데 사용하는 백엔드 API와 직접 통신하는 것이다.

  • 프로세스:
    1. 브라우저 개발자 도구(F12)의 ‘네트워크’ 탭을 연다.
    2. Fetch/XHR 필터를 활성화하고, 웹사이트에서 원하는 데이터를 로드하는 동작(예: 주문목록 클릭)을 수행한다.
    3. 생성된 요청 목록에서 실제 데이터(주로 JSON 형식)를 반환하는 API 호출을 식별한다.
    4. 해당 요청을 ‘cURL로 복사(Copy as cURL)’하여 요청에 필요한 모든 정보(URL, 헤더, 쿠키, 페이로드 등)를 확보한다.
    5. cURL 명령어를 Python의 requests 라이브러리를 사용하는 코드로 변환하여 API를 직접 호출한다. 이때 인증에 사용되는 Authorization이나 Cookie 헤더를 정확히 포함하는 것이 중요하다.
  • 장점: 매우 빠르고 자원 소모가 적으며, UI 변경에 영향을 받지 않고, 브라우저 핑거프린팅 기반의 봇 탐지를 완전히 우회할 수 있다.

4. 결론 및 요약

단순한 웹 크롤러 개발 프로젝트는 배포 및 운영 단계에서 복합적인 기술적 과제에 직면했다. 이 과정을 통해 얻은 핵심적인 기술적 교훈은 다음과 같다.

  1. 인프라 선택의 중요성: 애플리케이션의 특성(예: 브라우저 자동화)에 맞는 실행 환경(예: VM 또는 컨테이너)을 선택하는 것은 코드 구현만큼이나 중요하다.
  2. 봇 탐지 시스템에 대한 이해: 현대 상용 웹사이트는 정교한 방어 체계를 갖추고 있으므로, 이를 우회하기 위해서는 다각적인 탐지 벡터를 이해하고 전략적으로 접근해야 한다.
  3. API 우선 접근 방식의 효율성: 가능한 경우, UI 자동화를 통한 데이터 수집보다 API를 직접 호출하는 방식이 속도, 안정성, 자원 효율성 측면에서 월등히 우수하다.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다