Skip to content
isdnetworks
Go back

목록에 섞여 있던 내부 API

(수정됨)

수집 대상 사이트가 무한 스크롤이라 목록을 다 가져오려면 계속 스크롤을 해야 했다. 그래서 Playwright 로 브라우저를 띄우는 수밖에 없다고 보고 그 전제로 설계를 시작했다.

Table of contents

Open Table of contents

배경 — 직렬화라는 최대 제약

브라우저로 수집할 때의 가장 큰 문제는 직렬화였다. 한 세션에서 한 페이지씩 열어야 하므로 여러 대상을 동시에 처리할 수가 없다.

대상과 분류를 곱하면 조합이 열여덟 개인데 그것을 전부 하나씩 순서대로 해야 했다. 이 직렬화가 이 설계에서 가장 큰 제약이었다.

검증 — 관찰이 찾은 내부 API

설계 전에 두 가지 방법이 있었는데 무한 스크롤이니 브라우저 필수라고 두고 바로 짜는 것과 브라우저를 띄우고 실제로 스크롤을 유발하면서 DevTools 의 Network 탭으로 나가는 요청을 관찰하는 것이다. 뒤쪽을 골랐다. 이유는 화면이 갱신되는 이상 어딘가에서 데이터를 받아 오는 요청이 반드시 있어서다. 대신 설계 착수가 하루 늦어지는 것을 감수했다. 화면의 항목이 20건씩 늘어날 때마다 /api/list 를 부르고 있는 것이 보였다.

channel 과 category 와 last_id 를 넘기는 커서 페이지네이션이었다. 페이지만 열었으면 초기 요청만 보였을 것이므로 동작을 유발한 것이 이 발견의 조건이었다.

조치 — 봉투 안의 조각

그 응답을 열어 보니 {"html": "..."} 봉투 안에 HTML 조각이 들어 있는 형태였다. 순수 JSON 은 아니지만 봉투를 벗기고 안의 조각을 DOMDocument 로 파싱하면 되는 구조였다.

이것으로 목록 수집을 브라우저 없이 Guzzle 요청만으로 할 수 있게 됐다. 브라우저 세션 하나로 열여덟 조합을 직렬 처리하던 것이 Pool 로 요청 열여덟 개를 병렬로 보내는 것이 됐고 브라우저는 쿠키 공급원으로만 남았다.

원인 — 같이 나온 부가 API

같은 관찰에서 /api/access 권한 조회와 /api/comments/count 조회도 함께 나왔다. 그중 앞의 것이 특히 유용했는데 화면에 뜨는 잠금 표시의 실체였기 때문이다.

문서 객체 통계로 판정하던 것을 API로 직접 얻을 수 있게 됐다. 관찰 한 번에서 목록 수집과 잠금 판정 둘 다 나온 셈이다.

주의 — 성격이 다른 문서

수집하는 중에 한 대상의 글이 성격이 다르다는 것을 발견했다. 일반 글이 항목 하나에 8천 자 정도인데 그 대상은 항목이 열셋에 3만 자가 넘고 표가 여럿이었다.

한 항목이 한 요약이라는 파이프라인에 안 맞으므로 별도 처리 경로가 필요하다고 적었다. 표를 단순 텍스트로 뽑으면 행과 열이 뭉개지므로 구조를 살려 변환해야 하고 매 글에 반복되는 면책 조항과 채널 소개는 요약 입력에서 빼야 한다. 관찰 한 번이 브라우저를 띄워야 한다는 제약을 없애면서 아키텍처를 바꿨다.

정리


Share this post on:

Previous Post
무한 반복이 된 자동 재시작
Next Post
이미지 하나에 서빙 경로 셋