JS. XML , FETCH 요청

MJ·2023년 6월 23일
0
post-thumbnail

XML

  • 서버로 부터 데이터를 받아오기 위해 사용하는 JS 객체입니다.

  • 해당 방식은 프로미스를 지원하지 않아서 수많은 콜백을 받게 되며 현재는
    거의 사용하지 않는 방식입니다. (FETCH 로 대체 되었음)


1.1 XML 사용

  • 데이터 정보를 요청해서 받아올 API 사이트는 스와피 사이트에서 사람에 관련된
    people 속성을 사용의 예시로 들어보겠습니다.
const req = new XMLHttpRequest();
// XRH 객체 생성 

req.open("GET", "https://swapi.dev/api/people/1");
// 요청을 전송할 방식과 요청할 서버 URL을 작성해서 요청을 준비한다.
req.send();
// open 에서 기재한 URL 서버에 API 응답을 요청합니다.


/* 요청이 성공한 경우 onload의 구문이 실행 */
req.onload = function(){
  console.log("SUCCESS")
  console.log(this)
}

/* 요청이 실패한 경우 onerror의 구문이 실행 */
req.onerror = function(){
  console.log('ERROR');
  console.log(this)
}

URL 서버로부터 JSON 응답을 받아왔으며, 데이터를 JS 객체로 변환해서 접근할 수 있다.


1.2 JSON 데이터 -> JS 객체로 변환

const req = new XMLHttpRequest();

req.open("GET", "https://swapi.dev/api/people/1");
req.send();

req.onload = function () {
  console.log("SUCCESS")
  const data = JSON.parse(this.responseText)
  /* JSON 데이터로 수신된 데이터를 JS 객체로 변환해서 접근 */
  console.log(data, this.responseURL, this.status)
}

req.onerror = function () {
  console.log('ERROR')**텍스트**;
  console.log(this)
}

JS 객체로 변환해서 수신된 데이터를 확인



FETCH

  • 비동기함수, 프로미스를 지원하기에 XML 요청 대신 이 방식을 사용합니다.

  • FETCH 함수를 호출하면 브라우저는 네트워크 요청을 보내고 프라미스를 반환한다.


/* 기본 문법 */
let promise = fetch(url, [options])


/*
url		: 접근하고자 하는 URL
option	: 선택 매개변수, method나 header등을 지정할 수 있음
		: 옵션이 공란인경우 기본 값은 GET 메서드로 요청을 한다

*/

동작 원리

  • FETCH 함수를 호출하면 서버에서 응답 헤더를 받자마자 FETCH 함수 호출 시 반환받은
    promise가 내장 클래스 Respone의 인스턴스와 함께 이행 상태가 됩니다.

  • 이 단계는 아직 본문(body)이 도착하기 이전인 상태라 JSON 응답 같은 데이터는
    도착하지 못하고, 요청에 대한 성공과 실패 유무만 확인할 수 있다.

HTTP 상태는 응답 프로퍼티를 사용해 확인할 수 있다.
status : HTTP 상태코드
ok : boolean 값, 상태 코드가 200~299 사이인 경우에는 성공(true)


2.0 FETCH 메서드

  • FETCH 함수를 호출하고 가져온 데이터는 본문이 도착하기 이전이라 JSON에 관한
    데이터를 확인하기 어렵습니다. JSON 데이터를 확인하려면 추가 메서드를 호출해서
    정보를 받아올 수 있습니다.
.text()		: 응답을 읽고 텍스트를 반환합니다,
.json()		: 응답을 JSON 형태로 파싱합니다,
.formData()	: 응답을 FormData 객체 형태로 반환합니다. 
.blob()		: 응답을 Blob(타입이 있는 바이너리 데이터) 형태로 반환합니다.
.arrayBuffer()	: 응답을 ArrayBuffer(바이너리 데이터를 로우 레벨 형식으로 표현한 것) 형태로 반환합니다.

이 외에도 response.body가 있는데, ReadableStream 객체인 response.body를 사용하면
응답 본문을 청크 단위로 읽을 수 있습니다. 

주의 사항

response.text() response.json() 둘 중 하나의 메서드만 사용가능
두 개의 메서드 모두 본문(JSON응답)을 읽을 때 사용되는 메서드로 두 메서드중 하나를
사용하면 본문의 내용을 모두 처리했기 때문에, 이후의 메서드는 에러가 발생한다.


2.1 FETCH 사용

/* FETCH 사용법 */

//1. fetch 함수를 호출해서 URL 전달
fetch("https://swapi.dev/api/people/1");

fetch 함수를 사용하면 promise가 생성된다.


// promise를 반환하기에 .then 또는 .catch 구문을 사용할 수 있다.
fetch("https://swapi.dev/api/people/1")
  .then(res => {
    console.log("RESOLVED!\n", res)
  })
  .catch(e => {
    console.log("ERROR!\n", e)
  })

서버로부터 응답은 받았지만 우리가 확인해야할 JSON 응답(responeText)이 보이지 않는다.
그 이유는 Fetch가 헤더를 수신하는 즉시 프로미스가 처리되는데 이 프로미스가 처리되기
이전에 생성되어서 확인할 수 없다. (데이터, 텍스트, JSON 응답 등)


2.2 json()을 사용해서 JSON 응답 받기

/* json() 메서드를 사용하면 반환된 프로미스에 대한 JSON 응답을 확인할 수 있다. */


fetch("https://swapi.dev/api/people/1")
  .then(res => {
    console.log("RESOLVED!\n", res)
  	return res.json();
  })
	.then((data) => { 
  	console.log(data);
})
  .catch(e => {
    console.log("ERROR!\n", e)
  })


/* 
동작 원리

1. fetch 함수 호출 => url 전달 (서버에 요청)
2. 프로미스가 처리되고 반환 값에 대해서 then or catch 구문으로 전달
3. 성공했다면 then 구문으로 실행하고, 반환된 프로미스 객체를 res에 저장하여 출력합니다.
4. 프로미스 처리 과정이 너무 빠르게 진행되어 손실된 데이터가 존재합니다.
   이 데이터들은 .json() 메서드를 사용해서 손실된 데이터에 관한 응답을 반환 받을 수 있습니다.
  .json() 메서드 또한 promise를 반환하기에 해당 구문을 return 하고 반환된 값을 다음 .then
   구문에서 확인할 수 있습니다.
    
5. .json()로 부터 반환받은 값을 data 객체에 저장하고 출력합니다.
* 이제 본문에서 손실된 json응답과 데이터들을 확인할 수 있다. *
*/

json() 메서드를 사용하면 기존에 받지못한 응답을 받은 것을 확인할 수 있다.


2.3 2 번째 이상의 요청이 필요한 경우

  • 연속적인 요청이 두 번 이상 필요한 경우에는 처음 요청이 성공하고 난 이후에 다시
    함수를 호출해서 연속적인 요청을 할 수 있습니다.
/* 첫 번째 요청 이후에 연속적인 요청이 필요한 경우 */ 


fetch("https://swapi.dev/api/people/1")
  .then(res => {
    console.log("RESOLVED!\n", res)
    return res.json();
  })
  .then((data) => {
    console.log(data);
    return fetch("https://swapi.dev/api/people/2")	// 1.
  })
  .then((res) => {	
    console.log("SECOND RESOLVED!\n", res)
    return res.json();
  })
  .then((data) => {
    console.log(data);
  })
  .catch(e => {
    console.log("ERROR!\n", e)
  })


/*
1. 첫 번쨰 요청이 끝난 다음 정보가 필요한 URL을 fetch 함수를 사용해서 호출하고 그 값을
   반환하면 됩니다. 그럼 다음 .then 구문에서 반환된 객체 값을 토대로 정보를 출력할 수 있습니다.
*/

2.4 비동기 함수를 사용해서 코드 리팩터링

/* 비동기 함수를 사용해서 .then .catch 구문 사용이 필요 없이 코드량을 간소화 할 수 있다 */

const loadStarwarzPeople = async (url) => {
  try {
    const res = await fetch(`${url}/1`);
    const data = await res.json();
    console.log(data);

    const res2 = await fetch(`${url}/2`);
    const data2 = await res2.json();
    console.log(data2);
  } catch (e) {
    console.log('ERROR\n', e)
  }
}

loadStarwarzPeople('https://swapi.dev/api/people')


/* 
동작 원리
1. 스타워즈 함수 호출
2. url 매개변수에 인자 저장
3. 비동기함수 (async)를 사용해서 fetch 함수를 호출하고 반환값을 res 변수에 저장합니다.
await 키워드로 인해 현재 함수의 프로미스가 완료되기 전 까지는 다음 구문을 실행하지 않습니다.

4. 전달받은 반환 값을 가지고 json() 메서드를 호출해서 json 응답을 가져와 출력합니다.
5. 첫 번째 요청이 성공적이면 두 번째 요청으로 넘어가서 반복수행 합니다.
6. 비동기 함수에서도 오류가 발생할 수 있으므로, try..catch 구문을 사용해서 오류를 전달합니다.
*/

오류가 발생하지 않으면 정상적으로 구문이 실행되고 오류(잘못된주소)가 발생되면
catch 구문으로 넘어가서 에러핸들링을 합니다.


2.5 FETCH 사용 예시(ko.javascript)

/* 깃헙 URL 을 이용해서 ID 정보 받아오기 */

let response = async function (url) {
  const respone = await fetch(url);

  if (respone.ok) {
    let json = await respone.json();
    console.log(json[0].author);
  } else {
    alert("HTTP-Error: " + respone.status);
  }
}

response('https://api.github.com/repos/javascript-tutorial/ko.javascript.info/commits');


/* 
동작 원리

1. 함수 호출 및 인수 전달
2. 비동기 함수 호출, 함수 내부에서 fetch 함수를 호출해 매개변수를 GET 방식으로 데이터 요청
3. 요청이 성공적이라면 if문 수행 (ok 프로퍼티는 상태코드가 200~299 사이인 경우 ture 값을 반환 합니다)
4. 응답받은 데이터에 대한 본문내용 (JSON)을 변수에 저장한다.
5. 가져온 본문 내용에 [0]번째 인덱스의 author 프로퍼티를 출력합니다. 
   응답받은 데이터는 30개의 배열로 구성되어 있습니다.
   await을 사용하지 않으면 promise의 이행상태도 같이 나오기에 json 응답을 받을 때도
   await를 사용 해야 한다.
*/

ID만 따로 보고 싶다면 json[0].author.login 프로퍼티에 접근하면 됩니다.

profile
프론트엔드 개발자가 되기 위한 학습 과정을 정리하는 블로그

0개의 댓글