-
[Spring] 즉시(Eager) 로딩 과 지연(Lazy) 로딩Spring JPA 2024. 8. 11. 21:54
Spring jpa 에서 연관관계 매핑을 할때 설정하는 문제이다
JPA 에서 데이터를 조회 할때 eager loading(즉시 로딩), lazy loading(지연 로딩) 으로 하는 두가지 방식이 있다
이 두개의 차이점은 한개의 테이블을 조회할때 그 테이블에 연관된 테이블까지 불러오냐 안 불러오냐의 차이점이다
여기서 즉시 로딩(eager)은 연관된 데이터까지 한 번에 불러오고
지연 로딩(lazy)은 필요한 시점에 연관된 데이터를 불러온다
어떻게 설정을 하냐?
@Entity @Setter @Getter @NoArgsConstructor @AllArgsConstructor @Table(name = "post") public class Post { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "post_id") private Long postId; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @Column(name = "title") private String title; @Column(name = "content") private String content; }
일단, 해당하는 테이블의 연관관계 1:N, N:1, 1:1 등등을 설정해주고 fetch 타입을 지정해준다
Fetch Type 이란?
JPA가 하나의 Entity를 조회할 때 연관관계에 있는 객체들을 어떻게 가져올 것이냐를 나타내는 설정값이다
여기에서 JPA는 ORM 기술이다
사용자가 쿼리를 직접 작성하지 않고 JPQL을 이용하여 쿼리문을 생성하기 때문에
객체와 필드를 보고 쿼리를 생성한다
즉시 로딩
- 데이터를 조회할 때 연관된 모든 객체의 데이터까지 한번에 불러오는 것
- @xxToxx(fetch = FetchType.EAGER)
@Entity @Getter @Setter @Table(name = "category") @NoArgsConstructor public class Category { @Id @Column(name = "category_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "parent_category_id") private Category parentCategory; @Column(name = "category_name") private String name; public Category(Category parentCategory, String name) { this.parentCategory = parentCategory; this.name = name; } }
이렇게 category라는 entity가 있고 부모 카테고리와 N:1의 관계를 가지고 있다고 보자
category 한개를 조회할 때 어떤 쿼리가 만들어질까 ?
Hibernate: select c1_0.category_id,c1_0.category_name,pc1_0.category_id,pc1_0.category_name,pc1_0.parent_category_id from category c1_0 left join category pc1_0 on pc1_0.category_id=c1_0.parent_category_id where c1_0.category_id=?
위와 같이 즉시 로딩을 사용하게 되면 category를 조회할때 부모 카테고리 까지 불러오는 쿼리를 작성하여 한꺼번에 데이터를 불러온다
지연 로딩
- 필요한 시점에 연관된 객체의 데이터를 불러온다
- @xxToxx(fetch = FetchType.LAZY)
위에 있는 Category entity에서 FetchType 을 Lazy로 바꾼다면 어떤 쿼리가 만들어질까?
Hibernate: select c1_0.category_id,c1_0.category_name,c1_0.parent_category_id from category c1_0 where c1_0.category_id=?
위와 같이 부모 카테고리의 데이터까지는 불러오지 않는다
즉, 지연 로딩을 사용하면 연관된 데이터는 사용하는 시점에 쿼리가 나가도록 할 수 있다
어떤 사람들은 "어차피 가져와야 하는 데이터면 EAGER가 좋지 않냐?"라고 말하기도 한다
그러나, EAGER 로딩을 무조건적으로 사용하는 것은 바람직하지 않다
EAGER 로딩은 연관된 모든 데이터를 한 번에 가져오므로, 불필요한 데이터가 함께 로딩되어 성능 문제를 야기할 수 있다
만약 특정한 경우, 예를 들어 카테고리와 부모 카테고리가 항상 함께 사용되는 상황이라면, EAGER로 설정하여 데이터를 함께 조회하는 것이 합리적일 수 있다
그러나 해당 엔티티를 조회할 때 연관된 데이터가 당장 필요하지 않거나, 특정 시점에만 필요한 경우라면 LAZY 로딩을 사용하는 것이 좋다 이 경우에는 필요한 시점에 별도의 쿼리를 작성하여 데이터를 가져오는 것이 성능 면에서 더 유리하다
'Spring JPA' 카테고리의 다른 글
[Spring JPA] JPA N+1 문제 (1) 2024.10.13 [Spring JPA] entity의 생성일, 수정일 어떤식으로 할까 (0) 2024.09.11 [Spring] DB 상태 테이블, Enum 관리 Converter 사용해보자 (0) 2024.07.04 [Spring] OSIV 란? (0) 2024.05.24