@EntityGraph란?
1. 기본 개념
@EntityGraph(attributePaths = {"user"})
의미: "Todo를 조회할 때 연관된 user도 함께 가져와줘!"
2. 왜 필요한가?
문제 상황:
// Todo 10개를 조회했다고 가정
List<Todo> todos = todoRepository.findAll();
// 각 Todo의 user 정보에 접근할 때마다 개별 쿼리 발생! (N+1 문제)
for (Todo todo : todos) {
System.out.println(todo.getUser().getEmail()); // 매번 DB 쿼리!
}
쿼리 실행 결과:
-- 1번: Todo 조회
SELECT * FROM todos;
-- N번: 각 user 개별 조회 (N+1 문제!)
SELECT * FROM users WHERE id = 1;
SELECT * FROM users WHERE id = 2;
SELECT * FROM users WHERE id = 3;
...
3. @EntityGraph 해결책
@EntityGraph(attributePaths = {"user"})
List<Todo> findAll();
쿼리 실행 결과:
-- 1번만 실행: JOIN으로 한 번에 가져옴!
SELECT t.*, u.*
FROM todos t
LEFT JOIN users u ON t.user_id = u.id;
4. 간단한 비유
@EntityGraph 없이:
- 📦 택배(Todo)를 받고
- 📝 영수증(user)은 나중에 따로 요청해서 받기
- → 택배마다 영수증 요청 = 비효율!
@EntityGraph 사용:
- 📦 택배(Todo)와 📝 영수증(user)을 한 번에 받기
- → 한 번의 요청으로 모든 것 해결 = 효율적!
5. 실제 사용 예시
// 기본 조회 (LAZY 로딩)
@ManyToOne(fetch = FetchType.LAZY) // user는 나중에 조회
private User user;
// EntityGraph로 즉시 로딩
@EntityGraph(attributePaths = {"user"}) // user를 미리 같이 가져와!
Page<Todo> findAllByOrderByModifiedAtDesc(Pageable pageable);
6. 다른 방법들과 비교
| 방법 | 코드 | 장단점 |
| JPQL | @Query("SELECT t FROM Todo t JOIN FETCH t.user") | 복잡하지만 세밀한 제어 |
| @EntityGraph | @EntityGraph(attributePaths = {"user"}) | 간단하고 직관적 ✅ |
| FetchType.EAGER | @ManyToOne(fetch = EAGER) | 항상 가져와서 비효율적 ❌ |
7. 더 복잡한 예시
// 여러 연관관계 함께 로딩
@EntityGraph(attributePaths = {"user", "managers"})
List<Todo> findByTitle(String title);
// 중첩된 연관관계까지 로딩
@EntityGraph(attributePaths = {"user", "managers.user"})
Optional<Todo> findWithManagersById(Long id);
핵심: @EntityGraph는 "이 데이터들을 한 번에 가져와줘!"라고 JPA에게 알려주는 간단한 방법!
'Spring 7기 프로젝트 > 코드 개선 + 테스트 코드 프로젝트' 카테고리의 다른 글
| [트러블슈팅] JWT + RefreshToken 구현 중 만난 5가지 트러블슈팅 (6) | 2025.06.08 |
|---|---|
| [트러블슈팅] JWT 예외 처리 시스템 구축 (0) | 2025.06.06 |
| [트러블슈팅] Spring Boot JWT 인증 시스템 : 나만의 설계 기준을 잡아보자. (0) | 2025.06.06 |
| [트러블슈팅] Spring Boot 어드민 API 로깅 시스템 구현 - 인터셉터와 AOP (0) | 2025.06.05 |
| [트러블슈팅] Spring JPA에서 연관관계 null 체크의 중요성 (0) | 2025.06.05 |