Next.js

jinjoo-jung·2024년 6월 24일

Next.js로 개발

  • 서버 사이드 렌더링 (SSR, Server-side Rendering)
  • 점진적 정적 생성 (ISR)
  • 정적 사이트 생성 (SSG, State Site Generation)
  • 동적 정적 생성 (SAG)
  • 클라이언트 사이드 렌더링 (CSR)
    위에 대한 이해가 매우 중요하다. 이 기능들은 웹 애플리케이션의 성능, 사용자 경험, SEO 등에 큰 영향을 미친다.

서버사이드 렌더링 (SSR, Server-Side Rendering)

  • 서버 사이드 렌더링은 요청 시 서버에서 HTML 페이지를 완성하며 클라이언트에 반환하는 방식이다. 이 방법은 빠른 초기 페이지 로딩과 SEO 최적화에 유리

  • 장점
    -SEO 친화적
    -초기 페이지 로딩 속도 향상

  • 단점
    -서버에 부하가 증가
    -각 요청마다 페이지가 재생성되므로 동적 페이지 생성이 느릴 수 있음.

// pages/index.js
export async function getServerSideProps() {
  // 데이터 페칭
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  // 페이지에 데이터 전달
  return {
    props: {
      data,
    },
  };
}

const Home = ({ data }) => {
  return (
    <div>
      <h1>Server-Side Rendering Example</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

export default Home;

2. 점진적 정적 생성 (ISR, Incremental Static Regeneration)

  • ISR은 정적 페이지를 생성하되, 필요할 때마다 특정 간격으로 해당 페이지를 재생성할 수 있는 방식. 이는 트래픽이 많은 사이트에서도 최신 데이터를 제공하면서도 정적 페이지의 성능 이점을 활용할 수 있게 한다.

  • 장점
    -최신 데이터 제공 가능
    -정적 페이지의 빠른 로딩 속도 유지

  • 단점
    -데이터의 최신성 유지 주기를 잘 관리해야 함.

// pages/index.js
export async function getStaticProps() {
  // 데이터 페칭
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  // 페이지에 데이터 전달
  return {
    props: {
      data,
    },
    revalidate: 60, // 페이지를 60초마다 재생성
  };
}

const Home = ({ data }) => {
  return (
    <div>
      <h1>Incremental Static Regeneration Example</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

export default Home;

3. 동적 정적 생성 (SAG, Static Application Generation)

  • 동적 정적 생성은 빌드 시점에 모든 페이지를 정적으로 생성하여 배포하는 방식이다. 이는 빌드 . 시모든 페이지가 생성되므로 요청 시 서버가 관여하지 않는다.

  • 장점
    -빠른 페이지 로딩 속도
    -서버 부하 감소

  • 단점
    -데이터 업데이트 시 재배포 필요

// pages/index.js
export async function getStaticProps() {
  // 데이터 페칭
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  // 페이지에 데이터 전달
  return {
    props: {
      data,
    },
  };
}

const Home = ({ data }) => {
  return (
    <div>
      <h1>Static Application Generation Example</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

export default Home;

4. 클라이언트 사이드 렌더링 (CSR , Client-Side Rendering)

  • CSR은 초기에는 빈HTML을 전달하고, JavaScript가 실행되어 클라이언트에서 모든 UI를 생성하는 방식이다. 이 방식은 클라이언트에서 모든 작업을 수행하므로 서버 부하가 적지만, 초기 로딩 속도가 느릴 수 있다.
  • 장점
    -클라이언트에서 데이터 변경 시 빠른 반응성
    -서버 부하 감소
  • 단점
    -초기 로딩 속도가 느림
    -SEO에 불리함
import { useState, useEffect } from 'react';

const Home = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then((res) => res.json())
      .then((data) => setData(data));
  }, []);

  return (
    <div>
      <h1>Client-Side Rendering Example</h1>
      {data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>Loading...</p>}
    </div>
  );
}

export default Home;

5. 정적 사이트 생성(SSG, Static Site Generation)

  • 정적 사이트 생성은 웹 애플리케이션의 모든 페이지를 빌드 시점에 미리 생성하여 정적파일로 만들어 두는 방식이다. 이렇게 생성된 정적 파일은 CDN을 통해 빠르게 제공될 수 있다. SSG는 요청 시 서버에서 동적으로 페이지를 생성하지 않으며, 이미 생성된 정적 파일을 빠르게 지공하기 때문에 성능와 보안 면에서 매우 유리하다.
  • 장점
    - 초고속 로딩 속도: 정적 파일로 제공되므로 페이지 로딩이 매우 빠릅니다.
    SEO 최적화: 페이지가 미리 생성되어 있으므로 검색 엔진 크롤러가 쉽게 콘텐츠를 인덱싱할 수 있습니다.
    - 보안 강화: 서버에서 동적 컨텐츠를 생성할 필요가 없어 공격 표면이 줄어듭니다.
    확장성: 정적 파일은 쉽게 CDN에 배포되어 전 세계적으로 빠르게 전달될 수 있습니다.
    - 서버 비용 절감: 서버 부하가 줄어들어 비용을 절감할 수 있습니다.

- 단점:
- 데이터 갱신 어려움: 콘텐츠 변경 시 다시 빌드 및 배포해야 하므로 실시간 데이터 변경이 어렵습니다.
- 빌드 시간: 페이지가 많아질수록 빌드 시간이 길어질 수 있습니다.
- 다양한 콘텐츠 업데이트 어려움: 사용자별 맞춤형 데이터나 실시간 정보 제공에 한계가 있습니다.

- 사용 사례:
- 블로그: 콘텐츠가 정적이며, 주기적으로만 업데이트되는 블로그 사이트.
- 마케팅 웹사이트: 주로 고정된 정보나 제품 소개를 제공하는 사이트.
- 문서화 사이트: 변경이 드문 문서나 가이드라인을 제공하는 사이트.

SSG의 동작 원리

  1. 빌드 시점에 페이지 생성: Next.js는 빌드 시 getStaticProps를 사용하여 페이지를 생성합니다.
  2. 정적 파일로 변환: 생성된 페이지는 정적 HTML 파일로 변환되어 빌드 디렉토리에 저장됩니다.
  3. CDN을 통해 제공: 이러한 정적 파일은 CDN에 배포되어 사용자에게 빠르게 제공됩니다.

=> SSG는 트래픽이 많은 웹사이트나 변동이 적은 웹사이트에서 매우 유용하며, 최신 데이터가 필요한 경우는 ISR(Incremental Static Regeneration)과 함께 사용하는 것이 좋습니다. SSG를 사용하면 안정적이고 빠른 웹사이트를 구축할 수 있습니다.

추가
서버 사이드 렌더링 (SSR)
: 클라이언트의 요청이 있을 때마다 서버에서 실시간으로 HTML 페이지를 생성하며 클라이언트에 전달하는 방식이다. 따라서, 사용자가 페이지를 요청할 때마다 서버는 새로운 HTML 페이지를 생성합니다.

SSR의 특징
1. 실시간 데이터 : 페이지가 요청될 때마다 서버에서 최신 데이터를 가져와서 HTML을 생성한다.
2. 초기 로딩 시간 : 서버가 요청마다 HTML을 생성하므로 초기 로딩 시간이 다소 길 수 있다.
3. SEO 친화적 : 서버에서 완성된 HTML을 제공하므로 검색 엔진에 적합하다.
4. 클라이언트가 HTML을 렌더링

정적 사이트 생성 (SSG)
: 정적 사이트 생성은 빌드 시점에 모든 페이지를 미리 생성하여 정적 파일로 저장하는 방식이다.
클라이언트가 페이지를 요청하면 서버는 미리 생성된 HTML 파일을 그대로 전달한다.

SSG의 특징
1. 빠른 로딩 속도: 페이지가 정적 파일로 미리 생성되어 있으므로, 로딩 속도가 매우 빠르다.
2. SEO 친화적 : 미리 생성된 HTML 파일이 제공되므로 SEO에 유리하다.
3. 빌드 시 데이터 : 페이지를 빌드할 때의 데이터가 포함되므로, 데이터가 변경될 경우 재빌드가 필요하다.
4. 사용 예: 변경이 자주 발생하지 않는 블로그, 문서화 사이트 등 정적 콘텐츠에 적합

SSG 동작 방식 :
1. 빌드시 모든 페이지를 HTML 파일로 생성
2. 클라이언트가 페이지를 요청
3. 서버에서 미리 생성된 HTML 파일을 전송
4. 클라이언트가 HTML을 렌더링

정적과 동적의 개념

  • 정적 (Static)
    정적의 의미 : 정적 콘텐츠는 변경되지 않는 콘텐츠이다. 한 번 생성된 이후에 내용이 변하지 않으며 HTML, CSS, 이미지와 같은 파일로 저장된다. 정적 페이지는 서버 요청 시 항상 동일한 내용을 반환한다.

정적의 특징 :

  • 변경이 드뭄 : 정적 페이지는 거의 변하지 않으므로 콘텐츠로 구성된다.
  • 빠른 로딩 : 서버에서 미리 생성된 파일을 제공하므로 로딩 속도가 빠르다.
  • SEO 최적화 : 정적 HTML이 이미 존재하므로 검색 엔진에 친화적이다.

정적의 예) 블로그, 회사 소개 페이지, 포트폴리오 등

동적 (Dynamic)
동적의 의미 : 동적 콘텐츠는 요청 시마다 변경될 수 있는 콘텐츠 이다. 사용자의 입력, 실시간 데이터, 특정 조건에 따라 생성되는 콘텐츠이다. 동적 페이지는 요청 시마다 서버에서 새로운 데이터를 사용하여 페이지를 생성한다.

동적의 특징

  • 실시간 데이터 : 동적 페이지는 실시간으로 변경되는 데이터나 맞춤 데이터를 제공
  • 변경 가능 : 페이지가 요청될 때마다 최신 상태에 맞게 변할 수 있다.
  • 서버 로드 증가 : 매번 새로운 HTML을 생성해야 하므로 서버 부하가 증가할 수 있다.

동적의 예) 사용자 대시보드, 뉴스 피드, 쇼핑몰의 제품 목록 등

정적 VS 동적

  • 정적 페이지는 한번 생성된 후 변하지 않고 항상 동일한 콘텐츠를 제공하므로 빠르고 서버 부하가 적다.
  • 동적 페이지는 사용자의 요청에 따라 실시간으로 데이터를 반영하여 HTML을 생성하므로, 사용자 맞춤형 경험을 제공하지만 서버에 부하를 줄 수 있다.

    SSR과 SSG는 모두 Next.js에서 사용되는 렌더링 방식으로, 상황에 맞게 적절한 방법을 선택하여 사용할 수 있다.
    정적 콘텐츠는 고정된 정보를 제공하는데 적합하며, 동적 콘텐츠는 실시간으로 변경되거나 사용자 맞춤형 정보를 제공하는데 적합합니다. Next.js를 사용하면 이러한 다양한 렌더링 방식을 유연하게 조합하여 최적의 성능과 사용자 경험을 제공하는 웹 애플리케이션을 구축할 수 있습니다.


> 앱 라우터(App Router)와 페이지 라우터 (Page Router)는 웹 애플리케이션에서의 라우팅을 관리하는 방법을 나타내는 두 가지 접근 방식이다. 둘 다 사용자 경험을 향상시키기 위해 웹 페이지 간의 이동을 관리하지만, 그 구현 방식과 사용 목적에서 차이가 있다.

앱 라우터

  • 앱 라우터는 싱글 페이지 애플리케이션(SPA)에서 주로 사용되는 라우팅 방식으로, 클라이언트 측에서 라우팅을 관리한다.
  1. 클라이언트 요청 기반 : 클라이언트 측에서 JavaScript로 라우팅을 관리하여 서버 요청을 최소화 한다.
  2. 페이지 리로드 없음 : URL이 변경되더라도 전체 페이지가 새로 고침되지 않고, 필요한 부분만 업데이트 된다.
  3. 빠른 사용자 경험 : 페이지 전환이 빠르고 부드럽다.
  4. 동적 컨텐츠 로딩 : 특정 URL에 따라 동적으로 콘텐츠를 로딩하고, 페이지 이동 없이 상태를 유지할 수 있다.
  5. SEO 최적화 필요 : JavaScript를 사용하여 페이지를 구성하므로, 별도의 SEO 최적화 작업이 필요하다.

페이지 라우터 (Page Router)

  • 페이지 라우터는 전통적인 라우터 방식으로, 각 URL 요청에 대해 서버에서 새로운 HTML 페이지를 반환한다.
  1. 서버 요청 기반 : 각 페이지 이동마다 서버로 요청을 보내고 새로운 HTML문서를 받는다.
  2. 페이지 리로드: URL이 변경될 때마다 전체 페이지가 새로고침된다.
  3. SEO 친화적 : 검색 엔진 크롤러가 각 페이지를 개별적으로 인식하므로 SEO에 유리하다.
  4. 단순한 구현 : 서버 측에서 라우팅을 관리하기 때문에 클라이언트 측 로직이 단순하다.

주요 차이점

  • 서버 요청 여부 : 페이지 라우터는 각 페이지 이동마다 서버 요청을 하지만, 앱 라우터는 클라이언트 측에서 대부분의 라우팅을 처리
  • 페이지 리로드 : 페이지 라우터는 페이지 리로드가 발생하지만, 앱 라우터는 리로드 없이 부분 업데이트를 수행
  • SEO처리 : 페이지 라우터는 SEO에 자연스럽게 유리하지만, 앱 라우터는 추가적인 SEO 최적화가 필요
  • 사용 경험 : 앱 라우터는 빠르고 부드러운 사용자 경험을 제공하지만, 페이지 라우터는 전통적인 웹 애플리케이션 구조에 더 적합

=> 두 가지 라우팅 방식은 애플리케이션의 요구사항과 목표에 따라 다르게 선택.
작은 규모의 웹사이트나 SEO가 중요한 경우 페이지 라우터가 더 적합할 수 있으며, 대규모 애플리케이션이나 사용자 인터페이스가 중요한 경우 앱 라우터가 더 나은 선택이 될 수 있다.

추가

리액트에서의 라우팅

  • 리액트에서는 'react-router-dom'라이브러리를 사용하여 라우팅 구현

페이지 라우터(Page Router)

  • 페이지 라우터는 전통적인 방식으로, 각 페이지마다 서버 요청을 보내고 전체 페이지를 다시 로드. 리액트에서 잘 사용되지 않지만, SSR을 사용하는 경우 일부 사용할 수도 있음.

앱 라우터(App Router)

  • 앱 라우터는 리액트 컴포넌트와 클라이언트 사이드 라우팅을 사용하여 페이지 전환을 처리. 이는 싱글 페이지 애플리케이션(SPA)에서 주로 사용된다.
// App.js 예제
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Signin from './Signin';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/signin" element={<Signin />} />
      </Routes>
    </Router>
  );
}

export default App;

Next.js에서의 라우팅

  • 넥스트.js는 파일 기반 라우팅을 사용하여 라우팅을 관리. 넥스트.js에서는 페이지 디렉토리 내에 파일을 생성하면 자동으로 라우트가 설정

페이지 라우터

  • next.js의 기본 라우팅 방식이 페이지 라우터 방식. 파일 시스템을 기반으로 라우팅이 자동으로 설정된다.
/pages
  index.js   // 접근 경로: /
  about.js   // 접근 경로: /about
  signin.js  // 접근 경로: /signin
// pages/index.js
export default function Home() {
  return <h1>Home Page</h1>;
}
// pages/about.js
export default function About() {
  return <h1>About Page</h1>;
}
// pages/signin.js
export default function Signin() {
  return <h1>Sign In Page</h1>;
}

앱 라우터
-Next.js부터는 새로운 앱 라우터 방식도 도입되었다. 좀 더 유연한 라우팅과 레이아웃 구조를 제공하며, 클라이언트 사이드 네비게이션도 쉽게 처리가능

/app
  page.js          // 접근 경로: /
  about
    page.js        // 접근 경로: /about
  signin
    page.js        // 접근 경로: /signin
  layout.js        // 공통 레이아웃 설정
// app/page.js
export default function Home() {
  return <h1>Home Page</h1>;
}
// app/about/page.js
export default function About() {
  return <h1>About Page</h1>;
}
// app/signin/page.js
export default function Signin() {
  return <h1>Sign In Page</h1>;
}
// app/layout.js
export default function Layout({ children }) {
  return (
    <div>
      <nav>
        <a href="/">Home</a>
        <a href="/about">About</a>
        <a href="/signin">Sign In</a>
      </nav>
      <main>{children}</main>
    </div>
  );
}

-> Next.js는 파일 시스템 기반의 라우팅을 제공하여, 해당 경로에 해당하는 페이지 컴포넌트를 자동으로 로드하고, 이를 레이아웃 컴포넌트에 'children'으로 전달한다.
따라서 Next.js 앱 라우터를 사용하면, 레이아웃 컴포넌트 내에서 'children'으로 현재 경로에 맞는 페이지 컴포넌트가 자동으로 전달되기 때문에, 별도의 작업 없이 이를 렌더링 할 수 있다. Next.js는 내부적으로 이러한 라우팅과 컴포넌트 전달을 관리해주기 때문에 개발자는 간단하게 라우팅을 설정하고 사용할 수 있다.

profile
개인 개발 공부, 정리용 🔗

0개의 댓글