Controller 소스코드로 설명을 진행하려고 합니다. 아래 소스코드를 참조해주세요.
소스 코드
@GetMapping("/announcement/page")
public Map<String, Object> getAnnouncePage(@RequestParam String reqPageNo, @RequestParam String reqPageRowCnt){
List<AnnouncementDto> announcementDtos = announcementMapper.getAnnouncementListWithSkill();
Map<String, Object> responseMap = new HashMap<>();
int pageNo = Integer.parseInt(reqPageNo);
int pageRowCnt = Integer.parseInt(reqPageRowCnt);
int totalCnt = announcementDtos.size();
int totalPageCnt = (int) Math.ceil((double) totalCnt/pageRowCnt);
int start = (pageNo - 1) * pageRowCnt;
int end = Math.min(start + pageRowCnt, totalCnt);
responseMap.put("list", announcementDtos.subList(start, end)); // 보여질 항목
responseMap.put("totalCnt", totalCnt); // 전체 item 개수
responseMap.put("totalPageCnt", totalPageCnt); // 전체 페이지 개수
responseMap.put("pageNo", pageNo); // 현재 페이지
responseMap.put("pageRowCnt", pageRowCnt); // 페이지에 보여질 item row 개수
return responseMap;
}
1. Request 항목
요청 항목에서는 현재 페이지 번호(=pageNo), 페이지에 보여질 항목의 갯수(=pageRowCnt)를 요청하면된다.
위 소스코드에서는 쿼리파라로 요청하는 방식으로 구현하기 위해, RequestParam으로 사용했다.
요청 url
/announcement/page?reqPageNo=2&reqPageRowCnt=3
2. Response 항목
ORM에서 해당 항목만 가져오도록 start, end 인덱스를 활용해 가져오는 것이 메모리 및 성능 측면에서 더 좋겠지만, 지금 게시글은 페이지 처리 하는 방법에 대해서만 설명하기 위해서 이렇게 Controller에서 모든 것을 표현했다.
소스 코드
int totalCnt = announcementDtos.size();
int totalPageCnt = (int) Math.ceil((double) totalCnt/pageRowCnt);
int start = (pageNo - 1) * pageRowCnt;
int end = Math.min(start + pageRowCnt, totalCnt);
responseMap.put("list", announcementDtos.subList(start, end)); // 보여질 항목
responseMap.put("totalCnt", totalCnt); // 전체 item 개수
responseMap.put("totalPageCnt", totalPageCnt); // 전체 페이지 개수
responseMap.put("pageNo", pageNo); // 현재 페이지
responseMap.put("pageRowCnt", pageRowCnt); // 페이지에 보여질 item row 개수
1) 보여질 Content : 위 자바버전이 11이전이라서 subList를 통해서 List 항목을 가져왔다. 11이후 버전부터는 List.copyOfRange() 도 사용가능하다. start, end 인덱스를 계산해서 사용하면 된다.
2) 전체 item 개수 : 프론트에서 전체 카운트 개수를 보여주기 위해 사용한다.
3) 현재 페이지 : 요청에서 보내준 값을 그대로 보여주면 된다.
4) 페이지에 보여질 item row 개수 : 요청에서 보내준 값을 그대로 보여주면 된다.
프론트도 리액트로 간단하게 구현
1. 리액트로 간단하게 페이지 처리 구현
소스코드는 아래와 같다.
소스 코드
import axios from "axios";
import { useEffect, useState } from "react";
function App() {
const [totalPageCnt, setTotalPageCnt] = useState(0);
const [reqPageNo, setReqPageNo] = useState(1);
const [list, setList] = useState([]);
const getData = () => {
axios
.get(
`http://localhost:8080/api/v1/announcement/page?reqPageNo=${reqPageNo}&reqPageRowCnt=4`
)
.then((res) => {
setTotalPageCnt(res.data?.totalPageCnt);
setList(res.data.list);
});
};
console.log(totalPageCnt);
const clickPage = (page) => () => {
setReqPageNo(page);
};
useEffect(() => {
getData();
}, [reqPageNo]);
return (
<>
<div>hello</div>
<ul>
{list.map((item) => (
<li>
{item.id} : {item.title}
</li>
))}
</ul>
{Array(totalPageCnt)
.fill(0)
.map((_, index) => (
<span onClick={clickPage(index + 1)} key={index}>
{index + 1}
</span>
))}
</>
);
}
export default App;
2. 프론트 결과 확인
총 10개의 데이터를 DB구성했고, 4개씩 보이는 것으로 현재페이지 1페이지를 요청하니 아래와 같이 보이게 된다.