Next.js로 개발
서버 사이드 렌더링은 요청 시 서버에서 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;
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;
동적 정적 생성은 빌드 시점에 모든 페이지를 정적으로 생성하여 배포하는 방식이다. 이는 빌드 . 시모든 페이지가 생성되므로 요청 시 서버가 관여하지 않는다.
장점
-빠른 페이지 로딩 속도
-서버 부하 감소
단점
-데이터 업데이트 시 재배포 필요
// 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;
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;
- 단점:
- 데이터 갱신 어려움: 콘텐츠 변경 시 다시 빌드 및 배포해야 하므로 실시간 데이터 변경이 어렵습니다.
- 빌드 시간: 페이지가 많아질수록 빌드 시간이 길어질 수 있습니다.
- 다양한 콘텐츠 업데이트 어려움: 사용자별 맞춤형 데이터나 실시간 정보 제공에 한계가 있습니다.
- 사용 사례:
- 블로그: 콘텐츠가 정적이며, 주기적으로만 업데이트되는 블로그 사이트.
- 마케팅 웹사이트: 주로 고정된 정보나 제품 소개를 제공하는 사이트.
- 문서화 사이트: 변경이 드문 문서나 가이드라인을 제공하는 사이트.
=> 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을 렌더링
정적의 특징 :
정적의 예) 블로그, 회사 소개 페이지, 포트폴리오 등
동적 (Dynamic)
동적의 의미 : 동적 콘텐츠는 요청 시마다 변경될 수 있는 콘텐츠 이다. 사용자의 입력, 실시간 데이터, 특정 조건에 따라 생성되는 콘텐츠이다. 동적 페이지는 요청 시마다 서버에서 새로운 데이터를 사용하여 페이지를 생성한다.
동적의 특징
동적의 예) 사용자 대시보드, 뉴스 피드, 쇼핑몰의 제품 목록 등
정적 VS 동적
SSR과 SSG는 모두 Next.js에서 사용되는 렌더링 방식으로, 상황에 맞게 적절한 방법을 선택하여 사용할 수 있다.
정적 콘텐츠는 고정된 정보를 제공하는데 적합하며, 동적 콘텐츠는 실시간으로 변경되거나 사용자 맞춤형 정보를 제공하는데 적합합니다. Next.js를 사용하면 이러한 다양한 렌더링 방식을 유연하게 조합하여 최적의 성능과 사용자 경험을 제공하는 웹 애플리케이션을 구축할 수 있습니다.
=> 두 가지 라우팅 방식은 애플리케이션의 요구사항과 목표에 따라 다르게 선택.
작은 규모의 웹사이트나 SEO가 중요한 경우 페이지 라우터가 더 적합할 수 있으며, 대규모 애플리케이션이나 사용자 인터페이스가 중요한 경우 앱 라우터가 더 나은 선택이 될 수 있다.
추가
페이지 라우터(Page Router)
앱 라우터(App Router)
// 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;
페이지 라우터
/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는 내부적으로 이러한 라우팅과 컴포넌트 전달을 관리해주기 때문에 개발자는 간단하게 라우팅을 설정하고 사용할 수 있다.