들어가며: 데이터가 넘쳐도 답을 찾지 못하는 역설

Cloudflare는 초당 10억 개 이상의 이벤트를 처리하는 글로벌 네트워크를 운영합니다. 하지만 몇 년 전만 해도 내부 분석가가 "오늘 가입한 도메인 중 트래픽 Top 100에 드는 도메인이 몇 개인가?"라는 질문에 답하려면, Postgres, ClickHouse, BigQuery, R2, Kafka 등 수많은 시스템을 오가며 각각의 자격 증명과 쿼리 언어를 익혀야 했습니다. 데이터는 넘쳐나는데, 정작 필요한 데이터를 찾는 것은 극도로 어려운 상황이었죠.

이 문제를 해결하기 위해 Cloudflare는 두 가지 내부 도구를 직접 만들었습니다. Town Lake(통합 데이터 분석 플랫폼)와 Skipper(그 위에서 동작하는 AI 데이터 에이전트)입니다. 이 글은 그 구축 과정에서 얻은 인사이트를 공유합니다. 특히 데이터 플랫폼을 설계할 때 고려해야 할 거버넌스, 확장성, AI 활용 전략에 초점을 맞춥니다.

Data lakehouse architecture diagram with query engine and metadata catalog Coding Session Visual

Town Lake: 데이터 레이크하우스의 실전 설계

Town Lake의 핵심 아키텍처는 데이터 레이크하우스입니다. 객체 스토리지(R2)에 데이터를 저장하고, 그 위에 메타데이터 레이어를 얹어 데이터베이스처럼 동작하게 만드는 구조입니다.

주요 컴포넌트

  • 쿼리 엔진 (Apache Trino): 단일 SQL 쿼리로 Postgres, ClickHouse, R2의 Iceberg 테이블을 조인할 수 있습니다.
  • R2 Data Catalog (Iceberg): 스키마 진화, 타임 트래블, 파티션 관리 등 데이터 레이크의 핵심 기능을 제공합니다.
  • DataHub: 메타데이터 카탈로그로, 모든 테이블/컬럼/소유자/라인리지 정보를 관리합니다.
  • Lifeguard: 접근 제어 서비스로, D1에 규칙을 저장하고 사용자 그룹 정보를 동적으로 반영합니다.
  • Skimmer: PII 탐지 스캐너로, Workers AI를 활용해 컬럼별 민감 정보를 자동 분류합니다.
  • Transformer: Workflows 기반 ELT 엔진으로, SQL 변환 DAG를 정의하고 실행합니다.
-- 예시: 단일 쿼리로 여러 소스 조인
SELECT
  c.customer_name,
  SUM(b.billed_amount) AS total_revenue
FROM fct.billings_allocated b
JOIN dim.accounts a ON b.account_id = a.account_id
JOIN dim.customers c ON a.customer_id = c.customer_id
WHERE b.billing_period = '2024-Q4'
GROUP BY c.customer_name
ORDER BY total_revenue DESC
LIMIT 100;

이 구조의 장점은 데이터를 이동하지 않고도 여러 시스템을 하나로 묶을 수 있다는 점입니다. 특히 쿼리 푸시다운을 통해 ClickHouse에 필터를 위임하고, Postgres의 차원 테이블과 조인하며, R2의 빌링 롤업을 랭킹하는 등 복잡한 작업을 단일 쿼리로 처리합니다.

Cloudflare Town Lake platform dashboard showing query metrics Development Concept Image

Skipper: 자연어로 데이터를 묻는 AI 에이전트

Skipper는 자연어 질문을 받아 올바른 테이블을 찾고, SQL을 작성하고, 결과를 검증하는 AI 에이전트입니다. 핵심은 다층적 컨텍스트를 제공하는 것입니다.

  1. 스키마 및 사용 메타데이터: DataHub가 모든 컬럼/타입/조인 관계를 제공합니다.
  2. 인간 주석: 테이블 소유자가 작성한 설명을 컨텍스트로 활용합니다.
  3. 코드 유래 지식: 테이블을 생성하는 SQL 파이프라인의 .meta.json 문서를 자동으로 등록합니다.
  4. 큐레이션된 데이터 모델: 소수의 휴먼 작성 문서로 에이전트의 우선순위를 안내합니다.
  5. 런타임 인트로스펙션: 필요시 DESCRIBESELECT DISTINCT 같은 쿼리를 직접 실행해 검증합니다.

Code Mode: MCP 서버의 새로운 패턴

Skipper의 MCP 서버는 30여 개의 개별 도구를 노출하는 대신, searchexecute 두 가지만 노출합니다. 모델은 JavaScript 스니펫을 작성해 전체 도구 세트를 프로그래밍 방식으로 호출합니다.

// 예시: MCP Code Mode에서 여러 단계를 한 번에 실행
const datasets = await skipper.search_datasets({ query: "billing product revenue" });
const queryId = await skipper.start_query({ sql: "SELECT ..." });
const results = await skipper.fetch_results({ queryId, mode: "inject" });
return skipper.create_chart({ chartType: "bar", data: results.rows, ... });

이 방식은 모델이 복잡한 워크플로우를 단일 왕복으로 표현할 수 있게 해주며, 감사 가능한 코드로 기록됩니다.

AI agent Skipper interface with natural language query and results chart Algorithm Concept Visual

한국 개발 생태계에서의 적용 맥락

국내 기업에서도 데이터 플랫폼 구축은 비슷한 어려움을 겪습니다. 특히 금융권이나 커머스에서는 개인정보보호법 등 규제로 인해 PII 관리가 더욱 중요합니다. Town Lake의 default-closed 방식, 즉 테이블이 검토되기 전에는 접근을 차단하는 정책은 국내 규제 환경에 잘 맞는 접근법입니다. 다만, 초기 구축 시 리뷰 병목이 생길 수 있으므로 자동화된 PII 분류기와 같은 도구를 도입하는 것이 필수적입니다.

주의사항 및 한계

  • 초기 구축 비용: Trino, Iceberg, DataHub 등 여러 오픈소스 컴포넌트를 조합해야 하므로 운영 복잡도가 높습니다.
  • 메모리 레이어의 중요성: 에이전트가 반복적인 실수를 줄이기 위해서는 장기 메모리(예: D1)가 필수입니다.
  • 보안은 설계의 일부: 접근 제어와 감사 로깅을 후순위로 미루면 결국 데이터 플랫폼 전체의 신뢰도가 떨어집니다.

다음 단계 학습 방향

  • Apache Iceberg와 Trino의 심화 활용법을 익혀보세요.
  • MCP 서버와 Code Mode 패턴을 직접 구현해보며 에이전트 개발 경험을 쌓아보세요.
  • 데이터 거버넌스 프레임워크(예: DataHub)를 실제 프로젝트에 적용해보는 것을 추천합니다.

결론

Cloudflare의 사례는 단순히 기술적 성공담이 아니라, 데이터 문화를 바꾸는 여정입니다. 데이터 플랫폼을 '백오피스'로 취급하지 않고 핵심 인프라로 승격시킨 점이 가장 큰 교훈입니다. 여러분의 조직에서도 데이터를 하나의 창구로 통합하고, AI 에이전트를 통해 접근성을 높이는 시도를 해보시길 권합니다. 더 자세한 내용은 Cloudflare 블로그 원문을 참고하세요.

함께 보면 좋은 글

본 콘텐츠는 신뢰할 수 있는 출처를 바탕으로 AI 도구를 활용하여 초안이 작성되었으며, 편집자의 검토를 거쳐 발행되었습니다. 전문가의 조언을 대체하지 않습니다.