본문 바로가기
IT

[Spring Boot 3] @DateTimeFormat을 활용한 날짜 유효성 검사 완전 정복

by 굿센스굿 2025. 5. 9.
반응형

 

Spring Boot로 웹 애플리케이션을 개발하다 보면 사용자로부터 날짜를 입력받아 처리해야 할 일이 자주 발생합니다. 특히 RESTful API를 설계할 때 URL 파라미터나 폼 데이터를 통해 날짜 정보를 전달받을 경우, 문자열 형태의 입력값을 LocalDate, LocalDateTime, Date 등의 자바 날짜 객체로 변환해주는 과정이 필요합니다.

이때 유용하게 사용할 수 있는 것이 바로 @DateTimeFormat 어노테이션입니다. 본 포스팅에서는 Spring Boot 3에서 @DateTimeFormat을 사용하는 방법부터 주의사항, 고급 사용법까지 하나하나 짚어보겠습니다.


✅ @DateTimeFormat이란?

@DateTimeFormat은 Spring Framework에서 제공하는 어노테이션으로, 사용자가 입력한 날짜 문자열을 자바의 날짜 타입으로 변환할 수 있게 도와줍니다. 주로 컨트롤러에서 쿼리 파라미터로 날짜를 받을 때 많이 사용되며, 지정된 패턴에 따라 형식을 검증하고 변환까지 자동으로 수행해줍니다.


🧪 기본 사용 방법

가장 기본적인 사용 방법은 @DateTimeFormat(pattern = "yyyy-MM-dd") 형태로 날짜 포맷을 지정하는 것입니다.

import java.time.LocalDate;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.AllArgsConstructor;
import lombok.Getter;

@RestController
public class DateValidController {

    @GetMapping("/valid/date")
    public ValidObject validDate(ValidObject object) {
        return object;
    }

    @Getter
    @AllArgsConstructor
    public static class ValidObject {
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate date;
    }
}

위 예제에서 /valid/date?date=2025-05-09 와 같이 요청을 보내면, 입력된 문자열 "2025-05-09"은 LocalDate 객체로 자동 변환됩니다.


❗ 유효성 검사는 어떻게 이루어질까?

  • 지정된 패턴(pattern = "yyyy-MM-dd")과 일치하는 경우, 유효성 검사를 통과하여 LocalDate 객체로 정상 변환됩니다.
  • 만약 "20250509"처럼 형식이 다르면 변환이 실패하며, Spring은 적절한 예외를 발생시켜 클라이언트에게 에러 응답을 반환합니다.

예를 들어:

/valid/date?date=20250509

이 요청은 yyyy-MM-dd 형식이 아니므로 변환에 실패하고 400 Bad Request 에러를 발생시킵니다.


📌 지원되는 날짜 타입

@DateTimeFormat은 다음과 같은 타입에서 사용할 수 있습니다:

@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate localDate;

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime localDateTime;

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;
  • LocalDate: 연-월-일
  • LocalDateTime: 연-월-일 시:분:초
  • Date: 자바 기본 날짜 객체도 사용 가능

⚠️ 주의할 점 1: String에는 유효성 검사가 적용되지 않음

@DateTimeFormat은 문자열(String) 에는 유효성 검사를 적용하지 않습니다. 즉, 다음과 같이 작성하면 아무런 검증도 하지 않습니다:

@DateTimeFormat(pattern = "yyyyMMdd")
private String stringDate;

따라서 날짜 유효성을 검증하고 싶다면 반드시 LocalDate, LocalDateTime, Date 등의 날짜 타입으로 선언해야 합니다.


⚠️ 주의할 점 2: @RequestBody에서는 동작하지 않음

많은 개발자들이 실수하는 부분 중 하나가, JSON 바디를 통해 데이터를 받을 때 @DateTimeFormat을 적용하는 것입니다.

@PostMapping("/valid/date")
public ValidObject validDateForPost(@RequestBody ValidObject object) {
    return object;
}

@Getter
@AllArgsConstructor
public static class ValidObject {
    @DateTimeFormat(pattern = "yyyyMMdd")
    private LocalDate localDate;
}

위 코드에서 JSON 바디로 {"localDate": "20250509"} 형식의 값을 보내면 변환이 되지 않습니다. 이유는 @DateTimeFormat은 스프링의 바인딩 컨버터에서만 작동하며, Jackson이 사용하는 JSON 역직렬화에는 적용되지 않기 때문입니다.

💡 해결 방법: @JsonFormat을 사용하세요.

import com.fasterxml.jackson.annotation.JsonFormat;

@JsonFormat(pattern = "yyyyMMdd")
private LocalDate localDate;

이렇게 하면 JSON 역직렬화 시 Jackson이 해당 포맷을 참고하여 날짜 문자열을 객체로 변환합니다.


🌐 ISO 형식 지정 방법

@DateTimeFormat은 pattern 외에도 ISO 형식을 사용할 수 있습니다. 자주 쓰는 날짜/시간 포맷을 간단하게 지정할 수 있는 방법입니다.

import org.springframework.format.annotation.DateTimeFormat.ISO;

@DateTimeFormat(iso = ISO.DATE)
private LocalDate localDate;

@DateTimeFormat(iso = ISO.DATE_TIME)
private LocalDateTime localDateTime;

@DateTimeFormat(iso = ISO.TIME)
private LocalTime localTime;

ISO 포맷의 정의는 다음과 같습니다:

  • ISO.DATE: "yyyy-MM-dd"
  • ISO.DATE_TIME: "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
  • ISO.TIME: "HH:mm:ss.SSSXXX"

특히 ISO.DATE는 가장 흔하게 사용되는 날짜 포맷이므로 pattern = "yyyy-MM-dd" 대신 사용할 수 있어 가독성과 유지보수 측면에서 유리합니다.


🔄 fallbackPatterns로 다중 형식 대응

Spring Boot 3부터는 하나의 필드에 여러 날짜 형식을 허용할 수 있는 fallbackPatterns 옵션이 추가되었습니다.

@DateTimeFormat(iso = ISO.DATE, fallbackPatterns = {"yyyyMMdd", "yyyy_MM_dd"})
private LocalDate localDate;

이렇게 설정하면 기본적으로 ISO.DATE 형식 (yyyy-MM-dd)을 우선 적용하고, 이와 일치하지 않을 경우 "yyyyMMdd" 또는 "yyyy_MM_dd" 형식으로 대체 시도를 합니다.

단, 모든 형식과 매칭되지 않으면 변환은 실패합니다.


✅ 정리 및 마무리

항목 설명

@DateTimeFormat 문자열을 날짜 객체로 변환해주는 어노테이션
pattern 수동으로 날짜 형식 지정 (예: yyyy-MM-dd)
iso ISO 표준 형식 사용 (예: ISO.DATE)
fallbackPatterns 형식 불일치 시 대체 포맷 지정
동작 대상 LocalDate, LocalDateTime, Date 등 날짜 객체에만 동작
@RequestBody 동작하지 않음 (→ @JsonFormat 사용)

📣 마치며

@DateTimeFormat은 Spring MVC에서 날짜 유효성 검사 및 자동 변환을 처리할 수 있게 해주는 매우 유용한 도구입니다. 하지만 동작 범위가 제한적이며, 특히 JSON 요청 바디에서는 작동하지 않는다는 점을 반드시 유의해야 합니다.

실무에서는 @DateTimeFormat과 @JsonFormat을 상황에 맞게 적절히 병행 사용하면서 API의 유연성과 안정성을 모두 확보하는 것이 중요합니다. 이번 글이 여러분의 스프링 부트 개발에 도움이 되었길 바랍니다.

 

반응형