Home

(JPA) LazyInitializationException 원인과 5가지 해결방법

Published in java
July 06, 2025
1 min read
(JPA) LazyInitializationException 원인과 5가지 해결방법

| 안녕하세요, 코딩하는곰입니다. 😊
JPA를 사용하다 보면 한 번쯤 마주치는 오류가 바로 LazyInitializationException인데요.
이 오류는 영속성 컨텍스트가 종료된 후 지연 로딩(Lazy Loading)을 시도할 때 발생합니다.
오늘은 이 문제의 근본적인 원인실무에서 적용 가능한 5가지 해결 방법을 상세히 설명드리겠습니다.
특히 Spring 환경에서의 해결책을 중점적으로 다룰 예정이니 끝까지 읽어주세요!

|

1. LazyInitializationException의 발생 원인

LazyInitializationException은 “no Session” 메시지와 함께 나타나며, 주로 다음 상황에서 발생합니다:

  • 트랜잭션 종료 후 지연 로딩된 객체 접근
  • 영속성 컨텍스트 닫힌 상태에서 프록시 객체 초기화 시도
  • 컨트롤러나 뷰 레이어에서 지연 로딩 수행 시
    @Entity
    public class Order {
    @Id @GeneratedValue
    private Long id;
    @OneToMany(mappedBy = "order", fetch = FetchType.LAZY) // ← 지연 로딩 설정
    private List<OrderItem> items;
    }
    위 코드에서 order.getItems()를 트랜잭션 외부에서 호출하면 예외가 발생합니다.
    하이버네이트는 프록시 객체를 통해 지연 로딩을 구현하는데, 영속성 컨텍스트가 없으면 초기화가 불가능하기 때문입니다.

    ▶ 왜 LAZY 전략을 사용할까?

  • 성능 최적화: 불필요한 조회 방지
  • 메모리 절약: 연관 관계 데이터가 큰 경우 유용
  • N+1 문제와의 밸런스 필요 (추후 설명)

(JPA) LazyInitializationException 원인과 5가지 해결방법
(JPA) LazyInitializationException 원인과 5가지 해결방법


🚀 개발자 커리어를 준비하고 있다면, (MySQL/MariaDB) INSERT 시 NULL과 DEFAULT 처리 완벽 가이드 - 코딩하는곰의 DB 이야기를 참고해보세요.

|

2. 해결 방법 ①: FetchType.EAGER 사용 (비추천)

가장 간단하지만 성능 문제를 유발할 수 있는 방법입니다.

@OneToMany(mappedBy = "order", fetch = FetchType.EAGER) // 즉시 로딩
private List<OrderItem> items;

⚠️ 주의사항

  • N+1 문제 발생: 연관된 모든 데이터를 한 번에 로딩하므로 쿼리 비효율성 증가
  • 불필요한 데이터 조회: 사용하지 않는 연관 관계도 로딩됨
  • 실무에서는 LAZY + fetch join 조합을 더 권장

    3. 해결 방법 ②: 트랜잭션 범위 확장 (OSIV)

    Spring의 Open Session In View(OSIV) 패턴을 활용합니다.
    # application.properties
    spring.jpa.open-in-view=true # 기본값이 true

    장점 vs 단점

    장점단점
    뷰 레이어까지 지연 로딩 가능장시간 연결 유지로 인한 리소스 낭비
    설정 간편성능 저하 가능성

(JPA) LazyInitializationException 원인과 5가지 해결방법
(JPA) LazyInitializationException 원인과 5가지 해결방법


PC나 모바일 브라우저에서 바로 실행되는 간편한 웹 스톱워치는 빠르게 시간 측정이 필요할 때 이상적인 도구입니다.

|

4. 해결 방법 ③: Hibernate.initialize()

트랜잭션 내에서 명시적 초기화를 수행합니다.

@Transactional
public Order getOrderWithItems(Long orderId) {
Order order = orderRepository.findById(orderId).orElseThrow();
Hibernate.initialize(order.getItems()); // ← 강제 초기화
return order;
}

5. 해결 방법 ④: DTO 변환 (추천!)

가장 안전한 방법으로, 엔티티 대신 DTO를 반환합니다.

public OrderDto getOrderDto(Long orderId) {
return orderRepository.findById(orderId)
.map(order -> new OrderDto(
order.getId(),
order.getItems().stream() // ← 트랜잭션 내에서 처리
.map(OrderItemDto::new)
.toList()))
.orElseThrow();
}

6. 해결 방법 ⑤: fetch join 최적화

JPQL의 fetch join을 사용하면 N+1 문제도 함께 해결됩니다.

@Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.id = :id")
Optional<Order> findByIdWithItems(@Param("id") Long id);

(JPA) LazyInitializationException 원인과 5가지 해결방법
(JPA) LazyInitializationException 원인과 5가지 해결방법


📅 다양한 문화행사를 한눈에 보고 싶다면, 거문도백도은빛바다체험행사를 참고해보세요.

| 정리하자면, LazyInitializationException은 영속성 컨텍스트 라이프사이클로딩 전략의 이해가 부족할 때 발생합니다.
개인적으로는 DTO 변환이나 fetch join을 가장 추천드리며, 간혹 OSIV를 사용하는 팀도 있습니다.
여러분은 어떤 방법을 선호하시나요? 💬
코딩하는곰의 다음 포스팅에서는 N+1 문제의 3단계 해결법을 다룰 예정이니 기대해주세요!
(궁금한 점은 댓글로 남겨주시면 아는 범위에서 성실히 답변드리겠습니다 😊)
[블로그 구독하기][GitHub 링크] [관련 포스팅 보기]

기억력 감퇴를 막고 인지 능력을 향상시키고 싶다면, AI 힌트 기능이 있는 스도쿠 저니를 활용해보세요.









최상의 건강을 위한 영양가득한 식품과 정보! life-plus.co.kr 바로가기
최상의 건강을 위한 영양가득한 식품과 정보! life-plus.co.kr 바로가기



다채로운 문화축제와 공연 소식을 공유하는 블로그! culturestage.co.kr 바로가기
다채로운 문화축제와 공연 소식을 공유하는 블로그! culturestage.co.kr 바로가기



비트코인 세계로의 첫걸음! 지금 가입하고 거래 수수료 할인 혜택 받으세요! bitget.com 바로가기
비트코인 세계로의 첫걸음! 지금 가입하고 거래 수수료 할인 혜택 받으세요! bitget.com 바로가기




Tags

#developer#coding#java

Share

Previous Article
(CSS 기초) CSS 선택자 완벽 정리 - 태그, 클래스, ID 선택자 이해하기

Table Of Contents

1
1. LazyInitializationException의 발생 원인
2
2. 해결 방법 ①: FetchType.EAGER 사용 (비추천)
3
4. 해결 방법 ③: Hibernate.initialize()
4
5. 해결 방법 ④: DTO 변환 (추천!)
5
6. 해결 방법 ⑤: fetch join 최적화

Related Posts

(Java 예외 처리 마스터하기) 다중 catch와 예외 흐름 제어의 모든 것 - 코딩하는곰의 20년 노하우
December 16, 2025
3 min