Rain Lag

디버깅 디브리핑: 모든 버그 수정을 확실한 배움으로 바꾸는 15분 포스트모템 의식

버그를 고친 직후 15분만 투자해 실행할 수 있는 실용적인 디버깅 디브리핑 의식. 고통스러운 문제를 오래가는 학습, 더 튼튼한 테스트, 더 나은 팀 관행으로 바꾸는 방법을 소개합니다.

디버깅 디브리핑: 모든 버그 수정을 확실한 배움으로 바꾸는 15분 포스트모템 의식

힘들게 악성 버그를 잡고, 수정 코드를 푸시하고, 드디어 안도의 한숨을 쉽니다.

그러고 몇 주 뒤, 수상하게 비슷한 버그가 다시 등장합니다… 그리고 지난번에 무엇을 배웠는지 정확히 기억나지 않는다는 걸 깨닫죠.

이 글은 바로 그 문제에 대한 이야기입니다.

우리는 압박 속에서 버그를 고치는 데는 익숙합니다. 하지만 그 버그 수정을 다음에 다시 쓸 수 있는, 오래가는 배움으로 만드는 것—직관을 쌓고, 이후 디버깅 속도를 높이고, 팀의 관행을 개선하는 그 배움—에는 훨씬 서툽니다.

그래서 등장하는 게 15분 디버깅 디브리핑입니다. 대형 장애뿐 아니라 일상적인 버그를 고친 뒤에 돌려보는, 작고 반복 가능한 포스트모템 의식입니다. 이 의식은 다음을 목표로 설계되어 있습니다.

  • 짧게 (약 15분)
  • 가볍게 (하나의 간단한 템플릿)
  • 반복 가능하게 (꾸준히 할 수 있도록)
  • 근본 원인놓친 신호에 집중하도록

시간이 지나면, 이 의식은 **디버깅 근육 기억(debugging muscle memory)**을 만들어 줍니다. 패턴을 더 빨리 알아보고, 더 나은 테스트를 작성하고, “이거 예전에 본 것 같은데…” 하는 사고를 줄여 줍니다.


왜 디버깅 디브리핑을 해야 할까?

전통적인 인시던트 리뷰(예: Howie, Google의 post‑incident review 등)는 훌륭합니다. 하지만 보통은 큰 장애에만 사용됩니다. 반면, 실제로 가장 많은 학습 기회가 숨어 있는 곳은 매일 쏟아지는 자잘한 버그들입니다.

  • 스테이징에서만 재현되던 이상한 직렬화 이슈
  • 두 번이나 “고쳤다”고 생각한 플레이키 테스트
  • 코드 리뷰를 통과해 버린 off‑by‑one 오류

이런 순간이야말로 이렇게 물어야 하는 완벽한 타이밍입니다.

이게 정확히 어떻게 생겼고, 다음에는 미리 눈치채려면 무엇을 바꿔야 할까?

일관된 디브리핑은 다음에 도움이 됩니다.

  • 배운 내용을 바로 강화한다 (기억이 생생할 때)
  • 반복 패턴을 발견한다 (예: 타임존 버그, 캐시 문제, 레이스 컨디션 등)
  • 놓쳤던 신호를 기록해서 다음에는 더 빨리 알아본다
  • 테스트와 툴을 조금씩 개선한다 (큰 사고 후에 한 번에 몰아서가 아니라)
  • 지식을 팀 전체로 확산시킨다 (버그를 고친 사람 머릿속에만 두지 않고)

그리고 이게 15분이면, 치명적인 장애뿐 아니라 대부분의 버그 뒤에도 현실적으로 해볼 수 있습니다.


단 하나의 필수 조건: 디브리핑 전에 재현 가능해야 한다

의미 있는 디브리핑 전에 반드시 갖춰야 할 조건이 하나 있습니다.

버그를 테스트나 개발 환경에서, 수정 전후에 신뢰할 수 있게 재현할 수 있어야 합니다.

이게 안 되면 나머지는 전부 추측일 뿐입니다.

목표는 다음 세 가지입니다.

  1. 통제된 환경에서 버그를 원하는 대로 재현할 수 있다.
  2. 그 재현 방법을 자동화된 테스트나 스크립트로 캡처해 둔다.
  3. 동일한 재현 절차를 돌려서 수정이 실제로 유효한지 검증한다.

이 세 가지는 강력한 효과를 냅니다.

  • 버그를 구체적으로 이해하도록 강제한다 (로그만 찍어 보며 어림잡지 않고).
  • 회귀(regression)를 막는다—테스트가 가드레일이 된다.
  • 디브리핑에서 참고할 수 있는 공유 아티팩트를 제공한다.

만약 버그를 안정적으로 재현할 수 없다면, 그 자체로 별도 체크리스트가 필요할 만큼 큰 주제입니다. 그래도, 재현 없이 포스트모템으로 바로 넘어가지는 마세요. 먼저, 최대한 반복 가능한 행동에 가깝게 만들어 보세요.


15분짜리 디버깅 디브리핑 템플릿

6페이지짜리 문서나 정식 회의가 필요하지 않습니다. 작고 일관된 템플릿 하나면 됩니다. 무거운 인시던트 리뷰 프레임워크에서 가볍게 가져온 버전이라고 보면 됩니다.

아래는 혼자서도, 팀과 함께도 약 15분 안에 진행할 수 있는 가벼운 버전입니다.

이 템플릿은 공유 문서, 위키, 티켓 시스템 템플릿 등 어디에든 저장해 두고 쓰면 좋습니다.

1. 사용자가 체감한 문제는 무엇이었나? (1–2분)

  • 누가, 또는 무엇이 영향을 받았는가?
  • 어떤 형태로 나타났는가? (에러 메시지, 잘못된 결과, 타임아웃, 크래시 등)
  • 어떻게 발견했는가? (모니터링, 사용자 제보, 테스트 실패 등)

짧고 구체적으로 적습니다. 예를 들어:

/checkout 엔드포인트에서 에러율 증가 알람을 통해 발견. 체크아웃 요청이 간헐적으로 HTTP 500으로 실패했다.

2. 어떻게 재현했는가? (2–3분)

정확한 단계나 테스트를 적습니다.

  • 환경 (로컬, 스테이징, 프로덕션 스냅샷 등)
  • 선행 조건 (데이터, 설정, 피처 플래그 등)
  • 수행한 단계
  • 지금은 이 버그를 캡처하고 있는 테스트, 스크립트, 명령어

예를 들면 다음과 같습니다.

스테이징 환경에서 장바구니에 10개 이상의 상품을 넣고 특정 프로모션 코드를 적용하면 재현됨. CheckoutPromoIntegrationTest.shouldApplyBogoDiscount()에 자동화된 재현 테스트 추가.

이 섹션은 다른 사람이 직접 돌려볼 수 있도록 재현 레시피를 문서화하는 단계입니다.

3. **근본 원인(root cause)**은 무엇이었나? 증상이 아니라. (4–5분)

이 부분이 디브리핑의 핵심입니다.

시스템이 이렇게 행동했는가?”를 묻고, 여기에 대해 “왜?”를 2–3번 더 파고듭니다.

다음 내용을 찾으려는 겁니다.

  • 버그를 유발한 구체적인 조건 (예: null 값, 레이스 컨디션, 오버플로우 등)
  • 그걸 가능하게 만든 설계나 가정 (예: “이 필드는 항상 non‑null일 거라고 가정했다”)
  • 사용자에게 노출되기까지 허용한 프로세스의 빈틈 (예: 특정 종류의 테스트 부재, 모니터링 블라인드 스폿 등)

좋지 않은 근본 원인 기술:

근본 원인: if 조건이 잘못됨.

더 나은 근본 원인 기술:

근본 원인: 프로모션을 적용하는 시점에는 모든 장바구니에 배송 방법이 설정되어 있다고 가정했다. 하지만 사용자가 이메일의 저장된 프로모션 링크를 사용해 들어온 경우, 장바구니가 배송 방법 없이 생성되면서 프로모션 엔진에서 null pointer 예외가 발생했다. 테스트에서 배송 방법이 없는 장바구니는 다루지 않았다.

이 과정을 통해 다음과 같은 명확한 멘탈 모델을 얻고 싶습니다.

이런 종류의 버그는, 조건 Y에서 가정 X가 깨질 때 발생한다.

4. 우리가 놓쳤거나 오해한 신호는 무엇이었나? (3–4분)

여기서부터 학습이 정말로 누적되기 시작합니다.

질문해 봅니다.

  • 더 일찍부터 존재했지만 우리가 눈여겨보지 못한 단서가 있었는가?
  • 로그, 메트릭, 알람이 이미 문제를 가리키고 있었는데, 우리가 잘못 해석했는가?
  • 플레이키 테스트나 경고를 “노이즈”라며 무시한 적이 있었는가?
  • 예전에 겪었던 버그와 비슷해 보였는데, 연결하지 못했는가?

놓친 신호의 예:

  • 실패 직전에 항상 찍히던 로그 라인, 그러나 아무도 신경 쓰지 않았던 것.
  • 인시던트 며칠 전부터 서서히 움직이던 메트릭.
  • “한동안” 플레이키였지만 우선순위에서 밀렸던 테스트.

2–3개 정도만 캡처하면 충분합니다. 목적은 누구를 탓하는 게 아니라, 패턴 인식 능력을 조율하는 데 있습니다.

다음에 로그에서 X, 메트릭에서 Y를 동시에 보면, 즉시 Z를 의심하자.

시간이 지나면, 이 단계가 뇌를 훈련시켜 더 빨리 눈치채고 더 빨리 연결하게 만듭니다.

5. 어떤 관행, 테스트, 도구를 다듬어야 할까? (3–4분)

여기서 디브리핑이 실제 시스템과 습관의 개선으로 이어집니다.

질문해 봅니다.

  • 이 버그를 더 일찍 잡을 수 있는 테스트는 무엇이었나? 지금 바로 추가할 수 있는가?
  • 코드 리뷰에서 추가해야 할 새로운 체크가 있는가? (예: 외부 입력은 항상 null 처리하기)
  • 이 영역에 대한 모니터링이나 로깅을 추가하거나 개선해야 할까?
  • 같은 잘못된 가정을 다시 하지 않도록, 업데이트해야 할 문서가 있는가?

액션 아이템은 작고 구체적이어야 합니다. 예를 들어:

  • 배송 방법이 없는 장바구니에 대한 유닛 테스트를 추가한다.
  • “프로모션 엔진” 문서에, 이 단계의 장바구니에는 배송 정보가 없을 수 있음을 명시한다.
  • 배송 방법 없이 프로모션이 적용되는 경우 디버그 로그를 남기도록 추가한다.

버그 하나당 1–3개의 실행 가능한 개선을 목표로 하세요. 절대 실행되지 않을 위시리스트를 만드는 것이 목적이 아닙니다.


특별한 이벤트가 아니라 루틴으로 만들기

이 의식은 습관이 되지 않으면 효과가 없습니다. 가끔 하는 특별 행사로 남으면 안 됩니다.

루틴으로 만드는 방법 몇 가지:

  • 티켓 템플릿에 “디버깅 디브리핑” 섹션을 추가합니다. 이 섹션을 채우기 전에는 버그 티켓을 종료하지 않습니다.
  • 15분으로 타임박스합니다. 타이머를 맞춰두세요. 더 길어진다면, 소설을 쓰려는 중일 가능성이 큽니다.
  • 처음에는 혼자 디브리핑부터 시작하고, 가끔 흥미로운 사례를 스탠드업이나 주간 “버그 클리닉”에서 공유합니다.
  • 팀 디브리핑을 할 때는 퍼실리테이터를 돌아가며 맡습니다. 모두가 더 좋은 질문을 던지는 법을 배우게 됩니다.
  • **블레임리스(blameless)**하게 진행합니다. 누가 “실수했는지”가 아니라, 어떤 시스템/가정/신호가 문제였는지에 집중합니다.

핵심은, 대부분의 버그 뒤에도 현실적으로 할 수 있도록 진입 장벽을 충분히 낮게 유지하는 것입니다.

버그 수정 → 재현 및 테스트 확보 → 15분 디브리핑 → 종료.


한 번짜리 수정을 넘어, 디버깅 근육 기억 만들기

처음에는 이 과정이 “일이 하나 더 생긴 느낌”일 수 있습니다. 하지만 몇 주만 지나도 패턴이 보이기 시작합니다.

  • “우리는 외부 API가 null을 반환하지 않을 거라고 반복해서 가정한다.”
  • “타임존/서머타임 경계 조건은 거의 테스트하지 않는다.”
  • “이 중요한 큐를 모니터링하지 않아서, 항상 너무 늦게 문제를 안다.”

디버깅 세션이 점점 빨라집니다. 왜냐하면:

  • 익숙한 실패 형태를 더 빨리 알아봅니다.
  • “예전에 이거랑 비슷한 버그가 있었지”가 떠오르고, 그때의 진짜 원인을 기억합니다.
  • 어떤 메트릭과 로그를 먼저 봐야 할지 이미 알고 있습니다.

팀 차원에서도 이런 변화가 생깁니다.

  • 실제로 겪은 버그와 그 진단 과정의 라이브러리가 쌓입니다.
  • 테스트와 모니터링이 점진적으로 개선됩니다. 큰 사고가 난 뒤에만 급히 손보는 게 아니라.
  • 근본 원인과 신호를 설명하는 공통 언어가 생깁니다.

이게 바로 디버깅 근육 기억입니다. 마법이 아니라, 작고 일관된 의식에 반복적으로 투자하는 의도적인 연습일 뿐입니다.


다음 버그부터 시작하자

거창한 도입 계획도, 새로운 툴도 필요 없습니다.

다음 버그가 생기면 이렇게 해보세요.

  1. 테스트나 개발 환경에서 신뢰할 수 있게 재현할 수 있도록 만든다.
  2. 버그를 고친 뒤, 15분을 블록으로 잡는다.
  3. 아래 템플릿을 따라가며 디브리핑한다.
    • 사용자가 체감한 문제는 무엇이었는가?
    • 어떻게 재현했는가?
    • 증상을 넘어서, 근본 원인은 무엇이었는가?
    • 어떤 신호를 놓쳤거나 오해했는가?
    • 어떤 관행, 테스트, 도구를 개선할 것인가?

이 디브리핑을 팀이 볼 수 있는 곳에 저장해 두세요.

이걸 몇십 번 반복해 보면 깨닫게 될 겁니다. 버그가 사라지는 건 아닙니다. 하지만 여러분과 팀은 더 빠르고, 더 똑똑하고, 훨씬 덜 데자뷔를 느끼며 버그를 다루게 됩니다.

이것이 15분 디버깅 디브리핑의 조용한 힘입니다. 고친 버그가 그냥 사라져 버리는 대신, 당신을 더 나은 엔지니어로 만들어 줍니다.

디버깅 디브리핑: 모든 버그 수정을 확실한 배움으로 바꾸는 15분 포스트모템 의식 | Rain Lag