From b9f1638fb22901d2ea5d82d91714e1867ccda7fc Mon Sep 17 00:00:00 2001 From: sonsujin Date: Sun, 5 Apr 2026 21:31:45 +0900 Subject: [PATCH] =?UTF-8?q?study:ch1-ch5=20=EC=9D=BC=EB=B6=80=EB=B6=84?= =?UTF-8?q?=EA=B9=8C=EC=A7=80=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next/onebite/sujin/section01.md | 48 ++++++++ next/onebite/sujin/section02.md | 192 ++++++++++++++++++++++++++++++++ next/onebite/sujin/section03.md | 88 +++++++++++++++ next/onebite/sujin/section04.md | 36 ++++++ next/onebite/sujin/section05.md | 20 ++++ 5 files changed, 384 insertions(+) create mode 100644 next/onebite/sujin/section01.md create mode 100644 next/onebite/sujin/section02.md create mode 100644 next/onebite/sujin/section03.md create mode 100644 next/onebite/sujin/section04.md create mode 100644 next/onebite/sujin/section05.md diff --git a/next/onebite/sujin/section01.md b/next/onebite/sujin/section01.md new file mode 100644 index 0000000..4811226 --- /dev/null +++ b/next/onebite/sujin/section01.md @@ -0,0 +1,48 @@ +# Next.js를 소개합니다 + +React.js 전용 웹 개발 Framework. 페이지 라우팅, 빌트인 최적화 기능, 다이나믹 HTML 스트리밍 등의 다양한 기능들을 제공하는 기술. vercel에서 개발하였으며 다수의 메이저 사이트들이 사용하고 있음. + +## 어떻게 이렇게 많은 사랑을 받을 수 있었을까? + +> Next.js가 리액트 전용의 웹개발 프레임워크이기 때문 + +## 프레임워크 vs 라이브러리 + +### 기능 구현의 주도권이 누구에게 있는가 + +라이브러리(주도권을 개발자가 가짐) + +- ex) jQuery, React.js, +- 기능 구현을 원하는 방향으로 진행한다 +- 쓰고싶은 도구, 쓰고싶은 기술을 사용한다. + +프레임워크(주도권을 Framework가 직접 가짐) + +- ex) Next.js, Remix,,.. +- 프레임워크가 제공하는 기능을 이용하거나 허용하는 범위에서만 추가 도구 사용 가능 + +자유도는 높아도 문제가 될 수 있음. ⇒ 그만큼 기본적으로 제공되는게 없다. + +# 사전 렌더링 이해하기 + +## 사전 렌더링이란 + +> 브라우저의 요청에 사전에 렌더링이 완료된 HTML을 응답하는 렌더링 방식. Client Side Rendering의 단점을 효율적으로 해결하는 기술 + +### Client Side Rendering(;CSR) + +리액트 앱의 기본적인 렌더링 방식이며, 클라이언트(브라우저)에서 직접 화면을 렌더링 하는 방식. + +장점: 초기 접속 이후 페이지 이동이 매우 빠르고 쾌적하다 + +단점: 초기 접속 속도(FCP)가 느림 + +초기 접속 요청이 발생한 시점으로 부터 실제로 화면이 렌더링 되기까지 오래 걸림. 빈 HTML, js Bundle들을 받아오고, 실행까지 마쳐야 하기 때문. + +## 사전 렌더링 과정 + +접속 요청 ⇒ 서버에서 JS 실행(렌더링) ⇒ 렌더링이 완료된 HTML 파일을 브라우저에게 전달 ⇒ 화면에 렌더링 ⇒ 화면이 나타남(상호작용 불가) ⇒ JS Bundle을 브라우저에게 보냄 ⇒ 브라우저에서 JS 실행(HTML과 연결) ⇒ 상호작용 가능(Time To Interactive; TTI) + +이후 페이지 이동 요청은 CSR 방식으로 처리됨. ⇒ 초기 접속 요청 과정에서 하이드레이션을 위해 리액트 앱(JS Bundle)을 전달해줬기 때문에 가능. + +빠른 FCP 달성 + 빠른 페이지 이동 diff --git a/next/onebite/sujin/section02.md b/next/onebite/sujin/section02.md new file mode 100644 index 0000000..f559284 --- /dev/null +++ b/next/onebite/sujin/section02.md @@ -0,0 +1,192 @@ +# **02. Page Router 핵심 정리** + +## **Page Router를 소개합니다** + +많은 기업에서 사용되고 있는 안정적인 라우터. React Router와 같이 페이지 라우팅 기능을 제공함. Pages라는 폴더의 구조를 기반으로 페이지 라우팅을 제공 + +![스크린샷 2026-03-20 162225.png](attachment:784ac2a1-0776-4794-b7d7-84d2fc8ff7d4:스크린샷_2026-03-20_162225.png) + +Next.js는 파일명 기반의 페이지 라우팅이지만. 폴더를 기준으로 설정할 수도 있음 + +![스크린샷 2026-03-20 162342.png](attachment:bedf1d30-0402-404e-bb82-d07b08b64dc0:스크린샷_2026-03-20_162342.png) + +### **동적 경로(Dynamic Routes)** + +![스크린샷 2026-03-20 162451.png](attachment:c21a7471-459b-4752-8f08-1eea52969174:스크린샷_2026-03-20_162451.png) + +### **\_\_app.ts** + +모든 페이지 컴포넌트의 부모역할을 하는 루트 컴포넌트. 레이아웃이나 비즈니스 로직을 작성하는데 쓰임. + +### **\_\_document.ts** + +모든 페이지에 공통적으로 적용되어야하는 Next.js 앱의 HTML을 설정. + +메타 태그, 폰트 불러오기, 캐릭터 셋 설정, 서드 파티 스크립트 등 + +### **next.config.mjs** + +## **네비게이팅** + +### **Link 컴포넌트** + +a태그를 사용하게 되면 서버로 새로운 페이지를 요청하는 방식으로 페이지를 이동시키게 됨. + +a 태그와 사용법이 동일하며, href 속성에 이동하려는 경로를 기입하면 됨. + +``` + +``` + +### **프로그래매틱한 페이지 이동** + +> 사용자가 링크를 직접 클릭했을 때 페이지를 이동시키는 게 아닌 특정 버튼이 클리이 되었거나 특정 조건을 만족시킬 경우 함수내부에서 일어나는 경우를 말함 + +``` +import "@/styles/globals.css"; +import type { AppProps } from "next/app" +import Link from "next/link" +import { userRouter } from "next/router" + +export default function App({ Component, pageProps }: AppProps) { + const router = useRouter() + const onClickButton = () => { + router.push("/test"); + }; + + return ( + <> +
+ index +
+ +
+
+ + + ) +} +``` + +## **프리페칭** + +> 페이지를 사전에 미리 불러오는것. + +### **Next.js에서의 프리페칭** + +현재 보고 있는 페이지에서 이동할 수 있는 페이지들을 사전에 미리 다 불러와 놓음으로써 페이지 이동을 지체없이 빨리 이동하도록 하는 기능. + +### **왜 필요한가?** + +넥스트.js 앱은 모든 리액트 컴포넌트들을 페이지별로 분리해서 저장을 해두기 때문. + +사전 렌더링의 과정에서 자바 스크립트 번들 파일을 전달할때 현재 페이지에 해당되는 자바스크립트 코드들만 전달되기 때문. + +이렇게 동작하는 이유는 초기 접속시 전달되는 자바스크립트 코드의 양을 줄이기 위해서. + +번들 양이 많아지면 하이드레이션 과정도 느려질 것이고, TTI가 늦어지는 문제가 발생할 수 있기 때문 + +이렇게 되면 나머지 페이지는 CSR로 처리될 수 있는게 아님. + +그래서 페이지 이동시 자바스크립트 코드를 또 불러와야 하는 과정이 필요할 수 있음 ⇒ 오히려 페이지 이동은 느려지고 비효율적으로 가져옴. + +이러한 문제를 방지하기 위해 프리페칭이라는 기능이 있는것! + +링크 컴포넌트로 명시된 경로가 아니면 프리패칭이 이루어지지 않음. + +이럴 경우 라우터 객체의 특정 메서드 이용해서 직접 프리패칭하도록 코드를 작성하면 됨. + +프리페칭을 원하지 않는 경우 Link 컴포넌트의 prefetch 속성을 false로 명시하면 됨. + +## **API Routes** + +> Next.js 앱에서 APi를 구축할 수 있게 해주는 기능 + +### **API Routes 공식 문서** + +https://nextjs.org/docs/pages/building-your-application/routing/api-routes + +## **스타일링** + +### **인라인방식** + +길어지면 가독성을 해칠 수 있음 + +### **스타일 분리** + +Next.js 에서는 앱 컴포넌트가 아닌 다른 파일에서는 임포트 문을 통해 CSS파일을 그대로 불러오는걸 제한하고 있음. 페이지별로 CSS의 클래스네임이 겹치는 문제를 원천차단하기위함. CSS 모듈을 사용해서 작업하면 됨. + +## **사전 렌더링과 데이터 페칭** + +기존 리액트에서 초기 접속 시 데이터 페칭은 컴포넌트가 마운트 된 이후에나 발생하기 때문에 데이터의 로딩이 오래걸림. + +사전 렌더링을 진행하는 과정에서 현재 페이지에 필요한 데이터까지 불러올 수 있음. + +다양한 방식으로 사전렌더링 할 수 있도록 여러 방식을 제공 + +### **1. SSR(서버 사이드 렌더링)** + +- 가장 기본적인 사전 렌더링 방식 +- 요청이 들어올 때마다 사전 렌더링을 진행 +- 페이지 내의 데이터를 최신으로 유지할 수 있다는 장점이 있음 +- 데이터의 응답속도가 느려지게 되면 브라우저의 로딩을 기다려야 하기 때문에 불편함을 초래할 수 있음. + +### **2. SSG(정적 사이트 생성)** + +- SSR의 단점을 해결하는 사전 렌더링 방식 +- 빌드 타임에 미리 페이지를 사전 렌더링 해둠 +- 사전 렌더링에 많은 시간이 소요되는 페이지더라도 사용자의 요청에는 매우 빠른 속도로 응답 가능 +- 매번 똑같은 페이지만 응답함. 최신 데이터 반영은 어렵다는 단점이 존재 + +### 2-1. SSG 동적 경로에 적용하기 + +정적 경로에 적용하는 것처럼 getStaticProps로 바꾸게 되면 해당 오류가 발생 + +```c +Error: getStaticPaths is required for dynamic SSG pages and is missing for '/book/[id]'. +Read more: https://nextjs.org/docs/messages/invalid-getstaticpaths-value +``` + +이 오류가 발생하는 이유는 동적 경로를 갖도록 설정한 페이지에서는 SSG 방식으로 사전 렌더링 하여 미리 생성해두기 위해선 어떤 URL 파라미터들이 존재할 수 있는지 설정해주어야 함. + +```c +export const getStaticPaths = () => { + return { + paths: [{ params: { id: "1" } }, { params: { id: "2" } }, { params: { id: "3" } }], + fallback: false, + }; +}; +``` + +### 2-3 SSG 폴백 옵션 설정하기 + +위의 코드에서 폴백옵션은 3가지중 하나로 설정할 수 있음. + +- false: 패스에 없는 경로로 요청시 404 페이지 반환 +- blocking: 즉시 생성(SSR 처럼) + ![image.png](attachment:9ddfa57f-f68f-4fe3-9a48-469899d414f1:image.png) + 주의사항 : 존재하지 않았던 페이지를 추가적으로 요청할 때 사전 렌더링 시간이 길어지면 로딩이 발생하게 될 수 있음 +- true : 먼저 props없는 페이지를 반환하고 Props를 계산하여 Props만 따로 반환. + ![image.png](attachment:45a890f2-d8ff-403a-bba6-7581babe793b:image.png) + +### **3. 증분 정적 재생성(ISR; Incremental Static Regeneration)** + +SSG 방식으로 생성된 정적 페이지를 일정시간을 주기로 다시 생성하는 기술 + +![image.png](attachment:22ce1b77-4c60-494d-b833-bb2c2a1b665b:image.png) + +### 3-1. ISR 주문형 재검증(On-Demand ISR) + +- 시간 기반의 ISR을 적용하기 어려운 페이지 + - 시간과 관계없이 사용자의 행동에 따라 데이터가 업데이트 되는 페이지 + - ex) 커뮤니티 사이트의 게시글 페이지 + +요청할 때마다 페이지를 다시 생성하는 ISR + +# 페이지 라우터의 단점 + +1. 페이지별 레이아웃 설정이 번거롭다 +2. 데이터 페칭이 페이지 컴포넌트에 집중된다 +3. 불필요한 컴포넌트들도 JS Bundle에 포함된다. + + 하이드레이션이 필요없는 컴포넌트들 까지 포함될 수 있음. ⇒ 하이드레이션 하는 시간이 더 걸리게 됨. diff --git a/next/onebite/sujin/section03.md b/next/onebite/sujin/section03.md new file mode 100644 index 0000000..b70400e --- /dev/null +++ b/next/onebite/sujin/section03.md @@ -0,0 +1,88 @@ +# App Router 시작하기 + +## 변경되거나 추가되는 사항 + +- 페이지 라우팅 설정 방식 변경 +- 레이아웃 설정 방식 변경 +- 데이터 페칭 방식 변경 +- React 18 신규 기능 추가(ex; React Server Component, Streaming) + +## 크게 변경되지 않는 사항 + +- 네비게이팅 +- 프리페칭 +- 사전렌더링 + +# 페이지 라우팅 설정하기 + +페이지 라우터에서의 라우팅과 방식 자체가 다르지는 않음. + +![image.png](attachment:c0f83f63-3cd4-48f6-845e-91b71245c463:image.png) + +## 동적 경로 + +![image.png](attachment:5bbac13d-1a04-44c7-ab88-e58480836e61:image.png) + +# 레이아웃 설정하기 + +![image.png](attachment:b1724121-3d1c-4737-b649-8ed9322fc57f:image.png) + +여기서 layout.tsx 파일은 ‘/search’ 경로로 시작하는 모든 페이지의 레이아웃으로 적용됨 + +# 리액트 서버 컴포넌트 이해하기 + +## 등장 배경 + +Page Router 버전의 Next.js에서의 문제점 + +상호작용이 필요없는 컴포넌트들까지 JS Bundle안에 포함됨. ⇒ 번들 크기가 커지면 하이드레이션 하는 과정이 길어지고, 사용자가 상호작용할 수 있기 까지의 시간(TTI)가 늦어져버림. + +## React Server Component + +서버 측에서만 실행되는 컴포넌트. 하이드레이션 이전에 JS Bundle로 전달하는 과정에서 서버 컴포넌트 들은 빠지게 됨. + +![image.png](attachment:110fa730-3b8a-42de-8ee9-3d95b3518eb1:image.png) + +페이지의 대부분을 서버 컴포넌트로 구성할 것을 권장하고, 클라이언트 컴포넌트는 꼭 필요한 경우에만 사용할 것. + +co-location + +# 리액트 서버 컴포넌트 주의사항 + +1. 서버 컴포넌트에는 브라우저에서 실행될 코드가 포함되면 안된다 + + ![image.png](attachment:6be583ba-6a38-40f8-9d0d-3eb39a362e08:image.png) + +2. 클라이언트 컴포넌트는 클라이언트에서만 실행되지 않는다 + + ![image.png](attachment:4e92db4c-c98c-4439-b712-fd880f4fcc20:image.png) + +3. 클라이언트 컴포넌트에서 서버 컴포넌트를 import할 수 없다 + + ![image.png](attachment:8bf24ad2-7e37-4fc4-b543-0ac02813dfb6:image.png) + + ![image.png](attachment:20fc1963-b3f3-4c33-81fd-062931653472:image.png) + + 이런 경우 Next.js 는 자동으로 서버 컴포넌트를 클라이언트 컴포넌트로 변경 + +4. 서버 컴포넌트에서 클라이언트 컴포넌트에게 직렬화 되지 않는 Props 는 전달 불가 + + 직렬화: 객체, 배열, 클래스 등의 복잡한 구조의 데이터를 네트워크 상으로 전송하기 위해 아주 단순한 형태(문자열, Byte)로 변환하는 것. + + 자바스크립트의 함수는 직렬화가 불가능 함. 이처럼 함수같은 값은 서버 컴포넌트에서 클라이언트 컴포넌트로 전달되는 Props가 될수 없음. + + 이건 Next 서버에서 서버 컴포넌트가 어떻게 실행되는지를 살펴보면 됨. + + 서버 컴포넌트는 사전 렌더링 시 클라이언트 컴포넌트와 함께 실행 되며, 모든 컴포넌트 들이 한번에 실행되지는 않음. 먼저 서버 컴포넌트 ⇒ 클라이언트 컴포넌트 + + ![image.png](attachment:29e9f914-93f8-42d2-af7c-d64837f5e527:image.png) + + 먼저 RSC 페이로드라는 json 형태의 문자열이 생성됨. + + RSC Payload : React Server Component 의 순수한 데이터(결과물) . RCS를 직렬화한 결과 + +# 네비게이션 + +Page Router 방식과 동일하게 Client Side Rendering 방식으로 처리됨 + +![image.png](attachment:ad7f4f07-53f8-4c51-8756-2f8ec6248677:image.png) diff --git a/next/onebite/sujin/section04.md b/next/onebite/sujin/section04.md new file mode 100644 index 0000000..66d807c --- /dev/null +++ b/next/onebite/sujin/section04.md @@ -0,0 +1,36 @@ +# 앱 라우터의 데이터 페칭 + +![image.png](attachment:f86b3403-b2e0-41ef-9337-1b1699e78709:image.png) + +![image.png](attachment:d62b50da-ef02-4de5-a55c-603be0f5ccc9:image.png) + +![image.png](attachment:f44eb132-70d2-4864-8e6d-0363fefba91d:image.png) + +![image.png](attachment:84b6d5d5-05c0-4601-aece-9f5a442abee9:image.png) + +서버 컴포넌트는 비동기적으로 데이터 페칭이 가능함. ⇒ 기존의 getServerSideProps, getStaticProps를 대체 + +![image.png](attachment:6cc1c8cb-7ad0-4efa-b09a-47a7319de09a:image.png) + +# 데이터 캐시 + +- cache: no-store + - 데이터 페칭의 결과를 저장하지 않는 옵션 + - 캐싱을 아예 하지 않도록 설정하는 옵션임 +- cache: force-cache + - 요청의 결과를 무조건 캐싱함 + - 한번 호출 된 이후에는 다시는 호출되지 않음 +- revalidate: 숫자 + - 특정 시간을 주기로 캐시를 업데이트함 + - 마치 Page Router의 ISR 방식과 유사함 +- tags + - On-Demand Revalidate + - 요청이 들어왔을때 데이터를 최신화 함 + +# 리퀘스트 메모이제이션 + +중복된 요청을 하나의 요청으로 자동으로 합쳐주는 기능. + +캐시와는 다름. 하나의 페이지를 헨더링 하는 동안에 중복된 api요청을 캐싱하기 위해 존재하며 렌더링이 종료되면 모든 캐시가 소멸됨. + +서버 컴포넌트를 도입하면서 데이터를 페칭하는 패턴이 변화했기 때문 diff --git a/next/onebite/sujin/section05.md b/next/onebite/sujin/section05.md new file mode 100644 index 0000000..f473a48 --- /dev/null +++ b/next/onebite/sujin/section05.md @@ -0,0 +1,20 @@ +# 풀 라우트 캐시 + +Next 서버측에서 빌드 타임에 특정 페이지의 렌더링 결과를 캐싱하는 기능 + +![image.png](attachment:863d31cc-55c9-4e70-ab65-09e6fe32faae:image.png) + +## 분류 기준 + +### Dynamic Page로 설정되는 기준 + +특정 페이지가 접속 요청을 받을 때마다. 매번 변화가 생기거나 데이터가 달라질 경우 + +1. 캐시되지 않는 데이터 페칭을 사용할 경우 +2. 동적함수(쿠키, 헤더, 쿼리스트링)을 사용하는 컴포넌트가 있을 때 + +### Static Page로 설정되는 기준 + +Dynamic Page가 아니면 모두 Static Page + +![image.png](attachment:a58b6b82-b3ca-4b33-baf2-e83652ac9f5a:image.png)