infra
Platform

모듈 맵

[Infra Ops] 애플리케이션 성능 모니터링과 대시보드 구성

0 / 52 완료

펼치기
0 / 52 완료0%

Infra-ops · 45 / 52

[Infra Ops] 애플리케이션 성능 모니터링과 대시보드 구성

Pinpoint/Dynatrace APM 개념, JMX Exporter로 Prometheus 연동, Grafana 대시보드 구성, 알람 설정까지 — 장애를 사전에 감지하는 모니터링 실무

🚨INCIDENT ALERT
HIGH

서비스가 왜 느린지 팀에서 원인을 못 찾고 있습니다. CPU는 70%대, 메모리도 여유 있는데 응답 시간이 2~3초가 나옵니다. topfree로는 더 이상 파악이 안 됩니다.

APM(Application Performance Monitoring)이 있었다면 "특정 API의 DB 쿼리가 1.8초"라고 바로 짚어줬을 것입니다. 그리고 Prometheus + Grafana가 있었다면 JVM Heap이 배포 직후부터 서서히 올라가는 트렌드를 그래프로 볼 수 있었을 것입니다. 이 모듈은 그 관찰력을 실무에서 구현하는 방법을 다룹니다.

이번 챕터에서 배울 것
  • 1APM과 인프라 모니터링의 차이를 설명하고 어떤 상황에 APM이 필요한지 판단할 수 있다
  • 2Pinpoint, Jennifer, Dynatrace의 특징과 사용 환경을 구분할 수 있다
  • 3JMX Exporter를 Tomcat에 붙여 Prometheus가 JVM 메트릭을 수집하도록 구성할 수 있다
  • 4Prometheus scrape_config를 작성하고 target 상태를 확인할 수 있다
  • 5Grafana에서 JVM Heap/GC 패널을 구성하고 alert rule을 설정할 수 있다

APM 개념

💡개념

인프라 모니터링만으로는 부족한 이유

인프라 모니터링(CPU, 메모리, 디스크)은 "서버가 힘들다"는 신호는 줍니다. 하지만 "왜 힘든지", "어느 코드가 원인인지"는 알 수 없습니다. APM은 그 공백을 채웁니다.

APM이 할 수 있는 것:

  • 특정 HTTP 요청의 전체 처리 시간 측정
  • 요청 안에서 어떤 메서드, 어떤 DB 쿼리가 시간을 먹는지 추적
  • 느린 쿼리 Top 10을 자동으로 정렬
  • 서비스 간 호출 관계(Service Map) 시각화
  • 에러 발생 시 스택트레이스를 포함한 전체 컨텍스트 저장

APM 없이 장애를 찾는 현실:

"서비스 느림" 신고
→ top, free, df 확인 → 정상
→ 로그에서 Exception 검색
→ 느린 API가 어딘지 추측
→ 코드 리뷰 시작
→ 30분 경과

APM 있을 때:

"서비스 느림" 신고
→ APM 트랜잭션 목록 열기
→ /api/orders GET 평균 2.1초
→ 내부에서 DB 쿼리 1.8초
→ 해당 쿼리 즉시 확인
→ 5분 경과
💡개념

주요 APM 솔루션 비교

APM 솔루션은 오픈소스 자체 호스팅부터 글로벌 SaaS 유료 서비스까지 범위가 넓어, 환경과 예산에 맞지 않는 선택을 하면 도입 후 운영 비용이나 유지 관리 부담이 기대를 초과하는 경우가 많습니다. 국내 공공·금융 환경에서는 규제 리포팅을 지원하는 상용 솔루션이 필요한 반면, 스타트업이나 온프레미스 팀에서는 무료 오픈소스로도 충분히 트랜잭션 추적이 가능합니다. 각 솔루션의 적합 환경과 핵심 특징을 파악해두면 "APM 도입" 논의가 나왔을 때 근거 있는 선택을 빠르게 제안할 수 있습니다.

APM 솔루션 비교

팀장이 "APM 하나 도입해보자"고 했습니다. 구글에서 검색하면 Pinpoint, New Relic, Datadog, Dynatrace가 나옵니다. 오픈소스와 유료 SaaS의 차이도, 자바 전용과 멀티언어 지원의 차이도 처음에는 구분이 안 됩니다. 환경에 맞지 않는 APM을 도입하면 운영 비용이 기대 이상으로 들거나, 설치는 했는데 실제로 아무도 보지 않는 대시보드가 됩니다. 주요 솔루션의 특성을 파악해야 상황에 맞는 선택을 할 수 있습니다.

Pinpoint (오픈소스, 네이버 개발):

국내에서 가장 널리 쓰이는 무료 APM입니다. Java 에이전트를 Tomcat/Spring Boot JVM에 붙이면, 트랜잭션이 HBase에 저장되고 Web UI에서 Scatter Chart(응답시간 분포)와 Call Tree(메서드 추적)를 확인할 수 있습니다.

로컬 터미널
# Pinpoint Agent 설정 (Tomcat JAVA_OPTS에 추가)
# /opt/tomcat/bin/setenv.sh
JAVA_OPTS="$JAVA_OPTS -javaagent:/opt/pinpoint-agent/pinpoint-bootstrap.jar"
JAVA_OPTS="$JAVA_OPTS -Dpinpoint.agentId=was01"
JAVA_OPTS="$JAVA_OPTS -Dpinpoint.applicationName=my-service"
JAVA_OPTS="$JAVA_OPTS -Dpinpoint.collector.ip=pinpoint-collector-host"

Jennifer (제니퍼소프트, 국내 기업 필수):

금융, 공공기관, 대기업에서 가장 많이 보이는 상용 APM입니다. 실시간 트랜잭션 히트맵, 액티브 서비스 현황, 서버 자원을 통합 화면에서 보여줘, 운영팀이 대시보드 한 화면으로 전체 상황을 파악합니다. 국내 규제 환경에 맞는 리포팅 기능이 포함됩니다.

Dynatrace / New Relic (글로벌 SaaS APM):

에이전트 설치 후 자동으로 서비스 맵을 생성하고, ML 기반으로 이상 징후를 탐지합니다. 글로벌 SaaS 서비스나 MSA 환경에서 주로 선택합니다. 비용이 높지만 설치와 유지 관리가 단순합니다.

솔루션비용적합 환경특징
Pinpoint무료온프레미스, Java국내 오픈소스, HBase 필요
Jennifer유료국내 금융/공공한국 규제 리포팅, UI 직관적
DynatraceSaaS 과금글로벌, MSAAI 이상 탐지, 자동 서비스 맵
New RelicSaaS 과금스타트업~중견설정 최소, 다양한 언어 지원

JMX Exporter + Prometheus 연동

💡개념

JVM 메트릭을 Prometheus로 가져오는 방법

Grafana 대시보드에서 "Tomcat JVM 메모리를 보고 싶다"는 요구가 생겼습니다. 이미 Prometheus는 서버 OS 메트릭을 수집하고 있는데, JVM 내부 Heap과 GC 정보는 보이지 않습니다. JVM은 JMX라는 자체 관리 인터페이스로 내부 상태를 노출하는데, Prometheus는 이 형식을 직접 읽지 못합니다. JMX Exporter가 변환 다리 역할을 합니다. 설정 파일 하나와 JVM 시작 옵션 한 줄이 전부입니다.

Prometheus는 HTTP /metrics 엔드포인트에서 텍스트 형식 메트릭을 pull합니다. JVM은 JMX(Java Management Extensions)로 내부 상태를 노출합니다. 두 형식이 달라 JMX Exporter가 변환 역할을 합니다.

JMX Exporter는 Java 에이전트(-javaagent)로 동작해 JVM 내부 MBean 값을 HTTP로 노출합니다.

YAML
# /opt/jmx_exporter/config.yml
# 모든 MBean 수집 (기본 설정)
rules:
- pattern: ".*"
로컬 터미널
# /opt/tomcat/bin/setenv.sh — Tomcat 시작 시 JAVA_OPTS에 추가
JAVA_OPTS="$JAVA_OPTS -javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent.jar=9090:/opt/jmx_exporter/config.yml"

9090 포트로 메트릭이 노출됩니다. Tomcat을 재시작한 후 확인합니다.

로컬 또는 서버
# 메트릭 노출 확인
curl http://localhost:9090/metrics | head -30

# JVM 관련 메트릭만 필터링
curl -s http://localhost:9090/metrics | grep jvm_memory_bytes
# 예시 출력:
# jvm_memory_bytes_used{area="heap",} 1.34217728E8
# jvm_memory_bytes_max{area="heap",} 5.36870912E8

방화벽에서 9090 포트를 Prometheus 서버 IP에서만 허용해야 합니다. 외부에 노출하면 JVM 내부 정보가 공개됩니다.

로컬 터미널
# iptables로 Prometheus 서버만 9090 허용
iptables -A INPUT -p tcp --dport 9090 -s <prometheus-server-ip> -j ACCEPT
iptables -A INPUT -p tcp --dport 9090 -j DROP
💡개념

Prometheus scrape 설정

JMX Exporter를 설치했는데 Grafana에 여전히 JVM 메트릭이 안 보입니다. Prometheus가 그 엔드포인트를 수집 대상으로 등록하지 않았기 때문입니다. Prometheus는 수동으로 타겟을 지정해야 데이터를 가져옵니다. prometheus.ymlscrape_configs에 등록하지 않으면 메트릭이 아무리 노출되어 있어도 수집되지 않습니다.

Prometheus에서 JMX Exporter 엔드포인트를 수집 대상으로 등록합니다.

YAML
# /etc/prometheus/prometheus.yml

global:
  scrape_interval: 15s      # 기본 수집 주기
  evaluation_interval: 15s  # alert rule 평가 주기

scrape_configs:
  - job_name: 'tomcat-jvm'
    static_configs:
      - targets:
          - 'app-server-01:9090'
          - 'app-server-02:9090'
    scrape_interval: 15s
    metrics_path: /metrics    # 기본값, 생략 가능

  - job_name: 'node-exporter'
    static_configs:
      - targets:
          - 'app-server-01:9100'
로컬 터미널
# 설정 파일 검증
promtool check config /etc/prometheus/prometheus.yml

# Prometheus 재시작
systemctl reload prometheus

APM 핵심 지표 — 성능 문제 드릴다운 흐름

실습

1JMX Exporter 메트릭 확인

JMX Exporter가 정상적으로 동작하면 JVM Heap, Non-Heap, GC 관련 메트릭이 텍스트 형식으로 출력됩니다. jvm_memory_bytes_used에서 현재 사용량을, jvm_memory_bytes_max에서 최대 허용치를 확인합니다. 이 두 값의 비율이 사용률입니다.

curl -s http://app-server:9090/metrics | grep jvm_memory
🔍실행 후 확인할 것
  • curl 응답에 jvm_memory_bytes_used{area="heap"} 값이 출력됐는가
  • jvm_gc_collection_seconds_count 메트릭으로 GC 발생 횟수를 확인할 수 있는가
  • HTTP 200 응답이 오고 있는가 (curl -I http://app-server:9090/metrics)
  • 메트릭 수가 수백 줄 이상 출력됐는가 (curl ... | wc -l 로 확인)
2Prometheus target 수집 상태 확인

Prometheus API로 등록된 target의 상태를 확인합니다. health: up이면 정상 수집 중, health: down이면 연결 실패입니다. Grafana 데이터가 없을 때 이 명령으로 먼저 Prometheus-target 간 연결을 확인합니다.

curl -s http://prometheus:9090/api/v1/targets | python3 -m json.tool | grep -E 'health|scrapeUrl'
🔍실행 후 확인할 것
  • tomcat-jvm job의 target이 health: up 상태인가
  • lastScrape 시각이 최근(15초 이내)인가
  • scrapeUrl에 설정한 app-server:9090 주소가 맞게 표시되는가
  • down 상태인 target이 있다면 lastError 메시지로 원인을 확인했는가

Grafana 대시보드 구성

💡개념

JVM 모니터링 대시보드 패널 구성

"Tomcat이 느려졌다"는 신고가 들어왔을 때, CPU와 메모리는 정상인데 응답이 느립니다. JVM Heap이 꽉 차서 GC가 과도하게 돌고 있는 경우입니다. 하지만 이 상황을 OS 레벨 메트릭으로는 알 수 없습니다. JVM 전용 패널이 있어야 Heap 사용률과 GC 빈도를 즉시 확인할 수 있습니다. 핵심 패널 4개가 있으면 대부분의 JVM 성능 이슈를 진단할 수 있습니다.

Grafana에서 Prometheus를 Data Source로 등록한 후 JVM 모니터링 대시보드를 구성합니다. 핵심 패널 4개면 JVM 상태를 충분히 파악할 수 있습니다.

패널 1 — Heap 사용률 (%):

PROMQL
# Heap 사용률 계산
(jvm_memory_bytes_used{area="heap", job="tomcat-jvm"}
 / jvm_memory_bytes_max{area="heap", job="tomcat-jvm"}) * 100

패널 2 — GC 발생 빈도 (rate):

PROMQL
# 분당 GC 발생 횟수
rate(jvm_gc_collection_seconds_count{job="tomcat-jvm"}[5m]) * 60

패널 3 — GC 소요 시간 비율 (%):

PROMQL
# GC에 소비되는 CPU 시간 비율
rate(jvm_gc_collection_seconds_sum{job="tomcat-jvm"}[5m])
/ rate(jvm_gc_collection_seconds_count{job="tomcat-jvm"}[5m]) * 1000
# ms 단위로 환산

패널 4 — Thread 수:

PROMQL
jvm_threads_current{job="tomcat-jvm"}

Alert Rule — Heap 85% 초과 5분 지속:

Grafana의 Alert 탭에서 다음과 같이 설정합니다.

YAML
# Grafana Alert Rule (개념 표현)
condition: Heap 사용률 > 85
for: 5m       # 5분 이상 지속 시 알람
labels:
  severity: warning
annotations:
  summary: "JVM Heap 사용률 위험 수준"
  description: "{{ $labels.instance }} Heap {{ $value }}%"

Grafana 8.x 이상에서는 Unified Alerting을 사용하며, Alert > Contact Points에서 Slack/Email 연동을 설정합니다.

트러블슈팅

원인: 두 가지 가능성입니다. 첫째는 Tomcat JAVA_OPTS에 -javaagent 옵션이 제대로 반영되지 않은 것, 둘째는 방화벽에서 9090 포트를 차단하고 있는 것입니다.

로컬 터미널
# 1단계: Tomcat 프로세스에 -javaagent 옵션이 있는지 확인
ps aux | grep java | grep jmx_prometheus

# 없으면 setenv.sh 확인
cat /opt/tomcat/bin/setenv.sh | grep javaagent

# setenv.sh가 없거나 JAVA_OPTS에 미반영된 경우
# Tomcat 재시작 후 확인
systemctl restart tomcat

# 2단계: 9090 포트 리슨 확인
ss -tlnp | grep 9090

# 3단계: 방화벽 확인 (CentOS/RHEL)
firewall-cmd --list-ports | grep 9090
# 필요 시 오픈 (Prometheus 서버 IP만 허용 권장)
firewall-cmd --add-port=9090/tcp --permanent && firewall-cmd --reload

# 4단계: JMX Exporter 설정 파일 경로 확인
# -javaagent 옵션에 지정한 config.yml 경로가 실제로 존재하는지
ls -la /opt/jmx_exporter/config.yml

원인: Prometheus가 target에서 scrape에 실패하거나, PromQL 쿼리에서 job 레이블이 실제 설정과 다를 때 발생합니다.

로컬 또는 서버
# 1단계: Prometheus target 상태 확인
curl -s http://prometheus:9090/api/v1/targets \
  | python3 -m json.tool | grep -A5 "tomcat-jvm"
# health: "down"이면 scrape 실패

# 2단계: 수동으로 메트릭 수집 시뮬레이션
curl -s http://app-server:9090/metrics | head -5
# 직접 접근이 되는지 확인

# 3단계: Prometheus에서 메트릭 존재 여부 확인
curl -s "http://prometheus:9090/api/v1/query?query=jvm_memory_bytes_used" \
  | python3 -m json.tool | grep value

# 4단계: Grafana PromQL에서 job 레이블 확인
# jvm_memory_bytes_used{job="tomcat-jvm"} 의 job 값이
# prometheus.yml의 job_name과 정확히 일치하는지 확인
curl -s "http://prometheus:9090/api/v1/labels" | python3 -m json.tool
💼
실무 맥락
현업 패턴

실제 업무에서 이 지식이 쓰이는 상황:

서버 3대를 운영하면서 "가끔 응답이 늦어진다"는 민원이 들어올 때, APM이 있으면 30분 안에 원인을 찾고, 없으면 며칠을 추측합니다. APM 솔루션을 당장 도입하기 어려운 환경이라면, JMX Exporter + Prometheus + Grafana 조합이 비용 없이 구현 가능한 대안입니다.

실무 모니터링 스택 예시:

인프라 모니터링: Prometheus + Node Exporter → Grafana
JVM 모니터링:   JMX Exporter → Prometheus → Grafana
APM:            Pinpoint 에이전트 → Pinpoint Collector → Web UI
알람:           Grafana Alert → Slack webhook

신입 엔지니어가 자주 하는 실수:

  1. JMX Exporter 포트를 방화벽 예외 없이 설정해 Prometheus가 수집 못 함
  2. Heap alert를 순간 값으로 걸어 false positive 남발 → for 5m 조건 필수
  3. scrape_interval을 너무 짧게 설정해 모니터링 서버 자체가 부하

다음 모듈에서는 장애가 발생했을 때 타임라인을 재구성하고 5-Why 분석으로 재발 방지 대책을 수립하는 장애 보고서 작성법을 다룹니다.

지식 확인

퀴즈 — 4문제

Q1

APM과 인프라 모니터링(CPU/메모리 등)의 핵심 차이는?

Q2

Prometheus가 JVM 메트릭을 직접 수집하지 못하는 이유와 JMX Exporter가 필요한 이유는?

Q3

Grafana alert 설정에서 'for 5m' 조건의 의미는?

Q4

Prometheus scrape_interval을 5초처럼 너무 짧게 설정하면 발생하는 문제는?

0 / 4 답변

🧪 실습으로 확인하기

Nginx 설치 및 기동

초급

Linux 서버에 Nginx를 설치하고 systemd 서비스로 등록하여 80포트에서 응답하는 상태까지 만든다.

30📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

infra-ops중급 · 60
[Infra Ops] 계정 권한 관리, 보안 헤더, TLS 강화 실무
인프라 서비스 운영 트랙 계속
linux입문 · 30
[Linux] 개발자가 왜 리눅스 서버와 커맨드라인을 반드시 배워야 하는가
Linux 트랙 시작점