일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 호스트인식
- 참조자료형
- condestates
- 회고
- 코드스테이스
- cta button
- 원시자료형
- OOP
- html
- cta버튼
- 코드스테이츠
- self reliance
- codestate
- 프로토타입
- JavaScript
- 자바스크립트
- WAI-ARIA
- 개발자
- Javascript #코드스테이츠
- 객체지향
- Router
- 프론트엔드
- codestates
- JS
- 계산기
- css
- frontend
- css in js
- CDD
- Prototype
- Today
- Total
jh.nrtv
Next.js Server Component 에서 페이지네이션 구현하기 본문
Next.js와 MongoDB를 사용한 게시판을 만들고 있으며
게시판의 페이지네이션을 구현하는 과정을 기록해보고자 한다.
현재 내 실력과 상황에서 현실적인 구현방법을 고민한 것이며, 분명 이보다 훨씬 나은 방법이 있을 것이라 확신한다.
다음은 기존에 게시판의 글 목록을 보여주는 소스코드이다.
// /community/page.tsx
import { connectDB } from "@/util/database";
export default async function Community() {
const client = await connectDB;
const db = client.db("uppernight");
const result = await db
.collection("community")
.find()
.sort({ _id: -1 })
.toArray();
return (
<div>
<h2> 노력 자랑 게시판</h2>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div> 글 목록 </div>
...
</div>
<div className="community">
{result?.map((el, index) => {
return (
<Content
element={el}
key={index}
// result={result}
/>
);
})}
</div>
</div>
);
}
import 받은 connetDB에는
를 비롯해서 MONGODB_URI를 이용해서 DB와 단순 연결하는 기본 세팅 코드가 있다.
따라서 connectDB를 통해서 DB와 연결한 후에 원하는 데이터를 요청하고 , Array로 변환하고 .map을 통해서 화면에 뿌려주는 간단한 구성이다.
이전에 React를 통해서 페이지네이션을 간단하게 구현한 적이 있기 때문에 해당 코드와 비슷하게 구현하면 쉽게 페이지네이션에 성공할 것이라고 생각했다.
문제상황
하지만 이 상황에서 문제가 발생했다.
- 기존 페이지네이션 코드는 useEffect와 useState를 사용해서 page를 관리하고 , page가 바뀔 때마다 데이터를 요청하는 코드로 구성되었다.
// 아래와 같이 페이지네이션 컴포넌트에 props로 필요한 것들을 내려주는 형태였다.
<Paging page={page} setPage={setPage} />
- 하지만 위 글목록 코드는 Next.js의 서버 컴포넌트로 useState등의 hook이 사용이 불가능했다.
- 따라서 PostsWrapper.ts를 따로 Client Component로 선언해서 그 안에서 hook을 사용해서 구현하려고 시도했으나
- 위의 ConnectDB를 사용해서 데이터 요청을 하기 위해서는 async await의 비동기처리가 필요한데 Client Component에서는 사용이 불가능했다. ( 대신 use(...) 라는 비동기 대체 hook을 제공하기 위해서 준비중이라고 한다.)
- 즉, 정상적인 Data 요청을 위해서는 Server Component를 사용해야 하는데, 페이지네이션을 구현하기 위해서는 시시때때로 바뀌는 page 숫자를 반영하기 위해서는 Client Component를 사용해야 했기 때문에 두 가지 모두를 만족하면서 구현하기가 나에게는 어려웠다.
해결?
결국 기존에 생각했던 페이지네이션 방법을 포기했다.
그 대신에 url parameter를 사용해서 페이지네이션 구현을 시도했다.
먼저 아래와 같은 파일 구성으로 Next.js가 parameter를 이용해서 라우팅 하도록 유도해준다.
이렇게 세팅하고 커뮤니티 탭을 누르면 '.../community/1' 로 라우팅되도록 해서 1페이지가 초기값이 되도록 한다.
다음으로는 서버 컴포넌트에서 url parameter에 접근할 수 있도록 세팅해주고
// /community/[page]
export default async function Community({
params, //쿼리데이터 가져오기위한 코드
}: {
params: { page: string };
})
{
return (
<div>
...
<div/>)
}
파라미터에 있는 page 값에 접근해서 현재 페이지의 값을 넣어준다.
console.log(params);
let page = Number(params.page); //파라미터에서 페이지 가져와서 현재 페이지 값 넣어주기
다음으로는 .skip() .limit() 등을 통해서 원하는 데이터가 올 수 있도록 한다.
const client = await connectDB;
const db = client.db("uppernight");
const postcount: number = await db.collection("community").count();
console.log(params);
let page = Number(params.page); //파라미터에서 페이지 가져와서 현재 페이지 값 넣어주기
const result = await db
.collection("community")
.find()
.sort({ _id: -1 })
.skip((page - 1) * 6) //원하는 데이터 가져오도록 설정->이전 페이지의 글들은 스킵하도록
.limit(6)
.toArray();
이전페이지, 다음페이지에 접근할 수 있는 버튼을 만들어준다.
단, 현 페이지가 1페이지라면 이전 페이지 버튼은 안보이도록 해준다.
<div className="pagination_box">
{page != 1 ? (
<Link href={`community/${page - 1}`}>
<button>이전 페이지</button>
</Link>
) : null}
<div> {page}</div> // 현 페이지 표시
<Link href={`community/${page + 1}`}>
<button>다음 페이지</button>
</Link>
</div>
전체 코드
// /community/[page]
export default async function Community({
params, //쿼리데이터 가져오기위한 코드
}: {
params: { page: string };
}) {
const client = await connectDB;
const db = client.db("uppernight");
const postcount: number = await db.collection("community").count();
console.log(params);
let page = Number(params.page); //파라미터에서 페이지 가져와서 현재 페이지 값 넣어주기
const result = await db
.collection("community")
.find()
.sort({ _id: -1 })
.skip((page - 1) * 6) //원하는 데이터 가져오도록 설정->이전 페이지의 글들은 스킵하도록
.limit(6)
.toArray();
return (
<div>
<h2> 노력 자랑 게시판</h2>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div> 오늘의 노력에 대해서 자랑해주세요!</div>
</div>
<div className="community">
{result?.map((el, index) => {
return (
<Content
element={el}
key={index}
// result={result}
/>
);
})}
</div>
<div className="pagination_box">
{page != 1 ? (
<Link href={`community/${page - 1}`}>
<button>이전 페이지</button>
</Link>
) : null}
<div> {page}</div>
<Link href={`community/${page + 1}`}>
<button>다음 페이지</button>
</Link>
</div>
</div>
);
}
실행화면 ( .../community/2 )
구현은 됐으나, 하면서도 이게 맞나 .. 하는 생각이 든다.
분명 더 나은 방법이 있을 거라고 생각한다.
더 공부하면서 고민해보아야겠다. 🥹
참조링크
next.js 서버컴포넌트에서 쿼리 파라미터 접근
'Next.js' 카테고리의 다른 글
Next.js 프로젝트에 Quill Editor 사용하기 (0) | 2023.07.25 |
---|---|
Next.js 13에 metadata 설정하기 (0) | 2023.07.19 |