🚀 프로젝트/🥁 두둥

[Spring] 스프링 날짜 타입 JSON 변환 및 포맷팅하기 - @JsonFormat, @JacksonAnnotationsInside

gengminy 2023. 2. 27. 00:46

개발을 하다보면

좋든 싫든 항상 날짜에 대한 포맷팅을 마주하게 된다.

 

이 글에서는 그 과정에서 공부했던,

@JsonFormat 을 활용하여 LocalDateTime 등 날짜에 대한 JSON 직렬화하기와

또 날짜 포맷팅, Jackson 을 활용한 커스텀 어노테이션까지 적어보았다.

 

 

💥 LocalDateTime 형식

{
  "name": "hello",
  "startAt": "2023-02-26T15:12:17.536Z",
  "endAt": "2023-02-26T15:12:17.536Z"
}

LocalDateTime 같은 경우에는

기본적으로 중간에 알파벳 등이 섞여있어

응답 시 같이 내보내게 된다.

 

{
    "name": "hello",
    "startAt": "2023.03.20 12:00",
    "endAt": "2023.03.20 13:30"
}

응답값에 포맷팅을 걸어서

이런 식으로 요청 및 응답하게 할 순 없을까?

 

 

📌 @JsonFormat

Jackson 에서 제공하는 @JsonFormat 을 사용하면

Request 나 Response 필드의 날짜 형식을 JSON 으로 변환시킬 수 있다.

 

📝 MyRequest

@Getter
@RequiredArgsConstructor
public class MyRequest {
    private String name;
    
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd HH:mm", timezone = "Asia/Seoul")
    private LocalDateTime startAt;
}

@JsonFormat 의 pattern 필드에 내가 원하는 날짜 형식을 입력하면 된다.

 

{
  "name": "HI",
  "startAt": "2023.03.20 12:00"
}

Request DTO 필드에 @JsonFormat 을 쓸 경우

내가 원하는 형식에 맞게 필드를 사용할 수 있다!

 

이런 식으로 하게 되면 Controller 에서 String 형식으로 가져오거나 해서

번거롭게 변환하지 않아도 되는 큰 장점이 있다

 

 

📝 BasicResponse

@Getter
@Builder
public class BasicResponse {
    private String name;
    
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd HH:mm", timezone = "Asia/Seoul")
    private LocalDateTime startAt;
    
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd HH:mm", timezone = "Asia/Seoul")
    private LocalDateTime endAt;
}

Response DTO 도 마찬가지이다.

자동으로 해당 패턴에 맞는 형식으로 직렬화된다.

 

 

 

📌 @DateTimeFormat

스프링에서 지원하는 어노테이션인 @DateTimeFormat 도 있지만,

기본적으로 Spring 의 기본 JSON 컨버터는 Jackson 이기 때문에 우선순위에서 밀린다.

 

하지만 @DateTimeFormat 을 사용해야 하는 곳이 있는데

JSON 직렬화를 하지 않는 Request Parameter 나 ModelAttribute 등에서는

이 어노테이션을 사용하면 된다.

 

JSON 은 @JsonFormat 을 사용하자!

 

 

 

🚀 커스텀 어노테이션 @DateFormat

프로젝트 내에서 날짜 형식을 통일하기 위해

모든 필드에 이와 같이 붙여줘야 하는데,

 

일단 코드 길이가 길며

파라미터가 3개라 오탈자 등의 가능성도 있었다.

때문에 이를 단순화하고 싶었다.

 

📝 DateFormat

@JacksonAnnotationsInside
@Retention(RetentionPolicy.RUNTIME)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd HH:mm", timezone = "Asia/Seoul")
public @interface DateFormat {}

커스텀 어노테이션인 @DateFormat 이다.

사용 목적은 @JsonFormat 을 전부 통일시키고

재사용성을 높이기 위해서이다.

 

중요한 점은 @JacksonAnnotationsInside 를 반드시 붙여줘야 하는데,

이 어노테이션이 Jackson 관련 어노테이션을 상속하여 사용하겠다는 의미이다.

이것을 붙이지 않는다면 인터페이스 자체에 어노테이션이 적용되어 원치 않는 결과가 발생한다.

 

이렇게 사용하게 되면 굉장히 단순해지고

가독성이 올라가게 된다!

 

다만 커스텀 어노테이션을 남발하거나 이름을 명확하게 짓지 않으면

팀원들이 혼동할 수 있고, 오히려 생산성이 저해되기 때문에

적절하게 잘 만들어 팀원들과 소통할 필요가 있겠다.