Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
Tags
- Java
- 환급챌린지
- KDT
- 오블완
- UXUI기초정복
- Be
- 백준
- mysql
- OPENPATH
- 오픈챌린지
- 국비지원교육
- baekjoon
- 디자인챌린지
- 티스토리챌린지
- Spring
- 디자인강의
- 백엔드 부트캠프
- 객체지향
- UXUI챌린지
- 디자인교육
- 패스트캠퍼스
- 국비지원
- 국비지원취업
- 내일배움카드
- JPA
- 백엔드개발자
- UXUIPrimary
- 자바
- 부트캠프
- 오픈패스
Archives
- Today
- Total
군만두의 IT 개발 일지
[스터디10] 08. 프록시와 연관관계 관리 본문
목차
8장. 프록시와 연관관계 관리
- 프록시와 즉시로딩, 지연로딩
- 영속성 전이와 고아 객체
8.1 프록시
- 엔티티를 조회할 때 연관된 엔티티들이 항상 사용되는 것은 아니다. 예를 들어, 회원 엔티티를 조회활 때 회원과 연관된 팀 엔티티까지 데이터베이스에서 조회하는 것은 비효율적이다.
- 따라서 JPA는 엔티티가 실제 사용될 때까지 데이터베이스 조회를 지연하는 지연 로딩 방법을 제공한다.
- 지연 로딩 기능을 사용하려면 실제 엔티티 객체 대신에 데이터베이스 조회를 지연할 수 있는 가짜 객체인 프록시 객체가 필요하다.
8.1.1 프록시 기초
JPA에서 식별자로 엔티티 하나를 조회할 때는 EntityManager.find()를 사용한다.
- EntityManager.find(): 영속성 컨텍스트에 엔티티가 없으면 데이터베이스를 조회한다.
- EntityManager.getReference(): 엔티티를 실제 사용하는 시점까지 데이터베이스 조회를 미룬다. JPA는 데이터베이스를 조회하지 않고 실제 엔티티 객체도 생성하지 않는 대신에 프록시 객체를 반환한다.

프록시의 특징
- 프록시 클래스는 실제 클래스를 상속 받아서 만들어지므로 실제 클래스와 겉 모양이 같다. 그래서 == 비교 대신 instanceof를 사용해야 하는 경우도 있다.
- 프록시 객체는 실제 객체에 대한 참조를 보관한다.
- 프록시 객체의 메소드를 호출하면 프록시 객체는 실제 객체의 메소드를 호출한다.
- 프록시 객체는 처음 사용할 때 한 번만 초기화된다. 프록시 객체가 초기화되면 프록시 객체를 통해서 실제 엔티티에 접근할 수 있다.
- 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 데이터베이스를 조회할 필요가 없으므로 em.getReference()를 호출하면 실제 엔티티를 반환한다.
- 초기화는 영속성 컨텍스트의 도움을 받아야 가능하다. 준영속 상태의 프록시를 초기화하면 LazyInitializationException 문제가 발생한다.
8.1.2 프록시와 식별자
엔티티를 프록시로 조회할 때 식별자(PK) 값을 파라미터로 전달하는데 프록시 객체는 이 식별자 값을 보관한다.
- 엔티티 접근 방식을 프로퍼티(@Access(AccessType.PROPERTY))로 설정한 경우, 식별자 값을 조회하는 메소드를 호출해도 프록시를 초기화하지 않는다.
- 엔티티 접근 방식을 필드(@Access(AccessType.FIELD))로 설정하면 JPA는 해당 메소드가 어떤 일을 하는지 알지 못하므로 프록시 객체를 초기화한다.
8.1.3 프록시 확인
- JPA가 제공하는 PersistenceUnitUtil.isLoaded(Object entity) 메소드를 사용하면 프록시 인스턴스의 초기화 여부를 확인할 수 있다.
- 조회한 엔티티가 진짜 엔티티인지 프록시로 조회한 것인지 확인하려면 클래스명을 직접 출력해보면 된다.
8.2 즉시 로딩과 지연 로딩
JPA는 개발자가 연관된 엔티티의 조회 시점을 선택할 수 있도록 두 가지 방법을 제공한다.
- 즉시 로딩: 연관된 엔티티를 즉시 조회한다. 하이버네이트는 가능하면 SQL 조인을 사용해서 한 번에 조회한다.
- 설정 방법: @ManyToOne(fetch = FetchType.EAGER)
- 지연 로딩: 연관된 엔티티를 프록시로 조회한다. 프록시를 실제 사용할 때 초기화하면서 데이터베이스를 조회한다.
- 설정 방법: @ManyToOne(fetch = FetchType.LAZY)

8.3 지연 로딩 활용
8.3.2 JPA 기본 페치 전략
- JPA의 기본 페치(fetch) 전략은 연관된 엔티티가 하나면 즉시 로딩을, 컬렉션이면 지연 로딩을 사용한다.
- 저자는 모든 연관관계에 지연 로딩을 사용하는 것을 추천한다. 그리고 필요한 곳에만 즉시 로딩을 사용하도록 최적화한다.
8.3.3 컬렉션에 FetchType.EAGER 사용 시 주의점
- 컬렉션을 하나 이상 즉시 로딩하는 것은 권장하지 않는다.
- 컬렉션 즉시 로딩은 항상 외부 조인(OUTER JOIN)을 사용한다.
FetchType.EAGER 설정과 조인 전략
- @ManyToOne, @OneToOne
- (optional = false): 내부 조인
- (optional = true): 외부 조인
- @OneToMany, @ManyToMany
- (optional = false): 외부 조인
- (optional = true): 외부 조인
8.4 영속성 전이: CASCADE
- 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶으면 영속성 전이(transitive persistence) 기능을 사용한다.
- JPA는 CASCADE 옵션으로 영속성 전이를 제공한다. 영속성 전이를 사용하면 부모 엔티티를 저장할 때 자시 엔티티도 저장할 수 있다.
- JPA에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태여야 한다.

8.4.1 영속성 전이: 저장
- 부모를 영속화할 때 cascade = CascadeType.PERSIT 옵션을 설정하면 부모와 자식 엔티티를 한 번에 영속화할 수 있다.
- 영속성 전이는 연관관계를 매핑하는 것과는 관련 없이 엔티티를 영속화할 때 연관된 엔티티도 영속화하는 편리함을 제공할 뿐이다.
8.4.2 영속성 전이: 삭제
- CascadeType.REMOVE로 설정하고 부모 엔티티를 삭제하면 연관된 자식 엔티티도 삭제된다.
- CascadeType.REMOVE를 설정하지 않고 부모 엔티티만 삭제하면 자식 테이블의 외래키 제약조건으로 인해 데이터베이스에서 예외가 발생한다.
8.4.3 CASCADE의 종류
public enum CascadeType {
ALL, // 모두 적용
PERSIST, // 영속
MERGE, // 병합
REMOVE, // 삭제
REFRESH, // REFRESH
DETACH // DETACH
}
8.5 고아 객체
- 고아 객체(ORPHAN) 제거: JPA는 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동을 삭제한다.
- 고아 객체 제거는 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능이다. 따라서 참조하는 곳이 하나일 때만 사용해야 한다.
- orphanRemovel은 @OneToOne, @OneToMany에만 사용할 수 있다.
- 고아 객체 제거에서 부모를 제거하면 자식은 고아가 되어 자식이 같이 제거된 것(CascadeType.REMOVE를 설정한 것)과 같다.

8.6 영속성 전이 + 고아 객체, 생명주기
CascadeType.ALL + orphanRemoval = true를 동시에 사용하면 부모 엔티티를 통해 자식의 생명주기를 관리할 수 있다.
- 자식을 저장하려면 부모에 등록만 하면 된다(CASCADE).
- 자식을 삭제하려면 부모에서 제거하면 된다(orphanRemoval).
✔️ 복습하기
- em.find()와 em.getReference()의 차이점은?
- 영속성 컨텍스트에 이미 로딩된 엔티티가 있을 때 em.getReference()를 호출하면 무엇이 반환되는지?
- 모든 연관관계를 FetchType.LAZY(지연 로딩)으로 설정하는 것을 권장하는 이유는?
- CascadeType.PERSIST란?

이 글은 『 자바 ORM 표준 JPA 프로그래밍』 책을 학습한 내용을 정리한 것입니다.
'학습일지 > Java' 카테고리의 다른 글
| [스터디10] 10. 객체지향 쿼리 언어 (0) | 2025.09.04 |
|---|---|
| [스터디10] 09. 값 타입 (0) | 2025.08.21 |
| [스터디10] 07. 고급 매핑 (1) | 2025.08.04 |
| [스터디10] 06. 다양한 연관관계 매핑 (0) | 2025.07.22 |
| [스터디10] 05. 연관관계 매핑 기초 (1) | 2025.07.19 |
Comments