세팅 방법
Next.js by Vercel - The React Framework
npx create-next-app@latest
동작 방식
파일 시스템 기반 라우팅 동작 방식으로, 디렉토리 안의 파일 구조를 자동으로 탐지하여 URL 경로와 매핑된다.
npm run dev 등으로 next.js를 실행할 시
next dev
명령어를 통해 개발 서버를 실행.
- 프로젝트의 설정과 필요한 리소스를 초기화.
pages
디렉토리에서 라우트를 생성하기 위해 파일들을 탐색. (동적 경로, 정적 경로 포함)
- Webpack Dev Server 초기화
- Webpack Dev Server를 실행.
- 번들링 및 트랜스파일링.
- 핫 모듈 교체 (HMR) 활성화.
- 개발 서버 실행
- 라우팅 및 렌더링 준비
- 서버 사이드 렌더링(SSR) 지원 - 동적 HTML 생성, getServerSideProps 처리
- 정적 파일 서빙 -
public
디렉토리에 있는 정적 파일을 /
경로로 서빙
- API 엔드포인트 활성화 -
pages/api
디렉토리의 파일을 API 엔드포인트로 설정하고 요청을 처리할 수 있도록 준비
- 모니터링 및 파일 변경 감지
- Next.js는 개발 모드에서 파일 변경 사항을 실시간으로 감지
파일 구조
app 디렉토리든, pages디렉토리든, 기본적으로 디렉토리 내부에 존재하는 파일 이름에 해당하는 url 페이지가 자동으로 생성된다.
src/app/layout.js (구 src/pages/_app.tsx)
- 모든 페이지에 공통으로 적용되는 컴포넌트. Next.js를 초기화할 때 사용한다.
src/app/document.tsx (구 src/pages/_document.tsx)
- HTML, HEAD, BODY 태그를 초기화할 수 있다. 서버에서만 렌더링된다.
npm 스크립트
npm run dev
- 개발 환경 (Development Mode) 상에서 프로젝트를 개발할 때 사용.
- Hot Module Replacement (HMR) - 파일을 수정하면 서버가 자동으로 리로드됨.
process.env.NODE_ENV
값이 development
.
- Next.js의 개발 서버를 실행하여 로컬 환경에서 프로젝트를 테스트할 수 있도록 함.
npm run start
- 프로덕션 환경 (Production Mode) 상에서 배포된 프로젝트를 실행할 때 사용.
- 정적 파일 및 서버 코드가 프로덕션용으로 최적화됨.
- HMR 기능 없음 - 수정된 파일은 서버를 다시 빌드하고 시작해야 반영됨.
process.env.NODE_ENV
값이 production
.
- 런타임 성능이 향상됨: 불필요한 디버그 및 개발 도구 제외.
next build
로 미리 빌드된 결과물을 실행하는 Next.js 서버를 시작.
CSR과 SSR - "use client"
CSR(Client-Side Rendering)
- 초기 요청 시 브라우저는 서버로부터 최소한의 HTML을 가져온다 (일반적으로 빈
<div>
또는 "Loading..." 같은 기본 구조)
- 클라이언트가 React, 컴포넌트 코드, 데이터 패칭 로직 등이 포함된 JS 번들을 다운로드하고 실행한다.
- React가 브라우저에서 데이터를 패칭하고, 그 데이터를 기반으로 화면을 렌더링한다.
- 초기에는 빈 HTML이 나타나고, 모든 데이터를 가져온 후 완전한 페이지가 렌더링된다.
SSR(Server-Side Rendering)
- 브라우저가 서버에 요청을 보내면, 서버는 React 컴포넌트를 실행하여 HTML을 생성하며, 필요 시 데이터 패칭도 서버에서 실행한 후 최종 HTML에 포함한다.
- 서버에서 완전한 HTML을 브라우저로 전송하고, 브라우저는 이를 즉시 렌더링한다.
- 브라우저에서 React가 동작하면서 HTML에 인터랙티브 기능(이벤트 리스너 등)을 추가한다.
use client
- 컴포넌트가 클라이언트에서 실행되어야 한다고 선언하고, 서버에서 정적으로 렌더링되는 컴포넌트를 클라이언트 단에서 이벤트 리스너를 붙이는 등 상호작용 가능한 동적인 컴포넌트로 만든다. 이를 hydarate라고 한다.
- 이벤트 핸들러나
useState
, useEffect
를 사용하는 경우가 해당
- 이로써 SSR을 기본으로 하되, 특정 부분만 CSR로 전환하여 성능과 유연성을 동시에 확보할 수 있는 혼합 렌더링이 가능해진다.
use client
가 없는 서버 컴포넌트에 대한 JS 코드를 다운받을 필요가 없어진다.
- 서버 컴포넌트 안에서 클라이언트 컴포넌트를 가질 수 있다. 반대로 use client를 선언한 클라이언트 컴포넌트 안에서 서버 컴포넌트를 가질 수 없다. 모든 컴포넌트가 클라이언트 컴포넌트로 취급된다.
use clinet
를 사용한 컴포넌트는 백엔드에서 먼저 Rendering되고, 프론트엔드에서 Hydrate된다. (use client
보다는 use hydrate
가 더 적합한 표현?)
use client를 썼는데도 왜 HTML에 포함이 되어 있지?
- Static Rendering의 경우
"use client"
컴포넌트가 정적인 콘텐츠만 포함하고 있다면, 서버가 해당 콘텐츠를 정적으로 렌더링하여 초기 HTML에 포함시킬 수 있다.
- SSG와 같은 정적 생성 방식에서 자주 발생하는 현상.
- Server-side Hydration Support
"use client"
컴포넌트 내부의 결과가 Hydration을 위한 HTML로 삽입될 수 있다.
- 이를 통해 사용자에게 플래시가 없는 초기 렌더링을 제공한다.
- 동적인 React 로직은 클라이언트에서 번들을 통해 활성화된다.
클라이언트 컴포넌트든, 서버 컴포넌트든, Next(백엔드) 단에서 먼저 rendering 된다는 것은 차이가 없다. interactive한 컴포넌트, 즉 hydrate 여부에 대한 차이가 있을 뿐이다.
Hydration
서버에서 렌더링된 정적 HTML을 브라우저에서 React의 동적인 동작으로 활성화시키는 과정
다시 말해, 단순한 정적 HTML 파일을 React Application으로 초기화하는 과정이다.
- Next.js와 같은 프레임워크는 SSR(Server-Side Rendering)이나 SSG(Static Site Generation)를 통해 초기 HTML을 생성한다.
- 브라우저에 도착했을 때, React가 이를 활성화해서 인터랙션과 상태 관리를 가능하게 만든다.
필요한 이유
React는 SPA(Single Page Application) 특성을 가지므로 브라우저에서 상태 관리와 이벤트 처리가 가능해야 한다.
하지만 서버에서 미리 렌더링된 HTML은 단순한 정적인 마크업이기에, React의 Virtual DOM을 통해 HTML을 다시 탐색하고 필요한 이벤트 핸들러 및 상태를 연결함으로써 정적 페이지를 동적 페이지로 변환하는 과정이 필요한 것이다.
동작 과정
- 서버에서 HTML 생성 - Next.js가 React 컴포넌트를 HTML로 렌더링하고 클라이언트로 전송
- React 번들(JavaScript) 로드 - React와 페이지 로직이 포함된 JavaScript 번들
- Virtual DOM 생성 - 서버에서 렌더링된 HTML과 일치하도록 설정
- 이벤트 핸들러 및 상태 연결 - 컴포넌트의 동작(이벤트 핸들러, 상태 변화 등)을 서버 렌더링된 HTML에 연결
Next 14 버전부터는 모든 컴포넌트를 hydrate하는 방식이 use client를 사용한 컴포넌트에 한해 hydrate하는 것으로 변경되었다.