사이트 운영자는 bunny.net CDN을 사이트 앞단에 두고 캐시와 크롤러 차단을 엣지로 옮겼다. 기존 Redis 캐시와 실시간 경로를 유지하면서 로딩 속도 개선도 기대하지만, 조건부 요청 헤더가 전달되지 않는 문제 등은 별도로 처리해야 했다.

기존에는 404가 너무 많이 발생한 IP를 차단하는 Go 작업, robots.txt와 연동한 크롤러 차단 목록, SQL 인젝션 탐지 필터를 각각 운영했다. 운영자는 이미지 제공에 이미 사용하던 bunny.net을 사이트에도 적용했다. 새 풀 존에는 www 도메인만 연결하고, 기본 도메인과 관리자 페이지는 원본 서버를 계속 가리키게 했다. 원본 서버는 bunny의 엣지에서 공유 키가 든 헤더를 보낸 요청만 받도록 설정했다. 현재 재생 정보와 문의 양식, 일부 API는 엣지 캐시에서 제외했다.

Go 애플리케이션은 페이지마다 Cache-Control 헤더로 캐시 기간을 설정한다. 기본 기간은 짧게 두고 자주 바뀌지 않는 페이지에는 더 긴 기간을 적용했으며, 예측 가능성을 위해 bunny의 Smart Cache는 사용하지 않았다. 응답에는 CDN-Tag를 붙인다. 관리자 화면에서 내용을 저장하면 몇 초 뒤 해당 태그의 캐시를 비우며, 서버 시작 때도 캐시를 비운다. Redis는 데이터베이스 쿼리를 캐시하고 bunny는 렌더링된 HTML을 엣지에서 캐시하므로, 원본 서버에 도달한 요청은 페이지를 다시 렌더링한다.

봇 차단 규칙은 bunny의 웹 애플리케이션 방화벽(WAF)을 학습 모드로 실행해 조정했다. 운영자는 규칙을 곧바로 차단 모드로 적용하면 영어로 작성한 문의 양식 제출처럼 정상 요청까지 막을 수 있다고 설명한다. CMS에서 관리하는 크롤러 목록은 경로별 사용자 에이전트 문자열로 구성되며, 이 목록을 CDN 규칙과 동기화해 엣지에서도 같은 크롤러를 차단한다. bunny가 제공하는 차단 목록 중에는 Tor와 VPN 이용자까지 막는 항목이 있어, 해당 규칙은 차단 대신 추가 확인을 요구하도록 바꿨다. 이전의 IP 차단 작업과 Caddy의 크롤러 목록은 제거했다. 기존 봇 차단 방식은 관련 글에서 다뤘다.

분석 기능에서는 방문 국가를 확인하던 GeoIP 조회를 bunny가 보내는 국가 헤더로 대체했다. 페이지를 떠날 때가 아니라 페이지가 열릴 때 방문을 기록하도록 바꿨고, 크롤러 방문은 집계에서 제외한다. 원본 서버 앞에 추가 캐시 계층을 두는 Origin Shield도 사용했다. 캐시가 없는 요청을 한곳으로 모아 원본 서버가 받는 요청 수를 줄이며, IPv4만 지원하는 원본 서버에 연결할 수 없는 일부 엣지 위치의 문제도 중간 계층을 통해 해결했다. Origin Shield 안내

적용 과정에서 확인한 제약도 있다. 피드 리더는 변경되지 않은 피드를 다시 내려받지 않도록 If-None-Match를 사용하지만, bunny는 캐시하지 않고 원본으로 전달하는 요청에서도 조건부 요청 헤더를 제거한다. 그 결과 폴링 요청이 모두 200 응답이 되어 운영자는 304 응답을 기준으로 처리할 수 없게 됐다. 또 요청 병합 기능은 거의 동시에 들어온 요청에 같은 결과를 돌려주므로 실시간 경로와 맞지 않아, 해당 경로를 건너뛰도록 목록을 만들었다.

배포 중에는 새 Go 바이너리를 복사하고 앱을 재시작한 뒤 Caddy 설정을 다시 불러올 때까지 방문자에게 잠시 502 오류가 보일 수 있다. 이를 줄이기 위해 Caddy에 짧은 재시도 동작을 추가했다. 엣지 캐시의 오래된 앨범 이미지와 실시간 재생 정보가 함께 표시되며 화면이 깜박이는 문제는 새 이미지를 화면 밖에서 디코딩한 뒤 교체하도록 처리했다.

운영자는 기존보다 사이트가 빨라질 것으로 기대하며, 차단한 봇을 보여주는 분석 차트도 추가했다.