Next.js의 Server Action?

하영·2025년 3월 14일
1

Next.js

목록 보기
16/19

📝 Server Action

01. Server Action이란?

Server Action은 서버에서 직접 실행되는 함수로, 기존의 API 라우트 없이 클라이언트와 서버 간 데이터를 처리할 수 있는 새로운 방식이다.

Server Action은 Next.js 14에서 도입된 기능으로, 클라이언트 컴포넌트에서 서버 기능을 쉽게 호출할 수 있도록 설계된 API 이다.

✅ 기존 방식과 Server Action의 차이점

방식설명사용 방식
API Routeapp/api 또는 pages/api 에서 API 엔드포인트를 생성하여 호출fetch(”api/…”) 또는 axios.post(…)
useEffect + fetch클라이언트에서 API를 호출하여 서버에서 데이터를 가져오는 방식useEffect(() => { fetch(...); }, [])
Server ActionAPI 엔드포인트 없이, 함수 호출만으로 서버에서 실행use server 키워드를 사용하여 클라이언트에서 직접 실행

👉 결론: 기존에는 클라이언트에서 fetch()axios를 사용하여 API를 호출해야 했지만, Server Action을 사용하면 클라이언트에서 서버 함수를 직접 호출할 수 있다.


02. Server Action 특징

1. API 엔드포인트 없이 서버에서 실행 가능

  • app/api/… 없어도 서버에서 실행할 함수를 정의할 수 있음
  • use server 키워드를 사용하여 클라이언트에서 직접 서버 함수 호출 가능

2. 클라이언트에서 직접 서버 함수 호출 가능

  • 기존 API 요청처럼 fetch()를 사용하지 않고, 함수를 실행하는 것만으로 서버 로직을 호출할 수 있음

3. 비동기 데이터 처리 최적화

  • fetch() 를 이용한 API 호출보다 불필요한 네트워크 요청을 줄일 수 있음
  • React Suspense와 결합하여 데이터 로딩 최적화 가능

4. 상태 관리 및 폼 처리에 유용

  • 폼 제출 시, API 라우트 없이도 서버에서 데이터 처리 가능
  • useEffect 사용하지 않아도 클라이언트에서 서버 데이터를 조작할 수 있음

03. Server Action 사용법

3-1. 기본 예제

"use server";

export async function submitForm(formData) {
  const { name, email } = formData;
  console.log("서버에서 실행됨:", name, email);

  return { success: true, message: "폼 제출 성공!" };
}
  • use server 를 추가하면 해당 함수는 클라이언트가 직접 실행할 수 없는 서버 함수가 됨
  • 클라이언트에서 이 함수를 fetch() 없이 직접 호출할 수 있음!

3-2. 클라이언트에서 호출하기

"use client";

import { submitForm } from "./actions";

export default function FormComponent() {
  async function handleSubmit(event) {
    event.preventDefault();
    const formData = {
      name: event.target.name.value,
      email: event.target.email.value,
    };
    const response = await submitForm(formData); // ✅ fetch 없이 서버 함수 직접 호출
    console.log(response.message);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" placeholder="이름" />
      <input type="email" name="email" placeholder="이메일" />
      <button type="submit">제출</button>
    </form>
  );
}
  • 기존 fetch('/api/...')를 사용하지 않고, submitForm()을 직접 실행하여 서버 로직을 호출
  • API 라우트 없이, 서버에서 폼 데이터를 처리할 수 있음

3-3. 데이터베이스와 결합한 Server Action 예시

"use server";
import { db } from "@/lib/db"; // 사내 DB 연결

export async function createUser(name, email) {
  await db.user.create({
    data: { name, email },
  });
  return { success: true, message: "사용자 생성 완료!" };
}
  • Server Action 내부에서 직접 데이터베이스 접근 가능
  • API 라우트처럼 공개된 엔드포인트가 없으므로 클라이언트가 직접 접근할 수 없음 (보안이 강화 됨)

04. Server Action 장점과 단점

👍 장점

장점설명
API 라우트 불필요API 엔드포인트를 따로 만들 필요 없이, 클라이언트에서 서버 함수를 직접 호출 가능
불필요한 네트워크 요청 감소fetch() 없이 서버 함수 호풀 가능하여 네트워크 부하 감소됨
보안 강화클라이언트에서 직접 API 요청을 보낼 필요가 없기에, 민감한 데이터 노출 위험이 줄어든다.
데이터베이스 직접 접근 가능API 호출 없이, 서버에서 데이터베이스를 직접 조작 가능
React Suspense와 결합데이터 로딩을 최적화하여 UX 개선 가능

👎 단점

단점설명
브라우저 개발자 도구에서 호출 불가능기존 fetch()처럼 개발자 도구에서 직접 호출하여 디버깅할 수 없음
직접적인 상태 변경 제한클라이언트 상태를 직접 변경할 수 없고, useState와 결합해야 함
제3자 API 호출에는 부적합내부 로직에는 적합하지만, 외부 API를 호출할 때는 fetch()를 사용해야 함

🧐 굳이 server action을 사용하는 이유가 뭘까?

면접질문 대비로 개념 정리를 하다가 문득 든 생각이었다.
간단하게 요약하면 "Server Action는 회사 내에서 만든 자체 API를 사용할 때 fetch를 사용하지 않고도 효율적인 방식으로 가져올 수 있는 것이고, 외부 API를 불러올 때는 기존 방식과 동일하게 fetch 또는 axios 를 사용해야한다." 라는 것이다.

server action이 언제 쓰이는지와 장점이 있는 건 알겠는데 문득 굳이 사용해야하나 하는 생각이 들었다.
개인적으로 느꼈을 때 fetch()를 사용한 로직이 그렇게 번거로운 편이 아니라고 느꼈다.
API 요청 최적화 때문이라면 TanStack Query나 Zustand 같은 라이브러리로 캐싱해도 될 것 같다고 생각했고 무엇보다 디버깅이 안 되는건 치명적인 단점이라고 생각했다.

실제 사용 사례를 정리해보면서 필요성에 대해 이해할 수 있었다.


👩🏻‍💻 Server Action이 필요한 이유

Server Action은 fetch()와 비교했을 때, 단순히 API 호출을 대체하는 기능이 아니다!!!
이 기능이 필요한 이유는 "데이터 처리 방식의 변화" 때문이다.

✏️ 기존 API 요청 방식 (fetch or axios)

async function getUserData(userId) {
  const response = await fetch(`/api/user?userId=${userId}`);
  return await response.json();
}
  • API 라우트(/api/endpoint)를 별도로 생성해야 함
  • 서버에서 데이터를 가져오는 동안, 추가적인 네트워크 요청 비용 발생
  • 캐싱을 위해 TanStack Query, Zustand 등의 라이브러리를 추가로 도입해야 함

✏️ 외부 API 호출 (기존 fetch 또는 axios 필요)

"use server";

export async function getUser(userId) {
  return await db.user.findUnique({ where: { id: userId } });
}
  • fetch() 없이 클라이언트에서 서버 함수를 직접 호출 가능
  • API 엔드포인트가 필요 없음 (/api/... 불필요)
  • 네트워크 요청을 최소화하여 불필요한 API 요청 감소
  • 보안성이 강화됨 (API가 공개되지 않음)

👩🏻‍💻 Server Action 사용 사례

1️⃣ 폼 제출

✅ 기존 방식

async function handleSubmit(event) {
  event.preventDefault();
  const formData = new FormData(event.target);
  await fetch("/api/submit", {
    method: "POST",
    body: formData,
  });
}

✅ Server Action 방식

"use server";

export async function submitForm(formData) {
  await db.user.create({ data: formData });
}
// 클라이언트에서 직접 실행
<form action={submitForm}>
  <input name="name" />
  <button type="submit">제출</button>
</form>

2️⃣ 인증(로그인, 회원가입)

  • Server Action 내부에서 세션, 쿠키를 직접 관리
  • 클라이언트에서 로그인 API 호출 없이 바로 인증 가능

✅ 기존 방식

async function login(email, password) {
  const response = await fetch("/api/login", {
    method: "POST",
    body: JSON.stringify({ email, password }),
  });
}

✅ Server Action 방식

"use server";

export async function login(email, password) {
  const user = await db.user.findUnique({ where: { email, password } });
  if (user) {
    return { success: true, message: "로그인 성공" };
  } else {
    return { success: false, message: "로그인 실패" };
  }
}
// 클라이언트에서 직접 실행
<form action={submitForm}>
  <input name="name" />
  <button type="submit">제출</button>
</form>

3️⃣ 이 외

  1. 이커머스 플랫폼 : 장바구니, 결제 처리 / 사용자 정보 및 주문 정보 저장
  2. 내부 대시보드 : 관리자가 데이터베이스를 조회할 때 API를 거치지 않고 직접 실행함
  3. Saas 제품 : SaaS 제품의 폼 제출, 설정 변경, 사용자 데이터 업데이트 등에 활용가능

📚 참고자료

profile
왕쪼랩 탈출 목표자의 코딩 공부기록

0개의 댓글