- Published On
Next.js - Server Actions
Server Actions
Next.js에서 새로 도입된 server actions
은 API 라우트의 대안
으로 제공됩니다.
Server Actions를 사용하면 페이지나 컴포넌트 내부에서 직접 서버 측 코드를 작성할 수 있어, 데이터를 가져오거나 데이터베이스와의 상호작용 같은 서버 측 작업을 보다 쉽게 처리할 수 있습니다.
이는 개발자가 프론트엔드와 백엔드 로직을 하나의 파일 내에서 관리할 수 있게 하여, 파일 구조를 단순화하고 개발 프로세스를 개선합니다.
주요 특징
- 로컬 개발 환경의 개선: 별도의 API 경로를 설정하지 않고도, 페이지 또는 컴포넌트 내에서 직접 데이터베이스 쿼리를 실행할 수 있습니다.
- 백엔드 코드의 재사용성 향상: 컴포넌트나 페이지 간에 쉽게 백엔드 로직을 공유하고 재사용할 수 있습니다.
- 페이지 데이터 요구 사항의 명시적 선언: Server Actions을 통해 페이지가 필요로 하는 데이터와 그 데이터를 가져오는 방법을 명시적으로 선언할 수 있습니다.
- React 18과의 통합:
useFormStatus
와useFormState
와 연계하여 다양한 기능을 활용할 수 있습니다. - 단점:
복잡성 증가
,디버깅의 어려움
,서버 부하 증가
등이 있습니다.
React 18에서 새로 도입된 form 관련 hooks
Server Actions에 대해 설명하기 전에 새로 나온 리액트 훅들에 대해 설명하겠습니다. form
태그의 action
에 콜백 함수를 생성하여 넣으면, props
로 formData
= input
태그의 name
값을 받을 수 있습니다.
export default function Search() {
function search(formData) {
// 'use server'를 입력하지 않으면 클라이언트에서 실행됩니다.
'use server'
const query = formData.get('custom_name')
alert(`You searched for '${query}'`)
}
return (
<form action={search}>
<input name="custom_name" />
<button type="submit">Search</button>
</form>
)
}
useOptimistic
Server Actions에서 mutation을 사용할 때 사용합니다. useOptimistic 훅은 UI를 낙관적으로 업데이트하여 애플리케이션의 반응성을 향상시킵니다. 사용자가 폼 제출 시, 서버 응답을 기다리는 대신 예상되는 결과로 UI가 즉시 업데이트됩니다. "전송 중..." 상태의 메시지가 사용자에게 바로 보여지며, 이후 서버로부터 성공적인 응답을 받으면 해당 상태가 업데이트됩니다.
useFormState
Next.js에서 useFormState를 사용하려면 actions 함수를 따로 빼야 합니다. useFormState는 React의 훅 중 하나이기 때문에 클라이언트 컴포넌트에서 작동합니다.
사용 방법은 useState와 유사합니다.
매개변수 첫 번째 인자로 actions 함수를 넣고, 두 번째 인자로 초기값(보통 null)을 넣습니다. 반환 값의 첫 번째 인자로는 state(actions 함수의 return 값 = 결과 값), 두 번째 인자로는 action(dispatch)가 있습니다.
useTransition
useTransition은 UI를 차단하지 않고 상태를 업데이트할 수 있는 리액트 훅입니다. useFormState, useFormStatus와 조합하여 사용할 수 있습니다. isPending과 startTransition을 반환합니다.
const [isPending, startTransition] = useTransition()
// ...
const onSubmit = (values: z.infer<typeof LoginSchema>) => {
setError('')
setSuccess('')
startTransition(() =>
loginAction(values).then((data:any) => {
setError(data.error)
setSuccess(data.success)
})
)
}
Server Actions 사용 예시
- 서버 액션 함수를 따로 만들어 useFormState에 첫 번째 인자로 넣고, 두 번째 인자로 초기값(보통 null)을 넣습니다.
"use server";
export default async function handleForm(prevState: any, formData: FormData) {
console.log(prevState);
console.log(formData.get("name"), formData.get("password"));
console.log("I run in the server");
return { errors: ["this is just a test message", "test msg is short"] };
}
-
제출 버튼을 클라이언트 컴포넌트로 만듭니다.
-
form에 action, input에 name 속성을 지정해줍니다.
import { useFormStatus } from "react-dom";
import handleForm from '@/app/login/actions';
const Page = () => {
const [state, action] = useFormState(handleForm, null);
return (
<form action={action} className="flex flex-col gap-3">
<div className="flex flex-col gap-3">
<input name="name" type="text" placeholder="user name" required/>
<input name="password" type="password" placeholder="********" required autoComplete='off'/>
<FormButton />
{/* 아래처럼 생긴 버튼을 client component로 생성합니다
// <button type="submit" disabled={pending}>{pending ? "로딩 중..." : "생성하기"}</button>*/}
</div>
</form>
)
}
export default Page;
// console.log(state)
// { errors: ["this is just a test message", "test msg is short"] }
위와 같이 Next.js에서 Server Actions를 활용하여 프론트엔드와 백엔드 로직을 통합하고, React의 새로운 훅들을 사용하여 더욱 효율적인 상태 관리를 할 수 있습니다.
이러한 접근 방식은 개발의 복잡성을 줄이고, 코드의 재사용성을 높이며, 애플리케이션의 반응성을 향상시킬 수 있습니다.
이전 포스트
Next.js로 블로그 제작하기 4다음 포스트
Next.js Image 컴포넌트연관된 포스트 구경가기