
- 프로젝트에서 백엔드에 API 요청을 보낼 때, 토큰을 함께 보내야 했다. (로그인이 필요한 요청)
headers: { Authorization: `Bearer ${token}`, },
- 로그인 시에 저장해 둔 Access Token을 보내야 하는데, 토큰이 만료됐을 때 Refresh Token을 통해 Access Token을 재발급 받는 과정이 필요했다.
만약, Refresh Token 또한 만료가 된 상황 : 로그인 페이지로 이동
then 또는 catch로 처리되기 전, 요청과 응답을 가로챌 수 있다.// 요청 인터셉터 추가
axios.interceptors.request.use(function (config) {
// 요청이 전달되기 전에 작업 수행
return config;
}, function (error) {
// 요청 오류가 있는 작업 수행
return Promise.reject(error);
});
axios.interceptors.request.use(
(config) => {
// 요청 보내기 전 여기에서 처리! 토큰을 localStorage에서 가져온다고 가정
const token = localStorage.getItem("accessToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config; // 수정한 요청을 서버로 보냄
},
(error) => {
// 요청 오류가 발생했을 때,
return Promise.reject(error); // 처리
}
);
// 응답 인터셉터 추가
axios.interceptors.response.use(function (response) {
// 2xx 범위에 있는 상태 코드는 이 함수를 트리거
// 응답 데이터가 있는 작업 수행
return response;
}, function (error) {
// 2xx 외의 범위에 있는 상태 코드는 이 함수를 트리거
// 응답 오류가 있는 작업 수행
return Promise.reject(error);
});
axios.interceptors.response.use(
(response) => {
// 응답 데이터 처리
return response.data; // 필요한 데이터 반환
},
(error) => {
// 응답 오류 발생 시 => status 코드는 백엔드와 소통
if (error.response.status === 401) {
// 인증 오류, 재로그인이 필요한 상황
navigate(); // 필요한 페이지로 이동
}
return Promise.reject(error);
}
);
필요 시 인터셉터를 제거할 수 있다.
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
eject() 메서드를 호출해 특정 인터셉터를 제거할 수 있다.const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});
로그인이 필요하지 않은 요청용 인스턴스
const publicApi = axios.create({
baseURL: "요청 URL",
timeout: 10000, // 10초가 넘었을 때 요청 중단 : 수정 필요
});
로그인이 필요한 요청용 인스턴스
const privateApi = axios.create({
baseURL: "요청 URL",
timeout: 10000, // 10초가 넘었을 때 요청 중단 : 수정 필요
});
로그인이 필요한 요청용 인스턴스 - 요청 인터셉터
// 요청 인터셉터 : 토큰 추가
privateApi.interceptors.request.use(
(config) => {
const token = localStorage.getItem("accessToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
로그인이 필요한 요청용 인스턴스 - 응답 인터셉터
// 응답 인터셉터 : 토큰 만료 시 처리
privateApi.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
// Access Token 만료 시
if (error.response?.status === 401) {
try {
const refreshToken = localStorage.getItem("refreshToken");
if (refreshToken) {
// 백엔드 api로 변경 필요
const { data } = await publicApi.post("/refresh", { refreshToken }); // Refresh Token으로 Access Token 재발급
// 재발급 받은 Access Token 저장
localStorage.setItem("accessToken", data.accessToken);
// 요청 다시 시도
originalRequest.headers.Authorization = `Bearer ${data.accessToken}`;
return privateApi(originalRequest);
}
} catch (refreshError) {
// Refresh Token 만료 시
localStorage.clear(); // 토큰 제거 (로컬)
navigate(); // 필요한 페이지로 이동
}
}
return Promise.reject(error);
}
);
해당 인스턴스를 export해서 API 요청에 사용하면 된다.
로그인이 필요한 API 요청
async function tempApiData() {
try {
const response = await privateApi.get("/temp");
// 헤더는 요청 인터셉터에서 처리됨
console.log('데이터:', response.data);
} catch (error) {
console.error('오류:', error.message);
}
}