CSR, SSR의 데이터 패칭

Bumgu

2024/01/26

Tags: CSR SSR next.js

개발하다보면 만나게 되는 CSR, SSR 이 두가지의 방식으로 next.js에서 get요청으로 json 데이터를 받아오는걸 해보겠습니다.

1. CSR, SSR의 차이

CSR (Client-Side Rendering)

SSR(Server-Side Rendering)

요약

CSR : 빈 방(브라우저)에 가구(데이터)를 직접 배치 가구(데이터)를 가져오기 위한 추가 작업이 필요함 SSR : 이미 가구(데이터)가 배치된 방을 제공하므로 초기 로딩 시 빈 화면이 나타나지 않음

언제 쓸까?

SSR
CSR

2. 앱 생성

먼저 next앱을 생성하겠습니다. yarn create next-app next-data-fetching

데이터 패칭만 할것이기 때문에 ESLintTailwindCSS는 포함하지 않았습니다.

이동 cd next-data-fetching 실행 yarn dev next앱의 기본 화면입니다.

3. Data fetching - CSR

get 요청할 주소 https://nomad-movies.nomadcoders.workers.dev/movies

app/page.tsx의 내용을 전부 지워주고 useStateuseEffect를 임포트합니다.

import { useState, useEffect } from 'react';

export default function Home() {
  const [movies, setMovies] = useState([]);
  return (
  <div>
  </div>
  );
}

3-1. “use client”

Next.js의 app은 기본적으로 Server Component기 때문에 useState, useEffect를 사용하지 못합니다. 그래서 맨 위에 "use client"를 적어줌으로써 이 컴포넌트는 클라이언트 컴포넌트라는 것을 선언합니다.

"use client"
import { useState, useEffect } from 'react';

export default function Home() {
  const [movies, setMovies] = useState([]);
  return (
  <div>
  </div>
  );
}

3-2. getMovies()

이후 fetch를 사용해 데이터를 받아오겠습니다. getMovies()라는 함수를 생성합니다.

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

getMovies()는 비동기 함수로 지정된 URL에 요청을 보내고 받아온 응답을 json으로 바꾸고 setMovies()를 통해 movies를 세팅합니다. 그리고 그 json을 반환합니다.

3-3. useEffect()

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

getMovies()는 초기 로딩시 한번만 렌더링할 것이기 때문에 useEffect()안에서 호출하고, 의존배열은 빈칸으로 둡니다.

이제 데이터 준비는 다됐으니 화면에 띄우도록 하겠습니다.

return (
<div>
{JSON.stringify(movies)}
</div
)

json 형태의 데이터이기 때문에 stringify()로 문자열로 바꿔줍니다.

"use client"
import { useState, useEffect } from 'react';

export default function Home() {
  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)
    return json;
  }

  useEffect(() => {
    getMovies();
  }, [])
  return (
  <div>
     {JSON.stringify(movies)}
    </div>
  );
}

최종 코드의 모습은 이렇습니다.

받아온 데이터를 잘 보여줍니다. 하지만 위에서 설명했듯이, CSR방식은 데이터를 초기 로딩후 가져옵니다. 그렇다면 정말로 데이터 가져오는데 시간이 걸릴까요? 한번 확인해보겠습니다.

3-4. isLoading 만들기

로딩중이라면 Loading... 이란 문구를 띄워주고 데이터를 다 가져오면 데이터를 보여주도록 하겠습니다. 먼저 isLoading, setIsLoading을 만들어줍니다. const [isLoading, setIsLoading] = useState(true);

이후 getMovies()함수안에 setMovies(json) 밑에 setIsLoading(false)를 적어줍니다. 그리고 return문안에 삼항연산자를 이용해 렌더링합니다. {isLoading ? 'Loading.....' : JSON.stringify(movies)}

"use client"
import { useState, useEffect } from 'react';

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

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

  useEffect(() => {
    getMovies();
  }, [])
  return (
  <div>
     {isLoading ? 'Loading.....' : JSON.stringify(movies)}
    </div>
  );
}

데이터 패칭이 완료되면 IsLoadingfalse가 되어 movies가 렌더링되고 패칭되기전에는 Loading.....이란 문구가 렌더링됩니다.

많은 양의 데이터가 아니기 때문에 오래걸리진 않지만, 페이지가 나타나고 그 뒤에 데이터를 가져오기 때문에 로딩하는 시간이 잠시 있습니다.

4. Data fetching - SSR

이제 SSR방식으로 데이터 패칭을 해보겠습니다.

다시 초기 상태로 코드를 되돌립니다.

export default function Home() {
  return (
  <div>
      {JSON.stringify(movies)}
    </div>
  );
}

JSON.stringify(movies)부분은 그대로 사용할 것이라 그대로 뒀습니다.

4-1. getMovies()

CSR과 같이 getMovies()비동기 함수를 작성합니다.

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

데이터를 패칭하는것 자체는 CSR방식과 다른것은 없습니다. 차이점은 렌더링 하는 방식이 다릅니다.

4-2. 데이터 렌더링

export default async function Home() {
  const movies = await getMovies();
  return (
  <div>
      {JSON.stringify(movies)}
    </div>
  );
}

Home컴포넌트를 비동기 함수로 바꿔주고 movies라는 변수에 getMovies();의 반환값을 담아줍니다. getMovies()는 비동기 함수이기 때문에 await키워드가 있어야합니다.

최종 코드

const getMovies = async () => {
  const response = await fetch("https://nomad-movies.nomadcoders.workers.dev/movies");
  const json = await response.json();
  return json;
}
export default async function Home() {
  const movies = await getMovies();
  return (
  <div>
      {JSON.stringify(movies)}
    </div>
  );
}

5. 결과 차이

CSR은 초기 로딩이후 데이터를 패칭해오고 보여주기 때문에 잠깐의 로딩시간이 있는반면, SSR은 데이터를 미리 캐싱해놓기 때문에 기다림 없이 바로 데이터를 보여주고 있습니다.

하지만 SSR이 만능 무조건 좋다 이것은 아니기 때문에 상황에 맞게 사용하면 될것 같습니다.

이상으로 포스팅을 마치겠습니다. 감사합니다.

>> Home