왜 쿠팡 가격을 긁어야 했을까

중고폰 유통 업체 ‘다원트레이드’와 파트너 작업을 하고 있다. 이 업체는 쿠팡에서 중고 아이폰을 판매하는데, 경쟁 셀러들의 가격이 수시로 바뀐다. 아이폰15PRO 256G, 아이폰16 128G, 아이폰17PRO 512G 등 10개 키워드의 최저가와 판매자를 매일 모니터링해야 했다.

사람이 매번 쿠팡에 들어가서 검색하고 가격을 비교하는 건 한계가 있다. 자동화해야 한다. 그래서 크롤링을 시작했다.


7가지 방법, 전부 실패

처음에는 쉽게 생각했다. “requests로 HTML 긁어서 파싱하면 끝이지 뭐.” 결과는 403 차단이었다.

# 방법 결과
1 requests (리눅스/윈도우) 403 차단
2 Selenium headless (리눅스/윈도우) Access Denied
3 Playwright headless (리눅스) Access Denied
4 Playwright 일반 모드 (리눅스) Access Denied
5 Selenium 일반 (윈도우 SSH) Access Denied
6 undetected-chromedriver (윈도우) ChromeDriver 버전 오류
7 쿠팡 내부 API 직접 호출 403 차단

Selenium headless? Access Denied. Playwright? Access Denied. undetected-chromedriver? 크롬 버전이 안 맞아서 실행조차 안 됐다. 쿠팡 내부 API를 직접 때려봤지만 역시 403이었다.

쿠팡의 봇 탐지가 이 정도로 강력할 줄 몰랐다. 진짜 하루 종일 삽질만 했다.


돌파구: 크롬 확장 프로그램

포기하려다가 떠올린 아이디어가 있었다. “사람이 브라우저로 보는 건 되잖아?” 크롬 확장 프로그램은 실제 브라우저 안에서 돌아간다. 봇이 아니라 브라우저의 일부다. 쿠팡 입장에서는 사람이 페이지를 보는 것과 구분할 수 없다.

바로 만들었다. 이름은 “DWT 가격 수집기 v1.1”.

결과? 36개 상품을 1~2초 만에 수집 성공. 드디어 뚫렸다.


확장 프로그램 구조

파일 4개가 전부다.

 

dwt_extension/
├── manifest.json    ← 확장 프로그램 설정
├── content.js       ← 쿠팡 페이지에서 DOM 파싱
├── background.js    ← 탭 관리, 메시지 중계
└── popup.js         ← 수집 버튼 UI + 서버 전송

manifest.json에서 쿠팡 도메인에 content script를 주입하도록 설정한다. 사용자가 popup에서 “수집” 버튼을 누르면, content.js가 현재 검색 결과 페이지의 상품명, 가격, 링크, 광고 여부를 긁어온다.


판매자 추출이 진짜 고비였다

상품 목록에서 가격은 금방 뽑았다. 문제는 판매자명이었다. 쿠팡 검색 결과 페이지에는 판매자 정보가 없다. 상세 페이지에 들어가야 나온다.

F12 개발자 도구를 열고 Console에서 셀렉터를 하나씩 찾았다. 상세 페이지마다 자동으로 방문해서 판매자명을 추출하는 로직을 background.js에 넣었다. 중간에 판매자 평가 점수(“87%”)가 판매자명으로 잘못 잡히는 버그도 있었지만, 셀렉터를 다듬어서 해결했다.


서버 연동: FastAPI + SQLite

수집한 데이터를 어딘가에 저장해야 한다. 다원트레이드 전용 윈도우 PC에 FastAPI 서버를 올렸다.

 

@app.post("/api/crawl")
async def receive_crawl(request: Request):
    data = await request.json()
    for p in data["products"]:
        db.insert(p["name"], p["price"], p["seller"])
    return {"success": True}

주요 API는 이렇다:

  • POST /api/crawl – 확장 프로그램이 수집 데이터를 서버로 전송
  • GET /api/latest – 최신 수집 결과 조회
  • GET /api/stats – 키워드별 최저가/평균가 통계
  • GET/POST/DELETE /api/keywords – 모니터링 키워드 CRUD

전용 PC 세팅이 또 한 건

2일차에는 다원트레이드 사무실에 있는 전용 PC를 원격으로 세팅했다. Tailscale로 VPN을 연결하고, SSH + RDP + AnyDesk 3중 원격 접속을 구축했다.

여기서도 삽질이 있었다. RDP 포트 3389가 LISTEN 상태가 안 되는 거다. 원인은 UmRdpService가 안 돌고 있었기 때문이었고, 재부팅 한 방으로 해결됐다.

최종 구조는 이렇게 됐다:

 

다원트레이드 PC (Tailscale 연결)
├── 크롬 + DWT 확장 프로그램 → 쿠팡 가격 수집
├── FastAPI 서버 (포트 8001) → 데이터 저장 + 대시보드
├── SQLite DB → 수집 결과 저장
└── start.vbs → 서버 백그라운드 실행

결과: 대시보드 완성

대시보드에서 키워드별로 탭을 눌러 최저가, 판매자, 수집 시간을 한눈에 볼 수 있다. 10개 키워드 자동 순회 버튼도 만들어서, 한 번 클릭하면 10개 키워드를 순서대로 수집한다.

첫 테스트에서 “아이폰15PRO 256G” 키워드로 16개 상품이 수집됐고, 키워드 필터링으로 삼성 등 관련 없는 상품을 걸러낸 뒤 14건이 DB에 깔끔하게 저장됐다.


다음 단계

지금은 수동으로 “수집” 버튼을 눌러야 한다. 앞으로 할 일:

  1. 타이머 자동 수집 – 1시간마다 자동으로 10개 키워드 순회
  2. PC 부팅 시 자동 시작 – 서버 + 크롬 자동 실행
  3. 텔레그램 알림 – 최저가가 변동되면 즉시 알림
  4. 키워드별 가격 추이 그래프 – 시간에 따른 가격 변화 시각화

마무리: 정공법이 안 되면 우회하라

이번 작업에서 배운 건 하나다. 막히면 관점을 바꿔야 한다. requests, Selenium, Playwright 전부 “외부에서 브라우저를 조종하는” 방식이었다. 쿠팡은 이걸 다 잡는다. 하지만 크롬 확장 프로그램은 “브라우저 안에서 동작하는” 방식이라 탐지 대상이 아니었다.

7번 실패하고 8번째에 성공했다. 포기하지 않은 게 아니라, 포기할 타이밍에 다른 아이디어가 떠올랐을 뿐이다. 삽질도 결국 경험이 된다.