이 글은 Spring Boot 멀티 모듈 기반 서버 개발 시, Validation 설정을 어떻게 구성해야 하는지 정리하는 글입니다.
Validation은 DTO를 만들기 시작할 때부터 사용되는 기능이며, 클라이언트가 보낸 요청 데이터를 컨트롤러 진입 전 단계에서 자동으로 검증해줍니다.
아직 실제 프로젝트에는 Validation이 적용되지 않았기 때문에, 이 글에서는 왜 필요한지 → 어떤 모듈에 둬야 하는지 → 필요한 의존성 → 간단한 예시 구현까지 전체 맥락을 정리합니다.
📌 Spring Boot(Kotlin) 기본 셋팅 — 전체 시리즈
- 왜 멀티 모듈 구조인가? (아키텍처 철학 & 전체 설계 편)
- API Response 포맷 설계
- 글로벌 예외 처리(GlobalExceptionHandler)
- Swagger(OpenAPI) 설정
- Security(JWT) 기본 골격
- JWT TokenProvider
- Redis 설정
- Validation 설정 ← 지금 글
- Logging + MDC(traceId)
- application.yml 프로필 분리 (local/dev/prod)
- 멀티모듈 + JPA 기본 구조 정리
- 완성된 프로젝트 템플릿 git 공유
✔ Validation은 왜 필요한가?
Validation은 클라이언트가 보낸 요청값을 서버가 처리하기 전에 검증하는 기능입니다.
즉, Controller의 메서드가 실행되기 이전에 데이터의 유효성을 체크하여, 잘못된 값이 서비스 로직까지 도달하지 못하도록 막습니다.
Validation이 없으면 다음과 같은 문제가 발생할 수 있습니다:
- 필수 파라미터 누락(null)
- 문자열 길이 제약 위반
- Email 형식 오류
- 문제가 있는 값이 service → repository → DB까지 흘러들어가는 상황
→ Validation은 서버의 안정성을 높이는 가장 첫 번째 방어막입니다.
✔ Validation은 어느 모듈에 있어야 하는가?
멀티 모듈 구조에서 Validation은 Controller에서 RequestDTO를 검증할 때만 동작하면 될 것으로 판단했습니다.
api → Controller, Request/Response DTO
application → Service, Biz logic, Service Model
domain → Entity
api 모듈 계층에서 Validation 체크를 한 후 비즈니스 로직 전용 서비스 DTO로 매핑 후 전달하게 되면 이후에는
request 값을 신뢰할 수 있습니다.
제가 설계한 프로젝트에서는 Validation이 “클라이언트 입력값 검증”이라는 한 가지 목적만 있기 때문에
api 모듈만 의존성을 가지면 충분합니다.
✔ 필요한 의존성 (Spring Boot 3.x 기준)
DTO에서 Validation 어노테이션(@NotBlank 등)을 사용하려면 아래 의존성을 추가해야 합니다.
dependencies {
implementation("org.springframework.boot:spring-boot-starter-validation")
}
이 코드는 api/build.gradle.kts에 넣으면 됩니다.
✔ 간단한 DTO & Controller 예시
1) Request DTO
import jakarta.validation.constraints.Email
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Size
data class CreateUserRequest(
@field:NotBlank(message = "이름은 필수 입력값입니다.")
val name: String?,
@field:Email(message = "올바른 이메일 형식이 아닙니다.")
val email: String?,
@field:Size(min = 8, max = 20, message = "비밀번호는 8~20자여야 합니다.")
val password: String?
)
@field:를 붙이는 이유는 Kotlin이 프로퍼티에 대해 getter/setter를 생성하기 때문이며,
Validation이 실제 필드에 적용되도록 명확히 지정해주는 역할을 합니다.
2) Controller에서 사용하기
@RestController
@RequestMapping("/users")
class UserController(
private val userService: UserService
) {
@PostMapping
fun createUser(
@Valid @RequestBody request: CreateUserRequest
): ApiResponse<Unit> {
userService.create(request)
return ApiResponse.ok()
}
}
요청값이 잘못되면 컨트롤러에 진입하기 전에 Spring이 자동으로 validation 오류를 발생시킵니다.
✔ Validation 오류 응답 처리 (GlobalExceptionHandler)
이미 시리즈에서 만든 글로벌 예외 핸들러에 아래 내용을 추가하면 깔끔하게 처리됩니다.
@ExceptionHandler(MethodArgumentNotValidException::class)
fun handleValidation(e: MethodArgumentNotValidException)
: ResponseEntity<ApiResponse<Unit>> {
val msg = e.bindingResult.fieldErrors.firstOrNull()?.defaultMessage
?: "올바르지 않은 요청입니다."
return ResponseEntity
.badRequest()
.body(ApiResponse.fail(code = "INVALID_REQUEST", message = msg))
}
이제 Validation 오류가 발생하면 다음과 같은 통일된 JSON 응답 포맷으로 내려갈 것입니다:
{
"success": false,
"code": "INVALID_REQUEST",
"message": "이름은 필수 입력값입니다."
}
✔ 마무리
Validation은 “클라이언트 입력값 검증”이라는 분명한 역할을 가진 기능이며,
멀티 모듈 구조에서는 api 모듈에서 RequestDTO를 다룰 때만 필요합니다.
즉, Validation을 어디에 둬야 하는지 고민할 필요 없이 api 모듈 하나만 설정하면 됩니다.
다음 글에서는 Logging + MDC(traceId) 설정을 정리할 예정입니다.
https://jaemoi8.tistory.com/44
Spring Boot(Kotlin) — 9편. Logging + MDC(traceId) 설정
이번 글은 Spring Boot 멀티 모듈 기반 프로젝트에서 로깅(Logging)을 체계적으로 구성하고,MDC(Mapped Diagnostic Context)를 활용해 요청 단위 추적(traceId)을 적용하는 방법을 정리한 글입니다.실무 환경에서
jaemoi8.tistory.com
'개발' 카테고리의 다른 글
| Spring Boot(Kotlin) — 10편. application.yml 프로필 분리 (local/dev/prod) (0) | 2025.11.27 |
|---|---|
| Spring Boot(Kotlin) — 9편. Logging + MDC(traceId) 설정 (0) | 2025.11.27 |
| Spring Boot(Kotlin) — 7편. 왜 Redis인가? Spring Boot 애플리케이션에서 Redis를 사용하는 이유와 설정 (0) | 2025.11.25 |
| Spring Boot(Kotlin) — 6편. JWT TokenProvider 이해하기 (토큰 생성·검증·구조 설계까지) (0) | 2025.11.25 |
| ⚠️ Spring Boot(Kotlin) — 5편. Security(JWT) 설정 (0) | 2025.11.25 |