주요 기능 | 로그인 - itsyuna/Foot-Salon GitHub Wiki

Login

Redux Toolkit을 사용하여 User 상태 관리

Firebase와 연동하여 User 정보 관리

정규 표현식을 활용하여 닉네임/이메일/비밀번호 검증 기능 구현


✔️ 이메일,비밀번호 맞지 않을 시 안내 문구 활성화

✔️ Input 공백 시 / 형식에 맞지 않을 시 안내 문구 활성화


💻 Code

store/user.tsx
const initialUserState = {
  nickname: "",
  email: "",
  uid: "",
  isLoggedIn: false,
};

const userSlice = createSlice({
  name: "user",
  initialState: initialUserState,
  reducers: {
    login(state, action) {
      state.nickname = action.payload.userNickname;
      state.email = action.payload.userEmail;
      state.uid = action.payload.userUid;
      state.isLoggedIn = true;
    },
    logout(state) {
      state.nickname = "";
      state.email = "";
      state.uid = "";
      state.isLoggedIn = false;
    },
  },
});

export const userActions = userSlice.actions;

export default userSlice.reducer;
Login.tsx
const Login = () => {
  const {
    handleSubmit,
    control,
    formState: { errors },
  } = useForm<FormData>();

  const [error, setError] = useState("");

  const navigate = useNavigate();

  const onSubmit = async (data: FormData) => {
    const auth = getAuth();

    try {
      await signInWithEmailAndPassword(auth, data.email, data.password);

      navigate(-1);
    } catch (error) {
      if (error instanceof Error) {
        // 이메일 or 비밀번호가 맞지 않을 시 안내 문구 state 넣어주기
        if (error.message.includes("auth/user-not-found")) {
          setError("존재하지 않는 이메일입니다.");
        } else if (error.message.includes("auth/wrong-password")) {
          setError("비밀번호를 다시 확인해 주세요.");
        } else {
          toast.error("오류가 발생했습니다 :(");
        }
      }
    }
  };
 
  useEffect(() => {
    if (error) {
      setTimeout(() => {
        setError("");
      }, 2000);
    }
  }, [error]);

  return (
    <Card>
        ...
        <form onSubmit={handleSubmit(onSubmit)}>
          ...
          <Controller
            control={control}
            defaultValue=""
            name="password"
            rules={{
              required: "필수 입력 사항입니다.",
              pattern: {
                // 정규표현식을 활용하여 검증
                value: /^(?=.*[a-zA-Z])((?=.*\d)|(?=.*\W)).{8,15}$/,
                message:
                  "8-15자 / 최소 1개의 숫자 혹은 특수문자를 포함했는지 확인해 주세요.",
              },
            }}
            render={({ field }) => (
              <Input
                type="password"
                placeholder="비밀번호를 입력해 주세요."
                value={field.value}
                onChange={field.onChange}
                autoComplete="off"
                width="20vw"
                height="4vh"
                marginTop="1rem"
              />
            )}
          />
          // Input 공백 시/형식에 맞지 않을 시 안내 문구 활성화
          <ErrorText>{errors.password && errors.password.message}</ErrorText>
          // 이메일 or 비밀번호가 맞지 않을 시 안내 문구 활성화
          <ErrorText>{error && error}</ErrorText>        
    ...

🖥 View

로그인 페이지 로그인 페이지
에러 처리

🔻 Input 공백 시
Input 공백 시

🔻 Form 형식에 맞지 않을 시
Form 형식에 맞지 않을 시

🔻 이메일이 맞지 않을 시
이메일이 맞지 않을 시

🔻 비밀번호가 맞지 않을 시
비밀번호가 맞지 않을 시

⚠️ **GitHub.com Fallback** ⚠️