develop/Backend -Java

[spring] 에러 코드 관리

reko_ 2022. 11. 25. 21:17

여러 api에 대한 수많은 에러 코드를 하나의 enum 클래스안에 정의한다.

 

예를 들어 관리자가 특정 유저의 nickname으로 유저 전체 정보를 조회하는 api가 있다면

(관리자 권한은 주어졌고 get method로 얻을 수 있다고 치자)

 

 

미리 정의해둔 에러 코드 클래스는 다음과 같다. (닉네임을 입력 받지 못했을 때 에러 처리만 작성)

public enum ResponseStatus{

    private final boolean isSuccess;
    private final int code;
    private final String message;

    private BaseResponseStatus(boolean isSuccess, int code, String message) {
        this.isSuccess = isSuccess;
        this.code = code;
        this.message = message;
    }
    
    SUCCESS(true, 100, "요청에 성공하였습니다.")
	
    USER_EMPTY_NICKNAME(false, 400, "닉네임을 입력해주세요")
}

만약 nickname을 입력 받지 못한다면

- 해당 에러 코드는 요청에 실패했을 때 뜨는 것임을 명시하는 isSuccess에 false

- 에러 코드 400

- "닉네임을 입력해주세요" 라는 메세지

 

이렇게 하나의 에러 코드 타입을 정의했다. SUCCESS는 어떤 요청이든 성공했을 때 반환할 타입이다.

 

 

에러 코드 타입을 정의했다면 실제로 요청에 대한 에러가 발생했을 때 반환할 객체를 만들어야 한다.

@JsonPropertyOrder({"isSuccess", "code", "message", "result"})
public class Response<T> {
    @JsonProperty("isSuccess")
    private final Boolean isSuccess;
    private final String message;
    private final int code;
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T result;

    // 요청에 성공한 경우
    public Response(T result) {
        this.isSuccess = SUCCESS.isSuccess();
        this.message = SUCCESS.getMessage();
        this.code = SUCCESS.getCode();
        this.result = result;
    }

    // 요청에 실패한 경우
    public Response(ResponseStatus status) {
        this.isSuccess = status.isSuccess();
        this.message = status.getMessage();
        this.code = status.getCode();
    }
}

요청이 성공할 경우

- 성공할 경우 반환하는 모든 요청에서 에러 코드 타입이 똑같기 때문에 SUCCESS 타입에서 반환할 정보들을 가져옴

- 제너릭 타입을 이용하여 api코드에서 반환할 객체를 받아옴 T

 

예를 들어 유저 조회에 성공한다면 user 객체를 T에 받아와 리턴한다. 요청마다 반환할 객체가 다르기 때문에 (유저 말고 다른 객체를 조회하고 반환할 때) 제너릭 타입으로 설정한다.

 

실패할 경우

- api에서 위에서 설정한 에러코드를 넘겨받음

- 받아온 에러코드 타입으로 반환할 정보들을 설정

 

 

이제 api에서 만약 내가 예측한 에러가 발생했을 때 각 Response 객체를 생성하고

성공시 T에 반환할 객체를, 실패시 해당 에러 코드 타입을 반환하면 된다.

 

 

api는 다음과 같다.

@ResponseBody
  	@GetMapping("")
    public Response<GetUserRes> getUsers(@RequestParam(required = true) String nickname) {
        try{
            if(userNickname.length()==0){
                return new Response<>(USERS_EMPTY_NICKNAME);
            }
            GetUserRes getUsersRes = userProvider.getUsersByNickName(nickname);
            return new Response<>(getUsersRes);
        } catch(myException exception){
            return new Response<>((exception.getStatus()));
        }
    }

닉네임을 입력 받지 못했을 때

- 맨 처음 정의한 USERS_EMPTY_NICKNAME을 넘겨주어 response 객체를 생성하고 반환한다. 

 

 

성공 시

- provider에서 유저 객체를 가져와 reponse객체를 생성하고 반환한다.

 

 

만약 내가 설정한 에러 코드가 아닌 에러가 발생했을 때

- catch문으로 exeption에 담긴 정보를 response에 넘겨주면서 반환한다. 

물론 exeption을 반환하는 객체도 만들어 줘야 한다. 기존 exception 클래스에서 getStatus 가능

public class myException extends Exception {
    private ResponseStatus status;
}

 

모든 api에 대한 에러 코드 타입과 그 타입을 반환할 response 클래스를 작성하면,

API 코드에서 내가 원하는 에러 상황에 적합한 객체를 반환하는 코드를 간결하게 작성할 수 있다.