자바스크립트를 사용하면 필요할 대 서버에 네트워크 요청을 보내고 새로운 정보를 받아오는 일을 할 수 있습니다.
네트워크 요청은 다음과 같은 경우에 이뤄집니다.
- 주문 정보
- 사용자 정보 읽기
- 서버에서 최신 변경분 가져오기
- etc..
그런데 이 모든 것들은 페이지 새로 고침 없어도 가능합니다.
AJAX(Asynchronous Javascript And XML, 비동기적 Javascript와 XML)라는 용어를 들어보았을 겁니다.
AJAX는 서버에서 추가 정보를 비동기적으로 가져올 수 있게 해주는 포괄적인 기술을 나타내는 용어로, 만들어진지 오래되었습니다.
AJAX 이외에도 서버에 네트워크 요청을 보내고 정보를 받아올 수 있는 방법은 다양합니다.
이번에는 fetch() 메서드에 대해 글을 작성해보았습니다.
fetch() 기본 문법은 다음과 같습니다.
let promise = fetch(url, [options]);
url
- 접근하고자 하는 URL
options
- 선택 매개변수, method나 header 등을 지정할 수 있음.
options에 아무것도 넘기지 않으면 요청은 GET 메서드로 진행되어 url 로부터 콘텐츠가 다운로드 됩니다.
fetch()를 호출하면 브라우저는 네트워크 요청을 보내고 프로미스가 반환됩니다. 반환되는 프로미스는 fetch()를 호출하는 코드에서 사용됩니다.
응답은 대개 두 단계를 거쳐 진행됩니다.
먼저, 서버에서 응답 헤더를 받자마자 fetch 호출 시 받은 promise가 내장 클래스 Response의 인스턴스와 함께 이행 상태가 됩니다.
이 단계는 아직 본문(body)이 도착하기 전이지만, 개발자는 응답 헤더를 보고 요청이 성공적으로 처리되었는지 아닌지를 확인할 수 있습니다.
네트워크 문제나 존재하지 않는 사이트에 접속할 경우같이 HTTP 요청을 보낼 수 없는 상태에선 프로미스는 거부상태가 됩니다.
HTTP 상태는 응답 프로퍼티를 사용해 확인할 수 있습니다.
- status - HTTP 상태 코드 (ex) 200)
- ok - boolean 값, HTTP 상태 코드가 200과 299 사이일 경우 true
let response = await fetch(url);
if(response.ok){ // HTTP 상태 코드가 200~299일 경우
// 응답 본문을 받습니다.
let json = await response.json();
}else{
alert("HTTP-Error: "+response.status);
}
두 번째 단계에선 추가 메서드를 호출해 응답 본문을 받습니다.
response 에는 프로미스를 기반으로 하는 다양한 메서드가 있습니다. 이 메서드들을 사용하면 다양한 형태의 응답 본문을 처리할 수 있습니다.
- response.text() - 응답을 읽고 텍스트를 반환합니다.
- response.json() - 응답을 JSON 형태로 파싱합니다.
- response.formData() - 응답을 FromData 객체 형태로 반환합니다.
- response.blob() - 응답을 Blob(타입이 있는 바이너리 데이터) 형태로 반환합니다.
- response.arrayBuffer() - 응답을 ArrayBuffer(바이너리 데이터를 로우 레벨 형식으로 표현한 것) 형태로 반환합니다.
JSON형태로 받아보는 예시
1)
let url = 'http://domain.com';
let response = await fetch(url);
let result = await response.json(); // 응답 본문을 읽고 JSON 형태로 파싱합니다.
2) await없이 Promise만 사용하기
fetch('url')
.then(response=>response.json())
.then(result=>console.log(result));
3) 응답을 텍스트 형태로 얻기 위해 .json() 대신 response.text()를 사용하기
let response = await fetch('url');
let result = await response.text(); // 응답 본문을 텍스트 형태로 읽습니다.
console.log(result);
4) blob로 받아오기
let response = await fetch('http://domain/com');
let blob = await response.blob(); // 응답을 Blob 객체 형태로 다운로드받습니다.
// 다운로드받은 Blob을 담을 <img>를 만듭니다.
let img = document.createElement('img');
img.style = 'position:fixed;top:10px;left:10px;width:100px';
document.body.append(img);
// 이미지를 화면에 보여줍니다.
img.src = URL.createObjectURL(blob);
setTimeout(() => { // 3초 후 이미지를 숨깁니다.
img.remove();
URL.revokeObjectURL(img.src);
}, 3000);
!! 본문을 읽을 때 사용되는 메서드는 딱 하나만 사용할 수 있습니다.
response.text()를 사용해 응답을 얻었다면 본문의 컨텐츠는 모두 처리 된 상태이기 때문에 response.json()은 동작하지 않습니다.
let text = await response.text(); // 응답 본문이 소비됩니다.
let parsed = await response.json(); // 실패
응답 헤더
응답 헤더는 response.headers 에 맵과 유사한 형태로 저장됩니다.
맵은 아니지만, 맵과 유사한 메서드를 지원합니다.
이 메서드들을 사용하면 헤더 일부만 추출하거나 헤더 전체를 순회할 수 있습니다.
let response = await fetch('http://domain.com');
// 헤더 일부를 추출
console.log(response.headers.get('Content-Type'));
// application/json ; charset=utf-8
// 헤더 전체를 순회
for (let [key, value] of response.headers){
console.log(`${key} = ${value}`);
}
요청 헤더
headers 옵션을 사용하면 fetch에 요청 헤더를 설정할 수 있습니다. headers엔 아래와 같이 다양한 헤더 정보가 담긴 객체를 넘기게 됩니다.
let response = fetch(protectedUrl, {
headers:{
Authentication: 'secret'
}
});
그런데 headers를 사용해 설정할 수 없는 헤더도 있습니다.
참고 : https://fetch.spec.whatwg.org/#forbidden-header-name
POST 요청
GET 이외의 요청을 보내려면 추가 옵션을 사용해야 합니다.
- method - HTTP 메서드( ex) POST)
- body - 요청 본문으로 다음 항목 중 하나여야 합니다.
- 문자열( ex) JSON 문자열)
- FormData 객체 - form/multipart 형태로 데이터를 전송하기 위해 쓰입니다.
- Blob나 BufferSource - 바이너리 데이터 전송을 위해 쓰입니다.
- URLSearchParams - 데이터를 x-www-form-urlencoded 형태로 보내기 위해 쓰이는데, 요즘엔 잘 사용하지 않습니다.
대부분은 JSON을 요청 본문에 실어 보내게 됩니다.
user 객체를 본문에 실어 보내는 예시를 살펴봅시다.
let user = {
name: 'John',
surName: 'Smith'
};
let response = await fetch('url'.{
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(user)
});
let result = await response.json();
console.log(result.message);
POST 요청을 보낼 때 주의할 점은 요청 본문이 문자열일 때 Content-Type 헤더가 text/plain; charset=UTF-8로 기본 설정된다는 점입니다.
하지만 위 예시에선 JSON을 전송하고 있기 때문에 headers에 제대로 된 Content-Type인 application/json을 설정해 주었습니다.
이미지 전송하기
Blob나 BufferSource 객체를 사용하면 fetch로 바이너리 데이터를 전송할 수 있습니다.
예시
async function submit() {
let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
let response = await fetch('/article/fetch/post/image', {
method: 'POST',
body: blob
});
// 전송이 잘 되었다는 응답이 오고 이미지 사이즈가 얼럿창에 출력됩니다.
let result = await response.json();
console.log(result.message);
}
요약
일반적인 fetch 요청은 두 개의 await 호출로 구성됩니다.
let response = await fetch(url, options); // 응답 헤더와 함께 이행됨
let result = await response.json(); // json 본문을 읽음
물론 await 없이도 요청을 보낼 수 있습니다.
fetch(url, options)
.then(resposne => response.json())
.then(result => /*결과 처리*/)
응답 객체의 프로퍼티는 다음과 같습니다.
- response.status - 응답의 HTTP 코드
- response.ok - 응답 상태가 200과 299 사이에 있는 경우 true
- response.headers - 맵과 유사한 형태의 HTTP 헤더
응답 본문을 얻으려면 다음과 같은 메서드들 사용하면 됩니다.
- response.text() - 응답을 읽고 텍스트를 반환합니다.
- response.json() - 응답을 JSON 형태로 파싱합니다.
- response.formData() - 응답을 FromData 객체 형태로 반환합니다.
- response.blob() - 응답을 Blob(타입이 있는 바이너리 데이터) 형태로 반환합니다.
- response.arrayBuffer() - 응답을 ArrayBuffer(바이너리 데이터를 로우 레벨 형식으로 표현한 것) 형태로 반환합니다.
지금까지 배운 fetch 옵션은 다음과 같습니다.
- method - HTTP 메서드
- headers - 요청 헤드가 담긴 객체(제약 사항이 있음)
- body - 보내려는 데이터(요청 본문)로 String이나 FormData, BufferSource, Blob, UrlSearchParams 객체 형태
출처 : https://ko.javascript.info/fetch
'javascript' 카테고리의 다른 글
[Javascript] 문자열 숫자로 변환하기 ParseInt(ParseFloat) vs Number vs Number.parse (0) | 2022.01.17 |
---|---|
[Javascript] 열거형 Enum (0) | 2022.01.14 |
[Javascript] 'try...catch'와 에러 핸들링 (0) | 2022.01.11 |
[Javascript] label(레이블) 구문 (0) | 2022.01.11 |
[Javascript] JSON stringify 사용법, parse 사용법(JSON과 메서드) (0) | 2022.01.10 |
댓글