Axios Interceptor를 이용한 Refresh Token 문제 해결

Axios 인터셉터: 여러 요청에 대한 리프레시 토큰 인증이 필요한 API를 사용할 때, 액세스 토큰이 만료된 후에 새로운 액세스 토큰을 얻기 위해 리프레시 토큰이 필요한 경우가 일반적입니다. 이 블로그 포스트에서는 자바스크립트에서 Axios 인터셉터를 구현하여 401 오류 …

title_thumbnail(Axios Interceptor를 이용한 Refresh Token 문제 해결에 대해 여러 요청들에 대해)

Axios 인터셉터: 여러 요청에 대한 리프레시 토큰

인증이 필요한 API를 사용할 때, 액세스 토큰이 만료된 후에 새로운 액세스 토큰을 얻기 위해 리프레시 토큰이 필요한 경우가 일반적입니다. 이 블로그 포스트에서는 자바스크립트에서 Axios 인터셉터를 구현하여 401 오류 응답을 받았을 때 토큰을 자동으로 리프레시하는 방법을 탐색해보겠습니다.

문제 이해하기

API에 요청을 보낼 때 기대한 데이터 대신 401 Unauthorized 오류가 반환되는 경우 문제가 발생합니다. 이는 액세스 토큰이 만료되어 리프레시해야 함을 나타냅니다.

axios.interceptors.response.use(
    response => {
        return response;
    },
    err => {
        return new Promise((resolve, reject) => {
            if (err.response.status === 401 && err.config && !err.config.__isRetryRequest) {
                const originalRequest = err.config;
                this.emit('onAutoLogin', originalRequest);
            }
        });
    }
);

위의 코드 조각은 Axios를 사용하여 응답을 인터셉트하는 방법을 보여줍니다. 401 오류가 발생하고 다시 시도하는 요청이 아닌 경우 ‘onAutoLogin’ 이벤트를 발생시켜 원래 요청을 전달합니다.

해결책 구현하기

토큰 리프레시를 처리하기 위해, 실패한 요청의 큐를 유지하고 리프레시 프로세스를 트리거하는 함수를 만들겠습니다. 다음은 예시 구현입니다:

let isRefreshing = false;
let failedQueue = [];

const processQueue = (error, token = null) => {
    failedQueue.forEach(prom => {
        if (error) {
            prom.reject(error);
        } else {
            prom.resolve(token);
        }
    });

    failedQueue = [];
};

axios.interceptors.response.use(
    response => {
        return response;
    },
    err => {
        const originalRequest = err.config;

        if (err.response.status === 401 && !originalRequest._retry) {
            if (isRefreshing) {
                return new Promise(function(resolve, reject) {
                    failedQueue.push({ resolve, reject });
                })
                    .then(token => {
                        originalRequest.headers['Authorization'] = 'Bearer ' + token;
                        return axios(originalRequest);
                    })
                    .catch(err => {
                        return Promise.reject(err);
                    });
            }

            originalRequest._retry = true;
            isRefreshing = true;

            return new Promise(function(resolve, reject) {
                axios
                    .post('/fooUrl/refreshToken', {
                        refreshToken: "fooToken"
                    })
                    .then(({ data }) => {
                        axios.defaults.headers.common['Authorization'] = 'Bearer ' + data.fooToken;
                        originalRequest.headers['Authorization'] = 'Bearer ' + data.fooToken;
                        processQueue(null, data.fooToken);
                        resolve(axios(originalRequest));
                    })
                    .catch(err => {
                        processQueue(err, null);
                        store.dispatch(showMessage({ message: 'Expired Token' }));
                        reject(err);
                    })
                    .then(() => {
                        isRefreshing = false;
                    });
            });
        }

        return Promise.reject(err);
    }
);

위의 코드 조각은 토큰 리프레싱 메커니즘을 구현하는 방법을 보여줍니다. 토큰 리프레싱 프로세스가 이미 실행 중인지 확인합니다. 실행 중인 경우, 실패한 요청을 큐에 추가하고 토큰이 리프레시된 후에 해결합니다. 리프레싱 프로세스가 실행되지 않는 경우에는 토큰 리프레싱 요청을 만들고 큐에 있는 실패한 요청을 업데이트된 토큰과 함께 다시 처리합니다.

결론

이 블로그 포스트에서는 Axios 인터셉터를 사용하여 여러 요청에 대한 토큰 리프레싱을 처리하는 문제를 해결하는 방법을 탐구했습니다. 401 오류 응답을 인터셉트하여 토큰을 자동으로 리프레시하고 초기 실패한 요청을 다시 시도함으로써 사용자 경험을 원활하게 유지할 수 있습니다.

이 솔루션을 구현함으로써 액세스 토큰이 만료되는 경우에도 원활한 인증을 보장하여 사용자 경험을 최소한으로 방해하지 않습니다.

이 블로그 포스트가 Axios 인터셉터를 사용하여 토큰 리프레싱을 처리하는 방법을 명확하게 이해하도록 도움이 되었기를 바랍니다. 즐거운 코딩하세요!

참고 자료 : 

reactjs

Leave a Comment