세상세상 놀라온 정말 간단한 Axios GET/PUT/DELTE/PATCH 이런 기능만 쓰다가 면접에서 딱 "Interceptor" 설명해주세요. 하는 순간
아..........
그래요.. 나는 길에 굴러다니는 말도 못하는 감자입니다. 읍.ㅇ.ㅡㅂ....
인터셉터
공식 문서 : then 또는 catch 로 처리되기 전에 요청과 응답을 가로챌 수 있다.
공식 문서에서는 단어 뜻 그대로 서버로부터 데이터를 받아오거나 에러로 분기 되기 전에 중간에서 훽! 가로채는 녀석이란다.
서버랑 통신하기 전에 잠깐 기다렸다가 이것 좀 하고 가!!!! 이런 녀석이랄까...?
//요청
axios.interceptors.request.use(function () {
// 요청이 전달 되기 전에 작업 수행
return config;
}, function (Err) {
// 요청 오류가 있는 작업 수행
return Promise.reject(error);
})
//응답
axios.interceptios.response.use((function (response) {
// 응답 데이터가 있는 작업 수행
return response;
}, function (error){
// 응답 오류가 있는 작업 수행
return Promise.reject(error);
})
아니 세상에나 그래서 이걸 어케 사용하는 겨...? 실제 코드에 적용해볼까..
Axios A.K.A : 인터셉터 - Interceptors 실제 코드에 적용해보기
가장 많이 사용하는 예시가 서버와 통신을 하던 중 "토큰" 만료로 서버한테 401 에러 뽝! 반환 받아버린 경우!
이때 토큰을 다시 갱신해주고 원래 하려던 요청을 다시 요청해야 하는 과정을 요 Axios 인터셉터를 적용해서 " 중복 코드를 제거 " 하고 " 유지보수성을 향상 " 할 수 있다는 장점을 얻을 수 있다.
//util/axios_interceptor.ts
import axios from "axios";
import { rotateRefresh } from "./axiosCall";
const instance = axios.create({
baseURL : process.env.NEXT_PUBLIC_BASE_URL,
});
instance.interceptors.request.use((config) => {
config.withCredentials = true;
return config;
}, (error) => {
console.log(error);
return Promise.reject(error);
});
instance.interceptors.response.use((response) => {
return response;
}, async (error) => {
if(error.response?.status === 401 && error.response.data.message === "기한이 만료된 AccessToken입니다."){
//token문제 - 기한이 만료된 accesstoken
await rotateRefresh();
//중단된 요청 새로운 토큰으로 재전송
const originalResponse = await axios.request(error.config);
return originalResponse;
}if(error.response?.status === 401 && error.response.data.message === "기한이 만료된 RefreshToken입니다."){
// recoil 별도의 설정을 위해 코드를 어떻게 수정해야 할까요.
throw new Error("RefreshTokenExpired")
}if(error.response?.status === 403 && error.response.data.message === "로그인 후 이용할 수 있습니다."){
throw new Error("RefreshTokenExpired")
}
return Promise.reject(error);
});
export default instance;
추가 설명 ::
나는 서버에서 바로 쿠키에 토큰을 넣어버리고 클라이언트 쪽에서는 건들지 못하는 " httpOnly" 설정이라서... 요청할 때 별도의 설정은 필요하지 않았다. 그리고 서버에서 토큰이 필요하지 않는 곳에는 유효하지 않은 토큰이어도 반응하지 않도록 해놔서 모든 요청에 쿠키를 넣어주고 있다.
참고로.. 기획 단계에서 에러 헨들러 정의가 명확하지 않아서 각 요청마다 조금.. 엣헴.. RefrshToken 만료에 대한 코드가 다르르.ㅁ....쿨러ㅓ쿠루러ㅓㄱ...ㅜㅠ
rotateRefresh() 함수는 accessToken을 새롭게 업데이트 요청하는 함수.
refreshToken 마저 만료되었을 경우에는 RefreshTokenExpired 메세지를 캐치해서 로그인 안내 모달을 뛰우고 있다.
import instance from "@/util/axios_interceptor";
const getList = async () => {
try {
const listData = await instance.get("/api/chat-rooms/me");
if(listData.status === 200){
setChatList(listData.data.result);
}
} catch (err) {
const error = err as AxiosError; // 타입 단언 사용
if(error.message === "RefreshTokenExpired"){
setOpenTokenModal({ tokenExpired: true }); //전역에서 로그인 안내 모달 관련 recoil 상태 관리
} else {
console.log(`목록 함수 에러 ${error}`)
}
}
}
refreshToken이 완전 만료되서 axios 요청 후 403 응답을 받아서 로그인으로 보내버리는 로직이 구현됨.
나는 기껏 rotateRefresh 함수를 만들어 놓고 죄다 에러 헨들러로 요청 마다 추가하고 붙여넣고 했다. 이 무슨 창조 경제란 말인가..
이걸 알았다면 아주 똑똑하게 초롱초롱하게 대답했을 텐데 ... 흑흑흑.
총 정리
Axios의 Interceptors를 사용하는 이유
- 서버와의 통신 도중에 어떠한 작업을 해야 할 경우, (Ex. 데이터 조회하다가 토큰 만료 시 재발급 후 데이터를 재 요청)
Axios의 Interceptors를 사용하면 얻게 되는 장점은?
- 중복 코드 제거!
- 한 곳에서 관리하기 때문에 유지보수성 향상 가능!
[ 참고 ]
- axios로 interceptor로 401 처리하기
- Axios Interceptor : 공식 문서
- Axios 인터셉터 적용하기
'Programming > React & TypeScript' 카테고리의 다른 글
[작성 중] useRef에 대한 고찰 (0) | 2023.12.23 |
---|---|
React에서 svg 파일을 함수 컴포넌트화해서 사용하기 (0) | 2023.11.17 |
상태관리 도구들의 차이점 정리 [ Redux / Redux-Toolkit / Recoil ] + Redux 미들웨어들 [Redux-Saga / Redux - Thunk ..etc ] (0) | 2023.09.22 |
[React] 하위 컴포넌트의 트리거로 상위 컴포넌트에서 무한 랜더링 지옥 해결하기 (0) | 2023.09.16 |
[React + TypeScript] reac-icon 의 Type을 활용해서 Props 로 내려주는 방법 (0) | 2023.08.24 |