dev-guide

React 19 Server Actions 완벽 가이드 — API Route를 대체하는 새로운 표준

React 19에서 도입된 Server Actions의 작동 원리부터 폼 처리, 낙관적 업데이트, 캐시 재검증 전략까지 실무 중심으로 정리하였다.

★★★★★적극 추천
ReactReact19ServerActionsNext.js풀스택
React 19 Server Actions 완벽 가이드 — API Route를 대체하는 새로운 표준
  • ·React 19 공식 릴리스: 2024년 12월
  • ·Server Actions는 'use server' 디렉티브로 선언
  • ·useFormStatus와 useOptimistic 훅이 함께 도입됨
  • ·form의 action 속성에 함수를 직접 전달 가능
기존 프로젝트의 API Route 기반 폼을 Server Actions로 전환하면서 초기에 Date 객체를 그대로 전달해 직렬화 오류가 반복되었다. ISO 문자열로 변환하여 전달하고 서버에서 파싱하는 방식으로 해결하였으며, revalidatePath 호출 위치에 따라 재검증 범위가 달라진다는 점도 실제 운영 중에 파악하였다.

Server Actions란 무엇인가

기존 API Route와의 근본적 차이

React 19 이전에는 서버와의 데이터 통신을 위해 API Route 파일을 별도 생성하고 클라이언트에서 fetch로 호출하는 방식이 표준이었다. 타입 동기화, 엔드포인트 URL 관리, 오류 처리 코드가 서버와 클라이언트 파일에 분산되어 유지보수 부담이 컸으며, 코드베이스가 커질수록 동기화 오류가 누적되었다. Server Actions는 use server 디렉티브 선언만으로 서버 함수를 클라이언트에서 직접 호출하듯 사용할 수 있게 하여 이 복잡성을 근본적으로 제거한다. 별도 엔드포인트 없이 타입 안전한 서버 로직 실행이 가능해져 풀스택 개발 생산성이 크게 향상된다.

// app/actions.ts
'use server'
import { revalidatePath } from 'next/cache'

export async function createPost(formData: FormData) {
  const title = formData.get('title') as string
  await db.posts.create({ data: { title } })
  revalidatePath('/posts')
}

'use server' 디렉티브의 컴파일 원리

Next.js 컴파일러는 use server 함수를 서버 엔드포인트로 자동 변환하고 클라이언트 번들에는 참조값만 남긴다. 클라이언트에서 Server Action을 호출하면 내부적으로 HTTP POST 요청이 발생하지만 개발자에게는 완전히 투명하다. 인자와 반환값은 직렬화 가능한 형태여야 하며, Date 객체나 클래스 인스턴스는 전달 전에 변환이 필요하다. 이 제약은 서버-클라이언트 경계를 명확히 유지하기 위한 의도적 설계로, 직렬화 불가 값을 전달하면 런타임이 아닌 빌드 타임에 오류를 감지할 수 있어 안전하다.

실전 구현 패턴

HTML Form과의 통합

React 19에서는 form의 action 속성에 Server Action 함수를 직접 전달할 수 있도록 확장되었다. JavaScript가 비활성화된 환경에서도 기본 HTTP 동작이 유지되어 점진적 향상을 자동 지원하며, 접근성 측면에서도 유리하다. 폼 데이터는 FormData 객체로 전달되고, 하위 컴포넌트에서 useFormStatus().pending을 구독하면 제출 중 버튼 비활성화와 로딩 UI를 간결하게 구현할 수 있다. 서버에서 유효성 검사 실패를 반환할 때는 구조화된 오류 객체를 반환하고 클라이언트에서 useActionState로 처리하는 패턴이 권장된다.

useOptimistic으로 즉각적 UI 반응 구현

useOptimistic 훅은 Server Action 실행 중 임시 낙관적 상태를 화면에 표시하다가 응답 완료 후 실제 데이터로 자동 교체한다. 요청 실패 시 이전 상태로 자동 롤백되므로 별도 복구 로직이 필요 없다. 좋아요, 북마크, 목록 정렬처럼 즉각 반응이 필요한 인터랙션에 적합하며, 네트워크 지연 환경에서도 체감 성능을 크게 향상시킬 수 있다. useOptimistic(state, updateFn) 형태로 사용하고 현재 낙관적 상태와 업데이트 함수를 반환받아 UI에 반영한다.

재검증과 보안 고려사항

revalidatePath vs revalidateTag 전략

데이터 변경 후에는 Next.js 캐시를 무효화해 최신 상태를 반영해야 한다. revalidatePath는 특정 경로의 모든 캐시를 초기화하는 단순한 방법이지만 범위가 넓다. 보다 정밀한 제어를 위해서는 fetch에 next: { tags: ['posts'] } 옵션으로 태그를 부여하고 변경 시 revalidateTag('posts')를 호출하는 태그 기반 전략이 권장된다. 여러 페이지에서 공유하는 데이터에 태그 전략을 적용하면 불필요한 캐시 초기화를 줄이고 성능을 최적화할 수 있다.

인증·권한 검사 필수 적용

Server Actions는 CSRF 방어가 기본 적용되지만 인증과 권한 검사는 개발자가 직접 구현해야 한다. 각 Action 최상단에서 세션을 검증하고 권한 없는 요청에는 즉시 오류를 반환하는 방어 코드를 빠뜨리면 인증 없이 누구나 서버 함수를 직접 호출할 수 있는 취약점이 생긴다. next-authlucia와 함께 사용할 때는 세션 검증 유틸리티를 분리해 각 Action에서 재사용하는 것이 표준 패턴이며, 민감한 작업에는 역할 기반 접근 제어를 추가하는 것이 좋다.

자주 묻는 질문

Server Actions는 Next.js 없이 사용할 수 있나요?+

Server Actions는 React 19의 기능이지만 서버 실행 환경이 필요합니다. 현재는 Next.js App Router가 가장 완성도 높은 지원을 제공하며, Remix에서도 유사한 개념을 지원합니다.

Server Actions와 tRPC 중 무엇을 선택해야 하나요?+

Next.js 전용 프로젝트에서 뮤테이션이 주목적이라면 Server Actions가 설정 비용이 낮아 유리합니다. 모바일 앱 등 외부 클라이언트가 같은 API를 사용하거나 복잡한 미들웨어가 필요하다면 tRPC나 REST API가 더 적합합니다.