공부/인프라

Grafana 커스텀 대시보드 구축

chanyoun 2026. 4. 17. 16:14
Grafana 커스텀 대시보드 구축

Grafana 커스텀 대시보드 구축

Grafana + Prometheus + Spring Boot Actuator를 함께 사용하고 있었습니다. Grafana에서 Spring Boot를 모니터링할 때 많이 쓰는 JVM (Micrometer) 대시보드를 가져와서 쓰고 있었는데, 이 대시보드는 JVM 내부 메트릭에 집중되어 있어서 정작 궁금한 것들에 대한 답을 주지 못했습니다.

  • 어떤 API가 느린지
  • 5xx 에러가 어디서 발생하는지
  • DB 커넥션 풀은 괜찮은지

이런 질문들에 답하려면 매번 Explore에서 쿼리를 직접 날려야 했고, 문제가 발생했을 때 한눈에 파악이 안 되는 게 가장 불편한 점이었습니다.

그래서 직접 커스텀 대시보드를 만들었습니다.

 

전제 조건

구성 요소상태
Grafana v11.1.0설치 및 접속 가능
PrometheusDocker 네트워크 내부에서 동작
Spring Boot 3.2.xActuator + Micrometer로 /management/prometheus 엔드포인트 노출
Prometheus → Spring Boot 스크래핑설정 완료

 

1. 수집 중인 메트릭 확인

대시보드를 만들려면 Prometheus가 어떤 메트릭을 수집하고 있는지부터 알아야 합니다. Grafana의 Explore에서 확인할 수 있습니다. Explore에 들어가서 데이터소스를 Prometheus로 선택하고, 쿼리 입력 영역 왼쪽의 Metrics browser를 클릭합니다.

1단계 - 메트릭 선택: 수집 중인 전체 메트릭 목록이 나옵니다. 검색창에 http_server_requests를 입력하면 관련 메트릭만 남습니다. 여기서 사용할 메트릭을 하나 클릭합니다.

2단계 - 라벨 선택: 메트릭을 클릭하면, 해당 메트릭에 붙어있는 라벨만 필터링되어 표시됩니다. 예를 들어 http_server_requests_seconds_count를 클릭하면 다음 라벨들이 나타납니다.

 

라벨값 수설명
error3에러 종류
exception3예외 클래스명
instance1서버 인스턴스
job1Prometheus job 이름
method6HTTP 메서드 (GET, POST, PUT 등)
outcome4결과 (SUCCESS, CLIENT_ERROR, SERVER_ERROR 등)
status9HTTP 상태코드 (200, 400, 500 등)
uri100API 엔드포인트 경로

 

괄호 안 숫자는 해당 라벨의 고유 값 개수입니다. uri (100)이면 100개 엔드포인트가 기록되어 있다는 뜻입니다.

3단계 - 라벨 값 선택: 라벨을 클릭하면 실제 값을 선택할 수 있습니다. 예를 들어 status를 선택하면 200, 400, 500 등이 나타나고, 원하는 값을 골라 필터를 만들 수 있습니다.

아래 4. Resulting selector에 완성된 쿼리가 표시됩니다. Use query를 누르면 바로 결과를 볼 수 있습니다.

 

1.1 주요 메트릭 카테고리

Spring Boot Actuator + Micrometer가 자동으로 노출하는 메트릭 중, 대시보드에서 활용할 항목입니다.

카테고리대표 메트릭설명
HTTP 요청http_server_requests_seconds_*요청 수, 응답 시간, 상태 코드
JVM 메모리jvm_memory_used_bytes, jvm_memory_max_bytesHeap/Non-Heap 메모리 사용량
GCjvm_gc_pause_seconds_*GC 일시 정지 시간
JVM 스레드jvm_threads_live_threads, jvm_threads_daemon_threads스레드 수
HikariCPhikaricp_connections_*DB 커넥션 풀 상태
디스크disk_free_bytes, disk_total_bytes디스크 용량
프로세스process_cpu_usage, system_cpu_usageCPU 사용률

테이블의 _* 표기는 편의상 공통 접두사를 묶어 쓴 것입니다. 실제 Prometheus에는 개별 메트릭이 따로 존재합니다. 예를 들어 http_server_requests_seconds_*는 하나의 히스토그램 메트릭에서 자동 생성된 _count(요청 횟수), _sum(응답 시간 합계), _bucket(구간별 분포) 세 개를 의미합니다.

 

2. 대시보드 설계

 

2.1 구성 목표

대시보드를 통해 다음 질문에 답할 수 있어야 합니다.

  1. 어떤 API가 느린가? - 비즈니스 로직 최적화 대상 선정
  2. 에러가 얼마나 발생하는가? - 5xx 에러율 추적
  3. 서버 리소스는 괜찮은가? - JVM 메모리, CPU, 커넥션 풀
  4. DB 커넥션은 부족하지 않은가? - HikariCP 상태 확인

 

2.2 패널 구성

대시보드를 열었을 때 위에서부터 아래로 자연스럽게 훑을 수 있도록 4개 Row로 나눴습니다.

Row 1은 지금 서비스가 괜찮은지 아닌지를 5초 안에 판단하는 요약 줄입니다. Uptime, 5xx 에러율, 평균 응답시간, Heap 사용률, DB 커넥션 사용률, 디스크 사용률 — 6개 숫자가 한 줄에 나란히 있고, 정상이면 초록, 문제면 빨간색입니다. 여기서 빨간색이 보이면 아래 Row로 내려가서 원인을 찾는 흐름입니다.

Row 2는 HTTP 요청에 대한 상세 지표입니다. 느린 엔드포인트 Top 10 테이블, 전체 RPS, 현재 처리 중인 요청 수, 5xx 에러 누적 건수, 에러가 발생한 엔드포인트 테이블, 에러 추이 그래프, 느린 API 응답시간 추이, 상태코드별/method별 요청 분포를 배치했습니다. "어떤 API가 느리고, 어디서 에러가 나는지"를 이 Row에서 전부 확인할 수 있습니다.

Row 3은 JVM 상태입니다. Heap 메모리 추이, GC 일시정지 시간, CPU 사용률, 스레드 수와 상태별 분포, 로그 이벤트 빈도를 넣었습니다. Row 1에서 Heap 사용률이 높으면 여기로 내려와서 메모리 누수인지, GC 문제인지를 확인합니다.

Row 4는 HikariCP 커넥션 풀입니다. Active/Idle/Pending/Max 상태, 커넥션 획득 시간, 사용 시간, 타임아웃 누적을 모아뒀습니다. 느린 API가 커넥션을 오래 물고 있으면 여기서 먼저 징후가 보입니다.

 

3. 대시보드 생성 방법

Grafana UI에서 패널을 하나씩 추가할 수도 있지만, JSON으로 전체 대시보드를 한 번에 import하는 방법이 더 편리합니다.

Dashboards > New > Import dashboard 페이지에서 3가지 방법을 제공합니다.

방법설명
Upload dashboard JSON fileJSON 파일을 드래그 앤 드롭으로 업로드
grafana.com dashboard URL or ID커뮤니티 대시보드 ID를 입력하여 가져오기
Import via dashboard JSON modelJSON을 직접 텍스트로 붙여넣기

커스텀 대시보드는 세 번째 방법을 사용합니다. JSON을 작성해서 텍스트 영역에 붙여넣고 Load 버튼을 누르면 됩니다.

 

3.1 대시보드 JSON 기본 구조

{
  "title": "{서비스명} Spring Boot Overview",
  "tags": ["spring-boot"],
  "timezone": "Asia/Seoul",
  "refresh": "30s",
  "panels": [ ]
}

 

3.2 패널 JSON 구조

각 패널은 아래와 같은 형식을 따릅니다.

{
  "type": "timeseries",
  "title": "Request Rate (req/s)",
  "gridPos": { "h": 8, "w": 8, "x": 0, "y": 1 },
  "datasource": { "type": "prometheus", "uid": "<DATASOURCE_UID>" },
  "targets": [
    {
      "expr": "<PromQL 쿼리>",
      "legendFormat": "{{method}}"
    }
  ],
  "fieldConfig": {
    "defaults": { "unit": "reqps" }
  }
}
  • type: 패널 종류. timeseries(시계열 그래프), stat(숫자 하나), table(테이블) 등
  • gridPos: 대시보드 내 위치와 크기. w는 너비(최대 24), h는 높이
  • targets.expr: 이 패널에서 사용할 PromQL 쿼리
  • datasource.uid: Prometheus 데이터소스의 UID

<DATASOURCE_UID>는 Grafana > Connections > Data Sources에서 Prometheus를 클릭하면 URL에서 확인할 수 있습니다.

 

4. 대시보드 UX 커스터마이징

패널을 다 만들고 나서 기본 설정 그대로 두니까 정상인지 이상인지 구분이 잘 안 됐습니다. 몇 가지 설정을 바꿔서 해결했습니다.

 

4.1 Stat 패널 색상 모드

Grafana Stat 패널의 colorMode는 두 가지가 있습니다.

  • "value": 배경은 어둡게, 숫자 텍스트에만 색상 적용
  • "background": 패널 전체 배경에 색상

colorMode"value"로 설정하고, thresholds에 임계값을 지정하면 값에 따라 텍스트 색상이 바뀝니다.

{
  "options": { "colorMode": "value" },
  "fieldConfig": {
    "defaults": {
      "color": { "mode": "thresholds" },
      "thresholds": {
        "mode": "absolute",
        "steps": [
          { "color": "green", "value": null },
          { "color": "red", "value": 80 }
        ]
      }
    }
  }
}

배경 전체에 색상을 채우려면 "background"로 변경합니다.

{
  "options": { "colorMode": "background" }
}

 

4.2 패널 Description 활용

각 패널의 (i) 아이콘에 마우스를 올리면 설명이 표시됩니다. 여기에 임계값의 의미와 문제 발생 시 확인할 항목을 적어두면, 대시보드 자체가 런북(Runbook) 역할을 합니다.

예시 (5xx 에러율 패널의 Description):

최근 5분간 전체 HTTP 요청 대비 5xx 응답 비율 (rate 기반).

빨간색 (1% 초과): 서버 에러가 유의미하게 발생 중.
- 확인: 아래 '5xx 에러 발생 엔드포인트' 테이블에서 어떤 API인지 확인
- 확인: 서버 로그에서 해당 시간대 Exception 스택트레이스
- 확인: DB 커넥션 풀 고갈, 외부 API 타임아웃 여부
- 확인: 최근 배포 이후 발생했는지 (롤백 필요 여부)

 

4.3 테이블 패널 노이즈 제거

느린 엔드포인트, 5xx 에러 발생 엔드포인트 테이블은 다음과 같이 조정했습니다.

  1. 기본 셀 색상을 transparent로 설정하여 배경과 동일하게 만들고, 빨간색/노란색 행만 눈에 띄게 했습니다.
  2. 5xx 에러 테이블에서 Value가 0인 행을 제거하여, 에러가 실제로 발생한 엔드포인트만 표시합니다.
# 변경 전: 0건인 엔드포인트도 모두 표시
sum(increase(http_server_requests_seconds_count{status=~"5.."}[1h])) by (uri, method, status)

# 변경 후: 에러가 1건 이상인 것만 표시
sum(increase(http_server_requests_seconds_count{status=~"5.."}[1h])) by (uri, method, status) > 0

 

4.4 rate와 increase를 함께 배치

대시보드에는 에러 관련 패널이 두 개 있습니다.

  • 5xx 에러율 (Row 1): rate 기반. 최근 5분간 초당 에러 비율을 계산합니다.
  • 5xx 에러 (Row 2): increase 기반. 최근 1시간 동안 에러가 총 몇 건 발생했는지를 누적합니다.

이 두 패널을 함께 배치하는 이유가 있습니다. 5xx 에러율이 0%인데 5xx 에러가 30건인 상황이 실제로 발생합니다. 30분 전에 에러가 집중 발생했지만 지금은 멈춘 상태라면, rate 기반 지표는 0이 됩니다. 반면 increase 기반 누적 지표는 1시간 동안의 총량을 보여줍니다.

rate는 "지금 에러가 나고 있는가?", increase는 "최근에 에러가 있었는가?"를 보는 것입니다. 둘 다 있어야 상황 파악이 됩니다.

 

완성된 대시보드

스크린샷 2026-04-17.png

Row 1을 훑으면 지금 서비스가 괜찮은지 5초 안에 알 수 있고, 빨간색이 보이면 아래 Row로 내려가서 어떤 API가 느린지, 어디서 에러가 나는지, 커넥션 풀은 괜찮은지를 바로 확인할 수 있습니다. 기존 JVM (Micrometer) 대시보드에서는 매번 Explore를 열어야 했던 질문들에 이제 대시보드 하나로 답할 수 있게 됐습니다.

전체 대시보드 JSON은 첨부된 dashboard.json 파일을 Grafana Import로 가져오면 동일하게 구성할 수 있습니다.

다음 글에서는 Grafana Alerting을 활용해서 임계값 초과 시 Slack으로 자동 알림을 보내는 방법을 다룹니다.

dashboard.json
63.4 kB