이 글에서 얻는 것
- 로그/메트릭/트레이스가 각각 어떤 질문에 답하는지(무엇이/얼마나/왜) 구분할 수 있습니다.
- Spring 기반 서비스에 “운영 가능한 최소 관측성”을 붙이는 베이스라인(지표/로그/traceId)을 설계할 수 있습니다.
- 고카디널리티, 로그 폭발, 액추에이터 노출 같은 운영 함정을 피하는 기준이 생깁니다.
0) 관측성(Observability)은 “데이터로 디버깅”하는 능력
모니터링이 “알람을 받는 것”이라면, 관측성은 “알람 이후 원인을 좁혀가는 것”까지 포함합니다.
실무에서 자주 쓰는 질문 3가지:
- 무엇이 일어났나? → 로그
- 얼마나/어느 정도인가? → 메트릭
- 왜 이런 경로로 실패/지연이 생겼나? → 트레이스
1) 로그: 사건의 맥락을 남긴다(구조 로그 + 상관관계)
1-1) 구조 로그(JSON)와 필드
텍스트 로그는 검색/집계가 어렵습니다. 구조 로그는 운영에서 큰 차이를 만듭니다.
자주 쓰는 필드:
timestamp,level,logger,messagetraceId,spanId(트레이싱과 연결)requestId(클라이언트 요청 식별)userId(가능하면 비식별/마스킹 정책과 함께)
1-2) 로그 레벨과 민감정보
- INFO: 정상 흐름(과도하면 비용 폭발)
- WARN/ERROR: 비정상(알람/트러블슈팅의 중심)
- PII/시크릿은 로그에 남기지 않기(마스킹/필드 제거)
1-3) 수집 파이프라인(개념)
- Filebeat/FluentBit → Logstash/Opensearch(또는 ELK)
여기서 중요한 건 “형식 통일 + 추적 키(traceId)”입니다.
2) 메트릭: 서비스 건강을 숫자로 본다(SLI/SLO)
메트릭은 알람의 기반입니다. 최소한 아래는 갖추는 게 좋습니다.
2-1) Golden Signals / RED
- Latency(레이턴시) / Errors(에러율) / Traffic(처리량) / Saturation(포화)
또는
- Rate(요청 수), Errors(에러 수), Duration(지연)
2-2) Spring에서의 기본 스택
- Micrometer(계측) + Prometheus(스크랩) + Grafana(대시보드)
자주 보는 지표:
- HTTP 요청 레이턴시(p95/p99), 에러율(4xx/5xx)
- JVM/GC, 메모리, 스레드
- DB 커넥션 풀 사용량(HikariCP), 쿼리 시간
주의(실전 함정):
- “label/cardinality”가 폭발하면 Prometheus 비용/성능이 무너집니다(예: userId를 label로 넣기).
3) 트레이스: 분산 호출에서 “왜 느린지”를 찾는다
서비스가 여러 개(또는 외부 API, DB, Redis)를 부르면, 로그/메트릭만으로는 병목 지점을 찾기 어렵습니다.
분산 트레이싱은:
- 요청 경로를 스팬(span)으로 쪼개고,
- 각 구간의 시간을 측정해,
- 어디에서 지연/실패가 났는지 보여줍니다.
구성(개념):
- OpenTelemetry(표준) → Collector → Jaeger/Zipkin/Tempo 등
실무 팁:
- 전체 트레이스를 100% 수집하면 비용이 크므로 샘플링이 필요합니다.
- 샘플링은 “에러/슬로우 요청을 우선”으로 설계하는 편이 효과적입니다.
4) 연결고리: traceId로 로그 ↔ 트레이스를 묶어라
관측성의 핵심은 “한 요청”을 데이터로 엮는 것입니다.
- 트레이스에서 traceId를 보고
- 로그 검색에서 같은 traceId로 필터링하고
- 해당 구간의 메트릭을 함께 보며
원인을 좁혀갑니다.
5) 운영에서 자주 하는 실수
/actuator를 외부에 그대로 노출(정보 노출/공격면 증가) → 네트워크 제한/인증 필요- 로그가 너무 많아 비용이 폭발 → 샘플링/레이트 리밋/레벨 정책 필요
- 메트릭 label에 고카디널리티 값(userId, requestId)을 넣음 → Prometheus가 무너짐
- 트레이스가 없어서 “느린 구간”을 추측으로만 찾음
연습(추천)
- Spring 로그에
traceId가 찍히게 만들고, “한 요청의 로그를 traceId로 묶어” 조회해보기 - p95/p99 레이턴시/에러율/처리량 대시보드(한 화면)를 만들고, 알람 기준을 1개 정의해보기
- 외부 API 호출/DB 쿼리 구간이 트레이스에 스팬으로 보이게 인스트루먼트해보기
💬 댓글