
이런 상황 겪어보셨죠
어떤 거대한 입력 파일이나 수천 줄짜리 코드에서 프로그램이 뻥 터졌어요(크래시). 그런데 정확히 어느 부분 때문에 터지는 건지 모르겠는 거예요. 5000줄을 일일이 지워가며 "이거 지우면 안 터지나?" 손으로 이분 탐색하다 보면 한나절이 그냥 날아가죠. 이때 진짜 과소평가되고 있는 도구가 바로 테스트 케이스 리듀서(test-case reducer)예요.
이게 뭐냐면요, 버그를 재현하는 거대한 입력을, 버그가 여전히 재현되는 선에서 자동으로 최대한 작게 줄여주는 프로그램이에요. 5000줄짜리 크래시 유발 코드를 "버그는 그대로 나면서 10줄짜리"로 깎아주는 거죠. 작아지면 원인이 눈에 확 보이거든요.
어떻게 동작하나
핵심 아이디어는 의외로 단순해요. 리듀서한테 딱 하나만 알려주면 돼요. "이 입력이 여전히 흥미로운가(=버그가 나는가)?"를 판단하는 스크립트 하나요. 이걸 보통 "interestingness test(흥미로움 판정)"라고 불러요. 예를 들면 "이 코드를 컴파일했을 때 컴파일러가 segfault로 죽으면 흥미롭다(=1을 리턴), 아니면 안 흥미롭다(=0)" 이런 식이에요.
그러면 리듀서는 이렇게 일해요. 입력의 일부를 뭉텅 지워본 다음, 아까 그 판정 스크립트를 돌려봐요. 여전히 버그가 나면 "오, 이 부분은 없어도 되네" 하고 줄어든 상태를 채택하고요, 버그가 안 나면 "이 부분은 필요했구나" 하고 되돌려요. 이걸 더 이상 줄일 게 없을 때까지 반복합니다. 처음엔 절반씩 크게 지우다가 점점 잘게 지워서 효율을 높이는 delta debugging(ddmin) 알고리즘이 고전적인 방식이에요.
여기서 똑똑한 도구들은 한 발 더 나가요. 그냥 텍스트를 줄 단위로 지우는 게 아니라, 언어의 문법 구조를 이해하면서 줄여요. 예를 들어 C 코드라면 함수 하나, 변수 하나, 표현식 하나를 문법적으로 말이 되게 통째로 들어내는 거죠. 그래야 "중간에 괄호만 사라져서 애초에 컴파일이 안 되는" 쓸모없는 결과를 피할 수 있거든요. 대표적인 도구가 컴파일러 버그 잡는 데 쓰는 C-Reduce(creduce)고, 언어 안 가리고 줄여주는 범용 도구로는 Shrinkray나 halfempty 같은 것들이 있어요.
업계 맥락
사실 이 개념은 우리가 이미 옆에서 쓰고 있어요. 속성 기반 테스트(property-based testing), 그러니까 QuickCheck이나 파이썬의 Hypothesis 같은 도구가 테스트 실패 시 "shrinking"이라는 이름으로 똑같은 일을 해요. 무작위로 만든 복잡한 실패 케이스를 사람이 보기 좋은 최소 케이스로 자동으로 줄여주거든요. 리스트 [3, 7, -2, 9]에서 터졌다면 [0] 하나로 줄여주는 식이죠. 컴파일러 개발자, 데이터베이스 엔진 개발자, 퍼징(무작위 입력으로 버그 찾기) 하는 보안 연구자들에겐 거의 필수 도구예요.
한국 개발자에게
이건 진짜 "알면 야근이 줄어드는" 실용 기술이에요. 꼭 컴파일러 만드는 사람만 쓰는 게 아니거든요. 여러분이 만드는 라이브러리나 서비스에서 "특정 큰 입력에서만 버그가 난다"는 이슈가 들어왔을 때, interestingness 스크립트 하나 짜서 리듀서 돌려놓고 커피 마시고 오면 최소 재현 케이스가 나와 있을 수 있어요. 버그 리포트 품질도 확 올라가고요. 또 property-based testing의 shrinking을 적극 활용하면, 테스트가 실패했을 때 디버깅 시간이 크게 줄어요. 평소에 Hypothesis 같은 도구를 테스트에 끼워두는 걸 추천합니다.
한 줄 정리: "버그 나는지 아닌지"만 판단하는 스크립트 하나면, 리듀서가 거대한 재현 케이스를 알아서 최소한으로 깎아준다.
여러분은 버그 최소 재현을 만들 때 보통 어떻게 하세요? 아직 손으로 줄이고 계셨다면, 다음번엔 리듀서 한번 돌려보는 거 어때요?
🔗 출처: Hacker News
"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"
실제 수강생 후기- 비전공자도 6개월이면 첫 수익
- 20년 경력 개발자 직강
- 자동화 프로그램 + 소스코드 제공