✓ 싱글 페이지 애플리케이션
- SPA(Single Page Application)
- 자바스크립트에 의존, 자바스크립트 번들이 렌더링
- 브라우저의 history.pushState & history.replaceState 를 이용해 페이지 전환
- 페이지를 불러온 이후에는 서버에서 HTML을 내려받지 않고, 하나의 페이지에서 모든 작업 처리
- 빈 <body /> 에 DOM을 추가하는 방식으로 페이지 전환
- ex) Gmail
✓ 서버 사이드 렌더링
-전통적인 방식
- 페이지 전환시 서버에 새로운 페이지 요청 -> HTML 페이지 다운로드 및 파싱
- 서버에서 렌더링에 필요한 작업 수행
✓ 서버 사이드 렌더링 장점
- 최초 페이지 진입이 빠름 : 보통 서버가 클라이언트보다 성능이 더 좋으므로
- 검색 엔진 최적화 / 메타 데이터 제공 : 크롤링 로봇이 자바스크립트를 실행하지 않은, 페이지의 정적 정보를 수집
- 누적 레이아웃 이동이 적음
- 사용자 디바이스 성능에 비교적 자유로움
- 보안에 안전
✓ 서버 사이드 렌더링 단점
- 소스 코드 작성시 서버 고려 : window is not defined / 클라이언트에서 실행하는 코드 실행 불가
- 적절한 서버 구축 필요
- 서비스 지연에 따른 문제 : 막대한 데이터를 포함하는 경우 페이지 렌더링 지연
✓ 싱글 페이지 애플리케이션 vs 서버 사이드 렌더링 애플리케이션
- code splitting(사용자에게 필요한 코드만 나눠서 번들링, 최적화)을 잘 한 SPA는 멀티 페이지 애플리케이션 보다 나음
- 평균적으로 SPA는 멀티 페이지 애플리케이션 보다 느림 : 서버 문제
- Paint holding, bfcache(Back forward cache), Shared element transition 과 같은 방법을 사용해 멀티 페이지 애플리케이션에서 발생하는 라우팅 관련 문제 해결
✓ 서버사이드 렌더링 관련 리액트 API
- renderToString : 인수로 넘겨받은 리액트 컴포넌트를 렌더링해 HTML 문자(string)로 반환, 클라이언트에서 실행되는 자바스크립트 코드 미포함, 렌더링 X
- renderToStaticMarkup : renderToString과 유사하게 HTML 문자열을 반환하나, hydrate를 수행하지 않는다는 가정 하에 리액트에서 사용하는 추가적인 DOM 속성 생성 X
- renderToNodeStream : 브라우저에서 사용 불가, Node.js 환경에 의존, 서버 환경에서만 사용 가능한 ReadableNodeStream 반환, Chunk 형태로 분할해서 순차적으로 데이터를 가져오는 방식
- renderToStaticNodeStream : renderToNodeStream 과 반환값은 같으나, renderToStaticMarkup과 같이 리액트 속성 미제공, hydrate를 할 힐요가 없는 순수 HTML이 필요한 경우 사용
- hydrate : renderToString / renderToNodeStream 으로 생성된 HTML 컨텐츠에 자바스크립트 핸들러나 이벤트를 붙이는 역할, 인터랙티브한 웹페이지 결과물 생성 cf) hydrate에서 만든 리액트 컴포넌트 트리와 서버에서 만든 HTML이 다르면 불일치 에러(suppressHydrationWarning)
- cf) render : 컴포넌트와 HTML 요소를 인수로 받아 HTML 요소에 해당 컴포넌트 렌더링, 이벤트 핸들러까지 붙이는 작업 모두 수행
✓ Next.js
- 미국 스타트업 Vercel 에서 만든 리액트 기반 프레임워크
- PHP에 영감
- react-page 와 유사
- npx create-next-app@latest
✓ Next.js project
- package.json
- next.config.js : Next.js 프로젝트 환경 설정, swcMinFy: true (번들링, 컴파일 빠르게 수행)
- pages/_app.tsx : 애플리케이션 전체 / Next.js 초기화, 에러 바운더리를 사용해서 애플리케이션 전역 에러 처리, 전역 css 선언, 모든 페이지에 공통 데이터 제공
- pages/_document.tsx : 애플리케이션 HTML 초기화, DOM 속성을 추가하고 싶을 때 사용, 무조건 서버에서 실행되므로 이벤트 핸들러 사용 불가능, next/document 에서 제공하는 head 사용 가능, CSS-in_JS 스타일을 서버에서 모아 HTML로 제공
- pages/_error.tsx : 클라이언트 에러 또는 서버 500 에러 처리 목적
- pages/404.tsx : 404 페이지 정의
- pages/500.tsx : 500 에러는 이 곳에서 먼저 처리
- pages/index.tsx : 웹 사이트 루트 ex) localhost:3000
- pages/.../...tsx : ex) localhost:3000/.../... 로 라우팅
- pages/.../[id].tsx : [ ] 사이에 어떠한 문자도 올 수 있음, 예를 들어 id라는 변수에 a, b
- pages/.../[...props].tsx : .../ 의 하위 모든 주소가 이 곳으로 라우팅, props라는 변수에 배열로 담겨짐
✓ next/link
- Next.js에서 제공하는 라우팅 컴포넌트 <Link />
- 서버 사이드 렌더링이 아닌 클라이언트 라우팅/렌더링 (SPA 방식)
- <a /> 태그와 비슷한 동작을 하나, a 태그는 서버 렌더링 -> 클라이언트에서 hydrate 시 한 번 더 실행
✓ getServerSideProps
- 페이지에 있으면 서버 사이드에서 렌더링되는 페이지로 분류
- 페이지에 없으면 서버 사이드 렌더링이 필요없는 정적인 페이지, 빌드 시점에 미리 만들어도 되는 페이지로 분류
✓ Data fetching
- Next.js 에서 서버 사이드 렌더링을 위한 데이터 불러오기 전략
- pages/ 폴더에 라우팅 되어 있는 파일, export 를 사용한 함수만 사용 가능
- 서버에서 미리 피요한 페이지를 만들어서 제공하거나, 해당 페이지 요청이 있을 때 서버에서 데이터 조회 후 미리 페이지를 만들어 제공
- getStaticPaths : 페이지를 정적으로 보여줄 때 접근 가능한 주소 정의, 정의되지 않은 주소는 404
- getStaticPaths { fallback } : 미리 빌드해야 하는 페이지가 많은 경우 사용, 'true'면 빌드되기 전까지는 fallback 컴포넌트를 보여주고 빌드가 완료된 이후 해당 페이지를 보여줌 <-> 'blocking'시 빌드 완료까지 사용자가 기다려야 함
- getStaticProps : 해당 페이지로 요청이 왔을 때 제공할 props를 반환하는 함수, props는 JSON으로 직렬화 할 수 있는 값만 가능, 무조건 서버에서 실행
- getInitialProps : getStaticPaths, getStaticProps 사용 권장, 페이지 데이터 불러오기
import { GetStaticPaths, GetStaticProps } from 'next';
export const getStaticPaths: GetStaticPaths = async () => {
return {
// /path/post/[id] : /post/1, /post/2 만 가능 /post/3 -> return 404
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
fallback: false,
};
};
export const GetStaticProps: GetStaticProps = async ({ params }) => {
const { id } = params;
const post = await fetchPost(id);
return {
post: { post },
};
}
export default function Post({ post }: { post: Post }) {
// page rendering with post ..
}
✓ Style
- 전역 스타일 : css reset 등 글로벌 스타일, 다른 페이지 컴포넌트와 충돌할 수 있으므로 _app.tsx 에 제한적으로 작성
- 컴포넌트 레벨 css : [name].module.scss / 다른 컴포넌트와 클래스명이 충돌되지 않도록 컴파일시 고유한 클래스명으로 변환 ex) .Button_alert_62TGU
- SASS : npm install --save-dev sass
- SCSS : export 문법 등 사용 가능
- CSS-in_JS : 자바스크립트 내부에 스타일 시트 삽입 ex) styled-component : 스타일을 모두 모아 각각의 스타일에 유니크한 클래스명 부여,서버에서 _document.tsx 를 렌더링할 때 React.Context 형태로 제공됨
✓ next.config.js
- basePath : 호스트 아래 매핑될 url 이름 ex) bathPath: docs -> localhost:3000/docs 에서 서비스 시작
- swcMinfy : swc를 사용해 코드 압축, 기본값 true
- powerByHeader : Next.js는 응답 헤더에 X-Power-by: Next.js 정보 제공, 보얀 취악점으로 분류되므로 false 설정
- redirects: 특정 주소를 다른 주소로 내보내고 싶을 때, 정규식 사용 가능
- reactStrictMode : 리액트 strict mode 사용 여부, true 면 리액트 업데이트 대비 가능
- assetPrefix : next 에서 빌드된 결과물을 동일한 호스트가 아니라, 다른 CDN에 업로드하고 싶을 때 해당 주소 명시