Debugging Production Issues at 2 AM: A Survival Guide

March 2026 · 20 min read · 4,730 wordsAdvanced

오전 2시의 프로덕션 문제 디버깅: 생존 가이드

오전 2시 17분. PagerDuty. 경고 내용은 결제 서비스에서 95%의 오류율이라고 말하고 있습니다. 847건의 영향을 받은 거래. 당신의 배가 떨어집니다. 당신은 즉시 깹니다—오직 프로덕션 사건에서만 느껴지는 특별한 아드레날린이 솟구칩니다. 당신의 전화는 이미 잠금 해제되어 있고, 노트북이 시작되고, 커피 머신이 근육 기억만으로 삶을 되찾고 있습니다. 이것은 당신 경력의 847페이지입니다. 네, 당신은 그것을 기록합니다. 200페이지 이후로 세기 시작했는데, 이게 당신의 직업적 삶의 중요한 부분이 될 것이라는 것을 깨닫고, 불면의 시간을 보내게 될 것이라면, 차라리 그에 대한 데이터를 갖고 있자고 생각했습니다. 결제 서비스. 물론 결제 서비스입니다. 항상 결제 서비스이거나 인증 계층이거나, 누군가가 3년 전에 "그냥 간단한 래퍼"라고 맹세했던 하나의 마이크로 서비스가 이후 당신의 인프라의 절반에 대한 중요한 경로 종속성으로 전이된 것일 수도 있습니다. 당신은 아마 관리자에게 두 번째 페이지가 나가기 전에 90초가 남았을 것입니다. 고객들이 지원 채널로 쇄도하기 전에 세 분이 남았을 가능성이 있습니다. C-suite의 누군가가 깨어나 Slack에서 질문을 하기 전에 다섯 분이 남았을 것입니다. 시간이 촉박하고, 당신의 손은 움직이고, 당신의 뇌는 이미 수백 번의 이러한 사건을 통해 만들어진 정신적 체크리스트를 거치고 있습니다. 이건 당신의 첫 번째 로데오가 아닙니다. 하지만 오전 2시에 프로덕션 디버깅에 대해 아무도 말하지 않는 것이 있습니다: 절대 쉬워지지 않습니다. 당신은 그저 더 빨라질 뿐입니다. 당신은 더 나은 도구를 만듭니다. 당신은 더 적은 어리석은 실수를 합니다. 당신은 모든 것을 의심하면서도 본능을 신뢰하는 법을 배웁니다. 당신은 실제로 무엇이 망가졌는지와 무엇이 그냥 망가져 보이는지를 아는 제6 감각을 발전시킵니다. 그리고 가장 중요한 것은, 10분간의 사건과 4시간의 사건의 차이는 종종 당신의 반응의 첫 60초에 달려 있다는 것입니다. 이 가이드는 페이지 번호 1 이전에 누군가가 나에게 말해줬으면 했던 모든 것입니다.

첫 60초: 당신의 일이 달려 있는 것처럼 분류하세요

어떤 프로덕션 사건의 첫 분은 순수한 혼돈 관리입니다. 당신의 뇌는 아직 부팅 중이고, 아마 바지를 입고 있지 않으며, 이 사건이 몇 분 또는 몇 시간 안에 해결될지를 결정짓는 중요한 결정을 내려야 합니다. 매번 제가 하는 일은 다음과 같습니다: 페이지를 즉시 인지하세요. "먼저 조사하세요"라고 기다리지 마세요. 인지하세요. 이것은 에스컬레이션 체인을 멈추고 팀에 누군가가 처리하고 있다는 신호를 보냅니다. 첫 번째 응답자가 인지를 하기 전에 "빠르게 살펴보겠다"고 해서 여러 사람이 페이지를 받은 사건을 너무 많이 보았습니다. 조사하는 데 소요된 30초는 당신을 수면으로 돌아가게 할 수 있는 요청자를 잃게 만듭니다. 사건 대응 대시보드를 엽니다. 애플리케이션이 아닙니다. 로그도 아닙니다. 당신의 대시보드입니다. 시스템 상태를 한 눈에 보여주는 것입니다. 저에게는 오류율, 지연 퍼센타일, 데이터베이스 연결 풀, 큐 깊이, 그리고 모든 주요 서비스의 CPU/메모리를 보여주는 맞춤형 Grafana 대시보드가 있습니다. 5초 이내에 폭발 반경을 확인할 수 있습니다. 여전히 발생하고 있는지 확인하세요. 이건 명백하게 들리지만, 경고가 발동되기 30초 전에 스스로 해결된 문제로 인해 페이지를 받은 적이 있습니다. 모니터링 시스템은 지연이 있을 수 있습니다. 경고 임계값에는 평가 기간이 있습니다. 때때로 문제는 이미 사라졌고, 롤백하거나 서비스 재시작을 시작하기 전에 알아야 합니다. 고객 영향을 평가하세요. 이론적 영향이 아니라—실제 영향입니다. 지금 현재 몇 명의 사용자가 영향을 받고 있나요? 100%의 트래픽인가요, 아니면 5%인가요? 하나의 지역, 하나의 고객 세그먼트, 하나의 기능에 국한되어 있나요? 이것은 당신의 반응의 긴급성을 결정하고 더 많은 사람들을 깨워야 할지를 판단합니다. 이 특정 사건에서—오전 2시 17분의 결제 서비스—제 대시보드는 8초 만에 제가 알아야 할 모든 것을 알려주었습니다. 오류율: 94.7%. 영향을 받은 요청: 지난 5분 동안 847건. 지리적 분포: 전 세계. 고객 세그먼트: 모두. 결제 제공자 API 지연: 정상. 데이터베이스 연결: 정상. 문제는 상류나 하류에 있지 않았습니다. 우리가 문제였습니다. 그때 저는 긴 밤이 될 것임을 알았습니다.

압박 속에서 실제로 작동하는 디버깅 방법론

모든 사람은 차분하고 카페인이 가득하며 오후 2시에 개발 환경에서 작업할 때 디버깅 방법론을 가지고 있습니다. 누군가는 반쯤 잠이 드는 상태에서 CEO가 사건 채널에 있으며 모든 다운타임이 실제 돈을 잃게 만드는 순간에도 유지되는 방법론을 가진 사람은 매우 드뭅니다. 저는 "폭발 반경에서 근본 원인으로" 접근법을 사용합니다. 화려하진 않지만, 당신의 뇌가 60%의 용량으로 작동할 때 효과적입니다. 근본 원인에서 시작하지 말고 폭발 반경에서 시작하세요. 이것은 반직관적입니다. 모든 본능이 즉시 근본 원인을 찾으라고 합니다. 그 본능을 억제하세요. 먼저 무엇이 망가졌고 무엇이 망가지지 않았는지 정확히 이해합니다. 실패의 경계를 매핑합니다. 이것은 두 가지 목적을 수행합니다: 건강한 시스템에서 잘못된 단서를 쫓는 것을 방지하고, 종종 제거 과정을 통해 근본 원인을 직접 지시합니다. 결제 서비스 사건을 위해 저는 폭발 반경을 매핑하는 데 90초를 썼습니다: - 결제 시작: 실패 - 결제 상태 확인: 실패 - 결제 웹훅: 실패 - 환불 처리: 정상 작동 - 관리자 결제 조회: 정상 작동 그 패턴은 저에게 중요한 것을 말해주었습니다: 읽기 작업은 괜찮고 쓰기 작업은 실패하고 있었습니다. 이것은 데이터베이스 문제, 큐 문제 또는 권한 문제입니다. 30개의 가능성이 아닌 세 가지 가능성입니다. 코드 흐름이 아니라 데이터 흐름을 따르세요. 오전 2시에 디버깅할 때 코드를 추적할 시간이 없습니다. 데이터를 따르세요. 결제 요청이 시스템에 어떻게 들어오나요? 다음에 어디로 가나요? 어디서 실패하나요? 분산 추적을 가져왔고 (정말 다행이었습니다) 단일 요청이 시스템을 통해 흐르는 것을 보았습니다. 인증을 통과하고, 속도 제한을 통과하고, 유효성을 검사하고, 데이터베이스에 쓰려고 할 때 죽었습니다. 데이터베이스. 바로 그곳이었습니다. 지루한 것부터 먼저 확인하세요. 디스크 공간. 메모리. 연결 풀. 파일 디스크립터. 인증서 만료. DNS. 지루한 것이 영리한 버그보다 더 많은 프로덕션 시스템을 죽입니다. 누군가의 크론 작업이 디스크를 채운 것으로 인해 오전 2시에 페이지를 받았습니다. 누군가 인증서가 만료되었다고 해서 페이지를 받았습니다. 누군가가 DNS TTL을 변경하고 전파를 기다리지 않았기 때문에 페이지를 받았습니다. 이 경우, 데이터베이스 연결 풀은 100%였습니다. 모든 연결이 사용 중이었습니다. 하지만 왜? 트래픽이 급증한 것은 아니었습니다. 쿼리 패턴이 바뀐 것도 아니었습니다. 무언가 연결을 열어두고 있었던 것입니다. 모니터링을 신뢰하되 모든 것을 확인하세요. 모니터링 시스템은 거짓말을 합니다. 악의적이지는 않지만—그들은 그냥 소프트웨어이고, 소프트웨어에는 버그가 있습니다. 완전히 작동하지 않는 건강한 서비스라고 보고한 모니터링 시스템을 보았습니다. 존재하지 않는 오류를 보고한 모니터링 시스템도 보았습니다. 항상 중요 경로를 수동으로 확인하세요. 결제 시스템의 경우, 테스트 신용 카드와 curl 명령어를 준비해두고 있습니다. 10초 안에 전체 결제 흐름을 검증할 수 있습니다. 테스트 결제를 실행했습니다. 30초 동안 멈췄고 타임아웃이 발생했습니다. 모니터링은 거짓말을 하지 않았습니다. 우리는 실제로 다운되었습니다.

데이터베이스 연결에 대해 모든 것을 가르쳐준 사건

페이지 번호 312에 대해 말씀드리겠습니다. 3월의 화요일 오전 3시 47분이었고, 데이터베이스 연결 관리에 대한 저의 생각을 영원히 바꾸었습니다. 우리는 플래시 세일을 진행하고 있었습니다. 트래픽은 높았지만 전례 없는 것은 아니었습니다—더 큰 급증을 처리한 적이 있었습니다. 그러다 갑자기 데이터베이스에 접근하는 모든 서비스가 타임아웃되기 시작했습니다. 연결 풀이 고갈되었습니다. 전형적인 증상입니다. 명백한 대답: 연결 풀 크기를 늘리기. 그래서 그렇게 했습니다. 우리는 그것을 두 배로 늘렸습니다. 그런 다음 세 배로 늘렸습니다. 문제가 더 악화되었습니다. 그때 저는 때때로 해결책이 문제를 악화시킨다는 것을 배웠습니다. 우리가 풀에 추가하는 각 연결은 이미 과부하된 데이터베이스에서 쿼리를 실행하려는 또 하나의 연결이었습니다. 우리는 스스로 DDoS 공격을 하고 있었습니다. 실제 문제는? 한 개발자가 5천만 개의 행이 있는 테이블에 대한 전체 테이블 스캔을 수행하는 새로운 기능을 추가했습니다. 인덱스가 없습니다. 쿼리를 완료하는 데 45초가 걸렸습니다. 해당 코드 경로에 도달한 모든 요청은 45초 동안 데이터베이스 연결을 유지했습니다. 충분한 트래픽이 있을 경우, 우리는 연결 풀이 고갈된 것이 아니라, 모든 연결이 그 끔찍한 쿼리가 끝나기를 기다리며 갇혀 있었기 때문입니다. 해결책은 더 많은 연결이 아니었습니다. 쿼리를 종료하고, 인덱스를 추가하고, 애플리케이션 수준에서 쿼리 타임아웃을 구현하는 것이었습니다. 그 사건은 저에게 세 가지를 가르쳐 주었습니다: 연결 풀 고갈은 증상일 뿐입니다, 병이 아닙니다. 이것을 보면 즉시 풀을 확장하지 마세요. 왜 연결이 해제되지 않는지 물어보세요. 쿼리가 느린가요? 교착 상태가 있나요? 무엇인가 트랜잭션을 열어두고 있나요? 연결 풀은 다른 곳에 문제가 있다고 말해주고 있습니다. 쿼리 타임아웃은 어디에나 있어야 합니다. 모든 데이터베이스 쿼리는 타임아웃이 있어야 합니다. 모든 HTTP 요청에는 타임아웃이 있어야 합니다. 모든 큐 작업에는 타임아웃이 있어야 합니다. 타임아웃은 선택 사항이 아닙니다. 그것들은 저하된 서비스와 완전히 다운된 서비스의 차이입니다. 무언가 잘못될 때 타임아웃 덕분에 실패를 빨리 할 수 있으며, 전체 시스템이 붕괴되기까지 차단된 연결을 쌓지 않습니다. 연결 풀 사용량 모니터링만으로는 충분하지 않습니다. 연결 수명을 모니터링해야 합니다. 평균 연결이 얼마나 오래 유지됩니까? P99는 얼마입니까? 평균 연결 수명이 갑자기 50ms에서 5초로 증가한다면, 아직 풀이 고갈되지 않았더라도 문제가 있습니다. 그것은 당신의 조기 경고 시스템입니다. 결제 서비스 사건으로 돌아와서 오전 2시 17분. 저는 연결 수명을 확인했습니다. 평균: 8초. P99:
C

Written by the Cod-AI Team

Our editorial team specializes in software development and programming. We research, test, and write in-depth guides to help you work smarter with the right tools.

Share This Article

Twitter LinkedIn Reddit HN

Related Tools

Base64 Encode & Decode — Free Online Tool COD-AI vs Cursor vs GitHub Copilot — AI Code Tool Comparison SQL Formatter & Beautifier — Free Online Tool

Related Articles

10 Online Developer Tools That Save Hours Every Week — cod-ai.com CSS Beautifier vs Minifier: When to Use Which Code Review Checklist: What I Look for After 10 Years of PRs \u2014 COD-AI.com

Put this into practice

Try Our Free Tools →