DB/JPA

[Hibernate/JPA] 타입

꾸준함. 2025. 5. 29. 10:50

1. JPA/Hibernate의 타입 매핑 구조

  • JPA와 Hibernate는 Java 객체를 관계형 데이터베이스에 영속화할 때 다양한 타입 매핑 방식을 제공하며 대표적으로 다음 세 가지 범주가 있음
    • 기본 타입(Basic Types): Integer, Long, String, Float, Enum 등과 같이 데이터베이스의 단일 컬럼에 매핑되는 타입
    • 임베디드 타입(Embeddable Types): 여러 컬럼을 하나의 Java 컴포넌트로 그룹화해 매핑할 수 있음 i.g. 주소( Address)와 같은 객체가 여러 컬럼을 가질 때 사용
    • 엔티티 타입(Entity Types): 데이터베이스의 테이블과 직접적으로 매핑되는, 각각의 식별자 (Primary Key)를 가지는 객체

 

2. 컬럼 타입의 컴팩트함이 중요한 이유

  • 데이터베이스에서 동일한 페이지 (메모리 또는 디스크 단위)에 더 많은 행을 저장할 수 있음
  • 인덱스와 자주 사용되는 테이블 페이지가 메모리에 더 잘 적재됨
  • 대용량 데이터 처리 시 성능과 확장성, 비용 측면에서 매우 중요함
    • i.g. 동일한 정보를 1바이트 (tinyint)로 저장할 수 있는데도 8바이트 (varchar 8)로 저장하면 메모리, 디스크, 네트워크 효율이 저하됨

 

3. Java Enum을 매핑하는 여러 전략

  • JPA와 Hibernate에서 @Enumerated 어노테이션을 사용해 Enum 매핑 전략을 선택할 수 있음

 

3.1 EnumType.STRING

  • Enum의 이름 (문자열 값, 예: "PENDING")이 데이터베이스 컬럼에 저장
  • 가독성이 높고, 데이터만 보고도 의미를 쉽게 파악할 수 있음
  • 단점은, enum 값이 길수록 더 큰 varchar 컬럼이 필요하고, 공간이 비효율적일 수 있음

 

 

3.2 EnumType.ORDINAL

  • Enum의 순서 (ordinal, 0부터 시작하는 숫자)가 데이터베이스 컬럼에 저장
  • 매우 컴팩트 (i.g. tinyint로 1바이트 사용 가능), 인덱스/저장 효율 최상
  • 단점은 숫자만 보면 의미를 알 수 없음 (설명력이 떨어짐), Enum 순서 변경 시 데이터 불일치 위험

 

 

3.3 EnumType.ORDINAL + 설명 테이블 조합

  • 효율성과 설명력을 모두 확보하는 방법
  • Enum ordinal 값과 이름/설명을 매핑하는 별도 테이블 (PostStatusInfo 등)을 생성
  • Post 엔티티에서 status 컬럼은 숫자로 저장, statusInfo와 다대일 연관관계로 의미까지 조회 가능
    • statusInfo 테이블: id(ordinal), name, description 등

 

 

4. PostgreSQL ENUM 타입 활용 및 Hibernate 연동

  • PostgreSQL은 사용자 정의 ENUM 타입을 지원
  • ENUM 타입은 문자열처럼 보이지만 내부적으로 4바이트로 저장됨
  • Java Enum과 PostgreSQL ENUM 매핑을 위해 Hibernate 커스텀 타입이 필요함

 

 

5. Hibernate 커스텀 타입의 필요성

  • Hibernate는 다양한 내장 타입 지원을 제공하지만, 실제 현업에서는 종종 기본 타입만으로는 충분하지 않을 수 있음
    • i.g. IPv4/IPv6 주소, JSON, 배열, 복합 구조 등 데이터베이스 고유 타입을 완벽하게 매핑하려면 커스텀 타입 필요

 

  • 적절한 데이터베이스 타입을 선택하면 데이터 접근 성능이 크게 향상됨
  • Hibernate는 개발자가 직접 새로운 Type을 손쉽게 추가할 수 있도록 유연한 확장 구조를 제공

 

5.1 IPv4 주소 저장 방식 예시

  • IPv4 주소(예: 192.168.123.231/24)를 데이터베이스에 저장하는 방법은 여러 가지가 있음
    • BIGINT 또는 NUMERIC(15): 4바이트(IP) + 1바이트(서브넷 마스크)를 합쳐 5바이트 정보 저장 가능하지만 비트 연산, 변환 로직이 필요해 개발 난이도가 높고, 가독성이 떨어질 수 있음
    • VARCHAR(18): 사람이 읽기 쉬운 문자열(최대 18자)로 저장, 접근성과 변환은 쉽지만 공간 효율이 떨어짐
    • 데이터베이스 고유 타입: PostgreSQL의 inet 혹은 cidr 타입은 네트워크 주소 전용으로 설계되어 7바이트로 저장하며,
      주소 비교, 포함, 변환 등 다양한 연산자와 함수 지원
      • i.g. host(inet), netmask(inet), <, >, && 

 

PostgreSQL inet 타입과 Hibernate 커스텀 타입 구현

  • PostgreSQL의 inet 타입은 IPv4/IPv6를 효율적으로 저장할 수 있으며, 다양한 네트워크 연산을 데이터베이스 레벨에서 바로 수행할 수 있음
  • Hibernate에서 PostgreSQL inet 타입을 완벽하게 활용하려면, 커스텀 타입을 직접 구현해야 함


 

부연 설명

  • 커스텀 타입을 통해 Hibernate/JPA에서 PostgreSQL INET 컬럼과 완벽하게 매핑
  • GIST 인덱스를 사용하면 네트워크 연산(<<=, >>=, && 등)도 효율적으로 실행
  • JPQL/Criteria, Native Query 모두에서 커스텀 타입 안전하게 사용 가능
  • 주소, 네트워크 마스크 추출 등 PostgreSQL 함수 (host(ip), netmask(ip) 등)도 활용 가능

 

참고

인프런 - 고성능 JPA & Hibernate (High-Performance Java Persistence)

 

반응형