3. Server Action

서버에서 비동기 코드를 실행할 수 있도록 해주는 기능입니다. 서버 액션을 사용하면, API 엔드포인트를 생성하지 않고도 컴포넌트 내에서 비동기 함수를 직접 정의할 수 있습니다.

3-1. Server Action 정의

함수 안 최상단 use server를 선언하고, async 키워드를 붙이면 서버에서 동작하는 Server Action이 됩니다.

async function UploadPost() {
  'use server'
  //...
}

한 파일 내에 여러 Server Action을 정의하는 경우 파일 최상단에 use server를 한번만 선언하면됩니다.

'use server'

async function UploadPost() {
  //...
}

async function DeletePost() {
  //...
}

<br>

3-2. Server Action 사용

Server Action 사용을 위해 로컬 데이터베이스 사용을 위해 better-sqlite3 라이브러리를 사용하였습니다.

Server Action 함수 생성

"use server";

const sql = require("better-sqlite3");
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";

const db = sql("posts.db");
export const getPosts = async () => {
  await new Promise((res) => setTimeout(res, 2000));
  return db.prepare("SELECT * FROM posts").all();
};

export async function upload(formData: FormData) {
  const title = formData.get("title") as string | null;
  const content = formData.get("content") as string | null;

  let errors = [];

  if (!title || title.trim().length === 0) {
    errors.push("Title is required.");
  }

  if (!content || content.trim().length === 0) {
    errors.push("Content is required.");
  }

  if (errors.length > 0) {
    return { errors };
  }

  const post = {
    title: formData.get("title"),
    content: formData.get("content"),
  };

  await savePost(post);
  revalidatePath("/posts");
  redirect("/posts");
}

export async function savePost(post: {
  title: FormDataEntryValue | null;
  content: FormDataEntryValue | null;
}) {
  db.prepare(
    `
    INSERT INTO posts
      (title, content)
    VALUES (
      @title,
      @content
    )
  `
  ).run(post);
}

Server Action 적용하기

form action를 통해 Server Action를 전달해주어 Server Action를 적용합니다.

💡 from action