발행일

fetch가 Next.js에서 선호되는 이유, 그리고 axios와의 차이점

fetch가 Next.js에서 선호되는 이유, 그리고 axios와의 차이점

2023년에 정리했던 글입니다. 기본 비교는 그대로 두고, 이후 실제 프로젝트에서 fetch를 채택해 운영하며 알게 된 것과 시효가 지난 부분의 정정을 뒤에 붙였습니다.

1. fetch가 선호되는 이유 (당시 정리)

  • 기본 내장 — 브라우저와 Node.js 양쪽에 내장이라, 서버(SSR)와 클라이언트를 오가는 Next.js에서 추가 설치 없이 동일하게 동작합니다.
  • 번들 크기 — axios는 외부 의존성이고, fetch는 번들에 아무것도 더하지 않습니다.
  • 표준 — 표준 API를 따르는 것이 장기 유지보수에 유리합니다.

2. fetch vs axios 핵심 차이

fetchaxios
제공 방식내장외부 라이브러리
JSON 처리.json() 직접 호출자동 변환
HTTP 에러reject 안 됨response.ok 직접 확인4xx/5xx에서 자동 reject
인터셉터·기본 헤더직접 구현기본 제공

fetch의 가장 큰 함정은 에러 처리입니다. 404·500에서도 Promise가 성공하므로, ok 확인을 빼먹으면 에러 응답을 정상 데이터처럼 파싱하다 엉뚱한 곳에서 터집니다.

const response = await fetch('/api/data')
if (!response.ok) throw new Error(`HTTP error: ${response.status}`)
const data = await response.json()

3. 다시 보니 — 이 글이 놓쳤던 것과 시효가 지난 것

진짜 이유는 "내장이라서"가 아니었다

당시엔 내장·번들·표준을 이유로 꼽았는데, App Router 이후로 보면 더 근본적인 이유가 있습니다. Next.js는 fetch를 자기 캐싱 계층의 인터페이스로 확장합니다fetch(url, { next: { revalidate: 60 } })처럼 요청 단위 캐시 수명을 걸고, 같은 렌더 패스의 중복 요청을 자동으로 합쳐요. 이 확장은 fetch에만 적용되므로, axios를 쓰면 Next.js 캐싱·재검증 체계 바깥에서 노는 셈이 됩니다. "선호"가 아니라 프레임워크와의 통합 여부의 문제였던 거죠. 이 글의 예시로 들었던 getServerSideProps/getStaticProps도 Pages Router 시절 API라, 지금 신규 프로젝트 기준으로는 서버 컴포넌트에서 fetch를 직접 await하는 모양이 표준입니다.

"취소가 필요하면 axios" — 지금은 틀린 말

원문 3절에서 요청 취소가 필요하면 axios(CancelToken)를 권했는데, CancelToken은 deprecated됐고 axios도 지금은 AbortController를 씁니다. 그런데 AbortController는 fetch도 똑같이 지원해요. 취소는 더 이상 axios를 고를 이유가 아닙니다. IE11 지원 항목도 마찬가지로 시효가 끝났습니다.

인터셉터 없는 대가는 실제로 치렀다

"인터셉터가 필요하면 axios"는 지금도 맞는 말인데, 실제 프로젝트(TripTune)에서는 그럼에도 fetch를 골랐고, 그 대가로 401 처리·토큰 갱신·재시도를 담은 래퍼를 직접 만들었습니다. 처음엔 그 처리가 화면마다 흩어져 로그인 풀림·중복 alert·무한 갱신 루프를 겪었고, 공통 래퍼 한곳으로 모으고서야 끝났어요 — 그 과정은 따로 정리했습니다. 요약하면: fetch를 고르는 건 공짜가 아니라, axios가 기본 제공하는 것을 언제 직접 만들지 정하는 결정이었습니다.

4. 지금 기준의 결론

  • Next.js라면 fetch — 내장이라서가 아니라, 프레임워크의 캐싱·중복 제거가 fetch 위에 얹히기 때문.
  • 인터셉터·재시도·공통 에러 처리가 필요한 규모라면, axios를 들이거나 fetch 래퍼를 직접 만들거나 — 어느 쪽이든 그 계층은 생깁니다. 안 만들면 화면마다 복사되다 사고가 나는 걸 겪었습니다.
  • 취소(AbortController)와 브라우저 지원은 이제 판단 기준이 아닙니다.