Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

13 오류와 예외 처리

Updated: 01 jun 2026

프로그램을 구현하다보면 여러 종류의 오류를 경험한다. 프로그래밍 과정 중에 가장 많이 발생하는 오류와 대처방안을 소개한다.

13.1오류와 디버깅

프로그램의 오류는 크게 세 가지 유형으로 나뉜다. 오류가 발생하면 프로그램 개발자는 오류의 원인을 찾아 해결해야 한다. 이렇게 프로그램의 오류를 찾아 해결하는 과정을 디버깅debugging이라 부르며, 파이썬 실행기는 오류가 발생할 경우 디버깅에 도움되는 정보를 제공한다.

13.1.1구문 오류

구문 오류syntax error는 명령문을 작성할 때 지켜야 하는 명령문 문법에 어긋나는 오류가 있음을 의미한다. 파이썬 실행기는 프로그램을 실행하기 전에 문법 검사를 통해 모든 구문 오류를 찾아낸다.

예제: 변수 선언 과정

변수를 선언할 때 변수로 False, if, return 등 파이썬에서 특별한 기능을 갖는 키워드를 사용하거나, bad name, odd~job, US$ 등처럼 허용되지 방식을 사용하면 SyntaxError와 같은 구문 오류가 발생한다.

False = 0
  Cell In[1], line 1
    False = 0
    ^
SyntaxError: cannot assign to False
bad name = 5
  Cell In[2], line 1
    bad name = 5
        ^
SyntaxError: invalid syntax

예제: 반복문 선언 과정

for 반복문을 작성할 때 콜론 기호 :를 생략하거나 본문 들여쓰기를 하지 않은 경우에는 종류에 따라 SyntaxError, IndentationError 등이 발생한다.

for i in range(5)
    print(i)
  Cell In[3], line 1
    for i in range(5)
                     ^
SyntaxError: expected ':'
for i in range(5):
j = i + 1
    print(j)
  Cell In[4], line 2
    j = i + 1
    ^
IndentationError: expected an indented block after 'for' statement on line 1

13.1.2런타임 오류

런타임 오류runtime error는 프로그램이 실행되는 도중에 발생하는 오류이다. 프로그램의 실행을 중단시키는 예외 상황이라는 의미에서 런타임 오류를 예외exception라고 부르기도 한다. 런타임 오류는 다양한 경우에 발생한다. 여기서는 네 종류의 런타임 오류를 살펴본다.

런타임 오류 예제 1: 0으로 나누기 오류

런타임 에러의 대표적인 예는 0으로 나누기 오류다. ZeroDivisionError 라고 표시되는데, 이는 num이 0을 가리키고 있기에 결국 0으로 나눗셈을 시도하기 때문에 발생한다.

num = 0
print(3 / num)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[5], line 2
      1 num = 0
----> 2 print(3 / num)

ZeroDivisionError: division by zero

참고로 3/num은 구문syntax 측면에서는 전혀 문제 없다. 이유는 실제로 3/num이 계산될 때까지는 변수 num에 할당된 값이 0이 될 수도, 되지 않을 수도 있기에 겉모양만 보고는 실행이 가능한지 여부를 알 수 없기 때문이다.

런타임 오류 예제 2: 변수 이름 오류

아래 코드를 실행하면 a_number 라는 변수가 선언되어 있지 않기 때문에 문제가 발생한다. NameError라고 표시되는데, 이 오류는 선언되지 않은 변수가 사용될 때 발생한다. 자세히 살펴보면 a_numbera_Number 둘 중에 하나는 오타임을 알 수 있다.

a_Number = 327.68
b = a_number * 3
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 2
      1 a_Number = 327.68
----> 2 b = a_number * 3

NameError: name 'a_number' is not defined

런타임 오류 예제 3: 자료형 오류

아래 코드는 float() 함수를 리스트와 함께 호출한다. 그런데 float() 함수는 str, int, float 세 종류의 자료형만 인자로 사용하기로 정의되어 있다. 따라서 함수 인자의 자료형이 틀렸다는 의미의 TypeError가 발생하며 코드의 실행이 멈춘다. 따라서 마지막 print() 함수의 호출은 실행되지 않는다.

x = [1, 2]

print(float(x))
print("프로그램 실행 완료!")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[7], line 3
      1 x = [1, 2]
----> 3 print(float(x))
      4 print("프로그램 실행 완료!")

TypeError: float() argument must be a string or a real number, not 'list'

런타임 오류 예제 4: 값의 형식 오류

아래 코드는 float() 함수를 123f2라는 문자열을 가리키는 변수 x와 함께 호출한다. 인자의 자료형이 str 이기에 float() 함수의 인자로 사용될 자격이 있다. 하지만 지정된 문자열이 부동소수점 형식이 아니기에 인자의 형식이 올바르지 않다는 의미의 ValueError가 발생하며 코드의 실행이 멈춘다. 따라서 마지막 print() 함수의 호출은 실행되지 않는다.

x = '123f2'

print(float(x))
print("프로그램 실행 완료!")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[8], line 3
      1 x = '123f2'
----> 3 print(float(x))
      4 print("프로그램 실행 완료!")

ValueError: could not convert string to float: '123f2'

13.1.3의미 오류

프로그램은 오류 없이 잘 실행되지만 원하는 결과를 만들지 못한다면 프로그램 어딘가에 논리적 오류가 존재한다는 의미이다. 이와같은 오류를 의미 오류semantic error라 부른다. 의미 오류의 발생원인은 매우 다양하다.

프로그램이 정상적으로 작동하기 때문에 구문 오류나 런타임 오류와는 다르게 오류의 원인을 바로 확인하기 어렵거나 아예 불가능할 수도 있다. 수학 문제를 풀다가 계산 실수를 하거나, 기호를 다르게 적거나, 문제를 잘못 이해했거나 해서 풀 수 있었던 문제를 틀렸던 경험이 있을 것이다. 프로그래밍에서도 유사한 실수가 많이 발생한다.

예를 들어, 아래 프로그램은 두 배 계산 대신에 제곱 계산을 하는 실수를 범한 경우이다.

num = 3
doubleNum = num ** 2

print("입력한 값", num, "의 두 배는", doubleNum, "입니다.")
입력한 값 3 의 두 배는 9 입니다.

두 배하려면 num * 2를 사용했어야 하는데 실수로 num ** 2를 사용하여서 결과적으로 입력한 값의 제곱을 계산하게 된다. 수천, 수만 줄로 이루어진 프로그램에서 이런 형식의 오류의 원인을 찾는 일은 경우에 따라 모래사장에서 바늘찾기처럼 매우 어렵거나 불가능할 수 있다.

13.1.4예제

예제 1: 구문 오류

코드를 실행해서 발생하는 오류를 설명하라.

try = "시도해봐!"
  Cell In[10], line 1
    try = "시도해봐!"
        ^
SyntaxError: expected ':'

답:

SyntaxError가 발생한다. 이유는 try는 예외 처리에 사용되는 키워드이며 따라서 변수명으로 허용되지 않기 때문이다.

예제 2: 구문 오류

코드를 실행해서 발생하는 오류를 설명하라.

x = 27

if x % 3 == 0
    print(x, "는(은) 3의 배수")
  Cell In[11], line 3
    if x % 3 == 0
                 ^
SyntaxError: expected ':'

답:

SyntaxError가 발생한다. if 논리식 명령문은 아래 코드처럼 항상 콜론(:)으로 마무리 해야 한다.

예제 3: 런타임 오류

코드를 실행해서 발생하는 오류를 설명하라.

L1 = [1, 2, 3]
print(L1[3])
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[12], line 2
      1 L1 = [1, 2, 3]
----> 2 print(L1[3])

IndexError: list index out of range

답:

IndexError가 발생한다. 길이가 3인 리스트에 사용할 수 없는 3을 인덱스로 지정하였기 때문이다. 하지만 코드 실행전까지는 오류가 있는지 여부를 알 수 없기 때문에 런타임 오류에 속한다.

예제 4: 의미 오류

아래처럼 출력하는 코드를 구현하려 한다.

[0, 1]
[0, 2]
[0, 3]
[1, 2]
[1, 3]
[2, 3]

그런데 아래 코드를 실행하면 원하는 모양이 출력되지 않는다.

i = 0
while i < 4:
    j = 0
    while j < 4:
        if j > i:
            print([j, i])
        j += 1
    i += 1
[1, 0]
[2, 0]
[3, 0]
[2, 1]
[3, 1]
[3, 2]

위 코드를 수정하여 원하는 모양이 출력되도록 하라.

힌트: 코드 한줄만 수정하면 된다.

답:

  • ij가 0부터 3까지 변할 때 j > i 일 때만 print() 함수 실행

  • 그런데 출력되는 어레이의 0번과 1번 인덱스의 값의 위치가 서로 바뀜.

  • 따라서 print([i, j])print([j, i]) 대신 사용.

i = 0
while i < 4:
    j = 0
    while j < 4:
        if j > i:
            print([i, j])
        j += 1
    i += 1
[0, 1]
[0, 2]
[0, 3]
[1, 2]
[1, 3]
[2, 3]

13.1.5연습문제

문제 1: 런타임 오류

코드를 실행해서 발생하는 오류를 설명하라.

y = "2" + 2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[15], line 1
----> 1 y = "2" + 2

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

문제 2: 런타임 오류

코드를 실행해서 발생하는 오류를 설명하라.

hello = "파이썬, 안녕!"
out_of_range = hello[-10]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[16], line 2
      1 hello = "파이썬, 안녕!"
----> 2 out_of_range = hello[-10]

IndexError: string index out of range

문제 3: 구문 오류

코드를 실행해서 발생하는 오류를 설명하라.

x = 5

while x % 2 != 0
    x = 3*x - 1
    print(x)
  Cell In[17], line 3
    while x % 2 != 0
                    ^
SyntaxError: expected ':'

문제 4: 구문 오류

코드를 실행해서 발생하는 오류를 설명하라.

x = 4

while x % 2 != 0:
x = 3*x - 1
    print(x)

print(x, ": 짝수")
  Cell In[18], line 4
    x = 3*x - 1
    ^
IndentationError: expected an indented block after 'while' statement on line 3

문제 4: 의미 오류

아래처럼 출력하는 코드를 구현하려 한다.

[0, 1]
[0, 3]
[1, 1]
[1, 3]
[2, 3]
[3, 3]

그런데 아래 코드를 실행하면 원하는 모양이 출력되지 않는다.

for i in range(4):
    for j in range(4):
        if j < i:
            continue
        print([i, j])
[0, 0]
[0, 1]
[0, 2]
[0, 3]
[1, 1]
[1, 2]
[1, 3]
[2, 2]
[2, 3]
[3, 3]

위 코드에 포함된 한 줄의 명령문만 수정하여 원하는 모양이 출력되도록 하라.

13.2예외 처리

오류가 발생할 수 있는 상황에 미리 대처하는 코딩 기법을 예외 처리exception handling라 부른다.

try: ... except: ...

가장 단순한 예외 처리 형식은 다음과 같다.

try:
    code1
except:
    code2

위 코드의 의미는 다음과 같다.

  • 먼저 try 키워드의 본문인 code1 을 실행한다. 실행 과정 중에 오류가 발생하지 않으면 except 키워드의 본문인 code2 부분은 건너 뛴다.

  • 만약 code1 실행중에 오류가 발생하면 프로그램의 실행을 멈추는 대신 바로 이어서 code2 를 실행한다.

예를 들어 아래 코드는 ValueError로 인해 코드 실행이 멈추는 대신 입력값에 어떤 문제가 있는지 정보를 출력한다. 이유는 try의 본문에 있는 코드가 실행할 때 오류가 발생하면 바로 except의 본문에 있는 코드가 실행되도록 약속되었기 때문이다. 또한 코드의 실행은 계속 이어져서 마지막 줄의 print() 함수도 호출되어 프로그램이 제대로 실행되었음을 확인해준다.

x = '123f2'

try:
    print(float(x))
except:
    print('부동소수점 모양의 문자열이 아닙니다.')
    
print("프로그램 실행 완료!")
부동소수점 모양의 문자열이 아닙니다.
프로그램 실행 완료!

try: ... except ...: ...: 오류 지정 예외처리

특정 종류의 오류가 발생할 때만 예외 처리를 실행하도록 할 수 있다. 예를 들어 아래 형식은 ValueError가 발생할 때만 예외 처리를 실행한다.

try:
    code1
except ValueError:
    code2

아래 코드를 실행하면 ValueEror 오류가 발생한다.

x = '123f2'

print(float(x))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[21], line 3
      1 x = '123f2'
----> 3 print(float(x))

ValueError: could not convert string to float: '123f2'

아래 코드는 ValueError가 발생했을 때의 예외 처리를 지정한다.

x = '123f2'

try:
    print(float(x))
except ValueError:
    print('부동소수점 모양의 문자열이 아닙니다.')
    
print("프로그램 실행 완료!")
부동소수점 모양의 문자열이 아닙니다.
프로그램 실행 완료!

오류의 종류를 명시하면 다른 종류의 오류는 처리하지 못한다.

예를 들어 아래 코드는 float() 함수의 인자로 튜플이 입력되어 TypeError 오류가 발생한다. 그런데 ValueError만 처리하도록 설정되어 있어서 예외 처리가 제대로 실행되지 못하고 결국에 프로그램 실행이 중간에 멈춰버린다.

x = [1, 2]

try:
    print(float(x))
except ValueError:
    print('부동소수점 모양의 문자열이 아닙니다.')
    
print("프로그램 실행 완료!")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[23], line 4
      1 x = [1, 2]
      3 try:
----> 4     print(float(x))
      5 except ValueError:
      6     print('부동소수점 모양의 문자열이 아닙니다.')

TypeError: float() argument must be a string or a real number, not 'list'

이에 대한 해결책은 오류의 종류를 명시하지 않거나 아래처럼 여러 종류의 오류를 처리하도록 지정하는 것이다.

x = [1, 2]

try:
    print(float(x))
except (ValueError, TypeError):
    print('사용된 인자에 문제가 있습니다.')

print("프로그램 실행 완료!")    
사용된 인자에 문제가 있습니다.
프로그램 실행 완료!

try: ... except ... as ...: ...: 오류 설명 예외 처리

코드를 실행할 때 오류가 발생하면 오류종류와 함께 오류에 대한 설명 문자열이 함께 지정되는데, 이 문자열을 받아 오류의 발생원인을 화면에 출력할 수 있다. 형식은 아래와 같으며 err이 오류가 발생한 이유를 설명하는 문자열을 가리키는 변수로 사용된다.

try:
    명령문
except 오류종류 as err:
    print(f"(오류 설명) 오류종류: {err}")

13.2.1예제

예제 1

문자열을 인자로 입력받을 때 부동소수점 형식이면 부동소수점으로 변환된 값을, 아니면 문자열 그대로를 반환하는 함수 whether_float()를 예외 처리를 이용하여 구현하라.

답:

변수 x가 가리키는 문자열이 부동소수점 형식을 갖추지 못한 경우 float(x)를 호출하면 ValueError 오류가 발생한다.

x = '3.14abc'
float(x)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[25], line 2
      1 x = '3.14abc'
----> 2 float(x)

ValueError: could not convert string to float: '3.14abc'

반면에 부동소수점 형식이면 정상적으로 부동소수점으로 변환된 값을 반환한다.

x = '3.14159'
float(x)
3.14159

따라서 x가 주어졌을 때 float(x)를 먼저 실행한 다음 오류가 발생할 경우에 대해 예외처리를 진행한다. 아래 whether_float() 함수는 오류가 발생할 경우 x를 반환하도록 설정되었다.

def whether_float(x):
    try:
        return float(x)
    except:
        return x
whether_float('3.14159')
3.14159
whether_float('3.14abc')
'3.14abc'

예외처리 단계에서 ValueError 만을 다루게 할 수도 있다.

def whether_float(x):
    try:
        return float(x)
    except ValueError:
        return x
whether_float('3.14159')
3.14159
whether_float('3.14abc')
'3.14abc'

예제 2

문자열 인덱싱을 이용하여 문자열에 포함된 문자를 확인할 수 있다. 예를 들어 첫째 문자는 0을, 셋째 문자는 2를 인덱스로 활용한다.

a_string = 'python'

a_string[0]
'p'
a_string[2]
't'

그런데 인덱스로 사용될 수 있는 정수들의 범위는 문자열에 따라 달라진다. python 문자열이 6개의 문자로 구성되었기에 인덱스로 사용될 수 있는 정수는 0부터 5까지 또는 -6부터 -1까지이다. 그 이외의 정수에 대해서는 아래처럼 IndexError가 발생한다.

이점을 활용하여 -10부터 10까지의 정수 n에 대해 a_string[n]을 출력하는 for 반복문을 작성하라. 단, IndexError 오류가 발생할 경우 "인덱스 범위 벗어남"을 출력하라.

힌트: try ... except IndexError: 명령문 활용

답:

  • n이 -10부터 10까지 변할 때 먼저 a_string[n]을 실행하도록 함

  • n이 허용된 범위를 넘어설 경우 IndexError가 발생할 것이기에 이에 대해 아래 코드처럼 예외처리 실행.

  • n이 -6부터 -1까지 변할 때 한 번, 그리고 0부터 5까지 변할 때 또 한 번 전체 문자가 출력됨.

a_string = "python"

for n in range(-10, 11):
    try:
        print(a_string[n])
    except IndexError:
        print("인덱스 범위 벗어남")
인덱스 범위 벗어남
인덱스 범위 벗어남
인덱스 범위 벗어남
인덱스 범위 벗어남
p
y
t
h
o
n
p
y
t
h
o
n
인덱스 범위 벗어남
인덱스 범위 벗어남
인덱스 범위 벗어남
인덱스 범위 벗어남
인덱스 범위 벗어남

13.2.2연습문제

문제 1

문자열을 인자로 입력받을 때 정수 형식이면 해당 정수가 10부터 100까지의 정수 중에 하나인지 여부를 출력하고, 정수 형식이 아니면 입력된 문자열의 길이를 반환하는 함수 whether_int()를 예외 처리를 이용하여 구현하라.

힌트: 문자열의 길이는 len() 함수가 계산한다.

문제 2

두 개의 정수 a, b를 입력받아 a/b를 계산한 결과를 다음과 같이 출력하는 코드를 작성하라.

a 나누기 b: a/b

단, 아래 조건이 만족되어야 한다.

  • 정수가 아닌 값이 입력되거나 b0이 입력된 경우 아래 문장을 출력한 후 재입력 요구.

  • 올바른 값이 입력될 때까지 재입력을 요구하며, 올바른 값이 입력되면 나눗셈을 실행하고 종료할 것.

힌트: input() 함수, while True 무한루프 반복문, break 명령문, try-except (ValueError, ZeroDivisionError) 명령문 등 활용.

문제 3

아래 코드는 실행될 때마다 1과 100까지의 정수 중에서 임의로 정해진 값을 할당받는 secret 변수가 가리키는 값을 맞히는 게임이다.

from random import randint

print("수 알아맞히기 게임에 환영합니다.")

secret = randint(1, 100)
guess = -1   # 이어지는 while 반복문이 최소 한 번은 실행되도록 함

while guess != secret:
    guess = int(input("1부터 100 사이의 정수 하나를 입력하세요: "))

    if guess == secret:
        print("맞았습니다!")
    elif guess > secret:
        print("너무 커요!")
    else:
        print("너무 작아요!")

print("게임 종료!")
수 알아맞히기 게임에 환영합니다.
1부터 100 사이의 정수 하나를 입력하세요: 50
너무 작아요!
1부터 100 사이의 정수 하나를 입력하세요: 75
너무 작아요!
1부터 100 사이의 정수 하나를 입력하세요: 87
너무 커요!
1부터 100 사이의 정수 하나를 입력하세요: 81
너무 커요!
1부터 100 사이의 정수 하나를 입력하세요: 78
너무 작아요!
1부터 100 사이의 정수 하나를 입력하세요: 80
너무 커요!
1부터 100 사이의 정수 하나를 입력하세요: 79
맞았습니다!
게임 종료!

위 코드를 수정하여 정수 입력이 아니거나 정수이더라도 1부터 100 사이의 정수가 아니면 재입력을 요구하도록 코드를 수정하라.

힌트: assert 명령문과 try ... except AssertionError 명령문