[2026] 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 아키텍처
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TB
subgraph App[Application Servers]
A1[App 1]
A2[App 2]
A3[App 3]
end
subgraph Redis_Cluster[Redis Cluster]
M1["Master 1\nSlots: 0-5460"]
M2["Master 2\nSlots: 5461-10922"]
M3["Master 3\nSlots: 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. 캐싱
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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. 세션 관리
아래 코드는 python를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 세션 저장
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
아래 코드는 python를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
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. 실시간 리더보드
아래 코드는 python를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 점수 추가
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 성능 팁
다음은 python를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# ✅ 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)
일상 비유로 이해하기: 메모리를 아파트 건물로 생각해보세요. 스택은 엘리베이터 같아서 빠르지만 공간이 제한적입니다. 힙은 창고처럼 넓지만 물건을 찾는 데 시간이 걸립니다. 포인터는 “3층 302호”처럼 주소를 가리키는 메모지라고 보면 됩니다.
2. ELK Stack: 로그 수집과 분석
ELK Stack이란?
ELK는 Elasticsearch, Logstash, Kibana의 조합으로, 로그 수집·저장·분석·시각화를 위한 통합 솔루션입니다. 다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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 문서를 인덱싱하고 빠르게 검색합니다.
인덱스 생성 및 문서 추가
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 인덱스 생성
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"
}'
검색 쿼리
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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 설정 예시
다음은 ruby를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 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)
아래 코드는 code를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 에러 로그 검색
level: 중급
# 특정 사용자의 로그
user_id: "user123" AND status: 500
# 느린 API 요청
response_time > 1000 AND endpoint: "/api/*"
3. Prometheus: 메트릭 기반 모니터링
Prometheus란?
Prometheus는 시계열 데이터베이스 기반의 모니터링 및 알림 시스템입니다. Pull 모델로 메트릭을 수집합니다.
Prometheus 아키텍처
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TB
subgraph Targets[모니터링 대상]
App1["App Server 1\n/metrics"]
App2["App Server 2\n/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 (카운터)
증가만 하는 값 (요청 수, 에러 수) 아래 코드는 python를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
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 사용률, 메모리) 아래 코드는 python를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
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 (히스토그램)
값의 분포 (응답 시간, 요청 크기) 아래 코드는 python를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
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) 아래 코드는 python를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
from prometheus_client import Summary
latency = Summary('request_latency_seconds', 'Request latency')
@latency.time()
def process_request():
# 처리
pass
Prometheus 설정
다음은 yaml를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 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 쿼리 예시
아래 코드는 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
다음은 yaml를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 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 대시보드 예시
다음은 json를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
{
"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 알림 설정
다음은 yaml를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 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 아키텍처
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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\nElasticsearch/Cassandra"]
UI[Jaeger UI]
end
S1 --> Agent
S2 --> Agent
S3 --> Agent
S4 --> Agent
Agent --> Collector
Collector --> Storage
Storage --> UI
OpenTelemetry로 Tracing 구현
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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에서 다음을 확인할 수 있습니다: 아래 코드는 code를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
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 | 밀리초 | 디스크 | 마이크로서비스 추적 |
선택 플로우차트
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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) 스택
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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 예시
다음은 yaml를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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. 적절한 만료 시간 설정
아래 코드는 python를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# ✅ 캐시에는 항상 TTL 설정
r.setex("user:123", 600, json.dumps(user_data)) # 10분
# ❌ TTL 없으면 메모리 부족 위험
r.set("user:123", json.dumps(user_data))
2. 키 네이밍 규칙
아래 코드는 python를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# ✅ 명확한 네이밍
"user:123:profile"
"session:abc123"
"cache:product:456"
# ❌ 모호한 네이밍
"u123"
"s1"
3. 대용량 데이터 처리
아래 코드는 python를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# ✅ 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. 인덱스 라이프사이클 관리
다음은 json를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
{
"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. 쿼리 최적화
다음은 python를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# ✅ 필터 컨텍스트 사용 (캐싱)
{
"query": {
"bool": {
"filter": [
{"term": {"status": "active"}},
{"range": {"timestamp": {"gte": "now-1h"}}}
]
}
}
}
# ❌ 쿼리 컨텍스트 (스코어 계산 오버헤드)
{
"query": {
"match": {"status": "active"}
}
}
Prometheus 베스트 프랙티스
1. 레이블 카디널리티 주의
아래 코드는 python를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# ✅ 낮은 카디널리티
http_requests_total{method="GET", endpoint="/api/users"}
# ❌ 높은 카디널리티 (user_id는 수백만 개)
http_requests_total{user_id="123456"} # 위험!
2. 적절한 스크랩 간격
아래 코드는 yaml를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 일반 애플리케이션: 15-30초
scrape_interval: 15s
# 고빈도 메트릭: 5초
scrape_interval: 5s
# 저빈도 메트릭: 1분
scrape_interval: 1m
3. Recording Rules로 쿼리 최적화
아래 코드는 yaml를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 자주 사용하는 쿼리를 미리 계산
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: 전자상거래 모니터링
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 애플리케이션 메트릭
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: 로그 기반 알림
다음은 ruby를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 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가지 기둥
아래 코드는 mermaid를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TB
Observability["관측성\nObservability"]
Logs["로그\nLogs"]
Metrics["메트릭\nMetrics"]
Traces["추적\nTraces"]
Observability --> Logs
Observability --> Metrics
Observability --> Traces
Logs --> ELK[ELK Stack]
Metrics --> Prom[Prometheus + Grafana]
Traces --> Jaeger[Jaeger]
시작 가이드
1단계: 기본 스택 구축
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# Docker Compose로 한 번에 실행
docker-compose up -d
# 접속 URL
# Kibana: http://localhost:5601
# Grafana: http://localhost:3000
# Prometheus: http://localhost:9090
# Jaeger: http://localhost:16686
2단계: 애플리케이션 계측
다음은 간단한 python 코드 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 1. Redis 캐싱 추가
# 2. Prometheus 메트릭 노출
# 3. Structured 로깅 (JSON)
# 4. OpenTelemetry Tracing
3단계: 대시보드 구성
다음은 간단한 code 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
1. Grafana에서 Prometheus 데이터 소스 추가
2. 주요 메트릭 대시보드 생성
3. Kibana에서 로그 인덱스 패턴 설정
4. Jaeger에서 서비스 추적 확인
참고 자료
- Redis 공식 문서
- Elasticsearch 가이드
- Prometheus 문서
- Grafana 문서
- Jaeger 문서 한 줄 요약: Redis로 캐싱, ELK로 로그 분석, Prometheus로 메트릭 수집, Grafana로 시각화, Jaeger로 분산 추적을 구현하여 완전한 관측성을 갖춘 시스템을 구축할 수 있습니다.