Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions next/onebite/sujin/section01.md
Original file line number Diff line number Diff line change
@@ -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 달성 + 빠른 페이지 이동
192 changes: 192 additions & 0 deletions next/onebite/sujin/section02.md
Original file line number Diff line number Diff line change
@@ -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 속성에 이동하려는 경로를 기입하면 됨.

```
<Link 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 (
<>
<header>
<Link href={"/"}>index</Link>
<div>
<button onClick={onClickButton}>/test page로 이동</button>
<div>
<header>
<Component {...pageProps} />
</>
)
}
```

## **프리페칭**

> 페이지를 사전에 미리 불러오는것.

### **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에 포함된다.

하이드레이션이 필요없는 컴포넌트들 까지 포함될 수 있음. ⇒ 하이드레이션 하는 시간이 더 걸리게 됨.
88 changes: 88 additions & 0 deletions next/onebite/sujin/section03.md
Original file line number Diff line number Diff line change
@@ -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)
36 changes: 36 additions & 0 deletions next/onebite/sujin/section04.md
Original file line number Diff line number Diff line change
@@ -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요청을 캐싱하기 위해 존재하며 렌더링이 종료되면 모든 캐시가 소멸됨.

서버 컴포넌트를 도입하면서 데이터를 페칭하는 패턴이 변화했기 때문
20 changes: 20 additions & 0 deletions next/onebite/sujin/section05.md
Original file line number Diff line number Diff line change
@@ -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)