본문 바로가기
개발 (ENG)

Spring Boot(Kotlin) — ep.8 Validation Configuration

by 새싹 아빠 2025. 11. 27.

This post explains how to configure Validation in a Spring Boot multi-module backend project.
Validation is applied from the moment you start creating DTOs, and automatically checks the data sent by the client before the controller method is executed.
Since the actual project does not yet include Validation logic, this article covers the full context of why it is needed → which module should contain it → required dependencies → simple implementation examples.

 

📚 Spring Boot(Kotlin) Server Setup — Series Overview

  1. Why Multi-Module Architecture? (Architecture Philosophy & Overall Design)
  2. API Response Format Design
  3. Global Exception Handling (GlobalExceptionHandler)
  4. Swagger (OpenAPI) Configuration
  5. Security (JWT) Basic Structure
  6. JWT TokenProvider
  7. Redis Configuration 
  8. Validation Configuration ← Current Article
  9. Logging + MDC(traceId)
  10. application.yml Profile Separation (local/dev/prod)
  11. Multi-Module + JPA Basic Structure
  12. Project Template git Distribution

✔ Why is Validation necessary?

Validation is a mechanism that checks client-provided request data before the server processes it.
In other words, it prevents invalid values from entering the service layer by verifying data before the controller method is invoked.

Without Validation, the following issues may occur:

  • Missing required parameters (null values)
  • String length constraint violations
  • Invalid email format
  • Bad values flowing into service → repository → DB

→ Validation is the very first defensive layer that enhances server stability.

 

✔ Which module should contain Validation?

In a multi-module architecture, Validation should work only when validating RequestDTOs in the Controller layer.


api        → Controller, Request/Response DTO
application → Service, Biz logic, Service Model
domain     → Entity

 

After validating request values in the api module, the data can be mapped to service-level DTOs. From this point on, the data is considered trustworthy, and deeper layers do not require additional validation.

 

Since Validation in this architecture has a single purpose — validating client request values
only the api module needs the Validation dependency.

✔ Required Dependency (Spring Boot 3.x)

To use Validation annotations such as @NotBlank, add the dependency below:


dependencies {
    implementation("org.springframework.boot:spring-boot-starter-validation")
}

Add this to api/build.gradle.kts.

 

✔ Simple DTO & Controller Example

1) Request DTO


import jakarta.validation.constraints.Email
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Size

data class CreateUserRequest(

    @field:NotBlank(message = "Name is required.")
    val name: String?,

    @field:Email(message = "Invalid email format.")
    val email: String?,

    @field:Size(min = 8, max = 20, message = "Password must be 8 to 20 characters.")
    val password: String?
)

@field: is required because Kotlin generates getters and setters for properties.
This ensures that Validation is applied directly to the underlying field.

 

2) Using it in the 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()
    }
}

If the request contains invalid values, Spring automatically triggers a Validation error before the controller method is executed.

 

✔ Handling Validation Errors (GlobalExceptionHandler)

Add the following logic to your existing GlobalExceptionHandler for cleaner error responses:


@ExceptionHandler(MethodArgumentNotValidException::class)
fun handleValidation(e: MethodArgumentNotValidException)
    : ResponseEntity<ApiResponse<Unit>> {

    val msg = e.bindingResult.fieldErrors.firstOrNull()?.defaultMessage
        ?: "Invalid request."

    return ResponseEntity
        .badRequest()
        .body(ApiResponse.fail(code = "INVALID_REQUEST", message = msg))
}

Validation errors will now respond in a consistent JSON format like this:


{
  "success": false,
  "code": "INVALID_REQUEST",
  "message": "Name is required."
}

 

✔ Conclusion

Validation has a very clear purpose: validating client request values.
In a multi-module structure like this project, Validation is needed only in the api module where RequestDTOs are handled.
Therefore, the Validation dependency must exist in api only, and no other module requires it.

The next article will cover Logging + MDC(traceId) configuration.

 

https://jaemoi8.tistory.com/45

 

Spring Boot(Kotlin) — ep.9 Logging & MDC(traceId) Setup Guide

This post explains how to systematically configure Logging in a Spring Boot multi-module project,and how to apply request-level tracing using MDC (Mapped Diagnostic Context).In real-world environments, it is extremely important to quickly identify “which

jaemoi8.tistory.com