[JS๐Ÿฃ] ๋น„๋™๊ธฐ ํ†ต์‹  ์ดํ•ดํ•˜๊ธฐ(XHR๊ณผ Fetch API)

๊น€๋‹ค์Šฌยท2021๋…„ 8์›” 26์ผ
0

Java Script ์™„์ „ ์ •๋ณต

๋ชฉ๋ก ๋ณด๊ธฐ
4/5
post-thumbnail

โŒ›๏ธ ๋น„๋™๊ธฐ ํ†ต์‹  ์ด์ „์˜ ์„œ๋ฒ„ ํ†ต์‹ 

form ํƒœ๊ทธ

๋ธŒ๋ผ์šฐ์ €์—์„œ ํผ์„ ์ฑ„์šฐ๊ณ  ์ด๋ฅผ ์›น ์„œ๋ฒ„๋กœ ์ œ์ถœ(submit)ํ•˜๋ฉด ์›น ์„œ๋ฒ„๋Š” ์š”์ฒญ๋œ ๋‚ด์šฉ์— ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ ์ƒˆ๋กœ์šด ์›นํŽ˜์ด์ง€๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‘๋‹ต์œผ๋กœ ๋˜๋Œ๋ ค์ค€๋‹ค.

๋™๊ธฐ ํ†ต์‹ ์˜ ๋‹จ์ 

  • ์ „์ฒด ํŽ˜์ด์ง€๋ฅผ reloadํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„์˜ ๋ถ€ํ•˜๊ฐ€ ์ปค์ง€๊ณ , ์‹œ๊ฐ„๋„ ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค.
  • ๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ํŽ˜์ด์ง€๊ฐ€ reload๋˜๋Š” ๋™์•ˆ์—๋Š” ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋‹ค.

๐Ÿ–ฅ ๋น„๋™๊ธฐ ํ†ต์‹ 

์š”์ฒญ์„ ๋ณด๋‚ธ ํ›„ ์‘๋‹ต๊ณผ๋Š” ์ƒ๊ด€์—†์ด ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

๐Ÿ“Œ AJAX

๋น ๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๋™์ ์ธ ์›น ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๊ฐœ๋ฐœ ๊ธฐ๋ฒ•์˜ ํ•˜๋‚˜

  • ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ reloadํ•˜์ง€ ์•Š๊ณ ์„œ ์ˆ˜ํ–‰๋˜๋Š” ๋น„๋™๊ธฐ์„ฑ

  • ์ฆ‰, ์‚ฌ์šฉ์ž์˜ event๊ฐ€ ์žˆ์œผ๋ฉด ์ „์ฒด ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹Œ ์ผ๋ถ€๋ถ„๋งŒ ์—…๋ฐ์ดํŠธ

  • ์„œ๋ฒ„์™€์˜ ํ†ต์‹ ์„ ์œ„ํ•ด XMLHttpRequest ๊ฐ์ฒด ์‚ฌ์šฉ

  • JSON, XML, HTML ๊ทธ๋ฆฌ๊ณ  ์ผ๋ฐ˜ ํ…์ŠคํŠธ ํ˜•์‹ ๋“ฑ์„ ํฌํ•จํ•œ ๋‹ค์–‘ํ•œ ํฌ๋งท์„ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค

AJAX๋ฅผ ์ด์šฉํ•œ ์›น ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์›น ์„œ๋ฒ„์™€ ํ†ต์‹ ์„ ํ•˜๊ฒŒ ๋œ๋‹ค.
๋”ฐ๋ผ์„œ, ์‚ฌ์šฉ์ž์˜ ๋™์ž‘์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ๋„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ง€์†ํ•ด์„œ ์„œ๋ฒ„์™€ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.


โญ๏ธ XMLHttpRequest(XHR)

  • AJAX์˜ ๊ฐ€์žฅ ํ•ต์‹ฌ์ ์ธ ๊ตฌ์„ฑ ์š”์†Œ
  • ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๊ณ„์†ํ•ด์„œ ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ์—ญํ• 

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ์ฝ”๋“œ ์‹ค์Šต

<html>
  <head> </head>
  <body>
    <button id="ajaxButton" type="button">XHR Test</button>
    <h3 id="testText"></h3>
    <script>
      (function () {
        let httpRequest;
        document
          .getElementById("ajaxButton")
          .addEventListener("click", makeRequest);

        function makeRequest() {
          // XMLHttpRequest ๊ฐ์ฒด ์ƒ์„ฑ
          // readyState : 0
          httpRequest = new XMLHttpRequest();

          if (!httpRequest) {
            alert("XMLHttp ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์–ด์š”");
            return false;
          }
          // onreadystatechange ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ ์„ ์–ธ
          httpRequest.onreadystatechange = alertContents;
          // open ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์š”์ฒญํ•  method, url ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ์„ค์ •
          // readyState : 1
          httpRequest.open("GET", "test.html");
          // send ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ „์†กํ•  ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์š”์ฒญ (POST)
          // readyState : 2 -> 3 -> 4
          httpRequest.send();
        }

        function alertContents() {
          // XHR ๊ฐ์ฒด์˜ ์ƒํƒœ ํ™•์ธ
          if (httpRequest.readyState === httpRequest.DONE) {
            // ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋œ ์‘๋‹ต์ธ์ง€ ๊ฒ€์‚ฌ
            if (httpRequest.status === 200) {
              document.getElementById("testText").innerHTML =
                httpRequest.responseText;
            } else {
              alert(`${httpRequest.status}์—๋Ÿฌ request์— ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์š”`);
            }
          }
        }
      })();
    </script>
  </body>
</html>

onreadystatechange

  • ์„œ๋ฒ„๋กœ ๋ณด๋‚ธ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ๋ฐ›์•˜์„ ๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ•  ๊ฒƒ์ธ์ง€ ์ง€์ •
  • ํŠน์ • ํ•จ์ˆ˜๋ฅผ ํ• ๋‹นํ•˜๋ฉด ์š”์ฒญ์— ๋Œ€ํ•œ ์ƒํƒœ๊ฐ€ ๋ณ€ํ™”ํ•  ๋•Œ ํŠน์ •ํ•จ์ˆ˜๊ฐ€ ๋ถˆ๋ฆผ

readyState

  • ๊ฐ์ฒด์˜ ์ƒํƒœ ๋ฐ˜ํ™˜

    • UNSENT(0): XMLHttpRequest ๊ฐ์ฒด์˜ ์ƒ์„ฑ๋œ ์ƒํƒœ
    • OPEND(1): ์˜ˆ์ œ์—์„œ๋„ ์žˆ์ง€๋งŒย open(~)๋ฉ”์†Œ๋“œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์‹คํ–‰๋œ ์ƒํƒœ
    • HEADERS_RECEIVED(2): ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์ด ๋„์ฐฉํ•œ ์ƒํƒœ
    • LOADING(3): ์š”์ฒญํ–ˆ๋˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์ฒ˜๋ฆฌ์ค‘(downloading)์ธ ์ƒํƒœ
    • DONE(4): ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ(complete)๋œ ์ƒํƒœ
  • readyState์— ๊ด€ํ•œ ์ •๋ณด

    XMLHttpRequest.readyState - Web APIs | MDN

Status

  • ์š”์ฒญ์ด ์™„๋ฃŒ๋œ ํ›„, http ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜

    • 200: SUCCESS(์š”์ฒญ ์„ฑ๊ณต)
    • 201: CREATED(์š”์ฒญ ์„ฑ๊ณต & ์ƒˆ๋กœ์šด ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ)
    • 404: NOT FOUND(์š”์ฒญ๋ฐ›์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ)
  • HTTP ์ƒํƒœ ์ฝ”๋“œ

    HTTP ์ƒํƒœ ์ฝ”๋“œ - HTTP | MDN

XHR์€ addEventListener์™€ ๋น„์Šทํ•˜๊ฒŒ Event ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.
์‘๋‹ต์„ ๋ฐ›์„ ๋•Œ State(์ƒํƒœ๊ฐ’)์„ ๋ฐ”๊พธ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚ค๊ณ ,
์ด๋ฅผ onreadystatechange๋ฅผ ํ†ตํ•ด ๊ฐ์ง€ํ•œ๋‹ค.


ES6์—์„œ XHR๋ณด๋‹ค ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•œ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•œ Fetch API๊ฐ€ ๋“ฑ์žฅํ•œ๋‹ค.

๐Ÿ”ฅ Fetch API

  • XMLHttpRequest์„ ๋Œ€์ฒดํ•˜๋ฉฐ ๋น„๋™๊ธฐ http ์š”์ฒญ์„ ์ข€ ๋” ์“ฐ๊ธฐ ํŽธํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” API

  • fetch() ํ•จ์ˆ˜๋Š” ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ URL, ๋‘๋ฒˆ์งธ ์ธ์ž๋กœ ์˜ต์…˜ ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š”๋‹ค.

    • ๋””ํดํŠธ๋กœ GET ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘, ์˜ต์…˜ ์ธ์ž ๋ถˆํ•„์š”

    • POST ๋ฐฉ์‹ ์ด์šฉ ์‹œ headers, body ๋“ฑ์˜ ์˜ต์…˜ ํ•„์š”

      Using Fetch - Web API | MDN

  • Promise ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ fetch์˜ ๊ธฐ๋ณธ ์‘๋‹ต ๊ฒฐ๊ณผ๋Š” Reponse ๊ฐ์ฒด์ด๋‹ค.

  • Response ๊ฐ์ฒด๋ฅผ ์–ป์€ ๋’ค์—” ์‘๋‹ต์„ json์œผ๋กœ ๋ฐ”๊พธ๊ฑฐ๋‚˜ text๋กœ ๋ฐ”๊พธ๋Š” ๋“ฑ์˜ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

    • json() : response์˜ body๋ฅผ ๋‹ค ์ฝ๊ณ  ์ด๋ฅผ promise ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜
    • ๋ณธ๋ฌธ์„ ์ฝ์„ ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ๋”ฑ ํ•˜๋‚˜๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • HTTP error๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ reject ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— response์˜ status code๋‚˜ ok ์ฒดํฌ ํ•„์š”

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ์ฝ”๋“œ ์‹ค์Šต

<html>
  <head> </head>
  <body>
    <button id="fetchButton" type="button" onclick="fetchPage('test.html')">
      Fetch Test
    </button>
    <h3 id="testText"></h3>
    <script>
      function fetchPage(fileName) {
        fetch(fileName)
          // fetch์˜ ๊ธฐ๋ณธ ์‘๋‹ต ๊ฒฐ๊ณผ๋Š” response ๊ฐ์ฒด
          .then((response) => {
            // response.ok๋Š” status๊ฐ€ 200~299์‚ฌ์ด์ธ ๊ฒฝ์šฐ true
            if (response.ok) {
							// ์‘๋‹ต์„ text ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜
              return response.text();
            }
            throw new Error(`${response.status} ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ–ˆ์–ด์š”!`);
          })
          .then((text) => {
            document.getElementById("testText").innerHTML = text;
          })
          .catch((e) => {
            alert(e);
          });
      }
    </script>
  </body>
</html>

๐Ÿš€ ๊ฒฐ๋ก ์ ์œผ๋กœ

  • Fetch API๋Š” Promise ๊ธฐ๋ฐ˜์œผ๋กœ async, await์˜ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ ์ง๊ด€์ ์ด๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹๋‹ค
  • ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ import ์—†์ด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค
  • ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์œ„ํ•œ Fetch Polyfill ์ง€์›

์ฐธ๊ณ  ์‚ฌ์ดํŠธ

https://velog.io/@shinychan95/42
https://kangaroo-dev.tistory.com/8
https://milkye.tistory.com/266
https://velog.io/@ldaehi0205/ajax-fetch-xhr-๋น„๋™๊ธฐํ†ต์‹ -์ดํ•ดํ•˜๊ธฐ https://developer.mozilla.org/ko/docs/Web/Guide/AJAX/GettingStarted#1.eb.8b.a8.ea.b3.84.e2.80.93say.22please.21.22_or_how_to_make_an_http_request
https://deeplify.dev/front-end/js/xml-http-requesthttp://tcpschool.com/ajax/ajax_intro_works https://developer.mozilla.org/ko/docs/Web/Guide/AJAX/Getting_Started

profile
์ธ์ƒ์€ ์šฉ๊ธฐ์˜ ์–‘์— ๋”ฐ๋ผ ์ค„์–ด๋“ค๊ฑฐ๋‚˜, ๋Š˜์–ด๋‚œ๋‹ค

0๊ฐœ์˜ ๋Œ“๊ธ€