Page<T> -> Pagination<T>로 바꾸기
- 국비지원 (스파르타)
- 2025. 3. 18. 18:37
레이어드 아키텍처로 개발하고 있었는데
문득 궁금증이 생겼다. 과연 이게 맞는것일까?
나같은 경우는 Page객체를 도메인객체에 두고 사용을 하고 있었고,
Pageable객체를 프리젠테이션 계층에서 두고 넘겨주고 있었다. 왜냐하면 마땅히 방안이 생각나는게 아니었기 때문에 나는 그냥 사용하기로 했다. 오늘 팀원분들과 코드 리뷰하면서 이렇게 개발하면 될거 같아 소개 하려고 한다.
일단 원래 방식의 문제가 Pagable이라던지 Page<T>가 외부에서 가져온 라이브러리라 인프라스트럭처에서 사용하는것이 맞는걸로 알고 있다.
근데 몇몇의 라이브러리는 편의성을 위해 프리젠테이션 혹은 어플리케이션측에 사용하는걸로 알고 있다.
대표적인 예시가 ResponseEntity<?>인데 얘도 어찌보면 외부에서 가져온것이기때문에 인프라에 있어야 하지만
얘도 편의성을 위해 프리젠테이션에 존재하는 걸로 알고 있다. 근데 어떤건 편의성으로 어떤건 인프라로 이러한 기준은 내가 새워야 하는데 그것이 쉽지 않는듯한 느낌이 든다.
하지만 인프라로 옮겨서 처리할 수 있다면 얘기는 달라진다.
처리가 되어진다는건 하면 된다는거구 위에서 했던 고민은 상관없어진다. 할 수 있다는건 쉽다는 거구 가능하다는 얘기로 생각할 수 있다고 생각한다.
그러면 어떻게 하면 될까?
제일 문제가 되는 Pagable 부터 지우자 그러면 프리젠테이션 혹은 어플리케이션 쪽에 그 정보가 지워질거다.
그러면 직접 받아서 데이터를 넘겨주면 된다.
이제 이렇게 준비가 끝났다면 두번째 Page<T>객체를 지워야 한다. 우리는 도메인 객체에 Pagination<T>을 정의하기로 하였다.
코드는 다음과 같다.
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Pagination<T> {
private final int page;
private final int size;
private final Long total;
private final List<T> content;
public static <T> Pagination<T> of(int page, int size, Long total, List<T> content) {
return new Pagination<>(page, size, total, content);
}
}
이제 이 코드를 어플리케이션 쪽에서 사용하면 된다.
그러면 자연스럽게 어플리케이션은 라이브러리가 아닌 도메인객체를 바라보게 되어진다.
이제 라이브러리를 보지 않게 되어진다. 근데 문제가 생겼다.
바로 기존과 코드가 달라져서 컴파일에러가 발생했다는 점이다.
아... 그전에 레파지토리도 변경을 해야한다.
레파지토리도 이런식으로 변경하였다.
@Repository
public interface QueryProductRepository {
Pagination<Product> searchProduct(Integer page, Integer size, UUID id, String name, Boolean deleted);
}
근데 이 부분 길다.. 이럴때 사용하는것이 커멘드라는거라고 알고 있는데 메시지를 받아서 도메인 객체로 만들어준 객체라 알고 있다.
중간에 정적으로 하든 new를 통해 데이터를 넣어주면 저걸 구현하는 곳은 상대적으로 길이가 줄어들거라 생각한다.
저건 지금 도메인 객체라 저거만으로 사용은 불가능하다. 정확히 말하면 저걸 실행시켜줄 무언가가 없을거 같다.
public Pagination<Product> searchProduct(Integer page, Integer size, UUID id, String name, Boolean deleteCheck) {
List<Product> content = query.select(product)
.where(nullNameCheck(name),
nullIdCheck(id),
nullCheckDeleted(deleteCheck)
)
.from(product)
.offset((long) (page - 1) * size)
.limit(size)
.fetch();
Long total = query.select(product.count())
.where(
nullNameCheck(name),
nullIdCheck(id),
nullCheckDeleted(deleteCheck)
)
.from(product).fetchOne();
return Pagination.of(page, size, total != null ? total : 0, content);
}
코드에서 주목을 해야하는 점은 offset과 limit이라는 점이다.
이걸 직접 계산해서 넣어줘야한다.
그래야 페이징을 처리할 수 있기 때문이다. 지금은 저거에 대한 내용은 생략한다.
근데 생각해보면 여기에서 Page<T>이거 사용해도 되지 않나 싶다. 여기서 계산해주고 적절한 값만 넘겨주면 되면 되지 않을까 생각이 든다.
지금 나는 정적 팩토리 메서드를 사용했는데
of, from,to가 있다고 한다.
of는 여러개를 하나로 합칠때
from은 데이터를 받을 때
to는 데이터를 보낼때 사용이 되어진다고 한다.
그러니까 여기에서는 of이기때문에 저 데이터를 Pagination객체로 묶어주는것이 된다고 생각한다.
아.. 근데 나 면접 준비해야 하는데.. 언제 하냐... ㅜㅜ
'국비지원 (스파르타)' 카테고리의 다른 글
Btree (0) | 2025.03.20 |
---|---|
재고 시스템에 동시성 적용하기 (1) (1) | 2025.03.19 |
프로젝트에 레이어 4 계층 적용기 (2) | 2025.03.17 |
프로젝트에 레코드를 추가해보자. (1) | 2025.03.14 |
4 layer 아키텍처 (0) | 2025.03.13 |