JiSoo's Devlog
[Next.js] Data Fetching 본문
client에서 모든 것을 fetch 하려면 보안을 위해 항상 API를 중간에 만들어 요청하고 API가 안전한 환경에 있다면 그 뒤에 데이터베이스에 요청을 보낸다
useState를 사용하면 metadata도 사용하지 못한다
Server Side
어떤 일이 발생하기를 기다리려고 await를 사용할 때 async를 무조건 써야 한다!
useEffect, useState를 쓰지 않아도 되고 로딩 상태를 구현하지 않아도 된다
export const metadata = {
title: "Home",
};
const URL = "https://nomad-movies.nomadcoders.workers.dev/movies";
async function getMovies() {
const response = await fetch(URL);
const json = await response.json();
return json;
}
export default async function HomePage() {
const movies = await getMovies();
return <div>{JSON.stringify(movies)}</div>;
}
Next.js는 프레임워크이기 때문에 server component를 사용한다면 fetch 된 url을 자동으로 캐싱시켜 준다
브라우저가 어떤 것도 fetch 하지 않는다
async function getMovies() {
console.log("I'm fetching!");
const response = await fetch(URL);
const json = await response.json();
return json;
}
이런 식으로 확인해 주면 여기서 콘솔은 백엔드에서만 실행된다
로딩상태도 존재
server component에서 Next JS가 내가 fetch 한 것을 기억한다
하지만 저 함수가 완료되기 전까지는 백엔드에서 렌더링 작업이 이루어지지 않아서 사용자는 아무것도 볼 수 없다
Loading Components
loading.tsx 파일은 React Suspense를 사용해 의미 있는 로딩 UI를 만들어 준다
브라우저가 첫 번째로 보내는 일부분은 layout이나 navigation이고 그다음에 loading component를 보낸다
브라우저는 로딩이 끝날 때까지 기다리다가 백엔드 작업(함수작업)이 완료되면 응답 결과를 보여준다
export default async function HomePage() {
const movies = await getMovies();
return <div>{JSON.stringify(movies)}</div>;
}
여기서 HomePage 컴포넌트가 async여야 하는 이유는 NextJS가 이 컴포넌트에서 await 해야 하기 때문
await가 끝나면 브라우저에게 마지막 HTML 부분 전달
Parallel Requests
export default async function MovieDetail({
params: { id },
}: {
params: { id: string };
}) {
console.log('start fetching')
const movie = await getMovie(id);
const videos = await getVideos(id);
console.log('end fetching')
return <h1>{movie.title}</h1>;
}
↓ ↓ ↓ ↓ ↓
export default async function MovieDetail({
params: { id },
}: {
params: { id: string };
}) {
console.log('start fetching')
const [movie, video] = await Promise.all([getMovie(id), getVideos(id)]);
console.log('end fetching')
return <h1>{movie.title}</h1>;
}
Promise.all 은 자바스크립트에서 여러 비동기 작업을 동시에 실행하고 모든 작업이 완료될 때까지 기다렸다가 결과를 배열 형태로 반환하는 함수
여러 Promise를 모두 이행할 때까지 기다린 후, 그 결과를 한꺼번에 받아볼 수 있게 한다
병렬적 fetch 가능!
Suspense
데이터 소스가 여러 개라면 Suspense를 사용해야 한다
이전 방식은 page 컴포넌트에서 2가지 모두 fetch
지금 방식은 개별 파일에서 2가지를 render 할 건데 개별적으로 기다릴 수 있다
Suspense 컴포넌트에는 fallback이라는 prop이 있고 이건 컴포넌트가 await 되는 동안 표시할 메시지를 render 할 수 있게 한다
return (
<div>
<Suspense fallback={<h1>Loading movie info</h1>}>
{/* @ts-expect-error Async Server Component */}
<MovieInfo id={id} />
</Suspense>
<Suspense fallback={<h1>Loading movie videos</h1>}>
{/* @ts-expect-error Async Server Component */}
<MovieVideos id={id} />
</Suspense>
</div>
);
2가지를 동시에 fetch할 수 있는데 하나의 요청이 완료되면 다른 컴포넌트를 기다릴 필요 없이 즉시 컴포넌트가 render 된다
이전에는 페이지 전체가 로딩 상태였다면 지금은 구체적으로 페이지의 어느 부분이 로딩 상태여야 하는지 명시해 줄 수 있다
Error Handling
error.js 파일을 사용하면 중첩된 경로에서 예기치 않은 런타임 오류를 적절히 처리할 수 있다
error.js는 중첩된 하위 세그먼트 혹은 page.js 구성 요소를 래핑 하는 React Error Boundary를 자동 생성한다
error.js 파일에서 내보낸 리액트 컴포넌트가 fallback 컴포넌트로 사용된다
'Frontend > Next.js' 카테고리의 다른 글
[Next.js] Deployment (3) | 2024.10.15 |
---|---|
[Next.js] Routing (0) | 2024.08.04 |
[Next.js] Introduction (0) | 2024.07.29 |