image

react-cookie

태그
React
상세설명react-cookie 사용하기
작성일자2024.03.11

쿠키에 토큰(jwt)을 저장하거나 로그인 페이지 구성 시 id같은 사용자 정보를 저장하는 등 react-cookie 라이브러리를 활용하는 경우가 많 react-cookie에 대해 정리해보았다.

cookie?

쿠키는 사용자 웹 사이트 방문 시 생기는 4KB 이하의 작은 파일로 키와 값이 들어있는 데이터 파일 이다. 쿠키는 사용자가 페이지를 얼마나 자주 방문하는지 알려줌으로써, 사용자가 관심을 갖는 정보를 파악할 수 있도록 해주는 역할을 한다. 예를 들어 쇼핑몰 사이트의 장바구니를 상품을 넣고 며칠 후에 방문했을 때, 상품이 그래도 유지되어있는 이유는 쿠키를 활용하기 때문이다.

react-cookie

react-cookie npm

https://www.npmjs.com/package/react-cookie

설치

npm install react-cookie
// or
yarn add react-cookie

기본 사용법

const [cookies, setCookie, removeCookie] = useCookies(['cookie-name']);
  • setCookie : 쿠키에 값 저장 | setCookie(쿠키 이름, 쿠키에 넣을 값, 옵션)
  • removeCookie : 쿠키 삭제 | removeCookie(쿠키 이름, 옵션)
  • ⭐옵션 중 path는 쿠키 경로로 { path: "/" } 설정 시 모든 페이지에서 쿠키에 접근할 수 있다.

    로그인 페이지 id 저장

    react-cookie를 활용하여 사용자의 아이디를 기억 할 수 있게 구성했다.

    계정 정보 저장

    계정 정보 저장하기 <input type="checkbox" / > 를 클릭하면 onChange의 cookie값을 저장하거나 삭제하는 handleChangeRemember 함수가 실행된다.

    const handleChangeRemember = (event: React.ChangeEvent<HTMLInputElement>) => {
        setRememberCheck(event.target.checked);
    
        if (event.target.checked) {
          setCookie("remember_id", getValues("email"), { path: "/" });
        } else {
          removeCookie("remember_id", { path: "/" });
        }
    };

    로그인 페이지 진입 시 쿠키 여부

    만약 remember_id 이름의 쿠키가 존재한다면 <input type="checkbox" / > 의 checked를 true 로 변경하고 id 영역인 email의 값에 remember_id 값을 부여한다.

    useEffect(() => {
        if (cookies.remember_id !== undefined) {
          setRememberCheck(true);
          setValue("email", cookies.remember_id);
        }
     }, []);

    전체 코드

    import { useCookies } from "react-cookie";
    import { useState, useEffect } from "react";
    import { useRouter } from "next/router";
    import { useForm } from "react-hook-form";
    
    export default function Login() {
      const router = useRouter();
      const [theme, setTheme] = useState("theme");
    
      useEffect(() => {
        const theme = localStorage.getItem("theme");
        setTheme(theme);
      }, []);
    
      const [passwordShow, setPasswordShow] = useState(false);
      const handlePasswordShow = () => {
        setPasswordShow((prev) => !prev);
      };
    
      const { register, handleSubmit, setError, watch, getValues, setValue, formState: { errors, isSubmitting }} = useForm<loginFormType>();
    
      // 계정정보 저장
      const [cookies, setCookie, removeCookie] = useCookies(["remember_id"]);
      const [rememberCheck, setRememberCheck] = useState<boolean>(false);
    
      useEffect(() => {
        if (cookies.remember_id !== undefined) {
          setRememberCheck(true);
          setValue("email", cookies.remember_id);
        }
      }, []);
    
      const handleChangeRemember = (event: React.ChangeEvent<HTMLInputElement>) => {
        setRememberCheck(event.target.checked);
    
        if (event.target.checked) {
          setCookie("remember_id", getValues("email"), { path: "/" });
        } else {
          removeCookie("remember_id", { path: "/" });
        }
      };
    
      const onValid = async (data: loginFormType) => {
        const result = await signIn("credentials", {
          redirect: false,
          email: data.email,
          password: data.password,
        });
        if (!result?.error) {
          router.replace("/");
        } else {
          setError("loginError", {
            message: "이메일 주소와 비밀번호를 다시 확인해주세요.",
          });
        }
      };
    
      const themeColor = theme === "light" ? "#121212" : "#dddddd";
    
      return (
        <div css={[loginPage]}>
          <div css={{color: themeColor}}>
            <div className="loginTop">
              <div className="logoArea"></div>
              <p className="loginTilte">
                PoledCS <span>관리자 로그인</span>
              </p>
            </div>
            <form onSubmit={handleSubmit(onValid)} css={loginForm}>
              <div className="input_area">
                <div>
                  <div className="wIcon_area">
                    <div className="left_icon">
                      <FiUser />
                    </div>
                    <input
                      type="text"
                      placeholder="이메일 아이디"
                      css={{
                        backgroundColor: theme === "light" ? "#f6f3f2" : "rgb(35, 47, 69)",
                        color: themeColor,
                        ":autofill": { "-webkit-text-fill-color": `${themeColor} !important`},
                      }}
                      {...register("email", {
                        required: "이메일은 필수 입력입니다.",
                        pattern: {
                          value: /\S+@\S+\.\S+/,
                          message: "이메일 형식에 맞지 않습니다.",
                        },
                      })}
                    />
                  </div>
                  {errors.email && (
                    <span className="errorTxt">{errors.email.message}</span>
                  )}
                </div>
                <div>
                  <div className="wIcon_area">
                    <div className="left_icon">
                      <FiLock />
                    </div>
                    <input
                      type={passwordShow ? "text" : "password"}
                      placeholder="비밀번호"
                      css={{ backgroundColor: theme === "light" ? "#f6f3f2" : "rgb(35, 47, 69)", color: themeColor }}
                      {...register("password", {
                        required: "비밀번호는 필수 입력입니다.",
                        minLength: {
                          value: 4,
                          message: "4자리 이상 비밀번호를 입력하세요.",
                        },
                      })}
                    />
                    <div className="password_icon" onClick={handlePasswordShow}>
                      {passwordShow ? <BsEye /> : <BsEyeSlash />}
                    </div>
                  </div>
                  {errors.password && (
                    <span className="errorTxt">{errors.password.message}</span>
                  )}
                </div>
                <div className="infoConfigArea">
                  <div className="rememberArea">
                    <input
                      type="checkbox"
                      id="rememberId"
                      checked={rememberCheck}
                      onChange={handleChangeRemember}
                      css={{
                        border: theme === "light" ? "1px solid #121212" : "1px solid #dddddd",
                        ":after": { border: theme === "light" ? "1px solid #121212" : "1px solid #dddddd"},
                      }}
                    />
                    <label htmlFor="rememberId">계정정보 저장하기</label>
                  </div>
                </div>
                <p {...register("loginError")}>
                  {errors.loginError && (
                    <span className="errorLogin">{errors.loginError.message}</span>
                  )}
                </p>
              </div>
              <button
                type="submit"
                disabled={isSubmitting}
                css={{ color: theme === "light" ? "#121212" : "#dddddd"}}
              >
                로그인
              </button>
            </form>
          </div>
        </div>
      );
    }
    
    Login.auth = false;

    결과