프론트엔드 개발/JavaScript

자바스크립트) Ajax (XMLHttpRequest , fetch)

Ella Seon 2023. 7. 19. 11:50

0. Ajax (Asynchronous JavaScript and XML)

- 자바스크립트를 사용하여 1) 브라우저가 2) 서버에게 비동기 방식으로 데이터를 요청하고, 서버가 응답한 데이터를 수신하여 웹페이지를 동적으로 갱신하는 프로그래밍 방식

- 브라우저가 가지고 있는 호스트객체 Web API 인 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고 페이지의 일부만을 로드하는 기법 (XMLHttpRequest는 HTTP 비동기 통신을 위한 메서드와 프로퍼티를 제공한다.)

=> 즉, 자바스크립트를 이용한 비동기 통신이며, 클라이언트와 서버간에 XML 데이터를 주고 받는 방식

🔸Ajax를 사용하면 기존 방식과 어떤 차이가 있을까?

- Ajax 가 등장하기 이전에는 웹브라우저가 어떤 정보를 요청하면, 서버는 해당 정보를 포함한 페이지 전체를 전달해주었다. 웹 브라우저는 서버로부터 받은 마크업 데이터(HTML)를 브라우저 창에 렌더링하는 일을 했다. 이 방법은 브라우저는 매번 똑같은 레이아웃의 페이지를 처음부터 다시 렌더링해야 했고 서버 역시 매번 같은 HTML 파일 생성해야 해서 서로 부담이 되었다. Ajax 기술을 사용하지 않는 사이트가 특유의 깜빡거림 현상이 생기는 이유가 매번 페이지를 싹 지우고 처음부터 다시 모든 것을 그려내기 때문이다. 

 

Ajax 를 사용하게 되면, 

1) 변경할 부분을 갱신하는데 필요한 데이터만 서버로부터 전송받기 때문에 불필요한 데이터 통신이 발생하지 않는다.

2) 변경할 필요가 없는 부분은 다시 렌더링하지 않는다. 따라서 화면이 순간적으로 깜박이는 현상이 발생하지 않는다.

3) 클라이언트와 서버와의 통신이 비동기 방식으로 동작하기 때문에 서버에게 요청을 보낸 이후 블로킹이 발생하지 않는다. 

🔸Ajax 로 HTTP 요청을 보내기 위해서는 어떤 방법을 사용할까?

1) XMLHttpRequest

- 브라우저는 주소창이나 HTML의 form 태그 또는 a 태그를 통해 HTTP 요청 전송 기능을 기본 제공한다.
- 자바스크립트를 사용하여 HTTP 요청을 전송하려면 XMLHttpRequest 객체를 사용합니다
- Web API인 XMLHttpRequest 객체는 ① HTTP 요청 전송② HTTP 응답 수신을 위한 다양한 메서드와 프로퍼티를 제공합니다

 

코드 보려면 아래 더보기 펼치기

더보기

🔸HTTP GET 요청 전송

// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// HTTP 요청 초기화
xhr.open("GET", "/users");

// HTTP 요청 헤더 설정
// 클라이언트가 서버로 전송할 데이터의 MIME 타입 지정: json
xhr.setRequestHeader("content-type", "application/json");

// HTTP 요청 전송
xhr.send();

 

🔸HTTP POST 요청 전송

// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// HTTP 요청 초기화
xhr.open("POST", "/users");

// HTTP 요청 헤더 설정
// 클라이언트가 서버로 전송할 데이터의 MIME 타입 지정: json
xhr.setRequestHeader("content-type", "application/json");

// HTTP 요청 전송
xhr.send(JSON.stringify({ id: 1, content: "HTML", completed: false }));

 

🔸HTTP 응답처리

// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// HTTP 요청 초기화
// https://jsonplaceholder.typicode.com은 Fake REST API를 제공하는 서비스다.
xhr.open("GET", "https://jsonplaceholder.typicode.com/todos/1");

// HTTP 요청 전송
xhr.send();

// load 이벤트는 HTTP 요청이 성공적으로 완료된 경우 발생한다.
xhr.onload = () => {
  if (xhr.status === 200) {
    console.log(JSON.parse(xhr.response));
    // {userId: 1, id: 1, title: "delectus aut autem", completed: false}
  } else {
    console.error("Error", xhr.status, xhr.statusText);
  }
};

 

2) Fetch

fetch cheatsheet : https://devhints.io/js-fetch

- fetch 함수는 XMLHttpRequest 객체와 마찬가지로 HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 Web API다.
- fetch 함수는 XMLHttpRequest 객체보다 사용법이 간단하고 프로미스를 지원하기 때문에 비동기 처리를 위한 콜백 패턴의 단점에서 자유롭다.
- fetch 함수는 비교적 최근에 추가된 Web API로서 인터넷 익스플로러를 제외한 대부분의 모던 브라우저에서 제공한다.
- fetch 함수에는 HTTP 요청을 전송할 URL과 HTTP 요청 메서드, HTTP 요청 헤더, 페이로드 등을 설정한 객체를 전달한다.

const promise = fetch(url [, options])

fetch 함수는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환한다.

fetch("https://jsonplaceholder.typicode.com/todos/1").then((response) =>
  console.log(response)
);

Response.prototype에는 Response 객체에 포함되어 있는 HTTP 응답 몸체(response.body)를 위한 다양한 메서드를 제공한다.
예를 들어, fetch 함수로 요청을 보내고 반환된 프로미스를 처리하는 경우, 해당 프로미스의 결과로 Response 객체를 얻을 수 있다. 이 Response 객체에는 HTTP 응답에 대한 여러 정보와 몸체(body)가 포함됩니다.
Response 객체의 몸체는 HTTP 응답의 실제 데이터를 포함하고 있다. 이 데이터를 사용하기 위해 Response.prototype.json 메서드를 사용할 수 있다. 이 메서드는 HTTP 응답의 몸체를 JSON 형식으로 역직렬화(deserialize)하여 JavaScript 객체로 변환한다.
따라서, MIME 타입이 "application/json"인 경우, 즉 HTTP 응답 몸체가 JSON 형식인 경우, Response.prototype.json 메서드를 사용하여 해당 JSON 데이터를 JavaScript 객체로 변환할 수 있다. 이를 통해 데이터를 쉽게 읽고 조작할 수 있다.


=> fetch 함수로 요청을 보내고 반환된 Response 객체의 json 메서드를 사용하면, HTTP 응답의 JSON 데이터를 JavaScript 객체로 쉽게 변환할 수 있다.

fetch('https://example.com/api/data')
  .then(response => response.json())
  .then(data => {
    // JSON 데이터를 사용하는 작업 수행
    console.log(data);
  })
  .catch(error => {
    // 오류 처리
    console.error(error);
  });

1) 응답 몸체를 텍스트로 변환: Response.prototype.json 메서드는 먼저 응답 몸체를 텍스트 형식으로 변환한다. 이를 위해 내부적으로 response.text() 메서드를 호출. 이 작업은 Promise를 반환함.
2) 텍스트를 JSON으로 파싱: 텍스트로 변환된 응답 몸체를 JSON으로 파싱하여 JavaScript 객체로 변환한다. 이 단계에서도 Promise를 반환함.

 

※ MIME(Multipurpose Internet Mail Extensions) 타입 : 인터넷에서 데이터를 전송하는 데 사용되는 데이터 형식을 나타내는 라벨, MIME 타입은 주로 웹에서 파일의 종류를 지정하기 위해 사용되며, 데이터의 형식을 나타내는 문자열로 표현

 

🔸fetch 로 crud 하는 코드 보고싶으면 아래 더보기 누르기

더보기
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>
  <body>
    <pre></pre>
    <script>
      const render = (res) => {
        console.log(res);
        const result = JSON.stringify(res);
        document.querySelector("pre").innerHTML = `<b>${result}</b>`;
      };

      const request = {
        // get 메서드
        get(url) {
          return fetch(url);
        },
        // post 메서드
        post(url, payload) {
          return fetch(url, {
            method: "POST",
            headers: { "content-Type": "application/json" },
            body: JSON.stringify(payload),
          });
        },
        // patch 메서드
        patch(url, payload) {
          return fetch(url, {
            method: "PATCH",
            headers: { "content-Type": "application/json" },
            body: JSON.stringify(payload),
          });
        },
        // delete 메서드
        delete(url) {
          return fetch(url, { method: "DELETE" });
        },
      };

      // get
      request
        .get("https://jsonplaceholder.typicode.com/todos/1")
        .then((response) => response.json())
        .then((todos) => render(todos))
        .catch((err) => console.log(err));

      // post
      request
        .post("https://jsonplaceholder.typicode.com/todos", {
          userId: 1,
          title: "JavaScript",
          completed: false,
        })
        .then((response) => response.json())
        .then((todos) => console.log(todos))
        .catch((err) => console.log(err));

      // patch
      request
        .patch("https://jsonplaceholder.typicode.com/todos/1", {
          completed: true,
        })
        .then((response) => response.json())
        .then((todos) => console.log(todos))
        .catch((err) => console.log(err));

      // delete
      request
        .delete("https://jsonplaceholder.typicode.com/todos/1")
        .then((response) => response.json())
        .then((todos) => console.log(todos))
        .catch((err) => console.log(err));
    </script>
  </body>
</html>

🔸XMLHttpRequest 와 fetch 메서드의 차이

- fetch 메서드 또한 XMLHttpRequest 처럼 Ajax 통신을 위해 사용됨.
- 하지만 fetch 메서드는 Promise를 기반으로 구성되어 있어서 더 간편하게 사용할 수 있다는 차이점이 있다.
- Promise의 후속 처리 메서드 .then() .catch() . finally() 등을 사용하여 코드를 작성할 수 있다.