Node.js 18 LTS 전환 후 fetch API 도입기

배경

10월 25일부터 Node.js 18이 LTS로 전환된다는 소식에 미리 테스트 환경에 적용해봤다. 가장 눈에 띈 건 fetch API가 글로벌로 제공된다는 점이었다. 그동안 axios나 node-fetch를 의존성으로 추가해야 했는데, 이제 브라우저와 동일한 API를 사용할 수 있게 됐다.

기존 코드

const axios = require('axios');

async function getUser(id) {
  try {
    const response = await axios.get(`https://api.example.com/users/${id}`);
    return response.data;
  } catch (error) {
    throw new Error(`Failed to fetch user: ${error.message}`);
  }
}

변경 후

async function getUser(id) {
  const response = await fetch(`https://api.example.com/users/${id}`);
  
  if (!response.ok) {
    throw new Error(`HTTP error: ${response.status}`);
  }
  
  return response.json();
}

마이그레이션 포인트

  1. 에러 처리 방식: axios는 4xx, 5xx를 자동으로 reject했지만, fetch는 response.ok를 명시적으로 체크해야 한다.
  2. 타임아웃: axios의 timeout 옵션 대신 AbortController를 사용해야 한다.
  3. 인터셉터: axios 인터셉터 로직은 별도 래퍼 함수로 구현했다.
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch(url, { signal: controller.signal });
} finally {
  clearTimeout(timeoutId);
}

결과

패키지 의존성 하나를 줄이고, 번들 크기도 약간 감소했다. 브라우저와 Node.js 코드 간 일관성도 좋아졌다. 다만 기존 axios에 익숙한 팀원들을 위해 에러 처리 패턴을 문서화하는 작업이 필요했다.

프로덕션 전환은 10월 말 LTS 전환 후 진행할 예정이다.