디버깅: 직접 찾아내기
다른 사람에게 먼저 물어보지 않고 디버깅하는 실용적인 가이드 — 버그를 분리하고, 검증하고, 실제로 이해하는 방법.
대부분의 초보자는 버그를 벽처럼 대한다. 부딪히고, 멈추고, 다른 사람에게 넘어가달라고 부탁한다. 실제 실력을 쌓는 습관은 다르다: 버그를 답을 찾을 수 있는 질문처럼 대하는 법을 배우고, 묻기 전에 직접 찾는 것이다.
에러 메시지를 잡음이 아니라 증거처럼 읽어라
스택 트레이스는 무섭게 보인다고 계속 건너뛴다. 하지만 보통 정확히 어디서, 왜 무언가가 깨졌는지 말해준다. Python에서 TypeError: 'NoneType' object is not subscriptable을 받으면, 그건 임의의 난센스가 아니다 — 리스트나 딕셔너리를 가질 것으로 예상한 변수가 실제로 None이라는 뜻이다. 줄 번호는 그 위치를 말해준다. 그 줄에서 거슬러 올라가 값이 설정되어야 했지만 설정되지 않은 곳을 찾는 것이 당신의 일이다.
온라인에서 뭔가를 검색하기 전에 이렇게 하라: 트레이스백의 마지막 줄을 먼저 읽고, 위로 올라간다. 마지막 줄은 보통 실제 예외를 이름으로 명시한다. 위의 줄들은 거기에 도달한 호출 체인을 보여준다.
의도적으로 재현해라
버그가 가끔만 나타나면, 아직 이해하지 못한 것이다. 코드를 건드리기 전에 신뢰할 수 있게 발생시켜보자. 한 번에 입력 하나씩 바꿔본다. 빈 리스트로는 실패하지만 가득 찬 리스트로는 실패하지 않는가? 함수를 처음이 아니라 두 번째 호출할 때만 실패하는가? 명령어로 재현할 수 있는 버그는 80% 해결된 버그다. 왜냐하면 이제 수정이 실제로 작동했는지 추측 대신 테스트할 수 있기 때문이다.
문제를 반으로 나누고, 또 반으로 나눠라
이진 탐색은 정렬된 배열만을 위한 것이 아니다 — 긴 함수나 파이프라인에서 깨진 코드를 찾는 가장 빠른 방법이다. 로직의 두 번째 절반을 주석 처리하거나 우회하고 첫 번째 절반이 여전히 버그를 생성하는지 확인한다. 그렇다면 문제는 첫 번째 절반에 있다. 아니면 두 번째 절반에 있다. 반복한다. 이것은 200줄 스크립트에서와 마찬가지로 print() 또는 df.head()로 각 단계의 출력을 확인하는 다단계 데이터 파이프라인에서도 작동한다.
이것은 압박감에서 행을 임의로 바꾸고 다시 실행하는 것보다 낫다. 그것은 시간을 절약하는 것보다 훨씬 더 많은 시간을 낭비한다.
print()가 작동을 멈출 때 디버거를 print() 대신 사용하라
print() 문은 간단한 경우에는 괜찮지만, 여러 함수 호출에 걸쳐 상태를 추적하기 시작하면, 실제 디버거는 실시간을 절약한다. Python에서는 의심스러운 줄 바로 앞에 import pdb; pdb.set_trace()를 놓고, 스크립트를 실행하면, 변수를 검사하고 n으로 한 줄씩 단계를 밟고 s로 함수 호출로 들어갈 수 있는 라이브 프롬프트를 얻는다. VS Code의 내장 디버거는 입력 대신 클릭하는 중단점으로 같은 작업을 한다. 어느 쪽이든 목표는 같다: 아마도 어떨 것인지 추측하는 대신 프로그램의 실제 상태를 보는 것이다.
나머지 프로젝트에서 분리해라
버그가 큰 코드베이스 안에서 발생하면, 큰 코드베이스 안에서 디버깅하지 말자. 관련 함수를 같은 실패를 유발하는 가짜, 최소한의 입력을 가진 새 파일로 복사한다. 버그가 사라지면, 주변 문맥 — 전역 변수, 임포트, 낡은 상태 — 이 실제 원인이고, 방금 뭔가 중요한 것을 배웠다. 버그가 고립 상태에서도 지속되면, 이제 작고, 공유할 수 있고, 테스트 가능한 경우가 있고, 실제 수정에 훨씬 더 가까워졌다.
메모리가 아니라 현실에 대해 당신의 가정을 확인하라
디버깅 시간의 많은 부분이 의심하지 않은 가정에 간다:
AI 도움을 받아 작성했으며, Michal Pilch(CISSP), Korra Studio에서 검토 및 게시했어요.
이것은 Korra Studio 나레지베이스의 한 노트예요. 플랫폼은 모든 주제를 1-to-1 멘토링과 함께 제공해요.
무료로 시작하기arrow_forward