들어가기
최근에 참고한 자료에 따르면 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
[5] https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
'3.구현 > Java or Kotlin' 카테고리의 다른 글
[spring boot] 다중 DB 사용하기: AbstractionRoutingDataSource 활용 (0) | 2023.10.31 |
---|---|
[spring boot] 다중 DB 사용하기: 설정 활용 (2) | 2023.10.30 |
[spring] Spring Framework에서 DB연동 테스트 (0) | 2023.10.26 |
Kotlin 배우기2 - 심화 (0) | 2023.10.18 |
Kotlin 배우기1 - 기본 (2) | 2023.10.17 |