🛡️ 검증(Validation)이란?
- 클라이언트가 보낸 데이터가 유효한지 검증하는 과정
→ 잘못된 데이터로 인해 시스템에 오류가 발생하는 것을 방지
🍽️ 비유: 식당 주문 시스템
📌 Validation을 사용하는 이유
| 이유 | 설명 |
|---|---|
| 안정성 확보 | 잘못된 데이터로 인한 시스템 오류 방지 |
| UX 향상 | 유저에게 정확한 피드백 제공 |
| 데이터 무결성 유지 | 올바른 데이터만 처리하게 함 |
💻 Validation의 역할
🔍 Validation의 종류
| 구분 | 특징 | 예시 |
|---|---|---|
| 프론트엔드 검증 | JS, HTML 등에서 즉각 피드백 | 비밀번호 특수문자 경고 등 |
| 서버 검증 | Spring Controller 등에서 체크 | 필수값, 범위 등 |
| DB 검증 | Not Null, Unique 제약조건 등 | 최종 방어선 |
→ 💡 모든 계층에서 검증이 필요하며, 특히 서버 검증은 선택이 아닌 필수
📑 BindingResult란?
- Spring이 제공하는 검증 오류를 담는 객체
Errors인터페이스 확장FieldError,ObjectError정보 저장- 기본 구현체:
BeanPropertyBindingResult
⚙️ 동작 방식
| 상황 | 결과 |
|---|---|
BindingResult 없음 | 파라미터 바인딩 실패 시 400 오류, Controller 호출 안됨 |
BindingResult 있음 | 오류가 객체에 담기고, Controller 정상 호출됨 |
❗ BindingResult는 반드시 검증 대상 파라미터 바로 뒤에 위치해야 함
💥 파라미터에 BindingResult가 없는 경우
@Data
public class MemberCreateRequestDto {
private Long point;
private String name;
private Integer age;
}
// View 반환
@Controller
public class BingdingResultController {
@PostMapping("/v1/member")
public String createMemberV1(@ModelAttribute MemberCreateRequestDto request, Model model) {
// Model에 저장
System.out.println("/V1/member API가 호출되었습니다.");
model.addAttribute("point", request.getPoint());
model.addAttribute("name", request.getName());
model.addAttribute("age", request.getAge());
// Thymeleaf Template Engine View Name
return "complete";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Member 생성이 완료되었습니다!</h1>
<ul>
<li><span th:text="${point}">포인트</span></li>
<li><span th:text="${name}">이름</span></li>
<li><span th:text="${age}">나이</span></li>
</ul>
</body>
</html>
→ 컨트롤러 호출조차 안 됨
→ 사용자는 갑작스러운 Error 페이지를 보게 됨
✅ 파라미터에 BindingResult가 있는 경우
@Controller
public class BindingResultController {
@PostMapping("/v2/member")
public String createMemberV2(
// 1. @ModelAttribute 뒤에 2. BindingResult가 위치한다.
@ModelAttribute MemberCreateRequestDto request,
BindingResult bindingResult,
Model model
) {
System.out.println("/V2/member API가 호출되었습니다.");
// BindingResult의 에러 출력
List<ObjectError> allErrors = bindingResult.getAllErrors();
System.out.println("allErrors = " + allErrors);
// Model에 저장
model.addAttribute("point", request.getPoint());
model.addAttribute("name", request.getName());
model.addAttribute("age", request.getAge());
return "complete";
}
}
→ 잘못된 값만 오류로 처리하고 나머지 필드는 정상적으로 바인딩
→ 에러 메시지와 함께 유저에게 피드백 제공 가능
📌 정리 요약
| 항목 | 설명 |
|---|---|
BindingResult | 검증 실패 시 오류 정보 저장 객체 |
| 위치 | @ModelAttribute 또는 @Valid 바로 뒤 |
| 사용 이유 | 컨트롤러 진입 차단 없이 에러 처리 가능 |
| 예외 상황 | 필드명 오류, 타입 불일치, 누락된 필드 등 |
📋 실전 Validation 전략
| 계층 | 역할 | 예시 |
|---|---|---|
| 프론트 | UX 개선, 빠른 피드백 | JS 알림창 등 |
| 서버 (Spring) | 핵심 검증 로직 | @Valid + BindingResult |
| DB | 최종 방어선 | Not Null, Unique 등 제약조건 |