
눈을 감고 운전하시겠습니까? (서버 모니터링 도입기)
서비스가 느리다는 항의를 받았는데, 로그파일만 뒤적거리다가 원인을 못 찾았던 경험이 있나요? Prometheus와 Grafana를 도입하여 '눈을 감고 운전하던' 상태에서 벗어난 경험과, 구글이 정의한 모니터링 4대 골든 시그널(Golden Signals)을 공유합니다.

서비스가 느리다는 항의를 받았는데, 로그파일만 뒤적거리다가 원인을 못 찾았던 경험이 있나요? Prometheus와 Grafana를 도입하여 '눈을 감고 운전하던' 상태에서 벗어난 경험과, 구글이 정의한 모니터링 4대 골든 시그널(Golden Signals)을 공유합니다.
서버를 끄지 않고 배포하는 법. 롤링, 카나리, 블루-그린의 차이점과 실제 구축 전략. DB 마이그레이션의 난제(팽창-수축 패턴)와 AWS CodeDeploy 활용법까지 심층 분석합니다.

새벽엔 낭비하고 점심엔 터지는 서버 문제 해결기. '택시 배차'와 '피자 배달' 비유로 알아보는 오토 스케일링과 서버리스의 차이, 그리고 Spot Instance를 활용한 비용 절감 꿀팁.

내 서버가 해킹당하지 않는 이유. 포트와 IP를 검사하는 '패킷 필터링'부터 AWS Security Group까지, 방화벽의 진화 과정.

왜 넷플릭스는 멀쩡한 서버를 랜덤하게 꺼버릴까요? 시스템의 약점을 찾기 위해 고의로 장애를 주입하는 카오스 엔지니어링의 철학과 실천 방법(GameDay)을 소개합니다.

서비스 런칭 일주일 차, 사용자로부터 문의 메일이 왔습니다. "저녁 9시만 되면 사이트가 너무 느려요. 어쩔 땐 접속도 안 되고요."
"그럴 리가 없는데?"
저는 제 로컬 환경과 배포된 서버에 직접 접속해 봤습니다. 아주 빠르고 쾌적했습니다.
서버에 SSH로 접속해서 top 명령어를 쳐봤지만 CPU 사용률도 5% 미만으로 아주 평온했습니다.
로그 파일(access.log)을 tail -f로 지켜봤지만 에러 로그도 없었습니다.
"사용자 인터넷 문제인가?" 하고 넘어갔죠. 하지만 다음 날 저녁 9시, 또다시 "느리다", "터졌다"는 불만이 커뮤니티에 올라왔습니다. 저는 망망대해에 떠 있는 기분이었습니다. 도대체 어디가, 얼마나, 왜 느린지 알 수가 없었으니까요.
마치 눈을 감고 고속도로를 운전하는 기분이었습니다. 어디가 막히는지 모르고, 엔진 과열인지 타이어 펑크인지 모른 채 달리고 있었죠. 사고(서버 다운)가 나야만 "아, 뭔가 잘못됐구나" 하고 알 수 있는 상태였습니다.
모니터링 문서를 읽으면서 Prometheus(데이터 수집)와 Grafana(시각화)를 부랴부랴 설치했습니다. AWS CloudWatch도 있었지만, 더 세밀한 애플리케이션 지표를 보고 싶어서 오픈소스를 선택했습니다.
그리고 대시보드를 띄운 순간, 저는 소름이 돋았습니다. 저녁 9시가 되자 그래프 하나가 수직 상승하고 있었거든요.
바로 DB Connection Latency(데이터베이스 연결 지연)였습니다.
알고 보니 특정 배치 작업(Batch Job)이 매일 밤 9시에 돌면서 DB 커넥션 풀(Connection Pool) 50개를 다 써버리고 있었습니다.
일반 사용자들은 남은 커넥션이 없어서 무한 대기(Pending) 상태에 빠져 있었던 거죠.
에러 로그가 안 남았던 이유도, 아직 에러가 난 게 아니라 '대기 중'이었기 때문입니다.
제가 접속했을 땐 운 좋게 잠깐 커넥션을 얻어서 빨랐던 거고요.
그래프를 보자마자 원인을 파악했고, 배치 작업 시간을 새벽 4시로 옮겨서 문제를 10분 만에 해결했습니다. "측정할 수 없으면, 개선할 수 없다(You can't improve what you don't measure)"는 피터 드러커의 말을 뼈저리게 느꼈습니다.
"그럼 뭘 모니터링해야 하나요?" 초보자는 보통 CPU 사용량, 메모리 같은 기본적인 것만 봅니다. 하지만 구글 SRE(Site Reliability Engineering) 팀은 4가지 황금 신호(The 4 Golden Signals)를 반드시 봐야 한다고 말합니다.
"사용자가 기다리는 시간은 얼마인가?" 평균(Average) 시간만 보면 안 됩니다. 평균이 200ms라도, p95(상위 5%), p99(상위 1%) 사용자는 10초를 기다리고 있을 수 있습니다. 꼬리(Tail Latency)를 잡아야 시스템이 안정됩니다.
"얼마나 많은 요청이 들어오는가?" 보통 RPS(Requests Per Second)로 측정합니다. 평소 100 RPS던 트래픽이 갑자기 1000 RPS로 튄다면? → 디도스(DDoS) 공격이거나 이벤트 트래픽 폭증. 갑자기 0이 된다면? → 네트워크 단절이나 로드밸런서 장애.
"얼마나 자주 실패하는가?" HTTP 500(서버 에러)뿐만 아니라, 400(잘못된 요청)이나 200 OK지만 내용이 비어있는 논리적 에러도 감시해야 합니다. 전체 요청 중 실패한 요청의 비율(%)을 봅니다.
"자원을 얼마나 다 썼는가?" CPU, 메모리, 디스크 용량, DB 커넥션 등이 한계에 얼마나 근접했는지 봅니다. 이 지표는 현재의 문제보다 "미래의 장애"를 예고해 줍니다. "이대로면 3일 뒤에 디스크 꽉 참" 같은 거죠.
모니터링 대시보드를 24시간 쳐다보고 있을 순 없습니다. 저는 Slack과 연동해서 알림(Alert)을 설정했습니다. 처음엔 의욕이 넘쳐서 "CPU 50% 넘으면 알림", "에러 1개라도 나면 알림"으로 설정했다가... 그날 밤 잠을 한숨도 못 잤습니다. 알림이 1분마다 울렸거든요.
그래서 알림 정책(Alert Policy)을 세웠습니다.
알림은 "진짜로 내가 지금 자다가 일어나야 하는 일인가?"를 기준으로 설정해야 합니다. 안 그러면 '양치기 소년'이 돼서 진짜 장애 알림을 무시하게 됩니다.
모니터링 도구는 크게 두 가지 방식으로 나뉩니다.
http://localhost:3000/metrics)하면, Prometheus 서버가 주기적으로 긁어갑니다(Scrape).현대의 대세는 Kubernetes 환경과 찰떡궁합인 Prometheus (Pull) 방식입니다.
서버를 운영하는 건 비행기를 조종하는 것과 같습니다. 창밖(User Logs)만 보고 감으로 운전할 순 없습니다. 고도계(CPU), 속도계(RPS), 연료 게이지(Memory)가 필요합니다.
최소한 RPS(트래픽), Latency(속도), Error Rate(에러) 이 3개는 지금 당장 대시보드에 띄우세요. 여러분의 서버가 지금 비명을 지르고 있을지도 모릅니다. 단지 여러분이 듣지 못하고 있을 뿐이죠. Observability(관측 가능성)를 확보하세요. 그래야 밤에 푹 잘 수 있습니다.
It was just one week after our grand launch. An email arrived from a frustrated user. "The site gets super slow around 9 PM every night. Sometimes it times out completely."
"That can't be right."
I accessed the site from my laptop and phone. It loaded instantly.
I SSH'd into the server and ran top. The CPU usage was calm at 5%.
I watched the logs with tail -f access.log. No error stacks.
"Must be the user's internet," I dismissed it. But the next day at 9 PM, complaints poured into the community forum. "Is the server down?", "Why is it spinning?" I felt like I was drifting in the open ocean without a compass. I had absolutely no idea WHERE, HOW MUCH, or WHY it was slow.
It felt like driving on a highway with my eyes closed. I couldn't tell if the engine was overheating or if I had a flat tire. I was in a state where I only knew something was wrong after crashing (server down).
Reading through monitoring documentation, I frantically installed Prometheus (Metric Collector) and Grafana (Visualization Tool). While AWS CloudWatch sends basic metrics, I needed application-level insights.
The moment I loaded the dashboard, I got goosebumps. At 9 PM sharp, one graph spiked vertically like a skyscraper.
It was DB Connection Latency.
The root cause? A scheduled Batch Job ran every night at 9 PM, hogging all 50 connections in the Connection Pool.
Regular users couldn't grab a connection and were stuck in a Pending state.
That's why there were no error logs—the requests didn't fail, they were just waiting endlessly.
I experienced "fast" speeds because I got lucky and grabbed a connection in between batch queries.
I identified the cause instantly and moved the batch job to 4 AM. Problem solved in 10 minutes. I painfully learned Peter Drucker's quote: "You can't improve what you don't measure."
"So what should I monitor?" Beginners often stare at CPU and Memory. But the Google SRE (Site Reliability Engineering) team recommends watching The 4 Golden Signals.
"How long does it take to serve a request?" Don't just watch the Average. Averages hide problems. Even if the average is 200ms, your p95 (95th percentile) or p99 users might be waiting 10 seconds. You must optimize the Tail Latency to ensure stability.
"How much demand is being placed on your system?" Usually measured in RPS (Requests Per Second). If traffic jumps from 100 to 1000 RPS? → Potentially a DDoS attack or a viral event. If it drops to 0? → Network outage or Load Balancer failure.
"Run rate of requests that fail." Watch not just explicit failures (HTTP 500s), but also implicit ones (HTTP 200 with "error: true" in body). Monitor the percentage of failed requests vs. total requests.
"How 'full' is your service?" This measures your most constrained resources (CPU, Memory, Disk I/O, DB Connections). Saturation is a leading indicator. It predicts "Future Failures". "At this rate, the disk will be full in 3 days."
You can't stare at Grafana screens 24/7. I integrated Slack for alerts. At first, I was over-eager. "Alert if CPU > 50%", "Alert on any Error". I didn't sleep that night. My phone buzzed every minute.
So I established an Alert Policy:
Set alerts based on: "Do I REALLY need to wake up for this?" Otherwise, you become the 'Boy Who Cried Wolf', and you'll ignore the alert when the server actually catches fire.
If you want to try this locally right now, copy this docker-compose.yml.
It sets up Prometheus (Collector) and Grafana (Dashboard) instantly.
version: '3'
services:
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
And a simple prometheus.yml configuration:
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'my-app'
static_configs:
- targets: ['host.docker.internal:3000'] # Your App URL
Run docker-compose up -d, and visit localhost:3000. You are now an SRE.
You might have heard of the RED Method as well. What's the difference?
Basically, RED is a subset of Golden Signals, removing "Saturation". For Application Developers, RED is often enough. For DevOps/SREs, Saturation involves disk usage and memory leaks, so it's critical.
Monitoring tells you when and where something is wrong. Logging tells you why it is wrong. You need both. Prometheus gives you the high-level alert "Error Rate is 5%". Then you go to ELK Stack (Elasticsearch, Logstash, Kibana) or Loki to find the specific stack trace. Don't mix them up. Prometheus is not for logs.
Why did I choose Prometheus? It uses a Pull model, unlike Datadog or New Relic.
/metrics). Prometheus "visits" this page every 15 seconds to scrape data.For Kubernetes environments, Pull (Prometheus) is the industry standard. It scales better and is more resilient.