Chef.Yeon
Code Cook
Chef.Yeon
전체 방문자
오늘
어제
  • 분류 전체보기 (230)
    • 게임 개발 (1)
      • Unity (1)
    • Android (27)
      • Kotlin (19)
      • 우아한테크코스 5기 (4)
    • Language (11)
      • 파이썬 (3)
      • Java (7)
    • DB (2)
      • SQL (16)
    • Spring (25)
    • 코딩테스트 (56)
    • Git (1)
    • TIL (85)
    • DevOps (6)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 프로그래머스
  • elasticsearch
  • 우아한테크코스
  • webflux
  • 내림차순
  • enum
  • MariaDB
  • ec2
  • kibana
  • 코틀린 인 액션
  • SQL
  • til
  • grafana
  • 에라토스테네스의 체
  • 코딩테스트
  • spring
  • rsocket
  • Docker
  • 코틀린
  • 다이나믹 프로그래밍
  • 안드로이드
  • 프리코스
  • Android
  • 레포지토리
  • java
  • 백준
  • 문자열
  • Wil
  • 파이썬
  • kotlin

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Chef.Yeon

Code Cook

Spring

[Spring] @Valid @ControllerAdvice와 @ExceptionHandler 사용한 전역 예외 처리

2023. 4. 25. 00:44

@ControllerAdvice

@ControllerAdvice란 Controller 계층 전역에서 발생하는 에러를 잡아 처리해주는 애노테이션이다.

 

@ExceptionHandler

@ExceptionHandler는 Controller로 등록된 빈에서 발생하는 에러를 메서드에서 처리해주는 애노테이션이다.

 

구성

MemberController

@RestController
@RequestMapping("member")
@RequiredArgsConstructor
public class MemberController {

    private final MemberService memberService;

    @PostMapping("/signup")
    public ResponseEntity signup(@Valid @RequestBody SignupRequestDto signupRequestDto) {
        return memberService.signup(signupRequestDto);
    }
}

 

SignupRequestDto

@Getter
@Setter
public class SignupRequestDto {

    @NotBlank
    @Size(min = 4, max = 10)
    @Pattern(regexp = "^[a-z0-9]*$")
    private String userId;

    @NotBlank
    @Size(min = 8, max = 15)
    @Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,15}")
    private String password;
}

 

Member

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String userId;
    @Column(nullable = false)
    private String password;

    public Member(SignupRequestDto requestDto) {
        this.userId = requestDto.getUserId();
        this.password= requestDto.getPassword();
    }
}

 

MemberRepository

public interface MemberRepository extends JpaRepository<Member, Long> {
}

 

MemberService

@Service
@RequiredArgsConstructor
public class MemberService {

    private final MemberRepository memberRepository;
    /**
     * 회원가입
     */
    public ResponseEntity signup(SignupRequestDto requestDto) {
        Member member = new Member(requestDto);
        memberRepository.save(member);
        return new ResponseEntity(member, HttpStatus.OK);
    }
}

 

@ControllerAdvice, @ExceptionHandler 예외처리

@Valid 를 통해 유효성 검사를 할 때, 유효하지 않은 경우 MethodArgumentNotValidException 에러가 발생한다.

@ControllerAdvice 애노테이션을 통해 모든 Controller 에서 예외를 찾고, @ExceptionHandler와 함께 캐치할 에러를 작성하여 예외처리가 가능하다.

 

예외처리를 적용하기 전 PostMan으로 테스트해보면 다음과 같은 결과가 나온다.

콘솔창에는 다음과 같이 뜬다.

Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.example.sample.controller.MemberController.signup(com.example.sample.dto.SignupRequestDto) with 2 errors: [Field error in object 'signupRequestDto' on field 'password': rejected value [1234]; codes [Pattern.signupRequestDto.password,Pattern.password,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signupRequestDto.password,password]; arguments []; default message [password],[Ljakarta.validation.constraints.Pattern$Flag;@4ccb9e30,(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\W)(?=\S+$).{8,15}]; default message ["(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\W)(?=\S+$).{8,15}"와 일치해야 합니다]] [Field error in object 'signupRequestDto' on field 'password': rejected value [1234]; codes [Size.signupRequestDto.password,Size.password,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signupRequestDto.password,password]; arguments []; default message [password],15,8]; default message [크기가 8에서 15 사이여야 합니다]] ]

 

@ControllerAdvice와 @ExceptionHandler를 적용해보고 다시 결과를 확인해보자.

 

ExceptionAdvice

@ControllerAdvice
public class ExceptionAdvice {
    /**
     * 회원가입 Valid 예외
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String signValidException(MethodArgumentNotValidException exception) {
        BindingResult bindingResult = exception.getBindingResult();

        StringBuilder builder = new StringBuilder();

        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            builder.append("[");
            builder.append(fieldError.getField());
            builder.append("](은)는 ");
            builder.append(fieldError.getDefaultMessage() + "\n");
        }

        return builder.toString();
    }
}

 

해당 과정을 한 번 살펴보자.

 

@Valid에서 MethodArgumentNotValidException 에러가 발생하면 해당 메서드로 진입한다.

BindingResult 객체에는 해당 에러에 대한 여러 정보가 담겨있다. BindingResult 객체 안에는 FieldErrors라는 리스트가 있는데, 이 리스트에는 에러와 관련한 정보가 담긴 FieldError 객체가 들어있다. 

반복문을 통해 각각의 FieldError 객체 안에 담긴 에러가 발생한 필드명, 메시지를 가져와 반환한다.

 

FieldError에  담기는 정보는 다음과 같다.

public class FieldError extends ObjectError {

	private final String field;

	@Nullable
	private final Object rejectedValue;

	private final boolean bindingFailure;
	
    /* ... */
}

field: 예외가 발생한 field

RejectedValue: 어떤 값으로 인해 예외가 발생했는가

DefaultMessage: 예외가 발생했을 때 제공할 메세지

 

PostMan을 통해 결과를 확인하면 다음과 같이 예외처리가 된 것을 확인할 수 있다.

728x90

'Spring' 카테고리의 다른 글

[Spring] AWS RDS MariaDB + Spring Boot, Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8mb4_unicode_ci,COERCIBLE) for operation '=' 해결  (0) 2023.05.08
[Spring] @Valid 메시지 message properties 사용하기, 한글 깨짐 해결  (0) 2023.04.27
[Spring] @Valid를 사용한 객체 유효성 검증  (0) 2023.04.22
[Spring] Spring profiles 통한 DB/개인정보 .gitignore에 추가하기  (0) 2023.04.11
[Spring] SpringBoot 프로젝트에서 MariaDB 사용하기, 간단한 테스트  (0) 2023.04.04
    'Spring' 카테고리의 다른 글
    • [Spring] AWS RDS MariaDB + Spring Boot, Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8mb4_unicode_ci,COERCIBLE) for operation '=' 해결
    • [Spring] @Valid 메시지 message properties 사용하기, 한글 깨짐 해결
    • [Spring] @Valid를 사용한 객체 유효성 검증
    • [Spring] Spring profiles 통한 DB/개인정보 .gitignore에 추가하기
    Chef.Yeon
    Chef.Yeon
    보기 좋고 깔끔한 코드를 요리하기 위해 노력하고 있습니다.

    티스토리툴바