Flask 에러 처리 — 예외를 우아하게 다루기
Flask 에러 처리 — 예외를 우아하게 다루기
애플리케이션은 실패하고 서버도 실패해요. 언젠가는 운영에서 예외를 마주하게 됩니다. 내 코드가 100% 정확해도 예외는 계속 나와요. 왜냐하면 그 주변의 모든 것이 실패할 수 있기 때문이에요. 그래서 에러를 어떻게 처리할지 설계해 두는 게 중요해요.
완벽해 보이는 코드도 서버 오류를 만들 수 있는 상황이 몇 가지 있어요.
- 클라이언트가 요청을 일찍 종료했는데 앱이 아직 들어오는 데이터를 읽고 있는 경우
- 데이터베이스 서버가 과부하로 쿼리를 처리하지 못한 경우
- 파일 시스템이 가득 찬 경우
- 하드 드라이브가 고장난 경우
- 백엔드 서버가 과부하된 경우
- 사용 중인 라이브러리의 프로그래밍 오류
- 서버가 다른 시스템과의 네트워크 연결에 실패한 경우
이건 겪을 수 있는 문제의 일부일 뿐이에요. 기본적으로 운영 모드에서 예외가 발생하면 Flask는 아주 단순한 페이지를 보여주고 예외를 logger에 기록해요. 하지만 더 잘할 수 있어요. 이 문서는 맞춤 예외와 서드파티 도구를 포함한 더 나은 에러 처리 구성을 다뤄요.
에러 로깅 도구
에러 메일을 보내는 방식은 사용자가 많은 에러를 맞으면 금방 감당이 안 돼요. 그래서 Flask 문서는 애플리케이션 에러 처리에 Sentry를 권장해요. Sentry는 중복 에러를 모아주고, 전체 스택 트레이스와 로컬 변수를 캡처해 디버깅에 도움을 주고, 새 에러나 빈도 임계값에 따라 메일을 보내줘요.
Sentry를 쓰려면 sentry-sdk 클라이언트를 flask 엑스트라와 함께 설치해요.
$ pip install sentry-sdk[flask]
그리고 Flask 앱에 이렇게 추가해요.
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init('YOUR_DSN_HERE', integrations=[FlaskIntegration()])
YOUR_DSN_HERE는 Sentry 설치에서 받은 DSN 값으로 바꿔야 해요. 설치 후 Internal Server Error로 이어지는 실패는 자동으로 Sentry에 보고돼요.
에러 핸들러
Flask에서 에러가 발생하면 적절한 HTTP 상태 코드가 반환돼요. 400-499는 클라이언트의 요청 데이터나 요청된 데이터의 오류를, 500-599는 서버나 애플리케이션 자체의 오류를 나타내요.
사용자에게 맞춤 에러 페이지를 보여주고 싶을 때 **에러 핸들러(error handler)**를 등록하면 돼요. 에러 핸들러는 특정 타입의 에러가 발생했을 때 응답을 반환하는 함수예요. 뷰가 요청 URL에 매칭되면 응답을 반환하는 것과 비슷하게, 에러 핸들러는 에러가 발생하면 응답을 반환해요. 핸들러는 처리 중인 에러의 인스턴스를 전달받는데, 대부분 HTTPException이에요.
응답의 상태 코드는 핸들러의 코드로 자동 설정되지 않아요. 핸들러에서 응답을 반환할 때 적절한 HTTP 상태 코드를 직접 제공해야 해요.
@app.errorhandler(404)
def not_found(e):
return "Page not found", 404
나만의 예외 클래스를 만들어 커스텀 에러 핸들러와 연결할 수도 있어요. 예를 들어 API에서 오류를 JSON으로 돌려주는 패턴을 만들어 볼 수 있어요.
정리하면, Flask 에러 처리는 생긴 예외를 logger에 남기고, 필요하면 Sentry로 집계하며, @app.errorhandler로 HTTP 에러에 맞춤 응답을 등록하는 방식이에요. 에러 핸들러에서 상태 코드를 직접 지정해야 한다는 점만 기억하면 돼요.