본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 22. · 4 Views
Prometheus 메트릭 수집 완벽 가이드
Spring Boot 애플리케이션의 메트릭을 Prometheus로 수집하고 모니터링하는 방법을 배웁니다. Actuator 설정부터 PromQL 쿼리까지 실무에 필요한 모든 내용을 다룹니다.
목차
1. Prometheus 소개
어느 날 김개발 씨는 운영 중인 서비스가 갑자기 느려졌다는 고객 문의를 받았습니다. 하지만 정확히 어디서 문제가 생긴 건지 알 수가 없었습니다.
이때 선배 박시니어 씨가 "Prometheus로 메트릭을 수집하고 있었다면 금방 찾을 수 있었을 텐데"라고 말했습니다.
Prometheus는 시스템의 상태를 숫자로 기록하고 저장하는 모니터링 도구입니다. 마치 병원에서 환자의 체온, 혈압, 맥박을 정기적으로 측정하는 것처럼, Prometheus는 애플리케이션의 CPU 사용률, 메모리, 요청 수 등을 계속해서 수집합니다.
이를 통해 문제가 생기기 전에 미리 감지하고 대응할 수 있습니다.
다음 코드를 살펴봅시다.
# prometheus.yml - Prometheus 설정 파일
global:
scrape_interval: 15s # 15초마다 메트릭 수집
evaluation_interval: 15s # 15초마다 규칙 평가
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus' # 메트릭 수집 경로
static_configs:
- targets: ['localhost:8080'] # 애플리케이션 주소
김개발 씨는 입사 6개월 차 백엔드 개발자입니다. 오늘도 열심히 새로운 API를 개발하고 배포했습니다.
그런데 다음 날 아침, 사용자들로부터 "서비스가 너무 느려요"라는 불만이 쏟아졌습니다. 김개발 씨는 당황했습니다.
코드에는 문제가 없어 보이는데, 도대체 무엇이 문제일까요? 로그를 뒤져봐도 에러는 없습니다.
CPU가 문제인지, 메모리가 부족한 건지, 아니면 데이터베이스가 느린 건지 알 수가 없었습니다. 선배 개발자 박시니어 씨가 다가와 물었습니다.
"모니터링은 설정해 놨어?" 김개발 씨는 고개를 저었습니다. 박시니어 씨가 한숨을 쉬며 말했습니다.
"그럼 문제를 찾기가 어렵죠. Prometheus를 설정해 봅시다." Prometheus란 무엇일까요?
쉽게 비유하자면, Prometheus는 마치 건강검진 센터와 같습니다. 병원에서 정기적으로 건강검진을 받으면 체중, 혈압, 혈당 수치 등을 측정하고 기록합니다.
시간이 지나면서 이런 데이터가 쌓이면, 건강 상태의 변화를 한눈에 파악할 수 있습니다. Prometheus도 마찬가지로 애플리케이션의 "건강 상태"를 지속적으로 측정하고 기록합니다.
모니터링이 없던 시절에는 어땠을까요? 개발자들은 문제가 발생하면 서버에 직접 접속해서 명령어를 입력하며 상태를 확인해야 했습니다.
"지금 CPU 사용률이 얼마지?", "메모리는 충분한가?" 같은 질문에 답하려면 매번 수동으로 확인해야 했습니다. 더 큰 문제는 과거 데이터가 없다는 것이었습니다.
어제 몇 시에 CPU가 급격히 올라갔는지, 일주일 전과 비교해서 메모리 사용량이 늘었는지 알 수 없었습니다. 바로 이런 문제를 해결하기 위해 Prometheus가 등장했습니다.
Prometheus를 사용하면 애플리케이션의 상태를 시계열 데이터로 저장할 수 있습니다. 시계열 데이터란 시간의 흐름에 따라 변하는 값을 기록한 것입니다.
예를 들어 "12시 30분에 CPU 사용률 45%, 12시 31분에 CPU 사용률 47%"처럼 말이죠. 또한 Prometheus는 Pull 방식으로 동작합니다.
즉, 애플리케이션이 메트릭을 보내는 게 아니라, Prometheus가 주기적으로 애플리케이션에 접속해서 메트릭을 가져옵니다. 위의 설정 파일을 한 줄씩 살펴보겠습니다.
먼저 scrape_interval: 15s는 15초마다 메트릭을 수집하겠다는 의미입니다. 이 간격이 너무 짧으면 시스템에 부담이 가고, 너무 길면 실시간으로 문제를 파악하기 어렵습니다.
보통 10~30초 사이로 설정합니다. 다음으로 job_name은 수집 대상의 이름입니다.
여러 애플리케이션을 모니터링할 때 구분하기 위한 라벨입니다. 마지막으로 targets에는 메트릭을 수집할 애플리케이션의 주소를 적습니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 쇼핑몰 서비스를 운영한다고 가정해봅시다.
매일 저녁 9시마다 주문이 폭증하는 패턴을 발견했다면, Prometheus 데이터를 보고 그 시간대에 서버를 미리 증설할 수 있습니다. 또한 특정 API의 응답 시간이 점점 느려지는 추세를 발견하면, 문제가 심각해지기 전에 최적화 작업을 진행할 수 있습니다.
넷플릭스, 에어비앤비 같은 글로벌 기업들도 Prometheus를 적극 활용하고 있습니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 너무 많은 메트릭을 수집하는 것입니다. 모든 것을 측정하려다 보면 저장 공간도 많이 필요하고, 정작 중요한 메트릭을 찾기 어려워집니다.
따라서 정말 필요한 핵심 메트릭만 선별해서 수집해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 도움으로 Prometheus를 설정한 김개발 씨는 이제 대시보드를 보며 문제를 빠르게 찾을 수 있게 되었습니다. "아, 저녁 시간대에 데이터베이스 연결이 부족했군요!" Prometheus를 제대로 활용하면 문제를 사후에 대응하는 것이 아니라, 미리 예방할 수 있습니다.
여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - 중요한 메트릭만 선별해서 수집하세요. 너무 많으면 관리가 어렵습니다.
- scrape_interval은 보통 15초로 설정하며, 시스템 상황에 맞게 조정하세요.
- Grafana와 함께 사용하면 시각화가 훨씬 편리합니다.
2. Actuator 메트릭 노출
Prometheus를 설정했지만, 김개발 씨는 한 가지 문제에 부딪혔습니다. "메트릭을 어디서 가져오지?" Spring Boot 애플리케이션 자체는 메트릭을 외부로 노출하지 않았습니다.
이때 박시니어 씨가 "Spring Boot Actuator를 활성화해야 해요"라고 알려줬습니다.
Spring Boot Actuator는 애플리케이션의 내부 상태를 외부로 공개하는 엔드포인트를 제공하는 라이브러리입니다. 마치 자동차 계기판이 속도, 연료, 엔진 온도를 보여주는 것처럼, Actuator는 애플리케이션의 헬스 체크, 메트릭, 환경 정보 등을 HTTP 엔드포인트로 제공합니다.
간단한 설정만으로 강력한 모니터링 기능을 활성화할 수 있습니다.
다음 코드를 살펴봅시다.
// build.gradle - 의존성 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
}
// application.yml - Actuator 엔드포인트 노출 설정
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus # 노출할 엔드포인트
metrics:
tags:
application: ${spring.application.name} # 모든 메트릭에 애플리케이션 이름 태그 추가
김개발 씨는 Prometheus 서버를 띄웠지만, 막상 Spring Boot 애플리케이션에서 메트릭을 가져오려니 막막했습니다. "어떻게 애플리케이션이 자신의 상태를 알려주지?" 박시니어 씨가 모니터를 가리키며 설명했습니다.
"Spring Boot에는 Actuator라는 강력한 기능이 있어요. 이걸 켜기만 하면 애플리케이션이 자동으로 상태 정보를 노출합니다." Actuator란 정확히 무엇일까요?
쉽게 비유하자면, Actuator는 마치 자동차의 계기판과 같습니다. 운전자는 계기판을 보고 현재 속도가 몇 킬로미터인지, 연료가 얼마나 남았는지, 엔진 온도는 정상인지 한눈에 파악합니다.
Actuator도 마찬가지로 애플리케이션의 현재 상태를 외부에서 확인할 수 있도록 정보를 제공합니다. Actuator가 없던 시절에는 어땠을까요?
개발자들은 애플리케이션의 상태를 확인하려면 직접 로깅 코드를 작성하고, 별도의 API를 만들어야 했습니다. "현재 메모리 사용량은?" 같은 간단한 질문에 답하려면 JMX에 접속하거나 복잡한 명령어를 입력해야 했습니다.
더 큰 문제는 표준이 없다 보니 각 팀마다 다른 방식으로 구현했다는 점입니다. 새 프로젝트에 투입될 때마다 모니터링 방식을 새로 배워야 했습니다.
바로 이런 문제를 해결하기 위해 Spring Boot Actuator가 등장했습니다. Actuator를 사용하면 표준화된 엔드포인트로 애플리케이션 정보에 접근할 수 있습니다.
/actuator/health로 헬스 체크를, /actuator/metrics로 메트릭을, /actuator/env로 환경 변수를 확인할 수 있습니다. 또한 자동 메트릭 수집 기능이 내장되어 있어서, 별도의 코드 작성 없이도 JVM 메모리, HTTP 요청 수, 데이터베이스 커넥션 등 핵심 메트릭이 자동으로 수집됩니다.
위의 설정 파일을 한 줄씩 살펴보겠습니다. 먼저 build.gradle에서 두 가지 의존성을 추가합니다.
spring-boot-starter-actuator는 Actuator 기본 기능을 제공하고, micrometer-registry-prometheus는 Prometheus 형식으로 메트릭을 노출하는 역할을 합니다. 다음으로 application.yml의 exposure.include에서 어떤 엔드포인트를 노출할지 선택합니다.
기본적으로는 보안을 위해 대부분의 엔드포인트가 비활성화되어 있습니다. 마지막으로 metrics.tags에서 모든 메트릭에 공통으로 붙을 태그를 지정합니다.
이렇게 하면 나중에 여러 애플리케이션의 메트릭을 구분하기 쉽습니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 마이크로서비스 아키텍처로 구성된 시스템을 운영한다고 가정해봅시다. 주문 서비스, 결제 서비스, 배송 서비스가 각각 독립적으로 돌아가고 있습니다.
모든 서비스에 Actuator를 설정해두면, Prometheus가 각 서비스의 메트릭을 자동으로 수집합니다. 그리고 Grafana 대시보드에서 전체 시스템의 상태를 한눈에 모니터링할 수 있습니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 프로덕션 환경에서 모든 엔드포인트를 노출하는 것입니다.
exposure.include: '*'처럼 설정하면 편리하지만, 민감한 정보가 외부로 유출될 위험이 있습니다. 따라서 꼭 필요한 엔드포인트만 선택적으로 노출하고, Spring Security로 접근을 제한해야 합니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. Actuator를 설정한 김개발 씨는 브라우저에서 http://localhost:8080/actuator에 접속해봤습니다.
그러자 사용 가능한 엔드포인트 목록이 나타났습니다. "오, 이렇게 간단하게 되는군요!" Actuator를 제대로 설정하면 별도의 코드 작성 없이도 강력한 모니터링 기능을 활용할 수 있습니다.
여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - 프로덕션에서는 필요한 엔드포인트만 선택적으로 노출하세요.
- Spring Security로 Actuator 엔드포인트에 인증을 추가하는 것이 안전합니다.
- micrometer-registry-prometheus 의존성을 꼭 추가해야 Prometheus 형식으로 메트릭이 노출됩니다.
3. prometheus 엔드포인트
김개발 씨는 Actuator를 활성화했지만, Prometheus가 여전히 메트릭을 가져오지 못했습니다. "왜 안 되지?" 박시니어 씨가 화면을 보더니 웃으며 말했습니다.
"아, /actuator/prometheus 엔드포인트를 확인해 보세요. Prometheus 전용 형식으로 메트릭이 노출되어야 합니다."
Prometheus 엔드포인트는 Actuator가 제공하는 특별한 엔드포인트로, Prometheus가 이해할 수 있는 형식으로 메트릭을 제공합니다. 일반적인 /actuator/metrics는 JSON 형식이지만, /actuator/prometheus는 Prometheus 전용 텍스트 형식으로 데이터를 반환합니다.
이 엔드포인트 하나로 수십 가지 메트릭이 자동으로 노출됩니다.
다음 코드를 살펴봅시다.
// application.yml - Prometheus 엔드포인트 활성화
management:
endpoints:
web:
exposure:
include: prometheus # prometheus 엔드포인트 노출
metrics:
export:
prometheus:
enabled: true # Prometheus 메트릭 export 활성화
distribution:
percentiles-histogram:
http.server.requests: true # HTTP 요청 히스토그램 활성화
# 브라우저에서 확인: http://localhost:8080/actuator/prometheus
# 출력 예시:
# jvm_memory_used_bytes{area="heap",id="PS Eden Space"} 123456789.0
# http_server_requests_seconds_count{method="GET",uri="/api/users"} 42.0
김개발 씨는 Actuator를 활성화하고 /actuator/metrics에 접속해봤습니다. JSON 형식으로 메트릭이 잘 나타났습니다.
"좋아, 이제 됐다!" 하지만 Prometheus 설정 파일을 작성하고 실행해도 메트릭이 수집되지 않았습니다. 박시니어 씨가 다가와 물었습니다.
"Prometheus 엔드포인트를 활성화했어요?" 김개발 씨는 고개를 갸우뚱했습니다. "Actuator를 켰는데요?" 박시니어 씨가 설명했습니다.
"Actuator의 일반 메트릭 엔드포인트와 Prometheus 전용 엔드포인트는 다릅니다." Prometheus 엔드포인트란 무엇일까요? 쉽게 비유하자면, Prometheus 엔드포인트는 마치 번역기와 같습니다.
같은 내용이라도 한국어로 말할지, 영어로 말할지에 따라 형식이 다릅니다. /actuator/metrics는 JSON이라는 "한국어"로 메트릭을 제공하고, /actuator/prometheus는 Prometheus 텍스트 형식이라는 "영어"로 제공합니다.
Prometheus는 자신만의 독특한 형식을 사용하기 때문에, 이 전용 엔드포인트가 필요합니다. Prometheus 엔드포인트가 없던 시절에는 어땠을까요?
개발자들은 애플리케이션의 메트릭을 Prometheus 형식으로 수동 변환해야 했습니다. 예를 들어 "현재 JVM 힙 메모리 사용량"이라는 메트릭을 jvm_memory_used_bytes{area="heap"}처럼 Prometheus 형식으로 바꾸는 코드를 직접 작성했습니다.
메트릭이 추가될 때마다 변환 코드도 함께 작성해야 했고, 실수로 형식을 잘못 맞추면 Prometheus가 데이터를 읽지 못했습니다. 바로 이런 문제를 해결하기 위해 Micrometer와 Prometheus 엔드포인트가 등장했습니다.
Micrometer는 다양한 모니터링 시스템을 위한 추상화 계층입니다. 마치 JDBC가 다양한 데이터베이스를 같은 방식으로 사용할 수 있게 해주는 것처럼, Micrometer는 Prometheus, Datadog, New Relic 등 여러 모니터링 시스템을 지원합니다.
Prometheus 엔드포인트는 Micrometer가 수집한 메트릭을 Prometheus 형식으로 자동 변환해서 제공합니다. 또한 히스토그램과 퍼센타일 같은 고급 메트릭도 자동으로 생성해줍니다.
위의 설정 파일을 한 줄씩 살펴보겠습니다. 먼저 exposure.include: prometheus로 Prometheus 엔드포인트를 노출합니다.
다음으로 export.prometheus.enabled: true로 Prometheus 메트릭 내보내기를 활성화합니다. 사실 의존성만 추가하면 기본적으로 활성화되지만, 명시적으로 적어주는 것이 좋습니다.
마지막으로 percentiles-histogram.http.server.requests: true는 HTTP 요청에 대한 히스토그램을 생성합니다. 이렇게 하면 응답 시간의 분포를 분석할 수 있습니다.
실제 현업에서는 어떤 메트릭이 노출될까요? 브라우저에서 /actuator/prometheus에 접속하면 수백 줄의 메트릭이 나타납니다.
jvm_memory_used_bytes는 JVM 메모리 사용량, http_server_requests_seconds_count는 HTTP 요청 수, hikaricp_connections_active는 데이터베이스 커넥션 풀 상태를 보여줍니다. 이 모든 메트릭이 코드 한 줄 작성 없이 자동으로 수집됩니다.
Netflix, Uber 같은 기업들은 이런 메트릭을 기반으로 실시간 알람을 설정하고, 자동 스케일링을 구현합니다. 메트릭 형식을 좀 더 자세히 살펴볼까요?
Prometheus 메트릭은 메트릭명{라벨="값"} 숫자 형식입니다. 예를 들어 http_server_requests_seconds_count{method="GET",uri="/api/users",status="200"} 42.0은 "/api/users" 엔드포인트에 GET 요청이 42번 왔고, 모두 200 상태 코드를 반환했다는 의미입니다.
이런 라벨 덕분에 나중에 PromQL로 복잡한 쿼리를 작성할 수 있습니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 히스토그램을 무분별하게 활성화하는 것입니다. 히스토그램은 매우 유용하지만, 메트릭 수가 급격히 늘어납니다.
하나의 히스토그램은 여러 개의 버킷으로 나뉘어 저장되기 때문입니다. 따라서 정말 필요한 메트릭에만 히스토그램을 적용해야 합니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 /actuator/prometheus에 접속해봤습니다.
화면 가득 메트릭이 나타났습니다. "우와, 이렇게 많은 정보가 자동으로 수집되는군요!" Prometheus 엔드포인트를 제대로 활용하면 애플리케이션의 모든 상태를 실시간으로 파악할 수 있습니다.
여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - /actuator/prometheus에 직접 접속해보면 어떤 메트릭이 수집되는지 확인할 수 있습니다.
- 히스토그램은 저장 공간을 많이 차지하므로 필요한 메트릭에만 적용하세요.
- Micrometer 덕분에 나중에 Datadog 등 다른 모니터링 시스템으로 쉽게 전환할 수 있습니다.
4. Prometheus 설정
이제 애플리케이션에서 메트릭을 노출했으니, Prometheus가 이를 수집하도록 설정할 차례입니다. 김개발 씨는 Prometheus 설정 파일을 작성하려다가 막막해졌습니다.
"target은 뭐고, job은 또 뭐지?" 박시니어 씨가 "차근차근 설명해 드릴게요"라고 말했습니다.
Prometheus 설정은 어디서 메트릭을 수집할지, 얼마나 자주 수집할지를 정의하는 과정입니다. prometheus.yml 파일에 수집 대상(target)과 수집 간격(scrape_interval)을 지정하면, Prometheus가 자동으로 주기적으로 메트릭을 가져옵니다.
마치 신문 배달원이 정해진 시간에 정해진 집을 방문하는 것과 같습니다.
다음 코드를 살펴봅시다.
# prometheus.yml - 실무에서 사용하는 설정 예시
global:
scrape_interval: 15s # 기본 수집 간격
evaluation_interval: 15s # 규칙 평가 간격
external_labels:
cluster: 'production' # 모든 메트릭에 붙을 라벨
region: 'ap-northeast-2'
scrape_configs:
- job_name: 'user-service' # 작업 이름
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['user-service:8080'] # 수집 대상
labels:
team: 'backend' # 커스텀 라벨 추가
- job_name: 'order-service'
scrape_interval: 10s # 이 작업만 10초 간격
static_configs:
- targets: ['order-service:8081']
김개발 씨는 Prometheus를 다운로드하고 실행했지만, 아무 메트릭도 수집되지 않았습니다. "어라, 왜 안 되지?" 설정 파일을 열어보니 기본 예제만 들어있었습니다.
박시니어 씨가 말했습니다. "Prometheus는 기본적으로 자기 자신만 모니터링해요.
우리 애플리케이션을 모니터링하려면 설정에 추가해야 합니다." Prometheus 설정이란 정확히 무엇일까요? 쉽게 비유하자면, Prometheus 설정은 마치 우체부의 배달 경로표와 같습니다.
우체부는 아침에 출근하면 오늘 어느 집에 우편물을 배달할지, 몇 시에 방문할지 적힌 경로표를 받습니다. Prometheus도 마찬가지로 설정 파일을 보고 "15초마다 user-service:8080에 접속해서 메트릭을 가져와야겠구나"라고 판단합니다.
설정이 복잡했던 시절에는 어땠을까요? 초기 모니터링 시스템들은 각 애플리케이션이 직접 메트릭을 보내야 했습니다.
이를 Push 방식이라고 합니다. 애플리케이션에서 주기적으로 "지금 CPU 70%야"라고 모니터링 서버에 전송했습니다.
하지만 이 방식은 문제가 많았습니다. 네트워크가 끊기면 메트릭이 유실되고, 애플리케이션이 다운되면 알림조차 보낼 수 없었습니다.
게다가 애플리케이션마다 전송 로직을 구현해야 해서 코드가 복잡해졌습니다. 바로 이런 문제를 해결하기 위해 Prometheus는 Pull 방식을 선택했습니다.
Pull 방식에서는 Prometheus가 능동적으로 애플리케이션에 접속해서 메트릭을 가져옵니다. 애플리케이션은 그저 엔드포인트만 열어두면 됩니다.
이렇게 하면 네트워크가 일시적으로 끊겨도 나중에 다시 수집할 수 있고, 애플리케이션이 다운되었는지도 Prometheus가 감지할 수 있습니다. 또한 동적 서비스 디스커버리를 지원해서, Kubernetes 같은 환경에서 자동으로 새로운 서비스를 찾아 모니터링할 수 있습니다.
위의 설정 파일을 한 줄씩 살펴보겠습니다. 먼저 global 섹션은 모든 작업에 공통으로 적용되는 설정입니다.
scrape_interval은 얼마나 자주 메트릭을 수집할지 정합니다. 15초는 실시간성과 부하의 균형을 맞춘 값입니다.
external_labels는 모든 메트릭에 자동으로 붙는 라벨로, 여러 Prometheus 서버를 운영할 때 구분하기 좋습니다. 다음으로 scrape_configs는 실제 수집 작업을 정의합니다.
job_name은 이 작업의 이름이고, 메트릭에 job="user-service"처럼 라벨로 추가됩니다. targets는 실제 수집할 주소입니다.
실제 현업에서는 어떻게 활용할까요? 마이크로서비스 환경에서는 수십 개의 서비스가 동시에 돌아갑니다.
각 서비스마다 job_name을 다르게 지정하면, 나중에 PromQL 쿼리로 특정 서비스의 메트릭만 필터링할 수 있습니다. 예를 들어 http_server_requests_seconds_count{job="order-service"}처럼 주문 서비스의 요청 수만 조회할 수 있습니다.
또한 Kubernetes를 사용한다면 kubernetes_sd_configs로 자동 디스커버리를 설정해서, 새로운 파드가 생성될 때마다 자동으로 모니터링에 추가됩니다. 라벨을 활용하는 방법도 중요합니다.
labels 필드로 커스텀 라벨을 추가하면 메트릭을 더 세밀하게 분류할 수 있습니다. 예를 들어 team: 'backend' 라벨을 추가하면, 나중에 "백엔드 팀이 담당하는 모든 서비스의 평균 응답 시간"을 한 번의 쿼리로 조회할 수 있습니다.
실제로 Google, Amazon 같은 대기업에서는 수천 개의 서비스를 모니터링하기 위해 정교한 라벨 전략을 사용합니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 scrape_interval을 너무 짧게 설정하는 것입니다. "1초마다 수집하면 더 정확하겠지?"라고 생각하지만, 실제로는 Prometheus 서버와 애플리케이션 모두에 큰 부담이 됩니다.
대부분의 경우 10~30초 간격이면 충분합니다. 또한 라벨을 너무 많이 추가하면 카디널리티가 높아져서 성능 문제가 발생할 수 있습니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 도움으로 설정 파일을 작성한 김개발 씨는 Prometheus를 재시작했습니다.
잠시 후 Prometheus UI에 접속하니 메트릭이 수집되고 있었습니다. "드디어 됐다!" Prometheus 설정을 제대로 작성하면 수십 개의 서비스를 자동으로 모니터링할 수 있습니다.
여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - scrape_interval은 보통 10~30초로 설정하며, 중요한 서비스는 더 짧게 설정할 수 있습니다.
- Kubernetes 환경에서는 kubernetes_sd_configs를 사용해 자동 디스커버리를 설정하세요.
- 라벨은 유용하지만, 너무 많으면 성능 문제가 생기니 신중하게 추가하세요.
5. PromQL 기초
메트릭이 잘 수집되는 걸 확인한 김개발 씨는 이제 데이터를 분석하고 싶었습니다. "CPU 사용률이 80% 넘는 시점을 찾고 싶은데..." 박시니어 씨가 "PromQL을 배워야 합니다.
Prometheus의 쿼리 언어죠"라고 말했습니다.
PromQL(Prometheus Query Language)은 Prometheus에서 메트릭을 조회하고 분석하는 전용 쿼리 언어입니다. SQL이 데이터베이스를 조회하는 언어라면, PromQL은 시계열 데이터를 조회하는 언어입니다.
간단한 메트릭 이름만 입력해도 되고, 복잡한 수식으로 계산된 값도 구할 수 있습니다. 마치 엑셀 수식처럼 강력하지만, 시계열 데이터에 특화되어 있습니다.
다음 코드를 살펴봅시다.
# PromQL 기본 쿼리 예시
# 1. 단순 메트릭 조회 - 현재 힙 메모리 사용량
jvm_memory_used_bytes{area="heap"}
# 2. 라벨 필터링 - GET 요청만 조회
http_server_requests_seconds_count{method="GET"}
# 3. 범위 벡터 - 최근 5분간 데이터
http_server_requests_seconds_count{method="GET"}[5m]
# 4. 집계 함수 - 모든 인스턴스의 합계
sum(http_server_requests_seconds_count)
# 5. 비율 계산 - 초당 요청 수 (QPS)
rate(http_server_requests_seconds_count[5m])
# 6. 복합 쿼리 - 5분간 평균 응답 시간
rate(http_server_requests_seconds_sum[5m]) / rate(http_server_requests_seconds_count[5m])
김개발 씨는 Prometheus UI에 접속해서 Graph 탭을 열었습니다. 검색창에 메트릭 이름을 입력하니 그래프가 나타났습니다.
"오, 신기하네!" 하지만 "최근 5분간 평균 응답 시간"을 구하려니 막막했습니다. 박시니어 씨가 화면을 가리키며 말했습니다.
"PromQL을 배우면 원하는 모든 계산을 할 수 있어요. SQL처럼 강력하지만, 시계열 데이터에 최적화되어 있습니다." PromQL이란 정확히 무엇일까요?
쉽게 비유하자면, PromQL은 마치 엑셀의 수식과 같습니다. 엑셀에서 =SUM(A1:A10)처럼 셀의 합계를 구하듯이, PromQL에서는 sum(http_server_requests_seconds_count)처럼 메트릭의 합계를 구합니다.
하지만 PromQL은 시간이라는 차원이 추가되어 있어서, "최근 5분간", "1시간 전" 같은 시간 조건을 쉽게 표현할 수 있습니다. PromQL이 없던 시절에는 어땠을까요?
개발자들은 Prometheus가 저장한 원시 데이터를 그대로 보거나, 복잡한 외부 스크립트를 작성해서 데이터를 처리해야 했습니다. "CPU 사용률이 80% 넘는 시점"을 찾으려면 수천 개의 데이터 포인트를 하나씩 확인해야 했습니다.
더 큰 문제는 실시간 계산이 어렵다는 점이었습니다. 알람을 설정하려면 별도의 모니터링 도구를 연동해야 했습니다.
바로 이런 문제를 해결하기 위해 PromQL이 등장했습니다. PromQL을 사용하면 실시간 쿼리로 복잡한 계산을 즉시 수행할 수 있습니다.
"최근 5분간 초당 요청 수"를 구하려면 rate(http_server_requests_seconds_count[5m])처럼 한 줄이면 됩니다. 또한 라벨 기반 필터링으로 원하는 메트릭만 선택적으로 조회할 수 있습니다.
예를 들어 {method="GET",status="200"}처럼 조건을 지정하면, GET 요청 중 성공한 것만 조회됩니다. 위의 쿼리 예시를 하나씩 살펴보겠습니다.
첫 번째 쿼리 jvm_memory_used_bytes{area="heap"}는 가장 기본적인 형태입니다. 메트릭 이름과 라벨을 지정하면 현재 값을 반환합니다.
두 번째 쿼리는 라벨 필터링의 예시입니다. 중괄호 안에 여러 조건을 넣을 수 있고, 쉼표로 구분합니다.
세 번째 쿼리의 [5m]는 범위 벡터라고 부르며, 최근 5분간의 모든 데이터 포인트를 반환합니다. 이것만으로는 그래프를 그릴 수 없고, 보통 rate() 같은 함수와 함께 사용됩니다.
네 번째 쿼리의 sum()은 집계 함수입니다. 여러 인스턴스에서 수집된 메트릭을 하나로 합칩니다.
예를 들어 서버가 3대라면, 각 서버의 요청 수를 모두 더한 값을 반환합니다. 다섯 번째 쿼리의 rate()는 초당 증가율을 계산합니다.
카운터 메트릭에 사용하며, "최근 5분간 초당 평균 몇 번 증가했는지"를 구합니다. 여섯 번째 쿼리는 좀 더 복잡합니다.
응답 시간의 합계를 요청 수로 나누면 평균 응답 시간이 나옵니다. 이처럼 PromQL은 수학 연산자를 지원해서 복잡한 계산도 가능합니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 "5분 내에 에러율이 5%를 넘으면 알람"이라는 규칙을 설정한다고 가정해봅시다.
PromQL로 sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m])) / sum(rate(http_server_requests_seconds_count[5m])) > 0.05처럼 작성하면 됩니다. 이 쿼리는 5xx 상태 코드의 비율을 계산하고, 5%를 넘는지 확인합니다.
이런 쿼리를 Alertmanager에 등록하면 자동으로 알람이 발생합니다. 더 고급 기능도 있습니다.
predict_linear()는 과거 데이터를 기반으로 미래를 예측합니다. 예를 들어 "현재 추세대로라면 4시간 후 디스크가 가득 찰 것"처럼 미리 알람을 보낼 수 있습니다.
또한 histogram_quantile()로 퍼센타일을 계산해서 "95%의 요청이 200ms 이내에 응답"처럼 정교한 SLA를 측정할 수 있습니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 rate()와 irate()를 혼동하는 것입니다. rate()는 지정한 시간 범위의 평균 증가율이고, irate()는 마지막 두 데이터 포인트만 사용한 순간 증가율입니다.
알람에는 rate()가 더 안정적이고, 실시간 그래프에는 irate()가 더 민감하게 반응합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨는 직접 쿼리를 작성해봤습니다. "오, 평균 응답 시간이 점점 늘어나고 있네요.
최적화가 필요하겠어요!" PromQL을 제대로 활용하면 데이터에서 인사이트를 빠르게 찾아낼 수 있습니다. 여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - rate()는 평균, irate()는 순간 증가율입니다. 알람에는 rate()가 더 적합합니다.
- 범위 벡터 [5m]는 함수와 함께 사용해야 하며, 단독으로는 그래프를 그릴 수 없습니다.
- Prometheus UI의 Graph 탭에서 직접 쿼리를 실행하며 연습하세요.
6. 메트릭 타입
PromQL을 연습하던 김개발 씨는 이상한 점을 발견했습니다. 어떤 메트릭은 _total로 끝나고, 어떤 것은 _bucket이 붙어있었습니다.
"이게 뭐지?" 박시니어 씨가 "Prometheus에는 네 가지 메트릭 타입이 있어요"라고 설명했습니다.
Prometheus는 Counter, Gauge, Histogram, Summary라는 네 가지 메트릭 타입을 제공합니다. 각 타입은 특정 종류의 데이터를 측정하는 데 최적화되어 있습니다.
Counter는 계속 증가하는 값, Gauge는 오르락내리락하는 값, Histogram과 Summary는 분포를 측정합니다. 올바른 타입을 선택하는 것이 정확한 모니터링의 시작입니다.
다음 코드를 살펴봅시다.
// Spring Boot에서 커스텀 메트릭 등록 예시
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;
@Service
public class CustomMetricsService {
private final Counter orderCounter; // Counter: 주문 횟수
private final MeterRegistry registry;
private int activeUsers = 0; // Gauge: 현재 활성 사용자 수
public CustomMetricsService(MeterRegistry registry) {
this.registry = registry;
// Counter 등록 - 계속 증가하는 값
this.orderCounter = Counter.builder("orders_total")
.description("Total number of orders")
.tag("type", "online")
.register(registry);
// Gauge 등록 - 변동하는 값
Gauge.builder("active_users", this, CustomMetricsService::getActiveUsers)
.description("Current active users")
.register(registry);
}
public void recordOrder() {
orderCounter.increment(); // 주문할 때마다 증가
}
private int getActiveUsers() {
return activeUsers; // 현재 값 반환
}
}
김개발 씨는 Prometheus UI에서 메트릭 목록을 보다가 혼란스러워졌습니다. http_server_requests_seconds_count, jvm_memory_used_bytes, http_server_requests_seconds_bucket처럼 이름 패턴이 제각각이었습니다.
박시니어 씨가 화이트보드에 그림을 그리며 설명했습니다. "Prometheus에는 네 가지 메트릭 타입이 있어요.
각각 다른 종류의 데이터를 측정하는 데 사용됩니다." 메트릭 타입이란 무엇일까요? 쉽게 비유하자면, 메트릭 타입은 마치 온도계, 저울, 스톱워치의 차이와 같습니다.
온도계로는 온도를 재고, 저울로는 무게를 재고, 스톱워치로는 시간을 잽니다. 각 도구는 특정 측정에 최적화되어 있습니다.
메트릭 타입도 마찬가지로, 측정하려는 데이터의 특성에 따라 적절한 타입을 선택해야 합니다. 메트릭 타입이 없던 시절에는 어땠을까요?
초기 모니터링 시스템들은 모든 데이터를 단순 숫자로 저장했습니다. "현재 주문 수: 1523"처럼 말이죠.
하지만 이 숫자가 누적값인지, 현재 진행 중인 주문 수인지 구분할 수 없었습니다. 평균을 구하려면 수동으로 계산해야 했고, 퍼센타일 같은 고급 통계는 아예 불가능했습니다.
데이터의 의미를 파악하기 어려워서 잘못된 분석으로 이어지기 쉬었습니다. 바로 이런 문제를 해결하기 위해 메트릭 타입이 도입되었습니다.
첫 번째 타입은 Counter입니다. Counter는 절대 감소하지 않고 계속 증가하는 값을 측정합니다.
예를 들어 "총 주문 수", "총 에러 발생 횟수"처럼 누적되는 값입니다. PromQL의 rate()나 increase() 함수와 함께 사용하면 "초당 주문 수", "시간당 에러 증가량" 같은 변화율을 계산할 수 있습니다.
Counter는 애플리케이션이 재시작되면 0으로 리셋되지만, Prometheus는 이를 자동으로 감지하고 처리합니다. 두 번째 타입은 Gauge입니다.
Gauge는 오르락내리락하는 값을 측정합니다. 예를 들어 "현재 메모리 사용량", "활성 사용자 수", "현재 온도"처럼 언제든 증가하거나 감소할 수 있는 값입니다.
Gauge는 현재 상태를 나타내므로 rate()를 사용하면 안 됩니다. 대신 avg(), max(), min() 같은 집계 함수를 사용합니다.
세 번째 타입은 Histogram입니다. Histogram은 값의 분포를 측정합니다.
예를 들어 "API 응답 시간"을 측정할 때, 단순히 평균만 알면 부족합니다. "대부분의 요청은 100ms인데, 일부가 10초 걸려서 평균이 1초"일 수도 있습니다.
Histogram은 데이터를 여러 버킷으로 나누어 저장합니다. "100ms 이하: 80건, 500ms 이하: 15건, 1초 이하: 5건"처럼 말이죠.
이를 기반으로 퍼센타일을 계산할 수 있습니다. 네 번째 타입은 Summary입니다.
Summary도 Histogram처럼 분포를 측정하지만, 클라이언트 측에서 퍼센타일을 직접 계산합니다. Histogram은 Prometheus 서버에서 계산하므로 여러 인스턴스를 합산할 수 있지만, Summary는 각 인스턴스별로 계산되어 합산할 수 없습니다.
대신 정확도가 높고 서버 부하가 적습니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 Counter.builder()로 Counter를 생성합니다. orders_total이라는 이름으로 등록되며, Prometheus에서는 자동으로 _total 접미사가 붙습니다.
tag()로 라벨을 추가할 수 있습니다. 다음으로 Gauge.builder()로 Gauge를 생성합니다.
Gauge는 값을 제공하는 함수를 인자로 받습니다. Prometheus가 수집할 때마다 이 함수를 호출해서 현재 값을 가져갑니다.
실제 현업에서는 어떻게 선택할까요? "총 요청 수"는 Counter, "현재 CPU 사용률"은 Gauge, "API 응답 시간 분포"는 Histogram을 사용합니다.
헷갈린다면 이렇게 생각하세요. "리셋하면 의미를 잃는가?"라는 질문에 "예"라면 Counter, "아니오"라면 Gauge입니다.
"분포를 알아야 하는가?"라는 질문에 "예"라면 Histogram이나 Summary입니다. Histogram과 Summary 중 어떤 것을 선택할까요?
대부분의 경우 Histogram이 더 유연합니다. 여러 인스턴스의 데이터를 합산할 수 있고, 나중에 원하는 퍼센타일을 자유롭게 계산할 수 있습니다.
Summary는 정확한 퍼센타일이 필요하지만 인스턴스별로 분리된 경우에 사용합니다. Spring Boot Actuator는 기본적으로 Histogram을 사용합니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 Counter에 rate() 없이 직접 사용하는 것입니다.
Counter는 누적값이므로 계속 증가합니다. 그래프로 그리면 오른쪽으로만 올라가는 직선이 됩니다.
의미 있는 정보를 얻으려면 rate()로 변화율을 계산해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다. "아, 그래서 _total, _bytes, _bucket 같은 접미사가 붙는 거군요!" 메트릭 타입을 제대로 이해하면 올바른 메트릭을 수집하고 정확하게 분석할 수 있습니다.
여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - Counter는 rate()와 함께, Gauge는 avg()나 max()와 함께 사용하세요.
- API 응답 시간처럼 분포가 중요한 경우 Histogram을 사용하세요.
- 메트릭 이름에 _total, _bytes 같은 접미사로 타입을 명확히 표현하면 좋습니다.
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
관찰 가능한 마이크로서비스 완벽 가이드
마이크로서비스 환경에서 시스템의 상태를 실시간으로 관찰하고 모니터링하는 방법을 배웁니다. Resilience4j, Zipkin, Prometheus, Grafana, EFK 스택을 활용하여 안정적이고 관찰 가능한 시스템을 구축하는 실전 가이드입니다.
EFK 스택 로깅 완벽 가이드
마이크로서비스 환경에서 로그를 효과적으로 수집하고 분석하는 EFK 스택(Elasticsearch, Fluentd, Kibana)의 핵심 개념과 실전 활용법을 초급 개발자도 쉽게 이해할 수 있도록 정리한 가이드입니다.
Grafana 대시보드 완벽 가이드
실시간 모니터링의 핵심, Grafana 대시보드를 처음부터 끝까지 배워봅니다. Prometheus 연동부터 알람 설정까지, 초급 개발자도 쉽게 따라할 수 있는 실전 가이드입니다.
스프링 관찰 가능성 완벽 가이드
Spring Boot 3.x의 Observation API를 활용한 애플리케이션 모니터링과 추적 방법을 초급 개발자 눈높이에서 쉽게 설명합니다. 실무에서 바로 적용할 수 있는 메트릭 수집과 분산 추적 기법을 다룹니다.
Zipkin으로 추적 시각화 완벽 가이드
마이크로서비스 환경에서 분산 추적을 시각화하는 Zipkin의 핵심 개념과 활용 방법을 초급자도 쉽게 이해할 수 있도록 실무 스토리로 풀어낸 가이드입니다. Docker 실행부터 UI 분석까지 단계별로 배웁니다.