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

빛혜원님의 프로필 이미지
빛혜원

작성한 질문수

실전! 스프링 데이터 JPA

페이지를 유지하면서 엔티티를 DTO로 변환관련하여 질문

작성

·

1.1K

·

수정됨

0


스프링 데이터 JPA 페이징과 정렬 강의 부분에서

페이지를 유지하면서 엔티티를 DTO로 변환하기

Page<Member> page = memberRepository.findByAge(10, pageRequest);
Page<MemberDto> dtoPage = page.map(m -> new MemberDto());

페이지를 유지하면서 엔티티를 DTO로 변환하는 예제가 있습니다.

만약에 아래와 같이

Page<Member> page = memberRepository.findByAge(10, pageRequest);

List<Member> dtoPage = faqListPage.stream().map(MemberDto::new)
    .toList();

List<> 로 반환하여 페이징 처리를 하였는데 페이지를 유지한 첫번째 방식 차이점이 있을까요??

실무에서는 어떤 방식을 사용하나요?

답변 1

0

안녕하세요, 빛혜원 님. 공식 서포터즈 y2gcoder 입니다.

빛혜원님께서 진행하고 계신 프로젝트의 요구사항에 따라 달라질 것 같습니다. 저는 간단하게 Page를 List + 페이징 정보 정도로 이해하고 있습니다. Page 객체의 메서드들을 보시면 아시겠지만, 페이징 처리를 위해 필요한 값들을 다 갖고 있다고 보셔도 좋습니다. 그래서 보통 웹 페이지에서 보이는 페이지 번호와 이전, 다음으로 페이징하는 목록 화면을 구성할 때 Page 객체의 페이징 정보들을 아주 유용하게 사용할 수 있습니다. Mybatis를 사용할 때는 페이징 처리를 위해 페이징 처리를 위한 객체를 따로 만들어 계산해줘야 했던 것을 생각하면 꿀 기능이라고 생각합니다.

감사합니다.

빛혜원님의 프로필 이미지
빛혜원
질문자

아하........... Page 객체 타입에 대해 잘 알지 못한채로 프로젝트를 진행 했습니다.

그래서 답변해주신것 처럼 좋은기능을 알지 못한채........ 일일히 페이징 처리를 위해 객체를 따로 만들어 계산해줬어요 ㅠㅠ... ㅋㅋㅋㅋㅋ 답변 감사합니다! 혹시 예시 코드 있을까요??

 

그리고 혹시 챗 gpt 에 검색도 해봤는데

 

  • 첫 번째 방식은 Spring Data JPA의 Page 객체를 사용하여 페이징 처리를 한 번에 수행합니다. 이는 데이터베이스 쿼리를 최적화하고 효율적으로 처리하는 장점이 있습니다.

  • 두 번째 방식은 페이징 처리가 된 엔티티를 List에 담아 처리하기 때문에, 데이터베이스 쿼리에 대한 페이징 처리가 아니라 메모리 상에서의 페이징이 이루어집니다. 따라서 큰 데이터셋의 경우 메모리 부하가 발생할 수 있습니다.

실무에서의 선택: 실무에서는 대부분 첫 번째 방식을 사용하는 편입니다. Spring Data JPA에서 제공하는 Page 객체를 활용하여 페이징 처리를 하면, 데이터베이스 쿼리를 효율적으로 실행하고 페이징 처리된 결과를 반환할 수 있기 때문입니다. 이는 데이터베이스의 성능을 최적화하고 메모리 사용량을 줄일 수 있습니다.

두 번째 방식은 메모리 상에서의 페이징 처리를 수행하므로, 작은 규모의 데이터셋에 대해서는 사용할 수 있지만, 대량의 데이터에 대해서는 성능 이슈가 발생할 수 있습니다. 따라서 대부분의 경우 Spring Data JPA의 Page 객체를 활용하는 첫 번째 방식이 권장됩니다.

이 내용도 맞을까요?

예시 코드에 대해서는 아래와 같이 추천드릴 수 있을 것 같습니다.

page: https://ibks-platform.tistory.com/277 (페이지를 이용한 REST API 응답을 보여주는 예제입니다. json으로 응답온 것을 보면 좀 더 이해하기 쉬우실 것 같아서 해당 링크를 선택했습니다.)
slice: https://devjem.tistory.com/74 (Slice는 Page의 상위 타입으로, 링크의 예처럼 모바일 환경에서 많이 사용하는 무한 스크롤링 예제에 사용하기 좋은 것 같습니다. 해당 예제도 필요하실까 싶어 첨부하겠습니다.)

실제로 Page나 Slice를 사용해보시면 생각보다 쉽게 사용하실 수 있으실 거라 생각합니다 :)

그리고 ChatGPT의 답변은 일정 부분에서는 맞습니다. 다만 빛혜원님께서는

Page<Member> page = memberRepository.findByAge(10, pageRequest);

List<Member> dtoPage = faqListPage.stream().map(MemberDto::new)
    .toList();

이렇게 코드를 짜셨고, 위의 findByAge()에서 이미 pageRequest 객체를 넣어 페이징된 쿼리로 조회하고 계십니다. 이 때 날아간 sql을 확인해보시겠습니까? limit 를 사용한 쿼리가 날아갔다면, 이미 데이터베이스 쿼리를 통한 페이징이 이루어진 것이기 때문에 첫번째 방식과 동일합니다. 메모리를 통한 페이징 정렬에 대한 내용은 해당 링크(클릭)을 참고해보시는 것을 추천합니다 :)

빛혜원님의 프로필 이미지
빛혜원
질문자

>.< 유용한 정보 감사합니다.

파이팅입니다

빛혜원님의 프로필 이미지
빛혜원

작성한 질문수

질문하기