[Spring] Formatter 과 Jackson

Coodori·2023년 3월 31일
0

CherishU

목록 보기
15/29

문제 발생

프론트가 업무가 많아짐에 따라 가격과 날짜 같은 경우 내가 보기 좋은 형식으로 프론트에게 주고 싶어졌다.
FE는 결국 화면에 중요하게 시간을 사용해야하므로
BE인 내가 사용하기 좋은 포맷으로 포맷팅을 해주고싶었다.

1. Formatter

Spring에는 다양한 Formatter를 제공한다.
그 중 유용한 포맷터인

  • @NumberFormat : 숫자관련 포맷터 사용
  • @DateTimeFormat : 날짜관련 포맷터 사용

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/format/annotation/NumberFormat.html

를 제공한다.

하지만 해당 Formatter에는 큰 사용 불가한 점이 있다.

사용불가

메세지 컨버터에는 해당 기능이 사용 불가하다.
사실 포맷터는 한곳에서 모아서 사용이 가능한지 판단해주는 Conversion 인터페이스에 등록되고 사용이 된다.
하지만
HttpMessageConverter 의 역할은 HTTP 메시지 바디의 내용을 객체로 변환하거나 객체를 HTTP 메시지 바디에 입력하는 것이다.
예를 들어서 JSON을 객체로 변환하는 메시지 컨버터는 내부에서 Jackson 같은 라이브러리를 사용한다.
객체를 JSON으로 변환한다면 그 결과는 이 라이브러리에 달린 것이다. 따라서
JSON 결과로 만들어지는 숫자나 날짜 포맷을 변경하고 싶으면 해당 라이브러리가 제공하는 설정을 통해서 포맷을 지정해야 한다.
결과적으로 이것은 컨버전 서비스와 전혀 관계가 없다.

컨버전 서비스는 @RequestParam , @ModelAttribute , @PathVariable , 뷰 템플릿(타임리프, jsp) 등에서 사용할 수
있다

그렇다면 스프링 메세지 컨버터는 어떤 라이브러리를 사용하고 있을까?

2. Spring Message Converter

Spring MVC인 spring-boot-starter-web에는 Jackson를 포함하고있다.

공식문서의 내용으로 일반적으로 Date타입을 Number 혹은 String 형식으로 직렬화 하는데 사용하고,
pattern() property을 통해 정확한 세부설정을 하기위해 사용한다고 한다.

사용법

@JsonFormat을 통해 사용가능하다

공식 문서와 사용 레퍼런스
https://www.baeldung.com/jackson-jsonformat

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date regDate;

매번 그럼 모든 필드값에 가서 업데이트해야하나요?

스프링은 이러한 반복되는 작업에서 굉장히 최적화가 잘되어있습니다.
고로 해당 번거로운 작업을 전체적으로 해줄 수 있습니다.

@Configuration
public class DateFormatConfiguration {

    private static final String dateFormat = "yyyy-MM-dd";
    private static final String datetimeFormat = "yyyy-MM-dd HH:mm:ss";

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
        return jacksonObjectMapperBuilder -> {
            jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("UTC"));
            jacksonObjectMapperBuilder.simpleDateFormat(datetimeFormat);
            jacksonObjectMapperBuilder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat)));
            jacksonObjectMapperBuilder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(datetimeFormat)));
        };
    }
}

여기서는 날짜 형식만 다루지만 이외에도 다른 Json응답값을 설정하고 변경할 수 있다.

하지만 여기서 스프링의 기본원칙

  1. 더 유연한 것이 우선권을 가진다.
  2. 범위가 넒은 것 보다 좁은 것이 우선권을 가진다.

그래서 만약 저렇게 전체적인 Json에 대한 포맷팅을 설정했어도
해당 필드위에

   @JsonFormat(pattern = "yyyy.MM.dd")
    private Date regDate;

라고 지정했으면
2023-03-31이 아닌 2023.03.31로 나오게 된다.

@DateTimeForamt / @JsonFormat

Request일 경우

  • @ModelAttribte, @RequestParam

    • @DateTImeFormat을 사용한다.
    • @JsonFormat은 사용할 수 없다.
  • @RequestBody

    • @DateTimeFormat을 사용한다.
    • @JsonFormat도 사용한다.(우선권,필수조건)

Response 일경우

  • @ReponseBody

    • @JsonFormat만 사용 가능하다.
    • @ModelAttribute, @RequestParam은 JSON이 아니기 때문에 @JsonFormat은 사용할 수가 없는 것이다.

결론

FE에게 일관적인 날짜 포맷을 제공하여 편리하게 사용하도록하였다.

REFERENCE

https://develop-writing.tistory.com/106
https://addio3305.tistory.com/101
https://dev-monkey-dugi.tistory.com/m/160

profile
https://coodori.notion.site/0b6587977c104158be520995523b7640

0개의 댓글