Manidle/Final-BackEnd

[BackEnd] 사전로딩(LAZY) 즉시로딩(EAGER) 설정에 관련된 List 사용유무

Closed this issue · 1 comments

부모객체에서 즉시로딩(EAGER) 타입의 객체를 2개 이상 가지고 있을경우 EAGER로 fetch해 올 때 발생 MultipleBagFetchException이 발생합니다.

즉, OneToMany, ManyToMany인 Bag 두 개 이상을 EAGER로 fetch할 때 발생합니다.
EAGER로 땡겨오면 N+1 쿼리 문제가 존재하기 때문에 fetchType을 전부 LAZY로 바꾼 후 한 방 쿼리로 불러와도 문제는 재발합니다.

때문에, EAGER로 땡겨오면 N+1 쿼리 문제가 존재하기 때문에 fetchType을 전부 LAZY로 바꾼 후 한 방 쿼리로 불러와도 문제는 재발합니다.

Bag(Multiset)은 Set과 같이 순서가 없고, List와 같이 중복을 허용하는 자료구조입니다.
하지만 자바 컬렉션 프레임워크에서는 Bag이 없기 때문에 Hibernate에서는 List를 Bag으로써 사용하고 있는 것 입니다.

MultipleBagFetchException이 발생하여 혹시나 하여 객체를 전부 LAZY로 변경했더니 본문과 다르게 오류는 해결이 되었음을 확인했습니다. 자료로 보아 Bag을 Set으로 바꾸면 우리가 원하는대로 한 방 쿼리로 날아가서 오류가 해결된다고 나옵니다.

사전로딩(LAZY) 즉시로딩(EAGER)에 대한 개념을 다 같이 복습하여 List를 사용해야 할 지 Set을 사용해야 할 지 의논해봐야 할 것 같습니다

참고:https://perfectacle.github.io/2019/05/01/hibernate-multiple-bag-fetch-exception/

EAGER와 LAZY를 정리해봤습니다. 같이 공부하고 나눌 수 있어서 참 좋네용

정의

EAGER - 즉시 로딩

  • 성실한, 열심인
  • 하나의 객체를 DB로부터 읽어올 때 참조 객체들의 데이터까지 전부 읽어오는 방식

LAZY - 지연 로딩

  • 게으른
  • 참조 객체들의 데이터들은 무시하고 해당 엔티티의 데이터만 가져옴

서로의 장단점

EAGER의 경우 쿼리문을 1번만 돌게 되지만, LAZY는 n번 돌게 된다.

→ 그럼에도 불구하고 Fetch type은 항상 LAZY를 써야 하는 게 맞다.

  • 이유 : EAGER의 경우 SELECT 요청에 대한 SELECT 요청을 n번 사용한다.

    단순한 조회 쿼리 하나가 지나치게 많은 쿼리문을 돌리다보면 성능저하를 유발할 수 있다.

  • 하나의 SELECT문을 날리고 싶은데 N개의 SELECT문이 동시에 사용된다면 엄청난 리소스 낭비가 일어난다.

참고 자료

JPA는 왜 지연 로딩을 사용할까? : [https://velog.io/@bread_dd/JPA는-왜-지연-로딩을-사용할](https://velog.io/@bread_dd/JPA%EB%8A%94-%EC%99%9C-%EC%A7%80%EC%97%B0-%EB%A1%9C%EB%94%A9%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C)