[Next.js] 서버 액션

SUN·2025년 1월 9일
0

Next.js - app router

목록 보기
15/21

1. 개요

브라우저에서 호출 할 수 있는 서버에서 실행되는 비동기 함수

서버액션을 활용하면 api를 만들필요없이 함수 하나만으로 브라우저에서 Next 서버측에서 실행되는 함수를 직접 호출할 수 있다.

2. 활용

특정 폼 특정 양식에서 사용

예시

export default function Page() {
    const saveName = async (formData: FormData) => {
        "use server";

		console.log(formData)
        const name = formData.get("name");
        await sql`INSERT INTO Names (name) VALUES (${name})`; //sql문
        await saveDB({ name:name}); // DB에 저장
    }

    return (

        <form action={saveName}>
            <input name="name" placeholder="이름을 입력해주세요" />
            <button type="submit">제출하기</button>
        </form>
    )
}
  1. input에 이름을 적고 제출 버튼을 누르면 form 태그의 action의 saveName 함수가 실행된다.
  2. 함수 내 "use server"가 있으면 서버 액셜으로 설정된다.
  3. input 태그의 값이 formData의 매개변수로 전달이 된다.
  4. save name 함수의 formData에서 값을 꺼내와서 DB에 값을 직접 저장한다거나 sql문에서 활용할 수 있다.

서버에서만 실행되는 함수를 브라우저가 직접 호출하면서 데이터까지 formData로 전달할 수 있게 해주는 기능 - 기존에서 api를 사용했어야했는데 js만으로도 가능해졌다.

사용 이유

api를 사용하려면 경로, 예외처리 등등 손이 많이간다.
단순한 기능을 사용할 때 코드가 간결해진다.
브라우저가 아닌 오직 서버만 실행되어 보안상으로 민감한거나 중요한 데이터를 다룰때 유용

재검증 구현

입력 내용이 화면에 바로 반영되어야 할 경우 보통 input을 통해 데이터를 전달하면 바로 적용이 되지 않고 새로고침을 해야 반영이 된다. 이를 해결하기 위해 재검증 구현이 필요하다.

데이터가 입력이 되면 재랜더링을 통해 재검증이 되어야한다.

  • revaliatePath() 사용하기
import { revalidatePath } from "next/cache";

try {
	...
	revaliatePath('경로') 
}

next 캐시에서 revalidatePath를 불러오고 불러온 경로에 페이지를 인수로 전달한다.
그러면 인수로 전달한 페이지를 재검증한다.

revalidatePath는 next 서버에게 인수로 전달한 경로의 페이지를 다시 생성(재검증)해달라는 메소드

주의점

  1. revalidatePath 메소드는 서버측에서만 호출할 수 있어 서버 컴포넌트에서만 사용이 가능하고 클라이언트 컴포넌트에서는 사용이 불가능하다.
  2. revalidatePath 메소드는 인수로 전달한 경로를 전부 재검증하기 때문에 해당 페이지의 모든 캐시도 무효화한다. force-cache를 설정하더라도 캐시가 다 날라간다.
  3. 데이터 캐시 뿐아니라 페이지를 캐싱하는 풀라우트 캐시도 삭제된다. 다시 풀라우트 캐시를 저장해주지 않는다.

다양한 재검증 방식

  1. 특정 주소에 해당하는 페이지만 재검증
revaliatePath('경로') 
  1. 특정 경로의 모든 동적 페이지를 재검증
revaliatePath("경로/폴더경로", "page") 

폴더경로나 파일의 경로를 명시

  1. 특정 레이아웃을 갖는 모든 페이지 재검증
revaliatePath('/경로', "layout") 

레이아웃을 재검증

  1. 모든 데이터 재검증
revaliatePath('/', "layout") 
  1. 태그기준, 데이터 캐시 재검증
import { revalidateTag } from "next/cache";

revaliateTag('태그명') 

태그 값을 갖는 데이터 캐시 재검증
태그는 데이터 페칭에 적용되는 옵션에 태그를 지정해준다.
지정해준 태그를 활용하여 재검증을 한다.
import 해주어야함

  • 태그 설정

const response = await fetch(
	`api 주소`,
	{ next: { tags : ['태그명']} }
)

태그 방식이 불필요한 캐시를 삭제하지 않고 가능하다.

클라이언트 컴포넌트에서 서버액션

import { useActionState } from "react";

export default funtcion Page () {
	const [state, formAction, isPending] = useActionState(
    	createReviewAction,
    	null
  	);
}

useActionState는 리액트 19 버전에서 출시
폼 태그의 상태를 쉽게 다룰 수 있는 기능이 있다.

  • 기본적으로 2개의 인수를 전달하며 호출
  1. 다룰 form의 액션 함수를 넣어준다.
  2. 두번째 인수는 form 상태의 초기값을 넣어준다. (null 등등)
  • const 배열 형태로 3개의 값을 반환
  1. form의 state값 반환
  2. form의 액션을 의미하는 formAction 반환
  3. 로딩 상태를 의미하는 isPending 반환

그러면 전달받을 form의 액션 값을 formAction으로 설정해 실행시켜주면 useActionState 훅이 인수로 전달한 createReviewAction을 실행. 자동으로 state와 pending 값을 관리

createReviewAction.ts

export default funtcion createReviewAction () {
	if (!bookId || !content || !author) {
    return {
      status: false,
      error: "내용을 입력해주세요",
    };
  }
}

특정 서버액션 조건에서 반환된 값을 사용할 수 있다.

특정 조건으로 action이 실패했다면
status로 액션이 실패했음을 알려주고 error 프로퍼티로 실패 이유를 알려줄 수 있다.

추가로 try catch문에서도 실패 시 반환값을 전달할 수 있다.

<input disabled={isPending}/>

useEffect(() => {
    if (state && !state.status) {
      alert(state.error);
    }
  }, [state]);

위 처럼 input의 제어할 수 있고 아래처럼 state 값으로 상황에 맞는 에러메세지를 추가할 수도 있다.

profile
안녕하세요!

0개의 댓글