본문 바로가기
Next.js

Next.js App Router에서의 렌더링 방식 이해하기

by rinny01 2025. 3. 10.
반응형

서버 사이드 렌더링 vs 클라이언트 사이드 렌더링

  • 서버 사이드 렌더링 : 주문한 가구가 완전히 조립된 상태로 배송되고, 고객은 바로 사용하면 되니 편리하다.
  • 클라이언트 사이드 렌더링 : 주문한 가구의 부품과 조립 설명서만 배송되고, 고객이 직접 조립해야함으로 시간과 노력이 필요하다.

 

- 서버 컴포넌트 : 

  • 서버에서만 렌더링 되는 컴포넌트로, SSR의 역할을 한다.
  • 클라이언으로 전달되는 HTML만 생성하고, 유저 상호작용을 하지 않는다.
  • Next.js의 App Router에서 모든 컴포넌트는 기본적으로 서버 컴포넌트 이다.
// src/app/page.tsx

const HomePage = async () => {
  const data = await fetchDataFromAPI();  // 서버에서 데이터 호출

  return (
    <div>
      <h1>Server-Side Rendered Page</h1>
      <p>{data.name}</p>
    </div>
  );
};

export default HomePage;

 

- 클라이언트 컴포넌트 : 

  • 클라이언트 사이드에서 실행되며, 상태관리, 이벤트 처리와 같은 상호작용이 필요한 컴포넌트를 다룬다.
  • "use client"를 통해 클라이언트 컴포넌트로 설정할 수 있다.
'use client';  // 클라이언트 컴포넌트 선언

import { useState } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      // onClick을 통한 상호작용 가능
      <button onClick={() => setCount(count + 1)}>Increase Count</button>
    </div>
  );
};

export default Counter;

 

Next.js의 App Router에서는 데이터를 어떻게 불러오느냐에 따라 페이지가 렌더링되는 방식이 달라지는데,

크게 SSR, CSR, ISR, SSG 네 가지 방식으로 구분할 수 있다.

 

SSR(Server Side Rendering)

- 서버 사이드 랜더링 과정 

  1. 사용자가 페이지에 접근하면 next.js서버가 요청을 처리한다.
  2. 컴포넌트를 구현하기 위해 서버에서 필요한 데이터를 가져온다.
  3. 서버는 완성된 HTML을 생성하여 클라이언트에게 전달한다.
  4. 클라이언트는 완성된 HTML을 받아 렌더링 하고, 이후 수화 과정을 통해 상호작욕을 한다.

서버요청시마다 데이터를 가져와 HTML을 생성하여 응답한다. 항상 최신 데이터가 보장되지만, 매 요청마다 데이터를 가져오기 때문에 서버 부담이 있다.

// page.jsx
export default async function Page() {
  const res = await fetch('https://api.example.com/data', 
  	{ cache: 'no-store' }
  );
  const data = await res.json();

  return <div>{data.message}</div>;
}
  • {cache : 'no-store'}
  • cache : 데이터를 임시저장하는곳 : 임시 저장 장소 (필요할때 빨리 가져다 쓰기 위해)
  • 캐시 옵션 : no-store (저장하지 않는다.) > 항상 최신 데이터를 가져온다는 말!
  • 실시간 정보를 가져올때 사용한다 (ex.뉴스)

 

CSR (Client Side Rendering) 

클라이언트 사이드 렌더링

페이지의 정적인 부분만 서버에서 생성하고, 데이터는 클라이언트에서 자바스크립트를 통해 가져온다.

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

export default function Page() {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const res = await fetch('https://api.example.com/data');
      const result = await res.json();
      setData(result);
    }

    fetchData();
  }, []);

  return <div>{data ? data.message : 'Loading...'}</div>;
}
  • 패치 옵션 : 없음
  • 서버에서 초기에만 생성하여주고 클라이언트에서 가져온다. ("use client" 사용) 
  • 데이터가 없어서 초기 로딩시 로딩상태가 발생한다.

 

ISR (Incremental Static Regeneration)

증분 정적 재생성 

정해진 시간마다 페이지를 다시생성한다. SSR와SSG의 중간상태

// page.jsx
export default async function Page() {
  const res = await fetch('https://api.example.com/data', 
  	{ next: { revalidate: 60 } }
  );
  const data = await res.json();

  return <div>{data.message}</div>;
}
  • 실시간으로 가져와지 않아도 되는 데이터
  • {next:{revalidate:60}} next에서 제공 >60초마다 최신 데이터를 가져온다.
  • 배포할때 ISR을 지원하는지 확인하고 배포해야한다.(지원 안해주는곳이 많아서)

 

SSG (Static Site Generation)

정적 사이트 생성

빌드 시 데이터를 가져와 정적인html을 미리 만들어 놓고 이를 사용자에게 제공한다.

// page.jsx
export default async function Page() {
  const res = await fetch('https://api.example.com/data', 
  	{ cache: 'force-cache' }
  );
  const data = await res.json();

  return <div>{data.message}</div>;
}
  • 미리 준비해놓고 제공하기 때문에 가장 빠르지만, 최신데이터는 아니다
  • (처음 만들어놓고 고정) 그럼 언제만들어지냐 ? 빌드 (배포) 할때 만들어지는데 배포시에만 가져와서 데이터가 변경되지않는다
  • {cache : {'force-cache'}}

 

한서비스에 여러 랜더링 방식을 사용해서 최적화가 가능하다!

렌더링 방식
데이터 최신성
성능
추천 사용 사례
SSR
높음
중간
자주 바뀌는 실시간 데이터
CSR
중간
높음
사용자 상호작용이 많은 앱
ISR
중간
높음
블로그나 뉴스 사이트
SSG
낮음
매우 높음
거의 바뀌지 않는 마케팅 페이지
반응형
LIST