Spring Boot

Spring Boot 강좌 06강 — 예외 처리와 입력 검증

🎯 학습 목표

  • @Valid로 요청 데이터를 검증한다.
  • 전역 예외 처리로 일관된 에러 응답을 만든다.
  • 적절한 상태코드를 반환한다.

📖 개념 설명

잘못된 입력을 그대로 두면 DB 오류나 500 에러로 이어집니다. Bean Validation(@NotBlank 등)으로 컨트롤러 진입 시점에 막고, @RestControllerAdvice로 모든 예외를 한 곳에서 처리해 클라이언트에 일관된 JSON 에러를 돌려줍니다.

💻 입력 검증

// 의존성: spring-boot-starter-validation
public record MemoRequest(
    @NotBlank(message = "제목은 필수입니다") String title,
    @Size(max = 1000, message = "본문은 1000자 이하") String body
) {}

@PostMapping
public ResponseEntity create(@Valid @RequestBody MemoRequest req) {
    return ResponseEntity.status(201).body(service.create(req));
}

💻 전역 예외 처리

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 검증 실패 → 400
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity> handleValidation(
            MethodArgumentNotValidException e) {
        Map errors = new HashMap<>();
        e.getBindingResult().getFieldErrors()
         .forEach(fe -> errors.put(fe.getField(), fe.getDefaultMessage()));
        return ResponseEntity.badRequest().body(errors);
    }

    // 없는 자원 → 404
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity> handleNotFound(IllegalArgumentException e) {
        return ResponseEntity.status(404).body(Map.of("error", e.getMessage()));
    }
}

💻 동작

# 제목 없이 요청 → 400 + {"title":"제목은 필수입니다"}
curl -X POST http://localhost:8080/api/memos 
  -H "Content-Type: application/json" -d '{"title":"","body":"x"}'

⚠️ 주의사항

  • 검증을 쓰려면 spring-boot-starter-validation 의존성과 @Valid가 함께 있어야 합니다.
  • 운영에서는 에러 응답에 내부 스택트레이스를 노출하지 마세요.

💡 팁

  • 커스텀 예외(예: NotFoundException)를 만들어 의미를 명확히 하면 처리도 깔끔해집니다.
  • 에러 응답 형식을 표준화(코드/메시지/시각)하면 프런트엔드가 다루기 쉽습니다.