route handler를 통해 폼 데이터에 있는 이미지를 서버에 추가하는 요청을 처리하였습니다. 근데 server action을 공식문서에서 처음 접하고, 이것으로도 폼 데이터를 처리할 수 있다는 걸 알게되었습니다. 그럼 '폼 데이터를 처리할 때, server action와 route handlers 중 어떤 걸 써야 할까? 어떤 차이가 있을까?' 궁금하게 되어 정리해봤습니다.
nextjs 공식문서에는 server action을 다음과 같이 설명하고 있습니다.
Server Actions are asynchronous functions that are executed on the server. They can be called in Server and Client Components to handle form submissions and data mutations in Next.js applications.
server action은 서버에서 실행되는 비동기 함수입니다. 주로 폼을 제출하고 데이터를 변경하는데(mutation) 사용되고, 서버 컴포넌트와 클라이언트 컴포넌트에서 호출할 수 있습니다.
<form>
, 이벤트 핸들러, useEffect, third-party library, button 같은 폼 요소에서 사용 가능합니다.서버 컴포넌트
server action 함수 내부 최상단에 'use server'
를 선언해줍니다.
export default function Page() {
// Server Action
async function create() {
'use server'
// 데이터 변조
}
return '...'
}
클라이언트 컴포넌트
server action을 둘 파일을 새로 생성하고, 그 파일 맨 위에 'use server'
를 추가해주세요.
// app/actions
'use server'
export async function create() {}
// 클라이언트 컴폰넌트
'use client'
import { create } from '@/app/actions'
export function Button() {
return <Button onClick={create} />
}
Route Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.
route handlers로 라우트에 대한 요청 핸들러를 만들수 있습니다. 단, app router 환경에서만 사용 가능합니다.
app 내에 폴더를 만들고 해당 폴더에 route.js 또는 route.ts 파일을 만들어두면 됩니다. 그럼 /api
경로로 요청하면 app/api/route.ts
에 선언된 handler가 처리해줍니다.
// app/api/hello/route.ts
export async function GET() {
return new Response('Hello, Next.js!', { status: 200 })
}
저는 주로 서버 컴포넌트일 경우 data fetching으로, 클라이언트 컴포넌트일 경우 useEffect을 이용하여 요청합니다.
// 서버 컴포넌트일 경우
export async function ServerComponent() {
const response = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/api/hello`)
const data = await response.json()
// ...
}
// 클라이언트 컴포넌트일 경우
export function ClientComponent() {
const [data, setData] = useState('')
useEffect(() => {
fetch(`${process.env.NEXT_PUBLIC_APP_URL}/api/hello`)
.then(res => res.json())
.then(result => setData(result))
}, [])
// ...
}
HTML 요소를 캡쳐한 이미지를 생성하는 요청을 route handlers 방법으로도 만들어보고, server action으로도 만들어봤습니다.
직접 비교한 결과, server action을 사용하기로 결정했습니다.
이미지 파일이 포함된 FormData를 서버에 추가하는 단순한 요청이므로 server action로 선택했습니다.
route handlers를 선택하지 않은 이유는 다음과 같습니다.