노트

최소 재현

Minimal Reproducible Example

개발 문화#debugging · 연결된 개념 11개

쉽게 말하면

최소 재현은 차에서 나는 이상한 소리를 정비소에 '이 속도로 이 길에서 브레이크 밟으면 나요'까지 좁혀 말하는 거예요. 조건을 줄이다 보면 원인이 저절로 드러나기도 해요.

비유가 깨지는 곳 차 소리는 매번 나지 않을 수 있지만 코드는 시드·시간·네트워크 응답을 고정해 매번 같은 결과가 나오게 만들 수 있어요. 그렇게 재현되면 실패하는 테스트로 고정해 둬요.

버그가 나는 복잡한 코드에서 상관없는 부분을 걷어 내고, 버그가 여전히 일어나는 가장 작은 형태(Minimal Reproducible Example, MRE)를 만드는 것이다. 줄이는 과정 자체가 디버깅이다. 무언가를 지웠더니 버그가 사라졌다면 그 부분이 단서다.

줄이는 방법

  • 함수 호출을 하드코딩한 값으로 바꿔도 버그가 나는지 본다
  • 의심 가지 않는 큰 덩어리를 주석 처리해 범위를 반씩 줄인다
  • 잘 동작하는 예제(문서의 예시 등)에서 출발해 조금씩 내 코드처럼 바꾸다 깨지는 지점을 찾는다
  • 한 번에 하나만 바꾼다. 여러 개를 한꺼번에 바꿨다면 되돌리고(git stash) 하나씩 다시 한다

무작위성 없애기

열 번에 한 번 나는 버그는 디버깅하기 어렵다. 매번 같은 결과가 나오게 만든다.

  • 난수 생성기(Random Number Generator)에 시드(Seed)를 고정한다
  • 현재 시간을 가짜로 고정한다(faketime, 테스트용 시계 주입)
  • HTTP(HyperText Transfer Protocol) 요청을 녹화해 재생한다(Ruby의 VCR 같은 도구, 프런트엔드라면 MSW로 API 모킹)
  • 실행 전체를 녹화하고 재생하는 디버거(rr 등)를 쓴다

실패하는 테스트로 고정하기

재현이 되면 그것을 테스트로 만든다.

남에게 물을 때

이슈를 올리거나 질문할 때 최소 재현을 붙이면 답을 받을 확률이 크게 오른다. 만드는 도중에 스스로 답을 찾는 경우도 많다 → 러버덕 디버깅

디버깅의 전체 흐름에서는 세 번째 단계에 해당한다 → 디버깅 문제 정의 5단계

출처: The Pocket Guide to Debugging Julia Evans · 참고: How to create a Minimal, Reproducible Example Stack Overflow

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 테스트 냄새

    테스트 코드나 테스트 습관에서 나는, 더 깊은 문제를 알리는 신호. 제라드 메스자로스의 xUnit 테스트 패턴 정리가 이름을 붙였다.

  • 예외 삼키기

    예외를 잡아 놓고 아무 처리 없이 흘려보내는 안티패턴(Anti-pattern). 빈 catch뿐 아니라 debug 레벨로만 찍고 정상인 척 진행하는 것도 마찬가지다.

  • 재귀

    함수가 자기 자신을 다시 호출해 문제를 푸는 방식. 같은 함수를 점점 작은 입력으로 부르다가 더 나눌 필요가 없는 지점(기저 조건, Base Case)에서 멈춘다.

  • 섣부른 최적화

    "섣부른 최적화는 모든 악의 근원이다." 도널드 크누스(Donald Knuth)가 1974년 글 「Structured Programming with go to Statements」에서 쓴 말이다. 원문의 맥락은 작은 효율은 대부분(약 97%)의 경우 잊으라는 것이고, 정말 중요한 3%는 놓치지 말라는 말이 이어진다.

  • 심플 디자인

    켄트 벡이 XP(Extreme Programming)에서 제시한 단순한 설계의 네 가지 규칙. 우선순위 순으로 ① 모든 테스트를 통과하고 ② 의도를 드러내고 ③ 중복이 없고 ④ 요소가 가장 적다. 마틴 파울러가 이렇게 정리한 형태가 널리 쓰인다.

보기 옵션