Skip to main content

Command Palette

Search for a command to run...

[Spring]@ElementCollection

Updated
4 min read
[Spring]@ElementCollection
S

Nice to meet u :) Im Backend Developer

✍️ 작성하게 된 이유

프로젝트를 진행하다가 RDB안에 List를 저장해야하는 상황이 발생했다. ElementCollection과 Jsonb를 고민하는 과정에서 ElementCollection에 대해 정리해보고자 한다.

값 타입은 몇 가지 주의할 점이 있으며, 잘못 사용하면 사이드 이펙트가 발생할 수 있다.

이번 글에서는 JPA에서의 값 타입 개념, 분류, 사용 예시, 주의사항, 그리고 실전 설계 팁까지 담아보았다.


💡 값 타입이란?

값 자체에 의미가 있으며, 식별자 없이 사용하는 타입

  • 자바의 int, String, Integer와 같은 기본형

  • 여러 값을 묶은 사용자 정의 타입인 임베디드 타입

  • 리스트, 셋 등 컬렉션 형태로 사용하는 값 타입 컬렉션


📌 값 타입 분류

1️⃣ 기본 값 타입

  • Java의 기본형 (int, double, boolean)

  • 래퍼 클래스 (Integer, Long, Double 등)

  • String

✅ 특징

  • 엔티티 내부에서 사용되며 생명주기를 공유

    • ex) 회원 삭제하면 이름, 나이 필드도 삭제
  • 값 타입은 절대 공유하면 안된다.

    • Side Effect → 참조를 공유하게 되면 예기치 않은 동시 변경이 발생할 수 있음

⚠️ 참고

  • 자바의 기본타입은 항상 값을 복사하여 사용하기 때문에 절대 공유 되지 않는다.

  • 래퍼클래스나 String은 주소값을 복사하여 사용하기 때문에 같은 장소를 가리키게 된다. 따라서, 하나를 수정하면 주소값이 공유된 객체도 수정된다.

    • 래퍼클래스나 String에는 setValue메서드가 존재하지 않는다. 따라서 공유가능한 객체지만 변경할 수 없다.

2️⃣ 임베디드 타입 (Embedded Type)

여러 값을 묶어 새로운 값 타입을 직접 정의

기본 값 타입을 모아 만들어 복합 값 타입
@Embeddable : 값 타입을 정의하는 곳에 표시

@Embedded: 값 타입을 사용하는 곳에 선언

✅ 장점

항목설명
재사용성여러 엔티티에서 공통으로 사용 가능
높은 응집도관련 필드를 하나의 타입으로 묶어 표현
객체지향적 설계해당 값 타입만 사용하는 의미 있는 메서드 추가 가능 (예: isWithinRange())

⚠️ 주의 : 임베디드 타입 공유에 따른 사이드 이펙트

👉 이렇게 공유하면 JPA는 업데이트 쿼리를 두 번 날리고, 두 객체의 상태가 의도치 않게 함께 변경


🧩 값 타입의 설계 팁

  • Embedded 타입은 기본 생성자 필수 (보통 protected)

  • 같은 임베디드 타입 2번 이상 사용할 땐 컬럼명이 겹치기 때문에 @AttributeOverrides 로 재정의

  • 테이블 수 < 클래스 수
    → 객체 모델은 더 세밀하게 나누는 것이 잘 설계된 ORM구조

    → 테이블 생성 쿼리는 임베디드를 사용하지 않을 때와 같다.(=매핑하는 테이블은 같다)


✅ 불변 객체(Immutable Object) 설계

값 타입의 공유 참조 문제를 해결하기 위해 내부 값을 변경할 수 없도록 설계

  • setXxx() 제거

  • 모든 필드는 final (선택)

  • 생성자만으로 초기화

🧠 equals & hashCode 꼭 재정의

값 타입은 동등성(equality) 기준으로 비교해야 함
== 대신 .equals() 활용


3️⃣ 컬렉션 값 타입(collection value type)

  • Java collection(Array, Map, Set)에 값을 넣을수 있는 것을 컬렉션 값 타입이라 한다.

값 타입 컬렉션 ElementCollection

값 타입(Value Object) 을 List, Set, Map 등의 컬렉션으로 관리하고, 별도의 테이블에 저장하는 JPA 기능

  • 한 개의 값 타입 컬렉션당 1개의 테이블 생성

  • 컬렉션마다 별도의 테이블 필요 (하나의 테이블에 여러 컬렉션은 불가)

📌 특징

항목설명
생명주기엔티티에 종속 (영속성 전이 + 고아 객체 처리됨)
저장방식별도 테이블에 저장(엔티티는 아님)
추적 방식변경 시 전체 삭제 후 다시 INSERT( 즉, 쿼리 2~N개 발생)
로딩 방식컬렉션은 지연 로딩 (Lazy)

⚠️ 한계

  • 컬렉션 내부 값이 바뀌면 전체 삭제 후 다시 저장

  • equals / hashCode가 정확히 구현되어야 remove 작동

  • 값타입은 식별자 개념이 없기 때문에 값의 변경을 JPA가 추적할 수 없음 → 객체 갈아끼우기 방식 사용

💡 값 타입 컬렉션의 한계 → 엔티티로 승격

위 한계 때문에 실무에서는 사용하지 않는 것을 추천한다.

실무에서는 추적, 수정, 식별이 필요하면 일대다 관계를 고려한다.

일대다 관계를 위한 엔티티르 만들고 여기에서 값 타입을 사용한다.

✅ 결론

값 타입은 언제 사용?언제 쓰면 안 됨?
단순하고 불변일 때자주 변경, 식별 필요, 참조 공유할 가능성 있을 때

1. 엔티티 타입의 특징

  • 식별자가 있다

  • 생명 주기 관리(값 타입은 생명주기 관리를 주도적으로 할 수 없다.)

  • 공유

2. 값 타입의특징

  • 식별자가 없다

  • 생명 주기를 엔티티에 의존

  • 공유하지 않는 것이 안전(복사해서 사용)

  • 불가피하게 공유가 필요할 때 불변 객체로 만드는 것이 안전

참고자료

https://ttl-blog.tistory.com/121

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

https://s-y-130.tistory.com/284?category=1065584

https://s-y-130.tistory.com/283

More from this blog

[Spring] N+1문제 발생과 분석

✍️ 작성하게 된 이유 옷을 관리하는 서비스를 개발하면서 Cloth 엔티티와 그에 연관된 ClothWithAttributes, Attribute 데이터를 함께 조회하는 기능이 필요했다.그런데 연관 데이터를 조회할 때마다 쿼리가 폭발적으로 증가(N+1 문제) 하며, 성능이 급격히 저하되는 상황을 마주하게 되었다. Spring JPA의 대표적인 문제로 N+1임을 알고있었지만, 해결하는 방법은 Fetch Join밖에 몰랐다. 지연로딩되는 필드를 엔티...

Sep 17, 20256 min read
[Spring] N+1문제 발생과 분석

데이터베이스 기본 개념 정리

1️⃣ 데이터베이스(DB) & DBMS DB (Database): 일정한 규칙(스키마)에 따라 구조화되어 저장된 데이터의 집합. DBMS (Database Management System): DB를 제어/관리하는 시스템 소프트웨어. 특징: 실시간 접근 가능, 동시 공유 가능. 구조: 데이터베이스 → DBMS → 응용 프로그램 → 사용자 2️⃣ 엔티티(Entity) & 릴레이션(Relation) 엔티티: 여러 속성을 가진 "개체"...

Aug 5, 20252 min read
데이터베이스 기본 개념 정리

[Project] 날씨에 맞는 옷 추천 서비스 : 지그재그 크롤링 여정 기록 (1) ChromeDriver를 EC2에 설치하기

✍️ 작성하게 된 이유 무신사, 29cm는 Jsoup으로 충분히 크롤링이 가능했기 때문에, ZigZag도 당연히 Jsoup으로 처리될 것이라 생각했다. 무신사, 29cm와 마찬가지로 필요한 데이터는 모두 <script> 태그 안에 들어있었다. 하지만… 예상은 보기 좋게 빗나갔다. 🧪 현상 ✅ 로컬 크롤링 → 정상 작동 Jsoup으로 script 태그 내에서 대표 이미지와 상품명을 잘 추출 로컬 환경에서는 아무 문제 없이 작동 ❌ A...

Jul 30, 20253 min read
[Project] 날씨에 맞는 옷 추천 서비스 : 지그재그 크롤링 여정 기록 (1) ChromeDriver를 EC2에 설치하기

[Project] 날씨에 맞는 옷 추천 프로젝트: Selenium은 정말 필요한 선택이었을까? - 크롤링 삽질 기록

✍️ 작성하게 된 이유 날씨에 따라 옷을 추천해주는 서비스를 만들면서, 사용자가 입력한 구매 링크에서 옷 정보( 대표이미지, 상품명 )를 불러오는 기능이 필요했다. 처음에 해당 페이지를 동적 페이지로 판단했고, 자연스럽게 Selenium을 도입했다. 하지만 이 결정이 과연 최선이었는지는 수많은 시행착오 끝에야 알 수 있었다. 🕸️ Selenium을 선택한 이유 동적 페이지는 Jsoup으로 크롤링이 어렵다는 인식으로 처음부터 Selenium을 ...

Jul 28, 20254 min read
[Project] 날씨에 맞는 옷 추천 프로젝트: Selenium은 정말 필요한 선택이었을까? - 크롤링 삽질 기록

Soyulia's Blog

49 posts