데브코스 1차 프로젝트에서 사용자 인증을 jwt 토큰을 사용하면서 헤더에 토큰을 적용해야 했다. 처음에 매번 통신 때 마다 토큰 유무를 확인하고 헤더에 넣는 작업을 해야하나 생각했지만 뭔가 비효율 적이라 생각하고 있었다.
팀원 한 분이 axios의 interceptor 기능 정보를 공유해주셨고 사용자 인증에 사용할 수 있다고 하셨다. 기능을 좀 살펴보니 헤더에 jwt 토큰을 넣는 작업을 위한 알맞춤 기능이였다.
http 요청 전에 항상 jwt 토큰 유무를 확인하고 관리하면 한 곳에서 이 로직을 관리함으로 재사용성과 유지보수에도 매우 좋을 것 같았고 흥미가 생겨 포스팅까지 작성하게 되었다.
Axios Interceptor는 요청이나 응답을 서버로 보내기 전에 처리할 수 있는 Axios의 기능이다. 요청 인터셉터(Request Interceptor), 응답 인터셉터(Response Interceptor) 두 가지로 나뉜다.
요청 인터셉터는 서버로 요청을 보내기 전에 항상 요청을 가로채서 특별한 로직을 수행하는데 사용된다.
우선 나는 토큰을 세션 스토리지로 클라이언트에서 관리했다. 보안 문제로 좋은 방법은 아니지만 고정된 openAPI와 refresh의 존재도 없어서 사용자 경험을 더 생각해보자는 의견으로 세션 스토리지를 통해 로그인을 유지했다.
axiosAuthInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
const accessToken = JSON.parse(
sessionStorage.getItem(AUTH_TOKEN_KEY) || '',
);
if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
},
(error) => {
console.error(error);
return Promise.reject(error);
},
);
2개의 인수를 받는다. 첫 번째 인수는 요청에 성공하고 요청에 대한 설정 정보 config 객체를 가지고 동작하는 콜백함수다.
config 객체에는 url, method, headers, params, data 등 다양한 프로퍼티가 있지만 현재 내가 원하는 프로퍼티는 headers 프로퍼티다.
매 요청마다 세션 스토리지를 통해 토큰 값을 조회하고 토큰이 있다면 헤더에 담는 콜백 로직이다. 인터셉터를 통해 매 axios 요청마다 토큰이 값을 넣을 필요없이 인터셉터에서 관리할 수 있다.
두 번째 인수는 네트워크 에러에 관한 문제가 있다면 발생한다. error 객체 정보를 통해 에러를 처리할 수 있다.
그리고 return Promise.reject(error)를 통해 axios를 사용하는 곳에서 catch문을 통해 에러릴 받아 처리할 수 있다.
응답 인터셉터는 서버로부터 응답을 받은 후에 항상 응답을 가로채서 처리하는데 사용된다.
보통 jwt 토큰이 만료되면 401 에러를 응답 받아 처리하는 작업을 할 수 있는데 이번 프로젝트에서는 API 명서세에 별도의 응답 에러도 없고 refresh 기능도 없어서 사용은 하지 않았다.
추후 jwt 토큰 만료 후 처리를 한다면 유용하게 사용할 수 있을 것 같다.
axios.interceptors.response.use((response) => {
// 응답 데이터를 가로채서 처리
return response;
},
(error) => {
// 응답 에러 처리
if (error.response.status === 401) {
// 예를 들어, 401 Unauthorized 응답이 올 경우 로그아웃 처리
}
return Promise.reject(error);
}
);