안녕하세요 웹 YB 김다현입니다.
4주차 과제를 하면서 axios를 다루게 됐는데 이때 header로 토큰을 받아오는 코드가 중복되더라구요.
중복 코드를 어떻게 해결할지에 대해 찾다가 axios의 interceptor 기능을 알게 되어 이번 아티클에서 다뤄보려고 합니다! (물론 저도 아직 코드에 적용은 안 했지만 사용해서 리팩토링 해보려고 합니다 ㅎㅎ,,,)
Interceptor가 뭐지?
Interceptor는 Axios의 기능 중 하나인데요. Interceptor라는 단어가 생소하게 느껴질 수 있는데 간단히 말하면 중간에 끼어들어서 원하는 작업을 해주는 도우미 라고 생각하면 돼요! 비유를 해보자면,,, 친구가 나한테 전화를 걸었다고 가정했을 때 보통은 곧바로 받겠지만 가끔은 전화를 받기 전 잠깐 무언가를 하고 (메시지로 먼저 확인을 한다던가) 다음 단계로 넘어가길 원할 때가 있죠? Interceptor도 이거랑 비슷하게 요청이 서버로 가기 전이나 응답이 도착한 후에 특정 작업을 수행할 수 있도록 도와주는 역할을 합니다.
요청이나 응답을 가로채서 원하는 로직을 추가할 수 있는 기능
한 줄로 정리해보자면 위와 같아요. 그래서 모든 API 요청에서 공통으로 처리해야 할 작업을 한 번에 쉽게 처리할 수 있답니다!
요청과 응답의 Interceptor
Axios에는 두 가지 종류의 Interceptor가 있는데요!
- Request Interceptor
요청이 서버에 도착하기 전에 실행되는 부분이에요. 주로 인증 토큰을 추가하거나 요청을 로깅할 때 사용합니다. 예를 들자면 로그인 후 발급받은 토큰을 서버에 보낼 때마다 요청 헤더에 추가할 수 있어요.
- Response Interceptor
서버에서 응답이 도착한 후에 실행되는 부분이에요. 주로 에러를 처리하거나 응답 데이터를 가공할 때 사용해요. 서버가 인증 실패 응답을 보내면 로그인 페이지로 자동으로 리다이렉트하거나 데이터를 더 깔끔하게 가공하는 작업을 추가할 수 있습니다!
Interceptor를 왜 사용할까?
1️⃣ 중복 코드를 줄일 수 있다
API 요청마다 반복적으로 수행해야 하는 작업이 있다면 Interceptor를 사용해서 이 작업을 한 곳에 모아둘 수 있어요. 예를 들어 모든 요청에 토큰을 포함해야 한다면 매번 headers에 토큰을 설정하는 코드를 반복적으로 작성하지 않고 Interceptor를 통해 한 번만 설정하면 됩니다. 이렇게 하면 코드가 훨씬 깔끔해지고 유지보수도 쉬워지겠죠?!
apiClient.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
2️⃣ 공통 에러 처리
API 요청을 하다 보면 서버에서 에러 응답이 올 때가 있는데요. 예를 들어 로그인 상태가 만료되어 401 에러가 발생했을 때 로그인 페이지로 보내야 하는 상황이 있을 수 있겠죠? 이런 경우에도 Interceptor를 활용해 모든 요청의 에러 처리를 한 곳에서 할 수 있답니다...! 이렇게 하면 코드가 중복되지 않고 에러 발생 시마다 빠르고 일관되게 대처할 수 있다는 장점이 있어요.
apiClient.interceptors.response.use(
(response) => response,
(error) => {
if (error.response && error.response.status === 401) {
alert('로그인이 필요해요!');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
3️⃣ 응답 데이터를 쉽게 가공 가능
그리고 때로는 서버에서 받은 응답 데이터의 형식을 바꿔서 사용하고 싶을 때도 있을 텐데요. Interceptor을 사용하면 서버 응답 데이터를 공통적으로 가공하여 필요한 형식으로 변경할 수 있습니다. 이렇게 하면 데이터 형식이 달라지더라도 모든 컴포넌트에서 일관된 방식으로 데이터를 사용할 수 있어요!
// 응답 데이터에서 특정 필드만 추출해 사용하기
apiClient.interceptors.response.use((response) => {
return response.data; // 필요에 따라 데이터 가공
});
어떻게 사용할까?
이제 실제 코드에서 어떻게 설정할 수 있는지 알아볼게요. Interceptor를 설정하려면 보통 Axios 인스턴스를 생성하고 여기에 Interceptor를 추가해주는 방식으로 진행하면 됩니다! 한 번 코드로 하나씩 살펴볼게요.
Axios 인스턴스 생성
먼저 Axios 인스턴스를 만들어야 합니다. 인스턴스를 만들면 하나의 설정을 여러 곳에서 재사용할 수 있어서 관리가 편해져요.
baseURL이나 timeout 같은 공통 설정을 인스턴스에 적용하면 모든 API 요청에서 자동으로 반영되니까 확실히 편리해지겠죠?!
import axios from 'axios';
// Axios 인스턴스를 생성
const apiClient = axios.create({
baseURL: 'https://api.example.com', // API 기본 URL
timeout: 5000, // 요청 제한 시간 설정 (5초)
});
Request Interceptor 설정
이제 apiClient 인스턴스에 Interceptor를 추가해볼게요. 우선 Request Interceptor를 설정해야 합니다! 이 Interceptor는 요청이 서버로 보내지기 전에 실행되기 때문에 주로 헤더에 토큰을 추가하는 작업을 할 때 유용해요. 모든 요청에 토큰을 추가하려면 아래와 같이 설정하면 됩니다.
apiClient.interceptors.request.use(
(config) => {
// 로컬 스토리지에서 토큰 가져오기
const token = localStorage.getItem('token');
if (token) {
// 요청 헤더에 토큰 추가
config.headers.Authorization = `Bearer ${token}`;
}
return config; // 설정을 마친 요청을 반환해요.
},
(error) => {
// 요청 중 에러가 발생하면 그대로 에러를 반환
return Promise.reject(error);
}
);
Response Interceptor 설정
이제 Response Interceptor를 설정해볼게요. 이 Interceptor는 서버에서 응답이 도착한 후에 실행되기 때문에 에러 처리나 응답 데이터 가공에 유용하게 사용할 수 있어요. 예를 들어서 서버에서 인증이 만료된 401 에러가 발생하면 로그인 페이지로 이동하는 설정을 할 수 있어요.
apiClient.interceptors.response.use(
(response) => {
return response; // 성공적인 응답은 그대로 반환
},
(error) => {
if (error.response && error.response.status === 401) {
// 인증 오류 시 로그인 페이지로 리다이렉트
alert('로그인이 필요해요!');
window.location.href = '/login';
}
return Promise.reject(error); // 에러는 그대로 반환
}
)
이렇게 하면 401 에러가 발생할 때마다 매번 코드를 작성하지 않아도 모든 요청에서 동일한 방식으로 에러를 처리할 수 있답니다!
응답 데이터 가공하기
마지막으로 Response Interceptor를 활용해 응답 데이터를 가공하는 예제인데요. 서버에서 오는 데이터 형식이 일관되지 않거나 우리가 원하는 형태로 바꿔야 할 때 쓰면 편하겠죠?!
apiClient.interceptors.response.use((response) => {
// 응답 데이터 중 필요한 부분만 반환
return response.data; // response.data만 반환해 컴포넌트에서 깔끔하게 사용
});
Interceptor는 한 번 설정해두면 매번 반복되는 작업을 자동화해줘서 이후에는 훨씬 편하게 코드를 작성할 수 있어요!
그리고 이 자동화를 해두면 더 중요한 로직에 집중할 수 있게 되겠죠?
저도 얼른 4주차 과제 리팩토링 해봐야겠어요,,, 특히 이 과제에 너무 도움이 되는 기능이었던 것 같아서 혹시 안 써본 웨비들이 있다면 이번 과제에 써보는 것도 추천!
'4주차' 카테고리의 다른 글
타입 좁히기 -> 타입 가드에 대해 알아보자! (0) | 2024.11.12 |
---|---|
💥 로딩/에러처리 및 데이터 패칭 라이브러리 (0) | 2024.11.12 |
[React] 타입 단언은 대체 (0) | 2024.11.12 |
Error Boundary로 에러 핸들링하기 (0) | 2024.11.12 |
개발 어떤 방식으로 하세요? _ CDD : 컴포넌트 주도개발 (0) | 2024.11.12 |