목차
1. 실제 서비스 장애 상황
오전 2시 17분, 회사 메신저에 긴급 알림이 울립니다. 서비스가 중단되었다는 메시지입니다.
운영팀이 급하게 로그를 확인하자 다음 에러가 보입니다.
ZeroDivisionError:
division by zero고객은 계속 접속 중이고 서버는 멈춰 있습니다. 개발자는 나눗셈 하나 때문에 서비스 전체가 죽는 상황을 마주합니다.
코드가 한 번 실행되면 프로그램이 완성되었다고 생각합니다.
만약 실패하면 어떻게 할지 먼저 생각합니다.
print("프로그램 작성 완료!")"만약 실패하면?"실무 개발자는 오류가 발생하지 않기를 기대하지 않습니다. 오류가 발생할 가능성을 전제로 프로그램을 설계합니다.
2. 프로그램은 생각보다 자주 실패한다
우리는 보통 정상적인 상황만 생각합니다. 예를 들어 숫자를 입력받는 코드를 보겠습니다.
number = int(input("숫자 입력 : "))사용자가 숫자를 입력하면 정상 동작합니다.
100그런데 사용자가 문자로 입력하면 어떻게 될까요?
안녕하세요결과입니다.
ValueError프로그램은 종료됩니다. 사용자는 당황하고, 운영팀은 전화를 받고, 개발자는 야근하게 됩니다.
실제 서비스에서는 입력값, 파일, 네트워크, 데이터베이스, 외부 API가 언제든 실패할 수 있습니다.
3. 예외와 try-except
예외 Exception은 프로그램 실행 중 발생하는 오류입니다. 예외가 발생하면 기본적으로 프로그램은 즉시 종료됩니다.
print("프로그램 시작")
10 / 0
print("프로그램 종료")결과입니다.
프로그램 시작
ZeroDivisionError마지막 출력인 프로그램 종료는 실행되지 않습니다. 즉, 예외는 프로그램을 죽이는 원인이 됩니다.
개발자는 범인을 잡아야 한다
실무 개발자는 예외가 발생하지 않기를 기도하지 않습니다. 예외가 발생할 것을 예상하고 미리 대응책을 준비합니다. 그 기술이 Exception Handling, 즉 예외 처리입니다.
첫 번째 방어막: try-except
기본 문법입니다.
try:
위험한 코드
except:
예외 발생 시 실행예시입니다.
try:
result = 10 / 0
except:
print("에러가 발생했습니다.")결과입니다.
에러가 발생했습니다.프로그램은 죽지 않았습니다.
나쁜 ATM은 잔액 부족 상황에서 ERROR를 내고 시스템을 종료합니다. 좋은 ATM은 잔액이 부족하니 다시 시도해달라고 안내합니다. 예외 처리는 좋은 ATM을 만드는 기술입니다.
예외 내용을 직접 확인하기
실무에서는 무슨 오류인지 알아야 합니다.
try:
result = 10 / 0
except Exception as e:
print(e)결과입니다.
division by zero실제 운영 시스템에서는 이 정보를 로그에 저장합니다.
4. 실무에서 흔한 예외 TOP 5
Python 실무에서 자주 만나는 예외를 정리하면 다음과 같습니다.
| 순위 | 예외 | 발생 상황 | 예시 |
|---|---|---|---|
| 1 | ZeroDivisionError | 0으로 나누기 | 10 / 0 |
| 2 | ValueError | 잘못된 데이터 입력 | int("hello") |
| 3 | FileNotFoundError | 파일 없음 | open("abc.txt") |
| 4 | IndexError | 리스트 범위 초과 | data[10] |
| 5 | KeyError | Dictionary 키 없음 | user["age"] |
1. ZeroDivisionError
10 / 02. ValueError
int("hello")3. FileNotFoundError
open("abc.txt")4. IndexError
data = [1, 2, 3]
print(data[10])5. KeyError
user = {
"name":"Lee"
}
print(user["age"])5. 보안 로그와 여러 예외 처리
보안 관제 시스템 사례
보안 로그를 읽는 프로그램이 있다고 가정해보겠습니다.
with open("security.log") as file:
data = file.read()그런데 security.log 파일이 삭제되면 다음 예외가 발생합니다.
FileNotFoundError예외 처리가 없다면 프로그램은 종료되고 서비스는 중단될 수 있습니다. 해결 코드는 다음과 같습니다.
try:
with open("security.log") as file:
data = file.read()
except FileNotFoundError:
print("로그 파일이 없습니다.")이제 로그 파일이 없어도 서비스는 계속 살아있습니다.
여러 개의 예외 처리하기
실무에서는 오류 종류별로 다르게 대응합니다.
try:
number = int(input())
except ValueError:
print("숫자만 입력해주세요.")
except KeyboardInterrupt:
print("사용자가 취소했습니다.")ValueError와 KeyboardInterrupt를 나누면 잘못된 입력과 사용자 취소를 서로 다른 방식으로 처리할 수 있습니다.
6. finally와 자원 정리
finally는 성공하든 실패하든 반드시 실행되는 영역입니다.
try:
print("파일 처리")
except:
print("오류 발생")
finally:
print("파일 닫기")정상 실행 결과입니다.
파일 처리
파일 닫기오류 발생 시에도 finally는 실행됩니다.
오류 발생
파일 닫기서버 개발자가 가장 좋아하는 코드
try:
connect_database()
except Exception as e:
log_error(e)
finally:
close_database()DB 연결 해제는 성공 여부와 관계없이 무조건 수행해야 합니다. 그래서 finally는 파일, 네트워크, 데이터베이스 같은 자원 정리에 자주 사용됩니다.
7. raise로 직접 예외 발생시키기
개발자는 직접 예외를 만들 수도 있습니다.
age = -10
if age < 0:
raise ValueError(
"나이는 음수가 될 수 없습니다."
)결과입니다.
ValueError:
나이는 음수가 될 수 없습니다.실무에서는 입력값 검증에 자주 사용됩니다.
로그인 시스템 예제
password = input("비밀번호 : ")if len(password) < 8:
raise ValueError(
"비밀번호는 8자리 이상이어야 합니다."
)raise를 사용하면 잘못된 값이 시스템 깊숙이 들어가기 전에 초기에 차단할 수 있습니다.
8. AI 시스템과 운영 서버 사례
AI 시스템도 예외 처리를 사용한다
ChatGPT가 파일을 읽는 상황을 생각해보겠습니다.
try:
read_pdf()
except:
print(
"파일을 읽을 수 없습니다."
)이미지 분석, 음성 인식, AI 모델 로딩, 파일 처리 등 모든 곳에 예외 처리가 존재합니다.
운영 서버에서 실제 발생하는 상황
오전 9시에는 DB 연결이 정상입니다.
DB 연결 성공오후 2시에 DB 서버 장애가 발생합니다.
Connection Error예외 처리가 없다면 서비스는 종료됩니다. 예외 처리가 있다면 사용자에게 다음처럼 안내하고 서비스는 살아있을 수 있습니다.
현재 서비스 점검 중입니다.
잠시 후 다시 시도해주세요.장애 없는 시스템은 없습니다. 중요한 것은 장애가 발생해도 살아남는 시스템입니다.
9. 실무자가 알려주는 예외 처리 원칙
예외 처리를 할 때 가장 위험한 패턴은 오류를 숨기는 코드입니다.
나쁜 코드
try:
...
except:
pass이 코드는 오류를 숨깁니다. 장애 분석이 어려워지고 실제 문제가 조용히 누적될 수 있습니다.
좋은 코드
try:
...
except Exception as e:
print(e)또는 로그 시스템을 사용합니다.
logging.error(e)예외를 처리하더라도 반드시 기록을 남겨야 합니다. 기록이 있어야 장애 원인을 추적하고 재발을 막을 수 있습니다.
실제 장애 사례
어느 쇼핑몰의 결제 서버에서 다음 코드가 실행되었다고 가정해보겠습니다.
price = 10000
discount = None
final_price = (
price - discount
)결과입니다.
TypeError결제 서버 전체가 중단될 수 있습니다. 예외 처리를 추가하면 서비스가 정상 유지될 수 있습니다.
try:
final_price = (
price - discount
)
except TypeError:
final_price = price10. 정리와 다음 편 예고
오늘 배운 내용을 한 문장으로 정리하면 초보 개발자는 오류가 발생하지 않기를 바라고, 실무 개발자는 오류가 반드시 발생한다고 가정하고 그 상황을 준비합니다.
코드가 실행되면 성공이라고 생각합니다.
오류가 발생하면 어떻게 할지 생각하기 시작합니다.
실패를 설계합니다.
코드가 실행되면 성공오류가 발생하면?실패를 설계한다- 예외는 프로그램 실행 중 발생하는 오류입니다.
- 예외가 처리되지 않으면 프로그램은 종료될 수 있습니다.
- try-except는 예외로부터 프로그램을 보호하는 기본 방어막입니다.
- Exception as e로 오류 내용을 확인하고 로그로 남길 수 있습니다.
- finally는 성공과 실패 여부와 관계없이 항상 실행됩니다.
- raise는 개발자가 의도적으로 예외를 발생시켜 잘못된 입력을 차단할 때 사용합니다.
- 실무에서는 예외를 숨기지 말고 반드시 기록해야 합니다.
Google, Amazon, Microsoft, OpenAI 같은 큰 서비스도 장애를 경험합니다. 중요한 것은 장애가 발생하지 않는 시스템이 아니라, 장애가 발생해도 살아남는 시스템입니다.
예외 처리는 Python이 제공하는 첫 번째 생존 기술입니다. 장난감 프로그램과 실제 서비스의 차이는 실패를 어떻게 다루는지에서 드러납니다.
- 클래스 Class 이해하기
- 객체지향 프로그래밍의 시작
- 현실 세계를 코드로 표현하는 방법
