Menu
Coddy logo textTech

예외 처리란 무엇인가요?

예외 처리(exception handling)는 프로그램이 실행 중에 발생하는 오류에 대응하는 방법입니다. 실패할 수 있는 코드를 try 같은 보호 블록에 넣고, 오류가 발생하면 프로그램이 멈추는 대신 except나 catch 같은 처리기로 제어가 넘어갑니다.

글쓴이: Kevin Spektor, 공동 창업자, CTO

업데이트: 2026년 9월 24일

나이를 묻는 프로그램은 언젠가 20 대신 "twenty"를 받게 돼요. 그 텍스트를 변환하는 것은 런타임 오류예요. int("twenty")는 ValueError를 발생시키고, 대비책이 없으면 프로그램은 멈춰요. 예외 처리가 바로 그 대비책이에요. 실패할 수 있는 코드를 표시하고, 실패했을 때 실행할 코드를 작성해요.

Next year you will be 35
Not a number: twenty
Next year you will be 20
Done

잘못된 답은 보고되고, 반복문은 다음 답으로 계속 진행해요. try가 없었다면 프로그램은 한 줄을 출력한 뒤 트레이스백을 출력했을 거예요.

예외 처리는 어떻게 동작하나요

  1. try 안의 코드가 평소처럼 실행돼요.
  2. 어떤 연산이 실패하면 런타임이 예외를 발생시켜요. 예외는 타입(ValueError)과 메시지(invalid literal for int() with base 10: 'twenty')를 가진 객체예요.
  3. try 블록은 그 줄에서 멈춰요. 나머지 줄은 건너뛰며, 그래서 "twenty"에 대해서는 "Next year you will be"가 출력되지 않아요.
  4. 런타임은 예외의 타입을 각 except 절과 위에서 아래로 비교하고, 처음으로 일치하는 절을 실행해요.
  5. 처리기가 끝나면 프로그램은 try 문 전체 다음의 첫 줄부터 계속돼요.
  6. 일치하는 절이 없으면 예외는 현재 함수를 벗어나고, 그 함수를 호출한 함수에서, 다시 그 함수의 호출자에서 검색이 이어져요. 이것을 호출 스택 되감기(unwinding)라고 해요. 일치하는 절 없이 프로그램 맨 위까지 도달하면 프로그램은 트레이스백과 함께 끝나요.

6단계는 처리기가 오류가 발생한 함수 안에 있을 필요가 없다는 뜻이에요. 여기서는 실패가 호출 두 단계 깊이에서 일어나는데, 맨 아래의 처리기가 여전히 이를 잡아요.

parsing 4.50
parsing free
Could not add the prices: could not convert string to float: 'free'

float("free")는 parse_price 안에서 실패했어요. parse_price에도 total에도 처리기가 없었으므로 둘 다 중단되었고, "3.20"은 끝내 파싱되지 않았어요. 이것이 예외 처리가 주는 핵심 설계 선택이에요. 오류를 어떻게 다룰지 아는 곳에서 처리하면 되고, 그곳은 오류가 발생한 곳에서 멀리 떨어진 경우가 많아요.

try, except, else, finally

Python의 try 문에는 선택적으로 쓸 수 있는 부분이 두 개 더 있어요. else는 try 블록이 예외 없이 끝났을 때만 실행돼요. finally는 모든 경우에 실행돼요. 성공한 뒤에도, 예외를 처리한 뒤에도, 심지어 함수가 try 안에서 반환할 때도 실행돼요.

no error
finally runs either way
2.0
b was zero
finally runs either way
None

finally는 파일 닫기, 락 해제, 데이터베이스 연결 종료 같은 정리 작업을 두는 곳이에요. Python에서는 with 문이 파일에 대한 정리를 자동으로 해 주며, 파일에는 보통 이쪽을 써요.

예외 직접 발생시키기

예외는 언어가 감지하는 오류에만 쓰이는 것이 아니에요. 여러분의 함수가 다룰 수 없는 입력을 받으면 예외를 발생시켜 거부할 수 있고, 다음에 무슨 일이 일어날지는 호출한 쪽이 정해요. 작은 예외 클래스를 정의하면 오류를 설명하는 이름을 붙일 수 있어요.

70
Refused: cannot take 250, balance is 100

Python은 raise를 써요. Java, C++, JavaScript는 같은 일에 throw를 써요.

다른 언어의 예외 처리

언어키워드알아 둘 점
Pythontry, except, else, finally, raise모든 예외는 BaseException을 상속한 객체예요
Javatry, catch, finally, throw, throwsIOException 같은 검사 예외는 잡거나 throws로 선언해야 해요
C++try, catch, throwfinally가 없고, 스택이 풀릴 때 소멸자가 정리해요
JavaScripttry, catch, finally, throwasync 코드의 오류는 await를 try로 감싸서 잡아요
C없음함수가 오류 코드를 반환하고, 많은 함수가 errno를 설정해요
Go일반 오류에는 없음함수가 error 값을 반환하고 호출한 쪽이 이를 검사해요

같은 파싱 예제를 Java로 쓰면 이래요.

try {
    int age = Integer.parseInt("twenty");
    System.out.println(age + 1);
} catch (NumberFormatException e) {
    System.out.println("Not a number: " + e.getMessage());
} finally {
    System.out.println("done");
}

Java는 예외를 두 그룹으로 나눠요. IOException 같은 검사 예외(checked exception)는 프로그램이 통제할 수 없는 문제를 나타내며, 컴파일러는 이를 잡지도 선언하지도 않은 코드의 빌드를 거부해요. NullPointerException처럼 RuntimeException의 하위 클래스인 비검사 예외(unchecked exception)는 보통 버그를 뜻하고, 컴파일러가 처리를 강제하지 않아요.

흔한 실수

  • 모든 것을 잡기. Python의 맨 except:는 KeyboardInterrupt까지 잡아서 Ctrl+C가 동작하지 않게 되고, except Exception:은 전혀 예상하지 못한 버그까지 잡아요. 처리 방법을 아는 특정 타입만 잡으세요.
  • 오류 삼키기. except ValueError: pass는 문제를 숨겨요. 최소한 무엇이 잘못됐는지 출력하거나 로그로 남기세요.
  • 너무 큰 try 블록. 잡으려는 예외를 발생시킬 수 있는 줄만 감싸야, 관련 없는 오류를 실수로 처리하지 않아요.
  • 버그를 고치지 않고 잡기. 한 단계 더 도는 반복문에서 나온 IndexError는 코드의 실수예요. 이를 처리하면 잘못된 코드가 살아남아요.
  • C나 C++에서 catch가 비정상 종료를 막아 주리라 기대하기. 세그멘테이션 오류는 예외가 아니라 운영체제가 보내는 시그널이며, Linux와 macOS에서 C++의 catch (...)는 이를 절대 보지 못해요.

다음 단계

예외 처리가 대응하는 오류는 런타임 오류 페이지에, 예외 처리로 잡을 수 없는 비정상 종료는 세그멘테이션 오류 페이지에 설명되어 있어요. 전체 문법은 Python 예외, Java try와 catch, C++ 예외, JavaScript try와 catch 가이드를 읽으세요. Java 강좌와 Python 강좌에서 모두 실제 연습 문제로 익힐 수 있어요.

자주 묻는 질문

Java 예외 처리의 키워드 5가지는 무엇인가요?
try, catch, finally, throw, throws예요. try는 지켜볼 코드를 표시하고, catch는 특정 예외 타입을 처리하며, finally는 예외 발생 여부와 관계없이 정리 코드를 실행해요. throw는 예외를 발생시키고, 메서드 시그니처의 throws는 그 메서드가 호출한 쪽으로 넘길 수 있는 검사 예외를 선언해요.
C++에서 예외 처리는 어떻게 하나요?
C++는 try, catch, throw를 사용해요. 어떤 타입이든 던질 수 있지만, 관례상 std::runtime_error처럼 std::exception을 상속한 객체를 던지고 catch (const std::exception& e)처럼 참조로 잡아요. C++에는 finally가 없어요. 정리는 스택이 풀리면서 자동으로 실행되는 소멸자에서 이루어져요.
오류(error)와 예외(exception)의 차이는 무엇인가요?
일상적으로는 잘못되는 모든 것이 오류이고, 예외는 언어가 그것을 알리는 데 쓰는 객체예요. Java는 더 분명하게 구분해요. Exception은 프로그램이 합리적으로 처리할 수 있는 문제이고, OutOfMemoryError나 StackOverflowError 같은 Error는 보통 프로그램이 잡으려 해서는 안 되는 JVM의 실패를 뜻해요. Python에서는 이름과 달리 ValueError와 ZeroDivisionError가 모두 예외예요.
Java에서 throw와 throws는 어떻게 다른가요?
throw는 그 지점에서 예외 하나를 발생시키는 문장이에요. throw new IllegalArgumentException("negative age");처럼 써요. throws는 메서드 선언의 일부로, 메서드가 호출한 쪽으로 넘길 수 있는 검사 예외를 나열해요. void load() throws IOException처럼 써요. 그러면 컴파일러는 모든 호출자가 그 예외를 잡거나 똑같이 선언하도록 강제해요.
예외 처리를 쓰면 코드가 느려지나요?
대부분의 최신 언어에서 try 블록에 들어가는 비용은 작아요. Python 3.11부터는 예외가 발생하지 않으면 try의 비용이 거의 없고, 주요 C++ 컴파일러도 아무것도 던지지 않는 경로에는 실행 비용을 추가하지 않아요. 예외를 발생시키고 잡는 것은 if 검사보다 훨씬 느리므로, 성능이 중요한 반복문에서는 예외에 기대지 말고 흔한 경우를 미리 검사하세요.
Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기