Contents
see List운영 장애는 로그만으로 해결되지 않는다
Spring Boot API가 느려지거나 오류율이 올라갈 때 가장 먼저 필요한 것은 현재 상태를 수치로 확인할 수 있는 관측성입니다. 애플리케이션 로그에는 예외가 남지만, 어떤 엔드포인트가 느린지, 데이터베이스 연결 풀이 고갈되는지, JVM 메모리가 증가하는지, 외부 API 호출이 병목인지까지 즉시 보여 주지는 않습니다. Spring Boot Actuator와 Micrometer를 함께 구성하면 헬스 상태, HTTP 요청 시간, JVM·프로세스·커넥션 풀 지표를 일관된 방식으로 수집할 수 있습니다.
중요한 원칙은 모든 값을 수집하는 것이 아니라 장애 판단에 쓰이는 지표를 먼저 정하는 것입니다. API 서비스에서는 요청 수, 4xx·5xx 오류율, p95·p99 응답 시간, 활성 요청 수, JVM 힙 사용량, GC 시간, DB 커넥션 풀의 active·pending 수가 기본입니다. 이 값들을 배포 전후와 평상시 기준선으로 비교할 수 있어야 원인을 추측이 아닌 증거로 좁힐 수 있습니다.
의존성과 노출 범위를 최소로 시작하기
Spring Boot 프로젝트에는 Actuator 의존성을 추가하고, 운영 환경에서 필요한 엔드포인트만 공개합니다. health는 로드밸런서 또는 오케스트레이터의 상태 확인에 쓰고, prometheus는 모니터링 서버가 수집하도록 제한합니다. env, configprops, heapdump 같은 정보성 또는 민감한 엔드포인트를 인터넷에 직접 열면 설정과 비밀값 노출 위험이 생기므로 기본 공개 목록에 넣지 않는 편이 안전합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>의존성을 추가한 다음 설정 파일에서 노출 목록과 health 상세 정보 정책을 지정합니다. 내부 네트워크에서도 health 상세 정보는 운영 담당자에게만 필요할 수 있으므로, 공개 API와 관리 API의 네트워크 경로를 분리하는 것이 좋습니다. Kubernetes를 사용한다면 liveness와 readiness를 서로 다른 상태로 확인해 일시적인 외부 의존성 장애가 곧바로 프로세스 재시작으로 이어지지 않게 설계합니다.
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
endpoint:
health:
probes:
enabled: true
show-details: when_authorized
metrics:
tags:
application: order-api응답 시간은 평균 대신 백분위로 판단하기
평균 응답 시간은 일부 느린 요청을 숨기기 쉽습니다. 대부분의 요청이 100ms여도 일부 요청이 수 초씩 걸리면 평균만 보고는 사용자가 체감하는 장애를 놓칠 수 있습니다. 따라서 API별 p95와 p99 응답 시간, 요청 수, 서버 오류 수를 같이 봐야 합니다. p95는 요청 100건 중 느린 5건의 경계이고, p99는 더 드문 지연을 확인하는 지표입니다.
태그 설계도 중요합니다. URI, HTTP 메서드, 상태 코드는 유용하지만 사용자 ID, 주문번호, 전체 쿼리 문자열처럼 값의 종류가 끝없이 늘어나는 데이터를 태그로 넣으면 시계열 수가 폭증합니다. 이를 고카디널리티 문제라고 합니다. 경로 변수는 가능한 한 템플릿 형태로 정규화하고, 특정 고객이나 주문의 추적은 로그와 trace ID로 분리해야 모니터링 시스템의 비용과 조회 성능을 지킬 수 있습니다.
management:
metrics:
distribution:
percentiles-histogram:
http.server.requests: true
percentiles:
http.server.requests: 0.5,0.95,0.99
slo:
http.server.requests: 100ms,300ms,1s,3s비즈니스 지표와 기술 지표를 연결하기
CPU와 메모리만으로는 실제 영향을 판단하기 어렵습니다. 주문 생성, 결제 승인, 회원 가입처럼 서비스의 핵심 작업에는 성공·실패·처리 시간을 직접 기록하는 것이 효과적입니다. Micrometer의 Counter와 Timer는 Prometheus 같은 백엔드로 전송할 수 있고, 대시보드에서는 기술 지표와 같은 시간 축으로 비교할 수 있습니다. 결제 실패 증가와 외부 결제 API 지연이 동시에 나타나는지, 주문 생성 감소와 DB 풀 대기가 연결되는지 확인할 수 있습니다.
@Service
public class PaymentService {
private final Counter paymentFailed;
private final Timer paymentTimer;
public PaymentService(MeterRegistry registry) {
paymentFailed = Counter.builder("payment.failed").register(registry);
paymentTimer = Timer.builder("payment.process").register(registry);
}
public PaymentResult approve(PaymentCommand command) {
return paymentTimer.record(() -> {
try { return requestApproval(command); }
catch (PaymentException e) { paymentFailed.increment(); throw e; }
});
}
}이 지표에는 결제수단 코드나 개별 사용자 식별자처럼 종류가 급증하는 값을 태그로 추가하지 않습니다. 결제 성공 여부, 처리 채널처럼 제한된 집합만 사용하고, 세부 오류 원인은 구조화 로그에 errorCode와 traceId를 남겨 추적합니다. 요청 시작 지점에서 상관관계 ID를 만들고 외부 HTTP 호출에도 전달하면 여러 서비스에 걸친 실패 경로를 훨씬 빠르게 재현할 수 있습니다.
알림은 증상과 영향 기준으로 설정하기
알림은 지표가 조금 변했다고 모두 보내는 방식보다, 사용자가 영향을 받을 가능성이 높은 조합을 기준으로 만들어야 합니다. 예를 들어 5분 동안 5xx 비율이 2%를 넘고 요청 수가 일정 수준 이상일 때 알림을 보냅니다. 지연 알림도 p95가 1초를 넘는 상태가 10분 이상 지속될 때 발생시키면 일시적인 스파이크로 인한 불필요한 호출을 줄일 수 있습니다. DB 커넥션 pending 증가, JVM GC 시간 급증, 외부 의존성 실패율 같은 선행 신호는 경고 단계로 분리합니다.
대시보드와 알림에는 배포 버전, 인스턴스, 리전 또는 환경 같은 공통 태그를 남겨야 합니다. 배포 직후 오류율이 상승했다면 버전별 비교로 롤백 여부를 빠르게 판단할 수 있습니다. 단, 인스턴스별 세부 지표는 원인 분석용이고 서비스 전체 경보는 합산 지표를 기본으로 해야 한 대의 교체나 재시작에 과도하게 반응하지 않습니다.
운영 적용 체크리스트
- health, prometheus, metrics만 필요한 관리 경로에서 노출했는지 확인합니다.
- p95·p99 응답 시간과 5xx 오류율을 엔드포인트별로 함께 확인합니다.
- 사용자 ID·주문번호·원문 URL처럼 카디널리티가 높은 값을 메트릭 태그에서 제외합니다.
- DB 풀, JVM 힙, GC, 외부 호출 실패율을 같은 대시보드에서 비교합니다.
- 핵심 업무의 성공·실패·처리 시간을 별도 비즈니스 지표로 기록합니다.
- 알림 조건, 담당자, 확인 절차를 문서화하고 정기적으로 실제 장애 시나리오로 점검합니다.
관측성은 도구 설치로 끝나지 않습니다. 서비스에 중요한 요청과 정상 범위를 정의하고, 지표·로그·추적 정보를 같은 사건에 연결해야 장애 대응 시간이 줄어듭니다. 작은 API부터 기준선과 알림을 만들고 배포마다 검증하는 운영 절차로 확장하는 것이 가장 안전한 시작입니다.
spring
| No | 작성일 | Title |
|---|---|---|
| 3265 | 2026. 07. 21. | Spring Boot API 장애 원인 빨리 찾기: Actuator와 Micrometer 관측성 구성 가이드 |
| 3238 | 2026. 07. 13. | Spring Boot 안정적인 외부 API 연동: WebClient·Circuit Breaker·Retry를 함께 운영하는 실전 가이드 |
| 3182 | 2026. 07. 04. | Spring Boot 무중단 배포를 위한 Graceful Shutdown과 Readiness Probe 설정 |
| 3137 | 2026. 06. 26. | Spring Security API 권한 설계: 공개 엔드포인트와 관리자 기능을 분리하는 실전 기준 |
| 3081 | 2026. 06. 18. | Spring Boot API 장애 추적을 위한 요청 ID와 관측 로그 설계 |
| 2992 | 2026. 06. 10. | Spring Boot 무중단 배포를 위한 준비 상태 점검과 종료 처리 설계 |
| 2935 | 2026. 06. 02. | Spring Boot Redis 캐시 운영 가이드: TTL, 무효화, 캐시 스탬피드 방지 설계 |
| 2881 | 2026. 05. 25. | Spring API 오류 응답 표준화: ProblemDetail과 @RestControllerAdvice 실전 가이드 |
| 2813 | 2026. 05. 17. | Spring Boot 무중단 배포를 위한 Readiness·Liveness·Graceful Shutdown 실전 가이드 |
| 2611 | 2026. 04. 25. | Spring Security 7 Passkey(패스키) 완전 가이드: WebAuthn 기반 비밀번호 없는 인증 구현 |