Create by.ChatGPT
예시 코드
@RequestMapping("getDemo")
public String main(@ModelAttribute Dummy data, BindingResult result) {
...
}
이 메서드에서 핵심은 @ModelAttribute Dummy data와 BindingResult result의 관계입니다.
1️⃣ @ModelAttribute가 하는 일
@ModelAttribute Dummy data
이 한 줄이 의미하는 것은:
- 요청 파라미터를 읽는다
Dummy객체를 생성한다- 요청 파라미터(String)를
Dummy필드에 바인딩한다 - 타입 변환 + 검증이 수행된다
이 모든 작업을 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";
}
실행 흐름
- 요청 도착
- DispatcherServlet → HandlerAdapter
- WebDataBinder 생성
- 요청 파라미터 → Dummy 객체 바인딩
- 타입 변환 / 검증 수행
- ❗ 오류 발생
- 오류를 BindingResult에 저장
- 컨트롤러 메서드 정상 진입 ✅
- 개발자가 오류를 직접 처리 가능
핵심 포인트
- 오류가 있어도 예외 발생 ❌
- 컨트롤러가 항상 호출됨
- 폼 재출력, 사용자 메시지 처리 가능
4️⃣ BindingResult를 “안 넣은 경우”
코드
@RequestMapping("getDemo")
public String main(@ModelAttribute Dummy data) {
return "ok";
}
실행 흐름
- 요청 도착
- WebDataBinder가 Dummy 객체 생성 시도
- 타입 변환 / 검증 중 오류 발생
- ❗ 오류를 담을 BindingResult가 없음
- Spring이 예외를 즉시 발생
- 컨트롤러 메서드 진입 실패 ❌
대표적인 예외
BindExceptionMethodArgumentNotValidException
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에 저장 | 즉시 예외 |
| 컨트롤러 실행 | O | X |
| 오류 제어 | 가능 | 불가능 |
8️⃣ 핵심 요약 (암기용)
@ModelAttribute→ 객체 생성 + 바인딩- WebDataBinder → 실제 작업 주체
- BindingResult → 바인딩/검증 결과 저장소
- BindingResult를 선언하면 예외 대신 흐름 제어
- 선언하지 않으면 Spring이 예외 처리
마지막 한 문장
BindingResult는 오류를 숨기는 장치가 아니라,
오류를 “내가 처리할 수 있게” 넘겨주는 장치다.