Search

23. 스프링부트 포토그램 인증 회원가입 글로벌 예외 처리하기

포토그램 인증 구현하기

회원가입 구현

컨트롤어드바이스에 대해서 진행
AuthController.java
@ResponseBody를 지워주면 리턴이 파일로 리턴되게 수정해준다
기존에 오류나면 리턴되게 해놨는데 익셉션이 떨어지게 변경해줄거다.
//회원가입버튼 -> /auth/signup/ -> /auth/signin @PostMapping("/auth/signup") public String signup(@Valid SignupDto signupDto, BindingResult bindingResult ) { //key=value (x-www-form-urlencoded) //에러가 존재한다 if(bindingResult.hasErrors()) { Map<String, String> errorMap = new HashMap<>(); for(FieldError error :bindingResult.getFieldErrors()) { errorMap.put(error.getField(), error.getDefaultMessage()); } throw new RuntimeException("유효성 검사 실패함"); }else { //log.info(signupDto.toString()); //User <- SignupDto User user = signupDto.toEntity(); //log.info(user.toString()); User userEntity = authService.회원가입(user); System.out.println(userEntity); return "auth/signin"; } }
Java
복사
작성 후에 오류나게 진행해보자
유효성 검사 실패함이라는 오류메세지가 뜬다.
근데 오류가 났을 때 사용자페이지에 이렇게 오류메시지를 보여주는건 좋은 UX는 아니다..
그래서 중간에 익셉션이 터진걸 가로챌거다
handler 패키지 생성
ControllerExceptionHandler.java 생성
모든 익셉션을 낚아챌려면
package com.cos.photogramstart.handler; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.RestController; @RestController // 응답리턴을 위해서 @ControllerAdvice //모든 익셉션을 낚아채기 위해서 public class ControllerExceptionHandler { }
Java
복사
@ControllerAdvice를 쓰면 모든 익셉션을 다 낚아챈다
@ExceptionHandler(RuntimeException.class) public String validationException() { }
Java
복사
RuntimeException.class 추가하면 RuntimeException 관련해서 모든 익셉션을
validationException 함수가 감지할거다.
@ExceptionHandler(RuntimeException.class) public String validationException(RuntimeException e) { return e.getMessage(); }
Java
복사
@RestController이라서 메세지로 데이터를 리턴하게 된다.
다시 회원가입을 진행해보자.
아까 오류메세지로 가득한 화면보다 훨씬 보기 좋아졌다.
헨들러를 통해서 런타임익셉션(AuthController.java의 signup함수의 오류)이 나면 ControllerExceptionHandler.java에서 @RestController를 통해서 데이터가 메세지로 전달되기때문에 저렇게 메시지로만 화면이 뜬거다.
근데 문제는 오류메시지를 “유효성검사 실패함” 이라는 메세지를 리턴하는게 아니라 hashMap에 담긴 오류메시지를 리턴하고 싶다.
근데 이걸 못하는 이유가
RuntimeException이 String만 받기 때문이다.
이걸 해결하기 위해서 handler 패키지에 ex 패키지를 생성해주자.
ex 패키지 안에 CustomValidationException.java 생성
package com.cos.photogramstart.handler.ex; public class CustomValidationException extends RuntimeException { }
Java
복사
익셉션이 될려면 RuntimeException을 상속받으면 된다.
public class CustomValidationException extends RuntimeException { private static final long serialVersionUID = 1L; }
Java
복사
CustomValidationException 부분에 노랑색 밑줄친 부분을 갖대되고 시리얼 생성
package com.cos.photogramstart.handler.ex; import java.util.Map; public class CustomValidationException extends RuntimeException { //객체를 구분할 때 !! (jvm에게 중요) private static final long serialVersionUID = 1L; private String message; private Map<String, String> errorMap; public CustomValidationException(String message, Map<String, String> errorMap) { this.message = message; this.errorMap = errorMap; } }
Java
복사
생성자를 만들어줘서 받게 해주자.
public Map<String, String> getErrorMap(){ return errorMap; }
Java
복사
getter도 생성
message에 대한 getter를 굳이 안 만드는 이유는
아까전에 RuntimeException에서 “유효성 검사 실패함” 이라는 메세지를 던져주면서
RuntimeException이 super를 통해 부모에게 메세지를 던져준다. 타고 타고 가면
detailMessage 실행되는 프로세스인데
그래서 그냥 getter를 만들어주지 않고 부모에게 던져주자.
public CustomValidationException(String message, Map<String, String> errorMap) { super(message); this.message = message; this.errorMap = errorMap; }
Java
복사
어차피 부모에게 던질거라서 message 선언 부분과 this 부분은 지워버렸다.
package com.cos.photogramstart.handler.ex; import java.util.Map; public class CustomValidationException extends RuntimeException { //객체를 구분할 때 !! (jvm에게 중요) private static final long serialVersionUID = 1L; private Map<String, String> errorMap; public CustomValidationException(String message, Map<String, String> errorMap) { super(message); this.errorMap = errorMap; } public Map<String, String> getErrorMap(){ return errorMap; } }
Java
복사
그러면 나만의 커스텀 익셉션 헨들러가 만들어졌다.
ControllerExceptionHandler.java로 돌아와서
RuntimeException.class가 아니라 CustomValidationException.class로 변경해주자
@ExceptionHandler(CustomValidationException.class) public String validationException(CustomValidationException e) { return e.getMessage(); }
Java
복사
그리고 리턴을 errorMap으로 리턴해주면서 리턴타입도 같이 변경
@ExceptionHandler(CustomValidationException.class) public Map<String, String> validationException(CustomValidationException e) { return e.getErrorMap(); }
Java
복사
그러면 이제 AuthController.java에서 signup함수에서 해당 오류를
throw new CustomValidationException("유효성 검사 실패함", errorMap);
Java
복사
으로 수정해주면 된다.
다시 회원가입 오류내면은
엄청 깔끔하게 리턴이 된다.

*참고