본문 바로가기
FrontEnd/Next.js

Form에서 두개 이상의 버튼을 다루기 (feat. server action )

by 위그든씨 2024. 6. 14.

Form 안에 두개 이상의 버튼이 있을 경우 어떤 버튼을 클릭했는지에 따라 행하는 액션이 다를 수 있다.

이 때 button의 name와 value 속성을 이용하면 form의 action에서 버튼의 주체를 파악할 수 있다.

form action에서 넘겨주는 파라미터는 FormData로써 폼 안에 버튼을 클릭하면 해당하는 버튼의 name과 value 정보가 포함되어져 있다.

(이 때 form 안에 input 필드가 있다면 input들의 name과 value들도 출력 됨.)

import { signIn } from '@/auth';

function SignIn() {
    const handleAction = async (data: FormData) => {
        'use server';
        console.log(data);
    };
    return (
        <form className="flex flex-col" action={handleAction}>
            <input
                name="email"
                className="border"
                placeholder="asd"
                type="text"
            />
            <button
                className="bg-blue-400 px-4 py-1"
                name="google"
                type="submit"
                value="google"
            >
                Google
            </button>
            <button
                className="bg-yellow-400 px-4 py-1"
                name="kakaoa"
                type="submit"
                value="kakao"
            >
                kakao
            </button>
        </form>
    );
}

export default SignIn;

input 창에 qweqwe를 입력 후 구글 버튼을 클릭하면 아래와 같이 터미널에 출력됨(server action이므로)

물론 카카오를 출력하면 아래와 같이 출력 됨.

이 같은 결과들은 action을 실행하면 서버단으로 POST 메서드가 요청 되면서 

POST /signIn?email=asdasd&kakaoa=kakao 

와 같이 전송되기 때문이다.

이제 구글 버튼을 클릭하면 구글로 , 카카오 클릭시 카카오로 인가를 요청할려면 

버튼의 주체인 provider를 알기 위해 아래와 같이 코드를 짜준다.

const provider = data.get('google') || data.get('kakaoa');

이제 next-auth의 메서드 signIn에게 해당 provider를 넘겨주면 해당 provider의 로그인 페이지로 이동되면서 성공하면  인가코드를 받아오고 이를 통해 토큰들을 받아오는 oauth가 진행 됨.

const handleAction = async (data: FormData) => {
        'use server';

        const provider = data.get('google') || data.get('kakaoa');
        if (provider) await signIn(provider as string);
};

아래는 전체 코드

import { signIn } from '@/auth';

function SignIn() {
    const handleAction = async (data: FormData) => {
        'use server';

        const provider = data.get('google') || data.get('kakaoa');
        if (provider) await signIn(provider as string);
    };
    return (
        <form className="flex flex-col" action={handleAction}>
            <input
                name="email"
                className="border"
                placeholder="asd"
                type="text"
            />
            <button
                className="bg-blue-400 px-4 py-1"
                name="google"
                type="submit"
                value="google"
            >
                Google
            </button>
            <button
                className="bg-yellow-400 px-4 py-1"
                name="kakaoa"
                type="submit"
                value="kakao"
            >
                kakao
            </button>
        </form>
    );
}

export default SignIn;

참고 문서:

https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations