불 끄기 전에 원인 조사하는 소방관은 없다 — 장애 복구를 결정짓는 First Action
수도관이 터졌다. 물이 바닥을 적시고 있다. 이 상황에서 가장 먼저 할 일은 무엇인가? 파이프의 재질을 확인하는 것이 아니다. 동파인지 노후인지 분석하는 것도 아니다. 밸브부터 잠그는 것이다. 원인 조사는 물을 멈춘 다음에 해도 된다. 서비스 장애도 똑같다. 우아한형제들(배달의민족)은 약 70건의 장애 사례를 분석한 끝에, 복구 시간과 피해 규모를 결정짓는 가장 큰 변수가 "원인 파악의 정확도"가 아니라 최초 조치의 종류와 속도라는 결론에 도달했다. 이를 First Action이라 부른다.
장애의 생명주기 — 순서가 핵심이다
장애는 무작위로 터지는 것처럼 보이지만, 대응에는 일정한 흐름이 있다.
- 감지(Detection) — 모니터링이 이상 징후를 포착한다. 알림이 울리고, 에러율 그래프가 솟구친다.
- 인지(Acknowledgment) — 담당자가 "장애 상황이다"라고 인식하고, 대응 채널에 집결한다.
- 초동 조치(First Action) — 인지 직후 가장 먼저 실행하는 구체적 행동이다. 이 단계가 전체 복구 시간을 좌우한다.
- 원인 분석(Root Cause Analysis) — 초동 조치로 출혈을 멈춘 뒤 근본 원인을 파고든다.
- 복구(Recovery) — 서비스를 정상 상태로 되돌린다.
- 후속(Post-mortem) — 타임라인, 원인, 재발 방지책을 문서화한다.
핵심은 3번이 4번보다 먼저라는 점이다. 원인을 모르는 상태에서도 피해를 줄이는 조치를 먼저 취한다. 이것이 우아한형제들이 70건의 장애에서 뽑아낸 가장 중요한 원칙이다.
[💡 잠깐! 이 용어는?] Post-mortem(포스트모템): 라틴어로 "사후"라는 뜻이다. IT에서는 장애 종료 후 원인, 타임라인, 재발 방지책을 기록하는 회고 문서를 가리킨다. "누가 잘못했나"를 찾는 것이 아니라 "시스템에 어떤 구멍이 있었나"를 찾는 것이 목적이다.
First Action의 다섯 가지 유형
First Action은 장애를 인지한 후 원인을 완벽히 파악하기 전에, 사용자에게 가는 피해를 줄이기 위해 취하는 행동이다. 대표적인 유형은 다섯 가지다.
| First Action 유형 | 설명 | 적합한 상황 |
|---|---|---|
| 롤백 | 최근 배포를 이전 버전으로 되돌린다 | 배포 직후 장애가 발생한 경우 |
| 트래픽 차단 | 특정 API나 서비스로의 트래픽을 끊는다 | 장애가 특정 엔드포인트에 격리된 경우 |
| 기능 토글 OFF | Feature Flag를 꺼서 문제 기능을 비활성화한다 | 새로 추가한 기능이 원인으로 의심되는 경우 |
| 수동 우회 | 장애 구간을 건너뛰는 임시 경로를 만든다 | 외부 의존성(결제 PG, 외부 API)이 원인인 경우 |
| 스케일 아웃 | 서버 인스턴스를 늘려 부하를 분산한다 | 트래픽 급증에 의한 과부하인 경우 |
좋은 First Action의 세 가지 조건
모든 초동 조치가 같은 효과를 내는 것은 아니다. 70건의 장애 분석에서 드러난 패턴은 명확하다. 빠르고, 되돌릴 수 있고, 범위가 좁은 조치일수록 효과적이다.
빠르다
실행까지 걸리는 시간이 짧아야 한다. 롤백 명령어 한 줄이면 되는 것과, 핫픽스를 작성하고 코드 리뷰를 받고 배포 파이프라인을 태우는 것은 차원이 다르다. 배달의민족처럼 분당 수만 건의 주문이 발생하는 서비스에서 10분의 차이는 수십억 원의 피해 차이를 만든다.
가역적이다
조치 자체를 되돌릴 수 있어야 한다. Feature Flag를 끄는 것은 다시 켤 수 있으니 가역적이다. 반면 데이터베이스 스키마를 변경하는 것은 되돌리기 어렵다. 가역적이지 않은 조치를 First Action으로 쓰면 장애 위에 장애를 쌓는 결과를 초래할 수 있다.
범위가 좁다
영향 범위를 최소화해야 한다. 결제 모듈에 문제가 있는데 전체 서비스를 내리는 것은 과잉 대응이다. 팔에 난 상처를 치료하겠다고 전신 마취를 하는 것과 비슷하다. 문제 지점만 정확히 격리하는 것이 좋은 First Action이다.
이렇게 하면 망한다 — 흔한 실수 세 가지
원인 분석부터 시작한다
가장 흔하고 가장 치명적인 실수다. "왜 이런 일이 생겼지?"부터 파고드는 것이다. 로그를 뒤지고, 코드를 읽고, 쿼리를 날리며 30분이 흘러간다. 그 30분 동안 사용자는 주문을 못 하고, 매출은 줄줄 빠져나간다.
핫픽스를 즉석에서 작성한다
"코드 한 줄만 바꾸면 되지 않나?"라는 판단으로 장애 현장에서 코드를 수정하고 긴급 배포를 시도한다. 문제는 장애 상황의 압박감 속에서 작성한 코드가 새로운 버그를 만들 확률이 높다는 것이다. 불 위에 기름을 붓는 결과가 된다.
여러 조치를 동시에 실행한다
"다 해보자"는 식으로 롤백, 스케일 아웃, 설정 변경을 동시에 건드리면, 어떤 조치가 효과를 낸 건지 알 수 없다. Post-mortem에서도 원인-해결 매핑이 불가능해진다. 한 번에 하나씩, 효과를 관찰하며 진행하는 것이 원칙이다.
[💡 잠깐! 이 용어는?] 런북(Runbook): 특정 장애 상황에서 어떤 순서로 무엇을 실행해야 하는지 적어둔 매뉴얼이다. 장애 상황에서 사람의 판단력은 평소의 50~60% 수준으로 떨어진다는 연구 결과가 있다. 미리 적어둔 런북이 이 판단력 저하를 보상한다.
장애가 터지기 전에 준비할 것
First Action의 핵심은 장애 발생 시점이 아니라 그 이전에 결정된다. 소화기 위치를 불이 난 후에 찾으면 늦는다. 미리 알고 있어야 한다.
사전_준비:
- 롤백_절차: "1분 이내에 이전 버전으로 되돌릴 수 있는가?"
- 기능_토글: "Feature Flag가 주요 기능에 적용되어 있는가?"
- 트래픽_제어: "특정 API의 트래픽을 즉시 차단할 수 있는가?"
- 스케일_아웃: "인스턴스 추가가 자동화되어 있는가?"
- 런북: "각 장애 유형별 First Action이 문서화되어 있는가?"
장애_발생_시:
- step_1: "장애 인지 → 대응 채널 집결 (Slack, War Room)"
- step_2: "증상 확인 → 가장 가능성 높은 원인 카테고리 판단"
- step_3: "런북에서 해당 카테고리의 First Action 실행"
- step_4: "효과 확인 (메트릭 변화 관찰, 최소 2~3분 대기)"
- step_5: "효과 없으면 다음 First Action으로 전환"
- step_6: "출혈 멈춘 후 → 원인 분석 시작"Post-mortem과의 순환 관계
First Action이 장애 중의 전략이라면, Post-mortem은 장애 후의 전략이다. 이 둘은 톱니바퀴처럼 맞물려 있다.
Post-mortem에서 "이번 장애의 First Action은 적절했는가?"를 반드시 점검하고, 부적절했다면 런북을 업데이트한다. 이 사이클이 반복되면서 팀의 장애 대응 역량이 쌓인다. 우아한형제들이 70건의 장애에서 패턴을 추출할 수 있었던 것도 이 Post-mortem 문화가 정착되어 있었기 때문이다.
중요한 것은 Post-mortem이 비난의 도구가 아니라 학습의 도구여야 한다는 점이다. "누가 잘못했나"가 아니라 "시스템에 어떤 구멍이 있었나"를 찾는 것이다. 이것을 Blameless Post-mortem이라 부른다.
[💡 잠깐! 이 용어는?] Blameless Post-mortem: "비난 없는 사후 분석"이라는 뜻이다. 장애의 원인을 개인의 실수가 아니라 시스템의 취약점에서 찾는 문화다. Google, Netflix 등 SRE 문화가 성숙한 조직에서 널리 채택하고 있다.
마무리
장애는 막을 수 없다. 충분히 복잡한 시스템에서 장애는 필연이다. 중요한 것은 장애가 터졌을 때 얼마나 빠르게, 얼마나 적은 피해로 복구하느냐다. 그 속도를 결정하는 변수는 엔지니어의 디버깅 실력이 아니라 사전에 준비된 First Action의 품질이다. 소방관의 원칙을 기억하면 된다. 불을 끄는 것이 먼저다. 원인 조사는 그 다음이다. 롤백할 수 있으면 롤백하고, Feature Flag를 끌 수 있으면 끈다. 빠르고, 되돌릴 수 있고, 범위가 좁은 조치. 이것이 장애 대응의 첫 번째 원칙이다.
관심 있을 만한 포스트
새벽 3시의 탐조등 — Google SRE가 Gemini CLI로 장애를 잡는 법
Google Cloud SRE 팀이 Gemini CLI를 장애 대응 워크플로우에 통합한 방법, 효과, 한계를 분석한다.
AI 코딩의 맹점 — Artifacts 없이 에이전트는 기억을 잃는다
PRD, ADR, TDD가 AI 코딩 워크플로우에서 왜 선택이 아닌 필수인지, 실전 구조와 함께 살펴본다.
Next-Translate 3.0 — Turbopack과 App Router를 위한 i18n 재건
1년간 공백 후 돌아온 Next-Translate 3.0이 Turbopack 지원, 비동기 params, App Router 안정화를 한 번에 처리하는 방법.
V8 WasmGC 투기적 최적화 — 가상 메서드를 인라인으로 만드는 법
V8이 WasmGC의 가상 메서드 디스패치에 투기적 인라이닝을 도입해 Dart와 Java 앱에서 최대 8% 성능을 끌어낸 방법.
Vinext — Vite 위에서 Next.js를 1주일 만에 다시 만든 이야기
Cloudflare가 AI와 함께 단 일주일, $1,100의 API 비용으로 Next.js 호환 프레임워크를 Vite 위에 구축한 과정.
Tsonic — TypeScript를 네이티브 바이너리로 컴파일하는 실험
TypeScript → C# → NativeAOT 파이프라인으로 네이티브 실행 파일을 만드는 Tsonic. 어떻게 동작하고, 어떤 한계가 있는지 살펴봤다.
VS Code 팀의 AI 에이전트 병렬화 — 월간 릴리스를 주간으로 만든 워크플로우
VS Code 팀이 월간 릴리스에서 주간 릴리스로 전환한 비결. 에이전트 세션 병렬화, 자동화 파이프라인, 품질 게이트 설계 전반을 공개했다.
React Compiler의 한계 — 뭘 최적화하고 뭘 못 하는가
React Compiler가 자동 메모이제이션으로 해결하는 것과 해결하지 못하는 것. 컴파일러 기반 UI 프레임워크의 능력 경계를 정리했다.