2025. 3. 2. 22:46ㆍ프론트엔드/Next JS
Next.js에서 getServerSideProps를 활용한 도서 데이터 관리
1. 개요
Next.js에서는 서버 측에서 데이터를 가져와 페이지를 렌더링할 때 getServerSideProps를 사용할 수 있습니다. 이번 글에서는 도서 데이터를 가져오는 웹 애플리케이션을 예제로, getServerSideProps를 활용하여 서버에서 데이터를 가져와 렌더링하는 방법을 정리합니다.
이 글에서 다룰 주요 내용은 다음과 같습니다.
- getServerSideProps를 사용하여 서버에서 데이터를 불러오기
- fetchBooks, fetchRandomBooks 등을 활용한 API 호출
- BookItem 컴포넌트를 이용한 데이터 렌더링
- 개별 도서 페이지(/book/[id])에서 특정 도서의 데이터를 불러오는 방법
2. getServerSideProps를 사용한 데이터 패칭
Next.js에서 getServerSideProps는 서버에서 데이터를 가져온 후, 페이지를 렌더링할 때 사용됩니다. 이를 활용하면 클라이언트에서 API를 호출하지 않고, 페이지 요청 시 서버에서 데이터를 미리 가져와 렌더링할 수 있습니다.
📌 코드 예시 (pages/index.tsx)
import SearchableLayout from "@/components/searchable-layout";
import style from "./index.module.css";
import { ReactNode } from "react";
import BookItem from "@/components/book-item";
import { InferGetServerSidePropsType } from "next";
import fetchBooks from "@/lib/fetch-books";
import fetchRandomBooks from "@/lib/fetch-random-books";
// 서버에서 도서 데이터 가져오기
export const getServerSideProps = async () => {
const [allBooks, recoBooks] = await Promise.all([
fetchBooks(),
fetchRandomBooks(),
]); // 병렬 처리!
return {
props: {
allBooks,
recoBooks,
},
};
};
// 홈 페이지 컴포넌트
export default function Home({
allBooks,
recoBooks,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<div className={style.container}>
<section>
<h3>지금 추천하는 도서</h3>
{recoBooks.map((book) => (
<BookItem key={book.id} {...book} />
))}
</section>
<section>
<h3>등록된 모든 도서</h3>
{allBooks.map((book) => (
<BookItem key={book.id} {...book} />
))}
</section>
</div>
);
}
// 페이지 레이아웃 설정
Home.getLayout = (page: ReactNode) => {
return <SearchableLayout>{page}</SearchableLayout>;
};
✨ 설명
- getServerSideProps에서 fetchBooks()와 fetchRandomBooks()를 호출하여 도서 데이터를 가져옵니다.
- 두 개의 API 요청을 병렬(Promise.all)로 처리하여 성능을 최적화합니다.
- 가져온 데이터를 Home 컴포넌트에서 렌더링하여 화면에 표시합니다.
- Home.getLayout을 사용하여 페이지 전체에 SearchableLayout을 적용합니다.
3. 도서 데이터 가져오기 (API 호출)
도서 데이터를 가져오는 함수는 lib/fetch-books.ts, lib/fetch-random-books.ts 등으로 분리하여 관리할 수 있습니다.
📌 모든 도서 목록 가져오기 (lib/fetch-books.ts)
import { BookData } from "@/types";
// 모든 책 데이터 불러오기
export default async function fetchBooks(
q?: string // 검색어 옵션 (q)
): Promise<BookData[]> {
let url = "http://localhost:12345/book";
if (q) {
url += `/search?q=${q}`;
}
try {
const response = await fetch(url);
return await response.json();
} catch (err) {
console.error(err);
return [];
}
}
📌 추천 도서 가져오기 (lib/fetch-random-books.ts)
import { BookData } from "@/types";
export default async function fetchRandomBooks(): Promise<BookData[]> {
const url = "http://localhost:12345/book/random";
try {
const response = await fetch(url);
return await response.json();
} catch (err) {
console.error(err);
return [];
}
}
✨ 설명
- fetchBooks()는 기본적으로 모든 도서를 가져오지만, q 값을 전달하면 검색 결과를 반환합니다.
- fetchRandomBooks()는 특정 API 엔드포인트(/book/random)를 호출하여 추천 도서를 가져옵니다.
- try-catch 블록을 사용하여 API 호출이 실패할 경우 빈 배열을 반환하도록 처리합니다.
4. 개별 도서 상세 페이지 (/book/[id]) 구현
특정 도서의 정보를 가져와 상세 페이지를 구성하려면, getServerSideProps를 사용하여 ID에 해당하는 도서 데이터를 가져와야 합니다.
📌 코드 예시 (pages/book/[id].tsx)
import { GetServerSidePropsContext, InferGetServerSidePropsType } from "next";
import style from "./[id].module.css";
import fetchOneBook from "@/lib/fetch-one-book";
// 특정 도서 가져오기
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const id = context.params!.id;
const book = await fetchOneBook(Number(id));
return {
props: {
book,
},
};
};
// 도서 상세 페이지 컴포넌트
export default function Page({
book,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
if (!book) return "문제가 발생했습니다. 다시 시도하세요.";
const { title, subTitle, description, author, publisher, coverImgUrl } = book;
return (
<div className={style.container}>
<div
className={style.cover_img_container}
style={{ backgroundImage: `url('${coverImgUrl}')` }}
>
<img src={coverImgUrl} alt={title} />
</div>
<div className={style.title}>{title}</div>
<div className={style.subTitle}>{subTitle}</div>
<div className={style.author}>
{author} | {publisher}
</div>
<div className={style.description}>{description}</div>
</div>
);
}
📌 개별 도서 데이터 가져오기 (lib/fetch-one-book.ts)
import { BookData } from "@/types";
export default async function fetchOneBook(id: number): Promise<BookData | null> {
const url = `http://localhost:12345/book/${id}`;
try {
const response = await fetch(url);
return await response.json();
} catch (err) {
console.error(err);
return null;
}
}
✨ 설명
- getServerSideProps에서 context.params!.id를 통해 URL의 id 값을 가져옵니다.
- fetchOneBook(id)를 호출하여 해당 도서의 데이터를 가져옵니다.
- book 데이터가 없을 경우, 사용자에게 "문제가 발생했습니다"라는 메시지를 출력합니다.
- coverImgUrl을 style의 backgroundImage로 설정하여 커버 이미지를 표시합니다.
5. 결론
이번 글에서는 Next.js의 getServerSideProps를 활용하여 서버에서 데이터를 가져오는 방법을 살펴보았습니다. 이를 통해 데이터가 페이지 요청 시 서버에서 미리 렌더링되므로 SEO와 초기 로딩 속도를 최적화할 수 있습니다.
'프론트엔드 > Next JS' 카테고리의 다른 글
| 📌 Next.js에서 getStaticProps와 getStaticPaths를 활용한 SSG 정리 (0) | 2025.03.05 |
|---|---|
| Next.js의 SSG(Static Site Generation) 개념과 활용 (0) | 2025.03.02 |
| React Router에서 accessToken 없을 경우 리디렉션 처리하기 (0) | 2025.03.02 |
| 백준 2206번: 벽 부수고 이동하기 - BFS 최단 거리 문제 정리 (0) | 2025.03.01 |
| 📌 API 통신 방법 정리 (컴공 회의실) (0) | 2025.03.01 |