안녕하세요! 오늘은 개발자라면 꼭 알아야 할 모니터링의 핵심 개념, 바로 **메트릭과 시계열 데이터의 카디널리티(Cardinality)**에 대해 이야기해보려고 합니다.
우리는 서비스의 상태를 파악하기 위해 다양한 모니터링 시스템(예: 프로메테우스, 데이터독)을 사용합니다. CPU 사용량, 메모리 점유율, API 요청 수 등 수많은 지표(Metric)를 수집하죠. 그런데 혹시, "어느 순간부터 모니터링 대시보드가 느려지거나 비용이 급증한" 경험 없으신가요? 🤔 그 원인은 바로 '고차원 카디널리티(High Cardinality)' 문제일 수 있습니다!

📊 메트릭과 시계열 데이터, 기본부터 알아보기
먼저 기본 개념을 잡아볼까요?
- 메트릭 (Metric): 우리가 측정하고 싶은 값의 이름입니다. 예를 들어, http_requests_total (총 HTTP 요청 수) 같은 것이죠.
- 속성/차원 (Attribute/Dimension/Label): 메트릭에 대한 상세한 정보를 담는 '꼬리표'입니다. key-value 쌍으로 이루어져 있죠.
- method="GET"
- status_code="200"
- region="ap-northeast-2"
이 메트릭과 속성들의 조합 하나하나가 고유한 시계열(Time Series) 데이터를 만들어냅니다.
예를 들어 볼까요?
- http_requests_total{method="GET", status_code="200", region="ap-northeast-2"} 👉 하나의 시계열
- http_requests_total{method="POST", status_code="200", region="ap-northeast-2"} 👉 또 다른 하나의 시계열
- http_requests_total{method="GET", status_code="404", region="us-east-1"} 👉 전혀 다른 새로운 시계열
이처럼, 같은 메트릭 이름이라도 붙어있는 라벨 조합이 다르면 완전히 별개의 데이터 흐름으로 취급됩니다.
🔢 그래서 '카디널리티'가 뭔가요?
카디널리티(Cardinality)란, 바로 이 '고유한 시계열 데이터의 총개수'를 의미합니다.
카디널리티는 각 속성이 가질 수 있는 고유한 값의 개수를 모두 곱해서 계산할 수 있습니다.
쉬운 예시: login_attempts (로그인 시도) 라는 메트릭이 있다고 가정해 봅시다.
- 속성 1: device (가질 수 있는 값: mobile, desktop, tablet 👉 3개)
- 속성 2: country (가질 수 있는 값: KR, US, JP, CN 👉 4개)
이 경우, login_attempts 메트릭의 총 카디널리티는 몇일까요?
📱💻 3 (device) x 🌍 4 (country) = 12개
총 12개의 고유한 시계열 데이터가 생성되는 것이죠. 이 정도는 전혀 문제없는 '낮은 카디널리티'입니다.
💥 고차원 카디널리티(High Cardinality)의 함정
문제는 속성의 값으로 거의 무한에 가까운 고유한 값이 들어올 때 발생합니다.
위험한 예시: api_latency_seconds (API 응답 시간) 라는 메트릭에 다음과 같은 속성을 추가했다고 상상해 보세요.
- 속성 1: endpoint (가질 수 있는 값: /users, /orders, /products 👉 3개)
- 속성 2: user_id (가질 수 있는 값: 1, 2, 3, ..., 1,000,000 👉 100만 개)
이 메트릭의 카디널리티는 어떻게 될까요?
🚀 3 (endpoint) x 👤 1,000,000 (user_id) = 3,000,000개 😱
user_id 하나를 추가했을 뿐인데, 순식간에 300만 개의 시계열 데이터가 폭발적으로 생성됩니다. 이것이 바로 고차원 카디널리티의 문제입니다.
이런 상황은 다음과 같은 심각한 문제들을 야기합니다.
- 💰 비용 폭증: 대부분의 모니터링 서비스는 시계열 데이터의 개수를 기준으로 비용을 청구합니다. 카디널리티가 높을수록 저장하고 처리해야 할 데이터가 많아져 요금 폭탄을 맞을 수 있습니다.
- 🐢 성능 저하: 수백만 개의 시계열 데이터를 조회하고 집계하는 쿼리는 매우 느려집니다. 실시간 장애 대응이 중요한 모니터링 시스템에서 이는 치명적입니다.
- 🔥 시스템 불안정: 모니터링 시스템 자체가 과도한 부하를 견디지 못하고 메모리 부족(OOM) 등으로 다운될 수 있습니다.
✅ 현명하게 카디널리티 관리하기
그렇다면 이 무서운 카디널리티 문제를 어떻게 피할 수 있을까요?
- 라벨은 신중하게 선택하세요!
- 절대 사용하면 안 되는 값: user_id, request_id, session_id, email, 정확한 timestamp 등 고유하고 무한히 증가할 수 있는 값은 라벨로 사용하지 마세요. ❌
- 사용하기 좋은 값: environment (prod/stg), region, http_method (GET/POST), error_code_group (2xx, 4xx, 5xx) 등 그룹화할 수 있고 예측 가능한 집합의 값들을 사용하세요. ✅
- 고유한 정보는 로그(Log)로 남기세요!
- user_id나 request_id처럼 특정 이벤트의 상세 정보는 메트릭의 라벨이 아닌, **구조화된 로그(Structured Log)**에 기록하는 것이 올바른 접근 방식입니다. 🪵
- 메트릭은 **'집계된 경향'**을 보는 용도, 로그는 **'개별 이벤트'**를 추적하는 용도로 역할을 분리하세요.
- 라벨의 개수를 제한하세요.
- 하나의 메트릭에 너무 많은 라벨을 붙이는 것은 잠재적인 카디널리티 폭증의 원인이 됩니다. 꼭 필요한 핵심 차원만 라벨로 추가하는 습관을 들이는 것이 좋습니다.
✨ 마치며
카디널리티는 데이터를 더 깊이 있게 분석할 수 있게 해주는 강력한 도구이지만, 잘못 사용하면 모니터링 시스템 전체를 마비시킬 수 있는 양날의 검과 같습니다.
오늘부터 우리가 수집하는 메트릭의 라벨들을 한번 점검해보는 것은 어떨까요? 현명한 카디널리티 관리를 통해 안정적이고 효율적인 모니터링 환경을 만들어가시길 바랍니다! 💪
'클라우드 > prometheus' 카테고리의 다른 글
| ☁️ 클라우드 네이티브의 심장, CNCF가 꿈꾸는 상생의 생태계 (0) | 2025.10.13 |
|---|---|
| ✨ 프로메테우스의 숨은 보석, honor_labels 파헤치기 (0) | 2025.10.12 |
| 프로메테우스(Prometheus) on() vs ignoring(): 벡터 매칭의 두 얼굴 🎭 (0) | 2025.10.12 |
| 🚀 골든 쿠버스트로넛을 향한 여정 (6/15): PCA 합격, 모니터링의 신세계를 맛보다! (feat. PromQL과의 사투) (0) | 2025.10.12 |
| 📊 히스토그램 vs 서머리: 당신의 선택은? 서버냐 클라이언트냐, 그것이 문제로다! (0) | 2025.10.11 |