1. 소개

Java 애플리케이션은 데이터 송수신을 위한 공통 형식으로 JSON을 사용하는 경우가 많습니다. 또한 데이터를 저장하기 위한 직렬화 프로토콜로 사용됩니다. JSON 데이터 크기가 작아지면 애플리케이션이 더 저렴해지고 빨라집니다.

이 사용방법(예제)에서는 Java 애플리케이션에서 JSON 크기를 줄이는 다양한 방법을 살펴봅니다 .

2. 도메인 모델 및 테스트 데이터

일부 연락처 데이터 를 사용하여 고객에 대한 도메인 모델을 생성해 보겠습니다 .

public class Customer {
    private long id;
    private String firstName;
    private String lastName;
    private String street;
    private String postalCode;
    private String city;
    private String state;
    private String phoneNumber;
    private String email;

phoneNumberemail 을 제외한 모든 필드는 필수 입니다.

JSON 데이터 크기 차이를 적절하게 테스트하려면 최소한 수백 개의 Customer 인스턴스 가 필요 합니다. 테스트를 보다 생생하게 만들려면 다른 데이터가 있어야 합니다. 데이터 생성 웹 사이트 mockaroo는 여기에서 우리를 돕습니다. 우리는 1,000개의 JSON 데이터 레코드를 무료로 자체 형식으로 실제 테스트 데이터로 생성할 수 있습니다.

도메인 모델에 대해 mockaroo구성 보겠습니다 .

다음은 염두에 두어야 할 몇 가지 항목입니다.

  • 여기에서 필드 이름을 지정했습니다.
  • 여기에서 필드의 데이터 유형을 선택했습니다.
  • 모의 데이터에서 전화번호의 50%가 비어 있습니다.
  • 이메일 주소의 30%도 비어 있습니다.

아래의 모든 코드 예제는 mockaroo 의 1,000명의 동일한 고객 데이터를 사용합니다 . Factory 메소드 Customer.fromMockFile()사용하여 해당 파일을 읽고 이를 Customer 객체 로 변환 합니다.

JSON 처리 라이브러리로 Jackson사용할 것 입니다.

3. Jackson 기본 옵션이 있는 JSON 데이터 크기

기본 Jackson 옵션을 사용하여 Java 객체를 JSON에 작성해 보겠습니다.

Customer[] customers = Customer.fromMockFile();
ObjectMapper mapper = new ObjectMapper();
byte[] feedback = mapper.writeValueAsBytes(customers); 

첫 번째 Customer에 대한 모의 데이터를 살펴보겠습니다 .

{
  "id" : 1, 
  "firstName" : "Horatius", 
  "lastName" : "Strognell", 
  "street" : "4848 New Castle Point", 
  "postalCode" : "33432", 
  "city" : "Boca Raton", 
  "state" : "FL", 
  "phoneNumber" : "561-824-9105", 
  "email" : "hstrognell0@dailymail.co.uk"
}

기본 Jackon 옵션을 사용할 때 1,000명의 고객이 모두 포함된 JSON 데이터 바이트 배열의 크기는 181.0KB 입니다.

4. gzip으로 압축하기

텍스트 데이터로서 JSON 데이터는 잘 압축됩니다. 이것이 gzip 이 JSON 데이터 크기를 줄이는 첫 번째 옵션인 이유 입니다. 또한 JSON을 송수신하기 위한 공통 프로토콜인 HTTP에 자동으로 적용할 수 있습니다.

기본 Jackson 옵션으로 생성된 JSON을 gzip으로 압축해 보겠습니다 . 그 결과 원래 크기의 25.3%에 불과한 45.9KB가 생성 됩니다. 따라서 gzip 을 활성화할 수 있다면 구성을 통해 압축을 Java 코드를 변경하지 않고도 JSON 데이터 크기를 75%까지 줄일 수 있습니다!

Spring Boot 애플리케이션이 JSON 데이터를 다른 서비스나 프론트 엔드에 전달하는 경우 Spring Boot 구성에서 gzip 압축을 활성화 합니다. YAML 구문의 일반적인 압축 구성을 살펴보겠습니다.

server:
  compression:
    enabled: true
    mime-types: text/html,text/plain,text/css,application/javascript,application/json
    min-response-size: 1024

먼저 enabled 를 true 로 설정하여 일반적으로 압축을 활성화 했습니다. 그런 다음, mime-types List에 application/json추가하여 특별히 JSON 데이터 압축을 활성화했습니다 . 마지막으로 min-response-size 를 1,024바이트 길이로 설정했습니다. 짧은 양의 데이터를 압축하면 원본보다 더 큰 데이터가 생성될 수 있기 때문입니다.

NGINX 와 같은 프록시  또는 Apache HTTP Server 와 같은 웹 서버  는 JSON 데이터를 다른 서비스나 프런트 엔드에 전달하는 경우가 많습니다 . 이러한 도구에서 JSON 데이터 압축을 구성하는 것은 이 사용방법(예제)의 범위를 벗어납니다.

gzip 에 대한 이전 사용방법(예제) 에서는 gzip 에 다양한 압축 수준이 있다고 알려줍니다 . 코드 예제 에서는 기본 Java 압축 수준과 함께 gzip사용  합니다. Spring Boot, 프록시 또는 웹 서버는 동일한 JSON 데이터에 대해 다른 압축 결과를 얻을 수 있습니다.

JSON을 직렬화 프로토콜로 사용하여 데이터를 저장하는 경우 데이터를 직접 압축 및 압축 해제해야 합니다.

5. JSON의 더 짧은 필드 이름

너무 짧Map 길Map 않은 필드 이름을 사용하는 것이 가장 좋습니다. 데모를 위해 이것을 생략하겠습니다. JSON에서 단일 문자 필드 이름을 사용하지만 Java 필드 이름은 변경하지 않습니다. 이렇게 하면 JSON 데이터 크기가 줄어들지만 JSON 가독성이 낮아집니다. 모든 서비스와 프런트 엔드에 대한 업데이트도 필요하므로 데이터를 저장할 때만 다음과 같은 짧은 필드 이름을 사용할 것입니다.

{
  "i" : 1,
  "f" : "Horatius",
  "l" : "Strognell",
  "s" : "4848 New Castle Point",
  "p" : "33432",
  "c" : "Boca Raton",
  "a" : "FL",
  "o" : "561-824-9105",
  "e" : "hstrognell0@dailymail.co.uk"
}

Java 필드 이름은 그대로 두고 JSON 필드 이름을 Jackson으로 쉽게 변경할 수 있습니다. @JsonProperty 어노테이션을 사용합니다 .

@JsonProperty("p")
private String postalCode;

단일 문자 필드 이름을 사용하면 원래 크기의 72.5%인 데이터가 생성됩니다. 또한 gzip을 사용하면 이를 23.8%로 압축합니다. 이는 단순히 gzip으로 원본 데이터를 압축하여 얻은 25.3%보다 훨씬 작지 않습니다. . 우리는 항상 적절한 비용 편익 관계를 찾아야 합니다. 작은 크기의 증가로 인해 가독성을 잃는 것은 대부분의 시나리오에서 권장되지 않습니다.

6. 배열로 직렬화

필드 이름을 완전히 생략하여 JSON 데이터 크기를 더 줄일 수 있는 방법을 살펴보겠습니다. JSON에 고객 배열 을 저장하여 이를 달성할 수 있습니다 . 가독성도 감소할 예정입니다. 또한 JSON 데이터를 사용하는 모든 서비스와 프런트 엔드를 업데이트해야 합니다.

[ 1, "Horatius", "Strognell", "4848 New Castle Point", "33432", "Boca Raton", "FL", "561-824-9105", "hstrognell0@dailymail.co.uk" ]

Customer 를 어레이로 저장하면 원래 크기의 53.1%, gzip 압축의 경우 22.0%가 출력 됩니다. 이것은 지금까지 우리의 최고의 결과입니다. 그래도 22%는 원래 데이터를 gzip으로 압축하여 얻은 25.3%보다 훨씬 작지 않습니다 .

고객을 배열로 직렬화하려면 JSON 직렬화를 완전히 제어해야 합니다. 더 많은 예를 보려면 Jackson 사용방법(예제)를 다시 참조하세요 .

7. null제외

Jackson 및 기타 JSON 처리 라이브러리는 JSON을 읽거나 쓸 때 JSON null 값을 올바르게 처리하지 못할 수 있습니다 . 예를 들어 Jackson은 Java null 값을 만나면 기본적으로 JSON null 값을 씁니다 . 그렇기 때문에 JSON 데이터에서 빈 필드를 제거하는 것이 좋습니다 . 이렇게 하면 각 JSON 처리 라이브러리에 빈 값 초기화가 남겨지고 JSON 데이터 크기가 줄어듭니다.

모의 데이터에서 전화번호의 50%, 이메일 주소의 30%를 비어 있는 것으로 설정했습니다. 이러한 null 값을 생략하면 JSON 데이터 크기가 166.8kB 또는 원래 데이터 크기의 92.1%로 줄어듭니다. 그런 다음 gzip 압축은 24.9%로 떨어집니다.

이제 null 값을 무시하고 이전 섹션의 더 짧은 필드 이름과 결합하면 원래 크기의 68.3%, gzip의 경우 23.4%로 훨씬 더 많이 절약할 수 있습니다 .

Jackson에서 클래스당 또는 모든 클래스에 대해 전역적으로 null 값 필드 의 생략을 구성할 수 있습니다 .

8. 새로운 도메인 클래스

배열로 직렬화하여 지금까지 가장 작은 JSON 데이터 크기를 달성했습니다. 이를 더욱 줄이는 한 가지 방법은 필드가 더 적은 새 도메인 모델입니다. 하지만 왜 그렇게 할까요?

이름과 주소라는 두 개의 열이 있는 테이블로 모든 고객을 표시하는 JSON 데이터의 프런트 엔드를 상상해 보겠습니다. 이 프런트 엔드를 위해 특별히 JSON 데이터를 작성해 보겠습니다.

{
  "id" : 1,
  "name" : "Horatius Strognell",
  "address" : "4848 New Castle Point, Boca Raton FL 33432"
}

name 필드를 name 으로 연결 하고 address 필드를 address 로 연결한 방법에 주목하세요 . 또한, 우리는 왼쪽으로 이메일PHONENUMBER을 .

이것은 훨씬 더 작은 JSON 데이터를 생성해야 합니다. 또한 프런트 엔드가 Customer 필드 를 연결하는 것을 방지 합니다. 그러나 단점은 백엔드를 프론트엔드에 단단히 연결한다는 것 입니다.

이 프런트 엔드에 대한 새 도메인 클래스 CustomerSlim만들어 보겠습니다 .

public class CustomerSlim {
    private long id;
    private String name;
    private String address;

테스트 데이터를 이 새로운 CustomerSlim 도메인 클래스 로 변환 하면 원래 크기의 46.1%로 줄어듭니다. 기본 잭슨 설정을 사용합니다. gzip 을 사용한다면 하면 15.1%까지 내려갑니다. 이 마지막 결과는 이미 이전 최고 결과인 22.0%를 크게 상회한 것입니다.

다음으로, 한 문자 필드 이름도 사용하면 원래 크기의 40.7% 로 줄어들고 gzip 은 이를 14.7%로 추가로 줄입니다. 이 결과는 Jackson 기본 설정으로 도달한 15.1% 이상의 작은 이득입니다.

CustomerSlim의 필드 는 선택 사항이 아니므로 빈 값을 생략해도 JSON 데이터 크기에 영향을 주지 않습니다.

마지막 최적화는 배열의 직렬화입니다. CustomerSlim 을 어레이 로 직렬화 하여 최상의 결과를 얻습니다. 원래 크기의 34.2%, gzip의 경우 14.2%입니다 .따라서 압축하지 않아도 원본 데이터의 거의 2/3를 제거합니다. 압축은 JSON 데이터를 원래 크기의 1/7로 축소합니다!

9. 결론

이 기사에서는 먼저 JSON 데이터 크기를 줄여야 하는 이유를 살펴보았습니다. 다음으로 이 JSON 데이터 크기를 줄이는 다양한 방법을 배웠습니다. 마지막으로 하나의 프런트 엔드에 맞춤화된 도메인 모델을 사용하여 JSON 데이터 크기를 더 줄이는 방법을 배웠습니다.

전체 코드는 항상 그렇듯이 GitHub에서 사용할 수 있습니다 .

Jackson footer banner