hooneats 2022. 6. 16. 02:10
728x90

참고 블로그 1

 

ResponseBody 로 응답을 하는 RestController 의 경우 ResponseEntity body 에 data 가 객체로 담기면 Json 으로 변환해 내려주게된다. 그러나 String 이 담긴다면 plain/test 형태로 내려주기에 응답의 형태가 달라지게 된다. 

-> 즉,

HttpResponse 응답을 내려줄때 정상응답/에러 등등 에서 데이터의 형식을 json 으로 통일시켜줄 필요가 있다.

 

이를 위해 공통 응답 클래스인 ApiResponse 를 만들어 사용하게 된다.

 

ApiResponse 클래스는 status, data, message 세가지 필드를 갖는다.
status : 정상(success), 예외(error), 오류(fail) 중 한 값을 갖는다.
data : 정상(success)의 경우 실제 전송될 데이터를, 오류(fail)의 경우 유효성 검증에 실패한 데이터의 목록을 응답한다. 어떤 타입도 처리할 수 있도록 제네릭을 사용한다.
message : 예외(error)의 경우 예외 메시지를 응답한다.

 

ApiResponse.java

@NoArgsConstructor
@Getter
@Setter
public class ApiResponse<T> {

    private String code;

    private String message;

    private String messageCode; // 추후 message.properties 와 활용도 가능

    private T data;

    ApiResponse(ErrorCode errorCode) {
        this(errorCode, null, null);
    }

    ApiResponse(ErrorCode errorCode, T data) {
        this.code = errorCode.getCode();
        this.message = errorCode.getDefaultMessage();
        this.data = data;
    }

    ApiResponse(ErrorCode errorCode, String responseMessage, T data) {
        this.code = errorCode.getCode();
        this.message = (responseMessage == null ? errorCode.getDefaultMessage() : responseMessage);
        this.data = data;
    }

    ApiResponse(ErrorCode errorCode, String message, String messageCode, T data) {
        this.code = errorCode.getCode();
        this.message = message;
        this.messageCode = messageCode;
        this.data = data;
    }

    public T getData() {
        return data;
    }
}

 

 

Error 코드를 따로 정의해 자체적인 role 를 정립해 사용할 수도 있다.

ErrorCode.java

@Getter
public enum ErrorCode {

    SUCCESS                                     ("2000", "OK"),

    /* 1001 ~ 2000 logic error*/
    SYSTEM_PERMISSION_ERROR                     ("1001", "시스템 권한 오류"),
    ...

    /* 9001 ~  system error*/
    SYSTEM_ERROR                                ("9001", "시스템 오류"),
    ...

    private final String code;
    private final String defaultMessage;

    ErrorCode(String code, String defaultMessage) {
        this.code = code;
        this.defaultMessage = defaultMessage;
    }

}

 

 

ApiResponse 객체를 생산할 팩토리 클래스를 정의하자

ApiResponseGenerator.java

public class ApiResponseGenerator {

    private static final ApiResponse<Void> RESULT_SUCCESS = new ApiResponse<>(ErrorCode.SUCCESS);
    private static final ApiResponse<Void> RESULT_ERROR = new ApiResponse<>(ErrorCode.UNKNOWN_ERROR);

    private ApiResponseGenerator() {

    }

    public static ApiResponse<Void> success() {
        return RESULT_SUCCESS;
    }

    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(ErrorCode.SUCCESS, null, data);
    }

    public static ApiResponse<Void> fail() {
        return RESULT_ERROR;
    }

    public static ApiResponse<Void> fail(ErrorCode code) {
        return new ApiResponse<>(code);
    }

    public static <T> ApiResponse<T> fail(ErrorCode code, T data) {
        return new ApiResponse<>(code, data);
    }

    public static ApiResponse<Void> fail(ErrorCode code, String msg) {
        return new ApiResponse<>(code, msg, null);
    }
    
    public static ApiResponse<String> fail(ErrorCode code, String msg, String messageCode) {
        return new ApiResponse<>(code, msg, messageCode,null);
    }

}

 

보통 ApiResponse 처럼 프로그램의 비즈니스에 관련되지않고 여러 모듈에 적용되는 utils 속하는 파일은 support 모듈을 만들어 관리하게된다. 때문에 support 모듈을 루트 build.gradle 에 implements 해줘서 subProject 들에서 사용할 수 있게 하자.

 

build.gradle

subprojects {
	...
	dependencies {
        implementation project(":support")
        ...
    }
}

 

사용은 다음과 같이 사용하면된다.

BlogController.java

@RestController
@RequestMapping("/blog")
public class BlogController {

    @GetMapping
    public ApiResponse<String> returnOk() {
        return ApiResponseGenerator.success("성공");
    }
    
    @GetMapping("/error")
    public ApiResponse<String> returnError() {
        return ApiResponseGenerator.fail(ErrorCode.BAD_REQUEST_ERROR, "요청실패입니다.", null);
    }
}

 

그러면 결과는 다음과 같이 Json 형태로 통일되어 나타난다.

 

 

 

마찬가지로 범용적인 Error 처리 또한 해보자

728x90