공통 성공 에러 응답 정의 - depromeet/Took-BE GitHub Wiki

공통 성공 응답

{
    "status": "CREATED",
    "message": "요청이 성공적으로 처리되었습니다.",
    "timestamp": "2025-02-07T02:20:33.315583",
    "data": {
        "test1": 1,
        "test2": 2,
        "test3": 3
    }
}

컨트롤러 구현 방법

아래와 같이 응답할 status와 body를 SuccessResponse.of()로 정의합니다. status를 정의하지 않은 경우 기본으로 200이 반환되도록 하였습니다.

@GetMapping("/api/test/response")
public SuccessResponse test() {
    TestDto response = new TestDto(1, 2, 3);
    return SuccessResponse.of(HttpStatus.CREATED, response);
}

공통 에러 응답

기본 에러 응답

상황: 커스텀 예외(TookException)가 발생할 때

관련 클래스: ErrorResponse

{
    "status": "BAD_REQUEST",
    "message": "유효하지 않은 사용자입니다.",
    "timestamp": "2025-02-07T01:45:32.235379"
}

기본 예외는 위와 같이 정의하였고, 서버 예외, 유효성 예외 등 특이한 경우의 예외들은 아래와 같이 상세 정보와 함께 반환하도록 하였습니다. 개발하면서 필요한 경우 핸들러를 하나씩 추가해가면 됩니다!

유효하지 않은 경로 에러 응답

상황: 구현되지 않은 API 경로에 대한 요청이 들어올 때

관련 클래스: ErrorResponse

{
    "status": "BAD_REQUEST",
    "message": "유효하지 않은 경로입니다.",
    "timestamp": "2025-02-07T02:07:43.898087"
}

유효성 검증 실패 에러 응답

상황: @Valid 유효성 검증에 실패할 때

관련 클래스: ValidationErrorResponse

{
	  "errors": [
	    {
		      "field": "email",
		      "message": "유효한 이메일 주소여야 합니다",
		      "value": "invalid.email"
	    },
	    {
		      "field": "age",
		      "message": "0보다 큰 값이어야 합니다",
		      "value": "-5"
	    }
	  ],
    "status": "BAD_REQUEST",
	  "message": "유효하지 않은 요청값입니다.",
	  "timestamp": "2025-02-07T01:46:01.139924",
}

서버 에러 응답

상황: 서버 내 예기치 못한 예외가 발생했을 때

관련 클래스: ServerErrorResponse

{
    "error": {
        "exception": "NullPointerException",
        "message": "Cannot invoke \"com.evenly.blok.domain.test.controller.TestDto.getTest1()\" because \"test\" is null",
        "stackTrace": "com.evenly.blok.domain.test.controller.TestController"
    },
    "status": "INTERNAL_SERVER_ERROR",
    "message": "서버 관리자에게 문의하세요.",
    "timestamp": "2025-02-07T01:51:00.403302"
}

커스텀 예외

저희 서비스가 대표로 사용할 한가지 커스텀 예외인 TookException을 정의하였습니다. 클라이언트에게 알리고 싶은 예외의 경우 아래 커스텀 예외를 사용해 구현해주시면 됩니다. (ex. 400, 404, 401 등) TookException이 발생했다는 것은 저희가 의도한 예외가 발생했다는 의미입니다.

public class TookException extends RuntimeException {

    private final ErrorCode errorCode;
}

커스텀 예외 구현 방법

예시: 유효하지 않은 사용자라는 예외를 반환하고 싶다.

  1. MemberErrorCode 클래스에 상태코드(HttpStatus)와 에러메시지(String) 정의하기

    // /domain/member/exception/MemberErrorCode.java
    
    @Getter
    @RequiredArgsConstructor
    public enum MemberErrorCode implements ErrorCode {
    
        INVALID_MEMBER(HttpStatus.BAD_REQUEST, "유효하지 않은 사용자입니다."),
        ;
    
        private final HttpStatus status;
        private final String message;
    }
    
  2. 예외를 발생시킬 지점에서 생성한 에러 코드를 바탕으로 커스텀 예외 생성하기

    // /domain/member/service/MemberService.java
    
    public void test() {
        throw new TookException(MemberErrorCode.INVALID_MEMBER);
    }