next.js 13버전 때 학습내용 정리 문서로 현재와 다름 주의
Fetching
async, await in Server Component
//app/page.tsx
async function getData() {
const res = await fetch('https://api.example.com/...');
if (!res.ok) {
throw new Error('Failed to fetch data');
}
return res.json();
}
export default async function Page() {
const data = await getData();
return <main></main>;
}
타입스크립트 오류나면 임시로 /* @ts-expect-error Async Server Component */ 쓰셈
서버 컴포넌트 기능
cookies(), headers()
use in Client Components
🤔 클라이언트 컴포넌트에서 fetch를 쓰면 여러번의 리렌더링이 발생하니
쓰지말고 SWR이나 React Query 쓰라는 말 맞음?
정적 데이터 가져오기
fetch를 사용하면 자동으로 가져오고 캐시함.
fetch(주소)
데이터 재검증
초당 캐시 만료시간을 줘서 해당 시간이 지나면 다시 가져옴
fetch('https://...', { next: { revalidate: 10 } });
동적 데이터 가져오기
캐시되지 않도록 no-store 옵션을 붙임
fetch('https://...', { cache: 'no-store' });
데이터 가져오기 패턴
병행
import Albums from './albums';
async function getArtist(username: string) {
const res = await fetch(`https://api.example.com/artist/${username}`);
return res.json();
}
async function getArtistAlbums(username: string) {
const res = await fetch(`https://api.example.com/artist/${username}/albums`);
return res.json();
}
export default async function Page({
params: { username },
}: {
params: { username: string };
}) {
// Initiate both requests in parallel
const artistData = getArtist(username);
const albumsData = getArtistAlbums(username);
// Wait for the promises to resolve
const [artist, albums] = await Promise.all([artistData, albumsData]);
return (
<>
<h1>{artist.name}</h1>
<Albums list={albums}></Albums>
</>
);
}
좀 더 나은 사용자 경험을 위해선 서스펜스 바운더리를 나눠라. 그럼 렌더링이 완료되는 순간 하나씩 노출된다.
import { getArtist, getArtistAlbums, type Album } from './api';
export default async function Page({
params: { username },
}: {
params: { username: string };
}) {
// Initiate both requests in parallel
const artistData = getArtist(username);
const albumData = getArtistAlbums(username);
// Wait for the artist's promise to resolve first
const artist = await artistData;
return (
<>
<h1>{artist.name}</h1>
{/* Send the artist information first,
and wrap albums in a suspense boundary */}
<Suspense fallback={<div>Loading...</div>}>
<Albums promise={albumData} />
</Suspense>
</>
);
}
// Albums Component
async function Albums({ promise }: { promise: Promise<Album[]> }) {
// Wait for the albums promise to resolve
const albums = await promise;
return (
<ul>
{albums.map((album) => (
<li key={album.id}>{album.name}</li>
))}
</ul>
);
}
순차적 데이터 가져오기
데이터를 순차적으로 가져오려면 데이터가 필요한 컴포넌트 내부에서 직접 가져오거나, 데이터가 필요한 컴포넌트 내부에서 가져오기 결과를 기다릴 수 있습니다.
// ...
async function Playlists({ artistID }: { artistID: string }) {
// Wait for the playlists
const playlists = await getArtistPlaylists(artistID);
return (
<ul>
{playlists.map((playlist) => (
<li key={playlist.id}>{playlist.name}</li>
))}
</ul>
);
}
export default async function Page({
params: { username },
}: {
params: { username: string };
}) {
// Wait for the artist
const artist = await getArtist(username);
return (
<>
<h1>{artist.name}</h1>
<Suspense fallback={<div>Loading...</div>}>
<Playlists artistID={artist.id} />
</Suspense>
</>
);
}
컴포넌트 내부에서 데이터를 가져오면 경로의 각 가져오기 요청과 중첩된 세그먼트는
이전 요청이나 세그먼트가 완료될 때까지 데이터 가져오기 및 렌더링을 시작할 수 없습니다.
경로에서 렌더링 차단
레이아웃에서 데이터를 가져오면 그 아래의 모든 경로 세그먼트에 대한 렌더링은 데이터 로딩이 완료된 후에만 시작할 수 있습니다.
페이지 디렉토리에서 서버 렌더링을 사용하는 페이지는 getServerSideProps가 완료될 때까지 브라우저 로딩 스피너를 표시한 다음 해당 페이지에 대한 React 컴포넌트를 렌더링합니다. 이것은 “전부 아니면 전무” 데이터 불러오기라고 설명할 수 있습니다. 페이지에 대한 전체 데이터를 가져올 수도 있고, 아무것도 가져올 수 없습니다.
앱 디렉토리에서 탐색할 수 있는 추가 옵션이 있습니다:
첫째, loading.js를 사용하여 데이터 불러오기 함수에서 결과를 스트리밍하는 동안 서버에서 즉시 로딩 상태를 표시할 수 있습니다.
둘째, 컴포넌트 트리에서 데이터 불러오기를 아래로 이동하여 페이지에서 필요한 부분의 렌더링만 차단할 수 있습니다. 예를 들어 루트 레이아웃에서 데이터를 가져오지 않고 특정 컴포넌트로 데이터 가져오기를 이동하는 것입니다.
가능하면 데이터를 사용하는 세그먼트에서 데이터를 가져오는 것이 가장 좋습니다. 이렇게 하면 페이지 전체가 아닌 로딩 중인 부분만 로딩 상태를 표시할 수도 있습니다.
fetch () 없이 데이터 가져오기
기본 캐싱 동작
fetch()를 사용하지 않으면 경로 세그먼트에 따라 정적 또는 동적이 됨.
세그먼트 캐시 구성
타사 쿼리의 캐싱 동작을 구성할때 세그먼트 구성을 사용하여 전체 세그먼트의 캐시 동작을 지정할 수 있음
import prisma from './lib/prisma';
export const revalidate = 3600; // revalidate every hour
async function getPosts() {
const posts = await prisma.post.findMany();
return posts;
}
export default async function Page() {
const posts = await getPosts();
// ...
}
'공부공부 > Next.js 공식문서' 카테고리의 다른 글
[next.js 공식문서] 16. Revalidating (0) | 2024.03.01 |
---|---|
[next.js 공식문서] 15. Caching (0) | 2024.03.01 |
[next.js 공식문서] 13. Edge and Node.js Runtimes (0) | 2024.02.29 |
[next.js 공식문서] 12. Static and Dynamic Rendering (0) | 2024.02.29 |
[next.js 공식문서] 11. Internationalization (0) | 2024.02.28 |