Fetch API는 Node.js에서 HTTP 요청을 수행하고 로컬 리소스를 가져오는 공식 지원되는 새로운 방식을 나타냅니다. 이는 프로젝트에서 더 이상 외부 HTTP 클라이언트 종속성이 필요하지 않음을 의미합니다. 여러분이 해야 할 일은 Node Fetch API 사용법을 배우는 것뿐이며, 이 가이드가 바로 그 내용을 다루고 있습니다.
여기서 다음을 확인할 수 있습니다:
- Fetch API란 무엇인가
- Node Fetch API 시작하기
- Node.js에서 Fetch API로 HTTP 요청 수행하기
- 추가 옵션 및 기능
자, 시작해 보겠습니다!
Fetch API란 무엇인가요?
Fetch API는 로컬 또는 네트워크를 통해 리소스를 가져오는 JavaScript 인터페이스입니다. 구체적으로, 비동기 HTTP 요청을 쉽게 수행할 수 있도록 하는 글로벌 fetch() 함수를 제공합니다. 동일한 메서드를 사용하여 로컬 파일도 가져올 수 있습니다. JavaScript Fetch API는 기존 XMLHttpRequest API를 대체하는 유연한 솔루션입니다.
fetch() 메서드는 Request 및 Response 객체를 기반으로 합니다. 필수 인수는 하나뿐이며, 가져올 리소스의 로컬 경로 또는 URL입니다. 또한 CORS, HTTP 헤더, 캐싱 설정 등 선택적 옵션을 추가로 받아들입니다. 비동기 메서드인 fetch()는 서버에서 생성된 응답을 해결하는 Promise를 반환합니다. 이는 Response 객체로 표현되며, 콘텐츠 본문에 접근하고 파싱하기 위한 여러 메서드를 제공합니다.
기본적인 Fetch API 호출은 다음과 같습니다:
fetch("https://httpbin.io/ip", {
// 선택적 구성...
}).then((response) => response.json())
.then((data) => {
// JSON 응답 본체 출력
console.log(data) // { "origin": "<YOUR_IP_ADDRESS>" }
})
// 또는 동등한 async/await 구문을 선호한다면 다음과 같이 작성할 수 있습니다:
const response = await fetch("https://httpbin.io/ip", {
// 선택적 구성...
})
// JSON 응답 본문 출력
console.log(await response.json()) // { "origin": "<YOUR_IP_ADDRESS>" }
Node Fetch API 시작하기
Fetch API는 수년간 주요 브라우저에서 지원되어 왔습니다. 그러나 Node.js 표준 라이브러리에 포함된 것은 2022년 4월 출시된 버전 18.0.0부터입니다. 구체적으로 Node Fetch API는 undici의 구현을 기반으로 합니다.
Node.js 18 이전에는 실험적 기능으로 활성화하거나, 또 다른 인기 있는 Fetch API 구현체인 node-fetch npm 라이브러리를 통해 fetch()를 사용할 수 있었습니다. 이제 fetch()가 공식 Node.js 표준 라이브러리의 일부가 되었으므로, 별도로 import하지 않고도 코드에서 직접 사용할 수 있습니다. 아래 구문으로 fetch() 메서드를 호출하기만 하면 됩니다:
fetch(url, options)
url은 필수 매개변수로 다음을 포함할 수 있습니다:
- 로컬 리소스 경로 (예: movies.json)
- 원격 엔드포인트 또는 리소스의 URL (예: https://httpbin.io/ip 또는 https://example.com/movies.json)
options는 선택적 객체로, 다음 선택적 필드를 지원합니다:
- method: 요청의 HTTP 메서드입니다. “GET”, “POST”, “PUT”, “PATCH”, “DELETE” 등이 있습니다. 기본값은 “GET”입니다.
- headers: 요청에 추가할 HTTP 헤더를 포함하는 Headers 객체 또는 객체 리터럴입니다. 기본적으로 헤더는 설정되지 않습니다.
- body: 요청 본문에 사용할 데이터를 포함하는 객체입니다. GET 및 HEAD 요청에는 본문이 있을 수 없습니다.
- mode: 요청에 사용할 모드(예: “cors”, “no-cors”, “same-origin”, “navigate”, “websocket”). 기본값은 cors입니다.
- credentials: 브라우저가 자격 증명을 전송할지 여부를 지정합니다. 다음 문자열 중 하나여야 합니다: “omit”, “same-origin”, “include”.
- redirect: HTTP 리디렉션 응답 처리 방식을 결정합니다. “follow”, “error”, “manual” 중 하나여야 합니다. 기본값은 “follow”입니다.
- referrer: 요청의 리퍼러를 포함하는 문자열입니다. 기본값은 빈 문자열입니다.
- referrerPolicy: 요청에 사용할 리퍼러 정책을 지정합니다.
- signal: AbortController 인터페이스를 통해 요청을 중단할 수 있도록 하는 AbortSignal 객체 인스턴스입니다.
- priority: 동일 유형의 다른 요청 대비 현재 Fetch 요청의 우선순위를 지정하는 문자열입니다. “high”, “low” 또는 “auto”를 허용합니다. 기본값은 “auto”입니다.
자세한 내용은 공식 문서의 fetch() 매개변수 섹션을 참조하세요.
다음은 옵션 객체를 사용한 Node.js Fetch 요청의 예시입니다:
const response = await fetch("https://your-domain.com/api/v1/users", {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username: "jane-doe",
email: "[email protected]",
role: "superuser",
age: 23,
birthplace: "New York",
}),
})
본문 데이터는 Content-Type 헤더와 반드시 일치해야 합니다.
Node.js에서 Fetch API를 사용한 HTTP 요청 수행
이제 가장 널리 사용되는 HTTP 메서드에 대한 실제 요청 예시를 통해 Node Fetch API가 작동하는 모습을 살펴보겠습니다.
GET
Fetch API로 GET 요청을 수행하는 방법은 다음과 같습니다:
const response = await fetch("https://your-domain.com/your-endpoint")
보시다시피 단 한 줄의 코드만으로 가능합니다. fetch()가 기본적으로 GET 요청을 수행하기 때문입니다.
다음과 같은 메서드 중 하나로 응답 콘텐츠에 접근할 수 있습니다:
- response.text(): 응답 본문을 텍스트로 반환하는 Promise를 해결합니다.
- response.json(): JSON 응답에서 파싱된 객체로 해결되는 Promise를 반환합니다.
- response.blob(): 응답 본문을 Blob 객체로 해결되는 Promise를 반환합니다.
- response.arrayBuffer(): 응답 본문을 ArrayBuffer 인스턴스로 해결되는 Promise를 반환합니다.
- response.formData(): 응답 본문을 FormData 객체로 해결되는 Promise를 반환합니다.
따라서 완전한 예제의 코드는 다음과 같습니다:
const response = await fetch("https://httpbin.io/ip")
const jsonResponseContent = await response.json() // { "origin": "<YOUR_IP_ADDRESS>" }
const origin = jsonResponseContent.origin // <YOUR_IP_ADDRESS>
서버에서 반환된 응답이 JSON 형식이 아닌 경우, response.json() 명령은 SyntaxError로 실패합니다.
POST
Node Fetch API 호출로 POST 요청을 만드는 데는 몇 줄만 필요합니다:
const formData = new FormData()
formData.append("username", "serena-smith")
formData.append("email", "[email protected]")
const response = await fetch("https://example.com/api/v1/users", {
method: "POST",
body: formData,
})
fetch()로 POST 요청을 보내는 핵심은 body 옵션에 서버로 전송할 데이터를 지정하는 것입니다. 이 데이터는 JSON, FormData, 텍스트 등 여러 형식으로 지정할 수 있습니다. FormData 객체를 보낼 때는 Content-Type 헤더를 지정할 필요가 없습니다. 그 외의 경우에는 반드시 지정해야 합니다.
PUT
Fetch API로 PUT 요청을 수행하는 것은 POST 요청을 하는 것과 같습니다:
const response = await fetch("https://example.com/api/v1/users", {
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username: "john-doe",
email: "[email protected]",
role: "regular-user",
age: 47,
birthplace: "Chicago",
}),
})
유일한 차이점은 메서드 설정을 “PUT”으로 지정해야 한다는 점입니다. 마찬가지로 “PATCH”로 설정하면 PATCH 요청을 보낼 수 있습니다.
DELETE
다음은 fetch()를 사용한 HTTP DELETE 요청 예시입니다:
const response = await fetch("https://example.com/api/v1/users/45", {
method: "DELETE",
})
다시 말해, 올바른 HTTP 메서드를 설정하는 것이 핵심입니다. Fetch API 구현체가 나머지를 처리합니다.
추가 옵션 및 기능
이제 일반적인 시나리오에서 fetch()를 사용하는 방법을 알았으니, Node Fetch API의 고급 옵션을 탐색할 준비가 되었습니다.
헤더 설정
fetch()는 옵션 객체의 headers 필드를 통해 요청의 HTTP 헤더를 사용자 정의할 수 있게 합니다. 특히 headers는 Headers 객체나 특정 문자열 값을 가진 객체 리터럴을 받아들입니다.
fetch() 요청에서 Content-Type 및 User-Agent 헤더를 설정하고 싶다면 아래와 같이 Headers 객체를 사용할 수 있습니다:
const customHeaders = new Headers()
customHeaders.append("Content-Type", "application/json")
customHeaders.append("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36")
const response = fetch("https://your-domain.com/your-endpoint", {
headers: customHeaders,
// 기타 옵션...
})
또는 객체 리터럴로 동일하게 설정할 수 있습니다:
const response = fetch("https://your-domain.com/your-endpoint", {
headers: {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
},
// 기타 옵션...
})
이 구문은 더 간결하고 읽기 쉽습니다.
헤더 읽기
서버가 응답에 설정해 놓은 HTTP 헤더를 읽으려면 다음과 같이 접근할 수 있습니다:
const response = await fetch("https://your-domain.com/your-endpoint", {
// 선택적 구성...
})
// "Content-Type" 응답 헤더 접근
const responseHeaders = response.headers
const responseContentType = response.headers.get("Content-Type")
response.headers 필드는 Headers 객체를 반환하며, 여기서 get() 메서드를 사용하여 특정 헤더에 접근할 수 있습니다.
Node Fetch API 오류 처리
Node.js Fetch API 호출은 다음 두 가지 이유로만 실패할 수 있습니다:
- AbortError 예외: AbortController에 의해 요청이 의도적으로 중단된 경우.
- TypeError 예외: 헤더 이름 오류, URL 오류, 일반적인 네트워크 오류 등 여러 이유로 발생할 수 있습니다. 자세한 원인은 문서를 참조하세요.
중요한 점은 Fetch API에서는 4xx 또는 5xx 응답도 성공적인 요청으로 간주된다는 것입니다. 즉, 서버에서 오류 응답을 반환해도 JavaScript 오류가 발생하지 않습니다. 이러한 동작의 이유는 fetch()가 요청을 수행했고 서버가 응답을 반환했기 때문입니다. 개념적으로 이는 네트워크 관점에서 오류로 간주될 수 없습니다. 결국 요청은 성공적으로 완료된 것입니다.
이는 서버가 반환한 데이터를 처리하기 전에 항상 성공적인 응답 여부를 확인해야 함을 의미합니다. 이를 위해 아래와 같은 오류 처리 로직을 구현할 수 있습니다:
try {
const response = await fetch("https://your-domain.com/your-endpoint", {
// 선택적 구성...
})
if (response.ok) {
// 서버가 반환한 데이터 사용...
// 예시:
// await response.json()
} else {
// 4xx 및 5xx 오류 처리...
}
} catch (error) {
console.error("Fetch 오류:", error.message);
// 네트워크 또는 중단 오류 처리...
}
Response의 ok 속성은 요청이 성공했을 때만 true를 포함합니다.
Fetch 요청 중단
Fetch API는 AbortController API를 통해 이미 시작된 요청의 중단을 지원합니다.
진행 중인 fetch() 요청을 중지하려면 먼저 아래와 같이 신호 객체를 생성해야 합니다:
const controller = new AbortController()
const signal = controller.signal
// 그런 다음 요청의 options 객체에 지정합니다:
const response = await fetch("https://your-domain.com/your-endpoint", {
signal: signal,
// 기타 설정...
})
이제 다음 명령어를 호출할 때마다 요청이 AbortError로 중단됩니다:
controller.abort()
서버가 이미 요청을 수신했을 수 있다는 점을 유의하세요. 이 경우 서버는 요청을 계속 처리하지만 Node.js는 응답을 무시합니다.
축하합니다! 이제 Node.js Fetch API 마스터가 되셨습니다!
결론
이 글에서는 Fetch API가 무엇이며 Node.js에서 어떻게 사용하는지 배웠습니다. 구체적으로 fetch()의 기본부터 시작하여 고급 옵션과 기능까지 깊이 있게 살펴보았습니다. 이렇게 강력한 HTTP 클라이언트를 사용하면 온라인 데이터 가져오기가 쉬워집니다. 예를 들어, SERP API 엔드포인트를 호출하여 SERP 데이터 스크래핑을 시작하는 데 활용할 수 있습니다.
Node.js를 활용한 스크래핑에 대해 더 알고 싶으신가요? Node.js로 웹 스크래핑하기 가이드를 읽어보세요.