Next.js에서 데이터를 업데이트하는 방법은 React의 서버 함수(Server Functions)를 활용하는 것입니다. 이 문서에서는 서버 함수를 생성하고 호출하는 방법을 안내합니다.
서버 함수(Server Functions)
서버 함수는 서버에서 실행되는 비동기 함수입니다. 서버 함수는 클라이언트에서 네트워크 요청을 통해 호출되므로 본질적으로 비동기입니다. action
의 일부로 호출될 때는 서버 액션(Server Actions)이라고도 부릅니다.
action
은startTransition
에 전달되는 비동기 함수입니다.- 서버 함수는 다음과 같은 경우 자동으로
startTransition
으로 래핑됩니다:<form>
의action
prop에 전달될 때<button>
의formAction
prop에 전달될 때useActionState
에 전달될 때
서버 함수 생성하기
서버 함수는 use server
디렉티브를 비동기 함수 상단에 선언하여 정의할 수 있습니다. 또는 파일 상단에 선언하면 해당 파일 내 모든 export가 서버 함수로 간주됩니다.
export async function createPost(formData: FormData) {
'use server'
const title = formData.get('title')
const content = formData.get('content')
// 데이터 업데이트
// 캐시 재검증
}
export async function deletePost(formData: FormData) {
'use server'
const id = formData.get('id')
// 데이터 업데이트
// 캐시 재검증
}
서버 컴포넌트에서의 서버 함수
서버 컴포넌트 내부에서 아래와 같이 직접 서버 함수를 정의할 수 있습니다:
export default function Page() {
// 서버 액션
async function createPost(formData: FormData) {
'use server'
// ...
}
return <></>
}
클라이언트 컴포넌트에서의 서버 함수 호출
클라이언트 컴포넌트에서는 서버 함수를 직접 정의할 수 없지만, use server
가 선언된 파일에서 import하여 사용할 수 있습니다.
// app/actions.ts
'use server'
export async function createPost() {}
// app/ui/button.tsx
'use client'
import { createPost } from '@/app/actions'
export function Button() {
return <button formAction={createPost}>Create</button>
}
서버 함수 호출 방법
서버 함수는 크게 두 가지 방식으로 호출할 수 있습니다:
- 서버/클라이언트 컴포넌트의 폼(form)
- 클라이언트 컴포넌트의 이벤트 핸들러
폼(form)에서 호출
React는 HTML <form>
요소에 action
prop을 확장하여 서버 함수를 호출할 수 있게 합니다. 이때 함수는 자동으로 FormData
객체를 인자로 받습니다.
import { createPost } from '@/app/actions'
export function Form() {
return (
<form action={createPost}>
<input type="text" name="title" />
<input type="text" name="content" />
<button type="submit">Create</button>
</form>
)
}
'use server'
export async function createPost(formData: FormData) {
const title = formData.get('title')
const content = formData.get('content')
// 데이터 업데이트
// 캐시 재검증
}
참고:
action
prop에 전달된 서버 함수는 _서버 액션(Server Actions)_이라고도 부릅니다.
이벤트 핸들러에서 호출
클라이언트 컴포넌트에서 이벤트 핸들러(예: onClick
)를 통해 서버 함수를 호출할 수 있습니다.
'use client'
import { incrementLike } from './actions'
import { useState } from 'react'
export default function LikeButton({ initialLikes }: { initialLikes: number }) {
const [likes, setLikes] = useState(initialLikes)
return (
<>
<p>Total Likes: {likes}</p>
<button
onClick={async () => {
const updatedLikes = await incrementLike()
setLikes(updatedLikes)
}}
>
Like
</button>
</>
)
}
예시
Pending(로딩) 상태 표시하기
서버 함수 실행 중에는 React의 useActionState
훅을 사용해 로딩 인디케이터를 표시할 수 있습니다. 이 훅은 pending
불리언 값을 반환합니다.
'use client'
import { useActionState } from 'react'
import { createPost } from '@/app/actions'
import { LoadingSpinner } from '@/app/ui/loading-spinner'
export function Button() {
const [state, action, pending] = useActionState(createPost, false)
return (
<button onClick={async () => action()}>
{pending ? <LoadingSpinner /> : 'Create Post'}
</button>
)
}
캐시 재검증하기
업데이트 후, revalidatePath
또는 revalidateTag
를 호출해 Next.js 캐시를 재검증하고 최신 데이터를 표시할 수 있습니다.
import { revalidatePath } from 'next/cache'
export async function createPost(formData: FormData) {
'use server'
// 데이터 업데이트
// ...
revalidatePath('/posts')
}
리다이렉트하기
업데이트 후 사용자를 다른 페이지로 이동시키고 싶다면, 서버 함수 내에서 redirect
를 호출하세요.
'use server'
import { redirect } from 'next/navigation'
export async function createPost(formData: FormData) {
// 데이터 업데이트
// ...
redirect('/posts')
}
API 참고
본 문서는 Next.js 공식 문서 - How to update data에서 번역되었습니다.