기술 (5)
문제해결 (1)
회고 (2)
기타 (1)
[PORKO] 로그인 및 회원가입
기술
2024년 05월 27일
![[PORKO] 로그인 및 회원가입의 썸네일](/_next/image?url=%2Fimages%2Fposts%2F%EA%B8%B0%EC%88%A0%2Fporko-login-signup%2Fthumbnail.png&w=3840&q=75)
여러 서비스들을 사용하다보면 회원가입 시 여러 정보들을 수집하는 경우가 있습니다.
아래 이미지를 통해 쉽게 이해할 수 있습니다.
위와 같은 UI패턴을 구현하기 위해 Funnel
과 Multi-Step-Form
을 학습하며 개발한 경험을 포스팅하고자 합니다.
Funnel
Funnel
은 사용자가 특정 목표에 도달하는 과정에서 거치는 단계들을 의미합니다.
회원가입이나 온보딩 과정에서 사용자가 각 단계를 거치며 이탈하지 않도록 설계하는 것이 핵심입니다.
Funnel의 중요성
각 단계에서 얼마나 많은 사용자가 이탈하는지 분석함으로써, 어느 단계가 문제인지 식별할 수 있습니다. 이탈률이 많은 단계가 있다면 해당 단계를 더 간소화하거나 UX를 개선할 필요가 있습니다. 이를 통해 사용자의 흐름을 분석하고 최적화하여 보다 더 많은 사용자가 회원가입을 완료할 수 있게 합니다.
주의할 점
사용자가 어느 단계에서 무엇을 해야 하는지 명확하게 제시해 주고, 이전 단계로 돌아가는 옵션도 제공해줘야 사용자가 혼란을 느끼지 않고 계속 진행할 수 있습니다.
Multi-Step-Form
Multi-Step-Form
은 하나의 긴 폼을 여러 단계로 나누어 사용자에게 부담을 줄여주는 방식입니다.
회원가입이나 온보딩 과정에서 복잡한 정보를 한 번에 다 입력하게 하는 대신, 몇 가지 중요한 정보만 한 단계씩 입력하게 함으로써 사용자 경험을 개선합니다.
Multi-Step-Form의 중요성
-
이탈률 감소: 긴 폼이 한 번에 보여질 때보다 이탈률이 적어집니다. 각 단계가 짧고 명확하기 때문에, 사용자는 완료할 수 있을 것이라는 자신감을 느끼고 계속 진행하게 됩니다.
-
데이터 수집 전략: 사용자가 중간에 이탈하더라도, 이미 입력한 정보를 저장해 놓으면 다음에 이어서 진행할 수 있게 설계할 수 있습니다.
그렇다면 위의 전략들을 어떻게 코드로 구현해낼 수 있을 지 알아보도록 합시다.
우선 저는 사용자가 회원가입 시 입력해야하는 많은 정보를 수집하고 유효성을 검증하기 위해 react-hook-form
과 zod
라이브러리를 채택했습니다.
기획된 회원가입의 단계는 총 4단계로 이루어져 있습니다.
각 단계에 입력된 정보를 수집하기 위해 SignipFormProvider
컴포넌트를 작성했습니다.
"use client";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import {
SignupInputsValues,
defaultValues,
signupSchema,
} from "../../schema/signupSchema";
import { Form } from "@/components/ui/form";
import { signup } from "@/service/api/auth";
import { useState } from "react";
import { useRouter } from "next/navigation";
import MessagePopup from "@/components/MessagePopup";
const SignUpFormProvider = ({ children }: { children: React.ReactNode }) => {
const form = useForm<SignupInputsValues>({
resolver: zodResolver(signupSchema),
defaultValues,
mode: "all",
});
const router = useRouter();
const [error, setError] = useState<string | undefined>("");
const { handleSubmit } = form;
const onSubmit = handleSubmit(async (formValues) => {
setError("");
const result = await signup(formValues);
if (result?.error) {
setError(result.error);
setTimeout(() => setError(""), 2000);
return;
}
router.push("/auth/login");
sessionStorage.removeItem("signup-storage");
});
return (
<Form {...form}>
<form onSubmit={onSubmit} className="px-20">
{children}
<MessagePopup isView={!!error}>{error}</MessagePopup>
</form>
</Form>
);
};
export default SignUpFormProvider;
수집된 정보를 세션 스토리지에 저장하여 브라우저 탭이 닫히지 않는 동안 데이터를 유지하기 위해
zustand
의 persist
를 사용했습니다.
// signup.ts
export const useSignupStore = create<SignupState>()(
persist(
(set) => {
return {
email: "",
checkEmail: false,
password: "",
confirmPassword: "",
name: "",
phoneNumber: "",
roadName: "",
detail: "",
gender: "",
setStorage: (field, value) => set({ [field]: value }),
};
},
{
name: "signup-storage",
storage: createJSONStorage(() => sessionStorage),
}
)
);
회원가입 페이지의 최상단에서 SignupFormProvider
를 사용하여 각 단계에 해당하는 정보를 수집하고, 새로고침을 하더라도 브라우저 탭만 닫지 않는다면 데이터가 유실되지 않도록 회원가입 기능을 구현할 수 있었습니다.
해당 글은 목차가 없습니다.