React 19 Server Actions와 기존 API 라우트 병행 전략

배경

React 19가 정식 출시된 지 반년이 지났다. Server Actions가 안정화되면서 프로덕션 도입을 검토했고, 기존 Next.js API 라우트를 전면 교체하기보다 점진적으로 전환하는 전략을 택했다.

병행 운영 구조

폼 제출과 같은 간단한 mutate 작업부터 Server Actions로 전환했다. 복잡한 비즈니스 로직이나 외부 API 연동은 기존 API 라우트를 유지했다.

// actions/user.ts
'use server'

export async function updateProfile(formData: FormData) {
  const name = formData.get('name') as string
  
  try {
    await db.user.update({
      where: { id: session.userId },
      data: { name }
    })
    revalidatePath('/profile')
    return { success: true }
  } catch (error) {
    return { success: false, error: 'Update failed' }
  }
}

에러 핸들링 패턴

Server Actions는 try-catch로 에러를 잡아 객체로 반환하는 방식을 택했다. throw하면 클라이언트에서 처리가 복잡해졌다.

// components/ProfileForm.tsx
const [result, formAction] = useActionState(updateProfile, null)

return (
  <form action={formAction}>
    <input name="name" />
    <button type="submit">저장</button>
    {result?.error && <p>{result.error}</p>}
  </form>
)

판단 기준

  • CRUD 작업: Server Actions
  • 결제, 알림 등 외부 연동: API 라우트
  • 모바일 앱 연동: API 라우트 유지

당분간은 두 방식을 병행할 예정이다. Server Actions는 편리하지만, 기존 인프라와의 호환성을 고려하면 완전 전환은 시기상조로 판단했다.