일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 프로그래머스 배열 회전시키기
- 프로그래머스 가위바위보
- 춥고더운우리집
- 주니어개발자
- programmers 배열 회전
- 리트허브 사용법
- 리트허브 오류
- collection python
- 프로그래머스 가위바위보 풀이
- 파이썬 특정 문자 제거하기
- 비지니스 레이어
- 특정문자 제거하기
- Programmers 배열의 유사도
- 2-layered architecture
- 프로그래머스
- 개발자 취준
- BigO notation
- 리트허브 커밋
- leftJoin
- 스프링 시스템 구조
- 프로그래머스 배열의 유사도 파이썬
- 가위바위보 풀이
- 프로그래머스 특정 문자 제거하기
- 춥고 더운 우리 집
- 프레젠테이션 레이어
- 슈츠 자막
- 알고리즘
- 공선옥
- 배열의 유사도 파이썬
- 파이썬 컬렉션
- Today
- Total
기억보다 기록을
[Springboot] aop advice 사용한 exception 처리 (@ControllerAdvice ,@ExceptionHandler, Validation 사용) 본문
[Springboot] aop advice 사용한 exception 처리 (@ControllerAdvice ,@ExceptionHandler, Validation 사용)
juyeong 2023. 2. 22. 18:06MVC 패턴에서 개발자에게 컨트롤러는 데이터를 뿌리는 최종 관문과 같다는 생각이 듭니다. 이 때 컨트롤러는 @Controller와 @RestController 두가지 어노테이션을 사용하여 IoC 할 수 있는데, 리턴타입에 따라 다르게 사용합니다.
파일을 리턴하고 싶다면 컨트롤러, 데이터를 리턴하고 싶다면 레스트 컨트롤러를 사용해요.
좀 더 직관적으로 비유하자면 지금은 스프링부트에서 버린 (...) JSP 파일을 리턴하고 싶다면 컨트롤러 어노테이션을 쓰면 됩니다.
Jsp 파일을 리턴하니까요. 하지만 Json 타입의 데이터를 리턴하려면 @RestController를 사용해야합니다.
요즘은 SPA방식을 선호하여 대부분 레스트풀하게 데이터를 뿌리는 것 같아요.
이 때, 파일타입도 리턴하고 싶고 데이터 타입도 동시에 리턴하고 싶다면 어떻게 해야할까요?
글로벌한 예외처리는 두 개의 다른 리턴 타입을 가능하게 해줘요.
(@Controller에서 데이터를 리턴하고 싶다면 메소드의 리턴타입에 @Resposebody 를 붙이는 방법도 있습니다.)
여기서 글로벌한 예외처리는 @ControllerAdvice + @ExceptionHandler의 조합입니다.
사이드 프로젝트의 회원가입 기능을 작성하던 중 사용자 유효성 검사를 진행했습니다. 이 때 어떻게 예외처리를 했는지 정리한 글입니다.
물론 프론트에서 막는 것이 간단하지 않나? 라고 생각할 수 있지만
만약 누군가 API로 데이터를 직접 쏜다면? 당연히 서버에서도 대책이 있어야합니다.
[문제상황]
회원가입시 20자 이상 작성은 금지되어 있는데, 20자를 초과한 클라이언트가 리퀘스트를 날렸습니다.
그 결과 다음과 같은 에러페이지가 발생합니다.
이런 익셉션 페이지는 사용자 UX 측면에서 좋지 않기에 제이슨 타입으로 에러 메세지를 내리는 것이 가장 깔끔할 것입니다.
익셉션이 발생했을 때 이런 페이지가 나오지 않도록
[해결방법]
[1] 핸들링 해줄 패키지(handler)와 클래스를 작성합니다.
1. CustomValidationException
public class CustomValidationException extends RuntimeException{
private static final long serialVersionUID = 1L;
private String message;
private Map<String,String> errMap;
public CustomValidationException(String message, Map<String,String> errMap) {
super(message);
this.message = message;
this.errMap = errMap;
}
public Map<String, String> getErrMap () {
return errMap;
}
}
에러메시지를 내릴 에러맵을 하나 생성합니다.
2. ControllerExceptionHandler
@RestController
@ControllerAdvice
public class ControllerExceptionHandler {
@ExceptionHandler(CustomValidationException.class)
public Map<String, String> validationException(CustomValidationException e) {
return e.getErrMap();
}
}
[2] 컨트롤러에서 익셉션을 호출합니다.
@PostMapping("/auth/signup")
public String signup (@Valid SignupReqDto signupReqDto, BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
Map<String, String> errMap = new HashMap<>();
for (FieldError err : bindingResult.getFieldErrors()) {
errMap.put(err.getField(),err.getDefaultMessage());
}
throw new CustomValidationException("로그인 유효성검사 실패함", errMap);
} else {
User user = signupReqDto.toEntity();
log.info(user.toString());
authService.signUp(user);
return "auth/signin";
}
Spring Validation의 BindingResult가 hasErrors() 메소드로 에러를 발견하면
선언한 errMap에 메시지를 넣어줍니다. 그 다음 CustomValidationException을 던집니다.
[3] 익셉션을 던지면 CustomValidationException 에서 ControllerExceptionHandler의 errMap을 리턴합니다.
이렇게 Json타입의 데이터가 잘 내려오는 것을 확인할 수 있습니다 😊
'Development > Springboot' 카테고리의 다른 글
[Springboot] spring security BCryptPasswordEncoder "raw password cannot be null" 에러 해결 (0) | 2023.03.23 |
---|---|
[Springboot] Instagram clone (3)Controller, http 4가지 요청 방식 (0) | 2022.07.02 |
[Springboot] Instagram clone (2)프론트 소스와 yml (0) | 2022.07.02 |
[Springboot] Instagram clone (1)개요와 환경설정 (0) | 2022.07.02 |