Published on

Axios vs Fetch

Authors
  • avatar
    Name
    Hyo814
    Twitter

Next.js에서 fetch 사용: 왜 Axios 대신 fetch를 사용할까?

Next.js에서는 기본적으로 fetch API를 사용하도록 권장하고 있으며, Next.js 13 버전부터는 특히 fetch API를 중심으로 하는 데이터 패칭 방식을 강화했습니다. fetch API는 브라우저 환경과 서버 환경 모두에서 사용할 수 있는 내장 API로, 추가적인 패키지 설치 없이도 HTTP 요청을 보낼 수 있어 간편하고 효율적입니다.

Next.js에서 fetch 사용: 왜 Axios 대신 fetch를 사용할까?

Next.js를 사용하는 개발자라면 데이터 패칭을 위해 axios 대신 fetch를 사용하는 것을 권장하는 것을 종종 보았을 것입니다. 특히 Next.js 13 버전 이후로, fetch API는 프레임워크의 기본 데이터 패칭 방법으로 자리 잡았습니다. 그렇다면 Next.js에서 왜 fetch를 사용하게 되었을까요? 그리고 fetch를 사용하면 어떤 점이 유리할까요?

Next.js에서 fetch가 기본 선택이 된 이유

Next.js는 최신 자바스크립트 기능을 최대한 활용하고, 서버와 클라이언트 양쪽에서 일관된 개발 경험을 제공하려는 목표를 가지고 있습니다. fetch는 브라우저 환경과 Node.js 서버 환경 모두에서 네이티브로 지원되는 API로, 추가적인 패키지 설치 없이도 쉽게 사용할 수 있습니다. 이를 통해 Next.js는 경량화된 번들 크기와 더 나은 성능을 제공할 수 있게 됩니다.

Axios와의 차이점:

  • 번들 크기: fetch는 브라우저 내장 API이기 때문에 번들에 포함되지 않습니다. 반면 axios는 외부 라이브러리이므로 번들 크기가 증가할 수 있습니다.
  • 호환성: fetch는 최신 브라우저 및 Node.js에서 지원되며, Next.js에서는 서버 측에서 실행될 때도 호환성이 보장됩니다.
  • 직관적인 사용: fetch는 Promise 기반의 간단한 API를 제공하며, 최근의 ES6 문법과 함께 사용하면 코드의 가독성이 좋습니다.

fetch를 사용하면 어떤 점이 더 유리할까?

  1. 서버 사이드 렌더링(SSR)과 정적 사이트 생성(SSG)에서의 이점:

Next.js는 서버 사이드 렌더링과 정적 사이트 생성을 지원하는 프레임워크입니다. 이때 fetch API는 서버와 클라이언트 모두에서 사용 가능하기 때문에, 동일한 코드로 데이터 패칭을 할 수 있습니다. 이는 코드의 재사용성과 유지 보수성을 높입니다.

// getServerSideProps 예시에서 fetch 사용
export async function getServerSideProps() {
  const res = await fetch('<https://api.example.com/data>');
  const data = await res.json();
  return { props: { data } };
}

   ```

2. **간편한 설정과 추가 의존성 제거:**

`fetch`는 자바스크립트의 내장 API이기 때문에 별도의 설정이나 추가 패키지가 필요 없습니다. 이는 초기 설정 단계에서 시간을 절약해주고, 프로젝트의 의존성을 줄여 관리가 간편해집니다.

3. **ES6+ 기능과의 호환성:**

`fetch` API는 최신 자바스크립트 문법과 잘 어울립니다. `async/await`와 함께 사용하면 비동기 요청을 동기식 코드처럼 작성할 수 있어 가독성이 뛰어납니다.

```jsx
// fetch와 async/await 사용 예시
async function fetchData() {
  try {
    const response = await fetch('<https://api.example.com/data>');
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Fetch error:', error);
  }
}

   ```

4. **최신 브라우저 기능 지원:**

`fetch` API는 최신 브라우저의 기능을 잘 지원합니다. 예를 들어, `AbortController`를 통해 요청을 취소하거나 타임아웃을 설정할 수 있는 기능이 있어 유연하게 요청을 제어할 수 있습니다.

```jsx
// fetch와 AbortController 사용 예시
const controller = new AbortController();
const signal = controller.signal;

fetch('<https://api.example.com/data>', { signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Fetch aborted');
    } else {
      console.error('Fetch error:', error);
    }
  });

// 특정 조건에서 요청 취소
controller.abort();

   ```

5. **프레임워크와의 깊은 통합:**

Next.js는 `fetch`를 기본으로 하는 서버 컴포넌트, 클라이언트 컴포넌트 등 다양한 기능을 제공하며, 이는 프로젝트의 퍼포먼스 최적화와 코드 일관성 유지에 큰 도움이 됩니다. 특히, Next.js의 새 기능인 데이터 패칭 전략과 결합하면 프론트엔드의 성능을 극대화할 수 있습니다.


### Next.js에서 `fetch``axios`의 성능 차이는 실제로 얼마나 되나요?

`fetch``axios`의 성능 차이는 사용 사례와 요청의 복잡도에 따라 다를 수 있지만, 일반적으로 `fetch`는 더 가볍고 빠른 성능을 보입니다. 이유는 다음과 같습니다:

- **번들 크기 차이:** `fetch`는 브라우저 내장 API이기 때문에 번들 크기에 영향을 주지 않습니다. 반면, `axios`는 외부 라이브러리로써 번들 크기를 증가시켜 페이지 로딩 시간을 약간 더 길게 만들 수 있습니다.
- **네트워크 요청 성능:** 일반적인 GET, POST 요청에서 두 라이브러리의 성능 차이는 크지 않지만, `axios`가 추가적인 기능(예: JSON 변환, 응답 데이터 구조 처리)을 제공하기 때문에 `fetch`보다 약간의 오버헤드가 있을 수 있습니다.
- **서버 환경에서의 성능:** 서버 사이드에서 Next.js를 사용할 때, `fetch`는 Node.js 환경에서도 내장되어 있어 일관된 환경을 제공합니다. `axios`는 브라우저와 서버 모두에서 사용할 수 있지만, 서버 환경에서의 `fetch`가 경량으로 작동할 수 있습니다.

실제로 복잡한 설정이나 응답 변환 로직이 많지 않다면 `fetch`가 약간 더 빠르고 가벼운 성능을 보이는 것이 일반적입니다. 그러나 이 차이는 대개 미세하며, 큰 규모의 애플리케이션에서 성능 최적화의 주요 요인이 되는 경우는 드뭅니다.

### `fetch` API의 에러 핸들링은 어떻게 하는 것이 좋을까요?

`fetch` API의 에러 핸들링은 아래와 같은 방식으로 할 수 있습니다:

1. **HTTP 상태 코드 확인:** `fetch`는 네트워크 요청이 성공하더라도, 응답이 HTTP 에러 상태 코드(예: 404, 500 등)를 반환하면 `response.ok``false`가 됩니다. 이 경우 명시적으로 에러 처리를 해야 합니다.

```jsx
async function fetchData() {
  try {
    const response = await fetch('<https://api.example.com/data>');
    if (!response.ok) {
      // HTTP 에러 상태 처리
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    return data;
  } catch (error) {
    // 네트워크 에러 또는 HTTP 에러 처리
    console.error('Fetch error:', error);
  }
}

   ```

2. **네트워크 에러:** `fetch`는 네트워크 오류(예: 인터넷 연결 문제) 시 Promise를 거부하지만, HTTP 에러는 거부하지 않습니다. 이 때문에 항상 상태 코드를 체크하는 것이 중요합니다.
3. **타임아웃 처리:** 기본적으로 `fetch`는 타임아웃을 지원하지 않습니다. 타임아웃을 처리하려면 `AbortController`를 사용하여 요청을 중단할 수 있습니다.

```jsx
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5초 후 요청 중단

try {
  const response = await fetch('<https://api.example.com/data>', { signal: controller.signal });
  clearTimeout(timeoutId);
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  const data = await response.json();
  return data;
} catch (error) {
  if (error.name === 'AbortError') {
    console.error('Fetch aborted due to timeout');
  } else {
    console.error('Fetch error:', error);
  }
}

   ```


이처럼 `fetch` API의 에러 핸들링은 HTTP 상태 코드 확인과 네트워크 오류 처리를 통해 안전하게 수행할 수 있습니다.

### `fetch``axios`를 함께 사용하는 것도 좋은 방법인가요? 그런 경우는 언제인가요?

`fetch``axios`를 함께 사용하는 것도 가능합니다. 다음과 같은 경우에는 둘을 조합해서 사용할 수 있습니다:

1. **특정 기능이 필요할 때:** `fetch`는 기본적인 HTTP 요청에 적합하지만, 더 복잡한 요청 구성이나 기능(예: 요청 취소, 자동 JSON 변환, 응답 데이터 구조 조작)이 필요할 때는 `axios`를 사용하면 더 편리합니다. 예를 들어, 파일 업로드나 멀티 파트 요청을 자주 사용하는 경우 `axios`의 사용이 더 직관적일 수 있습니다.
2. **기존 코드베이스와의 호환성:** 프로젝트에서 이미 `axios`를 사용 중인데 새로운 부분에서 가벼운 요청이 필요할 때 `fetch`를 도입할 수 있습니다. 기존 코드를 전부 리팩토링할 필요 없이 필요한 부분에만 `fetch`를 사용할 수 있습니다.
3. **성능 최적화 필요 시:** 클라이언트 측에서는 번들 크기를 줄이기 위해 가벼운 요청에는 `fetch`를 사용하고, 서버 사이드나 복잡한 요청에는 `axios`를 사용할 수 있습니다. 이를 통해 성능 최적화와 기능의 균형을 맞출 수 있습니다.