서버를 가동한 후 페이징 처리가 된 기능을 쓰면 딱 한 번 나오는 로그가 있다.
rationWarningLoggingModifier
: Serializing PageImpl instances as-is is not supported, meaning that there is no guarantee about the stability of the resulting JSON structure!
For a stable JSON structure, please use Spring Data's PagedModel
(globally via @EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO))
or Spring HATEOAS and Spring Data's PagedResourcesAssembler as documented in https://docs.spring.io/spring-data/commons/reference/repositories/core-extensions.html#core.web.pageables.
이 로그는 PageImpl 객체를 ResponseEntity<Page> 형태로 반환하면, JSON 구조가 불안정할 수 있다고 경고해주는 로그이다.
현재 별 문제는 없이 돌아가고 있지만 뭔가 로그에 찍히면 고치고 싶다.
이걸 쓰면 전역 설정이 되어 자동 변환 가능하다
하지만!!!!!
PagedModel을 사용하면 반환형이
{
"content": [데이터들......],
"page": {
"size": 10,
"number": 1,
"totalElements": 228,
"totalPages": 23
}
}
이렇게 고정이 되어버린다.
그런데 우리 서비스는
"content": [], // 데이터들
"number": 1, // 현재 페이지 (0부터 시작)
"size": 2, // 요청한 페이지 크기
"totalPages": 10, // 전체 페이지 수
"totalElements": 20, // 전체 아이템 수
"numberOfElements": 2, // 현재 페이지에 실제 담긴 아이템 수
"first": false, // 첫 페이지인지 여부
"last": false, // 마지막 페이지인지 여부
"empty": false // 현재 페이지가 비었는지
이런 부가적인 정보들이 더 필요했다.
그래서 이 방법 말고, 다른 방법을 사용해야 했다.
public class PageResponse<T> {
private List<T> content;
private int number; // 현재 페이지 번호 (0부터 시작)
private int size; // 페이지당 아이템 수
private int totalPages; // 전체 페이지 수
private long totalElements; // 전체 아이템 수
private int numberOfElements; // 현재 페이지의 아이템 수
private boolean first; // 첫 페이지 여부
private boolean last; // 마지막 페이지 여부
private boolean empty; // 현재 페이지가 비어있는지 여부
public PageResponse(Page<T> page) {
this.content = page.getContent();
this.number = page.getNumber();
this.size = page.getSize();
this.totalPages = page.getTotalPages();
this.totalElements = page.getTotalElements();
this.numberOfElements = page.getNumberOfElements();
this.first = page.isFirst();
this.last = page.isLast();
this.empty = page.isEmpty();
}
}
여기서
private long totalElements; // 전체 아이템 수
이것만 long 타입인 이유는 Spring Data의 Page 인터페이스에서 정해둔 규칙이기 때문이다.
public interface Page<T> extends Slice<T> {
int getTotalPages();
long getTotalElements();
}
실제 데이터 개수가 int의 범위를 넘을 수도 있기 때문에 더 큰 범위를 표현할 수 있는 long을 사용하는 것이다.
그리고 컨트롤러에서는
Page<ReviewResponseDTO> reviews = ~~~~~~
return ResponseEntity.ok(new PageResponse<>(reviews));
요렇게 내가 만든 응답 객체인 new PageResponse<>()를 사용해주면
더이상 PageImpl 직렬화 경고 로그가 뜨지 않게 된다!