JPA에서 연관된 엔티티를 언제 조회할 것인지를 결정하는 옵션이다.
- LAZY : 실제로 사용할 때 조회
- EAGER : 부모를 조회할 때 함께 조회
| 구분 | LAZY (지연 로딩) | EAGER (즉시 로딩) |
| 조회 시점 | 사용할 때 조회 | 부모 조회 시 함께 조회 |
| SQL 실행 | 필요할 때 추가 SELECT | JOIN 또는 추가 SELECT 즉시 실행 |
| 성능 | 일반적으로 더 좋음 | 불필요한 데이터까지 조회 가능 |
| 기본값 | 대부분의 컬렉션(@OneToMany) | 대부분의 단일 참조(@ManyToOne) |
| 추천 | 대부분의 경우 추천 | 반드시 항상 필요한 경우만 사용 |
EAGER
public class Question {
@OneToMany(
mappedBy = "question",
fetch = FetchType.EAGER
)
private List<Answer> answers = new ArrayList<>();
}
Question 하나를 조회하면 Answer도 함께 조회한다.
Question question = questionRepository.findById(1).get();
실제로 Answer를 사용하지 않아도 이미 조회되어 있다.
Question 조회
↓
Answer도 함께 조회
항상 같이 가져오기 때문에 사용하지 않는 데이터까지 조회될 수 있어 성능상 불리하다.
LAZY
@OneToMany(
mappedBy = "question",
fetch = FetchType.LAZY
)
private List<Answer> answers = new ArrayList<>();
Question만 먼저 조회한다.
Question question = questionRepository.findById(1).get();
이 시점에는 Answer를 조회하지 않는다. 답변을 실제로 사용할 때
question.getAnswers();
그 순간 Answer 조회 SQL이 실행된다.
Question 조회
↓
Answer는 아직 조회 X
↓
getAnswers()
↓
Answer 조회
필요한 경우에만 조회하므로 대부분 성능이 더 좋다.
LAZY에서 자주 발생하는 오류
다음 코드는 LazyInitializationException오류가 발생할 수 있다.
Question question = questionRepository.findById(1).get();
question.getAnswers();
LAZY는 실제 사용할 때 DB에 접근한다.
하지만 이미 트랜잭션이 종료되어 영속성 컨텍스트가 사라졌기 때문에 조회할 수 없다.
해결 방법
트랜잭션 안에서 조회하도록 한다.
@Transactional
public void test() {
Question question = questionRepository.findById(1).get();
List<Answer> answers = question.getAnswers();
}
트랜잭션이 살아 있으므로 Answer를 정상적으로 조회할 수 있다.
언제 어떤 것을 사용할까?
- LAZY
- 대부분의 상황에서 사용
- 필요한 데이터만 조회하므로 성능이 좋다.
- EAGER
- 항상 함께 사용하는 데이터일 때만 사용
- 사용하지 않는 데이터도 함께 조회될 수 있으므로 남용하지 않는 것이 좋다.
실무에서도 특별한 이유가 없다면 LAZY를 기본으로 사용하는 경우가 많다.
@OneToMany / @ManyToOne
OneToMany는 기본적으로 Lazy가 적용되어 있고, ManyToOne은 기본적으로 Eager가 적용되어 있다.
'BackEnd > Spring' 카테고리의 다른 글
| [Spring] Bean 심화 - @Bean, @Qualifier, @Order 정리 (0) | 2026.08.06 |
|---|---|
| Spring Boot에서 HTML 페이지 출력하기 (Thymeleaf 사용법) (0) | 2026.08.06 |
| [Spring] JPA CascadeType과 Flush (0) | 2026.08.05 |
| [Spring] @OneToMany와 @ManyToOne (0) | 2026.08.05 |
| [Spring] Spring Boot에서 웹 요청은 어떻게 처리될까? (@Controller, @GetMapping) (0) | 2026.08.05 |
댓글