Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions week09/keyword/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
## 1. 개념

- 엔티티가 연관관계를 통해 서로 연결된 구조(객체 그래프)를 따라 탐색하는 것

- 예: `Member -> Orders -> OrderItems -> Item` 처럼 도메인 객체가 연쇄적으로 연결된 구조를 의미

- JPA, ORM, API 개발에서 **지연 로딩(LAZY), 즉시 로딩(EAGER), N+1 문제**와 밀접하게 연결된다.

---

## 2. 왜 중요한가?

- API 응답을 만들 때 엔티티 그래프가 깊어질수록
- 의도치 않은 추가 쿼리
- 순환 참조
- 성능 저하
- 무한 직렬화 오류(JSON 변환 실패) 발생

- 따라서 “무엇을 어디까지 탐색할 것인가?”를 통제하는 것이 필수

---

## 3. 주요 개념 키워드
### 3-1. 객체 그래프

- 엔티티 간의 **연관관계(1:N, N:1, N:M)** 로 이어진 전체 구조

- 프로그램이 런타임에 보유하는 객체들의 네트워크

### 3-2. 탐색 Traversal

- 연관 엔티티를 점(.)으로 계속 접근하는 것

- ex) `member.getOrders().get(0).getOrderItems().get(0).getItem().getName()`

### 3-3. LAZY vs EAGER

- **LAZY(지연 로딩)**: 필요한 시점에 쿼리 실행 -> **예측 가능한 성능**

- **EAGER(즉시 로딩)**: 처음부터 연관된 모든 엔티티를 조회 -> **예상치 못한 폭발적 쿼리 발생**

### 3-4. N+1 문제

- 객체 그래프를 탐색할 때 지연 로딩이 남용되면
-> 1번 조회 후, 연관된 엔티티마다 N개의 쿼리 추가 발생

- API에서 가장 흔한 성능 병목 지점

### 3-5. 순환 참조 Circular Reference

- 양방향 연관관계(예: Member ↔ Orders)는 **직렬화(JSON 변환)** 시 무한 루프 발생

- `@JsonIgnore`, DTO 변환이 필요한 이유

---

## 4. 객체 그래프 탐색 문제를 해결하는 패턴
### 4-1. DTO 변환 (엔티티 노출 금지)

- 엔티티 그대로 return하지 않고, 필요한 데이터만 꺼낸 DTO로 변환

- 장점:

- 순환 참조 차단

- API 응답 스펙 안정성

- 필요한 필드만 선택 가능

### 4-2. Fetch Join

- SQL JOIN을 통해 필요한 연관 엔티티를 한번에 가져옴

- LAZY + Fetch Join 조합이 실무 표준

### 4-3. Batch Fetch Size

- Hibernate 옵션으로 지연 로딩 시 한 번에 여러 엔티티를 가져옴

- collection 지연 로딩에서 N+1 완화

### 4-4. Projection(JPA, QueryDSL)

- 필요한 필드만 선택해서 조회

---

## 5. API & Paging에서 객체 그래프 탐색이 위험한 이유
### 5-1. 무한 탐색

- 엔티티 -> 엔티티 -> 엔티티로 끝없이 이어짐

- FE가 필요 없는 필드까지 전부 내려가 API 응답이 비대해짐

### 5-2. Lazy Loading + Pagination 충돌

- `@OneToMany`는 기본적으로 collection

- collection fetch join + paging 불가능

- 잘못 탐색하면 페이지네이션 성능 붕괴

### 5-3. 순환 참조 발생

- `Order -> Member -> Orders -> Member …` 무한 반복

- JSON 변환 시 에러 발생

---

## 6. 객체 그래프 탐색을 안전하게 쓰는 전략
### 6-1. 엔티티 → DTO 계층 분리

- API 계층에서 엔티티 직접 노출 금지

- "선택된 범위의 그래프만" DTO로 변환

### 6-2. Service 계층에서 명확한 조회 범위 관리

- 필요한 연관관계만 fetch join

- 무분별한 getter 호출 금지

### 6-3. Pagination 시 일대다 관계 조심

- 1:N fetch join은 paging 불가

- 해결법:

- 엔티티 ID 기반 페이징 + 배치 사이즈

- slice 방식

- QueryDSL distinct paging

### 6-4. Lazy 로딩 원칙 유지

- 모든 연관 관계 EAGER → 성능 위험

- 기본은 LAZY + 필요한 곳만 fetch join

---

## 7. 한눈에 정리: 객체 그래프 탐색의 위험 신호
| 위험 요인 | 설명 |
| ------------------- | ------------------------------ |
| 무한 연관 탐색 | 깊은 엔티티 그래프 return 시 JSON 무한 루프 |
| EAGER 남발 | 예측 불가 쿼리 폭발 |
| 컬렉션 Fetch Join + Pageable | JPA에서 금지된 조합 |
| LAZY 호출 반복 | N+1 문제 발생 |
| 엔티티를 직접 API 응답 | 순환 참조 + 유지보수 어려움 |

---

## 8. 마무리

- 객체 그래프 탐색은 API 설계에서 반드시 통제해야 하는 개념

- 엔티티를 그대로 반환하면 N+1, 페이징 오류, 순환 참조가 발생

- DTO 변환 + fetch join + lazy 전략을 통해 안전하게 처리해야 함
Loading