Slog
Sign in

React 토큰 자동 갱신 (refreshToken)

2021 Jan 21
3 min read
React 토큰 자동 갱신 (refreshToken)

오늘은 React 에서 refreshToken으로 accessToken을 자동으로 갱신 해주는 방법에 대하여 알아보도록 하겠습니다.

시작하기 앞서

jwt 토큰에 대하여 아직 모르시는 분은 토큰을 사용하여 인증하는 방법 게시글을 보고 오시면 굉장히 도움이 됩니다.

보안을 위하여 accessToken 의 만료시간을 짧게 하고, refreshToken 도 함께 발급하여 accessToken 이 탈취되더라도 금방 만료되게 하여 최대한 안전하게 인증이 가능합니다.

refreshToken 이란 접근에 필요한 accessToken 이 만료 되었을 때 갱신하기 위하여 필요합니다.

오늘은 이 refreshToken 으로 accessToken 을 자동으로 갱신하게 해주도록 하겠습니다.

(accessToken 과 토큰 만료시간은 로컬 스토리지, refreshToken 은 httpOnly cookie 에 저장되어 있다고 가정합니다.)

시작

axios 라는 http 통신 라이브러리에는 interceptor 가 존재합니다. 이는 http 통신을 하기 직전 함수를 실행하여 AxiosRequestConfig 를 수정할 수 있습니다.

개요

axios.interceptors.request.use() 함수에 실행할 함수를 매개변수로 넘기면 정상적으로 interceptor 가 등록됩니다.

// src/lib/refresh.ts

import axios, { AxiosRequestConfig } from "axios";
import Cookie from "js-cookie";
import { RefreshTokenResponse } from "util/types/Response";
import { server } from "config/config.json";
import moment from "moment";

const refresh = async (config: AxiosRequestConfig): Promise<AxiosRequestConfig> => {
  const refreshToken = Cookie.get("refreshToken");
  const expireAt = localStorage.getItem("expiresAt");
  let token = localStorage.getItem("accessToken");

  // 토큰이 만료되었고, refreshToken 이 저장되어 있을 때
  if (moment(expireAt).diff(moment()) < 0 && refreshToken) {
    const body = {
      refreshToken,
    };

    // 토큰 갱신 서버통신
    const { data } = await axios.post(`${server}/auth/token`, body);

    token = data.data.accessToken;
    localStorage.setItem("accessToken", data.data.accessToken);
    localStorage.setItem(
      "expiresAt",
      moment().add(1, "hour").format("yyyy-MM-DD HH:mm:ss")
    );
  }

  config.headers["Authorization"] = `Bearer ${token}`;

  return config;
};

const refreshErrorHandle = (err: any) => {
  Cookie.remove("refreshToken");
};

export { refresh, refreshErrorHandle };
// src/lib/customApi.ts
import axios from "axios";
import { server } from "config/config.json";
import { refresh, refreshErrorHandle } from "./refresh";

const Api = axios.create({
  baseURL: server,
  timeout: 10000,
  params: {},
});

Api.interceptors.request.use(refresh, refreshErrorHandle);

export default Api;

차근차근 코드를 살펴보면 src/lib/refresh.ts 에서는 토큰이 만료되었고, refreshToken 이 저장되어 있다면, 토큰을 갱신하는 api를 호출 후 새로운 accessToken 을 받아옵니다. 그 이후 config header 에 등록하여 정상적으로 인증을 할 수 있도록 합니다.

src/lib/customApi.tsaxios.interceptors.request.use() 로 등록을 하면 전역으로 interceptor 가 등록된 것이 아니기 때문에 axios.create 를 이용하여 전역으로 등록되게 합니다.

마무리

이제 유저 정보를 불러오는 api를 호출 할 때에는

import Api from "lib/customApi.ts";

const getInfo = async (email: string, pw: string) => {
  const { data } = await Api.get("/auth/getInfo");

  return data;
}

이런식으로 사용하시면 됩니다.

그러면 localStorage 에 저장된 토큰 만료시간이 초과 되었고, refreshToken 이 저장되어 있다면, 자동으로 새로운 토큰을 발급 받고 api를 호출하게 됩니다.

마치며

refreshToken 이 어떤식으로 돌아가는지는 이해하였지만 실제 프로젝트에 적용 해본적이 처음이라 axios interceptor 를 이용하여 적용하였는데 굉장히 편리하더라구요.

Explore Popular Contents

0 Comments

Anonymous