""" 에러 처리 유틸리티 표준화된 에러 응답 및 예외 처리 """ from fastapi import HTTPException, Request from fastapi.responses import JSONResponse from fastapi.exceptions import RequestValidationError from sqlalchemy.exc import SQLAlchemyError from typing import Dict, Any import traceback from .logger import get_logger logger = get_logger(__name__) class TKMPException(Exception): """TK-MP 프로젝트 커스텀 예외""" def __init__(self, message: str, error_code: str = "TKMP_ERROR", status_code: int = 500): self.message = message self.error_code = error_code self.status_code = status_code super().__init__(self.message) class ErrorResponse: """표준화된 에러 응답 생성기""" @staticmethod def create_error_response( message: str, error_code: str = "INTERNAL_ERROR", status_code: int = 500, details: Dict[str, Any] = None ) -> Dict[str, Any]: """표준화된 에러 응답 생성""" response = { "success": False, "error": { "code": error_code, "message": message, "timestamp": "2025-01-01T00:00:00Z" # 실제로는 datetime.utcnow().isoformat() } } if details: response["error"]["details"] = details return response @staticmethod def validation_error_response(errors: list) -> Dict[str, Any]: """검증 에러 응답""" return ErrorResponse.create_error_response( message="입력 데이터 검증에 실패했습니다.", error_code="VALIDATION_ERROR", status_code=422, details={"validation_errors": errors} ) @staticmethod def database_error_response(error: str) -> Dict[str, Any]: """데이터베이스 에러 응답""" return ErrorResponse.create_error_response( message="데이터베이스 작업 중 오류가 발생했습니다.", error_code="DATABASE_ERROR", status_code=500, details={"db_error": error} ) @staticmethod def file_error_response(error: str) -> Dict[str, Any]: """파일 처리 에러 응답""" return ErrorResponse.create_error_response( message="파일 처리 중 오류가 발생했습니다.", error_code="FILE_ERROR", status_code=400, details={"file_error": error} ) async def tkmp_exception_handler(request: Request, exc: TKMPException): """TK-MP 커스텀 예외 핸들러""" logger.error(f"TK-MP 예외 발생: {exc.message} (코드: {exc.error_code})") return JSONResponse( status_code=exc.status_code, content=ErrorResponse.create_error_response( message=exc.message, error_code=exc.error_code, status_code=exc.status_code ) ) async def validation_exception_handler(request: Request, exc: RequestValidationError): """검증 예외 핸들러""" logger.warning(f"검증 오류: {exc.errors()}") return JSONResponse( status_code=422, content=ErrorResponse.validation_error_response(exc.errors()) ) async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError): """SQLAlchemy 예외 핸들러""" logger.error(f"데이터베이스 오류: {str(exc)}", exc_info=True) return JSONResponse( status_code=500, content=ErrorResponse.database_error_response(str(exc)) ) async def general_exception_handler(request: Request, exc: Exception): """일반 예외 핸들러""" logger.error(f"예상치 못한 오류: {str(exc)}", exc_info=True) return JSONResponse( status_code=500, content=ErrorResponse.create_error_response( message="서버 내부 오류가 발생했습니다.", error_code="INTERNAL_SERVER_ERROR", status_code=500, details={"error": str(exc)} if logger.level <= 10 else None # DEBUG 레벨일 때만 상세 에러 표시 ) ) def setup_error_handlers(app): """FastAPI 앱에 에러 핸들러 등록""" app.add_exception_handler(TKMPException, tkmp_exception_handler) app.add_exception_handler(RequestValidationError, validation_exception_handler) app.add_exception_handler(SQLAlchemyError, sqlalchemy_exception_handler) app.add_exception_handler(Exception, general_exception_handler) logger.info("에러 핸들러 등록 완료")