2026년 필수 기술 스택 | Kibana·Prometheus·Redis·Grafana·ELK 완벽 가이드
이 글의 핵심
현대 개발자가 반드시 알아야 할 오픈소스 기술 스택. Kibana 로그 분석, Prometheus 모니터링, Redis 캐싱, Grafana 대시보드, ELK Stack 구축까지 실전 예제로 마스터하세요.
들어가며: 현대 기술 스택의 필수 요소
2026년 현재, 성공적인 서비스 운영을 위해서는 모니터링, 로그 분석, 캐싱, 메트릭 수집이 필수입니다. 이 글에서는 각 영역의 대표 오픈소스 도구들을 실전 예제와 함께 소개합니다.
다룰 기술 스택:
- Redis: 인메모리 데이터 저장소 및 캐시
- Elasticsearch: 분산 검색 및 분석 엔진
- Kibana: 로그 시각화 및 분석
- Prometheus: 메트릭 수집 및 모니터링
- Grafana: 메트릭 대시보드
- Jaeger: 분산 추적 (Tracing)
목차
- Redis: 초고속 인메모리 데이터베이스
- ELK Stack: 로그 수집과 분석
- Prometheus: 메트릭 기반 모니터링
- Grafana: 통합 대시보드
- Jaeger: 분산 추적
- 기술 스택 비교와 선택
- 실전 아키텍처
- 베스트 프랙티스
1. Redis: 초고속 인메모리 데이터베이스
Redis란?
Redis(Remote Dictionary Server)는 인메모리 키-값 저장소로, 캐싱, 세션 관리, 실시간 분석에 사용됩니다.
주요 특징
- 속도: 마이크로초 단위 응답 시간
- 자료구조: String, List, Set, Hash, Sorted Set, Stream
- 영속성: RDB, AOF 스냅샷
- 클러스터링: 샤딩 및 복제 지원
Redis 아키텍처
flowchart TB
subgraph App[Application Servers]
A1[App 1]
A2[App 2]
A3[App 3]
end
subgraph Redis_Cluster[Redis Cluster]
M1[Master 1<br/>Slots: 0-5460]
M2[Master 2<br/>Slots: 5461-10922]
M3[Master 3<br/>Slots: 10923-16383]
S1[Replica 1]
S2[Replica 2]
S3[Replica 3]
M1 --> S1
M2 --> S2
M3 --> S3
end
A1 --> M1
A2 --> M2
A3 --> M3
실전 사용 예시
1. 캐싱
import redis
import json
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
# 캐시 읽기
def get_user(user_id):
# 캐시 확인
cached = r.get(f"user:{user_id}")
if cached:
return json.loads(cached)
# DB에서 조회
user = db.query("SELECT * FROM users WHERE id = ?", user_id)
# 캐시 저장 (10분)
r.setex(f"user:{user_id}", 600, json.dumps(user))
return user
2. 세션 관리
# 세션 저장
def create_session(user_id, session_data):
session_id = generate_session_id()
r.setex(
f"session:{session_id}",
3600, # 1시간
json.dumps({"user_id": user_id, **session_data})
)
return session_id
# 세션 조회
def get_session(session_id):
data = r.get(f"session:{session_id}")
return json.loads(data) if data else None
3. Rate Limiting
def check_rate_limit(user_id, limit=100, window=60):
key = f"rate_limit:{user_id}"
current = r.incr(key)
if current == 1:
r.expire(key, window)
return current <= limit
4. 실시간 리더보드
# 점수 추가
r.zadd("leaderboard", {"user1": 1000, "user2": 1500})
# 상위 10명 조회
top10 = r.zrevrange("leaderboard", 0, 9, withscores=True)
for user, score in top10:
print(f"{user}: {score}")
Redis 성능 팁
# ✅ Pipeline으로 네트워크 왕복 최소화
pipe = r.pipeline()
for i in range(1000):
pipe.set(f"key:{i}", f"value:{i}")
pipe.execute()
# ✅ Lua 스크립트로 원자적 연산
lua_script = """
local current = redis.call('GET', KEYS[1])
if tonumber(current) < tonumber(ARGV[1]) then
return redis.call('SET', KEYS[1], ARGV[1])
end
return 0
"""
r.eval(lua_script, 1, "counter", 100)
2. ELK Stack: 로그 수집과 분석
ELK Stack이란?
ELK는 Elasticsearch, Logstash, Kibana의 조합으로, 로그 수집·저장·분석·시각화를 위한 통합 솔루션입니다.
flowchart LR
subgraph Sources[로그 소스]
App[Application]
Web[Web Server]
DB[Database]
end
subgraph Logstash[Logstash]
Input[Input]
Filter[Filter]
Output[Output]
Input --> Filter --> Output
end
subgraph Elasticsearch[Elasticsearch Cluster]
ES1[Node 1]
ES2[Node 2]
ES3[Node 3]
end
subgraph Kibana[Kibana]
Dashboard[Dashboard]
Discover[Discover]
Visualize[Visualize]
end
App --> Logstash
Web --> Logstash
DB --> Logstash
Logstash --> ES1
ES1 <--> ES2
ES2 <--> ES3
ES1 --> Kibana
Elasticsearch
분산 검색 및 분석 엔진으로, JSON 문서를 인덱싱하고 빠르게 검색합니다.
인덱스 생성 및 문서 추가
# 인덱스 생성
curl -X PUT "localhost:9200/logs" -H 'Content-Type: application/json' -d'
{
"mappings": {
"properties": {
"timestamp": {"type": "date"},
"level": {"type": "keyword"},
"message": {"type": "text"},
"user_id": {"type": "keyword"}
}
}
}'
# 문서 추가
curl -X POST "localhost:9200/logs/_doc" -H 'Content-Type: application/json' -d'
{
"timestamp": "2026-04-01T10:00:00Z",
"level": "ERROR",
"message": "Database connection failed",
"user_id": "user123"
}'
검색 쿼리
from elasticsearch import Elasticsearch
es = Elasticsearch(['http://localhost:9200'])
# 에러 로그 검색
response = es.search(index="logs", body={
"query": {
"bool": {
"must": [
{"match": {"level": "ERROR"}},
{"range": {"timestamp": {"gte": "now-1h"}}}
]
}
},
"sort": [{"timestamp": {"order": "desc"}}],
"size": 100
})
for hit in response['hits']['hits']:
print(hit['_source'])
Logstash
데이터 수집 및 변환 파이프라인입니다.
Logstash 설정 예시
# logstash.conf
input {
file {
path => "/var/log/app/*.log"
start_position => "beginning"
}
tcp {
port => 5000
codec => json
}
}
filter {
# JSON 파싱
json {
source => "message"
}
# 날짜 파싱
date {
match => ["timestamp", "ISO8601"]
}
# 필드 추가
mutate {
add_field => { "environment" => "production" }
}
# Grok 패턴으로 로그 파싱
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:msg}" }
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "logs-%{+YYYY.MM.dd}"
}
stdout {
codec => rubydebug
}
}
Kibana
Elasticsearch 데이터 시각화 도구입니다.
주요 기능
- Discover: 로그 검색 및 필터링
- Visualize: 차트, 그래프 생성
- Dashboard: 여러 시각화를 하나의 대시보드로
- Alerting: 조건 기반 알림
Kibana 쿼리 예시 (KQL)
# 에러 로그 검색
level: "ERROR" AND timestamp >= now-1h
# 특정 사용자의 로그
user_id: "user123" AND status: 500
# 느린 API 요청
response_time > 1000 AND endpoint: "/api/*"
3. Prometheus: 메트릭 기반 모니터링
Prometheus란?
Prometheus는 시계열 데이터베이스 기반의 모니터링 및 알림 시스템입니다. Pull 모델로 메트릭을 수집합니다.
Prometheus 아키텍처
flowchart TB
subgraph Targets[모니터링 대상]
App1[App Server 1<br/>/metrics]
App2[App Server 2<br/>/metrics]
Node1[Node Exporter]
DB[Database Exporter]
end
subgraph Prometheus[Prometheus Server]
Scraper[Scraper]
TSDB[Time Series DB]
Rules[Alert Rules]
Scraper --> TSDB
TSDB --> Rules
end
subgraph Alerting[Alerting]
AM[Alertmanager]
Email[Email]
Slack[Slack]
PagerDuty[PagerDuty]
end
subgraph Visualization[시각화]
Grafana[Grafana]
PromUI[Prometheus UI]
end
App1 --> Scraper
App2 --> Scraper
Node1 --> Scraper
DB --> Scraper
Rules --> AM
AM --> Email
AM --> Slack
AM --> PagerDuty
TSDB --> Grafana
TSDB --> PromUI
메트릭 타입
1. Counter (카운터)
증가만 하는 값 (요청 수, 에러 수)
from prometheus_client import Counter
request_count = Counter('http_requests_total', 'Total HTTP requests', ['method', 'endpoint'])
@app.route('/api/users')
def get_users():
request_count.labels(method='GET', endpoint='/api/users').inc()
return users
2. Gauge (게이지)
증가/감소하는 값 (CPU 사용률, 메모리)
from prometheus_client import Gauge
memory_usage = Gauge('memory_usage_bytes', 'Memory usage in bytes')
def update_metrics():
import psutil
memory_usage.set(psutil.virtual_memory().used)
3. Histogram (히스토그램)
값의 분포 (응답 시간, 요청 크기)
from prometheus_client import Histogram
response_time = Histogram('http_response_time_seconds', 'HTTP response time')
@app.route('/api/data')
@response_time.time()
def get_data():
# 자동으로 응답 시간 측정
return process_data()
4. Summary (요약)
분위수 계산 (P50, P95, P99)
from prometheus_client import Summary
latency = Summary('request_latency_seconds', 'Request latency')
@latency.time()
def process_request():
# 처리
pass
Prometheus 설정
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
- job_name: 'app'
static_configs:
- targets: ['localhost:8080']
metrics_path: '/metrics'
- job_name: 'kubernetes'
kubernetes_sd_configs:
- role: pod
PromQL 쿼리 예시
# CPU 사용률 (5분 평균)
rate(cpu_usage_seconds_total[5m])
# 에러율 (지난 1시간)
sum(rate(http_requests_total{status=~"5.."}[1h])) /
sum(rate(http_requests_total[1h]))
# P95 응답 시간
histogram_quantile(0.95,
rate(http_response_time_seconds_bucket[5m]))
# 메모리 사용률
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) /
node_memory_MemTotal_bytes * 100
Alert Rules
# alert.rules.yml
groups:
- name: example
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) /
sum(rate(http_requests_total[5m])) > 0.05
for: 10m
labels:
severity: critical
annotations:
summary: "High error rate detected"
description: "Error rate is {{ $value }}%"
- alert: HighMemoryUsage
expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage on {{ $labels.instance }}"
4. Grafana: 통합 대시보드
Grafana란?
Grafana는 메트릭, 로그, 트레이스를 시각화하는 오픈소스 플랫폼입니다. Prometheus, Elasticsearch, MySQL 등 다양한 데이터 소스를 지원합니다.
주요 기능
- 대시보드: 여러 패널을 조합한 시각화
- 알림: 임계값 기반 알림
- 템플릿: 변수를 사용한 동적 대시보드
- 플러그인: 다양한 데이터 소스 및 패널
Grafana 대시보드 예시
{
"dashboard": {
"title": "Application Monitoring",
"panels": [
{
"title": "Request Rate",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"legendFormat": "{{method}} {{endpoint}}"
}
],
"type": "graph"
},
{
"title": "Error Rate",
"targets": [
{
"expr": "sum(rate(http_requests_total{status=~\"5..\"}[5m]))"
}
],
"type": "stat",
"thresholds": [
{"value": 0, "color": "green"},
{"value": 0.01, "color": "yellow"},
{"value": 0.05, "color": "red"}
]
},
{
"title": "Response Time (P95)",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(http_response_time_seconds_bucket[5m]))"
}
],
"type": "graph"
}
]
}
}
Grafana 알림 설정
# Grafana Alert
apiVersion: 1
groups:
- name: app-alerts
interval: 1m
rules:
- uid: high-error-rate
title: High Error Rate
condition: A
data:
- refId: A
queryType: ''
relativeTimeRange:
from: 600
to: 0
datasourceUid: prometheus-uid
model:
expr: 'rate(http_errors_total[5m]) > 10'
noDataState: NoData
execErrState: Alerting
for: 5m
annotations:
summary: 'Error rate is too high'
labels:
severity: critical
5. Jaeger: 분산 추적
Jaeger란?
Jaeger는 마이크로서비스 환경에서 요청의 전체 흐름을 추적하는 분산 추적 시스템입니다.
Jaeger 아키텍처
flowchart TB
subgraph Services[Microservices]
S1[API Gateway]
S2[Auth Service]
S3[Order Service]
S4[Payment Service]
end
subgraph Jaeger[Jaeger]
Agent[Jaeger Agent]
Collector[Collector]
Storage[Storage<br/>Elasticsearch/Cassandra]
UI[Jaeger UI]
end
S1 --> Agent
S2 --> Agent
S3 --> Agent
S4 --> Agent
Agent --> Collector
Collector --> Storage
Storage --> UI
OpenTelemetry로 Tracing 구현
from opentelemetry import trace
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Tracer 설정
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
jaeger_exporter = JaegerExporter(
agent_host_name="localhost",
agent_port=6831,
)
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(jaeger_exporter)
)
# Span 생성
@app.route('/api/order')
def create_order():
with tracer.start_as_current_span("create_order") as span:
span.set_attribute("user_id", user_id)
span.set_attribute("order_id", order_id)
# 하위 작업
with tracer.start_as_current_span("check_inventory"):
check_inventory(order_id)
with tracer.start_as_current_span("process_payment"):
process_payment(order_id)
return {"order_id": order_id}
Trace 시각화
Jaeger UI에서 다음을 확인할 수 있습니다:
Trace: create_order (총 500ms)
├── check_inventory (100ms)
│ └── database_query (80ms)
├── process_payment (350ms)
│ ├── validate_card (50ms)
│ ├── charge_card (250ms)
│ └── send_receipt (50ms)
└── update_inventory (50ms)
6. 기술 스택 비교와 선택
종합 비교표
| 기술 | 목적 | 데이터 타입 | 지연시간 | 저장 방식 | 주요 사용 사례 |
|---|---|---|---|---|---|
| Redis | 캐싱, 세션 | 키-값 | 마이크로초 | 인메모리 | 캐시, 세션, Rate Limiting |
| Elasticsearch | 검색, 분석 | JSON 문서 | 밀리초 | 디스크 | 로그 검색, 전문 검색 |
| Prometheus | 메트릭 수집 | 시계열 | 초 단위 | 디스크 | CPU, 메모리, 요청 수 모니터링 |
| Grafana | 시각화 | - | - | - | 대시보드, 알림 |
| Jaeger | 분산 추적 | Span | 밀리초 | 디스크 | 마이크로서비스 추적 |
선택 플로우차트
flowchart TD
Start[무엇을 하고 싶나요?] --> Q1{데이터 타입은?}
Q1 -->|로그| Q2{검색 필요?}
Q2 -->|Yes| ELK[Elasticsearch + Kibana]
Q2 -->|No| Loki[Loki + Grafana]
Q1 -->|메트릭| Q3{시계열 데이터?}
Q3 -->|Yes| Prom[Prometheus + Grafana]
Q3 -->|No| InfluxDB[InfluxDB]
Q1 -->|캐시/세션| Q4{영속성 필요?}
Q4 -->|Yes| Redis_AOF[Redis + AOF]
Q4 -->|No| Redis_Mem[Redis 인메모리]
Q1 -->|분산 추적| Jaeger[Jaeger/Zipkin]
7. 실전 아키텍처
완전한 관측성(Observability) 스택
flowchart TB
subgraph App[Application Layer]
API[API Server]
Worker[Background Worker]
Service[Microservices]
end
subgraph Logs[로그 수집]
Filebeat[Filebeat]
Logstash[Logstash]
ES[Elasticsearch]
Kibana[Kibana]
end
subgraph Metrics[메트릭 수집]
Prometheus[Prometheus]
Grafana[Grafana]
end
subgraph Traces[분산 추적]
Jaeger[Jaeger]
end
subgraph Cache[캐싱]
Redis[Redis]
end
API --> Filebeat
Worker --> Filebeat
Service --> Filebeat
Filebeat --> Logstash
Logstash --> ES
ES --> Kibana
API --> Prometheus
Worker --> Prometheus
Service --> Prometheus
Prometheus --> Grafana
API --> Jaeger
Service --> Jaeger
API --> Redis
Service --> Redis
Docker Compose 예시
version: '3.8'
services:
# Redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
command: redis-server --appendonly yes
# Elasticsearch
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ports:
- "9200:9200"
volumes:
- es-data:/usr/share/elasticsearch/data
# Kibana
kibana:
image: docker.elastic.co/kibana/kibana:8.12.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch
# Prometheus
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
# Grafana
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
depends_on:
- prometheus
# Jaeger
jaeger:
image: jaegertracing/all-in-one:latest
ports:
- "5775:5775/udp"
- "6831:6831/udp"
- "6832:6832/udp"
- "5778:5778"
- "16686:16686" # UI
- "14268:14268"
- "14250:14250"
environment:
- COLLECTOR_ZIPKIN_HOST_PORT=:9411
volumes:
redis-data:
es-data:
prometheus-data:
grafana-data:
8. 베스트 프랙티스
Redis 베스트 프랙티스
1. 적절한 만료 시간 설정
# ✅ 캐시에는 항상 TTL 설정
r.setex("user:123", 600, json.dumps(user_data)) # 10분
# ❌ TTL 없으면 메모리 부족 위험
r.set("user:123", json.dumps(user_data))
2. 키 네이밍 규칙
# ✅ 명확한 네이밍
"user:123:profile"
"session:abc123"
"cache:product:456"
# ❌ 모호한 네이밍
"u123"
"s1"
3. 대용량 데이터 처리
# ✅ SCAN으로 안전하게 순회
cursor = 0
while True:
cursor, keys = r.scan(cursor, match="user:*", count=100)
for key in keys:
process(key)
if cursor == 0:
break
# ❌ KEYS는 프로덕션에서 금지 (블로킹)
keys = r.keys("user:*") # 위험!
Elasticsearch 베스트 프랙티스
1. 인덱스 라이프사이클 관리
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "50GB",
"max_age": "1d"
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": {"number_of_shards": 1}
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
2. 샤드 크기 최적화
# 샤드당 20-40GB 권장
# 인덱스 크기 100GB → 샤드 3-5개
3. 쿼리 최적화
# ✅ 필터 컨텍스트 사용 (캐싱)
{
"query": {
"bool": {
"filter": [
{"term": {"status": "active"}},
{"range": {"timestamp": {"gte": "now-1h"}}}
]
}
}
}
# ❌ 쿼리 컨텍스트 (스코어 계산 오버헤드)
{
"query": {
"match": {"status": "active"}
}
}
Prometheus 베스트 프랙티스
1. 레이블 카디널리티 주의
# ✅ 낮은 카디널리티
http_requests_total{method="GET", endpoint="/api/users"}
# ❌ 높은 카디널리티 (user_id는 수백만 개)
http_requests_total{user_id="123456"} # 위험!
2. 적절한 스크랩 간격
# 일반 애플리케이션: 15-30초
scrape_interval: 15s
# 고빈도 메트릭: 5초
scrape_interval: 5s
# 저빈도 메트릭: 1분
scrape_interval: 1m
3. Recording Rules로 쿼리 최적화
# 자주 사용하는 쿼리를 미리 계산
groups:
- name: aggregations
interval: 30s
rules:
- record: job:http_requests:rate5m
expr: sum(rate(http_requests_total[5m])) by (job)
- record: job:http_errors:rate5m
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) by (job)
실전 시나리오
시나리오 1: 전자상거래 모니터링
# 애플리케이션 메트릭
from prometheus_client import Counter, Histogram, Gauge
import redis
import logging
# Redis 캐시
cache = redis.Redis(host='localhost', port=6379)
# Prometheus 메트릭
order_count = Counter('orders_total', 'Total orders', ['status'])
order_amount = Histogram('order_amount_dollars', 'Order amount')
active_users = Gauge('active_users', 'Currently active users')
# Elasticsearch 로깅
logger = logging.getLogger('app')
logger.addHandler(LogstashHandler('localhost', 5000))
@app.route('/api/order', methods=['POST'])
def create_order():
# 캐시 확인
user = cache.get(f"user:{user_id}")
if not user:
user = db.get_user(user_id)
cache.setex(f"user:{user_id}", 600, json.dumps(user))
# 주문 처리
order = process_order(request.json)
# 메트릭 기록
order_count.labels(status='success').inc()
order_amount.observe(order['amount'])
# 로그 기록
logger.info(f"Order created: {order['id']}", extra={
'user_id': user_id,
'order_id': order['id'],
'amount': order['amount']
})
return jsonify(order)
시나리오 2: 로그 기반 알림
# Logstash 필터로 에러 감지 후 Slack 알림
filter {
if [level] == "ERROR" {
mutate {
add_tag => ["alert"]
}
}
}
output {
if "alert" in [tags] {
http {
url => "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
http_method => "post"
format => "json"
content_type => "application/json"
message => '{"text": "🚨 Error detected: %{message}"}'
}
}
}
정리
기술 스택 역할 요약
| 레이어 | 기술 | 역할 |
|---|---|---|
| 캐싱 | Redis | 데이터 캐싱, 세션 관리, Rate Limiting |
| 로그 | ELK Stack | 로그 수집, 검색, 분석, 시각화 |
| 메트릭 | Prometheus | 시스템/애플리케이션 메트릭 수집 |
| 시각화 | Grafana | 통합 대시보드, 알림 |
| 추적 | Jaeger | 분산 요청 추적, 성능 분석 |
관측성의 3가지 기둥
flowchart TB
Observability[관측성<br/>Observability]
Logs[로그<br/>Logs]
Metrics[메트릭<br/>Metrics]
Traces[추적<br/>Traces]
Observability --> Logs
Observability --> Metrics
Observability --> Traces
Logs --> ELK[ELK Stack]
Metrics --> Prom[Prometheus + Grafana]
Traces --> Jaeger[Jaeger]
시작 가이드
1단계: 기본 스택 구축
# Docker Compose로 한 번에 실행
docker-compose up -d
# 접속 URL
# Kibana: http://localhost:5601
# Grafana: http://localhost:3000
# Prometheus: http://localhost:9090
# Jaeger: http://localhost:16686
2단계: 애플리케이션 계측
# 1. Redis 캐싱 추가
# 2. Prometheus 메트릭 노출
# 3. Structured 로깅 (JSON)
# 4. OpenTelemetry Tracing
3단계: 대시보드 구성
1. Grafana에서 Prometheus 데이터 소스 추가
2. 주요 메트릭 대시보드 생성
3. Kibana에서 로그 인덱스 패턴 설정
4. Jaeger에서 서비스 추적 확인
참고 자료
한 줄 요약: Redis로 캐싱, ELK로 로그 분석, Prometheus로 메트릭 수집, Grafana로 시각화, Jaeger로 분산 추적을 구현하여 완전한 관측성을 갖춘 시스템을 구축할 수 있습니다.