본문 바로가기
클라우드/prometheus

📈 당신의 모니터링 시스템을 위협하는 보이지 않는 적, '카디널리티'

by gasbugs 2025. 10. 13.

안녕하세요! 오늘은 개발자라면 꼭 알아야 할 모니터링의 핵심 개념, 바로 **메트릭과 시계열 데이터의 카디널리티(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만 개의 시계열 데이터가 폭발적으로 생성됩니다. 이것이 바로 고차원 카디널리티의 문제입니다.

이런 상황은 다음과 같은 심각한 문제들을 야기합니다.

  1. 💰 비용 폭증: 대부분의 모니터링 서비스는 시계열 데이터의 개수를 기준으로 비용을 청구합니다. 카디널리티가 높을수록 저장하고 처리해야 할 데이터가 많아져 요금 폭탄을 맞을 수 있습니다.
  2. 🐢 성능 저하: 수백만 개의 시계열 데이터를 조회하고 집계하는 쿼리는 매우 느려집니다. 실시간 장애 대응이 중요한 모니터링 시스템에서 이는 치명적입니다.
  3. 🔥 시스템 불안정: 모니터링 시스템 자체가 과도한 부하를 견디지 못하고 메모리 부족(OOM) 등으로 다운될 수 있습니다.

 

✅ 현명하게 카디널리티 관리하기

그렇다면 이 무서운 카디널리티 문제를 어떻게 피할 수 있을까요?

  1. 라벨은 신중하게 선택하세요!
    • 절대 사용하면 안 되는 값: user_id, request_id, session_id, email, 정확한 timestamp 등 고유하고 무한히 증가할 수 있는 값은 라벨로 사용하지 마세요. ❌
    • 사용하기 좋은 값: environment (prod/stg), region, http_method (GET/POST), error_code_group (2xx, 4xx, 5xx) 등 그룹화할 수 있고 예측 가능한 집합의 값들을 사용하세요. ✅
  2. 고유한 정보는 로그(Log)로 남기세요!
    • user_id나 request_id처럼 특정 이벤트의 상세 정보는 메트릭의 라벨이 아닌, **구조화된 로그(Structured Log)**에 기록하는 것이 올바른 접근 방식입니다. 🪵
    • 메트릭은 **'집계된 경향'**을 보는 용도, 로그는 **'개별 이벤트'**를 추적하는 용도로 역할을 분리하세요.
  3. 라벨의 개수를 제한하세요.
    • 하나의 메트릭에 너무 많은 라벨을 붙이는 것은 잠재적인 카디널리티 폭증의 원인이 됩니다. 꼭 필요한 핵심 차원만 라벨로 추가하는 습관을 들이는 것이 좋습니다.

✨ 마치며

카디널리티는 데이터를 더 깊이 있게 분석할 수 있게 해주는 강력한 도구이지만, 잘못 사용하면 모니터링 시스템 전체를 마비시킬 수 있는 양날의 검과 같습니다.

오늘부터 우리가 수집하는 메트릭의 라벨들을 한번 점검해보는 것은 어떨까요? 현명한 카디널리티 관리를 통해 안정적이고 효율적인 모니터링 환경을 만들어가시길 바랍니다! 💪