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 호출 방지 가능