SQLException 으로 회원가입 중복검사 처리하기
이전 게시물에서 Controller 단에서 요청받은 requestbody 의 유효성을 검증하는 과정을 진행하였습니다.
필드에 어노테이션을 붙여 검증해주는 것이었는데요,
이 때 고려하지 않은 것이 유저이메일과 유저닉네임 중복처리였습니다.
이 두 가지에서 발생하는 에러는 SQLException 이었습니다.
User Entity의 필드에 Unique 설정을 걸어 주었기 때문입니다.
따라서 커스텀 에러를 만들고, 이를 반환하도록 하였습니다.
먼저 SQLException을 상속받는 커스텀 예외 클래스를 만들어줍니다.
public class AlreadyExistEmailException extends SQLException {
private static final String MESSAGE = "이미 등록된 이메일입니다.";
public AlreadyExistEmailException () {
super(MESSAGE);
}
}
public class AlreadyExistNicknameException extends SQLException {
private static final String MESSAGE = "이미 등록된 닉네임입니다.";
public AlreadyExistNicknameException () {
super(MESSAGE);
}
}
그리고 이것을 글로벌 예외 안으로 넣어서 묶어줍니다.
Response 객체를 커스터마이징 하였기 때문에 status 가 중복되고 있네요.
프론트 단에서 보기 편한 형식으로 만들었습니다.
ResponseEntity 에는 status 가 필수 값이라서 함께 넣어주었습니다.
@ControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler (AlreadyExistNicknameException.class)
protected ResponseEntity<Object> handleAlreadyExistNickname(AlreadyExistNicknameException ex) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("statusValue", HttpStatus.BAD_REQUEST.value());
body.put("status", HttpStatus.BAD_REQUEST);
body.put("errors", ex.getMessage());
return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler (AlreadyExistEmailException.class)
protected ResponseEntity<Object> handleAlreadyExistEmail(AlreadyExistEmailException ex) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("statusValue", HttpStatus.BAD_REQUEST.value());
body.put("status", HttpStatus.BAD_REQUEST);
body.put("errors", ex.getMessage());
return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
}
}
이 예외는 controller 가 아닌 service 단에서 처리해줍니다.
두 조건문을 거치면서 예외가 발생할 경우 예외를 만들어서 넘겨주는 구조입니다.
서버가 멈추지 않고, 로그도 잘 찍혀 나옵니다.
public boolean createUser(UserDTO userDto) throws AlreadyExistEmailException, AlreadyExistNicknameException {
String email = userDto.getEmail();
Optional<User> userByEmail = userRepository.findByEmail(email);
String nickname = userDto.getNickname();
Optional<User> userByNickname = userRepository.findByNickname(nickname);
if (userByEmail.isPresent()) {
log.info("user email already exists");
throw new AlreadyExistEmailException();
}
if (userByNickname.isPresent()) {
log.info("user nickname already exists");
throw new AlreadyExistNicknameException();
}
// 통과시 로직
}
추가로 메서드에 예외사항이 명시되어 있는데,
이는 service 메서드뿐 아니라 controller 메서드에도 써주어야 합니다.
throws AlreadyExistEmailException, AlreadyExistNicknameException
해당 메서드를 실행할 때 발생할 수 있는 에러를 작성해 주는 것인데요,
견고한 코드를 만드는데 도움이 됩니다.
참고자료
https://bloowhale.tistory.com/72
[Spring] 올바른 예외처리를 위한 방법
들어가며 먼저 이 글은 자바 진영에서 예외를 어떻게 관리하는지에 대한 기본 개념을 다루지는 않습니다. 이 글에서 다루는 것은 제가 진행 중인 향해 99 스프링 심화 과제에서 나온 다양한 예외
bloowhale.tistory.com