Server Action

okkyung·2026년 3월 19일

nextjs

목록 보기
10/13

1. RPC (Remote Procedure Call)

Server Actions의 기반 개념이다. 원격 서버의 함수를 로컬 함수처럼 직접 호출하는 기술로, 복잡한 네트워크 통신 로직을 추상화하여 개발자가 비즈니스 로직에만 집중할 수 있게 한다.

내부적으로는 Stub(클라이언트 대리자)과 Skeleton(서버 수신자) 구조로 동작한다. 클라이언트가 함수를 호출하면 Stub이 데이터를 직렬화(마샬링)하여 서버로 전송하고, 서버의 Skeleton이 이를 역직렬화하여 실제 함수를 실행한 뒤 결과를 반환한다.

  • 장점: 엔드포인트 URL, HTTP 메서드, 상태 코드를 별도로 설계할 필요 없이 함수 호출만으로 서버와 통신한다.
  • 단점: 네트워크 호출을 로컬 함수처럼 추상화하므로, 장애 발생 시 원인 파악이 어렵고 클라이언트-서버 간 결합도가 높아진다.

2. Server Actions

Next.js 15와 React 19가 RPC 개념을 적용해 HTML Form의 단순한 철학을 현대 기술로 구현한 방식이다. 서버에서 실행되는 비동기 함수로, 별도의 API 라우트 없이 폼 제출과 데이터 변경을 처리할 수 있다.

선언 방식

'use server' 지시어를 함수 본문 상단 또는 파일 상단에 선언한다. 파일 상단에 선언하면 해당 파일의 모든 export가 Server Action으로 지정된다. Server Component에서는 인라인으로 선언할 수 있고, Client Component에서는 별도 파일로 분리한 뒤 import하여 사용하거나 props로 전달받아 사용할 수 있다.

동작 방식

빌드 시점에 'use server' 선언을 감지한 빌드 시스템이 해당 함수를 고유 해시 ID를 가진 숨겨진 API 엔드포인트로 자동 변환한다. 폼이 제출되면 React가 브라우저의 기본 POST 요청을 가로채어 내부적으로 fetch를 통해 동일 URL로 POST 요청을 보내되, Next-Action 헤더에 함수 ID를 함께 전송한다. 서버는 이 헤더를 확인하고 매핑된 함수를 실행한 뒤 업데이트된 UI(RSC Payload)를 단일 네트워크 왕복으로 반환한다.

주요 특징

  • <form>action 속성뿐 아니라 이벤트 핸들러, useEffect, 서드파티 라이브러리 등 어디서든 호출할 수 있다.
  • JavaScript가 아직 로드되지 않은 상태에서도 폼 제출이 가능한 점진적 향상(Progressive Enhancement)을 기본 지원한다.
  • Server Action의 인자와 반환값은 React가 직렬화할 수 있는 타입이어야 한다.
  • 액션이 실행되는 페이지 또는 레이아웃의 런타임 환경을 그대로 상속한다.

폼 데이터 처리

<form action={serverAction}> 형태로 연결하면 FormData 객체가 자동으로 전달된다. formData.get('fieldName') 또는 Object.fromEntries(formData.entries())로 값을 추출할 수 있다. 추가 인자가 필요할 때는 .bind(null, extraArg) 패턴을 사용한다.

상태 처리

  • 로딩 상태: useFormStatus 훅의 pending 값으로 제출 중 상태를 감지할 수 있다. 반드시 <form> 의 자식 Client Component에서 사용해야 한다.
  • 에러 처리: try/catch로 에러를 잡아 반환하거나, 가장 가까운 error.js 또는 <Suspense> 바운더리에서 처리한다.
  • 유효성 검사: 기본적인 클라이언트 검증은 HTML의 required, type="email" 등을 활용하고, 서버 측 검증은 Zod 등의 라이브러리를 사용한다. 검증 실패 시 useFormState 훅을 통해 에러 메시지를 UI에 반영할 수 있다.
  • 낙관적 업데이트: useOptimistic 훅을 사용하면 서버 응답을 기다리지 않고 UI를 먼저 업데이트할 수 있다.

캐시 및 리다이렉트

  • revalidatePath('/경로'): 특정 경로의 캐시를 무효화한다.
  • revalidateTag('태그명'): 특정 태그로 지정된 캐시를 무효화한다.
  • redirect('/경로'): 액션 완료 후 다른 경로로 이동한다. 반드시 try/catch 블록 외부에서 호출해야 한다.

쿠키

next/headerscookies() API로 Server Action 내부에서 쿠키를 조회, 설정, 삭제할 수 있다.


3. 보안

인증 및 권한

Server Action은 외부에 공개된 API 엔드포인트와 동일하게 취급해야 한다. 액션 내부에서 반드시 사용자 인증 여부를 확인하고, 권한이 없으면 에러를 던져야 한다.

클로저와 암호화

컴포넌트 내부에 Server Action을 정의하면 클로저를 통해 외부 스코프의 변수에 접근할 수 있다. 이때 캡처된 변수는 클라이언트로 전송되었다가 액션 호출 시 서버로 돌아오는 구조이므로, Next.js는 이를 자동으로 암호화한다. 암호화 키는 빌드마다 새로 생성되며 특정 빌드에서만 액션을 호출할 수 있다. 단, 암호화만으로 민감한 데이터 보호를 완전히 신뢰하기보다는 React의 taint API를 통해 특정 데이터가 클라이언트로 전송되지 않도록 적극적으로 차단하는 것을 권장한다.

CSRF 방어

Server Action은 내부적으로 POST 메서드만 허용하며, Origin 헤더와 Host 헤더를 비교하여 불일치 시 요청을 차단한다. 리버스 프록시나 다중 백엔드 구조를 사용하는 경우 next.config.jsserverActions.allowedOrigins 옵션으로 허용할 출처를 명시적으로 지정해야 한다.


4. API Route vs Server Actions

API Route (route.ts)Server Actions
엔드포인트개발자가 URL과 HTTP Method를 직접 설계프레임워크가 고유 ID로 자동 생성
호출 방식fetch로 URL 문자열 기반 요청서버 함수를 직접 import하여 호출
데이터 변환JSON.stringify / request.json() 수동 처리프레임워크가 직렬화/역직렬화 자동 처리
타입 안전성프론트-백엔드 타입을 별도로 공유해야 함End-to-End 타입 공유, 컴파일 단계에서 오류 감지
캐시 연동데이터 변경 후 프론트엔드 상태를 별도 갱신revalidatePath 호출로 단일 네트워크 왕복 처리

외부 시스템(서드파티, 모바일 클라이언트 등)에 데이터를 제공하는 Open API 형태라면 route.ts가 적합하다. 동일한 웹 앱 내에서 프론트엔드가 백엔드를 호출하는 일반적인 경우라면 Server Actions가 더 나은 개발 경험과 유지보수성을 제공한다.

nextjs#server-action

0개의 댓글