1. Server Components VS ClientComponent
: React 프레임워크의 새로운 기능 중 하나입니다. 이 기능은 서버와 클라이언트 간의 데이터 및 렌더링 로직을 효과적으로 분리하여 성능을 향상시킬 수 있는 방법을 제공합니다.
React v18 버전 이전까지는 React를 사용하여 어플리케이션을 렌더링하는 주요한 방법이 "전적으로(entirely)" 클라이언트에 있었다.
서버 컴포넌트와 클라이언트 컴포넌트의 가장 큰 차이점은 컴포넌트가 렌더링되는 장소가 서버냐 클라이언트냐의 차이입니다.
서버 컴포넌트는 서버에서 한차례 해석된 이후 클라이언트로 전달되고, 클라이언트 컴포넌트는 클라이언트가 js 번들을 다운로드 받은 후 해석하게 됩니다.
서버컴포넌트 사용예시 (nginx + node(next))
-환경
[ 운영 체제 (Ubuntu, CentOS, Debian 등) ]
├── 🖥 Nginx (80번 포트, 정적 파일 제공 및 리버스 프록시)
├── 🖥 Node.js (3000번 포트, Next.js 실행)
(1) Nginx 설정 파일 수정 (/etc/nginx/sites-available/default)
server {
listen 80;
server_name myapp.com;
# 정적 파일을 Nginx에서 직접 서빙
location /_next/static/ {
alias /home/user/my-app/.next/static/;
expires 1y;
access_log off;
}
# API 및 서버 컴포넌트 요청은 Node.js로 전달
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
(2) 특정영역에 배포 .next/ 폴더 구조 (빌드 후)
📂/home/user/my-app/
├── 📂 .next/ # (빌드된 결과물)
│ ├── server/ # ✅ 서버 컴포넌트 코드 (Node.js에서 실행)
│ ├── static/ # ✅ 정적 파일 (Nginx에서 직접 서빙 가능)
│ ├── cache/ # 빌드 캐시
│ ├── build-manifest.json # 빌드 정보
│ ├── routes-manifest.json# 라우트 정보
│ ├── required-server-files.json # 서버 실행에 필요한 파일 목록
│ ├── package.json # 서버 실행에 필요한 의존성 정보
│ ├── prerender-manifest.json # 사전 렌더링 정보 (ISR 관련)
│ ├── images-manifest.json # 이미지 최적화 정보
│ ├── NEXT_VERSION # Next.js 버전 정보
│ ├── ... 기타 파일들
✅ 서버 컴포넌트(API 포함) 변경 시 → Node.js 재기동 필요
✅ 정적 파일만 변경 시 → Nginx 캐시만 갱신하면 됨.
✅ 운영 환경에서는 PM2를 사용하여 자동 관리하는 것이 좋음.
2. HTML Streaming
React v18에서의 주요 변경점 중 하나가 HTML Streaming과 점진적인 Hydration입니다
개발자들은 Server Side 단에서 먼저 정적 페이지를 렌더링하고 JS파일들도 번들링한 후에 둘다 Client Side로 보내주는 생각을 해냈다. 하지만 그 DOM에는 동적인 이벤트가 하나도 없는 메마를 상태일 것이다. 그래서 이 메마른 뼈대에 수분을 보충해서, 즉 HTML 코드와 JS 코드를 서로 매칭시켜 동적인 웹사이트를 브라우저에 랜더링하는 기술이 등장했는데 이게 바로
Hydratation이다. 그래서 Hydration을 한글로 직역하면 수분 보충이라고 말 할 수 있다.
=> 기존 HTML을 유지하면서 React가 이벤트 핸들러와 상태를 연결하는 과정
v18에서부터는 pipeToNodeWritable를 이용해 html 코드를 스트리밍 형식을 통해 작은 청크 형태로 나누어 보내줄수 있습니다.
import express from 'express';
import { renderToPipeableStream } from 'react-dom/server';
import App from './App';
const app = express();
app.get('/', (req, res) => {
res.setHeader('Content-Type', 'text/html');
const { pipe } = renderToPipeableStream(<App />, {
onShellReady() {
pipe(res);
},
onAllReady() {
console.log("전체 렌더링 완료");
}
});
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
3. React 마운트 과정
1. 함수 컴포넌트 호출
2. 구현부 실행
- props 취득, hook 실행, 내부 변수 및 함수 생성
- 단, hook 에 등록해둔 상태값, 부수함수 효과 등은 별도 메모리에 저장되어 관리된다.
3. return 실행
- 렌더링 시작
4. 렌더 단계(Render Phase)
- 가상DOM을 생성한다.
5. 커밋 단계(Commit Phase)
- 실제 DOM에 반영한다.
6. useLayoutEffect
- 브라우저가 화면에 Paint 하기 전에, useLayoutEffect에 등록해둔 effect(부수효과함수)가 '동기'로 실행된다.
- 이 때, state, redux store 등의 변경이 있다면 한번 더 재렌더링 된다.
7. Paint
- 브라우저가 실제 DOM을 화면에 그린다. didMount가 완료된다.
8. useEffect
- Mount되어 화면이 그려진 직후, useEffect에 등록해둔 effect(부수효과함수)가 '비동기'로 실행된다.
https://velog.io/@timosean/Server-component-vs.-Client-Component
https://react.dev/reference/react-dom/client/hydrateRoot#hydrating-server-rendered-html
https://curryyou.tistory.com/486
https://velog.io/@9rganizedchaos/React-Server-Components%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%B4%EB%B3%B4%EC%9E%90
'WEB개발 > REACT' 카테고리의 다른 글
[React] web성능 메트릭 (0) | 2023.12.18 |
---|---|
[React] Typescript (1) | 2023.12.18 |
[Next.js] Tailwind CSS, ESLint, Webpack (0) | 2023.12.11 |
[React] Next.js, Hydrate (0) | 2023.12.05 |
[React] 기본HOOKS (useState, useEffect, useContext, useMemo, useReduce, useRef) (0) | 2023.12.01 |