java | spring boot | BindingResult 정리.

Create by.ChatGPT

예시 코드

@RequestMapping("getDemo")
public String main(@ModelAttribute Dummy data, BindingResult result) {
    ...
}

이 메서드에서 핵심은 @ModelAttribute Dummy dataBindingResult result의 관계입니다.


1️⃣ @ModelAttribute가 하는 일

@ModelAttribute Dummy data

이 한 줄이 의미하는 것은:

  1. 요청 파라미터를 읽는다
  2. Dummy 객체를 생성한다
  3. 요청 파라미터(String)를 Dummy 필드에 바인딩한다
  4. 타입 변환 + 검증이 수행된다

이 모든 작업을 WebDataBinder가 수행합니다.


2️⃣ BindingResult가 하는 일

BindingResult result

BindingResult는 다음 정보를 담습니다.

  • 데이터 바인딩 중 발생한 오류
  • 타입 변환 실패 정보
  • 검증(@Valid, @Validated) 실패 정보

즉,

@ModelAttribute Dummy를 만들면서 발생한 모든 문제를 담는 결과 객체

입니다.


3️⃣ BindingResult를 “넣은 경우”

코드

@RequestMapping("getDemo")
public String main(@ModelAttribute Dummy data, BindingResult result) {

    if (result.hasErrors()) {
        return "error";
    }

    return "ok";
}

실행 흐름

  1. 요청 도착
  2. DispatcherServlet → HandlerAdapter
  3. WebDataBinder 생성
  4. 요청 파라미터 → Dummy 객체 바인딩
  5. 타입 변환 / 검증 수행
  6. ❗ 오류 발생
  7. 오류를 BindingResult에 저장
  8. 컨트롤러 메서드 정상 진입 ✅
  9. 개발자가 오류를 직접 처리 가능

핵심 포인트

  • 오류가 있어도 예외 발생 ❌
  • 컨트롤러가 항상 호출됨
  • 폼 재출력, 사용자 메시지 처리 가능

4️⃣ BindingResult를 “안 넣은 경우”

코드

@RequestMapping("getDemo")
public String main(@ModelAttribute Dummy data) {
    return "ok";
}

실행 흐름

  1. 요청 도착
  2. WebDataBinder가 Dummy 객체 생성 시도
  3. 타입 변환 / 검증 중 오류 발생
  4. ❗ 오류를 담을 BindingResult가 없음
  5. Spring이 예외를 즉시 발생
  6. 컨트롤러 메서드 진입 실패 ❌

대표적인 예외

  • BindException
  • MethodArgumentNotValidException

5️⃣ 왜 BindingResult를 바로 뒤에 써야 할까?

@ModelAttribute Dummy data, BindingResult result   // O

Spring 규칙:

BindingResult는 자신이 처리할 대상 바로 뒤에 와야 한다

잘못된 예

@ModelAttribute Dummy data, String type, BindingResult result

이 경우:

  • Spring이 result를 data와 연결하지 못함
  • BindingResult 동작 ❌
  • 예외 발생

6️⃣ 실제 예로 보면 더 명확

요청

/getDemo?age=abc

Dummy 클래스

public class Dummy {
    private int age;
}

✔ BindingResult 있음

public String main(@ModelAttribute Dummy data, BindingResult result)
  • age 변환 실패
  • result.hasErrors() → true
  • 컨트롤러 정상 진입
  • 에러 페이지로 분기 가능

❌ BindingResult 없음

public String main(@ModelAttribute Dummy data)
  • age 변환 실패
  • 예외 발생
  • 컨트롤러 실행 ❌

7️⃣ 한 줄로 정리하면

구분BindingResult 있음BindingResult 없음
타입 변환 오류result에 저장즉시 예외
검증 오류result에 저장즉시 예외
컨트롤러 실행OX
오류 제어가능불가능

8️⃣ 핵심 요약 (암기용)

  • @ModelAttribute → 객체 생성 + 바인딩
  • WebDataBinder → 실제 작업 주체
  • BindingResult → 바인딩/검증 결과 저장소
  • BindingResult를 선언하면 예외 대신 흐름 제어
  • 선언하지 않으면 Spring이 예외 처리

마지막 한 문장

BindingResult는 오류를 숨기는 장치가 아니라,
오류를 “내가 처리할 수 있게” 넘겨주는 장치다.