Browser Run: 이제 Cloudflare Containers에서 실행되어 더 빠르고 확장성이 뛰어납니다 (새 탭에서 열림)
Browser Run은 Cloudflare Containers 기반으로 재구축되면서 더 높은 처리량, 낮은 지연 시간, 향상된 안정성을 확보했다. 분당 브라우저 생성 한도는 60개, 동시 실행 수는 120개로 늘어 기존보다 4배 향상됐고, Quick Action 응답 시간은 50% 이상 단축됐다. 이 성능 개선의 핵심은 지역별 사전 준비 컨테이너 풀, D1의 트랜잭션 기반 상태 관리, Queues를 활용한 배치 쓰기다.
Browser Run의 역할
- Cloudflare의 글로벌 네트워크에서 실행되는 헤드리스 브라우저를 프로그래밍 방식으로 제어한다.
- 주요 활용 사례:
- 웹 애플리케이션의 엔드투엔드 테스트
- 의심스러운 URL의 안전한 조사
- PDF 렌더링
- 스크린샷 캡처와 콘텐츠 추출
- AI 에이전트의 웹 브라우징
- 목표는 자동화 브라우저를 안전하고 대규모로 활용할 수 있는 플랫폼이 되는 것이다.
기존 Browser Isolation 인프라의 한계
- 이전에는 Browser Run과 Browser Isolation(BISO)이 인프라를 공유했다.
- BISO의 큰 컨테이너 이미지는 브라우저 시작 시간과 개발 속도를 저하시켰다.
- BISO 브라우저의 글로벌 분산이 충분하지 않아 지연 시간과 복원력에도 문제가 있었다.
- BISO의 장시간·지속적 세션과 Browser Run의 짧고 급격한 트래픽 패턴이 서로 맞지 않아 확장 병목이 발생했다.
점진적인 Containers 마이그레이션
- 요청 경로에 Worker를 추가해 일부 사용자에게만 Container 기반 브라우저를 제공하며 마이그레이션을 시작했다.
- 기존 BISO 브라우저와 병행 운영하면서 성능을 비교하고 구현 오류를 검증했다.
- 적용 순서는 다음과 같았다.
- Quick Actions 엔드포인트
- 무료 계정의 Workers 브라우저 바인딩
- 종량제 계정
- 나머지 계약 고객
- 고객이 별도 설정을 변경하거나 Worker를 재배포하지 않아도 전환되도록 했다.
지역별 사전 준비 컨테이너 풀
- Durable Object(DO)는 요청에 가까운 위치에 생성될 수 있지만, 연결되는 Container는 지구 반대편에 배치될 수 있다.
- 단일 메시지에서는 문제가 작지만, 스크린샷 요청처럼 WebSocket으로 수십 개 메시지를 주고받는 작업에서는 왕복 지연이 누적된다.
- 이를 해결하기 위해:
- 지역별로 DO 기반 브라우저 컨테이너를 미리 실행해 둔다.
- 요청이 들어오면 해당 지역에서 사용자와 가장 가까운 DO-Container 쌍을 선택한다.
- 사용자-DO, DO-Container 양쪽의 네트워크 거리를 줄인다.
- 브라우저별 글로벌 상태를 관찰하고 수요에 따라 용량을 재배치해야 하므로 추가적인 아키텍처 복잡성이 생겼다.
Workers KV의 일관성 문제
- 초기에는 각 컨테이너 상태를 Workers KV에 저장했다.
- KV는 최종적 일관성을 사용하며, 캐시 TTL 때문에 최대 약 30초 또는 그 이상 오래된 상태를 읽을 수 있었다.
- “사용 가능”으로 읽은 컨테이너가 실제 라우팅 시점에는 이미 다른 요청에 할당되는 경쟁 조건이 발생했다.
- 이로 인해:
- 동일 브라우저의 중복 할당
- 과도한 브라우저 예약
- 급격한 수요 증가에 대한 확장 지연 문제가 생겼다.
D1을 이용한 원자적 브라우저 할당
- 컨테이너 상태를 KV에서 D1 데이터베이스로 이전했다.
- D1은 SQLite 기반 트랜잭션을 제공하므로 브라우저 할당을 원자적으로 처리할 수 있다.
- 브라우저는 사용자 간 공유 자원이 아니므로, 한 번 할당되면 독점적으로 사용되어야 한다.
- 후보 컨테이너를 선택하고 상태를
picked로 변경하는 작업을 하나의 트랜잭션으로 수행해 동시에 두 요청이 같은 브라우저를 차지하는 문제를 방지한다. - 지역별로 D1 샤드를 구성해 위치 기반 컨테이너 관리도 유지했다.
Queues를 활용한 상태 업데이트 배치 처리
- 수천 개 컨테이너가 5초마다 상태를 갱신하면 데이터베이스 쓰기 부하가 커진다.
- 개별 쓰기만 사용하면 초당 약 1,000회 쓰기라는 한계로 인해 지역당 약 5,000개 컨테이너 수준에서 병목이 발생할 수 있다.
- 상태 업데이트를 Queues에 모은 뒤 100개 단위로 배치 처리했다.
- 배치 쓰기는 개별 쓰기보다 처리 시간이 크게 늘지 않으므로 처리량을 크게 높일 수 있다.
- 100개 단위 배치 기준으로 지역당 최대 약 500,000개 컨테이너까지 업데이트할 수 있는 여유를 확보했다.
- 각 컨테이너는 5초마다 자신의 상태를 지역별 큐에 기록한다.
- 큐 소비자는 다음과 같이 설정했다.
- 최대 배치 크기: 100개
- 최대 배치 대기 시간: 1초
- 최대 재시도 횟수: 1회
- 배치 쓰기의 현재 P95 지연 시간은 0.1ms다.
성능 개선 결과
- Workers 바인딩을 통한 브라우저 생성량:
- 분당 최대 60개
- 동시 실행 브라우저:
- 최대 120개
- 이전보다 4배 증가
- Quick Action 응답 시간:
- 50% 이상 단축
- 개선 사항은 기존 고객의 코드 변경이나 Worker 재배포 없이 즉시 적용됐다.
Cloudflare의 사례는 짧고 급격한 트래픽을 처리하는 시스템에서 최종적 일관성 저장소를 핵심 할당 경로에 사용할 때 발생할 수 있는 문제를 보여준다. 실시간 자원 예약에는 트랜잭션 기반 DB를 사용하고, 빈번한 상태 갱신은 큐와 배치 쓰기로 분리하는 설계가 효과적인 접근이다.