[강의] 한 입 크기로 잘라먹는 Next.js #4

Onion·2025년 8월 14일

Next.js 공부

목록 보기
4/11

https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%ED%81%AC%EA%B8%B0-nextjs?srsltid=AfmBOop98SToIvyP4ZLiwetJfX_FMn0dbu097kRsUWsuX9BOUxCY1Ihi
위 내용을 바탕으로 강의를 수강하며 정리하였습니다.

App Router 시작하기

1. App Router 시작하기

1) App Router

Next.js 13 버전에 새롭게 추가된 라우터
기존의 Page Router를 완전히 대체

변경된 사항

  • 레이아웃 설정 방식 변경
  • 페이지 라우팅 설정 방식 변경
  • 데이터 페칭 방법 변경
  • React 18 신규 기능 추가

변경되지 않는 사항

  • 네비게이팅
  • 프리페칭
  • 사전 렌더링

2) 실습을 위한 환경 준비

  1. vscode로 열기
    vscode에서 .../onebite-next/ 폴더로 열기

  2. 터미널에서 section3 폴더 생성
    vscode에서 터미널을 열어서 npx create-next-app@14 section03 명령어 실행
    → Ok to proceed에서 y 입력
    → 타입스크립트를 사용할 거냐는 질문에 Yes 선택 후 엔터
    → ESLint를 사용할 거냐는 질문에 Yes 선택 후 엔터
    → Tailwind CSS를 사용할 거냐는 질문에 No 선택 후 엔터
    → src/ 디렉토리를 사용할 거냐는 질문에 Yes 선택 후 엔터
    → App Router를 사용할 거냐는 질문에 Yes 선택 후 엔터
    → import alias를 사용할 거냐는 질문에 No 선택 후 엔터

import alias: 임포트 문을 사용할 때 절대 경로를 사용해서 값을 불러올 수 있게 하는 그러한 기능

  • npx 명령어
    • node-package-execute
    • npmjs.com에 실제로 올라가 있는 등록되어 있는 라이브러리들의 최신 버전의 노드 패키지를 다운로드 없이 바로 실행
  • create-next-app 명령어
    • Next.js 공식 문서에서 안내하고 있는 새로운 Next.App을 생성하는 노드.js 패키지
  • @14 명렁어
    • 현재 설치하려는 Next App을 14 버전으로 설치하겠다는 뜻
    • 현재 가장 최신 버전과는 약간 차이가 있지만, 페이지 라우터에 존재하는 모든 기능들은 14 버전에서 안정적으로 모두 다 사용 가능
  1. 개발 모드로 넥스트 앱 실행
    생성된 /section03/ 폴더로 vscode에서 다시 열기
    → vscode의 터미널 열기
    → npm run dev 명령어 실행
    → http://localhost:3000/ 로 이동하면 확인 가능
    → (종료 시에는) Ctrl+D나 Ctrl+C 입력

  2. .eslintrc.json 파일명을 eslint.config.mjs로 바꾸고 코드는 아래와 같이 수정하기

import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const compat = new FlatCompat({
  baseDirectory: __dirname,
});

const eslintConfig = [
  ...compat.extends("next/core-web-vitals", "next/typescript"),
  {
    // 이 부분이 추가됩니다!
    rules: { 
      "@typescript-eslint/no-unused-vars": "warn",
      "@typescript-eslint/no-explicit-any": "off",
    },
  },
];

export default eslintConfig;

 

2. 페이지 라우팅 설정하기

1) App Router 버전의 페이지 라우팅

Page Router 버전의 페이지 라우팅과 방식이 크게 다르지 않음
→ 라우팅이 자동 설정된다는 점은 두 방식 모두 동일

Page Router 버전의 페이지 라우터에서는...
→ /src/pages/ 아래에 있는 파일명이나 폴더명이 페이지의 이름이 되었음

App Router 버전의 페이지 라우터에서는...
→ /src/app/ 아래에서 page.tsx라는 파일명을 갖는 파일만 페이지가 됨

→ 동적 경로는...

2) 진행할 프로젝트

page 라우터에서 진행했던 '한입 북스 프로젝트'를 그대로 진행

3) 실습 진행을 위한 환경 세팅

4) 실습 진행

추가 사항

App Router에서는 쿼리 스트링이나 URL 파라미터와 같은 경로상에 포함되는 값들은 페이지 컴포넌트에게 모두 props로써 전달

서버 컴포넌트의 경우에는 서버 측에서 사전 렌더링을 위해 딱 한 번 실행이 되기 때문에 async 키워드를 붙일 수 있음

 

3. 레이아웃 설정하기

1) 레이아웃 설정

2) 실습 진행을 위한 환경 세팅

  • vscode로 section03 폴더 열기
    → vscode 터미널을 열어서 npm run dev로 개발 모드 서버 열기

3) 실습

추가 사항

/src/app/layout.tsx

  • 모든 페이지에 다 동일하게 적용이 되는 가장 기초적인 레이아웃
  • HTML 페이지의 기초 틀을 유지하도록 만들어줌

layout.tsx 코드에서는 page/tsx가 어디 위치에 배치할 지 명시해줘야 함!!
→ layout.tsx 코드에서 {children}이라는 프롭스를 꼭 전달 받아야 함

특정 페이지들에만 적용되는 공통 레이아웃 적용을 위해서는 라우트 그룹(Route Group) 기능 사용 가능
→ /src/app/ 폴더 밑에 새로운 폴더를 생성하는데, 이때 폴더의 이름은 ()로 감싸주기
→ 라우트 그룹은 경로 상에는 아무런 영향을 미치지 않음

 

4. 리액트 서버 컴포넌트 이해하기

1) 리액트 서버 컴포넌트 등장 배경

상호작용이 있는 컴포넌트와 상호작용이 없는 컴포넌트가 섞여 있을 때, 상호작용이 있는 컴포넌트만 수화(Hydration)하면 되는데...
Page Router에서는 한 페이지에 속해있기만 한다면 상호작용 여부와 상관 없이 Hydration을 전부 진행해서 TTI까지 늦어지게 됨

그렇다면?

상호작용이 없는 컴포넌트들은 Hydration이 필요가 없기 때문에, 상호작용이 있는 컴포넌트만 구분해서 Hydration을 진행하면 됨
상호작용이 없는 컴포넌트들은 사전 렌더링 때 한 번만 불러오면 됨

2) 리액트 서버 컴포넌트(React Server Component)

  • React 18v부터 새롭게 추가된, 새로운 유형의 컴포넌트
  • 서버측에서만 실행되는 컴포넌트 (브라우저에서는 실행 X)

▼ 사전 렌더링 시에는 모든 컴포넌트를 불러옴

▼ 수화를 위해 컴포넌트를 불러올 때에는, 상호작용이 있는 컴포넌트들만 구분해서 불러옴

  • 서버 컴포넌트 = 서버에서만 실행되는 컴포넌트 (상호작용이 없는 컴포넌트)
  • 클라이언트 컴포넌트 = 일반적인 리액트 컴포넌트 (상호작용이 없는 컴포넌트)

=> Next.js의 공식 문서에서는 페이지의 대부분은 서버 컴포넌트로 구성할 것을 권장하며, 클라이언트 컴포넌트는 꼭 필요한 경우에만 사용할 것

2) 실습 진행을 위한 환경 세팅

  • vscode로 section03 폴더 열기
    → vscode 터미널을 열어서 npm run dev로 개발 모드 서버 열기

3) 실습

추가 사항

App Router에서는 기본적으로 모든 컴포넌트가 서버 컴포넌트로 동작

서버 컴포넌트에서는 원래 서버에서 할 수 있었던 보안에 민감한 작업들이나 데이터를 패칭해 오는 기능 등의 다양한 작업들을 진행할 수 있게 됨
= 클라이언트 컴포넌트에서는 해당 동작이 불가능
= 클라이언트 컴포넌트에서는 가능한 동작을 서버 컴포넌트에서는 동작 불가능 (Ex. useEffect())

링크는 HTMl의 고유 기능이기 때문에 JS 기능을 활용하는 상호작용은 아니어서, 링크로 이동하는 기능만 포함되어 있다면 해당 컴포넌트는 서버 컴포넌트!

 

5. 리액트 서버 컴포넌트 주의사항

1) 서버 컴포넌트에는 브라우저에서 실행될 코드가 포함되면 안된다

▼ 불가능!

2) 클라이언트 컴포넌트에는 클라이언트에서만 실행되지 않는다

  • 서버 컴포넌트 = 서버 측에서만 실행되는 것
  • 클라이언트 컴포넌트 = 클라이언트 + 서버 측에서 모두 실행되는 것

3) 클라이언트 컴포넌트에서 서버 컴포넌트를 import 할 수 없다

▼ 불가능!

▼ 왜 불가능하지?

▼ 그럼 이런 경우에서 Next.js는 어떻게 동작하지?

실습으로 확인해보기

추가 사항

만약 어쩔 수 없이 클라이언트 컴포넌트가 서버 컴포넌트를 반드시 자식으로 둬야 하는 경우가 된다면, 그럴 때에는 서버 컴포넌트를 클라이언트 컴포넌트에서 children props로 받아서 렌더링을 시켜주기

4) 서버 컴포넌트에서 클라이언트 컴포넌트에게 직렬화 되지 않는 Props는 전달 불가능하다

직렬화(Serialization)

  • 객체, 배열, 클래스 등의 복잡한 구조의 데이터를 네트워크 상으로 전송하기 위해 아주 단순한 형태(문자열, Byte)로 변환하는 것
  • 예시

그런데, JS 함수는 직렬화가 불가능
= 서버 컴포넌트에서 클라이언트 컴포넌트로 향하는 Props가 될 수 없음


사전 렌더링 과정 진행 중에...

  • 서버 컴포넌트가 실행되면 바로 HTML 태그가 실행되는 것이 아니라, RSC 페이로드라는 JSON과 비슷한 형태의 문자열이 생성
  • 특정 서버 컴포넌트가 자신의 자식인 클라이언트 컴포넌트에게 함수 형태의 값을 props로 전달하고 있다면, 함수값 또한 함께 직렬화가 되어서 RSC 페이로드에 포함이 되어야 하는데 그게 불가능!
    => 런타임 에러 발생!!

RSC Payload

  • React Server Component의 순수한 데이터(결과물)
  • React Server Component를 직렬화 한 결과
  • RSC Payload에는 서버 컴포넌트의 모든 데이터가 포함
    • 서버 컴포넌트의 렌더링 결과
    • 연결된 클라이언트 컴포넌트의 위치
    • 클라이언트 컴포넌트에게 전달하는 Props 값
  • 예시

 

6. 네비게이팅

실습 부분만 다시 듣기

1) 네비게이팅

네비게이팅(Navigating)
= 페이지 이동을 의미

페이지 이동은 Client Side Rendering 방식으로 처리
= Page Router 버전과 동일한 방식

App Router에서는 Server Component가 추가되어 방식이 살짝 변경됨 (비슷하긴 하지만...)

  • 기존에는 JS Bundle(클라이언트 컴포넌트)만 미리 전달되었지만, App Router에서는 서버 컴포넌트까지 같이 전달

2) 실습 진행을 위한 환경 세팅

  • vscode로 section03 폴더 열기
    → vscode 터미널을 열어서 npm run dev로 개발 모드 서버 열기

3) 실습

모든 페이지에 다 똑같이 렌더링 되는 글로벌 내비게이션 바 생성
→ 루트 레이아웃에 생성하면 됨

 

7. 한입북스 UI 구현하기

수업 자료로 올려주신 /src/ 코드를 바탕으로 코드 리뷰 진행

코드 리뷰 필요하면 다시 듣기

profile
눈물이 나도 코드를 계속 까보는 양파

0개의 댓글