로그인에 대해 살펴보기 전에 우선은 기초 지식이 필요함. 아래의 링크 참고.

로그인 자료

토큰 관리 방식

대표적으로 웹 스토리지(로컬 스토리지/세션 스토리지)를 이용하는 방법과 쿠키를 이용하는 방법이 있는데 그 중에서 이번 프로젝트에서는 로컬 스토리지를 이용하는 방법을 선택함

로그인 플로우

Untitled

프로젝트에 적용된 로그인 구조

Untitled

로그인 로직

⚠️ 주의! 여기에 쓰인 코드는 추후에 원작자 맘에 안들면 변경될 수 있음! (이미 최종 프로젝트 Q&A에서 까여서 어차피 고쳐야함 흑흑)

useValidateToken.ts

import { useContext } from 'react';

import { getLocalStorage } from '@/utils';
import { CommonError } from '@/utils/CommonError';
import { API_URL } from '@/constants';

import { AuthContext } from '@/AuthProvider';

export function useValidateToken() {
  const { setIsSignin, setUserName } = useContext(AuthContext);

  const accessToken = getLocalStorage('accessToken');
  const refreshToken = getLocalStorage('refreshToken');

  async function tokenValidator() {
    if (accessToken === null && refreshToken === null) {
      throw new CommonError('토큰이 없습니다.', 401);
    }

    try {
      const response = await fetch(`${API_URL}/auth/access-token/validate`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${accessToken}`,
        },
      });

      const { statusCode, message, data } = await response.json();

      if (!response.ok) {
        throw new CommonError(message, statusCode);
      }

      setIsSignin(true);
      setUserName(data.userName);
    } catch (error) {
      if (error instanceof CommonError) {
        const { statusCode, message } = error;

        if (statusCode === 401) {
          setIsSignin(false);
          localStorage.clear();
          throw new CommonError(message, statusCode);
        } else {
          throw new CommonError(message, statusCode);
        }
      } else {
        throw new Error(String(error));
      }
    }
  }

  return { tokenValidator };
}