티스토리 뷰
Page 인터페이스
Paging을 위해서 Spring boot에서는 Page 인터페이스를 제공합니다. 이 인터페이스의 기본 스펙을 살펴보면 다음과 같습니다.
{
"content": [
... (data)
],
"pageable": {
"sort": {
"unsorted": false,
"sorted": true,
"empty": false
},
"pageNumber": 0,
"pageSize": 7,
"offset": 0,
"paged": true,
"unpaged": false
},
"last": true,
"totalElements": 7,
"totalPages": 1,
"first": true,
"numberOfElements": 7,
"size": 7,
"sort": {
"unsorted": false,
"sorted": true,
"empty": false
},
"number": 0,
"empty": false
}
Page 인터페이스를 통해 리턴을 해주면 FE는 pageable 정보를 기반으로 화면에 적절한 UI를 보여줍니다. 이 인터페이스는 Spring에서 제공해주는 interface로 페이징한 데이터를 간편하게 반환해줄 수 있습니다.
Page 인터페이스의 단점
1. 비용 문제
page 인터페이스는 기본적으로 Spring에서 제공해주는 interface기 때문에 공통화를 위해 내부에 굉장히 많은 데이터가 필요합니다. 다만 이 데이터들이 굉장히 많이 들어있는데 이 인터페이스에는 너무 많은 데이터들이 들어있습니다.
최근 트랜드는 클라우드에서의 비용을 줄이기 위해 네트워크 통신 시 비용을 최소화하고 있습니다. 실제로 AWS 문서를 참고하면 다음과 같은 내용이 들어있습니다.
애플리케이션 및 쿼리 디자인을 검토합니다. 애플리케이션과 데이터 저장소 간에 전송되는 데이터의 양을 줄이는 방법을 찾으십시오. 읽기 전용 복제본을 사용하도록 애플리케이션 또는 쿼리를 설계하는 것이 좋습니다.
https://aws.amazon.com/ko/blogs/korea/exploring-data-transfer-costs-for-aws-managed-databases/
또한 네트워크는 세그먼트 단위로 전송 되기 때문에 데이터가 많다면 FE서버와 BE 서버간에 커넥션 시간도 길어진다고 고려가 되는 상황입니다.
이런 면에서 Page 인터페이스의 모든 데이터를 FE서버에서 이용하는 것이 아니라면 불필요한 데이터 때문에 계속해서 서버간 커넥션과 네트워크 통신 비용이 낭비되는 상황입니다.
2. 인터페이스 자체 유연성 낮음
Page 인터페이스는 공통으로 사용하기 위해 만들어진 Spring 제공 인터페이스로 외부에서 수정이 불가합니다. 하지만 외부에서 데이터를 전송해줄 때 항상 여러가지 상황을 고려해야하여 Page는 적합하지 않다고 생각했습니다.
코드를 예시로 들어보겠습니다.
ResponseEntity<Page<MemberResponse>> getMembers(final Pageable pageable) {
// ... //
}
다음과 같은 회원 정보들의 정보를 리턴해주는 api가 존재한다고 생각했을 때 당장은 문제가 없어 보입니다.
하지만 만약 저 api에서 호출한 사용자 정보를 리턴하는 요구사항이 들어왔다고 가정해봅니다. 우리는 Page 인터페이스 내부를 수정할 수 없기 때문에 하나의 DTO를 만들 수 밖에 없습니다. 그렇다면 굉장히 많은 변화가 필요한 상황입니다.
실제로 테스트 코드를 의무화하고 있다면 testcode에도 굉장히 많은 변화가 필요합니다.
Page 인터페이스 커스텀하기
위와 같은 문제를 해결하고 Page 인터페이스의 장점만을 최대한 살리기 위해 Page<> 인터페이스를 매게 변수로 만든 custom 객체를 이용할 수 있습니다. 구조는 다음과 같습니다.
public class PageCustomResponse<T> {
private List<T> data = new ArrayList<>();
private long totalPage;
private int pageSize;
private long totalElements;
private int number;
public static <T> PageCustomResponse<T> of(Page<T> response) {
return new PageCustomResponse<>(
response.getContent(),
response.getTotalPages(),
response.getSize(),
response.getTotalElements(),
response.getNumber());
}
}
위와 같이 커스텀을 하였을 때 다음과 같은 장점을 얻을 수 있습니다.
- 네트워크 비용을 최소화하여 클라우드 비용 자체를 줄일 수 있다.
- 넘겨줘야할 데이터가 적기 때문에 커넥션 유지 자체가 길어지지 않는다.
- 사용자가 정의한 객체기 때문에 요구사항이 변경되더라도 코드 한줄 간단하게 추가하여 해결할 수 있다.
- 일부 요구사항만 변경된다 하더라도 공통적으로 쓰이는 Page객체로 되어 있기 때문에 해당 객체를 복사하여 코드 한줄과 이름만 변경해주면 쉽게 변경할 수 있다.
물론 장점만이 있는 것은 아닙니다. Custom을 하게 된다면 WAS내에선 객체가 하나 더 생겨버려 Heap 메모리나 GC동작에 있어 stop the world가 비교적 많이 발생하기에 적용하기 전에 고려해야할 상황은 반드시 있습니다.
마침.
'Spring Framwork & JPA' 카테고리의 다른 글
[Redis] redis에서 get 연산이 일어나는 로직에 Transactional을 건다면? (0) | 2023.01.03 |
---|---|
많은 외부 API를 호출해야 하는 상황에서 성능 개선 (with. webClient) (0) | 2023.01.02 |
Redis 직렬화/역직렬화시 생기는 Issue (0) | 2022.05.23 |
[Thymleaf - 1부] 타임리프의 주요 문법 (0) | 2022.02.21 |
SpringBootApplication과 Spring AutoConfigure란? (0) | 2022.02.17 |
- Total
- Today
- Yesterday
- swarm
- MySQL
- 개발자
- Kotlin
- 자바
- 인터뷰
- Spring
- Redis
- JPA
- IT
- 개발
- 면접 준비
- 프로그래밍
- 동시성
- thread
- 취업준비
- docker
- 취업
- 백엔드
- 취준
- 면접준비
- DB
- java
- CS
- 면접
- 프로젝트
- 코드
- 코딩
- 게시판
- DevOps
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |