본문 바로가기
SpringBoot/서비스 계층 및 비즈니스 로직

유효성 검사와 예외 처리

by DEVLIB 2025. 4. 15.
728x90

유효성 검사 (Validation)

DTO 클래스에 유효성 조건 추가

public class MemberDto {

    @NotBlank(message = "이름은 필수입니다.")
    private String name;

    @Email(message = "유효한 이메일 형식이어야 합니다.")
    private String email;

    @Min(value = 10, message = "나이는 10세 이상이어야 합니다.")
    private int age;

    // getter/setter 생략
}

Java Bean Validation(표준) 기반이며, javax.validation.constraints 혹은 jakarta.validation.constraints 패키지를 사용합니다.


컨트롤러에서 유효성 검사 적용

@RestController
@RequiredArgsConstructor
public class MemberController {

    private final MemberService memberService;

    @PostMapping("/members")
    public ResponseEntity<?> register(@Valid @RequestBody MemberDto dto, BindingResult result) {
        if (result.hasErrors()) {
            String errorMessage = result.getFieldError().getDefaultMessage();
            return ResponseEntity.badRequest().body(errorMessage);
        }

        memberService.register(dto);
        return ResponseEntity.ok("등록 완료");
    }
}

@Valid와 BindingResult를 함께 사용하면 검증 실패 시 직접 처리 가능


자주 쓰는 유효성 애너테이션

애너테이션 설명
@NotNull null 허용 안 함
@NotBlank 공백 허용 안 함 (String)
@Size(min=, max=) 문자열 길이 제한
@Min, @Max 숫자 범위 제한
@Email 이메일 형식 확인
@Pattern 정규표현식 적용

예외 처리 (Exception Handling)

컨트롤러 개별 처리 (간단한 방법)

@PostMapping("/members")
public ResponseEntity<?> register(@Valid @RequestBody MemberDto dto) {
    try {
        memberService.register(dto);
        return ResponseEntity.ok("등록 성공");
    } catch (DuplicateEmailException e) {
        return ResponseEntity.badRequest().body(e.getMessage());
    }
}

@ControllerAdvice 전역 예외 처리

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<?> handleValidationException(MethodArgumentNotValidException ex) {
        String error = ex.getBindingResult().getFieldError().getDefaultMessage();
        return ResponseEntity.badRequest().body(error);
    }

    @ExceptionHandler(DuplicateEmailException.class)
    public ResponseEntity<?> handleDuplicateException(DuplicateEmailException ex) {
        return ResponseEntity.status(HttpStatus.CONFLICT).body(ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> handleAll(Exception ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("서버 오류 발생");
    }
}

@RestControllerAdvice는 모든 컨트롤러에서 발생하는 예외를 공통으로 처리합니다.


사용자 정의 예외 클래스 만들기

public class DuplicateEmailException extends RuntimeException {
    public DuplicateEmailException(String message) {
        super(message);
    }
}

 

비즈니스 로직에 맞는 커스텀 예외 클래스를 만들어 throw new DuplicateEmailException(...)처럼 사용할 수 있습니다.


마무리 요약

항목 설명
유효성 검사 DTO 클래스에 제약 조건을 선언 (@Valid, @NotBlank, @Email 등)
검증 실패 응답 BindingResult로 직접 처리하거나, 예외로 던져 @ControllerAdvice에서 처리
예외 처리 개별 처리도 가능하지만 전역 예외 처리가 더 깔끔하고 실무적
커스텀 예외 비즈니스 로직에 맞는 예외 클래스를 직접 정의하여 활용

실무용 유효성 & 예외 응답 포맷 예시

{
  "status": 400,
  "message": "이름은 필수입니다.",
  "timestamp": "2025-04-13T12:00:00"
}

JSON 형태의 에러 응답도 전역 처리기에서 구조화할 수 있어요.

LIST