이번 글에서는 프로메테우스와 그라파나를 활용한 Observability 구성 시리즈의 첫 번째 포스트로, Observability의 기본 개념과 모니터링과의 차이점, 그리고 Observability를 구성하는 세 가지 핵심 요소에 대해 알아보겠습니다.
📌 Observability란 무엇인가?
Observability(관측 가능성)는 시스템의 내부 상태를 외부에서 관찰할 수 있는 능력을 의미합니다. 이 개념은 제어 이론에서 유래했으며, 시스템 내부에서 일어나는 일을 외부 출력만으로 이해할 수 있는지를 평가합니다.
현대적인 IT 환경에서 Observability는 단순한 모니터링을 넘어 복잡한 분산 시스템의 내부 상태를 심층적으로 이해하고 문제의 근본 원인을 파악하는 능력을 의미합니다.
📌 Observability와 모니터링의 차이점
많은 사람들이 Observability와 모니터링을 혼동하는 경우가 있습니다. 비슷해 보이지만 실제로는 접근 방식과 목적에서 중요한 차이점이 있습니다.

✅ 모니터링
모니터링은 시스템의 알려진 상태를 측정하고 추적하는 것에 초점을 맞춥니다:
- 사전에 정의된 지표와 임계값에 중점을 둡니다
- 주로 '무엇이 잘못되었는가?'라는 질문에 답합니다
- 예상된 문제나 장애 상황을 감지하는 데 유용합니다
- CPU 사용률, 메모리 사용량, 디스크 공간과 같은 리소스 지표를 추적합니다
- 알림을 통해 문제 발생 시 운영팀에 통보합니다
✅ Observability
Observability는 시스템의 알려지지 않은 상태를 이해하고 탐색하는 능력에 초점을 맞춥니다:
- 데이터 탐색과 질의에 중점을 둡니다
- '왜 잘못되었는가?'라는 질문에 답하는 데 도움을 줍니다
- 예측하지 못한 문제나 복잡한 장애 상황을 진단하는 데 유용합니다
- 시스템의 모든 데이터를 수집하고 상관관계를 분석합니다
- 심층적인 인사이트와 근본 원인 분석을 제공합니다
쉬운 비유로 설명하자면, 모니터링은 자동차의 계기판을 보는 것과 같습니다. 속도, 연료량, 엔진 온도와 같은 기본적인 지표를 확인할 수 있지만, 자동차가 왜 이상한 소리를 내는지는 알려주지 않습니다. 반면, Observability는 자동차의 모든 센서 데이터에 접근하고, 그 데이터를 분석하여 엔진에서 발생하는 특정 문제의 근본 원인을 파악할 수 있게 해주는 것과 같습니다.
📌 Observability의 세 가지 핵심 요소
Observability는 세 가지 핵심 데이터 유형으로 구성됩니다. 이 세 가지 요소가 함께 작동하여 시스템의 전체적인 상태와 행동을 이해할 수 있는 종합적인 뷰를 제공합니다.

1️⃣ 메트릭(Metrics)
메트릭은 시스템의 상태를 나타내는 수치 데이터입니다. 시간에 따른 변화를 추적하고 시스템 성능을 이해하는 데 도움이 됩니다.
▶️ 특징:
- 시계열 데이터: 시간에 따른 값의 변화를 기록합니다.
- 집계 가능: 수집, 요약, 평균화할 수 있습니다.
- 경량: 최소한의 시스템 오버헤드로 수집할 수 있습니다.
- 장기 저장: 일반적으로 압축되어 장기간 저장됩니다.
▶️ 일반적인 메트릭 예:
- CPU, 메모리, 디스크 사용량
- 요청 수, 응답 시간, 오류율
- 큐 길이, 캐시 히트율
- 사용자 로그인 수, 활성 세션 수
▶️ 메트릭의 장점:
- 시스템 상태에 대한 고수준 개요 제공
- 이상 감지 및 알림에 이상적
- 대시보드에서 시각적으로 표현하기 쉬움
- 성능 추세를 장기간 분석 가능
▶️ 프로메테우스의 역할:
프로메테우스는 메트릭 수집 및 저장을 위한 대표적인 오픈소스 도구입니다. 풀(Pull) 기반 메트릭 수집 모델을 사용하여 모니터링 대상에서 주기적으로 메트릭을 스크래핑합니다.
# 프로메테우스 설정 예시 (prometheus.yml)
scrape_configs:
- job_name: 'spring_boot_app' # 애플리케이션 이름 정의
metrics_path: '/actuator/prometheus' # Spring Boot Actuator 엔드포인트 경로 지정
scrape_interval: 15s # 15초마다 메트릭 수집 (빈도 조정 가능)
static_configs:
- targets: ['app-server:8080'] # 메트릭을 수집할 서버와 포트
labels:
environment: 'production' # 환경 라벨 추가(쿼리 시 필터링 용이)
instance: 'main-api' # 인스턴스 식별자
2️⃣ 로그(Logs)
로그는 시스템에서 발생하는 이벤트에 대한 타임스탬프가 지정된 텍스트 기반 기록입니다. 시스템의 행동과 사용자 상호작용에 대한 상세한 정보를 제공합니다.
▶️ 특징:
- 구조화 또는 비구조화: JSON과 같은 구조화된 형식 또는 일반 텍스트로 저장될 수 있습니다.
- 상세 정보: 오류 메시지, 스택 트레이스, 사용자 활동 등 상세한 정보를 포함합니다.
- 높은 카디널리티: 각 이벤트가 고유한 속성을 포함할 수 있습니다.
- 상황적 자료: 이벤트 발생 당시의 세부 정보를 제공합니다.
▶️ 일반적인 로그 예:
- 애플리케이션 로그: 디버그 정보, 오류, 경고
- 액세스 로그: 사용자 요청, IP 주소, 응답 코드
- 보안 로그: 로그인 시도, 권한 변경
- 시스템 로그: 서비스 시작/중지, 패치 적용
▶️ 로그의 장점:
- 문제 해결을 위한 상세한 정보 제공
- 사용자 활동 및 시스템 이벤트 추적
- 보안 감사 및 규정 준수에 필요
- 복잡한 시스템 동작 이해에 도움
▶️ 로키(Loki)의 역할:
그라파나 로키는 로그 수집 및 분석을 위한 수평적으로 확장 가능한 도구입니다. 프로메테우스와 유사한 레이블 기반 접근 방식을 사용하여 로그 데이터를 인덱싱합니다.
# 로키 설정 예시 (loki-config.yaml)
auth_enabled: false # 인증 비활성화 (개발 환경용, 운영 환경에서는 true로 설정)
server:
http_listen_port: 3100 # 로키 서버가 리스닝하는 HTTP 포트
ingester:
lifecycler:
address: 127.0.0.1 # 인제스터 서비스 주소
ring:
kvstore:
store: inmemory # 데이터 저장 방식 (메모리 내, 소규모 배포용)
replication_factor: 1 # 복제본 수 (운영 환경에서는 보통 3 이상)
final_sleep: 0s # 셧다운 전 대기 시간
chunk_idle_period: 5m # 청크가 비활성 상태로 유지되는 기간
chunk_retain_period: 30s # 인제스터에서 청크 유지 기간
schema_config: # 로그 스키마 구성
configs:
- from: 2020-10-24 # 이 구성이 적용되는 시작 날짜
store: boltdb-shipper # 인덱스 저장소 유형
object_store: filesystem # 청크 저장소 유형 (파일 시스템)
schema: v11 # 스키마 버전
index:
prefix: index_ # 인덱스 파일 접두사
period: 24h # 인덱스 회전 주기 (24시간마다 새 인덱스)
3️⃣ 트레이스(Traces)
트레이스는 분산 시스템에서 요청이 여러 서비스를 통과할 때 요청의 전체 경로를 추적합니다. 이를 통해 복잡한 아키텍처의 성능 병목 현상을 식별하고 문제를 해결할 수 있습니다.
▶️ 특징:
- 분산 추적: 여러 서비스와 시스템에 걸쳐 요청을 추적합니다.
- 계층 구조: 스팬(span)이라는 작은 실행 단위로 구성됩니다.
- 타이밍 정보: 각 단계의 지연 시간을 측정합니다.
- 컨텍스트 전파: 요청 컨텍스트가 서비스 간에 전달됩니다.
▶️ 트레이스 구성 요소:
- 트레이스 ID: 전체 트랜잭션을 식별하는 고유 ID
- 스팬(Span): 작업 단위(예: API 호출, 데이터베이스 쿼리)
- 스팬 ID: 각 스팬의 고유 식별자
- 부모 스팬 ID: 계층 구조를 위한 관계 표시
▶️ 트레이스의 장점:
- 성능 병목 현상 및 지연 시간 원인 식별
- 서비스 간 종속성 및 통신 패턴 이해
- 분산 시스템의 복잡한 문제 해결
- 최적화 기회 발견
▶️ Jaeger와 Tempo의 역할:
Jaeger와 그라파나 Tempo는 분산 트레이싱 시스템으로, 마이크로서비스 아키텍처에서 복잡한 트랜잭션을 추적하고 시각화하는 데 도움을 줍니다.
# Jaeger 설정 예시 (jaeger.yaml)
apiVersion: jaegertracing.io/v1 # Jaeger 커스텀 리소스 API 버전
kind: Jaeger # 쿠버네티스 리소스 종류
metadata:
name: simple-prod # Jaeger 인스턴스 이름
spec:
strategy: production # 배포 전략 (production은 고가용성 모드)
storage:
type: elasticsearch # 스토리지 백엔드 유형 (대용량 트레이스 저장에 적합)
options:
es:
server-urls: http://elasticsearch:9200 # Elasticsearch 서버 URL
# 추가 옵션: 인증, 인덱스 설정 등 가능
ingress:
enabled: true # Jaeger UI에 인그레스 활성화
ui:
options:
dependencies:
menuEnabled: true # UI에서 종속성 메뉴 활성화
tracking:
gaID: UA-000000-0 # Google Analytics ID (필요시)
📌 세 요소의 통합: 완전한 Observability

각 요소는 시스템의 다른 측면을 보여주지만, 함께 사용할 때 가장 강력합니다:
- 메트릭은 문제가 있다는 것을 알려줍니다(무엇이 발생했는지)
- 로그는 문제에 대한 세부 정보를 제공합니다(어떻게 발생했는지)
- 트레이스는 문제가 어디서 발생했는지와 영향받은 서비스를 보여줍니다(어디서 발생했는지)
이 세 가지를 함께 사용하면 문제의 근본 원인을 빠르게 파악하고 해결할 수 있는 완전한 그림을 제공합니다.