[nextjs] Server Action

DD·2023년 7월 5일
3

프로그래밍 이론

목록 보기
12/12
post-thumbnail

Form 상태 관리, 캐싱, 유효성검사 관련하여 next에서 새롭게 제시하는 solution입니다
Form 데이터로 서버의 데이터를 변경하고, 중간 API 레이어 없이 서버에서 동작하는 함수를 클라이언트에서 직접 실행시킬 수 있습니다
next@13.4.0부터 'beta' 단계가 되었습니다.

How use it

클라이언트에서 서버의 함수를 호출할 수 있는 기능입니다. 해당 함수는 아래 3가지 방법으로 호출할 수 있습니다.

  1. form의 action
  2. formAction
  3. react의 startTansition

1. form의 action 사용하기

import db from './db'
import { redirect } from 'next/navigation'
 
async function create(formData: FormData){
  'use serevr'
  const post = await db.post.insert({
    title: formData.get('title'),
    content: formData.get('content'),
  })
   
  redirect(`/blog/${post.slug}`)
}
 
export default function Page(){
  return (
    <form action={create}>
      <input type="text" name="title" />
      <textarea name="content" />
      <button type="submit">Submit</button>
    </form>
  )
}

2. formAction 사용하기

export default function Page() {
  async function handleSubmit() {
    'use server';
    // ...
  }
  
  async function submitImage() {
    'use server';
    // ...
  }
  
  return (
    <form action={handleSubmit}>
      <input type="text" name="name" />
      <input type="image" formAction={submitImage} />
      <button type="submit">Submit</button>
    </form>
  );
}

3. React의 startTransition 사용하기

client component에서 server action을 호출하는 방법

// app/actions.js
'use server'; // client-component 파일에서 server action 직접 정의할 수 없기 때문에, 따로 파일을 만들어야합니다.
  
export async function addItem(id) {
  await addItemToDb(id);
  revalidatePath(`/product/${id}`);
}
 
// app/components/example-client-component.js
'use client';
  
import { useTransition } from 'react';
import { addItem } from '../actions';
  
function ExampleClientComponent({ id }) {
  let [isPending, startTransition] = useTransition();
  
  return (
    <button onClick={() => startTransition(() => addItem(id))}>
      Add To Cart
    </button>
  );
}

클라이언트에서 서버에 있는 함수를 직접 호출한다고? 이게 어떻게 가능한가!?

  1. next 컴파일 단계에서 use server 지시문이 있는 함수에 대한 고유 라우팅 경로를 할당합니다.
  • 길이가 40인 유니크 문자열 (Ex. 984ed20e3a894190cd12e4db981795e43fe8c042)
  1. 해당 함수를 클라에서 호출하면 헤더에 Next-Action : 고유 라우팅 경로를 담아 POST 요청을 하게 됩니다.
  2. next 서버는 리퀘스트 헤더에 Next-Action 필드가 있으면 미들웨어를 거쳐 해당 server action으로 라우팅을 시도합니다.
  3. 해당 함수를 실행하고 그 리턴값을 response 합니다.
  4. 현재 alpha 단계이기 때문에 구현 방식은 바뀔 수 있습니다.

Pages Router의 pages/api 디렉토리에 있는거랑 뭐가 다른가..?

1. 신기술이라서 간지난다
2. 정의/호출방식이 더 편리함. pages/api 디렉토리 구조에 맞게 경로 작성해서 요청할 필요 없다.
3. 서버 액션, 서버컴포넌트 등의 server only 코드는 클라에 내려주는 JS 번들에 포함되지 않아서, 전체적으로 JS 번들 사이즈가 줄어든다.
4. 사실 확 와닿는 차이는 모르겠다.. 제보 바랍니다.

Config

실험기능이라 아래와 같이 config 파일에 명시해줘야 사용 가능합니다

// next.config.js.
module.exports = {
  experimental: {
    serverActions: true,
  },
};

Creation

server action은 use server 지시문을 통해 생성할 수 있습니다.

user server 지시문을 함수 본문 상단에 작성해서 server action으로 만들 수도 있고, 파일 최상단에 위치시켜 파일에서 내보내는 모든 함수를 server action으로 만들 수도 있습니다.

// async function myAction() {
  'use server';
  // ...
}
 
or
 
// myActions.js
export async function myAction1(){
  'use server`;
  // ..
}
 
export async function myAction2(){
  'use server`;
  // ..
}
 
export async function myAction3(){
  'use server`;
  // ..
}
profile
기억보단 기록을 / TIL 전용 => https://velog.io/@jjuny546

0개의 댓글