로그인 기능을 구현할 때 아래의 조건을 충족시켜야 한다.

1. 이메일, 패스워드 유효성 검사 구현

/src/auth/components/SignInForm.jsx

  // 이메일, 비밀번호 유효성 검사 (컴포넌트 마운트 시 인풋창에 아무것도 써져 있지 않으므로 유효하지 않은 것으로 (false)으로 시작)
  // 유효성 검사 통과 시 유효한 것(true)으로 변경됨
  const [isValidEmail, setIsValidEmail] = useState(false);
  const [isValidPassword, setIsValidPassword] = useState(false);

  // 로그인 버튼 활성/비활성을 위한 state
  // 컴포넌트 마운트 시 처음에는 인풋창에 아무것도 써져 있지 않으므로 true로 시작
  const [isDisabled, setIsDisabled] = useState(true);
  
  // isValidEmail, isValidPassword값이 바뀔때 마다 즉 사용자가 이메일이나 패스워드 지우고 재입력할 때 마다
  // 호출되어 유효성 여부에 따라 버튼을 활성화/비활성화 시켜줌
  useEffect(() => {
    if (isValidEmail && isValidPassword === true) {
      setIsDisabled(false);
    } else {
      setIsDisabled(true);
    }
  }, [isValidEmail, isValidPassword]);

  const emailChangeHandler = (event) => {
    const value = event.target.value;
    setEmail(value);

    if (!value.includes('@')) {
      setIsValidEmail(false);
    } else {
      setIsValidEmail(true);
    }
  };

  const passwordChangeHandler = (event) => {
    const value = event.target.value;
    setPassword(value);

    if (value.length < 8) {
      setIsValidPassword(false);
    } else {
      setIsValidPassword(true);
    }
  };

유효한 이메일과 패스워드인지 판단하기 위한 isValidEmail, isValidPassword state를 만들고 처음 컴포넌트 렌더링 시 아무런 입력 값이 없으므로 기본 값으로 false를 해주었다.

그리고 emailChangeHandler, passwordChangeHandler 함수에서 if문과 else문을 이용해 유효성 통과 조건에 맞지 않으면 isValidEmail, isValidPassword state에 false값을, 통과 조건에 맞다면 true값을 설정하도록 하여

유효한 이메일과 패스워드인지 판단하도록 구현하였다.

 

위의 설명대로 유효성 여부에 따라 isValidEmail과 isValidPassword state값이 true또는 false로 변경 되게 구현 하였으니 이를 이용하여서 사용자가 이메일과 패스워드를 입력할 때마다  또는 지웠다가 재입력할 때마다

로그인 버튼을 활성, 비활성화 해주기 위해서 useEffect를 이용하고 deps배열에 isValidEmail, isValidPassword를 넣었다. useEffect 코드 블럭 내부에 if문으로 isValidEmail과 isValidPassword state값이 true면 isDisabled state 값이 true가 되게, 그 반대면 isDisabled state 값이 false 값이 되게끔 구현하였다. 그리고 로그인 버튼에 아래 코드와 같이 disabled속성에 isDisabled state를 넣어주어서 유효성 여부에 따라 버튼이 비활성/ 활성화 되게 구현하였다.

2. 로그인이 정상적으로 완료 되었을 시 /todo 경로로 이동 구현

/src/api/auth.js

import axios from 'axios';

const config = {
  headers: {
    'Content-Type': 'application/json',
  },
};

export const signUpApi = async (payload) => {
  const res = await axios.post(
    `${process.env.REACT_APP_SERVER_URL}auth/signup`,
    payload,
    config
  );
  return res;
};

export const signInApi = async (payload) => {
  const res = await axios.post(
    `${process.env.REACT_APP_SERVER_URL}auth/signin`,
    payload,
    config
  );
  return res;
};

회원가입, 로그인 api 통신 로직을 모듈로 구현

 

/src/auth/components/SignInForm.jsx

// 로그인 요청을 하고 응답 http상태 코드로 200이 아닌 다른 코드가 오면 로그인 실패 알림창이 나타나게 함
// 로그인 성공 시에는 useNavigate를 사용하여 /todo경로로 이동
// try catch문을 사용하여 예기치 않은 에러 발생 시 예외 처리
const submitHandler = async (event) => {
    event.preventDefault();
    const body = {
      email,
      password,
    };

    try {
      const res = await signInApi(body);
      if (res.status !== 200) {
        alert('로그인이 실패하였습니다.');
        return;
      }
      localStorage.setItem('auth', res.data.access_token);
      window.location.replace('/todo');
    } catch (error) {
      alert('에러가 발생하였습니다.');
      console.log(error);
    }
  };

로그인 api로 로그인 요청을 하고 if문을 사용하여 응답 상태 코드로 200이 아닌 다른 코드가 오면 로그인 실패 알림창이 나타나도록 하고 로그인 성공 시에는 window.location.replace('/todo')를 사용하여 /todo 경로로 이동하게 하였다. 또한 try catch문을 사용하여 예기치 못한 에러가 발생했을 시에 예외처리를 해주었다.

3. 로그인 여부에 따라 리다이렉트 구현

/src/auth/components/SignIn.jsx

  // 로컬스토리지에 토큰이 있을 시 /todo 경로로 이동
  const navigate = useNavigate();

  useEffect(() => {
    const hasToken = localStorage.getItem('auth');
    if (hasToken) {
      navigate('/todo');
    }
  }, [navigate]);

useEffect와 if문, useNavigate를 이용하여 컴포넌트가 마운트 될 때 로컬스토리지에 토큰이 있으면 /todo경로로 이동하게 구현하였다.

+ Recent posts