puppeteer prerender에서 차단해야 할 도메인 네 개
prerender 파이프라인에 한 줄을 추가한 이야기입니다.
SPA 사이트들을 정적 HTML 로 굳히기 위해 빌드 단계에서 puppeteer 로 페이지를 한 번 렌더링합니다. 그 결과 DOM 을 그대로 dist 에 떨궈두면, 검색 엔진이 자바스크립트 실행 없이도 본문을 읽을 수 있는 형태가 됩니다.
여기까지는 표준적인 흐름입니다.
문제는 그 한 번의 렌더링 시점에, 페이지가 외부 스크립트들을 그대로 불러온다는 점입니다. 광고 코드, 분석 코드, 그 외 외부 네트워크가 의존하는 하위 스크립트들. puppeteer 는 막지 않는 한 모두 통과시키고, 결과적으로 빌드 시점의 외부 URL 이 dist HTML 에 굳어 들어갑니다. 빌드 시점에 유효했던 URL 은 시간이 지나면 종종 사라집니다. 그래서 404 가 됩니다.
prerender 단계에서 차단해야 하는 도메인은 네 개입니다.
googlesyndication.com, googleads.g.doubleclick.net, googletagmanager.com, google-analytics.com.
puppeteer 쪽 구현은 한 블록입니다. page.setRequestInterception(true) 를 켜둔 다음, request 이벤트에서 요청 URL 의 hostname 이 위 네 도메인 중 하나에 매칭되면 request.abort(), 나머지는 request.continue(). 이 한 블록이 들어가면 dist HTML 에 외부 광고·분석 스크립트가 들어가지 않습니다.
사용자 브라우저가 페이지를 직접 열 때는 이 도메인들이 정상 호출됩니다. prerender 시점에만 차단되니까요. 런타임에 광고가 보이지 않을 일은 없습니다.
차단 목록은 더 늘릴 수도 있습니다. 일단 위 네 개로 시작하는 이유는 — 광고·분석 네트워크가 가장 자주 내부 경로를 갱신하기 때문입니다. 다른 외부 스크립트는 빌드 시점에 굳혀도 한참 동안 유효한 경우가 많습니다.
원칙 한 줄로 풀어두면 이렇습니다. prerender 시점에 호출되는 외부 도메인은 기본 차단, 필요한 도메인만 화이트리스트로 풀기. 처음부터 이렇게 잡아두는 편이 안전합니다.
이 패턴을 처음부터 적용했다면 사고 한 건이 없었을 텐데, 처음 빌드 스크립트를 짤 때는 prerender 가 외부 스크립트까지 굳혀 넣는다는 점을 깊게 인식하지 않았습니다. 정상 작동하던 시기가 길었고, 누적된 사이트가 100 개를 넘기면서 같은 파이프라인 위에서 한 번의 사고가 동시에 퍼졌습니다.
빌드 시점과 런타임 시점은 같은 페이지를 보더라도 다른 환경입니다. 그 차이를 처음부터 명시적으로 분리해두지 않으면 한쪽 동작이 다른 쪽으로 새어 들어옵니다. 차단 도메인 네 개는 그 분리를 강제하는 가장 단순한 장치에 가깝습니다.
