파이썬을 배우다 보면 다양한 오류를 마주하게 됩니다. 어떤 오류는 즉시 원인을 파악할 수 있지만, 어떤 오류는 초보자에게 혼란을 줍니다. 이 문서는 상위 5개 오류를 우선순위로 정리하고, 각 오류에 대한 설명, 예제, 원인, 해결책, 예방 방법, 그리고 실무에서 유용한 체크리스트를 제공합니다.
5 들여쓰기 오류 — IndentationError
들여쓰기 오류는 파이썬에서 가장 흔한 오류 중 하나입니다. 파이썬은 중괄호 대신 들여쓰기로 코드 블록을 구분합니다. 즉, 같은 블록에 속한 모든 문장은 동일한 들여쓰기 수준을 가져야 합니다. 들여쓰기 수준이 바뀌면 새로운 블록이 시작되거나 끝납니다. 일관성이 깨지면 IndentationError
가 발생합니다.
예시
for i in range(5):
print(i)
중요: 위 코드를 복사/붙여넣기할 때 편집기마다 탭과 스페이스 처리 방식이 달라 들여쓰기가 깨질 수 있습니다.
빠른 해결책
- 들여쓰기 수준을 일관되게 맞춥니다:
for i in range(5):
print(i)
- 탭과 공백(스페이스)을 혼용하지 마세요. 일반적으로 공백 4칸을 사용합니다.
- 에디터에서 ‘보이지 않는 문자 표시‘를 켜고 탭과 스페이스를 확인합니다.
- 프로젝트 루트에 .editorconfig 또는 편집기 설정을 추가해 규칙을 강제합니다.
디버깅 체크리스트
- 해당 블록의 모든 줄이 같은 들여쓰기인가?
- 탭과 스페이스가 혼용되어 있지는 않은가?
- 복사/붙여넣기 후 들여쓰기가 변형되진 않았나?
- 자동 포매터(black, autopep8)를 적용해 정상화했는가?
발생 빈도와 상황
- 초보자가 블록 구조를 잘못 이해했을 때 흔히 발생합니다.
- 코드 조각을 붙여넣거나, 서로 다른 편집기에서 작업할 때 자주 발생합니다.
4 문법 오류 — SyntaxError
모든 프로그래밍 언어는 문법(syntax)이 있습니다. 문법 규칙을 어기면 파이썬 인터프리터가 코드를 이해하지 못하고 SyntaxError
를 발생시킵니다. SyntaxError
는 프로그램이 시작조차 하지 못하게 막습니다.
흔한 원인
- 코드 블록 시작 시 콜론(:) 누락
- 키워드 오타 (예:
esle
대신else
) - 예약어를 변수명으로 사용
- 연산자 오용 (예: 비교문에서
=
대신==
필요) - 괄호나 따옴표를 닫지 않음
예시와 설명
if x > 0
print('positive')
위 코드에서는 if
다음에 콜론이 빠져 있어 SyntaxError
가 발생합니다.
해결 방법
- 파이썬 인터프리터가 출력하는 라인과 위치 정보를 확인합니다. 때로는 실제 오류가 그 전 줄에 있는 경우가 있습니다.
- IDE의 문법 검사 기능(린터)을 활용하세요.
- 작은 코드 단위로 실행해 어느 문장에서 오류가 나는지 좁혀갑니다.
예방 팁
- 코드를 자주 포매팅하세요(black, isort 등).
- 코드 리뷰에서 문법 규칙을 체크합니다.
- 단위 테스트를 통해 스크립트가 파싱되는지 확인합니다.
3 인덱스 오류 — IndexError
리스트, 튜플 같은 시퀀스 자료형은 각 요소에 인덱스를 가집니다. 파이썬 인덱스는 0부터 시작합니다. 따라서 길이가 N인 시퀀스는 0부터 N-1까지 유효한 인덱스를 가집니다. 이 범위를 벗어나 요소에 접근하면 IndexError
가 발생합니다.
numbers = [1, 2, 3]
print(numbers[1]) # prints 2
흔한 원인
- 오프바이원(off-by-one) 실수
- 반복 중 시퀀스를 동시에 수정(삽입/삭제)하여 길이가 변함
- 빈 리스트에 접근
방지와 해결
- 인덱스 접근 전 len()으로 길이를 확인하세요:
if index < len(my_list):
# execute code
- 반복할 때는 인덱스 대신 직접 요소를 사용하는 것이 더 안전합니다:
for element in my_list:
# 안전하게 요소 사용
- 시퀀스를 순회하면서 동시에 수정해야 한다면, 원본을 복사하거나 인덱스를 역방향으로 순회하세요.
디버깅 체크리스트
- 인덱스 값이 예상 범위 내인지 확인했는가?
- 반복문 내에서 리스트를 변경하고 있지는 않은가?
- 빈 리스트나 None을 접근하려는 것은 아닌가?
2 값 오류 — ValueError
ValueError
는 함수가 올바른 타입의 인수를 받았지만 그 값이 허용되지 않을 때 발생합니다. 즉, 타입은 맞지만 값 자체가 적절하지 않은 경우입니다.
예시
int('10')
위는 정상적으로 동작하지만,
int('ten')
은 ValueError
를 발생시킵니다.
또 다른 예시
import math
math.sqrt(-5)
sqrt()
는 음수를 허용하지 않으므로 ValueError
가 발생합니다.
사용자 입력 처리
사용자 입력은 항상 불확실하므로 ValueError
가 자주 발생합니다. 입력 값을 변환하기 전에 검증하거나 try-except로 처리하세요:
try:
num = input("숫자를 입력하세요: ")
num_int = int(num)
except ValueError as e:
print(f"ValueError 포착: {e}")
예방 팁
- 입력값을 정규 표현식 또는 파서로 검증하세요.
- 도메인 유효성 검사를 추가하세요(예: 음수 불가, 범위 검사).
- 예외 메시지를 로깅하여 어떤 입력이 문제였는지 기록하세요.
1 속성 오류 — AttributeError
AttributeError
는 객체가 요청한 속성이나 메서드를 제공하지 않을 때 발생합니다. 즉, 해당 객체에 그 이름의 속성이 존재하지 않는 경우입니다.
text = "hello world"
print(text.push())
문자열에는 push()
메서드가 없기 때문에 AttributeError
가 발생합니다.
user = None
print(user.name)
NoneType
객체는 name
속성이 없으므로 동일한 오류가 납니다.
원인과 해결
- 객체 타입을 잘못 가정한 경우가 많습니다.
type()
또는isinstance()
로 확인하세요. dir(obj)
를 호출하면 객체의 모든 유효 속성과 메서드를 확인할 수 있습니다.- 코드 설계 관점에서 객체의 책임이 명확하지 않으면 이런 오류가 잦아집니다. 인터페이스를 명확히 하세요.
처리 전략
- 속성 접근 전에 널(null) 체크를 하세요:
if user is not None:
print(user.name)
- 명시적 변환을 고려하세요(예: dict에서 .get 사용).
- duck typing을 사용할 때는 예외를 허용하고 문서화하세요. 필요한 경우 hasattr()로 체크합니다.
공통 디버깅 워크플로(미니 방법론)
- 오류 메시지와 트레이스백을 읽는다. 파일명, 라인, 콜스택을 확인한다.
- 문제가 발생한 최소 재현 사례(minimum reproducible example)를 만든다.
- 의심되는 변수를 출력하거나 디버거(breakpoint, pdb)로 검사한다.
- 한 번에 하나의 가설을 검증한다(예: “이 변수는 None이다”).
- 수정 후 회귀 테스트를 추가한다.
역할별 체크리스트
개발자
- 코드 작성 시 린터와 포매터를 적용한다.
- 입력 검증과 에러 처리를 명확히 작성한다.
- 예외 메시지를 친절하게 작성하고 로깅한다.
코드 리뷰어
- 경계 조건(빈 리스트, 0, 음수 등)을 체크한다.
- 탭/스페이스 혼용, 들여쓰기, 콜론 누락을 확인한다.
- 복잡한 표현은 분리하여 가독성을 높이자.
교육자/튜터
- 학생에게 작은 예제를 통해 오류 발생 원인을 직접 확인시키자.
- 에러 메시지를 해석하는 방법을 가르치자(트레이스백 읽기).
빠른 치트시트 (요약)
- IndentationError: 들여쓰기 불일치 → 탭/스페이스 확인, 포매터 적용
- SyntaxError: 문법 위반 → 라인/위치 확인, 린트로 사전검사
- IndexError: 인덱스 범위 초과 → len() 체크, 요소 직접 순회
- ValueError: 타입은 맞지만 값 부적절 → 입력/범위 검증, try-except
- AttributeError: 객체에 속성 없음 → isinstance/dir 확인, 널 체크
정신 모델(간단한 규칙)
- “파이썬은 들여쓰기로 블록을 인식한다” — 블록을 항상 일정하게 들여쓰기.
- “데이터 구조는 경계를 가지고 있다” — 인덱스는 0부터 시작.
- “함수는 타입과 값 둘 다 기대한다” — 타입 검사 + 값 검사.
- “객체는 무엇을 할 수 있는지 문서화되어야 한다” — 인터페이스 우선 설계.
언제 예외를 잡아야 하나(예외 처리 원칙)
- 외부 입력(사용자, 네트워크, 파일)에서 오는 값은 예외로부터 방어하세요.
- 내부 로직 오류는 가능한 한 빨리 수정하되, 의미 있는 컨텍스트를 추가해 다시 던지세요.
- 무분별한 broad except는 피하고, 가능한 구체적인 예외를 잡습니다.
간단한 용어집(1줄)
- 블록: 같은 들여쓰기를 가진 코드 묶음
- 트레이스백: 예외가 발생한 호출 스택과 라인 정보
- 린터: 코드 문법/스타일을 자동으로 검사해 주는 도구
결론
파이썬의 에러는 대부분 원인과 해결책이 명백합니다. 중요한 것은 오류 메시지를 읽고 작은 재현 사례를 만들어 문제의 범위를 좁히는 습관을 들이는 것입니다. 이 문서를 참고해 각 오류의 원인과 해결 방법을 빠르게 적용하면 생산성이 크게 향상됩니다.
요약 — 이제 다음을 기억하세요: 들여쓰기를 일관되게 관리하고, 문법을 검사하며, 인덱스와 값의 경계를 확인하고, 객체의 타입과 속성을 명확히 파악하면 대부분의 흔한 오류를 예방할 수 있습니다.