데이터 검증(Validation)
Bean Validation
if(data == null)을 작성하는 대신, 표준화된 Bean Validation을 통해 코드를 깔끔하게 관리할 수 있다.1. if문 대신 애너테이션으로 자동화
과거에는 들어오는 데이터가 유효한지 확인하기 위해 서비스 로직 절반이 검증 코드였다.
하지만 스프링은 애너테이션 하나로 이 과정을 자동화해주는것이다
자주 쓰는 검증 애너테이션
- @NotBlank: null이 아니고, 최소 한 글자 이상의 공백이 아닌 문자가 포함되어야 함.
- @Size(min=x, max=y): 문자열, 컬렉션 등의 크기를 제한함.
- @Email: 이메일 형식인지 검증함.
- @Positive / @Negative: 양수인지 음수인지 확인함.
| 애너테이션 | 의미 | 예시 |
| @NotNull | 값이 null이면 안 됨 | 필수 체크박스 |
| @NotBlank | 공백이나 빈 문자열 금지 | 이름, 아이디 |
| @Min / @Max | 최소/최대 숫자 제한 | 나이(0~150) |
| @Pattern | 정규식을 이용한 정밀 검사 | 전화번호 형식 |
왜 필요 할까? 가장 큰 이유 3가지
1. 데이터 무결성 -> DB에 원하는 적합한 정보의 데이터만 가져올 수 있
2. 보안 -> 이상한 값을 넣어서 서버를 공격 하려는 시도를 1차적으로 차단
3. 사용자 경험 -> 잘못된 입력이라고 친절하게 알려줘서 사용자가 수정을쉽게 하도록 도와줌
2. 실전 적용: @Valid와 @RequestBody
DTO 객체 필드에 검증 규칙을 정의하고, 컨트롤러 파라미터 앞에 @Valid를 붙여주면 끝입니다.
// DTO에서 규칙 정의
public class JoinRequestDto {
@NotBlank(message = "아이디는 필수입니다.")
private String username;
@Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 합니다.")
private String password;
}
// 컨트롤러에서 사용
@PostMapping("/join")
public String join(@Valid @RequestBody JoinRequestDto dto) {
return "회원가입 성공";
}
3. 현업 개발자가 챙겨야 할 3가지 디테일
① Entity와 DTO의 분리
현업에서는 절대로 DB Entity 클래스에 직접 검증 애너테이션을 도배하지 않아야 한다.
화면마다 요구되는 검증 규칙이 다르기 때문에(회원가입 vs 정보수정), 반드시 각 목적에 맞는 DTO를 만들고 그곳에서 검증을 수행합니다.
② @RestControllerAdvice를 통한 전역 예외 처리
검증에 실패하면 MethodArgumentNotValidException이 발생합니다. 이때 서버가 500 에러를 뱉게 두지 않고, 전역 예외 처리기에서 400(Bad Request) 응답과 함께 깔끔한 에러 메시지를 JSON으로 내려줘야 한다.
③ 사용자 정의 애너테이션 (Custom Validator)
"전화번호 형식"이나 "특정 단어 포함 금지" 같은 복잡한 비즈니스 규칙은 직접 애너테이션을 만들어 관리합니다. 코드의 재사용성이 비약적으로 상승합니다.
4. 검증 방식 비교
| 방식 | 장점 | 단점 |
|---|---|---|
| 수동 검증 (if문) | 직관적이고 자유로움 | 코드가 길어지고 가독성 최악 |
| Bean Validation | 가독성 우수, 표준화된 방식 | 복잡한 비즈니스 로직은 한계 |
정리
Validation은 단순히 "데이터가 비었나?"를 체크 유효성 검사와 서버의 안정성과 아키텍처의 깔끔하게 해준다.
Q1. 데이터 검증(Validation)을 프론트엔드와 백엔드 중 어디서 하는 것이 맞을까요?
- 답변: 둘 다 하는 것이 정답입니다.
- 프론트엔드 검증: 사용자에게 즉각적인 피드백을 주어 사용자 경험(UX)을 향상시키고, 잘못된 요청이 서버로 가는 것을 1차적으로 차단해 서버 부하를 줄입니다.
- 백엔드 검증: 프론트엔드 검증은 보안에 취약(Postman 등으로 우회 가능)하므로, 최종 방어선으로서 서버에서 반드시 한 번 더 검증해야 데이터 무결성을 보장할 수 있습니다.
Q2. @Valid와 @Validated의 차이점을 설명해 주세요.
- 답변: | 구분 | @Valid | @Validated | 패키지 | jakarta.validation (자바 표준) | org.springframework (스프링 전용) | | 위치 | 컨트롤러의 메서드 파라미터 등 | 클래스 레벨 또는 메서드 파라미터 | | 특징 | 기본적인 객체 검증 수행 | 그룹 검증(Group Validation) 기능 제공 | | 사용처 | 일반적인 DTO 검증 | 특정 상황(회원가입/수정)마다 다른 검증이 필요할 때 |
Q3. Entity가 아닌 DTO에 검증 로직을 넣어야 하는 이유는 무엇인가요?
- 답변: 계층 간의 역할 분리(Separation of Concerns) 때문입니다.
- Entity는 DB와 매핑되는 핵심 도메인 모델이므로, 화면 종속적인 검증 로직이 섞이면 코드가 복잡해집니다.
- 화면마다 요구하는 데이터 형식이 다를 수 있는데(예: 회원가입 시엔 비밀번호 필수, 정보 수정 시엔 선택), DTO를 사용하면 각 상황에 맞는 최적화된 검증을 독립적으로 수행할 수 있습니다.
Q4. 검증 에러 발생 시 스프링은 어떤 예외를 던지며, 어떻게 처리하나요?
- 답변: @RequestBody를 사용하는 경우 MethodArgumentNotValidException이 발생합니다.
- 현업에서는 이를 처리하기 위해 @RestControllerAdvice를 사용하여 전역적으로 예외를 가로챕니다. 이후 에러 메시지를 정제하여 클라이언트가 이해하기 쉬운 JSON 형태(예: ErrorResponse 객체)로 반환하는 방식을 주로 사용합니다.
Q5. 복잡한 비즈니스 규칙(예: DB 조회 후 중복 체크)도 Bean Validation 애너테이션으로 처리하나요?
- 답변: 아니요, 보통은 Service 계층에서 처리합니다.
- Bean Validation(@NotBlank 등)은 데이터의 형식(Format)을 검증하는 데 적합합니다.
- DB를 조회하거나 외부 API와 통신해야 하는 비즈니스 정합성 검증은 Service 단에서 로직으로 처리하거나, 필요하다면 스프링의 Validator 인터페이스를 구현하여 별도로 분리합니다.
'Spring > spring 숙련' 카테고리의 다른 글
| JPA Entity 연관 관계 (0) | 2026.04.10 |
|---|---|
| RestTemplate (0) | 2026.04.09 |
| Session/Cookie/Filter/Listener (0) | 2026.04.09 |
| 쿠키(Cookie)와 세션(Session) (1) | 2026.04.09 |
| 인증(Authentication) vs 인가(Authorization) (0) | 2026.04.09 |
