[Next.js 강의 정리] 서버 액션, Parallel Route, 최적화에 관하여

2025. 6. 8. 13:48·Frontend

이정환님의 '한 입 크기로 잘라먹는 Next.js(v15)' 강의를 듣고 정리한 내용입니다.

강의 링크: https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%ED%81%AC%EA%B8%B0-nextjs?srsltid=AfmBOoryPUbZjBwZDQne9kDfuiHCFu7VdxmeCNFtMqj4F58vfjIaezUX

 

한 입 크기로 잘라먹는 Next.js(v15) 강의 | 이정환 Winterlood - 인프런

이정환 Winterlood | , [임베딩 영상]한 입 크기로 잘라먹는 Next.js | Official Trailler한입 크기로 잘라먹는 Next.js(15+)15시간의 분량으로 Page Router부터 App Router까지💡 Page Router란?Next.js

www.inflearn.com


1. 서버 액션

브라우저에서 호출할 수 있는 서버에서 실행되는 비동기 함수

→ 클라이언트인 브라우저에서 특정 양식의 제출이 발생했을 때 서버 측에서만 실행되는 어떠한 함수를 실행시켜주는 기능

  1. “use server” 지시자를 사용해야
  2. formData.get을 통해서 브라우저에서 전달받은 값을 쉽게 꺼내쓸 수 있는데, 이 때 타입 추론을 위해 ?.toString()을 사용하면 편하다.
function ReviewEditor() {
  async function createReviewAction(formData: FormData) {
    "use server";

    const content = formData.get("content")?.toString();
    const author = formData.get("author")?.toString();

    console.log(content, author);
  }

  return (
    <section>
      <form action={createReviewAction}>
        <input name="content" placeholder="리뷰 내용" />
        <input name="author" placeholder="작성자" />
        <button type="submit">작성하기</button>
      </form>
    </section>
  );
}

 

서버 액션을 쓰는 이유?

→ 함수 하나만으로 API 역할을 할 수 있는 코드를 생성할 수 있으므로

→ 서버 측에서만 실행되기 때문에 보안상으로 안전

 

input에 required 애트리뷰트를 추가하면 빈 칸 입력을 방지할 수 있다.

input에 hidden 애트리뷰트를 추가하면 안보이게 할 수 있다 (bookId 같은 거 전달할 때 유용, 그리고 readOnly도 같이 추가해야 next에서 에러가 발생하지 않는다)


페이지 재검증

서버 액션이 성공적으로 종료되었을 때 서버 측에서 페이지(컴포넌트)를 재검증하기를 원한다면

→ revalidatePath(현재 경로)를 활용하자

→ Next 서버가 재검증 (방금 작성한 리뷰가 새로고침을 하지 않아도 보이게 됨)

→ 컴포넌트가 다시 렌더링되면서, 데이터 페칭도 다시 진행됨

 

주의할점1: 오직 서버에서만 호출할 수 있는 메서드 (클라이언트 컴포넌트x)

주의할점2: 페이지에 포함된 모든 캐시를 무효화시켜버림(force-cache라고 하더라도)

주의할점3: 페이지 자체를 캐싱하는 풀 라우트 캐시도 무효화됨(다음에 페이지에 접속할 때 dynamic page처럼 페이지가 다시 만들어짐)

revalidatePath가 실행되서 캐시들이 무효화될 때, purge라는 표현을 씀(숙청하다, 제거하다)


페이지 재검증의 다양한 방식

    // 1. 특정 주소의 해당하는 페이지만 재검증
    revalidatePath(`/book/${bookId}`);

    // 2. 특정 경로의 모든 동적 페이지를 재검증
    revalidatePath("/book/[id]", "page");

    // 3. 특정 레이아웃을 갖는 모든 페이지 재검증
    revalidatePath("/(with-searchbar)", "layout");

    // 4. 모든 데이터 재검증
    revalidatePath("/", "layout");

    // 5. 태그 기준, 데이터 캐시 재검증
    revalidateTag(`review-${bookId}`);

클라이언트 컴포넌트에서의 서버 액션

React 19의 기능인 useActionState를 활용하자.

export default function ReviewEditor({ bookId }: { bookId: string }) {
  const [state, formAction, isPending] = useActionState(
    createReviewAction,
    null
  );

 

createReviewAction 함수의 타입도 수정해주자 (첫 번째 매개변수로 컴포넌트의 스테이트까지 함께 받아오게 된다)

export async function createReviewAction(_: any, formData: FormData) {

사용자 경험을 좋게 하기 위해 클라이언트 컴포넌트로 폼 태그를 만드는 거 추천 (isPending 사용해야지)


2. Parallel route (병렬 라우트)

하나의 화면 안에 여러 페이지(page.tsx)를 병렬로 렌더링 시켜주는 패턴

→ 소셜미디어 서비스나 관리자의 대시보드 페이지처럼 엄청나게 복잡한 구조를 갖는 UI에 유용하게 활용이 된다.

 

Slot(슬롯): 병렬로 렌더링될 페이지 컴포넌트를 보관하는 폴더 (앞에 @를 붙인다)

parallel 폴더 안에 layout.tsx와 @sidebar/page.tsx가 있다면, @sidebar/page.tsx는 layout.tsx에게 props로써 자동으로 전달이 된다. (이 때 props의 이름은, 슬롯의 이름인 sidebar, 타입은 ReactNode)

 

참고1: Slot(슬롯)은 URL 경로에는 아무런 영향도 미치지 않음

참고2: Slot은 개수 제한이 없다.

 

가끔 Parallel route를 사용하면 next.js에서 에러가 발생하는데, .next 폴더를 제거하고 npm run dev로 다시 가동을 해보자

 

특정 슬롯 밑에서 추가적인 경로의 페이지를 생성하고 브라우저에서 해당 경로로 링크 컴포넌트 등을 이용해서 이동해보면 해당 슬롯의 페이지만 업데이트가 되고, 나머지 슬롯의 페이지들은 그대로 이전의 상태를 유지한다.

(슬롯 안에 default.tsx를 만들면 에러 상황에 대처할 수 있다)


Intercepting Route (인터셉팅 라우트)

사용자가 특정 경로로 접속해서 새로운 페이지를 요청할 때 이 요청을 가로채서 원래 렌더링되야되는 페이지가 아닌, 우리가 원하는 어떠한 페이지를 대신 렌더링하도록 설정하는 라우팅 패턴

→ 사용자가 동일한 경로로 접속하게 되더라도 특정 조건을 만족하게 되면 다른 페이지를 렌더링

→ 여기서 특정 조건: 초기 접속

→ 링크를 클릭한다거나, router.push 같은 client side rendering 방식으로 페이지가 이동할 때에만 인터셉팅이 일어난다. (새로고침을 하면 발생x)

 

만드는 방법: 동일한 이름의 폴더를 만드는데, 이름 앞에 (.)를 붙인다. (두 단계 위에 있다면 점을 두개 찍는다)

참고: Intercepting Route로 특정 페이지를 가로채 모달 슬롯에 띄우고, Parallel Route로 배경 페이지(기존 화면)를 함께 유지하여 자연스러운 UI를 만들 수 있다.


3. 최적화

이미지 최적화

웹페이지에서 가장 많은 용량을 차지하는 요소는 이미지다.(58%)

다양한 이미지 최적화 기법들

  • webp, AVIF 등의 차세대 형식으로 변환하기
  • 디바이스 사이즈에 맞는 이미지 불러오기
  • lazy loading 적용하기
  • blur image 활용
  • 기타 등등…

→ Next.js에서는 Image 컴포넌트를 활용하면 자동으로 적용이 된다!

import Image from "next/image";

<Image src={coverImgUrl} width={80} height={105} alt={`도서 ${title}의 표지 이미지`}

 

외부 주소로 이루어진 이미지를 불러오고 싶다면 next.config.js(mjs)를 수정해야한다.

images: {
	domains: [도메인 입력],
},

검색 엔진 최적화(SEO)

메타 데이터 설정하기 (페이지별로 동적으로)

page.tsx에 다음과 같은 코드를 넣자

export const metadata: Metadata = {
	title: "제목",
	description: "설명",
	openGraph: {
		title: "제목",
		description: "설정",
		images: ["/thumbnail.png"], // /로 시작하면 public 바로 아래를 가리킨다.
	},

동적인 값을 메타데이터를 설정하고 싶으면 generateMetadata 함수를 생성하자

저작자표시 비영리 변경금지 (새창열림)

'Frontend' 카테고리의 다른 글

딥링크를 활용하여 앱 설치 유무를 인식하는 앱 배너 구현하기  (0) 2025.11.08
모노레포 'common' 프로젝트의 이전 코드가 반영되는 오류 수정 후기  (0) 2025.10.18
[Next.js 강의 정리] App Router에 관하여  (0) 2025.06.06
[Next.js 강의 정리] Next.js와 Page Router에 관하여  (0) 2025.05.25
CORS 에러는 프론트가 해결해야하는가? (어떤 트윗을 보고)  (6) 2025.02.19
'Frontend' 카테고리의 다른 글
  • 딥링크를 활용하여 앱 설치 유무를 인식하는 앱 배너 구현하기
  • 모노레포 'common' 프로젝트의 이전 코드가 반영되는 오류 수정 후기
  • [Next.js 강의 정리] App Router에 관하여
  • [Next.js 강의 정리] Next.js와 Page Router에 관하여
퀵차분
퀵차분
Web Developer 🥐
  • 퀵차분
    QC's Devlog
    퀵차분
  • 전체
    오늘
    어제
    • 분류 전체보기 (178)
      • Frontend (31)
      • Fedify (4)
      • Study (42)
        • NestJS (2)
        • Node.js (3)
        • Modern JS Deep Dive (13)
        • SQL (1)
        • Network (1)
        • 프롬프트 엔지니어링 (4)
        • 인공지능 (9)
        • 시스템프로그래밍 (11)
        • 선형대수학 (1)
      • Intern (4)
      • KUIT (21)
      • Algorithm (48)
        • Baekjoon(C++) (26)
        • Programmers(JavaScript) (22)
      • 우아한테크코스(프리코스) (4)
      • Project (10)
        • crohasang_page (3)
        • PROlog (4)
        • Nomadcoder (2)
      • 생각 (4)
      • Event (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    javascript
    react
    알고리즘
    자바스크립트
    오블완
    KUIT
    리액트
    음악추천
    프론트엔드
    티스토리챌린지
    typescript
    next.js
    프로그래머스
    시스템프로그래밍
    fedify
    HTML
    백준
    타입스크립트
    인공지능
    프로그래머스 자바스크립트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
퀵차분
[Next.js 강의 정리] 서버 액션, Parallel Route, 최적화에 관하여
상단으로

티스토리툴바