[새로운 기능] fetch API
- -
이번 포스트에서는 fetch api에 대해서 살펴보자.
fetch는 '가져오다'라는 뜻으로 Request나 Response와 같은 객체를 이용해서 HTTP 파이프라인을 구성하는 요소를 조작하고 원격지에서 정보를 가져오기 위해 사용한다.
원문에 설명된 내용을 쓰다보니 말이 어려워졌는데 가장 쉽게 이해할 수 있는 예로 AJAX를 들 수 있다. 기존에는 AJAX를 Vanilla script에서 사용하기 위해서는 XMLHttpRequest 객체를 이용했는데 너무 번거롭기 때문에 jQuery나 Axios 같은 추가 라이브러리를 활용 했었다.
하지만 fetch API를 사용하면 간단하게 ajax 작업의 처리가 가능하다.
fetch api
fetch API?
fetch API는 Promise 를 기반으로 동작한다.
https://goodteacher.tistory.com/503
따라서 기존에 Promise 기반의 axios를 사용해본 경험이 있다면 아주 이해하기 쉽다.
fetch 함수는 필수 항목인 input과 옵션인 init을 파라미터로 가지며 Response 타입을 갖는 Promise를 반환한다.
function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
요청
input은 필수 속성으로 정보를 가져올 대상의 URL이다. 이 값은 string 형태가 가장 일반적이며 Request 객체를 구성해서 전달할 수도 있다.
init은 옵션 객체로 요청 시 전달할 속성을 설정할 수 있다. 대표적으로 설정하는 init 객체의 속성은 아래와 같다.
- method: GET, POST 등 요청 방식으로 문자열. 기본은 GET
- headers: 요청 header에 대한 설정으로 object
- body: request body를 통해서 전달할 내용으로 string, literal, FormData, ...
응답
fetch api의 promise는 네트워크 장애 및 요청 실패 시(서버가 개입되지 못한 경우) 만 rejected 상태이고 나머지는 fulfilled 상태이다. 만약 404, 500 등 오류를 수신하게 된다면 Response 객체의 ok 속성이 false가 되고 나머지 상황은 true이다.
응답은 통상 2단계를 거쳐 진행된다.
먼저 서버에서 응답 헤더를 받으면 fetch 호출 시 반환받은 Promise 객체가 fulfilled 상태가 되고 이때 Response 객체가 전달된다. Response의 ok 속성으로 작업의 성공 여부를 알게 되는데 만약 상태코드가 2XX 인 경우는 true이고 나머지는 false이다. 하지만 이 상태는 아직 본문(body)을 받지 않은 상태이다.
두 번째 단계는 본문의 내용을 받아오는 단계이다. 전달받은 Response를 통해서는 서버에서 전달해준 결과를 받아올 수 있다. 이때 사용되는 함수로는 body의 타입에 따라서 response.json(), response.text(), response.blob() 등이 있다. 이 메서드들의 리턴 타입은 다시 Promise 타입의 객체이다. 따라서 chaining을 통해 다시 한번 promise를 처리해줘야 한다.
fetch api 활용
다양한 형태로 fetch api를 사용해보자.
get
get 방식은 특별히 신경쓸 내용은 없어보이고 위에서 설명한 api의 기본 동작에 주목하자.
function fetchData(url) {
const content = document.querySelector("#content");
content.innerHTML = "";
const page = document.querySelector("#page").value;
fetch(url + page)
.then((response) => {
console.log(response);
if (response.ok) {
return response.json();
} else {
throw response.status; // 404도 일단 응답은 제대로 받음
}
})
.then((json) => {
json.data.forEach((element) => {
content.innerHTML += `<tr><td>${element.id}</td>
<td>${element.email}</td>
<td>${element.first_name}</td>
<td>${element.last_name}</td>
<td><img src="${element.avatar}"></td>
</tr>`;
});
})
.catch((reason) => alert("요청 실패: " + reason));
}
만약 위 fetchData를 호출하면서 제대로 된 url을 넘겨주면 당연히 바른 결과를 반환한다.
document.querySelector("#btnList").addEventListener("click", function () {
fetchData("https://reqres.in/api/users?page=");
});
하지만 도메인 내에서 존재하지 않는 자원을 요청하면 즉 404인 상태를 만들면 response 객체의 ok 값이 false로 반환되고 던져진 예외에 의해 alert이 출력된다.
document.querySelector("#btn404").addEventListener("click", function () {
fetchData("https://reqres.in/apy");
});
또는 url을 아예 존재하지 않는 서버로 요청해보면 오류는 아래와 같다.
document.querySelector("#btnError").addEventListener("click", function () {
fetchData("https://reqres.out");
});
post
get을 통해서 기본 사용법에 익숙해졌다면 post를 통해서 init 객체의 사용에 대한 예를 살펴보자. 일반적으로 init 객체는 method, headers, body 등에 대한 설정이 이뤄진다. 간단히 아래의 예를 살펴보자.
document.querySelector("#btnRegist1").addEventListener("click", function () {
const user = {
name: document.querySelector("#name").value,
job: document.querySelector("#job").value,
};
const init = {
method: "POST", // 전송 방식: default - get
headers: { // 전송 헤더 설정
"Content-type": "application/json;charset=utf-8",
},
body: JSON.stringify(user), // JSON 문자열 전달
};
postData(init);
});
function postData(init) {
fetch("https://reqres.in/api/users", init)
.then((response) => {
if (response.ok) {
return response.json();
} else {
throw response.status;
}
})
.then((json) => {
alert("추가되었습니다.");
console.log(json);
})
.catch((reason) => alert(reason));
}
post는 데이터를 body를 통해서 전달하는데 json 형태나 parameter로 보낼 수 있다. 보내는 데이터의 형태에 따라 headers의 content-type 설정이 다르니 주의 하자.
document.querySelector("#btnRegist2").addEventListener("click", function () {
const user = {
name: document.querySelector("#name").value,
job: document.querySelector("#job").value,
};
const init = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `name=${user.name}&job=${user.job}`, // parameter로 보낼 때
};
postData(init);
});
참고로 Servlet에서는 위 요청을 처리할 때 parameter로 전달 받았을 때는 request.getParameter로 처리하고 json으로 받았을 때는 request.getInputStream()을 이용해서 stream을 생성 한 후 문자열을 파싱해서 처리해야 한다. 스프링에서는 각각 @RequestParam, @RequestBody로 처리한다.
이제까지 간단히 fetch api 사용법에 대해서 살펴보았다. 개인적인 생각으로는 전역의 오류 처리나 전역 객체를 통한 공통 특성 관리 등이 없어서 좀 불편했다. 당분간은 axios를 주로 사용할 것 같다.
'JavaScript' 카테고리의 다른 글
[새로운 기능] Proxy (0) | 2022.07.01 |
---|---|
[새로운 기능] async와 await (0) | 2022.06.02 |
[새로운 기능] Promise_03 Promise 기본 사용법 (0) | 2022.05.02 |
[새로운 기능] Promise_02 Promise 기본 사용법 (0) | 2022.05.02 |
[새로운 기능] Promise_01 Callback hell과 Promise (0) | 2022.05.02 |
소중한 공감 감사합니다