Home > Spring > πŸƒ[Spring] JPAμ—μ„œ 연관관계λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 항상 μ’‹μ„κΉŒμš”?

πŸƒ[Spring] JPAμ—μ„œ 연관관계λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 항상 μ’‹μ„κΉŒμš”?
Spring Framework

πŸƒ[Spring] JPAμ—μ„œ 연관관계λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 항상 μ’‹μ„κΉŒμš”?

  • JPAμ—μ„œ 연관관계λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 λ§Žμ€ μž₯점을 μ œκ³΅ν•˜μ§€λ§Œ, 항상 μ΅œμ„ μ˜ 선택은 아닐 수 μžˆμŠ΅λ‹ˆλ‹€.
    • 상황에 따라 연관관계λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것이 더 μœ λ¦¬ν•˜κ±°λ‚˜, ν•„μš”ν•œ 경우 μ‹ μ€‘ν•˜κ²Œ μ„€μ •ν•΄μ•Ό ν•  λ•Œλ„ μžˆμŠ΅λ‹ˆλ‹€.
      • μ—°κ΄€κ΄€κ³„μ˜ λ¬΄λΆ„λ³„ν•œ μ‚¬μš©μ€ μ„±λŠ₯ λ¬Έμ œλ‚˜ μ„€κ³„μ˜ λ³΅μž‘μ„±μ„ μ΄ˆλž˜ν•  수 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

1️⃣ 연관관계λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•„μ•Ό ν•˜λŠ” 상황 λ˜λŠ” μ£Όμ˜ν•΄μ•Ό ν•  상황.

1️⃣ λ³΅μž‘ν•œ μ—°κ΄€κ΄€κ³„λ‘œ μΈν•œ μ„±λŠ₯ 문제.

  • 연관관계가 λ§Žμ•„μ§ˆμˆ˜λ‘ SQL 쑰인 쿼리가 λ³΅μž‘ν•΄μ§€κ³ , μ„±λŠ₯ μ €ν•˜μ˜ 원인이 될 수 μžˆμŠ΅λ‹ˆλ‹€.
  • 특히 μ¦‰μ‹œ λ‘œλ”©(Eager Loading)을 λ‚¨μš©ν•˜λ©΄ λΆˆν•„μš”ν•œ λ°μ΄ν„°κΉŒμ§€ λͺ¨λ‘ λ‘œλ“œν•˜λ―€λ‘œ N+1 λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • μ΄λŠ” 객체 κ·Έλž˜ν”„μ˜ 크기가 컀질수둝 μ„±λŠ₯을 크게 μ €ν•˜μ‹œν‚΅λ‹ˆλ‹€.
  • ν•„μš”ν•œ λ°μ΄ν„°λ§Œ μ‘°νšŒν•΄μ•Ό ν•  경우 연관관계λ₯Ό ν”Όν•˜κ³  ν•„μš”ν•œ μ •λ³΄λ§Œμ„ κ°€μ Έμ˜€λŠ” JPQLμ΄λ‚˜ λ„€μ΄ν‹°λΈŒ 쿼리λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 더 λ‚˜μ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ™‹β€β™‚οΈ 객체 κ·Έλž˜ν”„(Object Graph)

객체듀 κ°„μ˜ κ·Έλž˜ν”„λ‘œ ν‘œν˜„ν•œ 것을 μ˜λ―Έν•©λ‹ˆλ‹€.
객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ κ°μ²΄λŠ” λ‹€λ₯Έ 객체와 μ—°κ΄€ 관계λ₯Ό κ°€μ§ˆ 수 μžˆλŠ”λ°, μ΄λŸ¬ν•œ 객체듀이 μ„œλ‘œ μ°Έμ‘°ν•˜λ©΄μ„œ κ΅¬μ„±λœ μ—°κ²° ꡬ쑰λ₯Ό κ·Έλž˜ν”„ ν˜•νƒœλ‘œ λ‚˜νƒ€λ‚Έ 것이 객체 κ·Έλž˜ν”„μž…λ‹ˆλ‹€.
객체 κ·Έλž˜ν”„(Object Graph)λŠ” νŠΉμ • 객체λ₯Ό μ‘°νšŒν•  λ•Œ μ—°κ΄€λœ λ‹€λ₯Έ κ°μ²΄λ“€κΉŒμ§€ ν•¨κ»˜ νƒμƒ‰ν•˜κ²Œ λ˜λŠ” ꡬ쑰λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.

πŸ™‹β€β™‚οΈ JPQL(Java Persistence Query Language)

JPA(Java Persistence API)μ—μ„œ μ—”ν‹°ν‹° 객체λ₯Ό λŒ€μƒμœΌλ‘œ ν•˜λŠ” 쿼리 μ–Έμ–΄μž…λ‹ˆλ‹€.
JPQL은 SQLκ³Ό λΉ„μŠ·ν•œ 문법을 μ‚¬μš©ν•˜μ§€λ§Œ, λ°μ΄ν„°λ² μ΄μŠ€μ˜ ν…Œμ΄λΈ”μ΄ μ•„λ‹Œ μ—”ν‹°ν‹° 객체λ₯Ό λŒ€μƒμœΌλ‘œ 쿼리λ₯Ό μž‘μ„±ν•˜λŠ” μ–Έμ–΄μž…λ‹ˆλ‹€.
이λ₯Ό 톡해 JPAλ₯Ό μ‚¬μš©ν•˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ λ°μ΄ν„°λ² μ΄μŠ€μ— 독립적인 쿼리λ₯Ό μž‘μ„±ν•˜κ³  μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

2️⃣ μ—°κ΄€κ΄€κ³„λ‘œ μΈν•œ λ³΅μž‘ν•œ νŠΈλžœμž­μ…˜ 관리.

  • 연관관계가 μ–½νžŒ μƒνƒœμ—μ„œ νŠΈλžœμž­μ…˜μ„ μ²˜λ¦¬ν•  λ•Œ, μ—”ν‹°ν‹° κ°„ 데이터 일관성을 μœ μ§€ν•˜κΈ° μœ„ν•œ 관리가 λ³΅μž‘ν•΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • Cascade μ˜΅μ…˜μ΄λ‚˜ orphanRemoval μ˜΅μ…˜μ„ μ„€μ •ν•˜μ—¬ λΆ€λͺ¨-μžμ‹ μ—”ν‹°ν‹°μ˜ 생λͺ… μ£ΌκΈ°λ₯Ό ν•¨κ»˜ 관리할 수 μžˆμ§€λ§Œ, 잘λͺ»λœ μ„€μ •μœΌλ‘œ 인해 μ˜λ„μΉ˜ μ•Šμ€ 데이터 μ‚­μ œλ‚˜ 데이터 일관성 λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

3️⃣ ν•„μš” μ΄μƒμ˜ 쑰인 ν…Œμ΄λΈ” 생성.

  • λ‹€λŒ€λ‹€(N:M) 관계λ₯Ό 직접 μ—°κ΄€κ΄€κ³„λ‘œ μ„€μ •ν•˜λ©΄ μžλ™μœΌλ‘œ 쑰인 ν…Œμ΄λΈ”μ΄ μƒμ„±λ˜λŠ”λ°, 이둜 인해 μ„±λŠ₯ μ €ν•˜ 및 쿼리 μ΅œμ ν™”κ°€ μ–΄λ €μ›Œμ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • μ‹€λ¬΄μ—μ„œλŠ” λ‹€λŒ€λ‹€ 관계λ₯Ό 직접 μ‚¬μš©ν•˜κΈ°λ³΄λ‹€λŠ” 쑰인 ν…Œμ΄λΈ”μ„ μ—”ν‹°ν‹°λ‘œ λΆ„λ¦¬ν•˜μ—¬ λ‹€λŒ€μΌ(N:1) 및 μΌλŒ€λ‹€(1:N) κ΄€κ³„λ‘œ λ‚˜λˆ„μ–΄ κ΄€λ¦¬ν•˜λŠ” 방식이 더 ꢌμž₯λ©λ‹ˆλ‹€.

4️⃣ μ—°κ΄€κ΄€κ³„λ‘œ μΈν•œ 데이터 μ˜μ‘΄μ„±.

  • 연관관계λ₯Ό 톡해 객체 κ°„μ˜ μ˜μ‘΄μ„±μ„ 높이면, 단일 μ—”ν‹°ν‹°μ˜ 독립적인 μ‚¬μš©μ΄ μ–΄λ €μ›Œμ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.
    • 예λ₯Ό λ“€μ–΄ Order와 Customerκ°€ κ°•ν•˜κ²Œ μ—°κ²°λœ μƒνƒœμ—μ„œλŠ” Orderλ₯Ό μ‘°νšŒν•  λ•Œ 항상 Customer와 κ΄€λ ¨λœ 데이터도 ν•¨κ»˜ 쑰회될 수 μžˆμŠ΅λ‹ˆλ‹€.
      • μ΄λŠ” μ„œλ‘œ λ‹€λ₯Έ 도메인 λ‘œμ§μ— 영ν–₯을 λ―ΈμΉ  수 μžˆμŠ΅λ‹ˆλ‹€.

5️⃣ λ‹¨μˆœν•œ κ°’ 쑰회의 경우.

  • λ‹¨μˆœνžˆ ID만 ν•„μš”ν•˜κ±°λ‚˜ κ°„λ‹¨ν•œ 쑰회λ₯Ό ν•΄μ•Ό ν•˜λŠ” κ²½μš°μ—λ„ ꡳ이 연관관계λ₯Ό μ„€μ •ν•˜μ—¬ 객체λ₯Ό μ°Έμ‘°ν•˜λŠ” 것은 과도할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • 이 κ²½μš°μ—λŠ” 연관관계λ₯Ό μ„€μ •ν•˜μ§€ μ•Šκ³ , IDλ₯Ό 톡해 ν•„μš”ν•œ 데이터λ₯Ό μ‘°νšŒν•˜κ±°λ‚˜ DTOλ₯Ό μ‚¬μš©ν•˜μ—¬ ν•„μš”ν•œ λ°μ΄ν„°λ§Œ κ°€μ Έμ˜€λŠ” 것이 더 λ‚˜μ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

6️⃣ API 응닡 μ‹œ 데이터 κ³Όλ‹€ λ‘œλ”© 문제.

  • REST API 개발 μ‹œ 연관관계λ₯Ό μ„€μ •ν•˜λ©΄, 직렬화 κ³Όμ •μ—μ„œ μ–‘λ°©ν–₯ 관계에 μ˜ν•œ λ¬΄ν•œ λ£¨ν”„λ‚˜ κ³Όλ„ν•œ 데이터 λ‘œλ”©μ΄ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • 이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ 단방ν–₯ μ—°κ΄€κ΄€κ³„λ‘œ μ„€κ³„ν•˜κ±°λ‚˜, ν•„μš”ν•œ 경우 DTO(Data Transfer Object)λ₯Ό μ‚¬μš©ν•΄ ν•„μš”ν•œ λ°μ΄ν„°λ§Œ μ„ νƒμ μœΌλ‘œ μ „λ‹¬ν•˜λŠ” 방법이 더 μ μ ˆν•  수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ™‹β€β™‚οΈ DTO(Data Transfer Object)

DTO(Data Transfer Object)λŠ” 데이터 전솑 κ°μ²΄λΌλŠ” 뜻으둜, μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ—¬λŸ¬ 계측 간에 데이터λ₯Ό μ „λ‹¬ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•˜λŠ” κ°μ²΄μž…λ‹ˆλ‹€.
주둜 데이터λ₯Ό μš΄λ°˜ν•˜λŠ” 역할을 ν•˜λ©°, λ‘œμ§μ΄λ‚˜ κΈ°λŠ₯ 없이 μˆœμˆ˜ν•˜κ²Œ λ°μ΄ν„°λ§Œμ„ ν¬ν•¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.
DTO(Data Transfer Object)λŠ” 일반적으둜 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 μžˆλŠ” μ—”ν‹°ν‹° 객체와 λΆ„λ¦¬ν•˜μ—¬, ν•„μš”ν•œ λ°μ΄ν„°λ§Œ μΆ”μΆœν•˜μ—¬ μ „μ†‘ν•˜κ±°λ‚˜ λ°›μ•„μ˜€λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€.

7️⃣ μΊμ‹±κ³Όμ˜ 좩돌.

  • 연관관계가 λ§Žμ„ 경우, 캐싱 μ‹œμŠ€ν…œκ³Ό μΆ©λŒν•  수 있으며, λ°μ΄ν„°μ˜ κ°±μ‹  μ‹œμ μ΄λ‚˜ 쑰회 μ‹œμ μ—μ„œ μΊμ‹œ 데이터와 μ‹€μ œ 데이터 κ°„μ˜ 일관성을 κ΄€λ¦¬ν•˜κΈ° μ–΄λ €μšΈ 수 μžˆμŠ΅λ‹ˆλ‹€.
    • 특히 지연 λ‘œλ”©(Lazy Loading)κ³Ό 캐싱을 ν•¨κ»˜ μ‚¬μš©ν•  경우 μ˜ˆμƒμΉ˜ λͺ»ν•œ 쿼리가 λ°œμƒν•˜κ±°λ‚˜, μΊμ‹œμ—μ„œ 잘λͺ»λœ 데이터가 λ°˜ν™˜λ  κ°€λŠ₯성이 λ†’μŠ΅λ‹ˆλ‹€.

2️⃣ 연관관계 μ‚¬μš© μ‹œ μ£Όμ˜μ‚¬ν•­.

1️⃣ ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ‚¬μš©.

  • μ—°κ΄€κ΄€κ³„λŠ” ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ„€μ •ν•˜κ³ , κ°€λŠ₯ν•œ ν•œ λ‹¨μˆœν•œ κ΄€κ³„λ‘œ μœ μ§€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

2️⃣ 지연 λ‘œλ”©(Lazy Loading)을 기본으둜 μ„€μ •.

  • μ¦‰μ‹œ λ‘œλ”©(Eager Loading)은 N+1 문제λ₯Ό μΌμœΌν‚¬ 수 μžˆμœΌλ―€λ‘œ, 기본적으둜 지연 λ‘œλ”©(Lazy Loading)을 μ‚¬μš©ν•˜κ³ , ν•„μš”ν•  λ•Œ 페치 쑰인(Fetch Join)μ΄λ‚˜ 직접적인 JPQL 쿼리둜 ν•„μš”ν•œ 데이터λ₯Ό κ°€μ Έμ˜€λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

πŸ™‹β€β™‚οΈ N+1 문제

N+1 λ¬Έμ œλŠ” JPA와 같은 ORM(Object-Relational Mapping) 도ꡬλ₯Ό μ‚¬μš©ν•  λ•Œ μ—°κ΄€λœ 데이터λ₯Ό μ‘°νšŒν•˜λŠ” κ³Όμ •μ—μ„œ λΆˆν•„μš”ν•˜κ²Œ λ§Žμ€ 쿼리가 μ‹€ν–‰λ˜λŠ” 문제λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€.
주둜 지연 λ‘œλ”©(Lazy Loading) 섀정이 μžˆλŠ” μ—°κ΄€ κ΄€κ³„μ—μ„œ λ°œμƒν•˜λ©°, ν•˜λ‚˜μ˜ 데이터λ₯Ό μ‘°νšŒν•  λ•Œ μΆ”κ°€λ‘œ μ—°κ΄€λœ 데이터λ₯Ό 각각 μ‘°νšŒν•˜λŠλΌ N+1개의 쿼리가 μ‹€ν–‰λ˜λŠ” ν˜„μƒμ„ λ§ν•©λ‹ˆλ‹€.

3️⃣ 단방ν–₯ 연관관계 μš°μ„ .

  • μ–‘λ°©ν–₯ κ΄€κ³„λŠ” μ„œλ‘œ κ°„μ˜ 참쑰둜 인해 λ³΅μž‘μ„±μ΄ 증가할 수 μžˆμœΌλ―€λ‘œ, 단방ν–₯ 연관관계λ₯Ό μš°μ„ μ μœΌλ‘œ μ‚¬μš©ν•˜κ³ , 정말 ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ–‘λ°©ν–₯ 연관관계λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€.

4️⃣ 쑰회 μ „μš© 연관관계.

  • 연관관계λ₯Ό μ‚¬μš©ν•˜λŠ” 경우, λ°μ΄ν„°μ˜ 변경이 ν•„μš” μ—†λ‹€λ©΄ 읽기 μ „μš©μœΌλ‘œ μ„€μ •ν•˜μ—¬ λ³€κ²½ μž‘μ—… μ‹œ μ„±λŠ₯ λ¬Έμ œλ‚˜ 무결성 λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šλ„λ‘ ν•©λ‹ˆλ‹€.

3️⃣ μš”μ•½.

  • μ—°κ΄€κ΄€κ³„λŠ” 객체 κ°„μ˜ 관계λ₯Ό μžμ—°μŠ€λŸ½κ²Œ ν‘œν˜„ν•˜κ³  μ½”λ“œμ˜ 직관성을 λ†’μ΄μ§€λ§Œ, 잘λͺ»λœ μ„€μ •μ΄λ‚˜ κ³Όλ„ν•œ μ‚¬μš©μ€ μ„±λŠ₯ μ €ν•˜μ™€ λ³΅μž‘μ„±μ„ μ΄ˆλž˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 상황에 따라 연관관계λ₯Ό λ‹¨μˆœν™”ν•˜κ±°λ‚˜ ν•„μš”ν•œ λ°μ΄ν„°λ§Œ 직접 μ‘°νšŒν•˜λŠ” 방식도 κ³ λ €ν•΄μ•Ό ν•˜λ©°, 특히 νŠΈλžœμž­μ…˜ 관리와 데이터 일관성 μœ μ§€μ— μ£Όμ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.