크롤링 작동 가이드 : 재고, 가격 정보 수집
소싱처에서 재고·가격을 긁고 → 저장 → 계산 → 표시하는 전 과정의 단일 진실 원천
️ 보기 원문 (MD)
정보 수집
1️ 전체흐름
2 수집 방식
소싱처별 상세
3 재고
4 가격
운영
5 매트릭스 로그
6️ 에러이력
7➕ 신규추가
8 동기화
9 개발 체크리스트
정합성 기준점 3원칙 · 절대 규칙 · "무엇이 진실인가"의 기준점 (§4 무결성) · 위반=금전 손실
- 재고 기준 = 소싱처 실제 상품 브라우저 URL의 재고. 추정·폴백·평균 금지 — 그 URL 실데이터로만 확인, 못 하면 "확인 불가" 표기(있다고 단정 금지). _persist_option_stocks·_resolve_stock·stock_unknown
- 가격 기준 = 동일하게 실브라우저 소싱처 상품 URL. 표면노출가·최종매입가 모두 그 URL 실값. 실패 시 대표가 폴백 금지 → "가격 없음 + 크롤 실패". is_crawl_valid·_match_failed·_pick_cheapest_buyable
- 크롤은 서버가 아닌 로컬 PC로 한다. 크롤=로컬(확장/Playwright)·업로드=서버. "서버 크롤 실패"는 설계상 정상(버그 아님). EXTRACTORS·ext_bridge
핵심재고·가격이 화면에 뜨기까지 4단계 — 크롤 → 저장 → 계산 → 표시.
01크롤러
페이지에서 재고·표면노출가·혜택을 추출한다.
코드crawlers/<소싱처>.py
뜻크롬 확장이 실행해 긁고 서버로 전송(추출만).
02저장
추출값을 DB + 혜택 스냅샷에 기록. 옵션 재고는 (색·사이즈)당 1행씩 영속 — 매트릭스 한 칸 = 저장 1행.
| 항목 | 무엇을 | 어디에 | 주의 |
|---|---|---|---|
| 재고 | (색·사이즈)당 실수량 | current_stock | 빈값→상품값 둔갑 금지 |
| 표면가 | 최저 표면노출가 | last_price | — |
| 혜택 | SSG머니·쿠폰 등 | dynamic_benefits_json | 무로그인만 저장 |
| 옵션칸 | 색×사이즈 조합 행 | 서버 _ingest·navGrab parse | 확장 크롤=갱신만 |
코드 service.py:429 · 매트릭스 읽기(_match_option_so)·크롤 쓰기(_persist)가 같은 행을 봐야 함 — 중복행이면 stale 둔갑(→5 에러이력 S3).
옵션행 생성 vs 갱신 · 재고 둔갑 이력 (자세히)
사이즈별 SourceOption은 ①서버 _ingest ②navGrab parse(생성)에서만 만들어진다. 확장 crawl-result는 기존 행 갱신만·ext_bridge는 options[] 미전송 → 옵션행이 없으면(신규 URL) 상품 last_stock(전 사이즈 합계) 균일 폴백 = 르무통 올리브 품절 265도 '있음' 둔갑(2026-06-26 parse 생성으로 수정 — 르무통·SSF·SSG·스스. 무신사·롯데온 별도).
★ 남은 변종(2026-07-03 수정): 옵션행은 있는데 그 사이즈 current_stock=NULL이면 여전히 else last_stock으로 그 칸만 합계 둔갑(SSG 단품 블랙 13칸 중 7칸=380). → 매칭됐으면 None(미상) 표면화, last_stock 폴백 금지로 수정. 근본(SSG 단품 일부 NULL=저장 누락)은 별도 추적.
★ 남은 변종(2026-07-03 수정): 옵션행은 있는데 그 사이즈 current_stock=NULL이면 여전히 else last_stock으로 그 칸만 합계 둔갑(SSG 단품 블랙 13칸 중 7칸=380). → 매칭됐으면 None(미상) 표면화, last_stock 폴백 금지로 수정. 근본(SSG 단품 일부 NULL=저장 누락)은 별도 추적.
03계산
표면노출가 − 혜택 누적차감 = 최종매입가.
코드api_benefits.py:496 (compute_breakdown) → unified.py:75 (compute_market_price)
뜻표면가에서 혜택을 순서대로 빼는 계산 엔진.
04표시
셀 · 매트릭스 보기 · 크롤 로그에 보여준다.
코드api_pricing.py:309
뜻매트릭스 렌더. 셀·매트릭스가 window.DATA 한 벌 공유.
️ BG_PARSE(르무통·SSF·SSG·스스)는 price·stock만 저장 — 혜택 미저장.
핵심창을 여는 방식은 3가지 — 값이 어디 있느냐로 갈린다. '동시 상한'은 한 번에 동시에 긁는 개수(창 수 아님).
왜 나누나 — 같은 크롤이라도 값을 어디서 얻느냐에 따라 창 여는 방식이 다르다. fetch 는 원래 동시에 여러 개를 쏠 수 있어서, 탭 1개(또는 0개) 안에서 동시에 긁으면 창 없이도 빨라진다. 렌더가 꼭 필요한 소싱처(로그인 혜택 등)만 창을 URL 수만큼 연다.
SW fetch 창 0개
확장 서비스워커가 탭 없이 직접 원문 fetch. 가장 빠르고 조용.
르무통 SSF 현대H몰
same-origin fetch 창 1개
WAF(Sec-Fetch 차단)로 밖에서 못 부름 → 그 도메인 탭 1개서 same-origin fetch(렌더 없음). URL 여러 개여도 탭 1개.
SSG 롯데아이몰
렌더 창 창 N개
값이 JS로 그려져야 생김(로그인 혜택 등) → 페이지를 실제로 렌더. fetch형도 실패 시 이 렌더로 폴백.
무신사 롯데온
소싱처별 수집 한눈에 (요약표) — 창 여는 법 · 창 수 · 데이터 · 속도 · 혜택
| 소싱처 | 창 여는 법 | 창 수 | 데이터 | 속도 | 혜택 |
|---|---|---|---|---|---|
| 르무통 | SW fetch | 0 | HTML | 빠름 | 무로그인 |
| SSF | SW fetch | 0 | HTML | 빠름 | 무로그인 |
| 현대H몰 | SW fetch | 0 | 내장 | 빠름 | 일부 로그인 |
| SSG | same-origin | 1 | HTML | 보통 | 무로그인 |
| 롯데아이몰 | same-origin | 1 | 내장 | 보통 | 무로그인 |
| 무신사 | 렌더 | N | API | 느림 | 로그인 |
| 롯데온 | 렌더 | N | API | 느림 | 로그인 |
| 스마트스토어 | 확장 로그인 | — | API | 보통 | 로그인(per-SKU) |
동시 상한(자동화 설정) = 그 소싱처를 한 번에 동시에 긁는 개수. fetch형(창0·창1)은 창은 그대로 두고 동시 fetch만 늘고, 렌더형(창N)은 창 개수가 늘어난다. 차단이 보이면 그 숫자를 낮추면 됨.
카테고리 경로 수집 (§2-b · 2026-07-23) — 마켓 카테고리 맵핑의 입력값
상품이 어느 분류에 속하는지(예:
신발>스니커즈>라이프스타일화)를 소싱처에서 받아 판매처 카테고리로 옮길 때 쓴다. 못 뽑으면 빈 문자열 = 「카테고리 확인불가」 — 숫자 분류코드를 이름인 척 넣거나 상품명으로 추측하지 않는다(§4 무결성).| 소싱처 | 원천 | 추출 위치 | 상태 |
|---|---|---|---|
| 무신사 | api2/goods/{id} 의 category.categoryDepth{1..4}Name — 표면가를 이미 부르는 그 응답이라 추가 호출 0 | 확장 | |
| 롯데온 | JSON-LD Product.category 1순위 + DOM ol.locationList 폴백 | 확장 | |
| 롯데아이몰 | div.location 의 직계 a.home + div.his > a.one | 서버 | |
| 스마트스토어 | __PRELOADED_STATE__ 의 …category.wholeCategoryName(셀러가 고른 완성 경로) | 서버 | |
| 르무통 | Cafe24 「현재 위치」 div.xans-product-headcategory > ol li a | 서버 | |
| SSF | JSON-LD BreadcrumbList 1순위 + div.breadcrumb 폴백 | 서버 | |
| SSG | div.cate_location 단계별 div.lo_depth_01 의 직계 a | 서버 | |
| 현대H몰 | 없음(확인불가 고정) — SSR·DOM 둘 다 빵부스러기·JSON-LD·메타 0건. 있는 건 숫자코드 itemDScfCd 뿐이고 코드→이름 공개 경로 없음 | — | 부재확정 |
함정 — ① 드롭다운을 경로로 착각: 롯데아이몰
div.hislayer·SSG div.lo_depth_02 는 그 단계의 형제 카테고리 목록이라 경로가 아니다 → 직계 자식만 읽는다. ② SSG 첫 칸 「SSG.COM」(href="/")은 사이트 루트라 제외. ③ 르무통은 cate_no 없는 URL 이면 '홈'만 남아 빈 문자열. ④ 무신사 baseCategoryFullPath 는 1단계가 영문이라 안 쓴다. ⑤ 무신사·롯데온은 추출이 확장에 있어 서버 배포만으론 안 바뀐다(확장 재로드 필요). 용어 사전 — 데이터를 읽는 3가지 방법
API 호출
사이트가 데이터를 나르는 내부 요청을 그대로 부름. 값(JSON)을 통째로 정확히 받음. 가장 빠르고 안정적 → 선호.
HTML 파싱
서버가 처음 보내준 화면 원본 문서(HTML)에서 값을 찾아 뽑음. 화면 구조가 바뀌면 깨질 수 있음.
DOM 읽기
브라우저가 HTML을 그려 만든 살아있는 화면(DOM)에서 읽음. JS로 나중에 채워지는 값까지 잡음. (HTML의 브라우저판)
핵심소싱처마다 재고·가격을 읽는 방법이 다르다 — API일수록 정확. 종착지 _resolve_stock.
왜 소싱처마다 다른가 — 4가지가 방식을 정함: ① 전용 재고 API를 공개하나(무신사·롯데온) ② 페이지에 내장 구조데이터(__NEXT_DATA__·option_stock_data·uitemObj)가 있나(현대H몰·르무통·SSG) ③ WAF/봇차단으로 서버 접근이 막히나(롯데아이몰·네이버) ④ 로그인은 대개 혜택만 필요(재고·표면가는 무로그인). 그래서 "API > 내장 JSON > HTML > DOM" 순으로 가능한 가장 높은 방식을 쓴다.
재고 판정 우선순위 (게이트 순서) — 위에서 걸리면 멈춤
⓪ 수집 성공? (200+파싱+옵션데이터) → 실패 = 확인 불가 (999 금지·재크롤·판매보류)
성공 시 ↓ ① 옵션 있나? (소싱처 목록에 이 색×사이즈) → 없으면 = 품절(미판매·소멸) — 단 크롤 실패 상태면 목록이 최신 아님 → 확인불가(품절 둔갑 금지)
있으면 ↓ ② 품절신호(0·SLDOUT) → 품절 · ③ 한정 N(remainQty·stkQty·N) → 한정 · ④ 제한신호 없음 → 999 충분
성공 시 ↓ ① 옵션 있나? (소싱처 목록에 이 색×사이즈) → 없으면 = 품절(미판매·소멸) — 단 크롤 실패 상태면 목록이 최신 아님 → 확인불가(품절 둔갑 금지)
있으면 ↓ ② 품절신호(0·SLDOUT) → 품절 · ③ 한정 N(remainQty·stkQty·N) → 한정 · ④ 제한신호 없음 → 999 충분
️ 조용한 실패 방지 — 품절·한정 신호를 못 읽은 것(크롤 실패·필드 부재·파싱 에러)은 999가 아니라 확인불가(수량0·판매 제외). "성공적으로 읽었는데 제한이 없는 것"만 999. [2026-07-08 정정: SSG usablInvQty 필드부재·무신사 재고API 전체실패 → 999 아닌 확인불가(-1)]
충분 신호 종류 — 실수량 르무통·SSG·롯데온·현대H몰·스스·롯데아이몰(한정=실수량 N·충분=999) · 추론·상태값 무신사·SSF(양의 수량 없음 → ⓪게이트 특히 중요)
소싱처별 재고 한눈에 (요약표) — 게이트 순서 ①~④ + 프로그램 표시 로직
| 소싱처 | 수집 방식 | ① 옵션 존재 (수집 대상) | ② 품절 | ③ N개 | ④ 충분→999 | 충분 종류 | 프로그램 재고표시 로직 |
|---|---|---|---|---|---|---|---|
| 무신사 | API | options 배열(optionItems) 부재=소멸→품절 | outOfStock=true | remainQuantity | 신호無→999 | 추론 | ⓪실패→ · 0→ · N→ · 999→ · 목록에없음+크롤ok→품절 · 크롤실패→ |
| 르무통 | HTML | option_stock_data 키 | stock=0·is_selling=F | stock_number | 실수량 큰값 | 실수량 | 0→ · 실수량 그대로 |
| SSG | HTML | uitemObj 옵션 목록 | usablInvQty=0 | usablInvQty=N | 큰값→999 | 실수량 | 필드 부재→ · 0→ · N→ |
| SSF | HTML | #optionDiv1 li a[optcd] | statcd=SLDOUT | 품절임박(N) | 정상→999 | 상태값 | SLDOUT→ · 임박→ · 정상→ |
| 롯데온 | API | option/mapping 목록 | 매핑품절·li.soldout | stkQty=N | stkQty 큰값 | 실수량 | 매핑품절→ · stkQty N→ 502 |
| 현대H몰 | 내장 | __NEXT_DATA__.stockList | sellGbcd=11 | stockCount=N | 큼→999 | 실수량 | sellGbcd 우선(11→) · stockCount→ |
| 롯데아이몰 | 내장 | itemInvQtyInfo 목록 | inv_qty=0 | inv_qty<5=N | ≥5→999 | 실수량 | 0→ · <5→(N) · ≥5→(999) |
| 스마트스토어 | API | products/{A.id} optionCombinations | stockQuantity=0 | stockQuantity=N | 큼→999 | 실수량 | 0→ · 큼→ · A.id 필수(productNo→999 둔갑) |
소싱처별 상세 카드 ↓
무신사
재고·표면가무로그인 · 서버혜택로그인 · 확장
수집 방법 (데이터별)
상품명API대표이미지API추가이미지HTML옵션API재고API표면노출가API혜택API
| 품절(없음) | API outOfStock=true → 재고 0 |
| 한정(N개) | API 재고 수치 또는 "잔여·마지막 N개" → 실수량 N |
| 충분(표식없음) | API 신호 없음 → 999 추론 (양의 수량 없음 → ⓪게이트 중요) |
| 파싱 실패 | 재고 API 전체 실패(inv 0건) → 확인불가(-1) · 999(충분) 둔갑 금지 = 오버셀 방지 [2026-07-08 musinsa.py] |
| 특이사항 | 소싱처 목록에 이 색×사이즈 없음(크롤 ok) → 품절(미판매·소멸) / 크롤 실패 상태면 → 확인불가(목록 최신 아님·품절 둔갑 금지) / API 호출 실패 → 크롤실패 |
왜 API? 전용 재고 API(prioritized-inventories)가 옵션별 실수량을 JSON으로 줌 → 1순위. 표면가도 API(salePrice)+검증게이트. 혜택만 회원 로그인.
SSG
재고·표면가무로그인 · 서버혜택무로그인 · 서버
수집 방법 (데이터별)
상품명HTML대표이미지HTML추가이미지HTML옵션HTML재고HTML표면노출가HTML혜택HTML
| 품절(없음) | HTML 정규식 usablInvQty=0 |
| 한정(N개) | HTML usablInvQty=N (실수량) |
| 충분(표식없음) | HTML usablInvQty 큰 값 → 충분 실수량 |
| 파싱 실패 | usablInvQty 필드 부재(필드명·포맷 변경) → 확인불가(-1) · 0(품절)도 999(재고있음)도 둔갑 금지 [2026-07-08 ssg.py] |
| 특이사항 | 딜페이지(dealItemView.ss) 파싱 실패 → 크롤실패 / 단일색 사이즈 파싱버그 주의 |
| 해결(07-04) | 단품 미수집 36칸 = 중복 SourceOption(size_text '220' vs '220mm')에서 매칭이 stale None 행을 먼저 골라 실재고 무시 → _match_option_so 가 재고 있는 행 우선. 라이브 미수집 0·값 실측 일치. |
왜 창 1개? SSG는 WAF(Sec-Fetch 차단)로 확장이 밖에서 직접 fetch하면 막힘 → ssg.com 도메인 탭 1개를 열어 그 안에서 same-origin fetch(렌더는 안 함). URL이 여러 개여도 탭 1개 안에서 동시 fetch(동시 상한만큼) — SSF(창 0개)와 다른 점.
왜 HTML? 재고·가격·혜택이 SSR HTML JS블록(uitemObj의 usablInvQty·bestAmt)에 통째로 박혀 옴 → 2순위 내장 JSON(정규식). 익명 curl_cffi 서버, 로그인 불필요.
SSF
재고·표면가무로그인 · 서버혜택무로그인 · 서버
수집 방법 (데이터별)
상품명HTML대표이미지HTML추가이미지HTML옵션HTML재고HTML표면노출가HTML혜택HTML
| 품절(없음) | HTML statcd=SLDOUT |
| 한정(N개) | HTML 품절임박 ( N ) → N (괄호공백 주의) |
| 충분(표식없음) | HTML statcd 정상 → 충분 상태값 (수량 아님 → ⓪게이트 중요) |
| 특이사항 | 옵션 li 없음 → 옵션없음 · 옵션 목록 통째 파싱 실패 시 단품 폴백(999)은 정상 단품과 구분 불가 → 상품 status 로 게이트 |
왜 HTML 정규식? 옵션·statcd·품절임박N 이 raw HTML(SSR)에 모두 있음 → 창없이 정규식 파싱(3순위). curl_cffi/확장 SW fetch raw 서버, 무로그인. [2026-07-08 정정: DOM→HTML — 렌더 불필요·창없이 실증] 단 정상재고 정량은 비공개(999가 정답).
롯데온
재고무로그인 · API표면가렌더 DOM · 창혜택회원할인만 로그인
수집 방법 (데이터별)
상품명API대표이미지DOM추가이미지DOM옵션API재고API+DOM표면노출가DOM혜택DOM
| 품절(없음) | API 매핑 품절 / DOM li.soldout |
| 한정(N개) | API 옵션 매핑 stkQty → 실수량 N (라이브 검증 220=5·10개) |
| 충분(표식없음) | API stkQty 실수량(20·30·41) → 충분 실수량 (999 아님) |
| 특이사항 | 매핑 API + DOM 둘 다 실패 → 크롤실패 |
왜 API? 라이브 확장이 옵션 API(option/mapping)의 stkQty로 실수량을 잡음 — 충분도 20·30·41 실수량(999가 아님, 라이브 124셀 검증). 화면 999/품절 둔갑이 보이면 = 저장 중복행 stale 폴백(→5 에러이력 S3). 대체상품 999(품절 슬롯에 끼는 다른 상품)는 별개·드문 케이스(확장 spdNo 가드). 해결(07-04): 모음전 미수집 47칸 = 중복행에서 매칭이 stale None 을 먼저 고르던 것 → _match_option_so 가 재고 있는 행 우선. 라이브 미수집 0·올리브 230=품절·다크235=49 실측 일치.
스마트
스토어
스토어
표면가·리뷰적립무로그인 · 서버per-SKU 재고로그인 · 확장
수집 방법 (데이터별)
상품명API대표이미지API추가이미지API옵션API재고API표면노출가API혜택API
| 품절(없음) | API SKU stockQuantity=0 |
| 한정(N개) | API stockQuantity=N → 실수량 |
| 충분(표식없음) | API stockQuantity 큼 → 충분 실수량 |
| 특이사항 | per-SKU 재고는 _persist_option_stocks로 영속(2026-06-22 수정) · A.id 사용(productNo 쓰면 999 둔갑) / WAF 차단 → 크롤실패 |
왜 로그인 확장? 상품 inline JSON엔 SKU 단위 재고가 없고, 네이버 WAF가 서버 직접호출을 막음 → per-SKU 실수량은 로그인 확장 API로만 가능. 수집값은 _persist_option_stocks로 영속(라이브 98셀 실수량 확인). 표면가·리뷰적립은 무로그인 inline.
르무통
공홈
공홈
재고·표면가무로그인 · 서버혜택템플릿(크롤 아님)
수집 방법 (데이터별)
상품명HTML대표이미지HTML추가이미지HTML옵션HTML재고HTML표면노출가HTML혜택템플릿
| 품절(없음) | HTML option_stock_data 재고 0 / is_selling=F |
| 한정(N개) | HTML option_stock_data 수량 N → 실수량 |
| 충분(표식없음) | HTML option_stock_data 수량 큼 → 충분 실수량 |
| 특이사항 | 실제 조합만 수집(미판매 사이즈 과다수집 방지) → 날조 옵션 없음 |
왜 HTML? Cafe24가 실제 판매조합·실재고를 option_stock_data JSON으로 페이지에 통째로 박아줌 → 2순위 내장 JSON. 전부 무로그인 서버.
현대
H몰개선예정
H몰개선예정
재고·표면가무로그인 · 서버혜택로그인 · 확장
수집 방법 (데이터별)
재고내장 JSON표면노출가내장 JSON혜택DOM
| 품절(없음) | 내장 sellGbcd="11" → 품절 ( 품절도 stockCount=1 센티넬로 옴) |
| 한정(N개) | 내장 sellGbcd="00" + stockCount=N → 실수량 |
| 충분(표식없음) | 내장 sellGbcd="00" + stockCount 큼 → 충분 실수량 |
| ★ 품절판정 | 반드시 sellGbcd 우선 — stockCount 단독 판정 금지(품절도 stockCount=1 = 거짓 '1개 있음' 금전손실). 라이브 실증 2026-07-03(올리브 230·240·250·260 = sellGbcd 11 품절인데 stockCount 1) |
| 특이사항 | 단품=__NEXT_DATA__ stockList[] / 모음전(색×사이즈)=item-stockcount API 색별 프로브. API 직접호출 방화벽 차단 → navGrab. 혜택은 로그인 DOM |
왜 내장 JSON? Next.js SSR이 재고·가격을 __NEXT_DATA__에 통째로 줌(2순위). 전용 API는 방화벽 차단이라 못 씀. 혜택은 클라이언트 JS 렌더라 로그인 확장 DOM에서만.
롯데
아이몰
아이몰
재고·표면가무로그인 · 서버혜택L.POINT만 로그인
수집 방법 (데이터별)
재고내장 JSON표면노출가내장/DOM혜택내장 JSON
| 품절(없음) | 내장 itemInvQtyInfo inv_qty=0 |
| 한정(N개) | 내장 inv_qty<5 → 실수량 N ('N개 남음', 사이트 JS 기준) |
| 충분(표식없음) | 내장 inv_qty ≥5 → 999(충분) 실수량 (사이트: 5~500 라벨없음·>500 판매중, _lotteimall_disp_qty) |
| 특이사항 | WAF 403 → 롯데아이몰 도메인 탭 1개에서 same-origin fetch로 통과 도메인 탭 1개 · 간헐 실패 시 렌더 창 폴백 [2026-07-14 정정: SW fetch(창0) 아님 — same-origin(창1). SSG와 동일 방식] / 혜택 L.POINT는 로그인 |
왜 내장 JSON? 핵심 재고·가격이 SSR itemInvQtyInfo/dataBenefit에 박혀 옴(2순위). 단 WAF 403이라 도메인 탭 1개에서 same-origin fetch로 통과(SSG와 동일, 안 되면 렌더 창 폴백). 혜택(L.POINT)은 로그인.
핵심표면 노출가 − 혜택 = 최종 매입가 · 소싱처마다 [수집 → 가공 게이트 → 계산 순서] 3단 명세 (2026-07-23 실측 확정본).
소싱처 가격·혜택 정규화 v3 — 자동화 명세
2026-07-23 · 실측 근거: 8소싱처 실상품 URL 직접 접속(7/22~23) + 샘플 URL 14개 + 주문서 검산 3건 + 크롤러 원본 코드. 정본 스펙: docs/superpowers/specs/2026-07-22-소싱처-표면노출가-혜택-최종매입가-design.md §11 · 2026-07-23 2차 대조: 미확정 9건 코드 전수확인 — 구현완료 6건 승격(롯데온 최대혜택가·롯데온 혜택항목별·무신사 결제택1·Hmall OK캐시백·아이몰 OK캐시백·SSG 다운로드 쿠폰 레이어) · 미구현 1건(Hmall VIP라운지) · 주문서 확인 대기 2건(SSG 청구+제휴 동시·아이몰 상품별 쿠폰 적용)
목적 단 하나 — 자동화 프로그램이 「최종매입가 = 표면노출가 − 혜택」을 위해 정보수집 → 정보가공을 정확히 해내는 것
소싱처마다 [STEP1 수집(어디서·뭘·어떻게·자동화 신뢰등급)] → [STEP2 가공 게이트(선반영 제외·택1·이중차감 방지·조작)] → [STEP3 계산 순서] 를 프로그램 명세 그대로 기술
배지 안내 · 공통 엔진 규칙
API·내장 데이터페이지·API에 실려 오는 데이터 직읽기 (대부분 무로그인)
자동 실증이번 검증에서 스크립트로 자동 수집까지 실증됨
화면 글자 읽기HTML 글자에서 정규식·셀렉터로 추출
가능·구현확인확장 크롤 경로로 가능 — 구현하며 최종 확인
실화면·로그인(확장)확장이 로그인 실화면을 띄워 읽음
️ 추정·보수규칙 기반 추정 — 애매하면 안 깎음(매입가 과대=안전)
고정값(시드)크롤 없음 — 엔진 시드 테이블
미실측실측 전 — 값 사용 금지
공통 가공·계산 (전 소싱처 동일 — 계산 엔진
① 정액(원) 먼저 차감 → 정률(%)은 직전 잔액에 순차 곱셈 (Hmall 주문서로 실물 검증: 네이버 8% = 쿠폰 차감 후 잔액 기준) · 마지막 백원 버림
② 경로 전부 계산 → 최저가 자동 채택: 경유 택1 {일반 / N쇼핑(
③ 철칙: 크롤 실패·값 없음 = 0(안 깎음)·폴백 금지 · 선반영 항목 = 재차감 금지(이중차감 방지) · 1회성·이벤트성·전용카드 = 제외(추가수익) · 애매하면 안 깎음
④ 경유 판별 계약: 크롤이
⑤ 혜택 저장 =
compute_breakdown → compute_final_price → compute_market_price)① 정액(원) 먼저 차감 → 정률(%)은 직전 잔액에 순차 곱셈 (Hmall 주문서로 실물 검증: 네이버 8% = 쿠폰 차감 후 잔액 기준) · 마지막 백원 버림
② 경로 전부 계산 → 최저가 자동 채택: 경유 택1 {일반 / N쇼핑(
naver_via) / OK캐시백(cashback·base_ratio)} × 결제 택1(payment) — N쇼핑 경유면 캐시백 OFF · 캐시백 경유에도 현대카드 2.73% 유지 · N페이 1%는 결제와 동시(SSG·아이몰 ✗·롯데온 조건부)③ 철칙: 크롤 실패·값 없음 = 0(안 깎음)·폴백 금지 · 선반영 항목 = 재차감 금지(이중차감 방지) · 1회성·이벤트성·전용카드 = 제외(추가수익) · 애매하면 안 깎음
④ 경유 판별 계약: 크롤이
naver_via_preapplied(표시가 반영 여부)를 보내고, 엔진은 true 면 주입하지 않는다(재차감=이중차감 방지). ️저장 필터가 False 를 버리면 한 번 true 가 박힌 소싱처는 경유 혜택을 영영 못 깎는다 → 플래그 키는 예외 통과(2026-07-23 실측 수정)⑤ 혜택 저장 =
dynamic_benefits_json — ️확장 크롤 save_crawl_result가 혜택 미저장(기지 결함) → 구현 시 필수 해소
검산 영수증 3건 — 가공 로직의 테스트 정답지 (전부 원단위 일치 실측)
① 무신사 — "토글 안 끄면 오염된다"의 증명
musinsa.com/products/3347848 · 수집 게이트 검증용
API salePrice (깨끗한 표면가)119,900
− 적립금 사용 (사이트 기본 ON)−8,390
− 결제 즉시할인 (기본 자동선택)−10,000
= 사이트 「나의 할인가」101,510
교훈: 토글 2개를 끄지 않으면 표면가가 개인 보유금·특정카드에 오염됨 → 크롤은 salePrice 직읽기 + 조작 3종 필수
② Hmall 주문서 — 중첩·순차 곱셈 검증
나이키 줌 벨라 · 쿠폰+네이버+카드 전부 중첩
판매가102,500
− 10% 바로사용쿠폰−10,250
− 네이버가격비교 (92,250×8%)−7,380
− 현대카드 5% (84,870×5%)−4,243
+ 배송비+3,500
= 총 결제금액84,127
정률이 직전 잔액에 순차로 곱해지는 실물 — 엔진 순차차감 방식과 동일
③ 아이몰 주문서 — 택1·청구할인 기준 검증
같은 상품 · 아이몰 82,110 < Hmall 84,127 (몰 대결 실례)
판매가102,500
− 즉석쿠폰 13% (L.CLUB 7%와 택1)−13,330
− 네이버 7%플러스쿠폰 (89,170×7%)−6,240
+ 배송비+3,500
= 최종결제 86,430 → 삼성카드 5% 청구−4,320
= 카드청구할인가82,110
청구할인 5%는 배송비 포함 최종결제금액 기준 · L.POINT 432 = 86,430×0.5% 일치
한눈 비교표 — 항목 × 소싱처 8곳 (v2 A안 표 원본 이식 · 상세 근거는 아래 파이프라인 카드)
| 구분 | 르무통 공홈lemouton.co.kr | 스마트스토어brand.naver.com | 무신사musinsa.com | SSFssfshop.com | 롯데온lotteon.com | SSGssg.com | Hmallhmall.com | 롯데아이몰lotteimall.com |
|---|---|---|---|---|---|---|---|---|
| 표면노출가무엇을 기준가로 쓰나 | 판매가격 116,900화면 글자 읽기strong.price-number → 폴백 span.ProductPrice → meta[product:sale_price:amount] → JS var product_price · 원가 span.txt_price.ProductPrice기본할인 22% 선반영 |
나의할인가 118,000API·내장 데이터__PRELOADED_STATE__ → simpleProductForDetailPage.A.benefitsView.discountedSalePrice (폴백 mobileDiscountedSalePrice·dispDiscountedSalePrice) · 정가 salePrice즉시할인 31,000·상품쿠폰 선반영쿠폰 없으면 = 상품가격 (7/22 실측) · 비로그인 크롤 가능 |
API 판매가 119,900API·내장 데이터GET goods-detail.musinsa.com/api2/goods/{goodsNo} → salePrice (정가 normalPrice) · 페이지 내장 __NEXT_DATA__ goodsPrice.salePrice 동일️ 회원가 member_price 아님! · 적립금사용(기본 ON)·즉시할인(기본 선택) 토글 전부 끈 기준값 |
할인가 119,900화면 글자 읽기em.price (없으면 originPrice)시즌 상품할인 선반영비로그인 "최대" 표기 아님 · 조작 없음 |
최대혜택가 118,690실화면·로그인(확장)「최대 할인혜택 적용」 후 나의 혜택가 — 확장 lotteonExtractor · 데이터 원천 pbf.lotteon.com API · 보조정규식 나의 혜택가[^\d]*([\d,]+) (숫자+원 인접·자릿수≥4·1,000원 하한 가드)즉시할인 2종+최적카드+오너스 1% 선반영패널이 구성 금액 전부 노출 (7/22 실측) — 항목별 크롤로 이중차감 방지 · 현재 크롤은 「나의 혜택가」까지, 「최대 할인혜택 적용」 베이스 교체는 ⏳구현 예정 (스펙 §7-1) |
최적가 119,900API·내장 데이터내장 uitemObj → 1순위 bestAmt · 2순위 sellprc 폴백즉시할인+SSG MONEY 즉시할인(패턴 A/C) 선반영 7/23 실페이지 육안 확인: 표시가 119,900 = 크롤값 일치 · ️자동화 전 경로 차단 — 확장 크롤 유일 |
깜짝할인가 119,900API·내장 데이터<script id="__NEXT_DATA__"> → props.pageProps.respData.itemPtc.bbprc️ sellPrc=정가 149,000 둔갑 함정(실측) · 옵션루프 bbprc:0 다수 — 본품 항목만 · 카드할인 미포함 |
카드 미적용가 119,900API·내장 데이터dataBenefit JSON commonDiscountObj.benefitPrc(=최대할인가·카드 청구할인 포함, 라벨 benefitPrcLabelTxt) + 카드혜택 금액 되돌림(가산) · 할인 구성 = fullDiscountObj.discountList[](discountNm·discountAmount) — 7/23 필드 실측상품쿠폰(기본 ON) 선반영️「최대할인가」 그대로 쓰기 금지 — 카드 선반영 상품 有 · 실측: 이 상품 카드금액 0 → 119,900 그대로 · 카드 가산은 크롤러 기구현(2026-07-18) |
| 등급·멤버십 할인 | — | — | LV별 상시% (상품별)실화면·로그인(확장)확장 musinsaExtractor — 나의할인가 패널 「등급 할인」 항목실측: 이 상품 "등급 할인 불가" (상품별 상이) |
— | — | — | VIP 라운지 (상품별)실화면·로그인(확장)확장 navGrab(post-JS DOM) — 로그인 화면에서만 |
— |
| 상품쿠폰 | — | 선반영 → 차감 금지__PRELOADED_STATE__ → benefitsPolicy (예: sellerImmediateDiscountPolicyNo·sellerImmediateDiscountValue)「쿠폰받기」 자동 ON 포함가가 표면가 — 존재 여부만 확인 |
쿠폰별 키워드 게이트실화면·로그인(확장)확장 musinsaExtractor — 나의할인가 패널 「상품 쿠폰」 항목1회성·LV 지급 쿠폰 제외 · 실측: 이 상품 "사용가능 쿠폰 없음" |
「쿠폰다운」 버튼 (상품별)화면 글자 읽기raw HTML 쿠폰다운 영역 파싱 (ssf.py)표면 미반영 → 차감 · 실측: 이 상품 없음 |
스토어찜 쿠폰 (토글)실화면·로그인(확장)확장 lotteonExtractor — 혜택변경 패널 쿠폰 항목기간 한정 이벤트 |
상품쿠폰 (기간한정)화면 글자 읽기raw HTML 쿠폰 영역 파싱 (ssg.py) |
상품쿠폰 (기간한정)실화면·로그인(확장)확장 navGrab DOM |
선반영 → 차감 금지commonDiscountObj.benefitPrc에 포함기본 ON · 실측: 패널 「쿠폰할인 −29,100」 라벨 |
| 구매 적립 | — | 기본 1%API·내장 데이터benefitsView.managerPurchasePoint실측 1,180원 = 네이버 지급 (판매자 sellerPurchasePoint=0) |
라디오 「구매 적립」 택실화면·로그인(확장)확장 musinsaExtractor — 「구매 적립/선할인」 라디오 값선할인과 택1 · ★「적립금 사용」 기본 ON → 꺼야 함 |
멤버십포인트 0.5~5%화면 글자 읽기raw HTML 「멤버십포인트 NP」 정규식 (ssf.py)실측 599P = 0.5% |
오너스 0.5% + L.POINT 0.05%고정값(시드)시드 — 엔진 후반영(적립) 항목실측 「L.POINT 최대 652P」 = 0.55% 일치 | SSG MONEY 적립 n%화면 글자 읽기ssg_money_rate·ssg_money_amount·ssg_money_already_applied (ssg.py · 저장 화이트리스트 service.py:432)2분기: ①상시=항상 / ②충전결제=rate≥3%만 (api_benefits.py:581) · 선반영이면 already_applied=True → 중복차감 금지 · 7/23 육안 실측: 이 상품 = 충전 1.5%만 노출(3% 미만 → 미차감 분기 정상)·상시 적립 미노출 |
H.Point 0.1~1% (이벤트 5%)API·내장 데이터__NEXT_DATA__ itemPtc 적립 필드실측 「기본 140P」 = 0.1% |
L.CLUB 0.5%API·내장 데이터commonDiscountObj.lPointObj.lMbrPoint · L.CLUB 여부 lclubYn — 7/23 필드 실측실측 +599P = 0.5% (L.CLUB 가입 기준) |
| 리뷰 적립묶음주문 1건만 · 소싱처별 시드 통일 ⏳구현 예정 (스펙 §7-6) | 포토 5,000원고정값(시드)시드 — 크롤 불가 위치(구매 후 후기작성 화면) | 포토 3,000 + 한달포토 2,000 = 5,000API·내장 데이터benefitsView.photoVideoReviewPoint(2,850) + managerPhotoVideoReviewPoint(150) · afterUsePhotoVideoReviewPoint(2,000) · 텍스트 textReviewPoint+managerTextReviewPoint · 한달텍스트 afterUseTextReviewPoint실측: 2,850+150=3,000 정확 (크롤 4항목) |
텍스트 500원고정값(시드)화면 「후기적립 2,500」은 포토 등 포함 — 텍스트만 쓰기로 확정(7/22) | 텍스트 200원고정값(시드) | 텍스트 50원고정값(시드) | 텍스트 50원고정값(시드) | 텍스트 100원고정값(시드) | 별점 100원 (L.CLUB)고정값(시드)지급기준 실측: 일반 50/200/300 · L.CLUB 100/300/600 — "일반(별점)만 100원" 확정(7/22) |
카드 — 기본결제 택1 · payment 태그 |
현대카드 2.73%고정값(시드)시드 — payment 태그 |
현대카드 2.73%고정값(시드)시드 — payment 태그 |
무신사머니 vs 현대 2.73% 큰 쪽실화면·로그인(확장)확장 musinsaExtractor — 결제수단 적립 라디오 「무신사머니 결제 시 n% 적립」 금액 크롤 (%리터럴 없음)실측 3.5%(LV.8 다이아) > 2.73% → 머니 승 · 등급별 상이 · 현재 엔진은 "머니 있으면 머니", 큰 쪽 자동 비교는 ⏳구현 예정 (스펙 §7-3) |
현대카드 2.73%고정값(시드)시드 — payment 태그 |
§카드 경로 규칙최적카드=현대카드면 +2.73% 추가 / 타 카드면 2.73%·N페이 미차감 / 카드 없으면 2.73%+N페이 1% | 현대카드 2.73%고정값(시드)시드 — payment 태그 (카드혜택가 미노출 상품 fallback) |
현대카드 2.73%고정값(시드)시드 — payment 태그 |
현대카드 2.73%고정값(시드)시드 — payment 태그 |
| 카드 — 즉시·청구할인 | — | — | 「적용 안함」 라디오 필수실화면·로그인(확장)확장 musinsaExtractor — 결제수단 즉시할인 라디오를 「적용 안함」으로실측: 기본이 첫 항목(−10,000) 자동선택 — 끄고 크롤해야 표면가 오염 방지 |
— | 카드 즉시할인 목록 크롤실화면·로그인(확장)확장 lotteonExtractor — 혜택변경 패널 카드명+금액 목록경로 열거 + 보유카드 가드(PurchaseCard 17종 — 없는 카드 할인은 되돌려 가산) |
청구할인(카드혜택가 정률) + 제휴 동시화면 글자 읽기raw HTML 카드혜택가 영역 (ssg.py — 노출 시만·표시만, 자동적용 아님)청구+제휴 동시 적용 가정 (안 되면 추후 제거 — 데이터로 배선) ⏳배선 예정 (스펙 §7-8) · 7/23 육안 실측: 이 상품 카드혜택가 미노출 → 현대 2.73% 폴백 경로 확인 |
「즉시 할인」 카드 목록 — 창 없이 API 구현API·내장 데이터GET /api/hf/dp/v1/item-ptc/item-prmo-lst?slitmCd= → crdImdtDcPrmoList[] · ★쿠키 uh2oxid를 헤더로도 전송해야 200(쿠키만이면 401) — 확장 v0.7.57 fetchHmallPromosSW필드: crdcNm(카드명)·famtFxrtGbcd(1=정률/2=정액)·famtFxrtVal(5=5%)·strtVal(최소결제)·aplyStrtDtm~aplyEndDtm · ️일자별 로테이션(유효기간이 당일 00:00~23:59로 데이터 확증) + prmoNm "(전관)"=상품 공통 · 크롤 당일 값 사용(확정 7/23) · 경로 열거 + 보유카드 가드 |
청구할인(카드혜택가 정률) — fx 분리실화면·로그인(확장)dataBenefit 카드혜택 금액 (benefitPrc에서 분리·가산 후 fx로 차감)실측: 현대카드 5% 배너 |
| N페이 1%결제와 동시 | 적용 | 적용 | — | 적용 | 조건부카드 즉시할인 경로 선택 시 미적용 (§카드 경로 규칙) | ✗ | 적용 | ✗ |
경유 — N쇼핑naver_via 태그 · 수집·배선 (2026-07-23) · 몰별 선반영 판별 게이트 필수 |
— | — | — | ✗ 없음 | 제휴할인 (정액)실화면·로그인(확장)N쇼핑 경유 화면 제휴할인 금액 — naver_via쿠폰버튼 아님 · %가 아닌 정액 표기 |
「[제휴할인] N% 쿠폰」 화면 글자 읽기크롤러가 ckwhere=ssg_naver(+utm) 유입 파라미터로 요청 → PDP 에 제휴쿠폰 노출 → product_coupon_rate 파싱 · 라벨에 「제휴」 있으면 channel=naver_via★사장님 확정(7/23): 경유는 N쇼핑 or OK캐시백 택1 · 할인 큰 쪽 · 중복 금지 → 제휴쿠폰은 경유 축이라 캐시백과 자동 배타, 경로 열거로 큰 쪽 채택. 일반 상품쿠폰은 현행 수동 토글 유지 |
4~10% (상품별)naver_via · 용어 실물: 「네이버 8%할인」 · 할인내역 항목명 「네이버가격비교」️경유+로그인 시 혜택가에 선반영 — 실측(나이키 보메로): 198,000 −7%바로사용쿠폰 13,860 −네이버가격비교 14,730(=184,140×8%) = 169,410. 판별 원천 = item-ptc API 의 tcDcInf(tcCdNm"네이버가격비교"·dcRate8·tcDcAmt14,730) → naver_via_preapplied=true 로 보내 재차감 금지. ★raw HTML 엔 없다(할인내역이 JS 렌더 — 문자열 검색 방식은 실패) · 주문서 실측(줌 벨라): 네이버 8%는 "즉시할인" 분류로 쿠폰·카드 5%와 전부 중첩, 순차 곱셈 검산 일치(총 84,127) · 「바로접속 OFF」 트레이드오프: 경유=네이버 할인 ↔ 바로접속=H.Point 리워드·멤버십 쿠폰 (양자택일) |
~15% (상품별)naver_via · 실체 확정: 「네이버 N%플러스할인쿠폰」(6·7·9%, `_의류` 등 카테고리 한정) — 경유 시 쿠폰함 발급표시가 미반영 → 주문서 "플러스 할인쿠폰" 칸에서 적용 (7/23 주문서 실측: 89,170×7%=−6,240 검산 일치). 즉석쿠폰 13%(=benefitPrc 선반영)는 할인쿠폰 칸에서 L.CLUB 7%와 택1 · 청구할인 5%는 배송비 포함 최종결제금액 기준 · 경유 7% ≫ OK캐시백 2.5% |
경유 — OK캐시백cashback 태그 · 자사페이 결제 필수 |
— | — | — | — | 1.1% ×0.9고정값(시드)시드 base_ratio=0.9 |
2.0% ×1.0고정값(시드)시드 base_ratio=1.0 (전액 예외) |
2.7% ×0.9고정값(시드) ⏳신규 시드 예정시드 base_ratio=0.9 · ️key:hmall 문자열 source_id — 정수 시드 불가 기지 이슈 |
2.5% ×0.9고정값(시드) ⏳신규 시드 예정시드 base_ratio=0.9 |
| 기타 · 보류/제외 | 「이벤트결제 10% 추가적립」 배너 = 이벤트성 제외 | 플러스멤버십 5%·특정카드 4% 적립 = 제외 | 삼성카드 10% 적립·첫결제 3만 할인 = 전용카드·1회성 제외 (추가수익) | 기프트포인트 10%화면 글자 읽기정규식 기프트포인트</dt><dd>…([\d,]+)원 (GIFT_POINT_PATTERN, ssf.py)멤버십 한정 · 활성 시만 노출 · 변동값 |
토스페이 2.5%·L.PAY 제휴·L.PAY 충전 2% = 보류 | MONEY 충전적립 1.5% = 제외(7/23 육안 확인) · 쓱클럽 7%·SSG.COM카드 Ed2 = 멤버십·전용카드 제외 · ️확장 크롤이 혜택 미저장(기지 결함 — 구현 시 해소) | H포인트페이 추가할인·현대카드 Ed2 7%(전용) = 보류 | L.PAY 추가할인 = 보류 |
1. 르무통 공홈lemouton.co.kr · 7/22 실측
STEP 1 · 수집
| 항목 | 위치 · 코드 | 방식 | 신뢰 |
|---|---|---|---|
| 표면노출가 | 판매가격 — strong.price-number → span.ProductPrice → meta[product:sale_price:amount] → JS var product_price | 화면 글자 | |
| 리뷰적립 | 시드 포토 5,000원 (크롤 불가 위치 — 수집 안 함) | 고정값 | |
| 크롤 창 | 확장 서비스워커 직접 fetch — 창 0개 (winless 레인) | 창없이 |
STEP 2 · 가공 게이트
- 기본할인(22%) = 선반영 → 차감 금지
- 「이벤트결제 10% 추가적립」 배너 = 이벤트성 → 제외
STEP 3 · 계산 순서
판매가격 −리뷰 5,000(정액) → ×현대카드 2.73% ×N페이 1%(동시) · 경유 축 없음
2. 스마트스토어brand.naver.com · 7/22 실측
STEP 1 · 수집 — 전부 한 객체에서 (비로그인 가능, Playwright 실증)
| 항목 | 위치 · 코드 | 방식 | 신뢰 |
|---|---|---|---|
| 표면노출가 | __PRELOADED_STATE__…benefitsView.discountedSalePrice (폴백 mobile-·disp-) · 정가 salePrice | 내장 | |
| 쿠폰 존재 | benefitsPolicy (있으면 표면가에 이미 포함) | 내장 | |
| 구매적립 | benefitsView.managerPurchasePoint (실측 1,180=1%) | 내장 | |
| 리뷰 4항목 | photoVideoReviewPoint+manager-(=3,000) · afterUsePhotoVideoReviewPoint(=2,000) 외 | 내장 | |
| 크롤 창 | 확장 서비스워커 직접 fetch / per-SKU 혜택은 로그인 확장 | 창없이 |
STEP 2 · 가공 게이트
- 즉시할인·상품쿠폰 = 표면가에 선반영 → 차감 금지
- 리뷰 = 포토+한달포토만 (텍스트 제외 — 사장님 확정)
- 플러스멤버십 5%·특정카드 적립 = 제외
STEP 3 · 계산 순서
표면가 −리뷰 5,000 −구매적립 1% → ×현대카드 2.73% ×N페이 1% · 경유 축 없음(자기가 네이버)
3. 무신사musinsa.com · 7/22~23 실측 (르무통 외 3상품 포함)
STEP 1 · 수집
| 항목 | 위치 · 코드 | 방식 | 신뢰 |
|---|---|---|---|
| 표면노출가 | GET goods-detail.musinsa.com/api2/goods/{no} → salePrice (정가 normalPrice) | API | |
| 쿠폰선반영 게이트 | couponDiscount·couponPrice·finalPrice — true+차이나면 쿠폰적용가 존재 | API | |
| 등급할인·상품쿠폰·적립 | 확장 musinsaExtractor — 나의할인가 패널 항목별 (로그인) | 실화면 | |
| 무신사머니 적립액 | 결제수단 적립 라디오 「머니 결제 시 n% 적립」 금액 (실측 3.5% 다이아·등급별 상이) | 실화면 | |
| 리뷰적립 | 시드 텍스트 500원 (화면 「후기적립 2,500」은 포토 포함 — 미사용) | 고정값 | |
| 크롤 창 | 렌더 필요(로그인 혜택 패널) — URL 수만큼 창 · 표면가 API는 창없이 가능 | 렌더 창 |
STEP 2 · 가공 게이트
- 표면가 = salePrice만.
couponPrice(쿠폰적용가) 사용 금지 — 실물: 메이트 타색 129,890 vs 쿠폰가 116,910. 쿠폰은 fx로 분리 - 크롤 전 조작 3종 필수: 적립금 사용 OFF(기본 ON!) · 결제 즉시할인 「적용 안함」(기본 첫 항목 자동선택!) · 선할인 → 「구매 적립」 라디오(선할인이 기본 선택된 상품 실존 — 빈폴 −6,070 실측)
- 상품쿠폰 = 키워드 게이트(1회성·LV 지급 쿠폰 제외)
- 삼성카드 10% 적립·첫결제 할인 = 전용카드·1회성 → 제외 · N페이 없음
STEP 3 · 계산 순서
salePrice −후기 500 −등급할인(크롤값) −상품쿠폰(게이트 통과분) → 결제 택1: 무신사머니 적립 vs 현대카드 2.73% 큰 쪽 현대카드 플로어 방식으로 구현 — 무신사머니가 잡히면 플로어 비활성, 큰 쪽이 남는다. 핀 =
tests/pricing/test_card_candidates.py(결제수단 동시 등장 금지)·test_hyundai_floor_all_sources.py §3-3 · 경유 축 없음4. SSF샵ssfshop.com · 7/22~23 실측 (빈폴 포함)
STEP 1 · 수집 — 무로그인 raw HTML 하나로
| 항목 | 위치 · 코드 | 방식 | 신뢰 |
|---|---|---|---|
| 표면노출가 | em.price (없으면 originPrice) | 화면 글자 | |
| 다운로드 쿠폰 | 「쿠폰다운」 버튼 영역 (상품별 — 실물: 빈폴 있음·르무통 없음) | 화면 글자 | |
| 멤버십포인트 | 「멤버십포인트 NP」 정규식 — 0.5~5% 상품별 (실측 599P=0.5% · 6,616P=5%) | 화면 글자 | |
| 기프트포인트 | GIFT_POINT_PATTERN 정규식 — 활성 시만 노출·변동값 | 화면 글자 | |
| 리뷰적립 | 시드 텍스트 200원 | 고정값 | |
| 크롤 창 | 확장 서비스워커 직접 fetch(무로그인 raw HTML) — 창 0개 | 창없이 |
STEP 2 · 가공 게이트
- 시즌 상품할인 = 선반영 → 차감 금지
- 쿠폰다운 = 표면 미반영 → 차감 (상품별 유무 크롤)
- 카드사 1회성 추가할인 = 추가수익 → 제외 · N쇼핑 없음
STEP 3 · 계산 순서
em.price −쿠폰(있으면) −기프트포인트 −멤버십포인트 −리뷰 200 → ×현대카드 2.73% ×N페이 1%
5. 롯데온lotteon.com · 7/22~23 실측 (나이키 카드할인 상품 포함)
STEP 1 · 수집 — 확장·로그인
| 항목 | 위치 · 코드 | 방식 | 신뢰 |
|---|---|---|---|
| 표면노출가 | 「최대 할인혜택 적용」 후 나의 혜택가 — 확장 lotteonExtractor(0.7.55+)가 pbf.lotteon.com qtyChangeFavorInfoList 를 aplyBestPrcChk:"Y"(=사이트 「최대 할인혜택 적용하기」와 같은 경로)로 호출 → orderDcAplyTotAmt(폴백 favor.totAmt) · 보조정규식 나의 혜택가[^\d]*([\d,]+)(1,000원 하한 가드) | 실화면 | |
| 혜택 구성 항목별 | 혜택변경 패널 — 스토어 즉시할인·롯데ON n%·오너스 1% 금액별 노출 (실측 검산 일치) · 수집 = lotteon_card_discounts[{label,amount,rate}]·lotteon_store_discount (서버 화이트리스트 sources/service.py:643-645) | 실화면 | |
| 카드 즉시할인 목록 | 패널 카드명+금액 (실물: 롯데카드 5% −7,450·카카오페이머니 5% — 비로그인에도 노출) | 실화면 | 구조 실증 |
| N쇼핑 제휴할인 | 가격 구성의 「제휴할인」 항목 — 경유 시 자동 반영(별도 네이버 표시 없음, 7/23 사장님 확정) · 존재 여부+금액 수집 | 실화면 | 확정 |
| 적립·리뷰 | 시드: 오너스 0.5%+L.POINT 0.05%(실측 652P=0.55% 일치) · 리뷰 50원 | 고정값 | |
| 크롤 창 | 렌더 필요 — URL 수만큼 창(로그인 쿠키로 pbf 호출) · WAF로 밖에서 직접 fetch 불가 | 렌더 창 |
STEP 2 · 가공 게이트
- 패널 구성 항목(즉시할인 2종+최적카드+오너스) = 전부 선반영 → 차감 금지
- 카드 경로 규칙: 최적카드=현대카드→+2.73% 추가 / 타 카드→2.73%·N페이 미차감 / 카드 없음→2.73%+N페이 1%
- 보유 카드 가드:
PurchaseCard17종에 없는 카드 할인은 되돌려 가산 - 「제휴할인」 항목 존재 = N쇼핑 경유 상태로 인지 — 자동 선반영이므로 naver_via 재차감 금지 (이중차감 판별 게이트)
- 토스페이 2.5%·L.PAY류 = 보류
STEP 3 · 계산 순서
최대혜택가 −리뷰 50 −오너스적립 0.5% −L.POINT 0.05% → 카드 경로 × 경유{일반 / N쇼핑(제휴할인 자동 선반영 — 존재 시 재차감 금지) / OK캐시백 1.1%×0.9}
6. SSGssg.com · 7/23 육안 3상품 (자동화=확장 크롤 유일)
STEP 1 · 수집 — ️외부 자동화 전 경로 차단 → 확장 크롤러만
| 항목 | 위치 · 코드 | 방식 | 신뢰 |
|---|---|---|---|
| 표면노출가 | uitemObj → 1순위 bestAmt · 2순위 sellprc (실측: 정가=bestAmt 상품도 존재) | 내장 | |
| SSG MONEY | ssg_money_rate·amount·already_applied (저장 화이트리스트 service.py:432) | 화면 글자 | |
| 카드혜택가(청구) | 노출 시만 파싱 (실측: 미노출 상품 → 현대 폴백) | 화면 글자 | |
| 다운로드 쿠폰 | 「쿠폰보기」 레이어 — 실물: [제휴할인] SSG 5% 8,342원(=166,840×5%) · 경유 ckwhere=네이버값 URL로 접속 · 2026-07-23 구현 완료 — 레이어 #store_modal_view_coupon_detail → div.dialog_group(제목이 「다운로드 쿠폰」인 것만) → div.dialog_coupon 안 .dialog_coupon_detail_tit(라벨)·.dialog_coupon_detail_price em(금액). 코드 ssg.py::_parse_download_coupons·pick_download_coupon·merge_coupon_fields. 검산: 즉시할인가 71,638 × 8% = 5,731 · × 5% = 3,581 — 사이트 표시 금액과 원 단위까지 일치(두 장 모두). 값은 요율로 실어 표면가가 바뀌어도 맞게 재계산. ️여러 장이면 큰 쪽 1장만(동시 적용 여부는 주문서에서만 확정 — 아이몰 P31 교훈) · 「적용 중인 쿠폰」 그룹은 선반영이라 안 읽음 · 쓱클럽 제외. 라벨의 「제휴」로 엔진이 경유 축 자동 편입 → OK캐시백과 택1(실측: 5,731 vs 캐시백 1,432 → 쿠폰 채택) | 화면 글자 | 실측 |
| 리뷰적립 | 시드 텍스트 50원 | 고정값 | |
| 크롤 창 | WAF(Sec-Fetch 차단) → ssg.com 도메인 탭 1개에서 same-origin fetch(렌더 없음) · URL 여러 개여도 탭 1개 | 도메인 탭 1개 |
STEP 2 · 가공 게이트
- bestAmt = 즉시할인+MONEY 즉시할인 선반영 ·
already_applied=True면 MONEY 재차감 금지 - MONEY 2분기: ①상시=항상 차감 / ②충전결제=rate≥3%만 (실측: 충전 1.5% → 미차감 정상)
- 청구할인+제휴할인 동시 적용 가정 주문서 확인 대기 · 양쪽 다 수집·배선 완료(청구할인 =
api_benefits.py:854-946조건부 정액 + 현대카드 fallback 자동 비활성 / 제휴할인 = 2026-07-23 레이어 파서 구현). 엔진 실행 실측(71,638 상품): 제휴 8% −5,731 → 현대카드 2.73% −1,799 → 64,108 으로 둘 다 차감된다. 남은 건 이게 실제 주문서와 같은지 1건 확인뿐 · N페이 ✗ · 쓱클럽·전용카드 = 제외 - ️셀러 상품 배송비 별도(3,500원 실측) — 배송비 축은 본 스펙 범위 밖(기록)
STEP 3 · 계산 순서
bestAmt −쿠폰 −MONEY적립 −카드혜택가(청구) −리뷰 50 → ×현대카드 2.73% × 경유{일반 / N쇼핑 ckwhere 쿠폰 / OK캐시백 2.0%×1.0(전액 예외)}
7. Hmallhmall.com · 7/22~23 실측+주문서 검산 (자동 수집 실증)
STEP 1 · 수집
| 항목 | 위치 · 코드 | 방식 | 신뢰 |
|---|---|---|---|
| 표면노출가 | __NEXT_DATA__ → props.pageProps.respData.itemPtc.bbprc · ️sellPrc=정가 둔갑·옵션루프 bbprc:0 함정 | 내장 | |
| 카드 즉시할인 목록 | 창 없이 API — item-ptc/item-prmo-lst?slitmCd= → crdImdtDcPrmoList[](crdcNm·famtFxrtVal·strtVal) · ★쿠키 uh2oxid를 헤더로도 전송(쿠키만=401) · 기간·노출·PC적용 가드로 만료분 차단 | API | |
| 네이버가격비교 | NaPm URL 1회 방문(쿠키) 선행 → 할인내역 「네이버가격비교」 금액 — 파라미터 없는 재접속에도 유지 실증 · ️ 상품 URL 뒤에 파라미터만 붙이는 건 효과 없다(2026-07-23 실측: ckwhere=naver·utm 세트를 붙여도 SSR itemPtc 의 bbprc 119,900 불변 · tcDcInf null). 켜는 법은 NaPm 링크 1회 방문뿐 — SSG 식 URL 파라미터 방식이 아니다 | 실화면 | 자동 실증 |
| H.Point 적립 | itemPtc 적립 필드 (실측 140P=0.1% · 이벤트 5% 有) | 내장 | |
| VIP라운지·상품쿠폰 | 확장 navGrab(post-JS DOM·로그인) · 현재 미구현: 크롤러·확장 어디에도 VIP라운지 수집 코드 없음 (2026-07-23 전수 grep 0건 — Hmall 은 카드 즉시할인 item-prmo-lst 까지만 구현, 확장 0.7.59) | 실화면 | 미구현 — 수집 코드 없음 |
| 리뷰적립 | 시드 텍스트 100원 | 고정값 | |
| 크롤 창 | 표면가·적립 = 서비스워커 fetch(창 0) / VIP·쿠폰·카드는 로그인 navGrab 창 | 창없이혜택 창 |
STEP 2 · 가공 게이트
- bbprc = 깜짝할인 선반영·카드 미포함 — sellPrc 사용 금지
- 할인내역에 「네이버가격비교」 항목 존재 = 선반영 → naver_via 재차감 금지 (이중차감 판별 게이트)
- 쿠폰·네이버·카드 5% = 전부 중첩 가능 (주문서 검산 ②) · 카드 즉시할인 = 보유 카드만 결제 경로 후보 → 현대카드 2.73%와 택1(큰 쪽) ·
min_order미달 카드 제외 · 카드 행 주입 시에만 플로어 선태깅(안 하면 이중차감) - 「바로접속 OFF」 트레이드오프: 경유=네이버 할인 ↔ 바로접속=H.Point 리워드·멤버십 쿠폰 (양자택일 — 경유 시 리워드류 제외)
- 현대카드 Ed2 7%·H포인트페이 = 전용·보류
STEP 3 · 계산 순서
bbprc −쿠폰 −H.Point −리뷰 100 → 카드 경로{당일 즉시할인 카드(보유 가드·최소결제 충족) vs 현대 2.73%+N페이 1%} 구현 × 경유{일반 / N쇼핑(선반영 게이트) / OK캐시백 2.7%×0.9 엔진 상수 주입으로 구현 완료 —
api_benefits.py:1088 apply_mode='cashback'·base_ratio=0.9(적립율 0.027 원본 유지). 핀 = tests/pricing/test_catalog_source_benefits.py. ★DB 시드(OK_CASHBACK_SEED)에 없는 건 정상 — key:hmall 문자열 source_id 라 템플릿을 못 붙여 상수로 넣은 것이고, supports_benefit_templates 가드가 나중에 템플릿이 생기면 상수 주입을 자동 중단해 이중차감을 막는다}8. 롯데아이몰lotteimall.com · 7/22~23 실측+주문서 검산+쿠폰함 자동 수집+PDP 다운로드 쿠폰 택1 실증
STEP 1 · 수집
| 항목 | 위치 · 코드 | 방식 | 신뢰 |
|---|---|---|---|
| 표면노출가 | dataBenefit commonDiscountObj.benefitPrc(라벨 benefitPrcLabelTxt) + 카드혜택 금액 가산(크롤러 기구현) — 「최대할인가」 그대로 사용 금지 | 내장 | |
| 할인 구성 | fullDiscountObj.discountList[] (discountNm·discountAmount — 「쿠폰할인」 라벨 실측) | 내장 | |
| 적립 | lPointObj.lMbrPoint(실측 599P=0.5%)·lclubYn | 내장 | |
| 보유 플러스쿠폰 (네이버 포함) | GET /mypage/searchCouponList.lotte?coupon_type=P&pageIdx=N (로그인·15p) — 쿠폰명(요율%+카테고리 접미사)·매수·기간 · 실측: 「■ 네이버 7%·3%_잡화」 수집 성공 · ️ 네이버 쿠폰은 URL 파라미터로 안 켜진다(2026-07-23 실측: ckwhere=naver·utm 세트를 붙여도 PDP 동일 — 「네이버」 0건). 발급형이라 계정 쿠폰함에 받아둬야 잡힌다. 참고로 PDP 다운로드 쿠폰(「[르무통] 5%」)은 파라미터 없이도 원본 HTML 에 나온다(재확인) | 실화면 | 자동 실증 |
| 상품별 쿠폰 적용 여부 | 상품 카테고리(breadcrumb) ↔ 쿠폰 접미사(_의류·_잡화·_백화점N) 매핑 — 100% 확정은 주문서뿐 | — | ️ 추정 |
| PDP 다운로드 쿠폰 | div.layer_down_coupon .coupon_list li → .name·.price/.per(%=정률·그 외=정액) · ★확장이 이미 받는 원본 SSR HTML 안이라 추가 호출 0 (crawlers/lotteon.py::_parse_download_coupons) · 실측: 「[르무통] 5% 다운로드 쿠폰」 · 들어가는 칸 = 「플러스 할인쿠폰」(주문서 확인) | 내장 | 주문서 실측 |
| 쿠폰 칸(중복) 판별 | 주문서 hidden: cpn_crd_dc_amt_12=할인쿠폰(구분코드 12) / cpn_crd_dc_amt_dup_30=중복할인(코드 30 — 플러스쿠폰) · 플래그 dup_cpn_enable·dup_cpn_cnt · 쿠폰함 coupon_type=P 적재로도 확인(실측 1,557→1,558매) · PDP 엔 종류 코드 없음(goDownloadCoupon('P') 의 P 는 다운로드 방식이지 쿠폰 종류가 아님) | 주문서·쿠폰함 | 실측 |
| 리뷰적립 | 시드 별점 100원 (L.CLUB 기준 — 기준 실측: 일반 50/200/300·L.CLUB 100/300/600) | 고정값 | |
| 크롤 창 | WAF 403 → 도메인 탭 1개 same-origin fetch(간헐 실패 시 렌더 창 폴백) · 쿠폰함은 로그인 페이지 fetch | 도메인 탭 1개 |
STEP 2 · 가공 게이트
- 즉석쿠폰(discountList 「쿠폰할인」) = benefitPrc에 선반영 → 차감 금지
- 택1 공식 규칙(쿠폰함 문구): 할인쿠폰/카드할인/TV쇼핑할인 중 1개 · 플러스/즉시적립할인 중 1개
- 다운로드 쿠폰은 「플러스 할인쿠폰」 칸 — 표면가에 반영된 「할인쿠폰」과 동시 적용, 기준은 표면가. 주문서 실측: 149,000 −할인쿠폰 29,100(=119,900) −플러스 6,000 = 113,900. 택1은 경유 「네이버 N%플러스할인쿠폰」과의 사이에서(쿠폰함: 플러스/즉시적립 1개) — 큰 쪽 1장. 사장님 확정: 「플러스쿠폰은 일반 쿠폰과 중복은 되지만 플러스쿠폰을 여러 개 쓰는 건 안 된다」 (쿠폰함 문구 「선택할인에 더하여 추가할인이 가능한 쿠폰」과 일치). 수집·반영 분리: 레이어 쿠폰은 전량 저장(근거 보존)하고, 선택은 계산 단계에서 — 플러스 칸 후보 풀 {다운로드 쿠폰 전량} ∪ {경유 네이버 플러스쿠폰} 중 가장 큰 1장만. ️1차 구현 때 PDP 만 보고 「할인쿠폰 칸」으로 오판 → 칸 판정은 주문서에서 (§5 P31)
- 플러스쿠폰 적용 = 카테고리 매핑 추정 — 애매하면 안 깎음 + 실구매 주문서 실적용 쿠폰 피드백 배선(보정)
- 청구할인(실측 현대·삼성 5%) = 배송비 포함 최종결제금액 기준 · N페이 ✗ · L.PAY류 보류
STEP 3 · 계산 순서
카드미적용가 −플러스쿠폰 칸{다운로드 쿠폰 vs 경유 네이버 플러스쿠폰 — 큰 쪽 1장} −리뷰 100 −L.CLUB 적립(정률·쿠폰 차감 후 기준) → 청구할인 경로(정률·보유카드) × 경유{일반 / N쇼핑 발급쿠폰 / OK캐시백 2.5%×0.9 엔진 상수 주입으로 구현 완료 —
api_benefits.py:1149 apply_mode='cashback'·base_ratio=0.9. 핀 = test_catalog_source_benefits.py. 네이버페이는 사장님 제외 확정이라 아이몰엔 미주입}확인해 주실 것: ① 카드마다 수집→가공→계산 3단이 위에서 아래로 읽히는지 ② 신뢰 배지(️)만 봐도 프로그램이 뭘 믿어도 되는지 구분되는지 ③ 검산 영수증 숫자가 실측과 같은지 · 미실측() 0건 — 롯데온 N쇼핑도 사장님 확정(제휴할인 자동 반영)으로 해소
핵심셀·매트릭스 보기는 같은 데이터 한 벌(window.DATA) 공유, 로그만 별도 실시간.
데이터 4층
원천·DB표면가 last_price · 재고 current_stock · 혜택 dynamic_benefits_json
계산·fx표면 − 혜택 = final_price · api_benefits.py:496
공유 캐시window.DATA + SM_BREAKDOWNS — /option-matrix 1회 조회
표시셀 · 매트릭스 보기 | 크롤 로그(별도 실시간)
계산·fx표면 − 혜택 = final_price · api_benefits.py:496
공유 캐시window.DATA + SM_BREAKDOWNS — /option-matrix 1회 조회
표시셀 · 매트릭스 보기 | 크롤 로그(별도 실시간)
| 요소 | 위치 | 형태 | 호출 |
|---|---|---|---|
| 셀 | _matrix_v3.html ~5691 | 큰 숫자=최종매입가 + 작게 판매가 + 재고 + fx뱃지 + ★최저 | loadMatrix→window.DATA · fx=후보별 키 |
| 매트릭스 보기 | render() 1269~ | 옵션 × 소싱처 격자 + 상태점() | 같은 window.DATA(추가 호출 없음) |
| 로그 | crawl_log.js · ext_bridge | 진행바 + 소싱처 카드 + 표면가(취소선)·최종매입가(fx) | 별도 실시간 background.js→moum-crawl-log |
완전한 B — 한 소싱처에 URL 여러 개
셀은 그중 최종매입가가 가장 낮은 URL(후보)을 골라 표시. 셀과 계산식은 반드시 같은 후보를 써야 함(fx 단건에 source_product_id 첨부). 안 하면 셀 ≠ 계산식 = 단일 진실원천 위반.
️ 최저 후보가 stale면 실제보다 싼 값 표시 → 폴백가 금지, best는 last_status≠error·재고있음만.
핵심방향 복귀 기준 4가지 + 과거 발생 에러 — 신규 추가·수정 전 먼저 확인.
신규 소싱처 추가·크롤/저장 수정 전, 이 카탈로그부터 확인 — 같은 원인이 다른 소싱처에서 재발합니다. (자세한 분류·원칙·거버넌스는 아래 표와 원문(MD) 참고)
핵심샘플 URL 여러 개로 변형을 덮고, 혜택을 종합해 정답 카드를 만든다 — CLAUDE는 이 순서도만 읽으면 됨.
왜 URL 여러 개? 한 상품엔 그 상품 혜택·재고상태만 보임 → 변형을 덮는 3~6개를 받아 종합해야 전체 혜택 카탈로그 + 재고 3상태가 완성됨.
| 혜택 변형 | 세일/쿠폰/후기적립은 상품마다 켜짐꺼짐 → 상시 vs 조건부 + 트리거 키워드 |
| 재고 3상태 | 품절·한정·충분 각 1개 → 한정수량 '재고있음' 둔갑 차단 |
| 옵션 구조 | 단일색·멀티색·딜 → 단일색 파싱·딜 매핑 버그 차단 |
1
샘플 URL 세트 받기사용자
대표 1개 + 3축 변형 2~5개. 적을수록 카탈로그 누락 위험.
2
수집 방식 판정 래더 (성능 우선순위)CLAUDE
URL을 받으면 위 순위부터 적용 가능 여부를 따져 가능한 가장 높은 순위를 채택한다(빠르고 정확한 순).
| 순위 | 방식 | 적용 가능 판단 | 레퍼런스(어느 형) |
|---|---|---|---|
| 1 | 전용 API 직접 호출 | 상세에서 호출되는 내부 JSON 엔드포인트 존재 + 직접 호출 가능 | 무신사·롯데온형 |
| 2 | 내장 구조 JSON 파싱 | 페이지에 __NEXT_DATA__·option_stock_data·uitemObj·itemInvQtyInfo 통째로 존재(API 준함) | 현대H몰·르무통·SSG·롯데아이몰형 |
| 3 | SSR HTML 정규식/셀렉터 | 구조 JSON은 없지만 raw HTML/JS문자열에 값 존재 | SSF형 |
| 4 | 렌더 DOM (확장 navGrab) | 위 셋 불가·JS 렌더 후에만 생김 (최후) | 롯데온 혜택가형 |
전송 방법 — 창을 여는 3가지 방식 : 값이 어디 있느냐에 따라 크롤이 여는 창 수가 다르다.
창 0개 · SW fetch 확장 서비스워커가 탭 없이 직접 원문 fetch(쿠키+host_permissions). 르무통·SSF·현대H몰. 가장 빠르고 조용.
창 1개 · same-origin fetch WAF(Sec-Fetch 차단)로 밖에서 못 부름 → 그 도메인 탭 1개를 열고 그 안에서 same-origin fetch(렌더는 안 함). SSG·롯데아이몰. URL 여러 개여도 탭 1개서 동시 fetch.
창 N개 · 렌더 값이 JS로 그려져야 생김(로그인 혜택 등) → 페이지를 실제로 렌더. 무신사·롯데온. 실패 시 fetch형도 이 렌더로 폴백(자가보호).
창 1개 · same-origin fetch WAF(Sec-Fetch 차단)로 밖에서 못 부름 → 그 도메인 탭 1개를 열고 그 안에서 same-origin fetch(렌더는 안 함). SSG·롯데아이몰. URL 여러 개여도 탭 1개서 동시 fetch.
창 N개 · 렌더 값이 JS로 그려져야 생김(로그인 혜택 등) → 페이지를 실제로 렌더. 무신사·롯데온. 실패 시 fetch형도 이 렌더로 폴백(자가보호).
가로 게이트(어느 순위든 적용): 방화벽·게이트웨이(현대H몰 API 차단)·CORS → 한 단계 내림 / WAF·봇차단(SSG·롯데아이몰) → 도메인 탭 same-origin fetch(창 1개)로 통과, 안 되면 렌더 창 폴백 / 로그인은 혜택만 → 혜택만 확장 / 정량 비공개(무신사 정상재고·SSF 일반재고) → 999가 정답(가짜 숫자 금지) / 수집 실패·파싱 실패 → 999 아닌 확인불가(오버셀 방지).
3
항목별 위치 추출 (재고 3단계 규칙 포함)CLAUDE
→ 2 재고 + 3 가격
4
혜택 종합 — 여러 URL 교차분석신설CLAUDE
→ 3 가격 · 모든 URL=상시 / 일부=조건부 + 트리거
5
매입가 순차차감 로직CLAUDE
→ 3 가격 · 표면 − Σ혜택 (직전 잔액 기준)
6
검증 크롤·대조 → 정답 카드 저장CLAUDE
→ 5 에러이력 + 18항목 체크리스트 · crawl_guide
7
파이프라인 배선 — 등록 안 하면 화면에 아무것도 안 뜸신설CLAUDE
0단계 경로 정하기: 비로그인 HTML·내장 JSON으로 충분 → 경로 A 서버파싱(navGrab) / 로그인 회원가·SKU재고·렌더 후 값 → 경로 B 확장추출(navExtract). 경로 B는 EXTRACTORS 등록 필수(없으면 crawlOne이 "레시피 없음"으로 건너뜀).
백엔드 9지점 (origin/main 기준 라인 · 표류 시 심볼로 대조)
| # | 무엇 | 파일:함수 | 안 하면 생기는 증상 |
|---|---|---|---|
| B1 | 크롤러 클래스(fetch→CrawlResult) | crawlers/<소싱처>.py (계약 base.py:78·:23) | 읽을 수단 자체가 없음 |
| B2 | 크롤러 등록 dict | crawlers/__init__.py:21 build_crawlers() | 크롤러 만들어도 시스템이 못 부름 |
| B3 | 소싱처 레지스트리(라벨·로고·키) | source_registry.py:15 SOURCES | 드롭다운·소싱처 카드에 안 보임 |
| B4 | URL→소싱처 판정 | api_pricing.py:1620 _detect_site_from_url | 재크롤·자동크롤이 도메인 못 알아봄 |
| B5 | URL 저장 후 자동크롤 크롤러 선택 | api_pricing.py:1264 _auto_crawl_after_url_save | URL 붙여도 자동크롤 안 됨 |
| B6 | 동적혜택 키 화이트리스트 | service.py:631 PRODUCT_DYNAMIC_KEYS | 혜택 값이 DB에 저장 안 됨 |
| B7 | 혜택 source_id↔site 매핑 | source_ids.py site_key / _SITE_BY_PRICING_ID | 혜택 다 짜도 계산식에 영영 안 뜸(최빈 누락) |
| B8 | 소싱처별 혜택 차감 블록 | api_benefits.py:496 compute_breakdown | 혜택이 매입가에서 안 빠짐 |
| B9 | 재고 센티넬 분기(필요 시) | api_pricing.py:196 _resolve_stock | 특수 상한값이 '재고있음' 둔갑 |
확장 4지점 (심볼 기준 · 확장 v0.7.x churn 잦음)
️ 실제 확장 = 데스크톱 로드본(v0.7.6) · repo extension/(v0.4.3) 구버전 — 심볼 기준 인용
| # | 무엇 | 파일:심볼 | 비고 |
|---|---|---|---|
| E1 | 도메인 권한 | manifest.json:7 host_permissions | 두 경로 모두 필수(없으면 접근 차단) |
| E2 | 추출기 등록 | background.js:76 EXTRACTORS | 경로 B만 · 없으면 crawlOne(:92) 건너뜀 |
| E3 | 추출 함수 작성 | background.js (무신사·롯데온 모방) | 반환 price·stock·options·product_name(+benefit_lines) |
| E4 | 크롤 진입점 | ext_bridge.js enqueueCrawl → crawl.enqueue(확장 큐러너) | crawlBundle은 구버전 · 새 소싱처는 등록URL 포함시 자동순회 |
표시 배선 2지점 (크롤·계산은 돼도 화면에 안 보이는 누락 차단)
| # | 무엇 | 파일:심볼 | 안 하면 생기는 증상 |
|---|---|---|---|
| D1 | 전체크롤 위젯 라벨·순서 | crawl_log.js orderedUrlCards · SOURCE_LABELS | (2026-06-28) 커스텀 소싱처(현대H몰·롯데아이몰) 진행카드·완료/성공/실패 합 누락 수정 — orderedUrlCards가 b.sources 의 커스텀 베이스도 순회 + SOURCE_LABELS에 한글 추가(확장 재로드 불필요, 페이지측 JS) |
| D2 | 매트릭스 소싱처 색상 | _matrix_v3.html:1198~ 색상맵 | 새 소싱처 기본 파랑(#5b8def) 표시(폴백 있어 경미) |
라이브 자가검증 6종 (하나 빠지면 역추적): ①소싱처 드롭다운 뜨나→B3 / ②URL 붙이면 자동크롤 도나→B4·B5(+E1·E2) / ③셀에 표면가→크롤러·영속(B1)/E2 / ④계산식에 혜택→B6→B7→B8(DB엔 저장됐는데 안 뜨면 B7)·라이브갱신은 E4 / ⑤재고 3상태→크롤러 정규식·B9 / ⑥전체크롤 위젯에 진행카드 뜨나→D1·색 기본파랑이면 D2. dev DB는 stale 주의 → 라이브 대조 필수.
핵심크롤 코드가 바뀌면 이 가이드(원문·보기)도 같이 바뀌어야 한다 — 어긋나면 잘못된 설명서.
동기화가 필요한 2가지
| A 크롤방식 업데이트 | 크롤 로직·확장이 바뀜 (예: 전체크롤 확장 버전 업) |
| B 신규 소싱처 추가 | 새 소싱처 행·카드를 §1·§2·§6·§7 에 추가 |
0
요청·결정사용자
"소싱처 추가" / "크롤 방식 변경"
1
크롤 코드 변경CLAUDE
크롤러·배선(B/D)·확장 방식
2
가이드 원문+보기 둘 다 갱신CLAUDE
같은 작업에서 §1·§2·§6·§7 을 .md + map.html 양쪽
3
origin/main 배포CLAUDE
4
자동 검사 → 배너적용 완료MOU-M
데이터지도 열릴 때 소싱처 누락·확장버전·심볼 검사 → 어긋나면 상단 배너 / 0이면 조용함
5
배너 0 확인CLAUDE
배포 직후 스스로 확인 — 빨강이면 2로 복귀
6
육안 확인(장기 안전망)사용자
평소 데이터지도 보다 배너 뜨면 인지
자동 vs 절차: 소싱처 누락·확장버전·심볼변경 = 자동 감지 / 순수 로직만 조용히 바뀜(버전·심볼 그대로) = 절차(코드 고칠 때 가이드도 같이).
현재 상태: 4·5의 자동 배너 적용 완료 — 데이터지도 상단에 소싱처 누락(P1)·심볼 사라짐(C2)·확장 버전 불일치(C1) 자동 표시. 순수 로직 변경은 여전히 절차로.
[2026-07-08] 재고 게이트 로직 = A 트랙 동기화 대상 — 재고 판정 우선순위(⓪수집성공→확인불가 / ①옵션존재→②품절→③한정→④충분)·파싱/수집 실패 → 999 아닌 확인불가(-1)·충분 신호 종류(실수량/상한/추론)는 순수 로직이라 자동 감지 밖 → 코드(ssg.py·musinsa.py·api_pricing.py) 바뀌면 §2 재고 탭·.md 를 같은 작업에서 갱신한다.
핵심빈칸을 다 채우면 그 소싱처는 개발이 끝난 것. 자동으로 아는 건 「크롤러가 있나」 하나뿐 — 나머지는 손보정이다.
불러오는 중…
소싱처
소싱처별 상세 · 뒤 지도를 보면서 고칩니다
1
예시 주소 · 계산 결과
주소마다 「크롤」 → 우리가 계산한 값
불러오는 중…
2
수집 구조6항목 + 주소·구분자
불러오는 중…
3
혜택 · 최종 매입가
불러오는 중…
4
재고 규칙
불러오는 중…