π[Spring] μ§μ° λ‘λ©(Lazy Loading)μ 무μμΈκ°μ?
- JPAμμ μ€μ λ°μ΄ν°κ° νμν μμ κΉμ§ λ°μ΄ν°λ² μ΄μ€ μ‘°νλ₯Ό μ§μ°νλ κΈ°λ²μ λλ€.
- μν°ν°λ₯Ό μ²μ μ‘°νν λλ μ°κ΄λ λ°μ΄ν°λ₯Ό μ¦μ λ‘λνμ§ μκ³ , κ·Έ μ°κ΄λ λ°μ΄ν°κ° μ€μ λ‘ μ¬μ©λ λ λ°μ΄ν°λ² μ΄μ€μμ μ‘°ννλ λ°©μμ
λλ€.
- μ΄ λ°©μμ λΆνμν λ°μ΄ν° μ‘°νλ₯Ό μ€μ¬μ μ±λ₯μ μ΅μ ννλ λ° μ 리ν©λλ€.
1οΈβ£ μ§μ° λ‘λ©(Lazy Loading)μ κΈ°λ³Έ λμ.
- μ§μ° λ‘λ©(Lazy Loading)μ μ€μ νλ©΄ μ°κ΄λ μν°ν°λ 컬λ μ
μ μ²μμ νλ‘μ κ°μ²΄λ‘ λ‘λλ©λλ€.
- νλ‘μλ μ€μ μν°ν°λ₯Ό λμ νλ κ°μ²΄λ‘, λ°μ΄ν°λ² μ΄μ€ μ‘°νκ° νμν λ νλ‘μκ° μ€μ λ°μ΄ν°λ₯Ό μ‘°ννμ¬ κ°μ μ 곡ν©λλ€.
- λ°λΌμ μ²μλΆν° μ°κ΄λ λ°μ΄ν°λ₯Ό λͺ¨λ λ‘λνλ κ²μ΄ μλλΌ μ€μ μ κ·Ό μμ μ λ°μ΄ν°λ² μ΄μ€μμ λ‘λλλλ‘ μ§μ°λ©λλ€.
- νλ‘μλ μ€μ μν°ν°λ₯Ό λμ νλ κ°μ²΄λ‘, λ°μ΄ν°λ² μ΄μ€ μ‘°νκ° νμν λ νλ‘μκ° μ€μ λ°μ΄ν°λ₯Ό μ‘°ννμ¬ κ°μ μ 곡ν©λλ€.
πββοΈ JPAμμμ βνλ‘μ(Proxy)β
νλ‘μ(Proxy)λ JPAμμ μ€μ μν°ν°λ₯Ό λμ νμ¬ μμ±λλ κ°μ§ κ°μ²΄μ λλ€.
μ΄ νλ‘μλ μ°κ΄λ μν°ν°λ₯Ό μ§μ° λ‘λ©ν λ μ¬μ©λλ©°, μ€μ λ°μ΄ν°κ° νμν μμ κΉμ§ λ°μ΄ν°λ² μ΄μ€ μ‘°νλ₯Ό μ§μ°νλ μν μ ν©λλ€.
νλ‘μ(Proxy)λ μ€μ μν°ν°μ λμΌν μΈν°νμ΄μ€λ ν΄λμ€λ₯Ό μμλ°μ λ§λ€μ΄μ§ κ°μ²΄λ‘, μ€μ λ°μ΄ν°κ° νμν μμ μ λ°μ΄ν°λ² μ΄μ€μμ λ°μ΄ν°λ₯Ό λ‘λνμ¬ κ°μ μ 곡ν©λλ€.
2οΈβ£ μμ: @OneToMany
μ§μ° λ‘λ©(Lazy Loading) μ€μ .
- μλ₯Ό λ€μ΄, Team μν°ν°κ° μ¬λ¬ Member μν°ν°μ μ°κ΄λμ΄ μμ λ
@OneToMany
κ΄κ³μ μ§μ° λ‘λ©(Lazy Loading)μ μ€μ ν΄λ³Ό μ μμ΅λλ€.
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "team", fetch = FetchType.LAZY) // μ§μ° λ‘λ© μ€μ
private List<Member> members = new ArrayList<>();
// getter, setter
}
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
// getter, setter
}
3οΈβ£ μ€λͺ .
- Team μν°ν°μ members νλμ fetch = FetchType.LAZY μ΅μ μ μ€μ νμ΅λλ€.
- Team μν°ν°λ₯Ό μ‘°νν λ members 리μ€νΈλ λ°μ΄ν°λ² μ΄μ€μμ μ¦μ λ‘λλμ§ μμΌλ©°, members 컬λ μ μ μ€μ μ κ·Όνλ μκ° λ°μ΄ν°λ² μ΄μ€μμ μ‘°νκ° μ΄λ£¨μ΄μ§λλ€.
4οΈβ£ Lazy Loadingμ μ₯μ .
1οΈβ£ μ±λ₯ μ΅μ ν.
- νμν λ°μ΄ν°λ§ μ‘°ννμ¬ λΆνμν 쿼리 μ€νμ λ°©μ§νλ―λ‘ μ±λ₯μ΄ μ΅μ νλ©λλ€.
2οΈβ£ λ©λͺ¨λ¦¬ ν¨μ¨μ±.
- νμν μκ°κΉμ§ λ©λͺ¨λ¦¬μ λ°μ΄ν°λ₯Ό λ‘λνμ§ μμΌλ―λ‘ λ©λͺ¨λ¦¬ μ¬μ©μ μ€μΌ μ μμ΅λλ€.
3οΈβ£ ν° μ°κ΄ κ΄κ³ κ΄λ¦¬.
- μ°κ΄λ λ°μ΄ν°κ° λ§μ κ²½μ°, μ΄κΈ° λ‘λ© μ μ±λ₯ μ νλ₯Ό λ°©μ§νκ³ νμν μμ μ νμν λ°μ΄ν°λ§ λΆλ¬μ¬ μ μμ΅λλ€.
5οΈβ£ Eager Loadingκ³Όμ λΉκ΅.
- λ°λλ‘ μ¦μ λ‘λ©(Eager Loading)μ μν°ν°λ₯Ό μ‘°νν λ μ°κ΄λ λͺ¨λ λ°μ΄ν°λ₯Ό ν λ²μ ν¨κ» λ‘λνλ λ°©μμ λλ€.
- μ¦μ λ‘λ©(Eager Loading)μ fetch = FetchType.EAGER μ΅μ μ ν΅ν΄ μ€μ ν μ μμΌλ©°, μ²μλΆν° μ°κ΄λ λͺ¨λ λ°μ΄ν°λ₯Ό λ‘λ©νκΈ° λλ¬Έμ μΏΌλ¦¬κ° λ§μ΄ μ€νλκ±°λ, λ§μ λ°μ΄ν°λ₯Ό λΆνμνκ² λ‘λνλ N+1 λ¬Έμ κ° λ°μν μ μμ΅λλ€.
6οΈβ£ Lazy Loading μ¬μ© μ μ£Όμμ¬ν.
1οΈβ£ νλ‘μ μ΄κΈ°ν λ¬Έμ .
- μ§μ° λ‘λ©λ νλ‘μλ νΈλμμ λ²μλ₯Ό λ²μ΄λ νμλ μ΄κΈ°νν μ μκΈ° λλ¬Έμ, μ°κ΄ λ°μ΄ν°λ₯Ό μ κ·Όνλ €λ©΄ νΈλμμ λ΄μμ μ κ·Όν΄μΌ ν©λλ€.
2οΈβ£ N+1 λ¬Έμ .
- μ§μ° λ‘λ©μ μλͺ» μ¬μ©νλ©΄ N+1 λ¬Έμ κ° λ°μν μ μμ΅λλ€.
- μλ₯Ό λ€μ΄, 리μ€νΈ ννμ μν°ν°λ₯Ό μ‘°νν λ κ° μν°ν°μ μ°κ΄ λ°μ΄ν°μ λν΄ μΆκ° μΏΌλ¦¬κ° λ°μνλ κ²½μ°μ
λλ€.
- μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ νμΉ μ‘°μΈ(Fetch Join)μ μ¬μ©νμ¬ νμν λ°μ΄ν°λ₯Ό ν λ²μ κ°μ Έμ€λ κ²μ΄ μ’μ΅λλ€.
- μλ₯Ό λ€μ΄, 리μ€νΈ ννμ μν°ν°λ₯Ό μ‘°νν λ κ° μν°ν°μ μ°κ΄ λ°μ΄ν°μ λν΄ μΆκ° μΏΌλ¦¬κ° λ°μνλ κ²½μ°μ
λλ€.
3οΈβ£ JPA νμ€ μ μ½.
-
@OneToMany
λ°@ManyToMany
λ κΈ°λ³Έμ μΌλ‘ LAZYλ‘ μ€μ λμ§λ§,@ManyToOne
λ°@OneToOne
κ΄κ³λ κΈ°λ³Έμ΄ EAGERλ‘ μ€μ λ©λλ€.- λ°λΌμ νμμ λ°λΌ λͺ μμ μΌλ‘ fetch = FetchType.LAZYλ‘ μ€μ ν΄μΌ ν©λλ€.
7οΈβ£ μμ½.
- μ§μ° λ‘λ©(Lazy Loading)μ μ°κ΄λ λ°μ΄ν°λ₯Ό μ€μ μ¬μ© μμ κΉμ§ μ§μ°νμ¬ μ‘°νν¨μΌλ‘μ¨ μ±λ₯μ μ΅μ ννλ κΈ°λ²μ
λλ€.
- μ΄λ₯Ό ν΅ν΄ λΆνμν λ°μ΄ν° μ‘°νλ₯Ό λ°©μ§νκ³ λ©λͺ¨λ¦¬ ν¨μ¨μ±μ λμΌ μ μμ§λ§, μ¬μ© μ μ£Όμν μ μ κ³ λ €νμ¬ μ΅μ μ λ°©μμΌλ‘ μ€μ ν΄μΌ ν©λλ€.