제 코드 및 다른 팀원들의 코드를 내맘대로 리뷰하는 중 여러 Handler를 사용하면 코드가 더 깔끔하고 유지보수가 편해질 것 같아 상의도 없이 만들고 PR날린 그것,
ErrorHandler, Validator
기존 코드를 봅시다
@Service@RequiredArgsConstructorpublicclassBattleServiceImplimplementsBattleService{
//생략@OverridepublicvoidregistBattle(BattleInviteRequest battleInviteRequest, User user){
//생략if (battleInviteRequest.getOppositeUserId() == user.getId()) {
thrownew IllegalArgumentException("Not valid user");
}
if (battleInviteRequest.getTime() <= 0) {
thrownew RuntimeException("Wrong time setting");
}
아...
진짜 아... 싶죠? 분명 던지는 에러들이 서버 상 오류가아닌 비지니스로직 적 이루어질 수 있는 에러인데, 저렇게 서비스단에 2~3줄 심지어 if문으로 메서드 안에 넣으면...... 나중에 혹시라도 수정하게되거나 로직을 변경해야 되는 일이 생겼을 시 굉장히 귀찮아지겠죠?ㅎㅎ....
여기서 제가 생각해낸 방법은
1. 체크해야되는 조건들을 하나의 파일로 묶는다.
2. 오류 결과들을 하나의 파일에 정리한다
3. 던진다!
의 과정입니다.
먼저, 저 말도안되는 Not a valid user과 Wrong time setting을 과감히 지우고, "ErrorCode"의 Enum을 만들었습니다.
@Getter@AllArgsConstructorpublicenumErrorCode{
INVALID_BATTLE_TIME("최소 10분부터 최대 60분까지 설정 가능합니다."),
INVALID_USER("유저 설정이 유효하지 않습니다."),
INVALID_BATTLE_STARTTIME("시작 시간은 최소 60분 후부터 가능합니다."),
INVALID_OPINION_LENGTH("선택지는 최대 16자까지 작성 가능합니다."),
DUPLICATED_BATTLE("이미 해당시간에 예정된 배틀이 존재합니다."),
ENDED_BATTLE("응답 기간이 종료된 배틀입니다.");
privatefinal String message;
}
public classCustomExceptionextendsRuntimeException{
privatefinalErrorCode errorCode;
public CustomException(ErrorCode errorCode) {
super(errorCode.name());
this.errorCode = errorCode;
}
public ErrorCode getErrorCode() {
return errorCode;
}
}
그리고, 저 errorcode를 throw할 수 있는 custom exception을 정의해줍니다.
여기서 잠깐! RuntimeException을 extends하는 이유! 왜 하필 많은 오류 중 Runtime exception일까! 저는 굉장히 궁금했습니다. 사실 이름만 보면 그냥 Exception이 더 일반적으로 보이는데 쓰면 계속 throw를 하래잖아요! 그래서 패트병 대신 텀블러로 커피를 1회 마시고 GPT선생님께 여쭈어봤죠.
역시 우리으 친절하신 즤선생님,,
RuntimeException과 IllegalArgumentException과 같이 평소에 우리가 사용해도 try-catch 등을 쓰지 않아도 되는 Exception들은 Unchecked Exception이라고 합니다! 그에 반해, 일반 Exception은 Checked Exception이라고 try-catch나 throws를 해야된다고 하네요.
그래서 아무튼 Exception이 아닌 것들 중 가장 무난한 RuntimeException을 채택하였습니다.
그 후 원래 제가 만들어놨던 GlobalExceptionHandler 안에 제 작고 소중한 CustomException도 추가해줬어요...><