ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스프링 부트 시작하기] @JsonFormat과 Jackson2ObjectMapperBuilderCustomizer를 사용해서 날짜 형식 지정하기
    스프링 부트 시작하기 2019. 9. 30. 23:32

    안녕하세요. 

    오늘은 지난 글에 이어서 날짜 형식을 지정하는 방법에 대해서 살펴보겠습니다.

     

    -------------------------------------------------------------------------------------------------------------------------

    이전 포스팅에서 서버에서 조회한 날짜를 Thymeleaf의 기능을 사용해서 원하는 형식으로 변경했다.

    이 경우 API를 호출하고 그 결과값을 보여주는 클라이언트에서 일일이 날짜 형식을 지정해야 하는 문제가 있다. 

     

    따라서 서버에서 날짜 형식을 지정해서 보내주는 방식에 대해서 알아보자.

     

    1. @JsonFormat 어노테이션 사용하기

    @JsonFormat은 Jackson 라이브러리에서 제공하는 어노테이션으로 JSON 응답값의 형식을 지정할 때 사용한다. 응답값의 형식이란 날짜 형식 뿐만이 아니라 JSON 응답의 키 설정, 특정 값의 포함 여부, 응답값의 순서 등 여러가지 형태를 의미한다. 이와 관련된 내용은 나중에 좀 더 자세히 설명할 기회가.....있을까....? 

     

    어쨋든 @JsonFormat을 이용해서 날짜 형식을 지정하려면 다음과 같이 사용하면 된다.

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
    private LocalDateTime createdDatetime;

     

    딱 봐도 특별히 설명할 게 없을 만큼 간단하게 사용할 수 있다. 

    pattern : 원하는 날짜 형식을 지정한다.

    timezone : 타임존을(???) 설정한다. 기본값은 UTC다.

     

    이렇게 지정하고 API를 호출하면 다음과 같은 결과를 확인할 수 있다.

    여기서는 게시글 목록 조회 API를 호출했다.

    createdDatetime이 yyyy-MM-dd HH:mm:ss 형식으로 출력된 것을 알 수 있다.

    날짜 형식을 yyyy.MM.dd HH:mm:ss로 지정하면 다음과 같이 나온다.

    @JsonFormat 어노테이션으로 지정한 형식으로 나오는 것을 확인할 수 있다. 

     

     


    참고 : 

    Jackson 라이브러리를 사용하려면 build.gradle에 다음과 같이 라이브러리를 추가하면 된다.

    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.10'
    

     

    단, 우리가 만든 스프링 부트 애플리케이션에는 이와 같은 라이브러리를 추가하지 않았는데 어떻게 사용할 수 있을까?

     

    그 답은 스프링 부트 스타터 패키지에는 Jackson 라이브러리가 포함되어 있기 때문이다.

    build.gradle 파일을 보면 다음과 같은 의존성을 볼 수 있다.

    implementation('org.springframework.boot:spring-boot-starter-web')

    spring-boot-starter-web에는 몇가지 라이브러리를 포함하고 있는데 그 중 하나가 jackson-databind 라이브러리다.

     

    MVNREPOSITORY에서 spring-boot-starter-web에 포함된 라이브러리를 보면 spring-boot-starter-json을 볼 수 있고 spring-boot-starter-json이 다시 jackson-databind를 포함하고 있는것을 볼 수 있다.

    https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web/2.1.8.RELEASE

     

    Maven Repository: org.springframework.boot » spring-boot-starter-web » 2.1.8.RELEASE

    Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container org.springframework.boot spring-boot-starter-web 2.1.8.RELEASE // https://mvnrepository.com/artifact/org.springframework.boot/spring-b

    mvnrepository.com

    https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-json/2.1.8.RELEASE

     

    Maven Repository: org.springframework.boot » spring-boot-starter-json » 2.1.8.RELEASE

    Starter for reading and writing json org.springframework.boot spring-boot-starter-json 2.1.8.RELEASE // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-json compile group: 'org.springframework.boot', name: 'spring-boot-start

    mvnrepository.com


    2. Jackson2ObjectMapperBuilderCustomizer 사용하기

    앞에서 @JsonFormat으로 날짜 형식을 바꿨지만 단점이 있다. 프로젝트마다 차이는 있겠지만 일반적으로 API의 응답값에는 날짜가 들어가는 경우가 많다. 그럴때마다 @JsonFormat으로 날짜 형식을 지정하는 건 아무래도 귀찮은 일이기도 하고 날짜 형식이 통일되지 않을 수도 있다. 

    따라서 이번에는 애플리케이션의 Json 응답값을 만들 때 일괄적으로 날짜 형식을 지정하는 방법을 알아보자.

     

    board.configuration 패키지 밑에 DateFormatConfiguration 클래스를 생성하고 다음의 코드를 작성한다.

    package board.configuration;
    
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
    import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.time.format.DateTimeFormatter;
    import java.util.TimeZone;
    
    @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)));
    		};
    	}
    }
    

     

    Jackson2ObjectMapperBuilderCustomizer는 JSON 응답값을 변경할 수 있는 인터페이스다. Jackson2ObjectMapperBuilder 클래스는 Jackson 라이브러리의 기본적인 설정을 사용하는데, Jackson2ObjectMapperBuilderCustomizer 인터페이스를 이용해서 우리가 원하는 대로 JSON 응답값을 변경할 수 있도록 해준다.

    날짜 형식을 변경하기 위해서 사용하기 때문에 DateFormatConfiguration이라는 이름으로 만들었지만, JSON 응답에 관련된 수정을 하게된다면 클래스 이름을 그에 맞게 만들면 된다. 여기서는 날짜 형식만 변경하지만 이 외에도 JSON 응답값의 인덴트(띄어쓰기) 설정 등 여러가지를 변경할 수 있다.  

     

    사용법은 위의 코드에서 보듯이 간단하다. 사용할 클래스에 @Configuration 어노테이션을 붙이고 @Bean 어노테이션을 사용해서 Jackson2ObjectMapperBuilderCustomizer 인스턴스를 반환하면 된다. 

     

    여기서 설정한 것은 총 4 가지다.

    1) timezone 설정 - 시간대를 UTC로 지정했다. 

    2) java.util.Date 클래스의 날짜 형식 설정 - 우리는 Java8에서 추가된 LocalDate와 LocalDateTime을 사용하지만 상황에 따라서 java.util 패키지의 Date 클래스를 사용할 수도 있다. 따라서 Date 클래스의 날짜 형식을 지정해줬다.

    3) LocalDate 클래스의 날짜 형식 설정

    4) LocalDateTime 클새으의 날짜 형식 설정

     

    이제 설정이 정상적으로 동작하는지 확인할 차례다. 애플리케이션을 실행하고 게시글 목록 조회 API를 호출해보자. (앞에서 사용한 @JsonFormat은 제거했다.)

    우리가 지정한 형식으로 날짜가 표시되는 것을 볼 수 있다. (앞에서 본것과 동일한 스크린샷인것 처럼 느껴진다면 기분탓이다.)

     

    만약 Jackson2ObjectMapperBuilderCustomizer와 @JsonFormat이 같이 설정되어 있다면 결과는 어떻게 될까?

    확인을 위해서 Jackson2ObjectMapperBuilderCustomizer에는 yyyy-MM-dd HH:mm:ss로 지정하고 @JsonFormat은 yyyy.MM.dd HH:mm:ss 형식으로 지정하고 실행해보자. 

    이와 같이 @JsonFormat의 형식으로 출력되는 것을 볼 수 있다.

    따라서 Jackson2ObjectMapperBuilderCustomizer를 이용해서 날짜 응답의 공통적인 형식을 지정하고 상황에 따라서 날짜 형식을 변경해서 응답해야 할 경우에는 @JsonFormat을 사용하면 된다.

     

     


    질문 : 날짜 형식을 지정하는 방법에 대해서 인터넷을 검색하면 application.properties에 spring.jackson.date-format 속성을 지정하면 날짜 형식이 바뀐다데?

     

    답변 : spring.jackson.date-format은 java.util.Date 클래스에는 동작하지만 Java8에서 추가된 날짜 클래스들에는 동작하지 않는다. 따라서 Java 8 이상에서는 spring.jackson.date-format만으로 안된다.

     

    끝.

    댓글

Designed by Tistory.