Rain Lag

1페이지 에러 플레이리스트: 반복되는 장애를 나만의 디버깅 라이브러리로 바꾸기

반복해서 발생하는 버그를 구조화된 ‘에러 플레이리스트’로 정리해, 나와 팀이 재사용할 수 있는 디버깅 지식 베이스로 만드는 방법.

1페이지 에러 플레이리스트: 반복되는 장애를 나만의 디버깅 라이브러리로 바꾸기

버그에는 두 가지 종류가 있습니다.

  1. 한 번 보고 다시는 안 나오는 것.
  2. 몇 주마다 한 번씩, 금요일 오후 4시 59분만 되면 꼭 다시 나타나는 것.

이 글은 두 번째 타입에 대한 이야기입니다. 그리고 어떻게 하면 매번 똑같은 문제를 다시 파헤치느라 시간을 낭비하지 않을 수 있는지에 대한 방법입니다.

반복되는 장애를 그때그때의 귀찮은 사고로만 취급하는 대신, 이를 개인(그리고 팀 전체)의 디버깅 라이브러리로 바꿀 수 있습니다. 한 페이지짜리 “에러 플레이리스트”를 만들어, 무엇이 잘못됐는지, 어떻게 디버깅했고, 무엇으로 해결했는지를 정리해 두면, 미래의 나(혹은 팀원들)는 같은 문제를 몇 시간 아니라 몇 분 만에 해결할 수 있습니다.


왜 에러 플레이리스트가 필요한가

대부분의 팀에는 이미 Jira 티켓, Slack 스레드, 로그, 그리고 구전 지식(tribal knowledge)이 섞여 있습니다. 그런데도 같은 에러가 다시 뜨면 결국 이렇게 되곤 합니다:

  • 어렴풋이 기억나는 Slack 메시지를 키워드로 뒤져보고,
  • 예전 티켓이나 PR을 끝없이 스크롤하고,
  • 매번 똑같은 시행착오 디버깅을 반복합니다.

에러 플레이리스트는 이런 반복을 줄이기 위한 가볍고 구조화된 방식입니다. 반복되는 문제를 다음과 같은 형태로 정리해 줍니다.

  • 한눈에 훑어보기 쉽고: 형식과 필드가 통일되어 있고, 불필요한 잡음이 적고
  • 맥락이 풍부하고: 에러 문자열만이 아니라 문제의 전체 상황을 담고
  • 검색 가능하며: 공유된 위치에 저장되고 태그와 링크로 연결되며
  • 살아있는 문서: 시간이 지날수록 점점 정제되고 보강됩니다.

가장 아픈 “히트곡”들로 만든 큐레이션 앨범이라고 생각해도 좋습니다. 단지 다시 듣지 않기 위한 앨범이라는 점만 다릅니다.


1. 구조적이고 일관된 포맷을 쓰기

지식 베이스가 망하는 가장 큰 이유는 일관성 부족입니다. 사람마다 기록하는 방식이 다르면, 항목은 읽기 어렵고, 훑어보는 건 거의 불가능해집니다.

그래서 모든 에러 항목에 공통으로 적용할 1페이지 템플릿을 정하고, 반드시 그 형식을 지키는 것이 중요합니다.

예시 구조는 다음과 같습니다.

에러 플레이리스트 항목 템플릿

  1. 이름 / 제목
    짧고 설명적이며 표준화된 이름: ServiceX-Timeout-on-ExternalAPI 처럼.

  2. 에러 시그니처 (Error Signature)

    • 에러 메시지 (정확한 문자열 또는 대표 형태)
    • HTTP status code, exception 타입, 로그 패턴 등
  3. 컨텍스트 (Context)

    • 어디서: 서비스, 모듈, 엔드포인트, 잡 이름 등
    • 언제: 발생 시간대, 환경(prod/staging/local), 부하 수준
    • 누가 / 무엇이 영향 받았는지: 사용자 타입, 기능, 서브시스템
  4. 입력 / 선행 조건 (Inputs / Preconditions)

    • 예시 요청 payload / 입력 데이터
    • 관련 설정값 또는 feature flag 상태
    • 관련 환경 변수
  5. 증거 (Evidence)

    • Stack trace (핵심이 빠지지 않는 선에서 적당히 정리)
    • 주요 로그 메시지(타임스탬프 포함)
    • UI 이슈라면 스크린샷
  6. 진단 경로 (Diagnosis Path)

    • 어떤 방식으로 디버깅했는지 (사용한 도구, 쿼리, 실험 등)
    • 다음에는 피해야 할 막다른 길(dead end)
  7. 근본 원인 (Root Cause)

    • 실제로 무엇이 잘못되었는지에 대한 간결한 설명
    • 깨진 시스템적 가정이나 설계 전제
  8. 해결 방법 (Fix)

    • 무엇을 어떻게 변경했는지 (설정, 코드, 인프라)
    • 단기 완화(mitigation)와 장기 솔루션을 구분
  9. 후속 작업 / 엣지 케이스 (Follow-Ups / Edge Cases)

    • 알려진 변형 케이스나 유사 이슈
    • 관련 티켓이나 tech debt
  10. 링크 (Links)

    • 코드 (PR/commit)
    • 티켓 (Jira, Linear 등)
    • 대시보드/알람

각 항목을 한 페이지(또는 한 화면) 안에 담도록 제한하면, 날카롭고 구체적으로 쓰게 되는 동시에, 다른 사람이 몇 초 안에 훑어볼 수 있을 정도로 구조가 잡힙니다.


2. 에러 문자열만이 아니라 “전체 컨텍스트”를 기록하기

에러 메시지 그 자체만으로는 대부분 충분하지 않습니다.

에러를 문서화한다는 것은 사실, 장애가 발생했을 때의 시스템 상태 스냅샷을 남기는 일입니다. 이 스냅샷이 정확할수록, 나중에 같은 문제를 디버깅하는 속도가 빨라집니다.

다음 정보를 포함하세요.

  • 입력 (Inputs)

    • 요청 payload나 이벤트 body (필요하다면 민감 정보는 마스킹)
    • 실패를 유발한 파라미터 값, ID, 조건
  • 환경 정보 (Environment details)

    • 서비스 버전 / git SHA
    • 환경 (prod/staging/local)
    • Feature flag와 설정값
  • 운영 컨텍스트 (Operational context)

    • 트래픽/부하 수준
    • 최근 배포, 마이그레이션, 다른 인시던트
    • 외부 의존성 장애(예: 서드파티 API 장애)
  • 진단 정보 (Diagnostics)

    • Stack trace (필요하다면 프레임 주석 등)
    • 호출 체인에 걸친 여러 서비스의 로그 부분
    • 인시던트 발생 시점 주변의 메트릭/대시보드 스크린샷

이런 정보가 없으면, 미래의 나는 똑같은 재현·탐색 과정을 또 반복해야 합니다. 반대로, 이런 정보가 잘 담겨 있으면, 바로 이렇게 물어볼 수 있습니다. “이건 예전에 겪었던 바로 그 장애인가, 아니면 겉모습만 비슷한 다른 문제인가?”


3. 살아있는 문서로 다루기

에러 플레이리스트는 과거의 고통을 보관만 해두는 정적 아카이브가 아닙니다. 시간이 지나면서 다음과 함께 계속 진화하는 살아있는 문서입니다.

  • 해결 방법을 다듬고
  • 새로운 엣지 케이스를 발견하고
  • 아키텍처, 의존성, 전제가 바뀌면서

몇 가지 간단한 룰을 정해 두면 좋습니다.

  • 항목을 항상 최신 상태로 유지하기
    같은 에러가 다시 발생해서 새로운 변형(variant)을 발견했다면, 새 항목을 만들지 말고 기존 항목을 업데이트하세요. 예를 들어 "v2: 2025-03-12에 발견된 신규 변형" 같은 섹션을 추가합니다.

  • 부분적인 정보라도 기록하기
    완벽한 근본 원인을 규명할 때까지 기다리기보다는, “가설(Hypothesis)” 상태라도 적어 두는 편이 낫습니다. 가설임을 명확히 표시해 두고, 이후에 업데이트하면 됩니다.

  • ‘고쳤다’가 아니라 ‘무엇이 어떻게 바뀌었다’를 기록하기
    “Sprint 22에서 해결”보다는, “PR #1234에서 retry 로직과 timeout 설정 추가”라고 남겨 두는 것이 훨씬 유용합니다.

시간이 흐르면서 각 항목은 이렇게 진화합니다: 초기 추측 → 부분적인 해결 → 충분한 이해 → 재발 방지로 안정화.


4. 검색 가능하고 팀이 함께 쓰게 만들기

에러 플레이리스트가 내 개인 메모 앱 안에만 있다면, 그건 전형적인 지식 사일로입니다.

이를 팀 전체의 디버깅 라이브러리로 만들려면 다음이 필요합니다.

  • 중앙 저장소를 정하기

    • 사내 문서 시스템(Confluence, Notion, Google Docs 등) 안의 전용 폴더
    • infra/debug-playlist 같은 repo에 Markdown 파일로 관리
    • 내부 개발자 포털의 전용 섹션
  • 빠르게 찾을 수 있게 만들기

    • 예측 가능한 파일명: ERR-001-serviceX-timeout.md처럼
    • 팀, 서비스, 컴포넌트별로 태그 달기
    • 실제 에러 문자열을 본문에 포함해서, 그대로 복붙 검색이 되게 하기
  • 누구나 기여할 수 있게 권한 열어두기
    한 사람만 작성하고 유지하는 구조보다, 모든 엔지니어가 항목을 추가·수정할 수 있을 때 가치가 기하급수적으로 커집니다.

이렇게 검색 가능하고 공유된 라이브러리가 있으면, 신규 입사자도 과거 디버깅 히스토리를 처음부터 다시 발명할 필요가 없고, 인시던트 대응 속도와 정신적 여유도 크게 좋아집니다.


5. 에러를 코드, 티켓, 히스토리와 연결하기

에러는 혼자 존재하지 않습니다. 코드, 인프라, 제품 결정, 프로세스와 모두 연결되어 있습니다.

각 에러 항목이 관련 산출물을 모은 **허브(Hub)**가 되도록 만들면, 플레이리스트의 힘이 훨씬 커집니다.

  • 코드 링크

    • 해결을 구현한 Pull Request / Merge Request
    • 관련 파일과 라인(가능하면 VCS의 permalink 사용)
  • 이슈 트래커

    • 버그를 추적했던 Jira/Linear 티켓
    • 해당 에러를 계기로 진행된 리디자인의 Epic이나 RFC
  • 운영 히스토리

    • 인시던트 리포트나 포스트모템
    • 알람 runbook
    • 온콜(당직) 노트

이렇게 하면, 시간이 지나면서 **그 이슈를 어떻게 이해하게 되었는지에 대한 서사(narrative)**가 보존됩니다. 이는 다음에 도움이 됩니다.

  • 새로 합류한 팀원이 특정 설계 결정의 “이유”를 이해하는 데
  • 온콜 엔지니어가 “예전에 뭐 해봤는지”를 빠르게 파악하는 데
  • 테크 리드가 반복되는 패턴과 시스템적 문제를 발견하는 데

6. 팀의 정기적인 리추얼에 플레이리스트를 녹여 넣기

아무도 읽지 않는 라이브러리는 행동을 바꾸지 못합니다.

에러 플레이리스트가 실제로 반복 장애를 줄이는 도구가 되려면, 팀의 정기적인 리추얼(ritual) 안에 녹여 넣어야 합니다.

  • 회고(Retrospective)

    • 지난 스프린트/인시던트 기간 동안 추가되거나 재발한 항목을 함께 리뷰합니다.
    • 질문합니다: 이 에러는 더 근본적인 아키텍처 변경을 촉발해야 할 정도인가?
  • 온보딩(Onboarding)

    • 신규 엔지니어 온보딩 자료에 플레이리스트 링크를 포함합니다.
    • 작은 과제를 줄 수도 있습니다: “에러 하나를 골라서, 링크를 따라가며 읽어보고, 배운 점을 요약해 보세요.”
  • 코드 리뷰(Code Review)

    • 인시던트 관련 PR을 리뷰할 때, 해당 이슈에 대한 플레이리스트 항목이 있는지, 업데이트됐는지 확인합니다.
    • PR 설명에 에러 항목 링크를 포함하도록 장려합니다.
  • 온콜 인수인계(On-call handoff)

    • 가장 자주 발생하거나 치명적인 항목을 하이라이트합니다.
    • “이 로그가 보이면, 먼저 ERR-003 항목을 확인하세요” 같은 노트를 남깁니다.

이렇게 하면 과거 실패가 개별적인 불 끄기(firefighting)가 아니라, 공유 학습으로 전환됩니다.


7. 체계적인 분석을 위해 이름과 로깅을 표준화하기

한 단계 더 나아가려면, 단순히 이슈를 기록하는 수준을 넘어, 체계적으로 분석할 수 있어야 합니다.

그 출발점이 바로 표준화입니다.

  • 일관된 에러 네이밍

    • 예를 들어 SERVICE-COMPONENT-ERROR_TYPE 같은 스킴을 정합니다.
      예: BILLING-Invoices-ExternalAPITimeout
    • 이 코드를 모든 에러 경로에서 일관되게 로그에 남깁니다.
  • 구조화된 로깅(Structured logging)

    • error_code, service, environment, request_id 같은 필드를 포함합니다.
    • error_code는 플레이리스트 항목과 일치시키세요.
  • 그룹화와 우선순위 부여

    • 모니터링 도구에서 error_code 기준으로 에러를 그룹화합니다.
    • 정기적으로 리뷰합니다: 어떤 에러 코드가 가장 자주, 혹은 가장 심각하게 발생하는가?
    • 이 데이터를 바탕으로 엔지니어링 작업의 우선순위를 정합니다.

로깅, 모니터링, 플레이리스트가 같은 식별자를 사용하면 다음이 가능해집니다.

  • 알람에서 플레이리스트로 한 번에 점프하기
  • 특정 에러가 얼마나 자주 발생하는지, 추세가 어떤지 정량적으로 파악하기
  • 투입해야 할 엔지니어링 리소스를 수치로 설득하기

마무리: 전체를 한 번에 정리해 보기

엄청난 프로세스 개편이 필요한 일은 아닙니다. 이번 주 안에도 바로 시작할 수 있습니다.

  1. 1페이지 템플릿을 문서 도구나 repo 안에 만듭니다.
  2. 최근에 특히 고통스러웠던 에러 세 개를 골라, 템플릿에 맞춰 문서화합니다.
  3. 플레이리스트를 팀과 공유하고, 누구나 추가·수정할 수 있도록 초대합니다.
  4. 포스트모템과 버그 픽스 PR에 체크리스트 항목을 추가합니다: “플레이리스트 항목 생성/업데이트 완료?”
  5. 다음 회고에서 플레이리스트를 함께 리뷰합니다.

시간이 지나면, 에러 플레이리스트는 이렇게 자리 잡습니다.

  • 나와 팀을 위한 장기 기억 확장 도구로,
  • 신규 엔지니어를 위한 학습 리소스로,
  • 아키텍처 개선 기회를 알려주는 신호 발생기로.

무엇보다, 디버깅의 감정 곡선을 바꿔 줍니다. 같은 장애를 끝없이 다시 겪는 데자뷰 지옥에서 벗어나, 각 인시던트를 잘 정리된 플레이리스트에 트랙 하나를 추가하는 경험으로 바꿉니다. 이렇게 쌓인 플레이리스트는 시간을 아끼고, 스트레스를 줄이고, 팀 전체가 더 자신 있게 제품을 배포하도록 도와줍니다.

지금부터 에러를 기록해 두세요. 미래의 당신이 정말 고마워할 겁니다.

1페이지 에러 플레이리스트: 반복되는 장애를 나만의 디버깅 라이브러리로 바꾸기 | Rain Lag