Frontend/Next.js
[Next.js/App Router] 7. 데이터 페칭
ayeongjin
2025. 2. 8. 00:35
데이터 페칭
1) Next.js에서 데이터 페칭
서버 컴포넌트에서의 데이터 페칭
// 서버 컴포넌트에서 비동기 함수 사용 가능
export async function Page(props){
const data = await fetch('...'); // 기존의 getServerSideProps, getStaticProps 대체
return <div>...<div>
}
- 클라이언트 컴포넌트에서는 async 키워드 사용 불가 (브라우저에서 문제 발생 가능)
- Next.js 공식 문서에서는 데이터는 필요한 곳에서 직접 불러오는 것이 최적의 방식이라고 권장
2) 서버 컴포넌트에서 데이터 불러오기 예제
- 서버 컴포넌트는 async 함수로 정의 가능
- 데이터 요청 실패 시 오류 메시지 출력
// 컴포넌트 자체가 async function이 될 수 있음
// fetch()를 컴포넌트 안에서 직접 실행 가능 (별도 데이터 페칭 함수 필요 없음)
async function AllBooks() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book`
);
if (!response.ok) {
return <div>오류가 발생했습니다 ...</div>;
}
const allBooks: BookData[] = await response.json();
return (
<div>
{allBooks.map((book) => (
<BookItem key={book.id} {...book} />
))}
</div>
);
}
- 기존 Page Router 방식: getServerSideProps 같은 별도 함수에서 데이터를 가져와서 props로 전달해야 함
- 새로운 App Router 방식: 서버 컴포넌트 내부에서 async/await을 직접 사용하여 데이터를 불러올 수 있음
cf) 환경변수를 활용한 API 주소 관리
.env 파일에 API 서버 주소 저장:
NEXT_PUBLIC_API_SERVER_URL=http://localhost:12345
- NEXT_PUBLIC_을 붙이지 않으면 서버에서만 사용할 수 있는 변수로 분류됨 → 오류 발생 가능
- ${process.env.NEXT_PUBLIC_API_SERVER_URL} 로 불러와서 사용 가능
Next.js 데이터 캐싱 (Data Cache)
fetch 요청의 결과를 Next.js 서버에서 캐싱하여 불필요한 API 요청을 줄이고 성능을 최적화하는 기능
데이터 캐싱 기본값
- 기본값: cache: "no-store"
- 캐싱을 설정하여 성능 최적화 가능
1) cache: "no-store" (캐싱 안함)
async function AllBooks() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book`,
{ cache: "no-store" } // 매번 새로운 데이터 요청
);
}
- 항상 새로운 데이터를 요청 (SSR과 유사)
- 데이터가 자주 바뀌는 페이지에서 유용
2) cache: "force-cache" (무조건 캐싱)
async function RecoBooks() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/random`,
{ cache: "force-cache" } // 항상 캐싱됨
);
}
- 한 번 호출된 이후에는 다시 API 요청하지 않음
- 정적 데이터에 적합
- 이렇게 캐싱된 데이터는 .next/cache/fetch-cache 폴더 안에 저장된다.
3) next: { revalidate: 3 } (ISR과 유사)
async function RecoBooks() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/random`,
{ next: { revalidate: 3 } } // 3초마다 데이터 갱신
);
}
- 일정 시간이 지나면 자동으로 데이터 갱신
- ISR 방식과 유사하여 성능과 최신 데이터 반영을 모두 가능하게 함
4) next: { tags: ['a'] } (On-Demand ISR 유사)
async function RecoBooks() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/random`,
{ next: { tags: ["books"] } }
);
}
- 특정 조건에서만 데이터를 새로고침 가능
💡 참고
next앱에서 발생하는 모든 데이터 페칭이 자동으로 로그에 출력하기 위한 옵션
// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
logging: {
fetches: {
fullUrl: true,
},
},
};
export default nextConfig;
Request Memoization (요청 메모이제이션)
중복된 API 요청을 자동으로 합쳐서 불필요한 중복 호출을 방지하는 기능
1) 데이터 캐싱과의 차이점
기능 | 목적 | 지속 시간 |
데이터 캐싱 | API 요청을 줄이고 성능 최적화 | 서버가 꺼질 때까지 유지 |
Request Memoization | 동일한 페이지 내에서 중복된 요청 제거 | 렌더링이 끝나면 캐시 삭제 |
✅ Request Memoization
✅ 데이터 캐시
✅ Request Memoization이 필요한 이유
- App Router에서는 페이지 내에서 중복 API 호출이 발생할 가능성이 높음
- 같은 API를 여러 번 호출하는 문제를 해결하여 불필요한 리소스 낭비를 방지
🎯 배운점
✔ Next.js에서는 서버 컴포넌트에서 직접 async 키워드를 사용하여 데이터 페칭 가능
✔ 환경변수를 활용하여 API 주소를 설정하고 관리하는 것이 중요
✔ 데이터 캐싱을 적절히 활용하면 성능 최적화 가능 (no-store, force-cache, revalidate 활용)
✔ Request Memoization을 통해 동일한 페이지 내 중복 API 호출 방지 가능