Kimsora✨
article thumbnail
320x100
반응형

프로젝트 유지보수 해야지 하다가 한달만에 ....  여러 수많은 에러를 겪었는데 적지 않아 기억이 나지 않는다

 

 

📌기본세팅

<javascript />
const api = axios.create({ baseURL: process.env.REACT_APP_API_URL, headers: { "content-type": "application/json", }, withCredentials: true, });

바로 에러  프로젝트에서 content-type을 두가지 사용해야 되서 두가지 적용을 해야하기 때문에 따로 빼야했다 ㅎㅎ

<javascript />
const instance = axios.create({ baseURL: process.env.REACT_APP_API_URL, withCredentials: true, });

 

 

📌axios.interceptors.request.use를 사용하여 모든 HTTP 요청을 가로채기

<javascript />
instance.interceptors.request.use( async (config) => { if (accessToken && !config.headers["Authorization"]) { if (config.data instanceof FormData) { config.headers["Content-Type"] = "multipart/form-data"; } else { config.headers["Content-Type"] = "application/json"; } config.headers["Authorization"] = `Bearer ${accessToken}`; dispatch( login({ accessToken, memberId, isLogin: true, expire, refreshToken, }) ); } return config; }, (error) => { Promise.reject(error); } );

여기서 config는  매개변수는 HTTP 요청 구성(config) 객체이다

여기에서 content-type을 정해주었다

꼭 리턴해주기 return config 
=>수정된 요청 구성(config) 객체를 반환하여 해당 요청이 수정된 설정으로 실행되도록 하는 역할

 

instanceof는 자바스크립트에서 객체의 타입을 확인하는 연산자=>특정 객체가 특정 클래스의 인스턴스인지 아닌지를 검사하여 불리언 값을 반환한다

<javascript />
object instanceof constructor
object :테스트할 개체.
constructor:테스트할 생성자
 

📌response interceptor에서는 HTTP 응답 객체를 검사하고, 만료된 토큰에 대한 처리를 수행 =>로그인 연장 처리하기

 

현재시간과 로컬스토리지에 저장되어있는 expire시간을 비교해 자동로그인 하는 로직을 추가했다

만약 이 조건이 참이라면, 서버에 새로운 토큰을 요청하여 토큰을 갱신해서 로그인 해야하는데 404에러뜨고 안돼서 

콘솔로 찍으니 새로받은 토큰은 잘들어 왔지만 로그인 연장은 안돼서 한참 헤맸다 🥲

요청 객체의 구성(config)을 수정하지 않기 때문에 원래 요청 객체에 대한 정보가 손실될 가능성이 있다고 한다

<javascript />
instance.interceptors.response.use( function (response) { return response; }, async function (error) { if (isLogin && Date.now() >= expire) { try { const headers = { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, refreshtoken: `Bearer ${refreshToken}`, }; const data = await axios({ url: `${process.env.REACT_APP_API_URL}/api/members/${memberId}`, method: "GET", headers, }); console.log(data.headers); const { refreshtoken: newRefreshToken, authorization } = data.headers; // refreshToken 변수 이름 변경 dispatch( login({ accessToken: authorization, memberId, isLogin: true, expire: Date.now() + 1000 * 60 * 60, refreshToken: newRefreshToken, }) ); return instance.request(error.config); } catch (error) { ..//// } } return Promise.reject(error); } );

 

 

 

수정되지 않은 채로 원래의 요청을 보내게 되기 때문에 새로운 객체를 만들어주고 다시  Axios에 그객체를 넣어주고 리턴 해줘야한다
=> 수정된 newConfig 객체를 사용하여 Axios 요청을 다시 보내야한다

훅으로 만들었기 때문에  return instance해 주어야 한다

=>createAPIWithAuth 함수에서 생성한 인증 정보를 추가한 Axios 인스턴스를 리턴함으로써, 해당 인스턴스를 사용하는 쪽에서 인증 정보가 추가된 Axios 인스턴스를 이용하여 HTTP 요청을 보낼 수 있게 된다

<javascript />
//error.config.headers.Authorization = `Bearer ${authorization}`; // error.config.headers.refreshtoken = `Bearer ${newRefreshToken}`; const newConfig = { ...error.config }; newConfig.headers.Authorization = `Bearer ${authorization}`; newConfig.headers.refreshtoken = `Bearer ${newRefreshToken}`; return await axios(newConfig);

 

<javascript />
instance.interceptors.response.use( function (response) { return response; }, async function (error) { const { config, response } = error; console.log(config); console.log(response); if (isLogin && Date.now() >= expire) { try { const headers = { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, refreshtoken: `Bearer ${refreshToken}`, }; const data = await axios({ url: `${process.env.REACT_APP_API_URL}/api/members/${memberId}`, method: "GET", headers, }); const { refreshtoken: newRefreshToken, authorization } = data.headers; // refreshToken 변수 이름 변경 dispatch( login({ accessToken: authorization, memberId, isLogin: true, expire: Date.now() + 1000 * 60 * 60, refreshToken: newRefreshToken, }) ); const newConfig = { ...error.config }; newConfig.headers.Authorization = `Bearer ${authorization}`; newConfig.headers.refreshtoken = `Bearer ${newRefreshToken}`; return axios(newConfig); } catch (error) { dispatch( logout({ accessToken: null, memberId: null, isLogin: false, refreshToken: refreshToken, }) ); const headers = { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, refreshToken: `Bearer ${refreshToken}`, }; await axios({ url: `${process.env.REACT_APP_API_URL}/api/members/logout`, method: "POST", headers, }); localStorage.clear(); window.location.href = "/login"; window.location.reload(); } } return Promise.reject(error); } ); return instance; };

axios 인스턴스를 만드는 대신에, 기존의 axios 에서 로그아웃 처리를 해주기

=> 새로운 axios 인스턴스를 만드는 오버헤드를 줄이고, 코드의 일관성을 유지할 수 있다

 

 

인터셉터를 사용하면 한결더 간결해지고 한곳에서 에러핸드링하기 좋다

느낀점:어렵다.. 실제적용하기 어렵다 우선은 되는데 제대로 된코드 인지 모르겠다... 간편하라고 만들었는데 일일히 토큰추가 하는게 인터셉터 적용하는것보다 수십배는 빠를것같닿ㅎ

728x90
반응형
profile

Kimsora✨

@sorarar

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그

WH