유튜브 채널 1억 개 규모의 분석 서비스는 일반적인 웹 서비스 설계 상식이 거의 통하지 않는다. 쇼핑몰이나 SNS는 사용자 수에 비례해 데이터가 늘지만, 유튜브 분석기는 사용자가 0명이어도 시간에 비례해 데이터가 계속 누적된다. 게다가 워크로드가 OLTP, OLAP, 풀텍스트 검색, 벡터 검색, 콜드 아카이브 다섯 가지로 본질적으로 다르기 때문에 단일 DB로는 어느 한쪽이 반드시 깨진다.
이 문서는 한 운영 사례(추정치)를 기반으로, 채널 100만에서 1억까지 확장 가능한 인프라를 4계층으로 분리해 설계하는 방법을 정리한다. 각 계층에서 왜 특정 기술이 선택되는지, 어떤 대안이 왜 부적합한지, 그리고 단계별로 어떻게 마이그레이션할지를 함께 다룬다.
핵심 메시지는 분명하다. 데이터 종류별로 워크로드에 최적화된 저장소를 분리하는 Polyglot Persistence가 1억 채널 규모에서는 선택이 아닌 강제 조건이며, Supabase·Turso 같은 단일 솔루션은 1천만 채널 이하에서만 유효하다는 점이다.
1. 워크로드 특성과 단일 DB의 한계
유튜브 분석기와 일반 SaaS의 워크로드 차이는 다음 표로 정리된다.
| 워크로드 | 일반 SaaS | 유튜브 분석기 |
|---|---|---|
| 읽기:쓰기 비율 | 8:2 | 3:7 (지속적 수집) |
| 동시 연결 | 사용자 수 비례 | 워커 + 사용자 (수집 부하 지배적) |
| 쿼리 패턴 | 단순 CRUD | 시계열 집계 + 풀텍스트 + 벡터 혼재 |
| 데이터 증가율 | 사용자 비례 | 시간 비례 |
| 핫/콜드 비율 | 9:1 | 1:9 (최근 1개월만 핫) |
1.1. 데이터 종류별 접근 패턴
- 채널 메타데이터는 채널 ID 단건 조회가 90%이고 갱신은 주 1회 수준이라 OLTP DB가 최적이다.
- 트렌딩 시계열은 한 번 쓰면 거의 수정되지 않고 항상 GROUP BY 집계로 읽히며 행 수가 수십억으로 폭증해 컬럼형 OLAP DB가 필수다.
- 영상 카탈로그는 대부분 한 번 쓰고 거의 안 읽히는 콜드 데이터라 객체 스토리지에 Parquet으로 두는 것이 비용 효율적이다.
- 검색 인덱스는 풀텍스트 역인덱스가 필요하며 1억 행 규모에서는 전용 검색엔진이 압도적이다.
- 벡터 임베딩은 1536차원 코사인 유사도 검색이 필요해 HNSW 그래프 인덱스가 필수다.
1.2. 단일 DB로 모두 처리할 때의 문제
모든 데이터를 Postgres 하나에 넣으면 세 가지 문제가 동시에 터진다. 첫째, 트렌딩 집계 쿼리가 OLTP 트랜잭션을 블록해 수집 워커의 INSERT가 느려진다. 둘째, 검색용 GIN·시계열용 BRIN·벡터용 HNSW가 한 테이블에 걸리며 인덱스가 데이터의 3~5배로 폭증해 디스크 IO가 마비된다. 셋째, 5TB Postgres는 pg_dump에 12시간 이상 걸리고 복제 lag이 심해 HA 구성이 비현실적이다.
핵심 포인트: 1억 채널 규모에서 Polyglot Persistence는 선호가 아니라 강제 조건이다. 데이터 종류별로 최적 저장소를 분리하지 않으면 어느 한쪽 워크로드가 반드시 다른 쪽을 무너뜨린다.
2. 4계층 분리 아키텍처
전체 구조는 Edge·Origin API·데이터 저장소·수집 파이프라인 네 계층으로 분리된다.
2.1. 계층별 역할
- Layer 0 Edge & CDN은 Cloudflare Pages와 Workers로 구성되며 정적 자산 전송, 인증 검증, 캐시, Rate Limiting을 엣지에서 처리해 origin 부하를 80% 이상 감소시킨다.
- Layer 1 Origin API는 Go 백엔드 4노드 HA 구성으로 비즈니스 로직과 쿼리 라우팅을 담당하며, 프론트엔드가 4개의 DB를 직접 알 필요가 없도록 추상화한다.
- Layer 2 Data Stores는 Postgres+Citus, ClickHouse, MeiliSearch, Qdrant, R2 다섯 가지 저장소로 워크로드를 분산한다.
- Layer 3 Ingestion은 NATS JetStream 큐와 Go 워커 20개, Python 배치 ETL로 수집과 API를 완전히 분리한다.
2.2. 계층 분리의 핵심 효과
수집과 API를 분리하면 YouTube API 폴링이 폭증해도 사용자 페이지가 느려지지 않는다. 메시지 큐를 두면 워커가 5분 죽었다 살아나도 작업이 보존되며, 부하 분산이 자동으로 이루어진다.
3. OLTP 레이어 — Postgres + Citus
3.1. 왜 Postgres인가
- 풀텍스트(tsvector), JSON 인덱싱(GIN), 벡터(pgvector), 시계열(TimescaleDB), 분산(Citus)이 모두 확장으로 통합돼 단일 DB로 가장 많은 워크로드를 처리할 수 있다.
- MVCC 구현이 우수해 24시간 INSERT 환경에서도 읽기 성능 저하가 적다.
- Citus 확장으로 Postgres SQL 호환성을 99% 유지하며 자동 샤딩이 가능하다.
3.2. Supabase·Turso와의 비교
| 솔루션 | 적정 규모 | 1억 채널 적합성 | 한계 |
|---|---|---|---|
| Supabase (single-node) | 1천만 채널 이하 | 부적합 | 100GB~1TB 한계, VACUUM 며칠 |
| Turso (libSQL) | DB-per-tenant 모델 | 부적합 | SQLite 동시 쓰기 직렬화 |
| Postgres + Citus | 1억+ 채널 | 최적 | 운영 복잡도 중간 |
3.3. Citus 샤딩 전략 핵심
채널 ID 해시로 32샤드 분산하고, 영상 테이블을 같은 채널 ID 키로 co-located 배치하면 "특정 채널의 영상 목록"이라는 가장 흔한 쿼리가 단일 노드에서 끝난다. 사용자 즐겨찾기는 user_id로 분산하고, 국가·카테고리 같은 작은 테이블은 reference table로 모든 노드에 복제한다.
co-location 없이 분산하면 모든 쿼리가 모든 노드를 거쳐 latency가 10배 증가한다. 이 설계 결정이 분산 DB 성능을 좌우한다.
4. OLAP 레이어 — ClickHouse
4.1. 왜 ClickHouse인가
트렌딩 분석은 본질적으로 "수십억 행 GROUP BY 집계"다. ClickHouse는 이를 위해 설계됐다.
- 컬럼형 저장으로 필요한 컬럼만 디스크에서 읽어 IO가 1/10로 준다.
- 압축률 10~30배로 1TB 데이터가 50~100GB로 줄어든다.
- 벡터화 실행으로 같은 GROUP BY가 Postgres 30초, ClickHouse 0.3초다.
4.2. TimescaleDB와의 비교
| 항목 | TimescaleDB | ClickHouse |
|---|---|---|
| 압축률 | 3~5배 | 10~30배 |
| GROUP BY 속도 | 기준 | 5~20배 빠름 |
| 1TB+ 메모리 사용 | 폭증 | 안정 |
| 운영 복잡도 | 낮음(Postgres 확장) | 중간 |
TimescaleDB는 Postgres 안에서 가벼운 시계열을 처리할 때 강점이며, 수십억 행 본격 분석이 핵심이면 ClickHouse가 정답이다.
4.3. 테이블 설계 핵심
MergeTree 엔진에 event_date 월별 파티션, ORDER BY (event_date, country, category, rank)로 정렬키를 잡으면 "한국 게임 카테고리 지난주 트렌딩" 쿼리가 1ms 안에 위치 탐색을 끝낸다. TTL로 2년 후 콜드 볼륨 이전, 5년 후 자동 삭제를 걸어 핫 노드 용량을 일정하게 유지한다.
5. 콜드 아카이브 — R2 + Parquet + DuckDB
5.1. 비용 비교
| 저장소 | GB당 월 비용 | 10TB 월 비용 |
|---|---|---|
| NVMe SSD | 약 $0.10 | $1,000 |
| AWS S3 | 약 $0.023 + egress | $230 + 트래픽 |
| Cloudflare R2 | 약 $0.015 + egress 0 | $150 |
R2의 결정적 장점은 egress fee가 0이라는 점이다. 분석 쿼리가 가끔 콜드 데이터를 조회해도 비용 폭탄이 없다.
5.2. Parquet과 DuckDB의 역할
- Parquet은 컬럼형 파일 포맷으로 JSON·CSV 대비 10배 작고 부분 쿼리가 빠르다.
- DuckDB는 in-process OLAP DB로 별도 서버 없이 라이브러리처럼 임베드해 R2의 Parquet을 직접 쿼리한다.
- 콜드 데이터를 ClickHouse로 재로드할 필요가 없어 "3년 전 데이터 한 번만 보고 싶다"는 분석가 요청을 즉석에서 처리할 수 있다.
6. 검색·벡터·큐·캐시 레이어
6.1. MeiliSearch — 검색 전용
1억 행에 Postgres LIKE 쿼리는 풀스캔이라 불가능하고, 한국어 형태소 분석도 안 된다. 검색 전용 엔진은 역인덱스와 형태소 분석으로 다중 키워드 필터, 오타 교정, 자동완성, 패싯 필터링을 지원한다.
| 항목 | MeiliSearch | Typesense | Elasticsearch |
|---|---|---|---|
| 메모리 | 적음(Rust) | 중간(C++) | 많음(JVM 32GB+) |
| 설정 복잡도 | 매우 낮음 | 낮음 | 높음 |
| 분산/샤딩 | 약함 | 중간 | 강력 |
| 한국어 지원 | 양호(lindera) | 양호 | 최고(Nori) |
| 권장 규모 | ~1억 문서 | ~5천만 | 무제한 |
1억 채널 규모에서는 MeiliSearch가 비용·운영 면에서 최적이다.
6.2. Qdrant — 벡터 검색
pgvector는 1천만 벡터 이하에서는 가장 합리적이지만, 1억 벡터에서는 HNSW 인덱스 메모리가 600GB까지 폭증한다. Qdrant는 양자화(Scalar/Binary)로 메모리를 1/4~1/32로 줄이고, 디스크 기반 HNSW로 메모리에 다 안 올려도 동작한다.
6.3. NATS JetStream — 메시지 큐
Kafka는 ZooKeeper, 브로커, 스키마 레지스트리 등 최소 3종 컴포넌트가 필요해 운영 부담이 크다. NATS는 단일 20MB 바이너리로 Kafka의 95% 기능을 제공하고 초당 200만 메시지까지 검증됐다. Redis Streams는 메모리 기반이라 큐 적체 시 OOM 위험이 있으므로 NATS가 안전하다.
6.4. Redis 또는 Dragonfly — 캐시
"지난 24시간 인기 채널 TOP 100" 쿼리를 매번 ClickHouse로 돌리면 1초씩 걸리지만, 5분 캐시면 1ms로 응답한다. Dragonfly는 Redis 호환이면서 멀티스레드 아키텍처로 동일 하드웨어에서 25배 처리량을 낸다.
7. 백엔드·프론트·인프라 스택
7.1. 백엔드 언어 선택
- Go (Fiber/Echo)는 goroutine으로 1만 동시 연결을 노드 하나로 처리해 수집 워커와 API에 모두 적합하다.
- Python은 GIL로 수집 워커에는 부적합하지만 Polars·DuckDB 기반 배치 ETL에는 최적이다.
- Rust는 Go보다 30~50% 빠르지만 개발 속도가 느려, 핫 패스만 Rust로 작성하는 하이브리드 전략이 현실적이다.
- Node.js는 단일 스레드 이벤트 루프라 CPU 집약 JSON 파싱 대량 처리에서 병목이 된다.
7.2. 프론트엔드 — Next.js + shadcn/ui
SEO가 필요한 마케팅 페이지와 인증 후 대시보드가 혼재하므로 App Router의 SSG/SSR/CSR 페이지별 선택이 최적이다. shadcn/ui는 사용한 컴포넌트만 번들에 들어가 MUI·Antd 대비 번들 사이즈가 작다. 1만 행 테이블은 TanStack Virtual로 가상 스크롤, 100만 데이터포인트 차트는 ECharts Canvas 렌더링으로 60fps를 유지한다.
7.3. 인프라 오케스트레이션
- 소규모 15노드는
k3s로 충분하고, 대규모 47노드+는 Talos OS + 표준 K8s가 권장된다. - ArgoCD GitOps로 Git push 시 자동 배포·롤백을 git revert로 처리한다.
- VictoriaMetrics는 Prometheus 호환이면서 디스크 사용량 1/10, 쿼리 속도 10배다.
8. 데이터 흐름 시나리오
8.1. 새 채널 수집 흐름
- 트렌딩 수집 워커가 YouTube Data API에서 새 채널 ID를 발견한다.
- NATS의
channels.discovered토픽에 메시지 발행. - 채널 수집 워커가 메타데이터를 가져와 Postgres에 INSERT(Citus가 샤드 자동 라우팅).
- 인덱싱 워커가 MeiliSearch에 색인, OpenAI 임베딩을 Qdrant에 저장.
- 트렌딩 이벤트는 별도 워커가 1000건씩 묶어 ClickHouse 배치 INSERT.
- 1년 이상 묵은 데이터는 야간 배치가 Parquet으로 변환해 R2 업로드 후 ClickHouse에서 삭제.
8.2. 사용자 검색 흐름
- "한국 게임 100만 구독" 검색 요청이 Cloudflare Workers에 도달.
- JWT 검증과 Rate Limit 체크, KV 캐시 hit이면 30ms에 응답.
- 캐시 미스 시 Go API가 MeiliSearch·Postgres·ClickHouse에 병렬 쿼리.
- 세 결과를 merge해 Redis에 5분 TTL 캐시 후 반환.
- 전체 응답: hit 30ms, miss 150~300ms.
9. 서버 스펙·비용·마이그레이션
9.1. 풀스케일 노드 산정 추정
| 역할 | 노드 수 | 스펙 | 산정 근거 |
|---|---|---|---|
| Citus 워커 | 8노드 | 32vCPU/128GB/4TB NVMe | 채널·영상 합 노드당 2TB |
| ClickHouse | 4노드 | 32vCPU/256GB/8TB NVMe | 시계열 5TB 분산, 집계용 RAM |
| API 서버 | 4노드 | 16vCPU/64GB | 목표 RPS 500, 여유 12배 |
| 수집 워커 | 20노드 | 8vCPU/16GB | API 키 50개 풀, 채널당 월 1회 갱신 |
9.2. 인프라 비용 비교(추정)
| 인프라 | 월 비용 | 비고 |
|---|---|---|
| Hetzner Dedicated | 약 $7,000 | 전용서버, 무제한 트래픽 |
| AWS (EC2+RDS+S3) | 약 $28,000 | 매니지드, 4배 비쌈 |
| GCP | 약 $26,000 | AWS와 유사 |
| 자체 IDC | 약 $3,500 | 초기 투자 큼, 인력 필요 |
Hetzner + Cloudflare(R2/CDN) 하이브리드가 가성비 1위다.
9.3. 단계별 월 비용 누적
| 항목 | Phase 1 (100만) | Phase 2 (1천만) | Phase 3 (1억+) |
|---|---|---|---|
| 컴퓨팅 | $200 | $1,300 | $6,500 |
| 스토리지(R2) | $20 | $150 | $1,000 |
| YouTube API 추가 | $0 | $500 | $3,000 |
| AI 임베딩 | $50 | $500 | $5,000 |
| CDN·모니터링 | $0 | $150 | $500 |
| 합계 | 약 $270 | 약 $2,600 | 약 $16,000 |
9.4. 단계별 마이그레이션 전략
- Phase 0 → 1 (1~2개월): D1에서 Hetzner Postgres 16 single-node로 이전, Workers에서 Hyperdrive로 연결, 1주간 dual-run 후 전환.
- Phase 1 → 2 (3~6개월): 채널 1천만 도달 시 ClickHouse 2노드 도입, dual-write로 트렌딩 분리, R2 콜드 아카이브 파이프라인 구축.
- Phase 2 → 3 (6~12개월): 채널 5천만 돌파 시 Citus 분산 클러스터, MeiliSearch·Qdrant 추가, K8s 마이그레이션, 멀티 리전 Read Replica.
핵심 포인트: 현재 D1 구조에서 Phase 3로 직접 점프하면 운영이 무너진다. Phase 1부터 시작해 채널 수와 쿼리 패턴을 보며 ClickHouse·Citus·Qdrant를 순차 도입하는 것이 안전하다.
10. 운영 리스크와 대응
10.1. 주요 리스크 매트릭스
- YouTube API quota 고갈이 가장 큰 리스크다. 일일 10,000 units로는 1억 채널을 갱신할 수 없으므로 GCP 프로젝트 50~100개 운영, quota 증액 신청, 활성도 기반 우선순위 큐(활성 주1회·비활성 월1회·휴면 분기1회)로 대응한다.
- 단일 노드 SPOF는 Citus 코디네이터 2노드 Patroni failover, ClickHouse ReplicatedMergeTree 2-replica, MeiliSearch 일일 R2 snapshot, Qdrant 3-replica 클러스터로 방어한다.
- AI 임베딩 비용 폭증은 변경 감지(설명·제목 해시 비교) 후 변경분만 재임베딩, BGE-M3 자체 모델을 RTX 4090에서 운영하면 90% 절감 가능하다.
- 법적 리스크는 메타데이터·통계 위주 노출, 영상 자체 다운로드·재배포 절대 금지, 공식 API 우선·스크래핑 최소화 원칙으로 대응한다.
11. 마무리
위에서 살펴본 1억 채널 YouTube 분석기 인프라 설계의 핵심 내용을 정리하면 다음과 같습니다.
핵심 요약:
- 1억 채널 규모에서는 OLTP·OLAP·검색·벡터·콜드 다섯 워크로드가 본질적으로 달라 Polyglot Persistence가 강제 조건이다.
- OLTP는 Postgres + Citus 분산 샤딩, OLAP는 ClickHouse, 검색은 MeiliSearch, 벡터는 Qdrant, 콜드는 R2 + Parquet + DuckDB가 최적 조합이다.
- 큐는 NATS JetStream, 캐시는 Redis/Dragonfly, 백엔드는 Go(Fiber), 프론트는 Next.js + shadcn/ui가 비용·운영 효율 면에서 권장된다.
- 인프라는 Hetzner 전용서버 + Cloudflare 엣지 하이브리드가 AWS·GCP 대비 약 1/4 비용이다.
- 월 비용은 100만 채널 약 $270, 1천만 약 $2,600, 1억 약 $16,000 수준이며 AI 임베딩이 최대 변수다.
- 현재 D1에서 Phase 3로 직접 점프하지 말고 Phase 1→2→3 순차 마이그레이션이 안전하다.
실무에서는 1억~2억 채널 풀 수집보다 활성 채널 1천만~5천만 타깃으로 범위를 좁히는 것이 사업적·기술적으로 훨씬 합리적이며, 이 규모에서도 강력한 분석 서비스를 제공할 수 있고 비용도 약 1/3로 줄어든다.
자주 묻는 질문
- 왜 단일 DB(Supabase, Turso 등)로는 1억 채널 분석기를 운영할 수 없나요?
유튜브 분석기의 워크로드가 OLTP(채널 메타), OLAP(트렌딩 집계), 풀텍스트 검색, 벡터 검색, 콜드 아카이브 다섯 가지로 본질적으로 다르기 때문입니다. 모든 데이터를 Postgres 하나에 넣으면 트렌딩 집계 쿼리가 OLTP 트랜잭션을 블록하고, 인덱스가 데이터의 3~5배로 폭증하며, 5TB 백업에 12시간 이상 걸려 운영이 사실상 불가능합니다.
- ClickHouse와 TimescaleDB 중 무엇을 선택해야 하나요?
수십억 행 단위 본격 시계열 분석이 핵심이면 ClickHouse가 정답입니다. ClickHouse는 컬럼형 저장과 벡터화 실행으로 GROUP BY 속도가 TimescaleDB 대비 5~20배 빠르고 압축률도 약 10~30배입니다. 다만 Postgres 안에서 가벼운 시계열만 처리한다면 TimescaleDB가 운영 복잡도 면에서 더 단순한 선택입니다.
- 콜드 아카이브에 AWS S3가 아닌 Cloudflare R2를 권장하는 이유는 무엇인가요?
R2는 egress fee가 0이라는 결정적 장점이 있습니다. S3는 데이터를 빼낼 때 GB당 약 $0.09를 부과해 콜드 데이터 분석 쿼리가 자주 발생하면 비용 폭탄이 됩니다. 반면 R2는 분석 쿼리가 가끔 콜드 데이터를 조회해도 추가 트래픽 비용이 없어 안전합니다. 저장 단가도 GB당 약 $0.015로 S3보다 저렴합니다.
- 검색엔진으로 MeiliSearch가 Elasticsearch보다 나은 경우는 언제인가요?
약 1억 문서 이하 규모에서 운영 부담을 줄이고 싶을 때 MeiliSearch가 더 적합합니다. Rust로 작성돼 메모리 사용량이 Elasticsearch의 약 1/3 수준이고, 마스터·데이터·인제스트 노드 분리 같은 복잡한 클러스터 운영이 필요 없습니다. 다만 무제한 분산 확장이나 최고 수준 한국어 분석(Nori)이 필요하면 Elasticsearch가 여전히 표준입니다.
- 1억 채널 운영 시 월 비용에서 가장 큰 변수는 무엇인가요?
AI 임베딩 비용이 가장 큰 변수입니다. 1억 채널을 OpenAI text-embedding-3-small로 한 번 임베딩하면 약 $5,000이 들고, 채널 갱신 시마다 재임베딩하면 비용이 폭증합니다. 채널 설명·제목 해시 비교로 변경 감지 후 변경분만 재임베딩하고, BGE-M3 같은 오픈 모델을 RTX 4090에서 자체 운영하면 약 50~90% 절감이 가능합니다.
- 현재 D1 구조에서 바로 Phase 3로 점프하면 안 되는 이유는 무엇인가요?
Phase 3 아키텍처는 Postgres+Citus, ClickHouse, MeiliSearch, Qdrant, R2, NATS, K8s를 모두 운영해야 해서 학습 곡선과 운영 부담이 매우 큽니다. 채널 수와 쿼리 패턴이 충분히 검증되지 않은 상태에서 전부 도입하면 어떤 구간이 진짜 병목인지 파악하지 못한 채 인프라가 무너지기 쉽습니다. Phase 1에서 single-node Postgres로 시작해 실제 워크로드를 보며 ClickHouse·Citus·Qdrant를 순차 도입하는 것이 안전합니다.
- 유튜브 채널 1억 풀 수집 대신 권장되는 현실적 타깃은 무엇인가요?
활성 채널 1천만~5천만 타깃이 사업적·기술적으로 가장 합리적입니다. 전 세계 유튜브 채널의 약 91%는 구독자 1천 명 미만의 저활성·휴면 채널이라 수집해도 분석 가치가 낮습니다. 활성 채널만 타깃하면 인프라 비용이 약 1/3로 줄어들고, YouTube API quota 부담도 크게 완화되며, 분석 품질은 오히려 높아집니다.