본문 바로가기

3.구현/Java or Kotlin

[spring boot] jackson대신에 gson으로 사용하기

들어가기

최근에 참고한 자료에 따르면 gson이 성능이 좋아져서 jackson보다 더 좋아졌다는 글이 있었다. 그래서 한번 spring boot의 json 매퍼를 변경해서 사용해보았다.

작성자: ospace114@empal.com, http://ospace.tistory.com/

기본 환경

먼저 dependency을 추가하자. spring boot을 사용한다면 version을 사용하지 않아도 자동으로 버전을 잡아준다. 현재 기준(2022.07.06)으로 버전 2.8.8 이하는 vulerability가 있어서 사용을 권장하지 않는다.

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <!-- <version>2.9.1</version> -->
</dependency>

그리고 기존 jackson은 spring-boot-starter-web에서 exclusions에 포함시켜서 제외시켜준다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-json</artifactId>
        </exclusion>
    </exclusions>
</dependency>

또는 jackson을 사용하지만 매퍼로는 사용하지 않는다면 자동 설정에서 제외시켜준다.

@SpringBootApplication(exclude = {JacksonAutoConfiguration.class})

간혹 application.properties에서 아래 설정으로 매퍼를 변경해줘야한다고했는데 필자는 안해줘도 잘 동작했다.

spring.http.converters.preferred-json-mapper=gson

기존에 jackson을 사용할 때에 아래 어노테이션을 데이터 클래스에 추가해줬지만 gson에서는 기본으로 적용되고 있어서 사용할 필요 없다.

@JsonInclude(JsonInclude.Include.NON_NULL)

날짜와 시간 변환

application.propertis에서 날짜 포멧팅(date->string)은 아래처럼하면 된다.

spring.gson.date-format=yyyy-MM-dd'T'HH:mm:ss

위의 포멧팅은 Date 객체에만 해당한다. 만약 LocalDate, LocalDateTime을 사용하거나 다른 객체를 사용한다면 동작하지 않는다. 이때에는 별도 GsonBuilder을 만들어줘야 한다.

@Bean
public GsonBuilder gsonBuilder() {
    return new GsonBuilder()
        .setDateFormat(DateUtils.DATE_FORMAT) // application.properties의 spring.gson.date-format과 동일
        .registerTypeAdapter(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
            @Override
            public JsonElement serialize(LocalDateTime src, Type type, JsonSerializationContext ctx) {
                return new JsonPrimitive(
                        DateUtils.toString(src));
            }
        });
}

DateUtils은 아래와 같다.

public class DateUtils {
    //static final String DATE_FORMAT = "yyyy-MM-dd";
    static final String DATE_FORMAT = "yyyy/MM/dd HH:mm:ss";
    private static final String DATETIME_FORMAT = "yyyy/MM/dd HH:mm:ss";
    private static DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DATETIME_FORMAT);

    public static String toString(LocalDateTime date) {
        return null == date ? null : date.format(DATETIME_FORMATTER);
    }

    public static LocalDateTime toLocalDateTime(String str) {
        return null == str ? null : LocalDateTime.parse(str, DATETIME_FORMATTER);
    }
}

GsonBuilder도 serialize만 가능하다. deserialize하려면 application.properties에 아래 설정을 해줘야 한다.

spring.mvc.format.date=yyyy/MM/dd
spring.mvc.format.date-time=yyyy/MM/dd HH:mm:ss
spring.mvc.format.time=HH:mm:ss

다른 deserialize 방법으로 annotation을 사용한 방법이 있다.

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

이 방법은 잘 작동하지만 모든 LocalDateTime 사용하는 모든 곳에 넣어줘야 한다는 불편함이 있다.

deserialize를 spring 전체로 적용할 수 있는 방법이 Converter를 사용한 방법이 있다.

@Bean
public Converter<?, ?>  localDateTimeConverter() {
    return new Converter<String, LocalDateTime>() {
        @Override
        public LocalDateTime convert(String src) {
            return DateUtils.toLocalDateTime(src);
        }
    };
}}

Converter을 한꺼번에 관리할수 있는 게 addFormatters()가 있다.

// 출처: https://www.baeldung.com/spring-type-conversions
@Override
public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(new Converter<String, LocalDateTime>() {
        @Override
        public LocalDateTime convert(String src) {
            return DateUtils.toLocalDateTime(src);
        }
    });
}

마무리

gson이 최근?에 최적화가 잘되어서 jackson의 성능을 뛰어 넘었다고 하네요. 물론 이것도 어떻게 측정되고 어떤 데이터로 했는지에 따라 달라질 수 있겠지만, 아무튼 gson이 좀더 좋은 성능 보여준다고 하니 성능이 중요한 곳이면 한번 변경해서 테스트해보는 것도 나쁘지 않을 것 같습니다. 여러분에서 도움이 되었으면 합니다. 모두 즐프하세요. ospace.

참고

[1] Nick Andrews, The Ultimate JSON Library: JSON.simple vs. GSON vs. Jackson vs. JSONP, 2021-10-16, https://dzone.com/articles/the-ultimate-json-library-jsonsimple-vs-gson-vs-ja

[2] RAJEEV SINGH, Configuring Spring Boot to use Gson instead of Jackson, 2018-05-29, https://www.callicoder.com/configuring-spring-boot-to-use-gson-instead-of-jackson/

[3] Mvn repository: Gson, https://mvnrepository.com/artifact/com.google.code.gson/gson

[4] https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties.json

[5] https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

반응형