Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ OpinetClient를 native async 하나로 통합했다. 모든 조회·디버그에

## [Unreleased]

- 실험적 브라우저의 기본 off 부수 자원 차단과 안전 정수 단계 계측을 추가했다. HTTP cache 영향과 운영 미검증 한계를 명시했다.

### Fixed
- 지역별 화면 수집에서 한 지역(시군구)의 '조회' 검색 응답이 시간 초과되면 검색 화면을 새로 열고
탭·지역을 다시 고른 뒤 그 지역만 한 번 다시 조회한다(첫 시도의 늦은 응답을 쓰지 않는다). 재시도
Expand Down
74 changes: 74 additions & 0 deletions docs/browser-collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,77 @@ asyncio.run(main())
- 공식 API나 사전 협의된 데이터 제공 경로가 있으면 화면 수집보다 우선한다.
- 수집한 전화번호·사업자번호 등 공개 사업자 정보도 필요한 범위에서만 저장하고
로그에 원문을 남기지 않는다.


## 부수 자원 비용의 선택적 비교

기본 block_visual_resources=False는 route를 설치하지 않는다. True를 명시하면
현재 페이지의 image/font/media 요청만 abort한다. document/script/stylesheet/XHR/fetch
및 알 수 없는 종류는 기존 route로 fallback한다. service worker 정책·탭·지역 선택·
파서/raw/좌표/가격·재시도/검색 상한/pacing은 바꾸지 않는다.
collect_once는 첫 navigation부터, collect_page(page)는 호출 이후 요청에만 적용한다.
이미 로드된 자원은 되돌리지 않는다. 실패·취소 시 자기 handler만 제거하며
호출자 페이지나 기존 route를 닫거나 지우지 않는다.

**운영 개선은 아직 검증하지 않았다.** Playwright 공식
[route 계약](https://playwright.dev/python/docs/api/class-browsercontext#browser-context-route)은
routing 활성화가 HTTP cache를 끈다고 명시한다. 반복 navigation의 JS/CSS 요청은
늘 수 있고 service worker가 처리한 요청은 route를 통과하지 않을 수 있다.
CAPTCHA/접근 거부/401·403·429는 종전처럼 실패한다. 같은 입력에서 실제 출력·
서버 요청 수/CPU/메모리/wall을 검증하기 전 기본값을 바꾸거나 소비자에서 켜지 않는다.

on_metrics=callback은 별도 선택이며 실행당 한 번 읽기 전용 Mapping[str, int]를 받는다.
고정 키32개이며 URL·헤더·본문·지역·주유소·인증값은 없다. callback 일반 예외는
정제된 경고만 남기며 수집 결과나 원래 실패를 바꾸지 않는다. 동기 함수로 짧게 실행한다.

- navigation/discovery/search/wait/parse/close_elapsed_us와 같은 접두사의 count:
실제 경과 마이크로초·호출 수. wait는 의도적 pacing 대기이며 응답/DOM 대기는
discovery/search에 포함된다. 중첩 단계 시간을 합쳐 전체 CPU로 설명하지 않는다.
- total_elapsed_us, success/failed/cancelled: 전체 경과와 종료 상태. collect_once는
Playwright 시작/종료와 context/browser cleanup을 포함하며 Chromium CPU/RSS는 아니다.
- request_count/request_failed_count, 종류별 requests, blocked_resource_count:
브라우저의 요청 시도/실패/차단 수. cache/SW 때문에 서버 전송 수와 다를 수 있다.
- regions/query_regions/stations/region_retries: 완료 snapshot의 개수.
도중 실패한 호출에서 완료 개수를 추정하지 않는다.

계측만 켜면 route/cache 정책은 바뀌지 않는다. 과거 run별 내역을 collector에 쌓지 않으며
ContextVar로 동시 호출을 격리한다. 생산 CPU/RSS 감소나 누수 해결을 주장하지 않는다.


### 로컬 Chromium 비교와 재현

의존성 browser/dev와 Playwright bundled Chromium을 준비한 환경에서 아래 검증을 실행한다.
기본 unit suite는 Playwright 미설치 시 실제 브라우저 fixture를 건너뛴다. 설치했으나
브라우저 binary가 없으면 설치/환경 실패를 숨기지 않고 실패한다. 실제 Opinet에는 접속하지 않는다.

python -m pytest tests/test_browser_resource_fixture.py -q
python tests/benchmark_browser_resources.py --output 비교결과.json

테스트 전용 loopback origin만 허용하는 fixture로 1지역·주유소/LPG 2탭을 읽었다.
세 쌍 각각 다른 Python 프로세스를 사용하고 실행 순서를 off/on, on/off, off/on으로 바꿨다.
수집 시각·임시 origin을 제외한 모든 typed/raw 출력 digest는 여섯 번 모두 같았다.
숫자·가격·좌표 원문, unknown raw 필드, 두 업종 병합, 지역 선택은 보존됐다.
서버가 받은 검색 POST2회/탭 POST1회/문서 GET1회도 동일했다.
별도 실제 fixture는 401/403/429와 HTTP200 CAPTCHA를 추가 검색 없이 실패시켰다.

2026-10-16 Linux x86_64/Python3.12.13/Playwright1.63.0의 단기 fixture 측정이다.
각 칸은 자원 정책 기본 / 차단이며, 양쪽 모두 on_metrics를 켰다. ms와 MiB 단위를 쓴다.

| 쌍 | wall ms | Python+회수 하위 CPU ms | 표본 RSS 합 MiB | 표본 PSS 합 MiB |
| --- | --- | --- | --- | --- |
| 1 | 815.05 / 810.35 | 1017.84 / 1029.65 | 758.57 / 679.16 | 453.59 / 429.33 |
| 2 | 807.48 / 824.36 | 973.47 / 1004.70 | 758.04 / 683.07 | 453.37 / 459.56 |
| 3 | 824.21 / 820.96 | 990.86 / 985.49 | 762.98 / 678.09 | 456.38 / 429.48 |

서버 총 요청은 기본9회/차단10회였다. image/font/media 전송3회는 없어졌지만
JS/CSS 각각1회가3회로 증가했다. 요청 시도/차단 계수와 서버 전송 수를 혼용하지 않는다.
wall은 Playwright 시작과 cleanup을 포함한다. Python CPU에는 자기 fixture 서버와
50ms 메모리 sampler가 포함되며 하위 CPU는 종료 후 회수한 누계다.
RSS는 공유 페이지를 중복 합산한다. PSS도 50ms 표본이므로 실제 peak 상한이 아니며
두 메모리 수치의 peak 시점이 다를 수 있다. sampler와 서버는 이 비교용 도구에만 있다.

CPU·wall 개선은 입증되지 않았고 메모리 표본만으로 운영 개선을 주장하지 않는다.
짧은 단일 fixture·세 쌍·통제되지 않은 호스트 cache/부하이며 장시간·ARM·실제 provider
지역 수와 자원 정책은 검증하지 않았다. 특히 cache 재전송 비용 때문에 실제 수집에서
오히려 느려질 수 있다. 운영 출력·요청량·CPU/PSS/wall 비교와 두 독립 리뷰 전에는
소비자 pin/옵션을 바꾸지 않는다. Transport의 scraper 재구현이나 현재 fuel 중단은 없다.
11 changes: 11 additions & 0 deletions docs/implementation-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,14 @@ VWorld 연동은 비동기 search_district를 사용하며 완료된 지역 코


예제는 [docs/async-tps.md](../docs/async-tps.md)를 참고한다.


## 브라우저 부수 자원 선택과 계측

실험 collector에 기본 off인 block_visual_resources와 독립 on_metrics를 추가했다.
공식 HTTP API·provider 출력/raw·지역/두 탭·재시도/quota/pacing은 유지한다.
고정32 정수 키만 보고하고 URL·원문·식별자를 계측에 넣지 않는다.
실제 loopback Chromium 출력/실패 회귀 및 세 쌍 비용 비교는
[browser-collection.md](browser-collection.md#로컬-chromium-비교와-재현)에 기록했다.
route의 cache 비활성화로 서버 요청이 증가했고 CPU·wall 개선은 입증되지 않았다.
운영 적용/소비자 pin 변경은 아직 하지 않았다.
Loading
Loading