728x90
반응형
💡 JPA에서 즉시 로딩(EAGER)과 지연 로딩(LAZY)은 왜 중요할까?
우리가 JPA를 사용할 때 가장 자주 마주치는 개념 중 하나가 즉시 로딩(EAGER) 과 지연 로딩(LAZY) 이다.
이 둘의 차이를 알지 못한 채 개발을 진행하면, 언젠가는 의도치 않은 N+1 문제를 만나게 된다.
오늘은 이 두 개념의 차이를 이해하고, 언제 어떤 전략을 선택해야 할지에 대한 나의 생각을 정리해본다.
🔍 즉시 로딩과 지연 로딩이란?
JPA에서 연관 관계를 맺을 때, 하위 엔티티를 언제 로딩할지를 지정할 수 있다.
기본적으로는 다음 두 가지 방식이 존재한다.
java
복사편집
@OneToMany(fetch = FetchType.LAZY) private List<Order> orders;
- EAGER (즉시 로딩): 연관된 엔티티를 즉시 조회
- LAZY (지연 로딩): 연관된 엔티티를 실제로 접근할 때 조회
⚙️ 차이점 비교
구분EAGER (즉시 로딩)LAZY (지연 로딩)
| 조회 시점 | 엔티티 조회와 동시에 연관 엔티티도 조회 | 실제 필드에 접근할 때 쿼리 발생 |
| 성능 | 필요 없는 쿼리까지 발생 가능 | 초기 로딩이 가볍고 유연 |
| 주의점 | N+1 문제 위험 ↑ | LazyInitializationException 주의 필요 |
❗ N+1 문제란?
예를 들어, 다음과 같은 구조가 있다고 해보자.
java
복사편집
@Entity public class Member { @ManyToOne(fetch = FetchType.EAGER) private Team team; }
이제 모든 Member 리스트를 조회해보면?
java
복사편집
List<Member> members = memberRepository.findAll();
- 이때 @ManyToOne(fetch = EAGER) 이면 각 Member에 대해 Team을 조회하는 쿼리가 별도로 발생한다.
- 만약 Member가 100명이면? → 1 + 100 = 101번 쿼리가 발생하게 된다.
바로 이게 N+1 문제다.
EAGER는 개발자가 제어할 수 없다는 점에서 특히 위험하다.
✅ 그래서 뭘 써야 할까?
JPA에서는 대부분의 연관 관계를 기본적으로 LAZY로 설정하는 걸 추천한다.
그 이유는 단 하나. 개발자가 언제 로딩할지 직접 제어할 수 있기 때문이다.
java
복사편집
@ManyToOne(fetch = FetchType.LAZY) private Team team;
그럼 실제로 팀 이름을 출력하고 싶을 때만 쿼리를 날리게 된다.
👀 실무 경험에서 느낀 점
- 초기에 무지하게 EAGER로 설정해두고 개발했는데, 서비스 속도가 이상하게 느려졌다.
- JMeter로 테스트하니 무려 300개 이상의 쿼리가 날아가고 있었음.
- LAZY로 바꾸고 나니 전체 쿼리 수가 절반 이하로 줄었고, 응답 속도도 빨라졌다.
- 단, LAZY는 트랜잭션 범위를 벗어나면 LazyInitializationException이 터지기 때문에, 서비스 단에서 연관 데이터를 다 쓰도록 설계해야 한다.
✍️ 정리하며
- EAGER는 위험하다. 내가 원하지 않는 시점에 쿼리를 발생시킨다.
- LAZY는 제어권이 개발자에게 있다. 설계만 잘하면 성능도 좋고 관리도 쉽다.
- 기본은 LAZY, 정말 필요한 곳에만 fetch join이나 DTO Projection 등을 활용하자.
📚 참고 자료
- 공식 문서: JPA Fetching Strategies
- [김영한 강의 - 실전! 스프링 부트와 JPA 활용 1, 2]
728x90
반응형
'언어' 카테고리의 다른 글
| 최근 React · Next.js 보안 이슈 정리 (개발자 필독) (0) | 2025.12.17 |
|---|---|
| 🚀 리액트 프로젝트 시작할 때 꼭 알아두면 좋은 5가지 팁 (0) | 2025.10.01 |
| 엑셀다운로드 시 로딩바 구현 (2) | 2025.07.26 |
| React를 처음 배우는 사람을 위한 핵심 개념 정리 (2) | 2025.07.17 |
| 2025년 6월 최신 React 트렌드 (0) | 2025.06.06 |