[Spring] PageNation 구현

·2022년 12월 7일
0

Spring

목록 보기
19/24
post-thumbnail

PageNation📜

PageNation은 문서를 개별 페이지로 나누는 프로세스를 말한다.
어떠한 데이터의 목록을 불러올 때, 무한 스크롤을 사용해 목록을 꾸리면 가독성이 떨어지고 한 페이지가 담는 정보의 양도 수없이 많아질 것이다. 이런 경우를 방지하고자, 적절한 순서를 매겨 적당량의 데이터를 한 페이지에 보일 수 있도록 해야 한다.

목록 조회 프로세스 이해하기🧐

1. 클라이언트의 요청 👉 Controller

클라이언트의 요청을 제일 먼저 캐치해서 적절한 메서드에 Mapping 하는 일은 API계층Controller에서 진행한다.

2. Controller 👉 Service

클라이언트의 요청을 받은 Controller비즈니스 로직이 담긴 Service에게 해당 요청과 요청에 필요한 파라미터 값을 넘겨준다.

Service는 해당 요청에 대한 데이터를 Repository에서 불러온다. 이때 사용하는 Repository 메서드는 findAll()이다!

3. Service 👉 Repository

Repository는 구현된 로직 하나 없지만, JpaRepository를 상속 받고 있어 JpaRepository의 메서드를 사용할 수 있다.

🧐 JpaRepository<Member, Long>
Member는 JpaRepository를 상속 받고 있는 Repository가 다루는 Entity 클래스를 가르키고, Long은 해당 Entity 클래스의 @Id 애너테니션이 붇은 필드 변수의 타입을 의미한다.

⭐JpaRepository

JpaRepository의 메서드인 findAll()를 살펴보면 어디서, 어떻게 Pagenation를 구현해야 하는지 전혀 감이 오지 않는다.

그치만 두 눈 크게 뜨고 살펴보면 답이 보인다.🤓
(나는 몰랐지만..누가 알려줘서 깨달았지만..다음의 나는 잘 찾겠지..)

JpaRepositoryPagingAndSortingRepository를 상속 받고 있다.

🤔 pagenation...PagingAndSortingRepository...☝️😯..

Pageable 객체를 파라미터로 넣어 findAll()를 호출하면 Page<Member>를 얻을 수 있다!

Pagenation 구현 전 파악쓰📝

Pageable

최종적으로 Repository에서 findAll()을 호출하기 위해서는 Pageable 객체를 생성해야 한다.

그러나 Pageable인터페이스로 객체를 생성할 수 없고, 구현체의 도움을 받아야 한다!

Pageable에 대해 살펴보면 ofSize()new Pageable 반환하는 메서드로 정의되어 있으며, PageRequest.of(0, pageSize)을 리턴한다.

즉, PageRequest.of(0, pageSize)Pageable의 객체라는 의미가 된다.

PageRequest

PageRequestAbstractPageRequest를 상속 받은 클래스이고, AbstractPageRequestPageable 인터페이스를 구현한 추상 클래스였다.

PageRequestPageable의 하위 클래스나 마찬가지이므로 PageRequestPageable의 객체를 생성할 수 있다!(다형성!)

🤓☝️

of() 메서드를 통해 PageRequest 객체를 생성할 수 있음을 알 수 있다!

Pagenation 구현📜

1. 클라이언트의 요청 👉 Controller

PageRequestof() 메서드는 공통적으로 int page, int size를 파라미터로 받고 있다는 것을 알 수 있다.

그렇다면 이 파라미터의 값을 우리는 어디서 받아와야 할까?
🤓☝️
당연 클라이언트의 요청으로부터 받아와야 한다! 그러면 클라이언트가 요청할 때마다, 페이지수와 페이지 마다 입력될 데이터의 개수를 하나하나 적어줘야 하나?

URI의 구조를 보면 url-path 다음에 붙은 것이 query, 웹 서버에 보내는 추가적인 질문을 옵션으로 보낼 수 있다.

우리가 사용할 int page, int size는 이 query로 불러와 사용하게 할 것이다.

@RequestParam

URI에서 query의 값을 멤버 변수의 값으로 지정해주는 애너테이션.
만약 query에서의 이름과, 변수의 이름이 다를 경우에는 @RequestParam("쿼리 이름")으로 사용할 수 있다.

🧐 @PathVariable
이름에서 알 수 있듯이 url-path의 값을 지정하는 애너테이션이다.

2. Controller 👉 Service

Controller는 클라이언트의 요청에서 받은 int page, int size를 파라미터로 담아 ServicefindMembers()메서드를 호출한다.

Service 클래스에서는 파라미터로 받은 값으로 PageRequestof() 메서드를 호출해 Pageable 객체를 생성한다.

Sort.by("memberId").descending()

Member 객체의 memberId의 이름을 가진 변수에 따라 정렬하겠다는 의미!

🧐 page는 왜 -1를 해줄까?
배열과 마찬가지로 Page의 index도 0부터 시작하기 때문이다!

3. Service 👉 Repository

이제 생성된 Pageable 객체를 파라미터로 RepositoryfindAll() 메서드를 호출해 Page<Member>를 생성한다.

Page<T>

제네릭 타입의 클래스 객체들을 Page화 해주는 일종의 List.

4. Service 👉 Controller

Repository에서 Page<Member> 로 찾은 회원 목록 데이터를 Service의 메서드를 호출했던 Controller에게 반환한다.

반환한 Page<Member>를 이용해 페이지 정보와, 멤버 정보를 ResponseEntity에 담아 클라이언트에게 응답을 보낸다.

Pagenation 구현 완🤓☝️

profile
🧑‍💻백엔드 개발자, 조금씩 꾸준하게

0개의 댓글