오류 수정과 개선하기

in #krsuccessyesterday

오류는 무섭지 않아! 6-4 디버깅으로 코드 다듬기

이제 6-3 기능별 구현 단계까지 해왔으면, 솔직히 말하면… 프로그램이 “돌아는” 갔을 가능성이 커요.
근데 그게 끝이 아니더라고요. 보통 여기서부터가 진짜죠. 왜냐면 작동은 하는데 가끔 이상하게 동작하거든요. “어? 이 입력에서는 왜 이렇게 나와?” 같은 거요.

그래서 이번 글은 6-4 오류 수정과 개선하기입니다.
목표는 딱 하나예요: 오류를 찾아서 고치고, 코드도 좀 더 깔끔하게 만드는 법.

suixin390


1) 디버깅, 겁먹을 필요 없어요

디버깅이란 건 거창한 게 아니에요.
제가 처음 코딩 배울 때는 “오류 = 내 실력 부족”이라고 생각했는데… 사실은 오류가 있으면 프로그램이 말 걸어주는 거더라구요.

  • 오류 메시지: “나 지금 여기서 뻗었어”
  • 이상한 결과: “나는 이런 입력을 받아서 이런 계산을 했어”

그러니까 방향은 이미 정해져 있어요. 어디에서 문제가 생겼는지 찾아서 수정하면 끝!

congerdesign


2) 오류 메시지 읽는 법, 다시 써먹기

이전 글(1-5)에서 오류 메시지 읽는 법 했죠? 그걸 지금 바로 써먹습니다.
대충 이런 흐름이에요:

  1. 에러 메시지에 나온 핵심 단어 찾기
    • NameError, TypeError, ValueError 같은 거
  2. 메시지에 붙은 줄 번호(line number) 확인
  3. 해당 줄 주변에서 입력이 어떤 형태인지 / 변수 값이 뭔지 점검

예를 들어 이런 상황이 있으면요:

RyanMcGuire

total = "10" + 5

이건 솔직히… “10이 문자열이잖아? 거기에 숫자를 더하면 어떡해?” 같은 상황이에요.
이럴 때는 에러 메시지가 친절하게 알려줍니다.

  • TypeError: can only concatenate str (not "int") to str

이 메시지 뜨면, 그냥 당황하지 말고 “아, 문자열 + 숫자 문제구나”로 결론 내리면 돼요. 나름 속 시원하죠?


3) “재현”이 반이에요: 똑같이 만들어서 잡기

여기서 제가 예전에 진짜 많이 했던 실수 하나…
“아 맞다 그때는 됐는데?” 하면서, 조건을 놓치고 며칠을 끌었거든요. 유머러스하게 말하면… 범인을 못 잡으면 수사가 끝나지 않듯이요.

디버깅할 때는 이게 중요해요:

  • 어떤 입력에서 문제 생기는지 정확히 적기
  • 같은 입력이면 항상 같은 결과가 나오는지 확인
  • 가능하면 최소 입력으로 줄여서 테스트

예를 들어 계산기/메뉴 프로그램 만들었다면:

  • 1) 덧셈 선택했을 때
  • 첫 숫자 입력: 10
  • 둘째 숫자 입력: 5
  • 여기서 에러가 난다면, 그 입력을 그대로 재현하는 거죠.

jplenio


4) print로 쫓아가기 (가장 쉬운데 강력함)

“디버거 써야 하나요?” 물어보면… 사실 저는 처음엔 print가 제일 빠르다 쪽이에요.
특히 바이브 코딩 단계에서는요. 너무 거창한 도구 켜기 전에, 그냥 값 찍어보면 거의 잡힙니다.

예:

def add(a, b):
    print("DEBUG a:", a, "b:", b)
    return a + b

여기서 자주 나오는 패턴이 있어요.

  • 내가 생각한 값이 아니라 다른 타입이 들어옴
  • 입력을 받았는데 문자열 그대로임 (input()은 항상 문자열)
  • 변수 이름을 헷갈려서 엉뚱한 걸 더함

솔직히 말하면, 저도 가끔 “아니 분명 숫자로 바꿨는데 왜 문자열이지?” 이러고 멘탈 흔들리거든요. 근데 print 한 번 찍으면 바로 답이 나오더라구요.

suixin390


5) 흔한 오류 패턴 5가지 (이거 보면 반은 끝나요)

프로젝트 만들다 보면 반복적으로 나오는 것들만 먼저 정리해둘게요.

5-1. input()은 문자열이다

x = input("숫자: ")
print(x + 1)  # 에러!
  • x"10" 같은 문자열
  • 그래서 숫자 연산 하려면 변환 필요:
x = int(input("숫자: "))

5-2. 인덱스 범위 초과

items = ["a", "b"]
print(items[2])  # 에러!
  • 리스트는 0부터 시작
  • 길이 2면 인덱스는 0, 1까지만 가능

5-3. 딕셔너리 키가 없을 때

user = {"name": "철수"}
print(user["age"])  # 에러!
  • 키 체크하거나 기본값 처리 필요

5-4. 조건문에서 경우를 빼먹기

“1,2,3이면 되겠지” 하고 만들었는데 사용자가 4를 누르면?
그때 프로그램이 “어? 나는 뭐 해?” 하고 멈칫해요.

  • else를 넣거나, 범위 체크를 꼭 해요.

5-5. 함수 호출 인자를 순서대로 안 넘김

def divide(a, b):
    return a / b

divide(2, 10)  # 0.2 기대했는데 반대로면?
  • 이런 건 에러는 안 나는데 결과가 이상하게 나와서 더 짜증나요…
  • 그래서 출력으로 값 확인하는 게 진짜 중요해요.

RyanMcGuire


6) 고치고 끝? 아니죠, “개선”도 같이 해요

오류를 고치면 끝이라고 생각할 수 있는데, 나름 여기서 실력이 갈리더라구요.
왜냐면 같은 기능인데도 코드가 더 읽기 쉬워지고, 다음에 고치기 쉬워지면 그게 개선이니까요.

개선 포인트는 보통 이런 것들이에요:

  • 변수 이름을 더 명확하게 (x 말고 score 같은 느낌)
  • 반복되는 코드를 함수로 빼기
  • 조건문이 길어지면 정리하기
  • “주석”은 복잡한 이유를 설명하는 데만 쓰기 (코드 복붙 설명은 비추!)

그리고 좀 더 “친절한 프로그램”으로 만들 수도 있어요:

  • 사용자가 잘못 입력했을 때 바로 사과하기
  • 예: “숫자를 입력해주세요” 안내 후 다시 받기

솔직히 이런 거 하면, 프로그램이 갑자기 사람처럼 느껴져요. 나름 재밌고, 사용자 입장에서도 훨씬 편하거든요.

congerdesign


7) 실패담 1개만 유머로 풀고 갈게요 😅

예전에 메뉴를 만드는 프로그램을 만들었는데요…
어느 날 갑자기 제가 만든 메뉴가 “선택해 주세요”만 계속 출력하는 거예요.

원인은 간단했어요.

  • while 조건이 의도와 다르게 계속 참이었던 것
  • 그리고 “종료” 선택했을 때 변수가 갱신이 안 된 것

그때 저는 디버깅하면서 깨달았죠.

“코드는 생각보다 꼼꼼하게 따라온다. 내가 지시를 잘못하면 그대로 실행할 뿐이다.”

그래서 그 뒤로는 항상 종료 조건이나 반복 조건은 한 번 더 확인하게 됐어요. 지금도 그래요. 좀 습관이랄까…!


8) 이번 단계 체크리스트 (이대로만 하면 됨)

마지막으로, 작성 전에 스스로 확인해볼 질문들 가져갈게요.

  • [ ] 오류 메시지가 나왔던 줄 근처를 점검했고, 원인을 이해했다
  • [ ] 같은 입력에서 문제가 다시 재현되는지 확인했다
  • [ ] print/로깅(간단 출력)으로 변수 값과 타입을 확인했다
  • [ ] 사용자가 “이상한 입력”을 줘도 멈추지 않게 처리했다
  • [ ] 코드가 읽기 쉬운 형태로 조금이라도 정리됐다

jplenio


다음 글(6-5)에서는 드디어 작품 완성 및 공유로 넘어가요.
여기까지 고생해서 만든 프로그램, 이제는 “보여줄만한 형태”로 마무리하는 단계입니다.

다음 단계에서, 내가 만든 게 어디까지 완성인지 어떻게 마감하면 좋은지도 같이 정리해볼게요.