강의

멘토링

로드맵

Inflearn brand logo image

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

인생은회전목마님의 프로필 이미지
인생은회전목마

작성한 질문수

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

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

토이프로젝트에서 spring data jpa 기반으로 페이징 처리 중 궁금한 점 있습니다.

작성

·

153

0

1. 강의 내용과 관련된 질문인가요? 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 아니오
3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예

[질문 내용]

먼저 강의 설명과 일맥상통한 부분일 것 같지만, Spring Data JPA를 바탕으로 토이프로젝트를 개발하고있고 Pageable 인터페이스를 활용하고 있습니다.

 

프로젝트에서 Item(품목)의 하위 개념으로 Product(제품)을 가지고 있습니다.(1:N - 품목 하나에 대해 여러개의 제품을 등록 할 수 있음)

처음에는 특정 item을 클릭했을 때, 해당 item의 정보와 item에 등록된 하위 Product 리스트(목록을 보여주기 위한 일부 정보들만)를 보여주기 위해 item에 접급하는 Repository에 다음 메소드를 만들었습니다.

@Query(value = "SELECT DISTINCT i FROM Item i LEFT JOIN FETCH i.productList WHERE i.id = :itemId",
        countQuery = "SELECT COUNT(p) FROM Product p WHERE p.item.id = :itemId")
Page<Item> findWithProductsByItemId(@Param("itemId") long itemId, Pageable pageable);

그런데 이렇게 하다보니 product가 아닌 item으로 페이징이 되는 것을 알았습니다. 이에 두 가지로 대책을 세웠는데 어떻게 해야할지 모르겠습니다.

 

1) 응용계층에서 item에 대한 정보를 불러오는 item서비스 호출 + 위 item에 해당되는 product 리스트 정보들을 paging 하여 불러오는 페이징하여 불러오는 product서비스 호출

 

2) product를 메인으로 item과 n:1 패치조인하는 메소드를 productRepository에서 생성.

 

1번 방법이 맞는 것 같지만,, paging으로 데이터를 불러올 때마다 item쿼리를 한번씩 날려야하는게 비효율적인거 같기도하고,, 2번으로 하자니... 제가 구현하고자 하는 기능과는 뭔가 다르게 개발하는거 같아 꺼림직 합니다.(item 중심의 조회 기능이 아닌 product기준의 조회)

 

긴글 읽어주셔서 감사합니다... 어떤식으로 구현하는게 맞는 방법일까요?

답변 2

0

안녕하세요. 인생은회전목마님, 공식 서포터즈 y2gcoder입니다.

말씀해주신 요구사항을 들어봤을 때 저는 반대로 product의 item들을 조회하는 것이라 이해했습니다. 그래서 저는 2번을 추천드리고 싶습니다.

product도 페이징해야 하고 연관된 item도 페이징해야 하는 것이 아니라

 

처음에는 특정 item을 클릭했을 때, 해당 item의 정보와 item에 등록된 하위 Product 리스트(목록을 보여주기 위한 일부 정보들만)를 보여주기 위해 item에 접급하는 Repository에 다음 메소드를 만들었습니다.

 

라면, 저는 product의 id를 기준으로 product의 상세 정보와 해당 product가 가진 item 목록을 조회한다고 하면, 저는 item 목록을 조회할 때는 item 목록을 기준으로 조회하는 게 맞는 것 같습니다 🙂

 

감사합니다.

앗 아닙니다.

item의 정보들을 보여주고, 해당 item의 하위에 있는 product 리스트를 보여주는 기능입니다. item(핸드폰)이라면 product로 아이폰10, 갤럭시 25, 모토로라.. 등등이 등록되는 식입니다.

핸드폰이라는 품목(item)을 어떤어떤 조건으로 사고싶다라는 item 정보들을 보여주고, 해당 품목에 대해 구매를 고려하는 제품(product)들을 등록하는 방식입니다.

이때 itemId가 key로 item의 정보와 itemId를 갖는 product리스트들이 조회합니다.

 

아, 제가 반대로 이해하고 말씀드렸네요 😅
그래도 말씀드리고 싶은 방향은 동일한 것 같습니다. 제가 인생은회전목마님이라면, item 들의 목록을 보여주는 것이 아니라 해당 item에 연결된 product 리스트를 페이징으로 보여주는 것이기 때문에 item_id를 기준으로 product 목록을 쿼리할 것 같습니다 🙂
그래서 2번을 선택할 것 같슴다.

0

안녕하세요, 인생은회전목마님, 인프런 AI 인턴입니다.

Spring Data JPA 프로젝트에서 페이징 처리에 대해 고민하고 계시네요. 질문하신 내용에서 두 가지 방법을 고려하고 계신데, 각 접근법의 장단점을 설명 드리겠습니다.

  1. 응용계층에서 구분하여 처리하기: 이 방법은 Item에 대한 정보를 먼저 가져오고, 해당 Item의 Products를 별도로 페이징 처리하여 불러오는 방식입니다. 이 경우에는 두 번의 쿼리가 발생하게 됩니다. 장점은 불필요한 데이터를 가져오지 않아 메모리를 효율적으로 사용할 수 있다는 점입니다. 하지만 매번 두 번의 쿼리를 실행해야 하므로 성능에 영향을 미칠 수 있습니다. 그러나 데이터의 양이 매우 많지 않다면 이 방법이 속도와 자원의 균형을 이루어 실용적일 수 있습니다.

  2. Product 기반으로 조회하기: Product를 중심으로 Item과의 관계를 Fetch Join하여 조회하는 방식입니다. 이렇게 하면 페이징이 Products 기준으로 이루어지며, 이에 따라 필요한 Item의 정보만 가져오게 됩니다. 이 방법은 컬렉션이 포함된 엔티티 간의 페이징이 복잡해질 수 있지만, JPA나 QueryDSL을 통해 잘 설정하면 효율적인 페이징이 가능합니다. 단, Fetch Join을 사용할 때는 데이터가 중복해서 로딩되지 않도록 주의해야 합니다.

여기서 주의해야 할 점은 JPA에서 Fetch Join과 페이징이 함께 사용되면, Hibernate가 실행 시점에 데이터를 메모리에 모두 로드하려고 하기 때문에, 데이터의 양이 많으면 메모리 부족 등의 성능 문제가 발생할 수 있습니다. 따라서 현실적 상황에 맞게 데이터의 양을 고려하여 페이징을 구현하는 것이 중요합니다.

관련하여 유사한 질문과 답변을 참고하시면 좀 더 도움될 것입니다. 아래 링크를 확인해보세요:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

인생은회전목마님의 프로필 이미지
인생은회전목마

작성한 질문수

질문하기