카카오 엔터프라이즈 5기 먀옹팀의 프로젝트 PPLOG의 프론트엔드 기본 세팅 과정입니다.
Axios는 브라우저와 Node.js 환경에서 모두 사용할 수 있는 Promise 기반 HTTP 클라이언트 입니다. 주로 REST API와 통신하거나 비동기 요청을 처리하기 위해 사용되며, 쉽게 HTTP 요청을 만들고 관리할 수 있게 도와줍니다.
1. Promise 기반 비동기 요청
- Axios는 Promise 기반으로 동작해
then,catch를 사용해 비동기 요청 결과를 처리합니다. 그리고async/await문법을 사용할 수 있어 비동기 처리 로직을 직관적으로 작성할 수 있습니다.2. 요청 및 응답 인터셉터
- Axios는 인터셉터 기능을 제공하여 HTTP 요청 또는 응답을 가로채고, 추가 로직을 실행할 수 있습니다.
이를 통해 요청 전 헤더에 토큰을 추가하거나, 응답 오류를 일괄적으로 처리하는 등 다양한 전처리 및 후처리 작업을 수행할 수 있습니다.axios.interceptors.request.use(config => { config.headers.Authorization = `Bearer ${token}`; return config; });3. 자동으로 JSON 데이터 처리
- Axios는 요청 본문을 자동으로 JSON 형식으로 변환하여 전송하고, 서버로부터 받은 응답도 자동으로 JSON으로 파싱합니다.
4. 타임아웃 및 취소 기능
- Axios는 요청 타임아웃을 설정할 수 있어, 특정 시간 내에 응답이 오지 않으면 요청을 자동으로 취소합니다.
다음 명령어를 사용해 Axios를 npm install합니다.
npm install axios
아직 실제 api가 없으므로 아래부터 예제 코드로 대체합니다.
1. GET 요청
axios.get('api/get')
.then(response => {
console.log(response.data); // 서버로 부터 받은 데이터
})
.catch(error => {
console.error(error); // 오류 처리
});
2. POST 요청
axios.post('api/post', {
name: '김현중',
major: '컴공',
})
.then(response => {
console.log(response.data); // 서버의 응답 처리
})
.catch(error => {
console.error(error); // 오류 처리
});
3. async/await을 사용한 비동기 처리
async function getData() {
try{
const response = await axios.get('api/get');
console.log(response.data);
} catch (error) {
console.error(error);
}
}
4. 요청에 헤더 추가
axios.get('/api/get', {
headers: {
Authorization: 'Bearer token'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
}));
🤷♂️도대체 왜 브라우저에 내장된 fetch api를 사용하지 않고 Axios를 사용하는지 궁금해하는 저 자신을 위해 Axios와 fetch api의 차이점을 가져왔습니다.
1. JSON 데이터 처리 차이
axios.get('/api/get')
.then(response => {
console.log(response.data); // 자동으로 JSON 파싱
});
response.json()을 호출해 데이터를 파싱합니다.fetch('/api/get')
.then(response => response.json())
.then(data => console.log(data));
2. 요청 및 응답 인터셉터
3. 타임아웃 기능
axios.get('api/get', { timeout: 5000 })
.catch(error => console.log('요청 타임 아웃'));
// AbortController를 사용한 예시
const controller = new AbortController();
const timeoutId = setTimeout(()=> constroller.abort(), 5000);
fetch('/api/get', { signal: controller.signal })
.catch(error => console.log('요청 타임 아웃'));
Axios 인스턴스는 Axios에서 제공하는 기능 중 하나로, 여러 개의 HTTP 요청에서 공통으로 사용되는 설정을 모아 재사용 가능한 인스턴스를 생성하는 방식입니다.
예를 들면 공통 헤더, 베이스 URL, 타임아웃 설정 등을 한 번에 적용할 수 있습니다.
먼저, Axios 인스턴스를 생성하려면 axios.create() 메서드를 사용합니다. 이 메서드는 공통 설정을 포함한 새로운 Axios 인스턴스를 반환합니다.
const config = {
backend: {
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
},
};
const server = config.backend.baseURL;
const axiosInstance: AxiosInstance = axios.create({
baseURL: server, // 기본 URL
timeout: 5000, // 요청 타임아웃 시간 설정 (5초)
withCredentials: true,
headers: {
'Content-Type': 'application/json', // 모든 요청에 적용할 기본 헤더
Authorization: 'Bearer your-token', // 인증 토큰
},
});
Axios 인스턴스를 생성한 후에 axiosInstance를 사용하여 요청을 보낼 수 있습니다.
axiosInstance.get(), axiosInstance.post()등 메서드는 기본 Axios와 같습니다.
axiosInstance.get('/get')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('get 에러 발생', error);
});
axiosInstance.post('/post', {
name: '김현중',
major: '컴공',
})
.then(response => {
console.log('Post 성공: ', response.data);
})
.catch(error => {
console.error('post 에러 발생', error);
});
위 두 예시에서 요청 주소는 process.env.NEXT_PUBLIC_BASE_URL/get과 process.env.NEXT_PUBLIC_BASE_URL/post가 됩니다. 그리고 모든 요청에 미리 정의한 헤더(Content-Type과 Authorization)가 포함됩니다.
Axios 인스턴스를 사용할 때에도 인터셉터를 추가하여 모든 요청이나 응답을 가로채 특정 로직을 실행할 수 있습니다.
axiosInstance.interceptors.request.use(
config => {
// 요청 전에 수행할 작업(동적으로 토큰 추가)
const token = localStorage.getItem('authToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
// 요청 오류 발생 시 처리
return Promise.reject(error);
}
);
axiosInstance.interceptors.response.use(
response => {
// 응답 데이터 가공
return response;
},
error => {
// 오류 응답을 공통으로 처리
if (error.response.status === 401) {
console.error('!인증 오류! 로그인 페이지로 이동합니다');
}
return Promise.reject(error);
}
);
인터셉터를 사용해 모든 요청과 응답에 대한 공통 처리를 구현한 예제입니다. 401 오류 등의 응답이 발생하면 로그인 페이지로 이동하는 로직을 추가할 수 있습니다.
인스턴스와 인터셉터는 Axios 인스턴스 생성 파일에 같이 선언 후 export default를 사용해 내보내기 하면 됩니다.
아래는 인스턴스를 생성하고, 사용하는 예시입니다.
import axios, { AxiosInstance } from 'axios';
const config = {
backend: {
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
},
};
const server = config.backend.baseURL;
// Axios 인스턴스 생성
const axiosInstance: AxiosInstance = axios.create({
baseURL: server,
timeout: 1000,
headers: {
'Content-Type': 'application/json', // JSON 형식으로 통신
},
});
// 요청 인터셉터 추가
axiosInstance.interceptors.request.use(
config => {
const token = localStorage.getItem('authToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`; // 동적으로 인증 토큰 추가
}
return config;
},
error => Promise.reject(error)
);
// 응답 인터셉터 추가
axiosInstance.intercepotrs.response.use(
response => response,
error => {
if (error.response.status === 401) {
// 인증 실패 처리
console.error('!인증 오류! 로그인 페이지로 이동합니다');
}
return Promise.reject(error);
}
);
export default axiosInstance;
import axiosInstance from './axiosInstance';
// 사용자 목록 가져오기
export const fetchUsers = async () => {
try {
const response = await axiosInstance.get('/users');
return response.data;
} catch (error) {
console.error('유저 정보 get 실패: ', error);
throw error;
}
};
// 사용자 생성
export const createUser = async (userData: { name: string; major: string}) => {
try {
const response = await axiosInstance.post('/users', userData);
return response.data;
} catch (error) {
console.error('유저 생성 post 실패: ', error);
throw error;
}
};
import { fetchUsers, createUser } from './api/apiService';
const fetchEntireUsers = async () => {
await fetchUsers();
};
const addUser = async () => {
const newUser = { name: '김현중', major: '컴공' };
await createUser(newUser);
};