헬스체크, 로깅 전략, 메트릭과 추적을 어떻게 붙이는지 다룹니다.
이 파트에서 다루는 내용
사용자가 먼저 알면 이미 늦었습니다
Part 1에서 신고 시각과 발생 시각이 다르다고 했습니다. 사용자는 한참 참다가 연락합니다. 그 사이의 시간이 통째로 손실입니다.
조기 발견의 목표는 단순합니다. 사용자 신고보다 우리가 먼저 아는 것입니다. 20분 먼저 알면 20분치 영향이 줄어듭니다.
무엇을 설정하고 어떻게 지표를 노출하는지는 Spring Boot 코스의 관측과 운영 파트에서 다룹니다. 여기서는 그 도구로 무엇을 재고 언제 알릴지를 정하는 판단을 봅니다.
그중 무엇으로 알림을 받을지, 임계치를 어떻게 정할지, 무엇을 알림에서 뺄지를 다룹니다.
앞에서 나온 준비 항목을 모읍니다
트랙 A와 B를 지나오며 "평소에 해 둬야 한다"고 언급한 것들이 흩어져 있습니다. 여기서 한곳에 모읍니다. 이 다섯 개가 사전 준비의 최소 세트입니다.
공통점이 있습니다. 전부 장애가 난 뒤에 하면 이번 장애에는 쓸 수 없습니다. 그래서 평상시 과제로 잡아야 합니다.
로그에 요청 단위 식별자와 밀리초 정밀도 시각을 남깁니다. 이 둘만 있어도 추적 시간이 절반으로 줄어듭니다.
스레드 덤프 3회와 서버 상태, 로그 사본을 뜨는 스크립트를 운영 서버에 배치해 둡니다. 장애 중에 명령을 떠올릴 필요가 없어집니다.
GC 로그를 켜 두고 OOM 시 힙 덤프가 자동 저장되게 합니다. 덤프 경로의 여유 공간도 함께 확인합니다.
커넥션 풀과 스레드 풀의 사용량을 볼 수 있게 합니다. 없으면 스레드 덤프로 추정해야 합니다.
각 자원의 설정값과 평소 최대 사용량을 정리해 둡니다. 현재 값이 한계인지 즉시 판단됩니다.
누가 언제 연락받는지, 야간과 휴일은 어떻게 하는지를 미리 정합니다. 장애 당일에 정하면 대응이 늦습니다.
전부 한 번에 하기 어렵다면 요청 식별자와 증거 수집 스크립트부터 합니다. 이 둘이 대응 시간을 가장 크게 줄입니다. 나머지는 장애가 한 번 날 때마다 하나씩 붙여 나가도 됩니다.
증상으로 알리고 원인으로 진단합니다
무엇에 알림을 걸지가 이 파트에서 가장 중요한 판단입니다. 여기서 방향을 잘못 잡으면 알림은 많은데 정작 장애는 놓칩니다.
기준은 이렇습니다. 사용자가 느끼는 것에 알림을 걸고, 자원 지표는 진단할 때 봅니다.
응답시간, 오류율, 처리 실패 건수, 헬스체크 실패. 사용자가 겪는 것이므로 값이 나빠지면 반드시 문제입니다.
CPU, 메모리, 커넥션 사용량, GC 시간. 값이 높다고 반드시 문제는 아닙니다. 알림을 걸면 오탐이 쏟아집니다.
CPU 90%인데 서비스가 멀쩡하면 문제가 아닙니다. 반대로 CPU 30%인데 응답이 30초면 문제입니다. 사용자 관점이 기준입니다.
디스크 사용률처럼 한계에 닿으면 확실히 터지는 것은 원인 지표라도 알림을 겁니다. Part 8의 2차 장애를 막기 위해서입니다.
임계치는 평소 값을 알아야 정할 수 있습니다
응답시간 3초를 넘으면 알림을 걸자고 정했는데, 평소에도 자주 3초를 넘는 화면이라면 알림이 계속 울립니다. 반대로 평소 0.1초인 기능이 1초가 됐다면 이미 열 배 나빠진 것인데 3초 기준으로는 안 잡힙니다.
그래서 임계치를 먼저 정하지 말고, 며칠 관측해 평소 분포를 본 뒤에 정합니다. Part 8의 자원 한계값 표를 만드는 과정과 같습니다.
- 절대값보다 평소 대비 변화가 유용한 경우가 많습니다. 평소의 세 배가 되면 알리는 식입니다.
- 평균은 문제를 가립니다. 대부분 빠른데 일부만 아주 느린 상황이 평균으로는 안 보입니다. 상위 백분위 값을 함께 봅니다.
- 짧은 순간의 튐으로 알림이 울리면 피로가 쌓입니다. 몇 분간 지속될 때 알리도록 조건을 겁니다.
- 시간대별로 평소 값이 다르면 임계치도 나눕니다. 야간 배치 시간대를 주간 기준으로 재면 매일 울립니다.
- 정하고 끝이 아니라 몇 주 뒤 다시 봅니다. 오탐이 많으면 올리고, 놓친 장애가 있으면 내립니다.
알림이 많으면 아무도 안 봅니다
조기 발견 체계가 실패하는 가장 흔한 방식입니다. 처음엔 열심히 알림을 걸어 두는데, 오탐이 쌓이면서 사람들이 알림을 무시하게 됩니다. 그리고 진짜 장애 알림도 함께 묻힙니다.
이 상태가 되면 알림이 없는 것보다 나쁩니다. 알림이 있다는 이유로 다른 감시를 안 하기 때문입니다.
받으면 무엇을 할지 정해지지 않은 알림은 알림이 아닙니다. 보고 넘기기만 하는 알림은 지웁니다.
한 달에 한 번 알림 목록을 봅니다. 계속 울리는데 아무 조치도 안 한 것이 있으면 그건 지울 대상입니다.
즉시 대응이 필요한 것과 다음 날 확인해도 되는 것을 나눕니다. 채널이나 수신자를 다르게 합니다.
새벽에 사람을 깨우는 알림은 정말 즉시 대응이 필요한 것만 남깁니다. 대응하는 사람의 소모도 비용입니다.
도구를 못 쓰는 환경에서의 최소한
고객사 폐쇄망에서는 모니터링 도구 반입 자체가 안 되는 경우가 많습니다. 승인 절차가 길거나 아예 불가능합니다.
그렇다고 아무것도 안 하면 계속 사용자 신고로만 장애를 알게 됩니다. 도구 없이도 할 수 있는 최소한이 있습니다.
#!/bin/bash
# watch.sh - 5분마다 실행 (crontab)
LOG=/app/logs/application.log
ALERT=""
# 1) 헬스체크
if ! curl -sf -m 5 http://localhost:8080/actuator/health > /dev/null; then
ALERT="$ALERT\n[위험] 헬스체크 실패"
fi
# 2) 디스크
USE=$(df -P /app | awk 'NR==2{print $5}' | tr -d '%')
if [ "$USE" -gt 85 ]; then
ALERT="$ALERT\n[경고] 디스크 사용률 ${USE}%"
fi
# 3) 최근 5분 오류 건수
SINCE=$(date -d '5 minutes ago' '+%Y-%m-%d %H:%M')
CNT=$(awk -v s="$SINCE" '$0 >= s' $LOG | grep -c "ERROR")
if [ "$CNT" -gt 50 ]; then
ALERT="$ALERT\n[경고] 최근 5분 오류 ${CNT}건"
fi
if [ -n "$ALERT" ]; then
echo -e "$ALERT" | mail -s "[운영알림] $(hostname)" ops@example.com
fi헬스체크, 디스크, 오류 건수 세 가지만으로도 상당수 장애를 사용자보다 먼저 잡습니다. 메일이 막혀 있으면 파일로 남기고 담당자가 아침에 확인하는 방식도 없는 것보다 낫습니다. 임계치는 앞 섹션대로 평소 값을 보고 정합니다.
완전한 감시 체계를 못 만든다고 아무것도 안 하는 것이 가장 나쁩니다. 헬스체크 하나만 걸어도 전면 중단은 잡힙니다. 할 수 있는 것부터 하고, 장애가 한 번 날 때마다 그때 놓친 신호를 하나씩 추가해 나갑니다.