icon안동민 개발노트

Fetch API와 AJAX


 AJAX(Asynchronous 자바스크립트 and XML)와 Fetch API는 웹 애플리케이션에서 비동기적으로 데이터를 주고받는 핵심 기술입니다.

 이 절에서는 이 두 기술의 개념, 사용법, 그리고 실제 적용에 대해 자세히 알아보겠습니다.

AJAX의 개념과 역사

 AJAX는 2005년에 소개된 기술로, 웹 페이지의 전체를 다시 로드하지 않고도 서버와 데이터를 교환할 수 있게 해주었습니다.

 이는 더 반응적이고 네이티브 애플리케이션과 유사한 웹 경험을 가능하게 했습니다.

 AJAX가 가져온 변화는 다음과 같습니다.

  • 사용자 경험 향상
  • 서버 부하 감소
  • 단일 페이지 애플리케이션(SPA) 개발 가능

XMLHttpRequest

 먼저 도입된 XMLHttpRequest는 AJAX의 핵심 기술 중 하나입니다.

 XMLHttpRequest는 다음과 같이 사용됩니다.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseText);
  }
};
xhr.send();

 XMLHttpRequest의 한계

  • 복잡한 사용법
  • 콜백 기반 비동기 처리
  • 에러 처리의 어려움

Fetch API

 Fetch API는 XMLHttpRequest의 한계를 극복하기 위해 등장했습니다.

 Promise 기반의 현대적인 인터페이스를 제공합니다.

 기본 문법

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

 Fetch API vs XMLHttpRequest

  • Promise 기반 (더 깔끔한 코드)
  • 더 직관적인 인터페이스
  • 스트림 기반 응답 처리
  • 모듈화된 요청/응답 객체

Fetch를 사용한 요청 예시

 GET 요청

fetch('https://api.example.com/users')
  .then(response => response.json())
  .then(users => console.log(users));

 POST 요청

fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'John Doe', email: '[email protected]' })
})
  .then(response => response.json())
  .then(data => console.log(data));

Fetch API의 고급 기능

 1. 헤더 설정

fetch('https://api.example.com/data', {
  headers: {
    'Authorization': 'Bearer TOKEN',
    'Content-Type': 'application/json'
  }
});

 2. CORS 처리

  • Fetch API는 기본적으로 CORS를 지원합니다.
  • 서버 측에서 적절한 CORS 헤더를 설정해야 합니다.

 3. 인증

fetch('https://api.example.com/data', {
  credentials: 'include' // 쿠키 포함
});

async/await와 함께 사용

 Fetch API는 async/await와 함께 사용하면 더욱 깔끔한 코드를 작성할 수 있습니다.

async function fetchUsers() {
  try {
    const response = await fetch('https://api.example.com/users');
    const users = await response.json();
    console.log(users);
  } catch (error) {
    console.error('Error:', error);
  }
}

 이점

  • 더 읽기 쉬운 코드
  • 동기 코드와 유사한 흐름
  • 에러 처리 용이

Fetch API 사용 시 주의사항

 1. 에러 처리

  • Fetch는 네트워크 오류가 발생한 경우에만 Promise를 reject합니다.
  • HTTP 에러 상태(예: 404, 500)에 대해서는 별도 처리가 필요합니다.
fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('HTTP error ' + response.status);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.log('Error:', error));

 2. 타임아웃 설정

  • Fetch API는 기본적으로 타임아웃 설정을 제공하지 않습니다.
  • 필요한 경우 다음과 같이 구현할 수 있습니다.
function fetchWithTimeout(url, options, timeout = 5000) {
  return Promise.race([
    fetch(url, options),
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Timeout')), timeout)
    )
  ]);
}

Fetch vs Axios

 Fetch API

  • 장점 : 브라우저 내장, 별도 설치 불필요, 가볍고 기본적인 기능 제공
  • 단점 : 일부 기능(자동 타임아웃, 요청 취소 등) 부재, 구형 브라우저 지원 제한

 Axios

  • 장점 : 더 풍부한 기능(요청 취소, 자동 변환, 인터셉터 등), 폭넓은 브라우저 지원
  • 단점 : 추가 의존성, 번들 크기 증가

 선택 기준 : 프로젝트의 복잡성, 필요한 기능, 지원해야 할 브라우저 범위에 따라 결정

Best Practices

  1. 응답 상태 확인
fetch(url).then(response => {
  if (!response.ok) throw new Error('Network response was not ok');
  return response.json();
})
  1. 에러 처리 통합
function handleErrors(response) {
  if (!response.ok) throw Error(response.statusText);
  return response;
}
 
fetch(url)
  .then(handleErrors)
  .then(response => response.json())
  .catch(error => console.log(error));
  1. 재사용 가능한 Fetch 래퍼 만들기
async function api(url, options = {}) {
  const defaultOptions = {
    headers: {
      'Content-Type': 'application/json'
    },
    // 기본 옵션 설정
  };
  
  try {
    const response = await fetch(url, { ...defaultOptions, ...options });
    if (!response.ok) throw new Error('Network response was not ok');
    return await response.json();
  } catch (error) {
    console.error('API call failed:', error);
    throw error;
  }
}
  1. AbortController 사용하여 요청 취소
const controller = new AbortController();
const signal = controller.signal;
 
fetch(url, { signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(err => {
    if (err.name === 'AbortError') {
      console.log('Fetch aborted');
    } else {
      console.error('Fetch error:', err);
    }
  });
 
// 요청 취소
controller.abort();

 Fetch API와 AJAX는 현대 웹 개발의 핵심 기술입니다. AJAX의 등장으로 시작된 비동기 웹 통신의 혁명은 Fetch API를 통해 더욱 발전했습니다. Fetch API는 더 간결하고 강력한 인터페이스를 제공하여, 개발자들이 더 쉽고 효율적으로 서버와 통신할 수 있게 해줍니다.

 Fetch API의 Promise 기반 설계는 비동기 코드를 더 쉽게 관리할 수 있게 해주며, async/await와 결합하면 더욱 가독성 높은 코드를 작성할 수 있습니다. 또한, Fetch API는 스트림 기반의 응답 처리를 지원하여, 대용량 데이터 처리에도 효율적입니다.

 그러나 Fetch API를 사용할 때는 몇 가지 주의해야 할 점이 있습니다. 특히 에러 처리와 타임아웃 설정에 주의를 기울여야 합니다. 이러한 한계를 극복하기 위해 Axios 같은 라이브러리를 사용하는 것도 좋은 선택일 수 있습니다.

 최종적으로, Fetch API를 효과적으로 사용하기 위해서는 프로젝트의 요구사항을 잘 파악하고, 적절한 에러 처리와 추상화를 통해 견고하고 유지보수가 용이한 코드를 작성하는 것이 중요합니다. 이를 통해 더 나은 사용자 경험과 개발자 경험을 동시에 제공할 수 있습니다.