2025.2.7 금요일의 공부기록
Next.js에서 폼(Form) 제출을 처리하는 최신 방식으로 Server Actions을 활용하면 fetch 없이 서버에서 직접 데이터를 처리할 수 있다.
이 글에서는 Server Actions을 이용한 로그인 폼 처리 실습 코드를 분석하고, 기존 방식과의 차이점을 정리한다.
fetch()
없이 데이터를 변형하거나 서버와 직접 상호작용할 수 있음.🔗 공식 문서:
기존 fetch()
를 사용하던 방식과 달리, Next.js에서는 폼의 action
속성에 서버 액션을 직접 연결하여 데이터를 처리할 수 있다.
fetch
사용)const handleSubmit = async () => {
const response = await fetch("/api/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
};
📌 단점:
fetch()
)을 사용해야 하므로 코드가 길어짐.JSON.stringify()
)이 필요함.Server Actions
활용)Server Actions을 사용하면 API 없이 폼 데이터를 직접 서버에서 처리할 수 있다.
👉 fetch()
없이 바로 서버 함수 실행 가능!
login.tsx
)import FormButton from "@/components/form-btn";
import FormInput from "@/components/form-input";
import SocialLogin from "@/components/social-login";
export default function LogIn() {
// Server Action: Form 데이터 처리
const handleForm = async (formData: FormData) => {
"use server"; // 이 함수는 서버에서 실행됨
console.log(formData.get("email"), formData.get("password"));
console.log("form submitted");
};
return (
<div className="flex flex-col gap-10 py-8 px-6">
<div className="flex flex-col gap-2 *:font-medium">
<h1 className="text-2xl">안녕하세요!</h1>
<h2 className="text-xl">Log in with email and password.</h2>
</div>
{/* Next.js Server Actions 활용 */}
<form action={handleForm} className="flex flex-col gap-3">
<FormInput
name="email"
type="email"
placeholder="Email"
required={true}
errors={[]}
/>
<FormInput
name="password"
type="password"
placeholder="Password"
required={true}
errors={[]}
/>
<FormButton loading={false} text="Log In" />
</form>
<SocialLogin />
</div>
);
}
📌 설명:
handleForm
함수는 "use server";
를 선언하여 서버에서 실행됨.form
의 action
속성에 handleForm
을 직접 연결하여 fetch 없이 서버 액션 실행 가능.formData.get("email")
, formData.get("password")
를 사용해 폼 데이터 추출.방식 | 기존 방식 (fetch) | 최신 방식 (Server Actions) |
---|---|---|
요청 방식 | fetch("/api") 로 요청 | form action={handleForm} 직접 실행 |
API 필요 여부 | 필요 (/api/login.ts ) | 불필요 (서버 액션에서 직접 실행) |
데이터 변환 | JSON.stringify() 필요 | formData.get() 로 바로 사용 가능 |
보안 | API 엔드포인트 노출됨 | 내부적으로 서버에서 실행됨 |
📌 결론:
Server Actions을 사용하면 API 없이도 클라이언트에서 서버로 데이터를 전송할 수 있어 더 깔끔하고 보안성이 높은 코드 작성이 가능하다. 🎯
실제 서비스에서는 입력값 검증 및 응답 처리가 필요하다.
아래 코드에서는 폼 데이터 검증 후 메시지를 반환하는 방식을 추가했다.
"use server";
export async function handleForm(formData: FormData) {
const email = formData.get("email")?.toString();
const password = formData.get("password")?.toString();
if (!email || !password) {
return { success: false, message: "이메일과 비밀번호를 입력하세요." };
}
if (email === "test@example.com" && password === "1234") {
return { success: true, message: "로그인 성공" };
} else {
return { success: false, message: "이메일 또는 비밀번호가 올바르지 않습니다." };
}
}
"use client";
import { useState } from "react";
import { handleForm } from "@/server-actions";
export default function LogIn() {
const [message, setMessage] = useState("");
const handleSubmit = async (formData: FormData) => {
const response = await handleForm(formData);
setMessage(response.message);
};
return (
<div className="flex flex-col gap-10 py-8 px-6">
<form action={handleSubmit} className="flex flex-col gap-3">
<input name="email" type="email" placeholder="Email" className="border p-2" />
<input name="password" type="password" placeholder="Password" className="border p-2" />
<button type="submit" className="bg-blue-500 text-white px-4 py-2 rounded-md">
Log In
</button>
</form>
{message && <p className="text-red-500">{message}</p>}
</div>
);
}
📌 설명:
handleForm(formData)
를 호출하여 서버에서 로그인 검증 실행.setMessage(response.message)
로 상태 업데이트.서버에서 데이터가 변경되면 자동으로 페이지를 리렌더링(Revalidate) 할 수도 있다.
revalidatePath()
)import { revalidatePath } from "next/cache";
export async function handleForm(formData: FormData) {
// 데이터 처리 후 자동으로 페이지 갱신
revalidatePath("/dashboard");
}
📌 설명:
revalidatePath("/dashboard")
를 호출하면 /dashboard
페이지가 자동으로 최신 데이터로 업데이트됨.폼 제출(Form Submission)
데이터 저장 및 수정 (Mutations)
서버 상태 업데이트
API 요청 없이 서버와 상호작용
fetch()
호출 없이, 서버 액션을 함수처럼 호출할 수 있음.Server Actions가 더 간편한 방식이긴 하지만, 다음과 같은 경우에는 여전히 Route Handlers
가 필요하다.
타사 API와 연동할 때
fetch("/api/auth")
를 호출하면, Next.js 서버에서 외부 API(fetch("https://external.com/auth")
)를 호출해야 할 때.파일 업로드 및 대용량 데이터 처리
완전한 REST API를 제공해야 할 때
방법 | 사용 예시 | 추천 상황 |
---|---|---|
Server Actions ("use server"; ) | await loginUser() | API 없이 서버 코드를 직접 실행할 때 |
Route Handlers (api/route.ts ) | fetch("/api/users") | REST API가 필요할 때, 타사 API 연동 시 |
✅ 기능 | 🛠 설명 |
---|---|
서버 액션 실행 | action={handleForm} 사용하여 직접 서버 함수 실행 |
API 없이 서버 함수 호출 | fetch("/api") 없이 직접 실행 가능 |
데이터 변경 후 자동 갱신 | revalidatePath("/users") 사용 |
서버에서 폼 제출 처리 | <form action={handleForm}> |
fetch()
없이 서버와 직접 통신 가능 ✅ Next.js Server Actions을 활용하여 더 깔끔하고 효율적인 로그인 시스템을 만들어보자! 🚀
자세한 내용은 Next.js 공식 문서를 참고하자.