1111import org .springframework .http .HttpStatus ;
1212import org .springframework .http .HttpStatusCode ;
1313import org .springframework .http .ResponseEntity ;
14+ import org .springframework .http .converter .HttpMessageNotReadableException ;
1415import org .springframework .web .bind .MethodArgumentNotValidException ;
1516import org .springframework .web .bind .annotation .ExceptionHandler ;
1617import org .springframework .web .bind .annotation .RestController ;
1718import org .springframework .web .bind .annotation .RestControllerAdvice ;
1819import org .springframework .web .context .request .ServletWebRequest ;
1920import org .springframework .web .context .request .WebRequest ;
21+ import org .springframework .web .method .annotation .MethodArgumentTypeMismatchException ;
2022import org .springframework .web .servlet .mvc .method .annotation .ResponseEntityExceptionHandler ;
2123
2224import java .util .LinkedHashMap ;
2325import java .util .Map ;
2426import java .util .Optional ;
2527
2628@ Slf4j
27- @ RestControllerAdvice (annotations = {RestController .class })
29+ @ RestControllerAdvice (annotations = { RestController .class })
2830public class ExceptionAdvice extends ResponseEntityExceptionHandler {
2931
32+ /**
33+ * @Valid 어노테이션을 통한 검증 실패 시 발생합니다.
34+ * 주로 @RequestParam, @PathVariable 검증 실패 시 발생합니다.
35+ */
3036 @ ExceptionHandler
3137 public ResponseEntity <Object > validation (ConstraintViolationException e , WebRequest request ) {
3238 String errorMessage = e .getConstraintViolations ().stream ()
@@ -37,36 +43,61 @@ public ResponseEntity<Object> validation(ConstraintViolationException e, WebRequ
3743 return handleExceptionInternalConstraint (e , GeneralErrorCode .valueOf (errorMessage ), HttpHeaders .EMPTY , request );
3844 }
3945
46+ /**
47+ * @Valid 어노테이션을 통한 검증 실패 시 발생합니다.
48+ * 주로 @RequestBody 검증 실패 시 발생합니다.
49+ */
4050 @ Override
41- public ResponseEntity <Object > handleMethodArgumentNotValid (MethodArgumentNotValidException e , HttpHeaders headers , HttpStatusCode status , WebRequest request ) {
51+ public ResponseEntity <Object > handleMethodArgumentNotValid (MethodArgumentNotValidException e , HttpHeaders headers ,
52+ HttpStatusCode status , WebRequest request ) {
4253 Map <String , String > errors = new LinkedHashMap <>();
4354
4455 e .getBindingResult ().getFieldErrors ()
4556 .forEach (fieldError -> {
4657 String fieldName = fieldError .getField ();
4758 String errorMessage = Optional .ofNullable (fieldError .getDefaultMessage ()).orElse ("" );
48- errors .merge (fieldName , errorMessage , (existingErrorMessage , newErrorMessage ) -> existingErrorMessage + ", " + newErrorMessage );
59+ errors .merge (fieldName , errorMessage ,
60+ (existingErrorMessage , newErrorMessage ) -> existingErrorMessage + ", " + newErrorMessage );
4961 });
5062
51- return handleExceptionInternalArgs (e , HttpHeaders .EMPTY , GeneralErrorCode .valueOf ("_BAD_REQUEST" ), request , errors );
63+ return handleExceptionInternalArgs (e , HttpHeaders .EMPTY , GeneralErrorCode .valueOf ("_BAD_REQUEST" ), request ,
64+ errors );
5265 }
5366
67+ /**
68+ * JSON Request Body 파싱 실패 시 발생합니다.
69+ * 주로 잘못된 형식의 JSON이나 Enum 타입 불일치 시 발생합니다.
70+ */
71+ @ Override
72+ public ResponseEntity <Object > handleHttpMessageNotReadable (HttpMessageNotReadableException e , HttpHeaders headers ,
73+ HttpStatusCode status , WebRequest request ) {
74+ return handleExceptionInternalConstraint (e , GeneralErrorCode ._INVALID_INPUT , headers , request );
75+ }
76+
77+ /**
78+ * 처리되지 않은 모든 예외를 처리합니다.
79+ * 500 Internal Server Error를 반환합니다.
80+ */
5481 @ ExceptionHandler
5582 public ResponseEntity <Object > exception (Exception e , WebRequest request ) {
56- log .error ("500 Error" ,e );
57- return handleExceptionInternalFalse (e , GeneralErrorCode ._INTERNAL_SERVER_ERROR .getHttpStatus (), request , e .getMessage ());
83+ log .error ("500 Error" , e );
84+ return handleExceptionInternalFalse (e , GeneralErrorCode ._INTERNAL_SERVER_ERROR .getHttpStatus (), request ,
85+ e .getMessage ());
5886 }
5987
60- // 비즈니스 로직 커스텀 예외처리
88+ /**
89+ * 비즈니스 로직 실행 중 발생하는 커스텀 예외를 처리합니다.
90+ */
6191 @ ExceptionHandler (value = GeneralException .class )
6292 public ResponseEntity onThrowException (GeneralException generalException , HttpServletRequest request ) {
6393 return handleExceptionInternal (generalException ,
6494 generalException .getCode (),
6595 HttpHeaders .EMPTY ,
6696 request );
6797 }
98+
6899 private ResponseEntity <Object > handleExceptionInternal (Exception e , BaseErrorCode reason ,
69- HttpHeaders headers , HttpServletRequest request ) {
100+ HttpHeaders headers , HttpServletRequest request ) {
70101
71102 ApiResponse <Object > body = ApiResponse .onFailure (reason , reason .getMessage ());
72103
@@ -76,43 +107,40 @@ private ResponseEntity<Object> handleExceptionInternal(Exception e, BaseErrorCod
76107 body ,
77108 headers ,
78109 reason .getHttpStatus (),
79- webRequest
80- );
110+ webRequest );
81111 }
82112
83113 private ResponseEntity <Object > handleExceptionInternalFalse (Exception e ,
84- HttpStatus status , WebRequest request , String errorPoint ) {
85- ApiResponse <Object > body = ApiResponse .onFailure (GeneralErrorCode ._INTERNAL_SERVER_ERROR ,errorPoint );
114+ HttpStatus status , WebRequest request , String errorPoint ) {
115+ ApiResponse <Object > body = ApiResponse .onFailure (GeneralErrorCode ._INTERNAL_SERVER_ERROR , errorPoint );
86116 return super .handleExceptionInternal (
87117 e ,
88118 body ,
89119 HttpHeaders .EMPTY ,
90120 status ,
91- request
92- );
121+ request );
93122 }
94123
95- private ResponseEntity <Object > handleExceptionInternalArgs (Exception e , HttpHeaders headers , GeneralErrorCode errorCommonStatus ,
96- WebRequest request , Map <String , String > errorArgs ) {
124+ private ResponseEntity <Object > handleExceptionInternalArgs (Exception e , HttpHeaders headers ,
125+ GeneralErrorCode errorCommonStatus ,
126+ WebRequest request , Map <String , String > errorArgs ) {
97127 ApiResponse <Object > body = ApiResponse .onFailure (errorCommonStatus , errorArgs );
98128 return super .handleExceptionInternal (
99129 e ,
100130 body ,
101131 headers ,
102132 errorCommonStatus .getHttpStatus (),
103- request
104- );
133+ request );
105134 }
106135
107136 private ResponseEntity <Object > handleExceptionInternalConstraint (Exception e , GeneralErrorCode errorCommonStatus ,
108- HttpHeaders headers , WebRequest request ) {
137+ HttpHeaders headers , WebRequest request ) {
109138 ApiResponse <Object > body = ApiResponse .onFailure (errorCommonStatus , null );
110139 return super .handleExceptionInternal (
111140 e ,
112141 body ,
113142 headers ,
114143 errorCommonStatus .getHttpStatus (),
115- request
116- );
144+ request );
117145 }
118146}
0 commit comments