나의 개발일지
[SpringBoot] Page와 PageImpl 본문
HotShare 1차 프로젝트 기간을 진행하며 많은 것을 배웠습니다.
특히 제가 모르는 부분들을 다른 분들의 코드를 참고하는 시간은 각별했습니다.
그 중에는 PageImpl 과 PageRequest 라는 낯선 개념들도 등장했는데요.
실제로 어떤 역할을 하는지는 모르겠지만 우선 따라서 써본 결과 잘 작동하기 때문에 프로젝트 기간 동안에는 그러려니하고 넘어갔습니다.
@GetMapping("/me")
@MemberOnly
public ResponseEntity<ResponseDto<MyCashLogResponse>> showMyCashLogs(
final Pageable pageable,
@Auth final Accessor accessor
) {
Long memberId = accessor.getMemberId();
Page<CashLog> cashLogs = cashLogService.findMyPageList(memberId, pageable);
List<CashLogConfirmResponse> cashLogConfirmResponses =
cashLogs.stream()
.map(CashLogConfirmResponse::of)
.toList();
PageImpl<CashLogConfirmResponse> cashLogConfirmPage =
new PageImpl<>(
cashLogConfirmResponses,
pageable,
cashLogs.getTotalElements());
MyCashLogResponse myCashLogResponse = cashLogService.getMyCashLogById(
memberId,
cashLogConfirmPage
);
return ResponseEntity.ok(new ResponseDto<>(
HttpStatus.OK.value(),
"캐시 사용 내역 조회 성공", null,
null, myCashLogResponse
));
}
위는 해당 코드입니다.
Page 와 관련하여 세가지 단계를 거칩니다.
1. 프론트에서 전달 받은 page와 size값을 Pageable 객체로 받아 Repository에 넘기면 Page<> 객체를 반환받습니다.
2. Page<> 객체의 내용물들을 map 함수를 통해 dto 로 변환 후 List를 반환합니다.
3. 반환 받은 List를 다시 PageImpl 의 생성자를 통해 PageImpl<> 객체로 변환합니다.
이렇게 완성해두고 다른 코드들을 찬찬히 살피던 중 이상한 점을 발견했습니다.
팀원분이 작성하신 부분에선 이 과정 중 dto 로 변환 후 List로 변환한 후 PageImpl을 생성하는 작업 없이 바로 Page를 엔드포인트의 반환값 중 일부로 사용하더군요.
이런 식의 활용도 결국 문제가 없다니 신기했습니다.
제가 PageImpl 을 처음 접한 것은 rest api 환경의 서버를 처음 만들게 된 이번 프로젝트부터였기 때문에 다른 분이 작성한 것만 보고 지레짐작하길 rest api 환경에선 PageImpl을 사용해야하는 줄 알았으니까요
문제가 없다는 것은 팀원분의 코드가 정상 작동하는 것을 보아 틀림이 없고 그렇다면 뭔가 다른 부분이 있는 거겠지?

이 콘솔창은 제 팀원분 Page의 dto 반환 값이고

이것은 제가 작성한 PageImpl의 dto 반환값입니다.
content 를 시작으로 totalPages에 이르기까지 하나도 다른게 없습니다.
그렇다면 PageImpl 는 무엇을 위한 것일까요?
2.3. PageImpl
Finally, there’s the PageImpl class, which provides a convenient implementation of the Page interface that can be used to represent a page of results from a query, including the pagination metadata. It’s commonly used in conjunction with Spring Data’s repository interfaces and pagination mechanisms to retrieve and manipulate data in a pageable manner.
Now that we’ve got a basic understanding of the involved components, let’s set up a simple example.
PageImpl 클래스는 Page 인터페이스의 구현체로, 쿼리 결과의 한 페이지와 페이징 메타데이터를 표현하는 데 유용하게 사용됩니다. 주로 Spring Data의 리포지토리 인터페이스 및 페이징 메커니즘과 함께 사용되어 데이터를 페이지별로 검색하고 조작하는 데 적합합니다. 이로써 간단한 예제 설정에 대한 기본 이해를 마쳤습니다.
https://www.baeldung.com/spring-data-jpa-convert-list-page
위는 Baeldung 에서 가져온 글입니다.
결론은 PageImpl은 곧 Page 라고 보면 될 것 같습니다. 구현체라는 개념에 대한 이해가 부족했기 때문에 생긴 혼란이라고 볼 수 있겠네요.
저희가 그동안 사용해왔던 Page 또한 일종의 PageImpl이라고 생각할 수 있었던 겁니다.
PageImpl 을 Page로 형변환할 경우엔 기존 Page와 다를 바 없이 사용할 수 있다면 이제 제가 작성했던 코드를 좀 더 줄일 필요가 있습니다.
@GetMapping("/me")
public ResponseEntity<ResponseDto<MyCashLogResponse>> showMyCashLogs(
final Pageable pageable,
@Auth final Accessor accessor
) {
Member member = memberService.getMemberById(accessor.getMemberId());
Page<CashLogConfirmResponse> cashLogConfirmResponses = cashLogService.findMyPageList(member, pageable).map(CashLogConfirmResponse::of);
MyCashLogResponse myCashLogResponse = cashLogService.getMyCashLogById(
member,
cashLogConfirmResponses
);
return ResponseEntity.ok(new ResponseDto<>(
HttpStatus.OK.value(),
"캐시 사용 내역 조회 성공", null,
null, myCashLogResponse
));
}
불필요했던 과정들을 없애고 코드의 역할을 더 명확히 하기 위해 몇몇 코드는 합쳐보았습니다.
한결 깔끔해진 모습이 마음에 드네요.
또한 이와 비슷한 구현체와 인터페이스의 관계론 Pageable과 PageRequest가 있습니다.
'Language > SpringBoot' 카테고리의 다른 글
| [SpringBoot] WebClient 비동기 흐름 내 Transaction 비활성화 트러블슈팅 - 2 ( 문제 발생 및 해결 ) (0) | 2024.02.22 |
|---|---|
| [SpringBoot] WebClient 비동기 흐름 내 Transaction 비활성화 트러블슈팅 - 1 ( 토스페이먼츠 WebClient 로 구현 ) (0) | 2024.02.22 |
| [SpringBoot] hiddenmethod를 이용한 타임리프 환경에서 PutMapping, DeleteMapping 활용법 (1) | 2024.01.14 |
| 스프링 시큐리티 환경에서 H2 사용하기 위한 csrf 제어 코드 (0) | 2024.01.07 |
| 스프링부트 TDD 환경에 유용한 DB쿼리 송출 yml 코드 (0) | 2024.01.07 |