Apidog

올인원 협업 API 개발 플랫폼

API 설계

API 문서

API 디버깅

API 모킹

API 자동화 테스트

Node Fetch API의 궁극적인 가이드: Node.js에서 HTTP 요청하기

Young-jae

Young-jae

Updated on March 28, 2025

HTTP 요청은 현대 웹 개발의 기본적인 부분입니다. Node.js에 Fetch API가 도입되면서, 개발자들은 이제 브라우저와 서버 환경에서 네트워크 요청을 수행할 수 있는 강력하고 일관된 방법을 갖게 되었습니다. 이 포괄적인 튜토리얼에서는 프로젝트에서 Node fetch를 효과적으로 사용하는 방법을 살펴보겠습니다.

Node Fetch API란 무엇이며, 왜 사용해야 할까요?

Node fetch API는 Node.js 애플리케이션에서 HTTP 요청을 수행하기 위한 최신의 약속 기반 메커니즘입니다. 원래는 브라우저 전용 기능이었던 fetch는 Node.js v18에서 실험적인 기능으로 도입되었으며, Node.js v21에서 안정성을 갖추게 되었습니다.

Node Fetch 사용의 주요 이점:

  • 내장된 기능: 제3자 패키스를 설치할 필요 없음
  • 약속 기반: 비동기/대기(async/await) 지원이 있는 깔끔하고 현대적인 구문
  • 크로스 플랫폼 친숙함: 브라우저 측 fetch와 동일한 API
  • 개선된 성능: 고성능 Undici HTTP 클라이언트를 기반으로 함

현대 도구로 Node Fetch API 요청 테스트하기

Node fetch를 배우는 동안 API 엔드포인트를 테스트하기 위한 신뢰할 수 있는 도구가 필수적입니다. Apidog는 Node fetch API 요청을 테스트하고 문서화하는 데 가장 좋은 Postman 대안으로 돋보입니다.

모든 기능을 갖춘 API 개발 플랫폼인 Apidog는 단일 직관적인 인터페이스에서 API 문서화, 테스트 및 모의 서버를 결합합니다.

Node fetch로 애플리케이션을 개발할 때, Apidog는 응답을 시각화하고 팀원과 협업하며 코드에서 구현하기 전에 API 호출이 제대로 작동하는지 확인하는 데 도움을 줍니다. Node fetch 요청을 위한 코드 스니펫을 생성할 수 있는 기능은 테스트에서 구현으로의 전환을 원활하게 만들어 줍니다.

버튼

Node Fetch를 위한 환경 설정하기

Node Fetch 사용을 위한 필요 조건

Node fetch 예제를 살펴보기 전에 다음이 준비되어 있는지 확인하세요:

  1. Node.js v18 이상 (안정적인 fetch 지원을 위해 v21 이상을 권장)
  2. Node.js 버전 확인하기:
node -v

Node Fetch 버전 호환성

  • Node.js v21+: Fetch는 안정적이며 프로덕션 사용 준비 완료
  • Node.js v18-v20: Fetch 사용 가능하지만 실험적임 (-experimental-fetch 플래그 사용)
  • 구버전 Node.js: node-fetch 패키지를 설치하거나 Node.js를 업그레이드하세요

v18-v20을 사용하는 경우 다음 명령어로 애플리케이션을 실행하세요:

node --experimental-fetch app.js

첫 번째 Node Fetch 요청 만들기

Node fetch를 사용하여 기본 GET 요청부터 시작해 봅시다:

// Node fetch로 기본 GET 요청
fetch('<https://api.example.com/data>')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP 오류! 상태: ${response.status}`);
    }
    return response.json(); // JSON 응답 파싱
  })
  .then(data => {
    console.log('수신된 데이터:', data);
  })
  .catch(error => {
    console.error('Fetch 오류:', error);
  });

Async/Await로 Node Fetch 사용하기

더 깔끔한 코드를 위해 Node fetch와 함께 async/await를 사용할 수 있습니다:

async function fetchData() {
  try {
    const response = await fetch('<https://api.example.com/data>');

    if (!response.ok) {
      throw new Error(`HTTP 오류! 상태: ${response.status}`);
    }

    const data = await response.json();
    console.log('수신된 데이터:', data);
    return data;
  } catch (error) {
    console.error('Fetch 오류:', error);
  }
}

// 함수 호출
fetchData();

고급 Node Fetch 요청 메서드

Node Fetch로 POST 요청 만들기

async function postData(url, data) {
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    });

    if (!response.ok) {
      throw new Error(`HTTP 오류! 상태: ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error('Fetch POST 오류:', error);
  }
}

// 사용 예
const newUser = {
  name: 'John Doe',
  email: 'john@example.com',
};

postData('<https://api.example.com/users>', newUser)
  .then(data => console.log('생성된 사용자:', data));

Node Fetch로 PUT 요청 만들기

async function updateData(url, data) {
  try {
    const response = await fetch(url, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    });

    if (!response.ok) {
      throw new Error(`HTTP 오류! 상태: ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error('Fetch PUT 오류:', error);
  }
}

// 사용 예
const updatedUser = {
  id: 1,
  name: 'Jane Smith',
  email: 'jane@example.com',
};

updateData('<https://api.example.com/users/1>', updatedUser)
  .then(data => console.log('업데이트된 사용자:', data));

Node Fetch로 DELETE 요청 만들기

async function deleteResource(url) {
  try {
    const response = await fetch(url, {
      method: 'DELETE',
    });

    if (!response.ok) {
      throw new Error(`HTTP 오류! 상태: ${response.status}`);
    }

    // 일부 API는 DELETE 시 내용이 없음
    if (response.status === 204) {
      return { success: true };
    }

    return await response.json();
  } catch (error) {
    console.error('Fetch DELETE 오류:', error);
  }
}

// 사용 예
deleteResource('<https://api.example.com/users/1>')
  .then(result => console.log('삭제 결과:', result));

Node Fetch로 다양한 응답 유형 처리하기

Node fetch는 다양한 응답 형식을 처리할 수 있습니다:

JSON 응답 처리하기

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

텍스트 응답 처리하기

fetch('<https://example.com/plain-text>')
  .then(response => response.text())
  .then(text => console.log(text));

바이너리 데이터 처리하기

fetch('<https://example.com/image.png>')
  .then(response => response.arrayBuffer())
  .then(buffer => {
    // 바이너리 데이터 처리
    const bytes = new Uint8Array(buffer);
    console.log('바이너리 데이터 길이:', bytes.length);
  });

헤더와 옵션으로 Node Fetch 요청 설정하기

사용자 지정 헤더 설정하기

fetch('<https://api.example.com/protected-data>', {
  headers: {
    'Authorization': 'Bearer YOUR_TOKEN_HERE',
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'User-Agent': 'My Node.js Application'
  }
})
.then(response => response.json())
.then(data => console.log(data));

요청 옵션 설정하기

fetch('<https://api.example.com/data>', {
  method: 'GET',
  headers: { 'Content-Type': 'application/json' },
  cache: 'no-cache',
  redirect: 'follow',      // follow, error, or manual
  referrerPolicy: 'no-referrer'
})
.then(response => response.json())
.then(data => console.log(data));

Node Fetch에서 오류 처리하기

포괄적인 오류 처리

Node fetch에 대해 이해해야 할 중요한 점은 HTTP 오류 상태 코드에서 거부되지 않는다는 것입니다. 약속은 네트워크 오류가 발생하거나 요청 완료를 방해하는 문제가 있을 경우에만 거부됩니다.

다음은 포괄적인 오류 처리 접근 방식입니다:

async function fetchWithErrorHandling(url) {
  try {
    const response = await fetch(url);

    // HTTP 오류 확인
    if (!response.ok) {
      // 응답에서 오류 세부 정보 얻기 시도
      let errorDetails;
      try {
        errorDetails = await response.json();
      } catch (e) {
        errorDetails = await response.text();
      }

      throw new Error(
        `HTTP 오류! 상태: ${response.status}, 세부 정보: ${
          typeof errorDetails === 'object'
            ? JSON.stringify(errorDetails)
            : errorDetails
        }`
      );
    }

    return await response.json();
  } catch (error) {
    // 네트워크 오류, 파싱 오류 및 사용자 정의 HTTP 오류
    console.error('Fetch 실패:', error.message);
    throw error; // 호출 코드가 처리할 수 있도록 재발생
  }
}

Node Fetch로 요청 타임아웃 구현하기

Node fetch는 내장된 타임아웃 지원이 없지만 AbortController를 사용하여 구현할 수 있습니다:

async function fetchWithTimeout(url, options = {}, timeoutMs = 5000) {
  const controller = new AbortController();
  const { signal } = controller;

  // 타임아웃 설정
  const timeout = setTimeout(() => {
    controller.abort();
  }, timeoutMs);

  try {
    const response = await fetch(url, { ...options, signal });
    clearTimeout(timeout); // fetch가 완료되면 타임아웃 해제

    if (!response.ok) {
      throw new Error(`HTTP 오류! 상태: ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    clearTimeout(timeout);
    if (error.name === 'AbortError') {
      throw new Error(`요청이 ${timeoutMs}ms 후에 시간 초과되었습니다.`);
    }
    throw error;
  }
}

// 사용 예
fetchWithTimeout('<https://api.example.com/data>', {}, 3000)
  .then(data => console.log(data))
  .catch(error => console.error('오류:', error.message));

Node Fetch로 인증 처리하기

기본 인증

const username = 'user';
const password = 'password';
const credentials = Buffer.from(`${username}:${password}`).toString('base64');

fetch('<https://api.example.com/protected>', {
  headers: {
    'Authorization': `Basic ${credentials}`
  }
})
.then(response => response.json())
.then(data => console.log(data));

베어러 토큰 인증

const token = 'your_jwt_or_oauth_token';

fetch('<https://api.example.com/protected>', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
})
.then(response => response.json())
.then(data => console.log(data));

프로덕션에서 Node Fetch 사용을 위한 모범 사례

  1. 항상 응답 상태를 확인하세요: 응답이 성공적이라고 가정하지 마세요.
  2. 다양한 콘텐츠 유형을 적절히 처리하세요: 응답 유형에 맞는 올바른 메서드를 사용하세요 (json(), text() 등).
  3. 적절한 오류 처리를 구현하세요: 오류를 일관되게 처리하는 유틸리티 함수를 만드세요.
  4. 요청 타임아웃을 설정하세요: AbortController를 사용하여 요청이 끊기지 않도록 하세요.
  5. 재사용 가능한 fetch 래퍼를 만드세요: 공통 요청 패턴을 갖춘 서비스 레이어를 구축하세요.
  6. 실패한 요청을 위한 재시도 로직을 고려하세요: 불안정한 API에 대해 지수 백오프를 구현하세요.
  7. 기본 URL에 대해 환경 변수를 사용하세요: 환경에 특정한 URL을 코드에서 제외하세요.

일반적인 Node Fetch 문제 해결

"Fetch is not defined" 오류

ReferenceError: fetch is not defined 오류가 발생하면 다음을 확인하세요:

  1. Node.js v18 이상을 사용하고 있는지 확인하세요.
  2. Node.js v18-v20의 경우 -experimental-fetch 플래그를 사용하세요.
  3. 구버전을 사용하는 경우 node-fetch 패키지를 설치하세요.

HTTPS 인증서 문제

Node fetch는 Node의 HTTPS 인증서 처리를 상속합니다. 사용자 지정 인증서를 사용하려면:

const https = require('https');
const fs = require('fs');

const httpsAgent = new https.Agent({
  ca: fs.readFileSync('./custom-certificate.pem')
});

fetch('<https://api.example.com/data>', {
  agent: httpsAgent
})
.then(response => response.json())
.then(data => console.log(data));

결론: 프로젝트에서 Node Fetch 수용하기

Node fetch API는 Node.js 애플리케이션에서 HTTP 요청을 수행하는 방식에서 상당한 개선을 나타냅니다. 약속 기반 인터페이스, 플랫폼 간 일관된 동작 및 네이티브 구현 덕분에 현대 Node.js 개발의 선호하는 선택지가 되고 있습니다.

Node fetch를 숙달함으로써 현대 JavaScript 기능을 활용하면서 향상된 성능을享受할 수 있는 더 유지보수가 용이한 코드를 작성할 수 있습니다. 안정적인 구현이 Node.js에서 계속 성숙해짐에 따라 더 많은 개발자들이 HTTP 요청을 수행하는 표준 접근 방식으로 이 강력한 API를 채택할 것으로 기대됩니다.

이제 Node fetch에 대해 포괄적으로 이해하게 되었으니, 이를 프로젝트에 구현하고 모든 HTTP 요청 필요에 이 강력한 API를 활용할 준비가 되셨습니다.

버튼