NextJs (5) Fetch Data (client side vs server side) + 로딩 컴포넌트

채영민·2024년 2월 14일

📚 React(클라이언트 사이드)에서 데이터 fetching 하는 방법

💡 React의 내장 함수들로만 구현한 데이터 fetching 예시.

export default function HomePage() {
  const [isLoading, setIsLoading] = useState(true);
  const [movies, setMovies] = useState([]);

  const getMovies = async () => {
    const response = await fetch(
      "https://nomad-movies.nomadcoders.workers.dev/movies"
    );
    const json = await response.json();
    setMovies(json);
    setIsLoading(false);
  };

  useEffect(() => {
    getMovies();
  }, []);

  return <div>{!isLoading ? JSON.stringify(movies) : "Loading..."}</div>;
}
  • 클라이언트 사이드에서 데이터를 fetch를 하는 경우, 결국에는 사용자에게 로딩상태를 보여줘야만 한다.
  • 처음에는 컴포넌트에 데이터가 아무 값도 없기 때문에 항상 useState를 사용해서 렌더를 일으키고, 데이터를 스스로 관리해주어야 한다.
  • 클라이언트 사이드에서는 fetch는 항상 클라이언트측에서 발생하기에 브라우저가 API에 직접 요청을 보내야 한다.
    • 그러므로 클라이언트에서는 API키와 같은 보안과 관련된 것들을 사용해선 안된다.
  • 그러므로 리액트 애플리케이션에서는 데이터베이스와 직접 소통하기 보다는 API를 통해서 소통하는 방식을 채택해서 사용하고 있다.

📚 NextJs(서버 사이드)에서 데이터 fetching 하는 방법

💡 NextJs로 구현한 데이터 fetching 예시.

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() { // await를 쓰기 위해서는 그 부모 함수는 async 해야 한다.
  const movies = await getMovies();
  return <div>{JSON.stringify(movies)}</div>;
}
  • useState, useEffect등을 사용할 필요가 없다.
  • 브라우저는 이제 더 이상 어떤 것도 fetch 하지 않는다, fetch하는 주체는 백엔드이다.
  • NextJS는 프레임워크이기에 server component를 사용한다면 fetch된 url을 캐싱시켜주고, 이는 처음 한번만 진행된다.

🗣️ 단 위와 같은 경우에도 단점이 존재하는데, 만일 유저가 페이지에 도착했음에도 서버에서 데이터를 fetch하는데 오랜 시간을 소모하게 된다면, 유저는 데이터 fetch가 끝날 때까지 아무런 화면도 보지 못하게 된다.

📚 Loading Components

🗣️ 서버 사이드 렌더링시에 단점 :

NextJs에서는 백엔드에서 데이터들을 fetch해오기 때문에 해당 작업이 완료되기 전에는, 백엔드에서 랜더링이 이루어지지 않게 되므로 유저는 해당 페이지에서 아무것도 볼 수 없음.

💡 해당 문제에 대한 해결방법? loading.tsx

  • app/(home)/ 디렉토리 안에, loading.tsx라는 파일을 새로 생성해 주면 된다.
// app/(home)/loading.tsx
// 홈페이지 방문시에 보고싶은 로딩 화면이기 때문에 해당 page.tsx와 같은 디렉토리안에 파일을 만들어 줘야한다.

export default function Loading() {
  return (
    <div>
      <h1>Loading...</h1>
    </div>
  );
}

// app/(home)/page.tsx
 
export default async function HomePage() { // HomePage()가 async여야 하는 이유는 NextJs가 이 컴포넌트에서 await해야하기 때문이다.

  const movies = await getMovies();
  return <div>{JSON.stringify(movies)}</div>;
}
  • NextJS는 서버 컴포넌트에서 데이터를 fetch하는 도중, 우선 layout, naviagaion등을 우선 UI로 그려주고나서 해당 loading.tsx안에 컴포넌트를 UI로 그려준다.
  • 그러다 getMovies()의 마지막 결과값이 있는 컴포넌트가 브라우저에 전달되면 loading 컴포넌트가 유저가 원했던 HomePage()로 대체된다.
  • 유저가 웹사이트에 도착하는 순간 NextJs는 즉시 사용자에게 로딩 상태를 주게되고 streaming을 사용해서 우리의 페이지를 작은 HTML로 나누어 준비된 HTML 부분을 브라우저에게 줄 수 있다.
    • 스트리밍(streaming) : 프레임워크가 우리의 페이지를 작은 HTML부분으로 나누고 준비된 부분을 하나씩 보여주는 것을 의미
profile
항상 재밌는것을 찾아 헤매는 호랑이띠 떠돌이;

0개의 댓글