본문 바로가기
Spring/Spring

Interface로 추상화하여 Enum 사용

by 델버 2023. 1. 11.
  • @ExceptionHandler를 사용하여 예외 처리를 하고 클라이언트에게 ResponseEntity를 사용하여 보여줄 정보만 보내려고 한다. 이때 ExceptionResponse라는 것을 만들어서 이곳에 커스텀 Exception으로 만든 enum을 넘겨주려고 했다. 이 ExceptionResponse를 다른 곳에서 재사용하고 싶어 enum을 추상화하여 만들게 된 계기다.
  • 코드 - https://github.com/delvering17/toy_board

 

  • 로그인 요청을 받는데 정보가 없는 사용자이거나 비밀번호가 맞지 않을 때의 exception을 처리할 ExceptionHandler이다.
@ExceptionHandler(LoginException.class)
public ResponseEntity<ExceptionResponse> loginExHandle(LoginException e, Model model) {
    log.error("[loginExHandle] ex", e);
    ExceptionResponse exceptionResponse = new ExceptionResponse(e.getLoginExceptionCode());

    return ResponseEntity.status(exceptionResponse.getStatus()).body(exceptionResponse);
}
  • LoginExceptoin을 커스텀으로 만들었고 이 안에 LoginExceptionCode라는 enum을 넘겨주어서 처리하도록 했다.
@Getter
public class LoginException extends RuntimeException {

    private final LoginExceptionCode loginExceptionCode;

    public LoginException(LoginExceptionCode loginExceptionCode) {
        super(loginExceptionCode.getMessage());
        this.loginExceptionCode = loginExceptionCode;
    }
}
@Getter
public enum LoginExceptionCode{

    LOGIN_NOTFOUND_MEMBER(HttpStatus.UNAUTHORIZED, "LOGIN_001", "존재하지 않는 회원입니다."),
    LOGIN_PASSWORD_MISMATCH(HttpStatus.BAD_REQUEST, "LOGIN_002", "비밀번호가 맞지 않습니다.");

    private final HttpStatus status;
    private final String code;
    private final String message;

    LoginExceptionCode(HttpStatus status, String code, String message) {
        this.status = status;
        this.code = code;
        this.message = message;
    }

}
  • 하지만 이것을 ExceptionResponse를 하나씩 만들기는 그렇고 다른 컨트롤러에서도 사용하고 싶었다. 저 파라미터를 각 필드를 직접 넘겨주는 것을 하려니 loginExHandle 메서드에서는 이를 무엇을 사용해서 넘기는지 명확해보이지 않았다.
// ExceptionResponse.class
@Getter
public class ExceptionResponse {

    private final HttpStatus status;
    private final String code;
    private final String message;

    public ExceptionResponse(LoginExceptionCode exceptionCode) {
        this.status = exceptionCode.getStatus();
        this.code = exceptionCode.getCode();
        this.message = exceptionCode.getMessage();
    }
}
  • 그래서 ExceptionResponse로 넘길 enum을 interfacef를 사용하여 추상화하려고한다
  • enum은 extends는 불가능하지만 implements는 가능한 것을 이용하려고 한다.

Interface

public interface ExceptionCode {
    HttpStatus getStatus();
    String getCode();
    String getMessage();
}
  • enum 안에서 넘겨줘야 할 메서드들을 적어줬다.

Enum

@Getter
public enum LoginExceptionCode implements ExceptionCode {

    LOGIN_NOTFOUND_MEMBER(HttpStatus.UNAUTHORIZED, "LOGIN_001", "존재하지 않는 회원입니다."),
    LOGIN_PASSWORD_MISMATCH(HttpStatus.BAD_REQUEST, "LOGIN_002", "비밀번호가 맞지 않습니다.");

    private final HttpStatus status;
    private final String code;
    private final String message;

    LoginExceptionCode(HttpStatus status, String code, String message) {
        this.status = status;
        this.code = code;
        this.message = message;
    }
}
  • 만들어준 ExceptionCode를 implements해서 추상화했다. 이후 다른 MemberExceptionCode나 PostExceptionCode를 사용할 때 해당 인터페이스를 받으면 ExceptionResponse 하나로 응답을 넘겨줄 수 있다.

사용

@Getter
public class ExceptionResponse {

    private final HttpStatus status;
    private final String code;
    private final String message;

    public ExceptionResponse(ExceptionCode exceptionCode) {
        this.status = exceptionCode.getStatus();
        this.code = exceptionCode.getCode();
        this.message = exceptionCode.getMessage();
    }
}
  • 이제 파라미터는 ExceptionCode를 사용하여 유연하게 enum을 받을 수 있다.

참고

댓글