axios 로그인, 회원가입 - react, next, typescript

hisungmi·2025년 1월 11일

React

목록 보기
3/3
post-thumbnail

auth.ts

1. 모듈 정의 및 의존성

import { AxiosInstance } from 'axios';
import {
  RegisterRequestData,
  LoginRequestData,
  AuthResponseData,
} from '../types/auth';
  • AxiosInstance : HTTP 클라이언트 인스턴스, API 요청을 보낼 때 사용
  • 각 요청 및 응답 데이터의 구조를 타입으로 정의

2. auth 함수

const auth = (api: AxiosInstance) => ({
  register: async (data: RegisterRequestData): Promise<AuthResponseData> => {
    const response = await api.post<AuthResponseData>('/auth/register', data);
    return response.data;
  },
    
  login: async (data: LoginRequestData): Promise<AuthResponseData> => {
    const response = await api.post<AuthResponseData>('/auth/login', data);
    // 로그인 성공시 토큰을 localStorage에 저장
    if (response.data.accessToken) {
      localStorage.setItem('accessToken', response.data.accessToken);
    }
    return response.data;
  },

  logout: async (): Promise<void> => {
    localStorage.removeItem('accessToken');
    await api.post('/auth/logout');
  },
});

export default auth;
  • api라는 AxiosInstance를 인수로 받아 인증 관련 작업을 수행하는 메서드들을 반환하는 함수
register 메서드login 메서드logout 메서드
기능회원가입 요청을 서버로 전송로그인 요청,
성공시 accessTokenlocalStorage에 저장
로그아웃 처리
입력RegisterRequestData 타입 데이터 정보LoginRequestData 타입의 로그인 정보동작 1. localStorage에 서장된 accessToken제거
2. 서버에 로그아웃 요청을 보냄
출력AuthResponseData 타입의 응답 데이터응답 데이터반환값 없음
  • auth(api)와 같이 호출해 인증 모듈을 사용할 수 있다.

index.ts

import axios from 'axios';
import auth from './auth';

1. Axios 인스턴스 생성

export const API = axios.create({
  baseURL: 'http://localhost:8080',
});
  • API는 새 인스턴스
  • 기본 URL 설정 : 모든 요청이 이 URL을 기준으로 전송된다.

💡AxiosInstance

axios.create()는 새로운 axios 인스턴스를 생성하며, 이 인스턴스의 타입이 AxiosInstance 이다.

  • AxiosInstance는 Axios 라이브러리에서 제공되는 타입
  • Axios가 제공하는 모든 HTTP 메서드(get, post, put, delete 등)를 포함

withsCredentials 설정

axios.defaults.withCredentials = true;
  • 쿠키 기반 인증을 사용하는 경우, 브라우저가 요청에 쿠키를 포함하도록 만듬

2. 요청 인터셉터

API.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('accessToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);
  1. localStorage에 저장된 accessToken을 가져옴
  2. 토큰이 존재하면 Authorization 헤더에 Bearer ${token} 형식으로 추가하여 서버에 전달
  3. config를 수정한 후 반환하여 요청 진행
  4. 요청 생성 중 오류 발생 시 이를 거부 (Promise.reject)

3. 응답 인터셉터

API.interceptors.response.use(
  (response) => response,
  async (error) => {
    if (error.response?.status === 401) {
      // 토큰 만료 시 처리
      localStorage.removeItem('accessToken');
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);
  1. 응답이 정상일 경우, 그대로 반환
  2. 에러 응답 발생시, 401(Unauthorized) 확인
    • 토큰 만료되었다고 간주
      • localStorage에서 accessToken제거
      • 사용자를 로그인페이지로 리다이렉트
  3. 에러를 거부하여 호출한 코드에서 추가 처리를 할 수 있게함

4. auth 모듈과 통합

export const AuthAPI = auth(API);
  • 작성한 auth모듈을 Axios 인스턴스 API와 결합하여 AuthAPI를 생성

login, register 적용 예

  1. login
	try {
      const response = await AuthAPI.login({
        user_id: id,
        password: password,
      });

      // 로그인 성공 시 콜백 호출 (사용자 이름 전달)
      onLoginSuccess(response.userId);
    } catch (error: any) {
      if (error.response?.status === 401) {
        setError('아이디 또는 비밀번호가 일치하지 않습니다.');
      } else if (error.response?.status === 404) {
        setError('존재하지 않는 계정입니다.');
      } else {
        setError('로그인에 실패했습니다. 잠시 후 다시 시도해주세요.');
      }
    }
  1. register
	try {
      // RegisterRequestData 형식에 맞게 데이터 정제
      const requestData = {
        user_id: formData.user_id,
        password: formData.password,
      };

      const response = await AuthAPI.register(requestData);
      setShowSuccessModal(true);
    } catch (error: any) {
      alert(
        error.response?.data?.message || '회원가입 중 오류가 발생했습니다.'
      );
profile
난 성미다.

0개의 댓글