View Table + JPA

손병주·2024년 11월 24일

들어가며

회사 프로젝트를 진행하면서 여러 테이블의 데이터를 조합해 통계 자료나 조회성 데이터를 제공해야 하는 경우가 자주 있었습니다.

일반적으로 서비스 개발 과정에서는 여러 테이블에서 findByXXX 등을 이용해 데이터를 추출하고 이를 애플리케이션 단에서 조합하거나, Join을 활용해 한 번에 데이터를 조회하는 방식으로 처리해왔습니다.

하지만 배치성 데이터나 변하지 않는 통계성 데이터, 혹은 결합 데이터를 다룰 때, 이러한 방식이 효율적이지 않다는 의문이 들었습니다. 특히, 애플리케이션에서 N개의 테이블을 단일 조회하거나 Join으로 결합 데이터를 만들어내는 방식이 과연 적합한지, 그리고 Spring Boot 서버에서 이러한 불필요한 작업을 어떻게 줄일 수 있을지 고민하게 되었습니다.

이 과정에서 회사 동료분들께서 View Table을 활용해보라는 조언을 해주셨고, 이를 통해 View를 JPA와 함께 사용할 수 있을까? 라는 궁금증이 생겼습니다.

오늘은 View Table과 JPA를 활용하는 방법에 대해 소개하려고 합니다.

View Table

란 가상의 테이블이다.
테이블과 동일하게 보이지만, 실제 행 데이터를 가지고 있지 않다.
실체는 없지만, 진짜 테이블에 링크(Link)된 개념이다.

위 개념과 같이 View Table은 실제 물리적 데이터를 가지고 있는 테이블이 아닌 타 테이블에서 데이터들을 연결지어 테이블을 가상으로 만들어 데이터를 보고 쓸 수 있는 것입니다. 그 뿐만 아니라 물리적 테이블에 있는 데이터를 필터와 같이 이용하여 외부노출에 취약한 데이터를 숨길 수도 있습니다.

그렇기 때문에 여러 개의 테이블을 조합한 형태로 테이블을 구축하여 개발자가 여러 도메인적인 조합을 일으키지 않아도 단순 쿼리를 통해 테이블을 조회할 수 있는 것입니다.

JPA와 함께 사용하기

사용 방법은 기존 테이블 생성 시와 같이 Model을 추가하면 됩니다.

@Entity
@Table(name = "view_member")
@Getter
public class ViewMember {
    @Id
    @Column(name = "member_id")
    private Long memberId;

    @Column(name = "name")
    private String name;
}

다만 View Table은 조회성 테이블이기에 Read 작업이 아닌 Write 작업은 꺼두어야 되는데요. 이런 Write 작업을 막기 위해 Hibernate는 @Immutable 이란 어노테이션을 제공해주고 있습니다.

@Immutable

공식 문서에 따르면, 리소스에 올라간 데이터를 변경하려고 시도할 경우 HibernateException이 발생하며, 이는 Persistence Context에서 영속화를 시키지 않아 데이터 변경을 허용하지 않기 때문입니다.

이러한 특성 덕분에 View Table의 성격에 잘 맞는 어노테이션이라 할 수 있습니다.

사내 프로젝트에서는 데이터베이스에 View Table을 먼저 선언한 후, 이를 통해 데이터를 조회하고 사용하였으며, 이러한 방식만으로도 충분히 요구 사항을 충족할 수 있었습니다.

JPA에서는 View Table과 유사한 기능을 제공하기 위해 @Subselect 어노테이션을 지원합니다.

  • @Subselect는 데이터베이스에 실제 View Table이 선언되어 있지 않아도, 선언한 것처럼 사용할 수 있게 만들어주는 어노테이션입니다. 이를 통해 View Table의 역할을 코드 수준에서 구현할 수 있습니다.

@Subselect

@Entity
@Table(name = "view_member")
@Getter
@Immutable
@Subselect("""
    SELECT m.member_id, m.name
    FROM Member m left join Board b on m.member_id = b.upload_member
    WHERE b.createAt > '2024-11-22'
""")
@ToString
public class ViewMember {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long memberId;

    @Column(name = "name")
    private String name;
}

JPQL을 이용하여 개발자가 SELECT 조건을 설정을 해주면 Model로 사용할 수 있게끔 만들어준 것입니다.

하지만 개인적으로 하드코딩으로 되어있는 JPQL 특성상 관리 포인트(DB 변경점, 문법적 오류 등)가 늘어날 수 있다는 점에서 크게 사용하진 않을 듯 합니다.

마무리

테이블 간 결합을 하여 보여줘야 되는 경우 어느때나 종종 발생할 것이라고 봅니다.

View Table 이란 개념을 애플리케이션 단에서도 녹여 사용할 수 있다는 것을 필자는 크게 생각치 못하였습니다.

저는 View Table이 그저 개발자가 데이터 확인을 편하게 하기 위한 DBMS에서 제공한 경우라고만 생각했거든요..

이번 기회를 통해 View Table의 활용법을 명확히 이해하게 되었습니다. 특히, 애플리케이션 단에서 View Table을 활용하여 간단한 조회 데이터를 제공하는 방법을 알게 되어, 더 간결하고 효율적인 코드를 작성할 수 있을 것 같습니다.

profile
개발자. 근데 이제 글쓰기를 곁들인.

0개의 댓글