Skip to content

Commit e797a1f

Browse files
committed
Fix: Exception Handler 수정
1 parent f6725fd commit e797a1f

3 files changed

Lines changed: 62 additions & 109 deletions

File tree

Lines changed: 17 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,29 @@
11
package com.ktb.assignment.dto;
22

3-
import com.fasterxml.jackson.annotation.JsonIgnore;
3+
import com.fasterxml.jackson.annotation.JsonInclude;
44
import com.ktb.assignment.exception.CommonException;
55
import com.ktb.assignment.exception.ErrorCode;
6-
import jakarta.annotation.Nullable;
76
import lombok.Builder;
8-
import org.antlr.v4.runtime.misc.NotNull;
9-
import org.springframework.http.HttpStatus;
10-
import org.springframework.http.converter.HttpMessageNotReadableException;
11-
import org.springframework.web.bind.MethodArgumentNotValidException;
12-
import org.springframework.web.bind.MissingServletRequestParameterException;
13-
import org.springframework.web.method.annotation.HandlerMethodValidationException;
14-
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
157

168
@Builder
17-
public record ResponseDto<T>(@JsonIgnore HttpStatus httpStatus,
18-
@NotNull Boolean success,
19-
@Nullable T data,
20-
@Nullable ExceptionDto error) {
21-
22-
//static 으로 인한 공용 사용 가능
23-
24-
//성공시
25-
public static <T> ResponseDto<T> ok(@Nullable T data) { //성공
26-
return new ResponseDto<T>(HttpStatus.OK, true, data, null);
27-
}
28-
29-
public static <T> ResponseDto<T> created(@Nullable final T data) {
30-
return new ResponseDto<>(HttpStatus.CREATED, true, data, null);
31-
}
32-
33-
//실패시
34-
public static ResponseDto<Object> fail(final HandlerMethodValidationException e) { //실패한 경우
35-
36-
return new ResponseDto<>(HttpStatus.BAD_REQUEST, false, null, new ExceptionDto(ErrorCode.INVALID_PARAMETER));
37-
}
38-
39-
public static ResponseDto<Object> fail(final CommonException e) { //실패한 경우
40-
return new ResponseDto<>(e.getErrorCode().getHttpStatus(), false, null, new ExceptionDto(e.getErrorCode()));
41-
}
42-
43-
public static ResponseDto<Object> fail(final MethodArgumentNotValidException e) {
44-
return new ResponseDto<>(HttpStatus.BAD_REQUEST, false, null, new ArgumentNotValidExceptionDto(e));
45-
}
46-
47-
public static ResponseDto<Object> fail(final MethodArgumentTypeMismatchException e) {
48-
return new ResponseDto<>(HttpStatus.INTERNAL_SERVER_ERROR, false, null,
49-
new ExceptionDto(ErrorCode.INVALID_PARAMETER));
9+
@JsonInclude(JsonInclude.Include.NON_NULL)
10+
public record ResponseDto<T>(
11+
boolean success,
12+
T data,
13+
ExceptionDto error
14+
) {
15+
// 성공 응답
16+
public static <T> ResponseDto<T> ok(T data) {
17+
return new ResponseDto<>(true, data, null);
5018
}
5119

52-
public static ResponseDto<Object> fail(final MissingServletRequestParameterException e) {
53-
return new ResponseDto<>(HttpStatus.BAD_REQUEST, false, null,
54-
new ExceptionDto(ErrorCode.MISSING_REQUEST_PARAMETER));
20+
// 실패 응답 (커스텀 예외)
21+
public static ResponseDto<Object> fail(CommonException e) {
22+
return new ResponseDto<>(false, null, new ExceptionDto(e.getErrorCode()));
5523
}
5624

57-
public static ResponseDto<Object> fail(final HttpMessageNotReadableException e) {
58-
return new ResponseDto<>(HttpStatus.BAD_REQUEST, false, null, new ExceptionDto(ErrorCode.MISSING_REQUEST_BODY));
25+
// 실패 응답 (기본 예외)
26+
public static ResponseDto<Object> fail(ErrorCode errorCode) {
27+
return new ResponseDto<>(false, null, new ExceptionDto(errorCode));
5928
}
60-
}
29+
}

src/main/java/com/ktb/assignment/exception/ErrorCode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ public enum ErrorCode {
1111
INVALID_PARAMETER("40000", HttpStatus.BAD_REQUEST, "유효하지 않는 파라미터입니다."),
1212
MISSING_REQUEST_PARAMETER("40001", HttpStatus.BAD_REQUEST, "필수 파라미터가 누락되었습니다."),
1313
MISSING_REQUEST_BODY("40002", HttpStatus.BAD_REQUEST, "요청 바디가 누락되었습니다."),
14+
MISSING_API_KEY_PARAMETER("40003", HttpStatus.BAD_REQUEST, "API Key가 누락되었습니다."),
1415

1516
// 403 error
16-
ACCESS_DENIED_ERROR("40300", HttpStatus.FORBIDDEN, "액세스 권한이 없습니다."),
17+
ACCESS_DENIED_ERROR("40300", HttpStatus.FORBIDDEN, "API Key가 일치하지 않습니다."),
1718

1819
// 404 error
1920
NOT_FOUND_END_POINT("40400", HttpStatus.NOT_FOUND, "존재하지 않는 엔드포인트입니다."),
20-
NOT_FOUND_RESOURCE("40401", HttpStatus.NOT_FOUND, "요청한 데이터를 찾을 수 없습니다."),
2121

2222
// 500 error
2323
SERVER_ERROR("50000", HttpStatus.INTERNAL_SERVER_ERROR, "서버 내부 오류입니다.");

src/main/java/com/ktb/assignment/exception/GlobalExceptionHandler.java

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,85 +2,69 @@
22

33
import com.ktb.assignment.dto.ResponseDto;
44
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.http.ResponseEntity;
56
import org.springframework.http.converter.HttpMessageNotReadableException;
67
import org.springframework.web.HttpRequestMethodNotSupportedException;
7-
import org.springframework.web.bind.MethodArgumentNotValidException;
8-
import org.springframework.web.bind.MissingServletRequestParameterException;
98
import org.springframework.web.bind.annotation.ExceptionHandler;
109
import org.springframework.web.bind.annotation.RestControllerAdvice;
11-
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
1210
import org.springframework.web.multipart.support.MissingServletRequestPartException;
1311
import org.springframework.web.servlet.NoHandlerFoundException;
1412

1513
@Slf4j
1614
@RestControllerAdvice
1715
public class GlobalExceptionHandler {
1816

19-
// 지원되지 않는 HTTP 메소드를 사용할 때 발생하는 예외
20-
@ExceptionHandler(value = {NoHandlerFoundException.class, HttpRequestMethodNotSupportedException.class})
21-
public ResponseDto<?> handleNoPageFoundException(Exception e) {
22-
log.error("handleNoPageFoundException() in GlobalExceptionHandler throw NoHandlerFoundException : {}",
23-
e.getMessage());
24-
return ResponseDto.fail(new CommonException(ErrorCode.NOT_FOUND_END_POINT));
25-
}
17+
// 존재하지 않는 API 요청 (404)
18+
@ExceptionHandler({NoHandlerFoundException.class, HttpRequestMethodNotSupportedException.class})
19+
public ResponseEntity<ResponseDto<?>> handleNoPageFoundException(Exception e) {
20+
log.error("handleNoPageFoundException: {}", e.getMessage());
2621

27-
// @Validated 어노테이션을 사용하여 검증을 수행할 때 발생하는 예외
28-
@ExceptionHandler(value = {MethodArgumentNotValidException.class})
29-
public ResponseDto<?> handleArgumentNotValidException(MethodArgumentNotValidException e) {
30-
log.error(
31-
"handleArgumentNotValidException() in GlobalExceptionHandler throw MethodArgumentNotValidException : {}",
32-
e.getMessage());
33-
return ResponseDto.fail(e);
22+
CommonException exception = new CommonException(ErrorCode.NOT_FOUND_END_POINT);
23+
return ResponseEntity
24+
.status(exception.getErrorCode().getHttpStatus()) // ✅ HTTP 상태 코드 직접 설정
25+
.body(ResponseDto.fail(exception));
3426
}
3527

36-
// 메소드의 인자 타입이 일치하지 않을 때 발생하는 예외
37-
@ExceptionHandler(value = {MethodArgumentTypeMismatchException.class})
38-
public ResponseDto<?> handleArgumentNotValidException(MethodArgumentTypeMismatchException e) {
39-
log.error(
40-
"handleArgumentNotValidException() in GlobalExceptionHandler throw MethodArgumentTypeMismatchException : {}",
41-
e.getMessage());
42-
return ResponseDto.fail(e);
43-
}
28+
// 필수 요청 파라미터가 누락된 경우 (400)
29+
@ExceptionHandler(MissingServletRequestPartException.class)
30+
public ResponseEntity<ResponseDto<?>> handleServletRequestParameterException(MissingServletRequestPartException e) {
31+
log.error("handleServletRequestParameterException: {}", e.getMessage());
4432

45-
// 필수 파라미터가 누락되었을 때 발생하는 예외
46-
@ExceptionHandler(value = {MissingServletRequestParameterException.class})
47-
public ResponseDto<?> handleServletRequestParameterException(MissingServletRequestParameterException e) {
48-
log.error(
49-
"handleArgumentNotValidException() in GlobalExceptionHandler throw MissingServletRequestParameterException : {}",
50-
e.getMessage());
51-
return ResponseDto.fail(e);
33+
CommonException exception = new CommonException(ErrorCode.MISSING_REQUEST_PARAMETER);
34+
return ResponseEntity
35+
.status(exception.getErrorCode().getHttpStatus())
36+
.body(ResponseDto.fail(exception));
5237
}
5338

54-
// 필수 RequestPart가 누락되었을 때 발생하는 예외
55-
@ExceptionHandler(value = {MissingServletRequestPartException.class})
56-
public ResponseDto<?> handleServletRequestParameterException(MissingServletRequestPartException e) {
57-
log.error(
58-
"handleArgumentNotValidException() in GlobalExceptionHandler throw MissingServletRequestPartException : {}",
59-
e.getMessage());
60-
return ResponseDto.fail(new CommonException(ErrorCode.MISSING_REQUEST_PARAMETER));
61-
}
39+
// 요청 Body가 없는 경우 (400)
40+
@ExceptionHandler(HttpMessageNotReadableException.class)
41+
public ResponseEntity<ResponseDto<?>> handleMessageNotReadableException(HttpMessageNotReadableException e) {
42+
log.error("handleMessageNotReadableException: {}", e.getMessage());
6243

63-
// post 요청 body가 없을 때 발생하는 에러
64-
@ExceptionHandler(value = {HttpMessageNotReadableException.class})
65-
public ResponseDto<?> handleMessageNotReadableException(HttpMessageNotReadableException e) {
66-
log.error(
67-
"handleArgumentNotValidException() in GlobalExceptionHandler throw HttpMessageNotReadableException : {}",
68-
e.getMessage());
69-
return ResponseDto.fail(e);
44+
CommonException exception = new CommonException(ErrorCode.MISSING_REQUEST_BODY);
45+
return ResponseEntity
46+
.status(exception.getErrorCode().getHttpStatus())
47+
.body(ResponseDto.fail(exception));
7048
}
7149

72-
// 개발자가 직접 정의한 예외
73-
@ExceptionHandler(value = {CommonException.class})
74-
public ResponseDto<?> handleApiException(CommonException e) {
75-
log.error("handleApiException() in GlobalExceptionHandler throw CommonException : {}", e.getMessage());
76-
return ResponseDto.fail(e);
50+
// 개발자가 직접 정의한 커스텀 예외
51+
@ExceptionHandler(CommonException.class)
52+
public ResponseEntity<ResponseDto<?>> handleApiException(CommonException e) {
53+
log.error("handleApiException: {}", e.getMessage());
54+
55+
return ResponseEntity
56+
.status(e.getErrorCode().getHttpStatus())
57+
.body(ResponseDto.fail(e));
7758
}
7859

79-
// 서버, DB 예외
80-
@ExceptionHandler(value = {Exception.class})
81-
public ResponseDto<?> handleException(Exception e) {
82-
log.error("handleException() in GlobalExceptionHandle throw Exception : {}");
83-
e.printStackTrace();
84-
return ResponseDto.fail(new CommonException(ErrorCode.SERVER_ERROR));
60+
// 서버 내부 오류 (500)
61+
@ExceptionHandler(Exception.class)
62+
public ResponseEntity<ResponseDto<?>> handleException(Exception e) {
63+
log.error("handleException: {}", e.getMessage(), e);
64+
65+
CommonException exception = new CommonException(ErrorCode.SERVER_ERROR);
66+
return ResponseEntity
67+
.status(exception.getErrorCode().getHttpStatus())
68+
.body(ResponseDto.fail(exception));
8569
}
86-
}
70+
}

0 commit comments

Comments
 (0)