책의 이론 아키텍처 + 네이버 검색 SRE + 당근마켓 SRE 실제 구현 비교 정리
설계 범위 및 요구사항
처리 스케일
- DAU 1억 명 기준
- 서버 풀 1,000개 × 풀당 서버 100대 × 서버당 지표 100개 = 천만 개 지표 수집
- 데이터 보관 및 다운샘플링 정책:
~ 7일 : Raw 그대로 보관 (실시간성 확보)
7 ~ 30일 : 1분 단위로 롤업(Roll-up) 후 보관
30일 ~ 1년: 1시간 단위로 다운샘플링 후 콜드 스토리지
비기능 요구사항
- High Write / Spiky Read: 초당 수백만 건 쓰기, 읽기는 대시보드 조회/경보 시점에만 일시 폭증
- 낮은 질의 레이턴시: 대시보드 로딩과 경보 평가 신속 처리
- 안정성: 과부하 상태에서도 중요 경보 절대 누락 금지
데이터 모델
// 지표 이름 + 라벨(Key-Value) + 타임스탬프 + 값
cpu.load {host: "server-i631", env: "prod", zone: "us-west"} -> [1685670000, 65%]
⚠️ 카디널리티 폭발 (Cardinality Explosion) — 반드시 주의
라벨에 user_id, request_id 같이 무한히 변하는 값을 넣으면 TSDB 인덱스가 메모리를 초과(OOM)해서 전체 모니터링 시스템이 다운된다. 라벨의 고유 조합은 반드시 제한해야 한다. (샘플링 or mimir -> 컴팩터 이용)
전체 아키텍처 파이프라인
[지표 출처 / 에이전트]
│
(Pull / Push)
▼
[지표 수집기] ──(해시 링으로 샤딩)──> [수집기 클러스터]
│
(안전한 버퍼링)
▼
[Apache Kafka] ──> [스트림 처리 서비스] ──> [TSDB]
│
┌─────────────────┴──────────────────┐
▼ ▼
[질의 서비스 + 캐시] [경보 관리자]
│ │
▼ ▼
[시각화 (Grafana)] [Kafka] ──> [알림 채널]
수집 모델: Pull vs Push
항목 Pull 모델 (Prometheus) Push 모델 (CloudWatch, Datadog)
| 방식 | 수집기가 대상 서버를 주기적으로 스크랩 | 에이전트가 수집기로 직접 전송 |
| 상태 진단 | 쉬움 (안 오면 죽은 것) | 별도 헬스체크 필요 |
| 짧은 생명주기 프로세스 | 불리 (스크랩 전 종료 가능) | 유리 |
| 방화벽 복잡 환경 | 불리 | 유리 |
| 프로토콜 | TCP (오버헤드 낮음) | UDP (지연 낮음) |
| 데이터 신뢰성 | 미리 정의된 지표만 수집 | 인증 강제 필요 |
대규모 Pull 모델의 확장법: 수집기를 일관된 해시 링(Consistent Hashing Ring)으로 묶어 특정 수집기가 특정 서버군만 전담하도록 분산 샤딩.
카프카 — 유실 방지 버퍼
수집기와 TSDB 사이에 Kafka를 두는 이유:
- TSDB 장애 시에도 데이터 유실 없이 Kafka가 보관
- 수집/처리 컴포넌트 사이의 결합도 감소
- 지표 이름/라벨 기준으로 파티션 분리 → 컨수머 그룹 병렬 처리
데이터 집계 지점 3가지
방식 특징 단점
| 수집 에이전트에서 집계 | 클라이언트 측, 단순 집계만 가능 | 복잡한 집계 불가 |
| 파이프라인에서 집계 | 저장 전 처리 | 원본 데이터 소실 |
| 질의 시 집계 | Raw 보관 후 필요할 때 집계 | 속도 느림 |
1. 클라이언트(에이전트)에서 집계
앱 프로세스 안에서 이미 집계된 값을 노출하는 방식.
Prometheus client library
# SDK가 내부적으로 버킷별 카운트를 누적 집계
histogram = Histogram('http_request_duration_seconds',
buckets=[0.1, 0.5, 1.0, 2.0])
histogram.observe(0.3) # SDK가 0.1~0.5 버킷 카운트 +1
Prometheus가 /metrics를 스크랩하면 이미 집계된 _bucket, _sum, _count만 받음. raw 요청 데이터는 존재하지 않음.
OTEL SDK
views:
- selector:
instrument_name: http.server.duration
aggregation:
type: explicit_bucket_histogram
boundaries: [0.1, 0.5, 1.0]
한계: 각 인스턴스가 자기 것만 집계 → 서비스 전체 합산 불가. 퍼센타일 정밀도 낮음.
2. 파이프라인에서 집계
데이터가 TSDB에 들어가기 전 중간 단계에서 집계.
OTEL Collector — 파이프라인 집계의 대표 도구
processors:
groupbyattrs: # 수천 개 파드를 service 단위로 합산
keys: [service.name, env]
metricstransform:
transforms:
- include: http_requests_total
action: update
operations:
- action: delete_label_value
label: pod_id # 고카디널리티 라벨 제거
[파드 1000개 → http_requests{pod_id="xxx"}]
↓ OTEL Collector groupbyattrs
[service="order-api" 단위 시계열 1개]
↓ TSDB
Prometheus Recording Rules (Prometheus의 파이프라인 집계에 해당)
groups:
- name: aggregations
interval: 1m
rules:
- record: service:http_requests:rate5m # 미리 계산해 새 시계열로 저장
expr: sum(rate(http_requests_total[5m])) by (service)
Grafana가 service:http_requests:rate5m을 조회하면 raw 데이터를 건드리지 않음 → 네이버 VictoriaMetrics Pre-calculate에서 10배 성능 개선.
한계: 저장 전 집계면 원본 소실 → 나중에 "파드별로 다시 보고 싶다"가 불가능.
3. 질의 시 집계
Raw 데이터를 그대로 저장해두고, 조회할 때마다 집계.
Prometheus PromQL
# Grafana 대시보드 로딩 시마다 실행
sum(rate(http_requests_total[5m])) by (service)
# 1000개 파드 × 5분치 raw 데이터를 매번 스캔해서 합산
Thanos / Cortex (대규모 분산 Prometheus)
[Prometheus 샤드 A] ──┐
[Prometheus 샤드 B] ──┼──→ Thanos Querier ──→ PromQL 실행 (질의 시 합산)
[Prometheus 샤드 C] ──┘
각 샤드는 raw를 보관, Thanos가 조회 시점에 분산 집계 → 당근마켓 Cortex가 이 패턴.
한계: 조회할 때마다 수백만 포인트 스캔 → 대시보드 로딩 느림. 아키텍처에서 Redis 캐시로 흡수하는 이유.
3가지 비교 정리
클라이언트 집계 파이프라인 집계 질의 시 집계
| 도구 예시 | Prometheus SDK, OTEL SDK | OTEL Collector, Recording Rules | PromQL, Thanos Querier |
| 원본 보존 | ❌ | ❌ | ✅ |
| TSDB 부하 | 낮음 | 낮음 | 높음 |
| 유연성 | 낮음 | 중간 | 높음 |
| 속도 | 빠름 | 빠름 | 느림 |
실제 운용 패턴 (혼합 사용)
소규모 — Prometheus 단독
앱(SDK 집계) → Prometheus scrape → PromQL 질의 시 집계
중간 규모 — Prometheus + Recording Rules
앱(SDK 집계) → Prometheus scrape → Recording Rules 선행 계산 → PromQL
→ 네이버 VictoriaMetrics Pre-calculate 패턴
대규모 — OTEL + Thanos/Cortex
앱(OTEL SDK) → OTEL Collector(파이프라인 집계, 라벨 정리) → Prometheus 샤드(raw) → Thanos(질의 시 분산 집계)
→ 당근마켓 Cortex 패턴의 변형
선행 계산 (Pre-aggregation) — 핵심 성능 기법
대시보드를 열 때마다 수만 대 서버 지표를 실시간 합산하면 TSDB가 터진다.
백그라운드에서 무거운 쿼리를 미리 실행해 단일 타임 시리즈로 저장해두는 방식.
- Prometheus: 레코딩 룰(Recording Rules)
- VictoriaMetrics: 프리컴퓨터(Pre-calculate)
- InfluxDB: Continuous Tasks
질의 서비스 + 캐시 계층
[그라파나 / 시각화]
│
[질의 API 서버] ──> [Redis 캐시] ──(캐시 히트)──> 즉시 반환
│
(캐시 미스)
▼
[TSDB]
수많은 개발자가 동시에 같은 대시보드를 열 때 TSDB 부하를 Redis 캐시로 흡수.
경보 시스템
[경보 설정 캐시]
│
[경보 관리자] ──> [질의 서비스] ──> (이상 감지)
│
[경보 저장소 (Cassandra)]
│
[Kafka]
│
[경보 소비자] ──> 슬랙/이메일/PagerDuty
경보 관리자 핵심 기능
기능 설명
| 중복 제거 (Deduplication) | 수백 대 파드에서 동일 에러가 동시 발생 → 단 하나의 알람으로 묶어서 전송 |
| 침묵 (Silencing) | 인지된 점검/작업 중 특정 알람 뮤트 처리 |
| 그루핑 (Grouping) | 관련 경보들을 하나로 묶어 맥락 파악 용이 |
저장소 계층 최적화
기법 설명
| 데이터 압축 | Gorilla 압축, 델타 인코딩으로 디스크 I/O·용량 절감 |
| 다운샘플링 | 오래된 데이터는 해상도 낮춰서 저장 (1분 → 1시간 단위) |
| 콜드 스토리지 | 오래된 다운샘플링 데이터를 S3 등 저렴한 스토리지로 이동 |
이론 vs 실제 기업 구현 비교
설계 항목 책 이론 네이버 검색 SRE 당근마켓 SRE
| 규모 | DAU 1억, 천만 지표 | 수만 대 물리 장비, 수백 서비스 | MAU 1,800만, 400개 워크로드 |
| TSDB | InfluxDB / Prometheus | VictoriaMetrics | Cortex (프로메테우스 확장) |
| 수집 모델 | Pull/Push 선택 가이드 | Pull 기반 + 라벨링 커스텀 | 로컬 프로메테우스 샤딩 + Cortex 집중 |
| 선행 계산 | 파이프라인 집계 권장 | VictoriaMetrics Pre-calculate (10배 성능) | 로키 레코딩 룰 (로그 캐싱) |
| 경보 방식 | 배치 기반 주기적 평가 | 배치 → 스트리밍(Kafka) 전환 | Prometheus Alert + Datadog 워치독 |
| 질의 서비스 | 질의 서버 + Redis 캐시 | RDB 쿼리 메타 테이블 + WITH 템플릿 | 그라파나 직접 연동 + 네임스페이스별 대시보드 |
| 알람 관리 | Alert Manager 중복 제거 | 스트리밍으로 1분 내 경보 | 깨진 유리창 법칙 기반 노이즈 관리 |
| 로그 저장 | 별도 파이프라인 | Loki | Loki (비용 이유로 Datadog 로그 미사용) |
| 시각화 | Grafana 추천 | Grafana + 커스텀 쿼리 DB 연동 | Grafana + Datadog APM |
각 기업이 가장 집중했던 포인트
네이버 검색 SRE — "경보 레이턴시 최소화 + 쿼리 관리 효율화"
문제: 배치 구조로 인한 2분 30초 이상의 경보 지연.
해결: 경보 파이프라인을 메시지 큐 기반 스트리밍 구조로 전환 → 1분 내외 경보.
실증: 2022 카타르 월드컵 당시 트래픽이 7배 폭증하는 순간, 경보 수신 후 3~4분 만에 장애 해소. 기존 시스템이었으면 경보가 오기 전에 다른 시스템으로 장애가 전파될 수 있었던 상황.
쿼리 관리: 200개 이상의 쿼리를 코드에서 분리해 RDB 테이블로 데이터화 + VictoriaMetrics WITH 구문으로 중복 제거 → 쿼리 30% 경량화, API 서버 재배포 없이 쿼리 변경 가능.
Before: 코드에 쿼리 하드코딩 → 변경 시 API 서버 재배포 필요
After: RDB 쿼리 테이블 조회 → DB Row 수정만으로 실시간 변경
https://www.youtube.com/watch?v=j_5HOboU3lk&t=1486s
당근마켓 SRE — "소수 인원의 확장성 + 비용 절감 인프라 지원"
구조적 선택: 멀티 테넌시 대신 전사 단일 K8s 클러스터 + 프로젝트별 네임스페이스 분리.
역할 분리:
- SRE: 인프라/네트워크/K8s 공통 영역 대시보드 (K8s 닥터, Istio 닥터) 구축
- 개발팀: 비즈니스 지표는 Datadog/Superset으로 직접 관리
깨진 유리창 법칙 기반 알람 관리:
- 평상시 노이즈 관리 → 진짜 장애 알람이 무시되지 않는 환경 구축
- 에러 로그가 너무 자주 튀면 개발팀에 "워닝 로그로 내려달라" 요청
비용 절감 + 안정성 동시 달성:
CPU 리밋 해제 → 노드 스로틀링 모니터링 강화
스팟 인스턴스 → 파드 에비션 리스트 대시보드 추가
멀티 AZ → 리전 스큐(Region Skew) 모니터링 추가
https://www.youtube.com/watch?v=3iLTBBC9ZX4
모니터링 방법론 3가지
방법론 제안자 핵심 지표 적합 대상
| USE | Brendan Gregg (Netflix) | Utilization, Saturation, Errors | 인프라/시스템 자원 |
| RED | Tom Wilkie (Google) | Rate, Errors, Duration | 애플리케이션/서비스 |
| 4 Golden Signals | Google SRE Book | Latency, Traffic, Errors, Saturation | 분산 시스템 전반 |
핵심 교훈 정리
네이버는 선행 계산(Pre-aggregation) 원리를 VictoriaMetrics 프리컴퓨터로 구현해 수만 대 검색 장비의 조회 지연을 10배 개선했다.
당근마켓은 안정적 파이프라인 + 포스트모템 문화를 Cortex/Loki 인프라와 매주 목요일 5-Whys 회고로 실현해 지식 공유의 선순환을 만들었다.
두 기업 모두 오픈소스를 그대로 쓰지 않고, 자사 규모와 팀 상황에 맞게 트레이드 오프를 선택하여 커스텀했다.
'Book' 카테고리의 다른 글
| [대규모 시스템 설계 기초 2] 4장 분산 메시지 큐 (0) | 2026.05.12 |
|---|---|
| [대규모 시스템 설계 기초] 4장 처리율 제한 장치의 설계 (0) | 2025.05.06 |
| [대규모 시스템 설계 기초] 3장 시스템 설계 면접 공략법 (0) | 2025.04.23 |
| [대규모 시스템 설계 기초] 2장 개략적인 규모 추정 (0) | 2025.04.11 |
| [대규모 시스템 설계 기초] 1장 사용자 수에 따른 규모 확장성 (0) | 2025.04.06 |