[Spring] Spring 3.X에서 jsonb 자료형 사용하기

2023. 2. 19. 21:55BackEnd/Java - Spring


json 자료형이란?

json이라는 자료형은 2011년대 부터 사용되어왔다는데 10년이 지난 지금도 가장 많이 사용하는 자료형이라는 사실은 틀림없다고 생각합니다. Json의 형태는 Key와 Value의 값으로 채워져 있는 형태이며, 직관적으로 데이터를 확인할  수 있다는 점이 장점입니다.

 

jsonb 자료형이란?

이런 json 형태를 DB 컬럼의 데이터 타입으로 사용하면 어플리케이션을 개발함에 있어 편리하지 않을까하는 접근으로 postgresql에서 제공하는 데이터 타입입니다. 기존 json 자료형을 text 형태로 DB에 저장하는 것이 아닌, DB 내부에서 key - value 형태로 관리를 할 수 있도록 하자는 접근으로 만든 데이터 타입이라고 합니다.

 

json과 jsonb를 비교하면...

  JSON JSONB
저장방식 텍스트로 json 값 그대로 저장 바이너리 포맷으로 저장. 이 과정에서 key-value 형태로 변환하며 형변환과 정렬 등 가공처리가 됨
장점 쓰기의 장점 읽기의 장점. 인덱싱이 가능함
단점 데이터를 읽고 별도로 해석을 해야된다.
어플리케이션에서 별도 파싱이 필요함
쓰기 비용이 json에 비해 크다

 

위 내용은 Postgresql.kr의 블로그 내용을 정리해 보았습니다. 연산 및 인덱싱 관련해서는 블로그를 참고하는 것이 더 정확합니다. 이번 포스팅에서는 Spring 프로젝트에서 jsonb를 어떻게 적용하는 것인지 정도만 정리하려고 합니다.

 


Spring에서 jsonb 사용하기

Spring에서 jsonb를 사용하기 위해서는 의존성을 추가해줘야 합니다. 다만 이 때 Spring Version에 따라서 Hibernate 버전 차이가 발생하는데 그에 따라서 추가해주는 의존성도 다른 의존성을 추가해야 합니다. 그리고 사용법도 조금 차이가 납니다.

 

제가 생성한 Spring 3.2 버전, hibernate-core 6.1.6을 사용하는 상황입니다. spring JPA 의존성관련 내용을 확인해보면 core가 어떤 버전이 적용 되는지 확인이 가능합니다. 저의 경우 아래 의존성을 추가하였습니다.

implementation 'io.hypersistence:hypersistence-utils-hibernate-60:3.2.0'

버전별로 어떤 라이브러리를 추가해야 되는지는 해당 링크를 참고하면 됩니다. 해당 블로그에서 버전별로 installing guide를 주고 있습니다. 해당 내용만 발췌하면 아래와 같습니다.

 

Introduction

The Hypersistence Utils project gives you general-purpose utilities for both Spring and Hibernate.

The main advantage of this project is that it supports a broad range of Hibernate versions, spanning from Hibernate ORM 6.1 to 6.0, 5.6, 5.5, 5.4, 5.3, 5.2, 5.1, and Hibernate 5.

Installation Guide

Depending on the Hibernate version you are using, you need to add the following dependency:

Hibernate 6.1 and 6.0

<dependency>
    <groupId>io.hypersistence</groupId>
    <artifactId>hypersistence-utils-hibernate-60</artifactId>
    <version>3.2.0</version>
</dependency>

Hibernate 5.6 and 5.5

<dependency>
    <groupId>io.hypersistence</groupId>
    <artifactId>hypersistence-utils-hibernate-55</artifactId>
    <version>3.2.0</version>
</dependency>

Hibernate 5.4, 5.3 and 5.2

<dependency>
    <groupId>io.hypersistence</groupId>
    <artifactId>hypersistence-utils-hibernate-52</artifactId>
    <version>3.2.0</version>
</dependency>

Hibernate 5.1 and 5.0

<dependency>
    <groupId>io.hypersistence</groupId>
    <artifactId>hypersistence-utils-hibernate-5</artifactId>
    <version>3.2.0</version>
</dependency>

 

 


Spring Project에서  jsonb 타입 사용하기

의존성 관련 설정이 완료가 되었다면 해당 링크를 참고하여 사용하면됩니다. 버전에 따라 TypeDef 어노테이션을 사용하는 것인지, Type 어노테이션을 사용하는지 차이가 있습니다.

 

제가 생성한 Spring 3.2 버전, hibernate-core 6.1.6을 사용하는 상황에서의 예시입니다. Article(게시글), Review(댓글) 엔터티를 보겠습니다.

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Getter
@Where(clause = "deleted = false")
public class Article extends BaseTimeEntity {

  @Id
  @GeneratedValue(strategy = GenerationType.UUID)
  private UUID id;
  private UUID boardId;
  private String title;
  private String content;
  private String imageUrl;

  @JdbcTypeCode(SqlTypes.JSON)
  @Setter
  private Review review;

  private Article(UUID boardId, String title, String content, String imageUrl) {
    this.boardId = boardId;
    this.title = title;
    this.content = content;
    this.imageUrl = imageUrl;
  }

  public static Article of(UUID boardId, String title, String content, String imageUrl) {
    return new Article(boardId,title, content, imageUrl);
  }
}

 

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@ToString
public class Review {
  private UUID id;
  private String title;
  private String contents;
}

 

Review라는 클래스를 jsonb 타입으로 저장하는 방식입니다. Hibernate 6에서는 @JdbcTypeCode annotation을 선언하고 타입을 SqlTypes.JSON으로 설정해주면 됩니다.

 

Article을 조회하면 jsonb 형태로 저장된 데이터는 Review class의 멤버변수에 자동으로 매핑이 되어 편리하게 사용할 수 있습니다.

 

 


언제 사용하면 좋을까? 장단점( 개인적인 생각 )

Json 형태는 MySQL에서도 5.7 부터 지원을 하고있고 Postgresql도 9.7 버전부터는 jsonb를 지원하고 있습니다. 많이 쓰이긴 하나봅니다.

 

예전에 nestjs를 공부하면서 테이블 설계가 확정되지 않거나, 데이터 값이 유동적인 경우에 json 형태로 데이터를 가공하여 string 형태로 DB에 저장한 경험이 있습니다. 이럴 경우 불편했던 것이 key 값의 종류가 늘어날 경우 어플리케이션에서 이를 파싱하는 로직을 다 추가해주어야 했는데, 이를 hibernate에서 자동화 해준다면 jsonb를 사용하는 것이 훨씬 좋은 것 같습니다.

 

그리고 일단 이렇게 데이터를 다루면 매우 편하다는 생각이 듭니다.

 

다만 반대로 단점도 명확합니다. 먼저 데이터의 정규화를 너무 깨뜨리는 것이 아닌가 하는 생각이 들었습니다.

그리고 QueryDsl과 같은 다른 의존성을 추가하여 쿼리를 실행하는 경우 원하는대로 동작이 안되거나, 사용이 힘든 경우도 있었다는 사례를 보았습니다. ( 물론 제가 사용하는 지금 시점에는 큰 문제는 안되는 듯하네요. )

 

 


결론

현업의 비즈니스 형태에 맞춰서 적절하게 잘 쓰자!