Node.js 18의 fetch API 도입과 마이그레이션
배경
4월에 출시된 Node.js 18에서 fetch API가 실험적 기능으로 추가되었다. 10월 LTS 전환을 앞두고 미리 적용해보기로 했다. 기존에는 axios를 주로 사용했는데, 번들 사이즈도 줄이고 표준 API로 통일할 수 있다는 점이 매력적이었다.
기존 코드
const axios = require('axios');
const fetchUser = async (userId) => {
const { data } = await axios.get(`/api/users/${userId}`);
return data;
};
변경 후
const fetchUser = async (userId) => {
const response = await fetch(`http://localhost:3000/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
};
주요 차이점
1. 에러 핸들링 axios는 4xx, 5xx 응답을 자동으로 reject하지만, fetch는 네트워크 에러만 reject한다. response.ok를 직접 체크해야 했다.
2. baseURL 부재 axios.create()로 baseURL을 설정했던 부분을 환경변수로 처리하거나 wrapper 함수를 만들어야 했다.
const API_BASE = process.env.API_URL || 'http://localhost:3000';
const apiFetch = (path, options) => {
return fetch(`${API_BASE}${path}`, options);
};
3. 요청 인터셉터 incoming/outgoing 요청 수정이 필요한 경우 미들웨어 패턴으로 직접 구현해야 했다.
성능 개선
package.json에서 axios 제거 후:
- node_modules 크기: 약 2.3MB 감소
- 번들 사이즈: 약 13KB 감소
체감상 차이는 크지 않았지만 표준 API 사용으로 인한 호환성 개선이 더 큰 이득이었다.
결론
단순한 HTTP 요청이 대부분이라면 native fetch로 충분했다. 다만 복잡한 인터셉터나 retry 로직이 필요하면 여전히 axios가 유용할 것 같다. 프로젝트 특성에 맞춰 선택하면 될 것 같다.