[Project] 토큰을 이용한 로그인 기능 구현

챔수·2023년 7월 11일
0

개발 공부

목록 보기
88/101

회원가입, 로그인 목업 페이지를 만들고 로그인 기능구현을 먼저 시작 하였다. 서버에서 acessTokenrefreshToken이 들어오는것을 확인 했고 이를 이용해 로그인 로직을 작성 했다.

localStorage.ts

로컬 스토리지를 다룰 함수들이 들어있는 파일을 만들었다.

export const setLocalStorage = (key: string, token: string) => {
  localStorage.setItem(key, token);
};

export const deleteLocalstorage = (key: string) => {
  localStorage.removeItem(key);
};

export const getLocalstorage = (key: string) => {
  return localStorage.getItem(key) as string;
};
  • 순서대로 로컬스토리지에 데이터를 저장하는 함수, 삭제하는 함수, 조회하는 함수이다.

loginSlice.ts

로컬스토리지에 토큰이 있는지 유무에 따라 로그인 상태를 관리할 것이기 때문에 리덕스 툴킷을 활용해 state를 관리 해줬다.

import { createSlice } from "@reduxjs/toolkit";
import { getLocalstorage } from "../util/localStorage";

interface LoginState {
  isLogined: boolean;
  acesstoken: undefined | string;
  refreshtoken: undefined | string;
}

interface Action {
  payload: { acessToken: string; refreshToken: string };
}

const refreshToken = getLocalstorage("refreshToken");
const acessToken = getLocalstorage("acessToken");

// 로그인 상태의 초기값을 결정하는 코드
const initialState: LoginState = {
  isLogined: refreshToken && acessToken ? true : false,
  acesstoken: acessToken ? acessToken : undefined,
  refreshtoken: refreshToken ? refreshToken : undefined,
};

export const loginSlice = createSlice({
  name: "checkingLogin",
  initialState,
  
  // 로그인 및 로그아웃을 처리하는 액션
  reducers: {
    login: (state, action: Action) => {
      state.isLogined = true;
      state.acesstoken = action.payload.acessToken;
      state.refreshtoken = action.payload.refreshToken;
    },
    logout: (state) => {
      state.isLogined = false;
      state.acesstoken = undefined;
      state.refreshtoken = undefined;
    },
  },
});

export const { login, logout } = loginSlice.actions;

export default loginSlice;

loginContainer.tsx

로그인을 할 페이지에 서버와 데이터 통신에 대한 로직을 작성 해주었다.

  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

// 유효성 검사를 위한 boolean값
  const [isValid, setIsValid] = useState({
    isEmail: false,
    isPassword: false,
  });
  const dispatch = useDispatch();
  const isLogined = useSelector((state: RootState) => {
    return state.loginSlice.isLogined;
  });
  const navigate = useNavigate();

// loginSlice.ts에서 설정해 놓은것 처럼 서버에서 토큰을 보내주면
// isLogined값이 true로 변하고 로그인에 성공하면 navigate를 이용해 홈으로 보내준다.
  if (isLogined) {
    navigate("/");
  }

handleLogin()

const handleLogin: React.FormEventHandler<HTMLFormElement> = (e) => {
    e.preventDefault();
    axios
    // post 메서드를 이용해 user의 email, password를 보내준다.
      .post("/user/login", {
        userName: email,
        password: password,
      })
  // 서버에서 header로 코튼을 보내줄것이기 때문에 'heaeders.' 로 토큰을 받는다.
      .then((res) => {
        const acessToken: string | undefined = res.headers.authorization;
        const refreshToken: string | undefined = res.headers.refresh;
        const userId = res.data.userId;
      
      // 서버가 토큰을 보내줬다면 타입이 string이 될 것이기 때문에 if문을 사용 해줬다.
        if (typeof acessToken === "string" && typeof refreshToken === "string") {
          // loginSlice.ts에 있는 login()을 이용해 initialState값을 변경 해준다.
          // setLocalStorage를 이용해 로컬스토리지에 토큰과 유저id를 저장 해준다.
          dispatch(login({ acessToken, refreshToken }));
          setLocalStorage("acessToken", acessToken);
          setLocalStorage("refreshToken", refreshToken);
          setLocalStorage(userId, userId);
        } else {
          window.alert("로그인에 실패하였습니다.");
        }
      })
      .catch((err) => {
        const errMessage = (err.response as AxiosResponse<{ message: string }>)?.data.message;
        window.alert(errMessage);
      });
  };
profile
프론트앤드 공부중인 챔수입니다.

0개의 댓글