package com.zioinfo.mes.common; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; import org.springframework.http.HttpStatus; import org.springframework.security.access.AccessDeniedException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.multipart.MaxUploadSizeExceededException; /** * 전역 예외 처리. * *

보안 불변 규칙: 스택트레이스를 응답에 절대 노출하지 않는다. * 에러 코드 + 요약 메시지만 반환한다. */ @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MaxUploadSizeExceededException.class) @ResponseStatus(HttpStatus.PAYLOAD_TOO_LARGE) public ApiResponse handleMaxSize(MaxUploadSizeExceededException e) { log.warn("업로드 크기 초과: {}", e.getMessage()); return ApiResponse.fail("ERR-MES-413: 파일 크기 초과 (최대 20MB)"); } @ExceptionHandler(AccessDeniedException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public ApiResponse handleAccessDenied(AccessDeniedException e) { log.warn("권한 거부: {}", e.getMessage()); return ApiResponse.fail("ERR-MES-403: 권한이 없습니다"); } @ExceptionHandler(IllegalArgumentException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ApiResponse handleIllegalArg(IllegalArgumentException e) { log.warn("잘못된 요청: {}", e.getMessage()); return ApiResponse.fail(e.getMessage()); } @ExceptionHandler(DataAccessException.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ApiResponse handleDataAccess(DataAccessException e) { // 보안 불변 규칙: SQL/테이블/쿼리/스택 상세 절대 미노출 — 내부 로그만 남기고 일반 메시지 반환 log.error("DB 오류", e); return ApiResponse.fail("ERR-MES-DB: 데이터 처리 중 오류가 발생했습니다"); } @ExceptionHandler(RuntimeException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ApiResponse handleRuntime(RuntimeException e) { // 스택트레이스 미노출 — 에러 코드/요약만 반환 log.warn("업무 오류: {}", e.getMessage()); return ApiResponse.fail(e.getMessage()); } @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ApiResponse handleGeneral(Exception e) { log.error("시스템 오류", e); return ApiResponse.fail("ERR-SYS-001"); } }