티스토리 뷰

반응형

언제 JSON으로 데이터를 말아서 저장하면 좋은가?

 

저장될 데이터 구조의 변동성이 낮다면 일반적인 자료형으로 데이터를 저장하는 것이 바람직하다. 

하지만 RDB를 사용하며, 데이터가 1. 비정형 데이터이거나 2. Key-Value 형태로의 저장이 적절하며 3. JSON으로 묶인 데이터의 세부 내용을 각각 참조할 상황이 적다면

NoSQL을 사용하지 않는 경우에도 해당 데이터를 JSON으로 저장하는 것이 적절할 수 있다.

 

JSON 사용을 위한 Hypersistence-utils 의존성 추가하기

 

JPA에서 JSON 형태의 자료를 DB Column에 삽입하기 위해서는 별도의 의존성이 필요하다.

다음에 설명할 기술은 JPA의 구현체인 hibernate에만 부가적으로 사용 가능한 기능이므로

hibernate를 사용하지 않는다면 적용할 수 없다.

 

 

본인의 프로젝트에서 사용 중인 hibernate 구현체의 버전을 확인하고 그에 맞는 hypersistence-utils를 추가해야 한다.

 

Spring Boot 2.7이 사용하는 hibernate 5.6에서는 hypersistence 55:3.5.0이 호환된다.

https://github.com/vladmihalcea/hypersistence-utils

 

GitHub - vladmihalcea/hypersistence-utils: The Hypersistence Utils library (previously known as Hibernate Types) gives you Sprin

The Hypersistence Utils library (previously known as Hibernate Types) gives you Spring and Hibernate utilities that can help you get the most out of your data access layer. - GitHub - vladmihalcea/...

github.com

 

위의 페이지에서 호환되는 버전을 찾아볼 수 있다.

 

 

JSON을 사용하는 Entity 만들기

 

@Entity
@TypeDef(name = "json", typeClass = JsonType.class)
public class JsonEntity {

    @Id
    @GeneratedValue
    private Long id;

    @Type(type = "json")
    @Column(name = "answers", columnDefinition = "longtext")
    private Map<String, String> answers = new HashMap<>();

}

 

hypersistence-utils 의존성을 추가했다면 @TypeDef를 통해 사용자 정의된 JsonType의 사용이 가능해진다.

해당 칼럼에 들어갈 데이터는 위와 같이 Map을 사용해 Key-Value 형태로 데이터를 저장하면 된다.

 

추가로, 최신 버전의 hypersistence-utils를 사용할 땐 사용법이 아래와 같이 @Type에 바로 지정하도록 변화하였다.

(Hibernate 6.2, Hypersistence-utils 62:3.5.0에서 확인)

 

@Entity
public class JsonEntity {

    @Id
    @GeneratedValue
    private Long id;

    @Type(JsonType.class)
    @Column(name = "answers", columnDefinition = "longtext")
    private Map<String, String> answers = new HashMap<>();

}

 

 

데이터 저장

 

위의 JsonEntity 클래스를 사용해 생성되는 테이블과 데이터가 저장되는 과정을 아래처럼 확인할 수 있다.

 

 

편의를 위해 Spring Data JPA를 사용한 간단한 Repository를 만들었으며 JsonEntity에 answers를 생성자에서 초기화하도록 하였다.

아래와 같은 코드를 통해 entity가 저장되는 모습을 볼 수 있다.

 

@DataJpaTest
class JsonEntityTest {

    @Autowired
    JsonEntityRepository jsonEntityRepository;

    @PersistenceContext
    EntityManager em;

    @Test
    void test() {
        Map<String, String> answers = new HashMap<>();
        answers.put("Question1", "Answer1");
        answers.put("Question2", "Answer2");

        JsonEntity jsonEntity = new JsonEntity(answers);
        jsonEntityRepository.save(jsonEntity);
        em.flush();
        em.clear();
    }
}

 

Application에서 직렬화 / 역직렬화할 때 단순 텍스트와 Map 간의 변화가 일어난다.

 

이제 Application 내에서 데이터를 Key-Value 형태로 다룰 수 있으며 비교적 대응이 어려운 RDB의 Column 변동보다

Application에서 Map을 유연하게 다루어 대처가 가능해진다.

 

 


 

이외의 방법들이 있는 것으로 알고는 있으나 위에서 설명한 Hypersistence-utils 라이브러리가 현재는 사용자도 많고 가장 지원이 꾸준하게 되는 라이브러리인 듯하다.

직렬화, 역직렬화 과정에서 이 라이브러리가 성능적으로도 충분한지는 별도로 언급돼있지는 않았다.

반응형