인프런 커뮤니티 질문&답변

세승님의 프로필 이미지
세승

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

주문 조회 V3.1: 엔티티를 DTO로 변환 - 페이징과 한계 돌파

일대다 관계에서의 컬렉션 fetch join과 페이징에 대한 질문

해결된 질문

작성

·

542

·

수정됨

0

안녕하세요. 일대다 관계에서의 컬렉션 fetch join과 관련된 강의를 듣다가 궁금한 점이 생겨 질문 드립니다.

강의자료에서 컬렉션 페치 조인을 사용하면 페이징이 불가능한데, 그 이유는 하이버네이트가 경고 로그를 남기면서 모든 데이터를 DB에서 읽어오고, 메모리에서 페이징 해버리기 때문이라고 나와있습니다.(강의에서는 outofmemory 장애로 이어질수 있다고 하셨구요)

"컬렉션 페치조인을 사용하면, 일대다의 관계에서 다에 해당하는 데이터를 기준으로 DB의 데이터가 반환되기 때문에, 일에 해당하는 데이터를 기준으로 페이징할 수가 없다." 라는 점은 이해를 했습니다.

그런데 컬렉션 페치조인에서 페이징을 사용하던 하용하지 않던, DB에 요청하여 반환받게 되는 데이터(row)의 개수는 동일한 것 아닌가요?

결국 이 뻥튀기된 모든 데이터를 중복되지 않게 걸러주는 역할은 JPA가 하는 것이고, 페이징이 필요하다면 걸러진 데이터를 가지고 단순히 반환되는 데이터의 갯수만 정하면 될 것 같은데, 왜 outofmemory 장애가 발생하는지 모르겠습니다.

예를들어, 컬렉션 페치조인으로 DB에서 반환된 row의 갯수가 10000개라고 했을 때, JPA는 10000개의 모든 row를 확인하면서 중복된 엔티티가 만들어지지 않도록 걸러낼 것이고, 이는 페이징이 없더라도 수행되는 동작일 것이라고 생각합니다.

앞의 제 생각이 맞다면, 걸러진 데이터를 기준으로 페이징을 하면 되지않나요?

답변 1

1

안녕하세요, 세승 님! 공식 서포터즈 codesweaver 입니다.

fetch join 결과가 크다면 어차피 메모리를 많이 사용할텐데, 페이징을 하는 것이 문제인가 하는 질문이군요.

메모리에 불러온 데이터를 다시 페이징 할 경우 추가적인 메모리를 소모합니다. 또 말씀하신 것 같이 중복된 항목을 제거하는 작업도 추가적인 메모리를 소요하므로 out of memory를 유발할 수 있습니다.

사실, fetch join 으로 거대한 데이터를 메모리에 올리는 것 자체가 문제입니다. 가급적 페이징은 쿼리로 데이터베이스에서 실행해야 합니다.

감사합니다.

세승님의 프로필 이미지
세승

작성한 질문수

질문하기