DevYoon

[JS] 비동기 프로그래밍 & Ajax 본문

언어/Javascript

[JS] 비동기 프로그래밍 & Ajax

gimewn 2022. 7. 24. 23:43

비동기 프로그래밍 💻 & Ajax

Contents

1️⃣ 비동기 프로그래밍

​ 🔥 동기와 비동기의 차이점

​ 🔥 이벤트 루프 & 태스크 큐

​ 🔥 마이크로태스크 큐

2️⃣ Ajax

​ 🔥 Ajax란?

​ 🔥 Ajax 사용 시 기존 방식과의 차이

​ 🔥 JSON이란?

​ 🔥 JSON이 제공하는 정적 프로토타입 메서드

​ 🔥 Ajax로 HTTP 요청을 보내기 위해 사용할 수 있는 방법

1️⃣ 비동기 프로그래밍

🔥 동기와 비동기의 차이점

img

✏️ 자바스크립트는 기본적으로 싱글 스레드 엔진 기반 ➡️ 동기 처리되어 작성한 순서대로 수행

*️⃣ 프로세스 : 실행되고 있는 컴퓨터 프로그램

*️⃣ 스레드 : 프로세스 내에서 실행되는 흐름의 단위, 스레드를 여러 개 생성 ➡️ 여러 작업 동시 처리 가능

*️⃣ 싱글 스레드 : 하나의 프로세스가 한 번에 하나의 일만 처리

*️⃣ 멀티 스레드 : 하나의 응용프로그램을 여러 개의 스레드로 구성 ➡️ 각 스레드에서 하나의 작업을 처리

❓ 왜 자바스크립트는 멀티 스레드가 아닌 싱글 스레드를 선택했을까?

​ ➡️ 자바스크립트의 탄생 계기 : 웹페이지의 보조적인 기능을 수행하기 위해 브라우저에서 동작하는

경량 프로그래밍 언어를 도입하기로 결정하여 만들어짐

​ 멀티 스레드 모델은 프로그래밍 난이도가 높음 (동시성에 신경써야 함)

​ 싱글 스레드는 멀티 스레드 환경에서 발생할만한 복잡한 시나리오 ❌

❓ 소요가 큰 작업이 수행된다면...?

➡️ 선행 여부와 관계없이 수행할 수 있는 기능이 바로 비동기처리

⭐ 동기 (Synchronous)

  • 서버에 요청을 보냈을 때 응답이 돌아와야 다음 동작 수행 가능
  • 요청에 대한 결과가 그 자리에서 주어져야 함 ➡️ 요청에 대한 결과가 동시에 일어난다 ➡️ { 동기 }
  • 설계가 매우 간단하고 직관적

⭐ 비동기 (Asynchronous)

  • 서버에 요청을 보냈을 때 응답 여부에 관계없이 다음 동작 수행 가능
  • 요청에 대한 결과가 동시에 일어나지 않는다 ➡️ { 비동기 }
  • 동기식보다 설계가 복잡

✏️ 동기는 서버에 요청을 보냈을 때 응답이 돌아와야 다음 동작이 수행 가능하고, 비동기는 응답 여부에 관계 없이 다음 동작을 수행할 수 있다.

🤷 자바스크립트는 싱글 스레드인데, 대체 어떻게 비동기가 가능한 거야⁉️

🧙 그건 바로 ⭐ 이벤트 루프 ⭐ 가 있기 때문이지

🔥 이벤트 루프 (Event Loop) & 태스크 큐 (Task Queue)

img

⚙️ JavaScript Engine

Memory Heap

  • 메모리 할당이 일어나는 곳
  • 선언한 변수 및 함수 등이 담겨져 있음

Call Stack

  • 자바스크립트는 싱글 스레드 언어 ➡️ 콜 스택이 하나

  • 함수 호출 시 함수 실행 컨텍스트가 순차적으로 콜 스택에 푸시되어 순차적으로 실행

  • Stack 형태

    ➡️ 선입후출 (FILO, First In Last Out)

⚙️ Web API

  • 브라우저에서 제공하는 API
  • DOM, Ajax, Timeout 등
  • 콜백함수를 Callback Queue에 밀어넣음

⚙️ Callback Queue (=Task Queue)

  • 비동기적으로 실행된 콜백함수가 보관됨

    ex) setTimeout에서 타이머 완료 후 실행되는 함수나

    ​ addEventListener에서 이벤트 발생했을 때 실행되는 함수 등이 보관됨

  • Queue 형태

    ➡️ 선입선출 (FIFO, First In First Out)

⚙️ Event Loop

  • Call Stack과 Callback Queue의 상태를 체크 ✔️

  • Call Stack이 빈 상태가 되면 ➡️ Callback Queue의 첫번째 콜백을 Call Stack에 밀어넣음

    ➡️ 이러한 일련의 과정을 틱(tick)이라고 함

정리

1️⃣ 엔진에서 코드가 실행 ➡️ Call Stack에 쌓임

2️⃣ 선입후출 ➡️ 제일 마지막에 들어온 함수가 먼저 실행 ➡️ Stack에 쌓인 함수가 모두 실행

  • 만약 비동기 함수가 실행되면 ➡️ Web API 호출
  • Web API가 비동기 함수의 콜백함수를 Callback Queue로 밀어넣음
  • Event Loop가 Call Stack이 비면 Callback Queue의 첫번째 콜백을 Call Stack으로 이동시킴 (Tick)

🔥 마이크로태스크 큐 (Microtask Queue)

console.log('script start'); 

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

script start
script end
promise1
promise2
setTimeout

왜 Promise ➡️ setTimeout?

❕ Event Loop는 마이크로태스크 큐를 우선적으로 확인

​ ➡️ 만약 마이크로태스크 큐에 콜백이 있으면 Call Stack에 먼저 담음

​ ➡️ 마이크로태스크 큐에 처리해야 할 콜백이 없으면 태스크 큐 확인

콜백함수 in 태스크 큐(=매크로 태스크 큐)

setTimeout

setInterval

setImmediate

I/O

UI 렌더링

콜백함수 in 마이크로태스크 큐

Promise

process.nextTick

Object.observe

MutationObserver

2️⃣ Ajax

🔥 Ajax란?

Asynchronous Javascript And Xml

➡️ 비동기식 자바스크립트와 XML

XML❓

  • 데이터를 저장하고 전달할 목적으로만 만들어진 언어
  • HTML과 같은 마크업 언어이지만, 웹상에서 구조화된 문서를 전송가능하도록 설계되었음
    • 마크업 언어 ❓ : 태그 등을 이용하여 데이터의 구조를 기술하는 언어

그렇다면 Ajax는❓

  • 브라우저가 가지고 있는 XMLHttpRequest 객체를 이용해 페이지의 일부만을 위한 데이터를 로드하는 기법
    • XMLHttpRequest 객체
      • 비동기 통신을 담당하는 자바스크립트 객체
      • 특정 URL로부터 페이지 일부에만 필요한 데이터를 수신하는 역할
      • DOM 조작도 가능
      • 응답 결과 데이터에 따라 웹페이지 내에 삽입/변경하기도 함

🔥 Ajax 사용 시 기존 방식과의 차이

기존의 방식

1️⃣ 웹 브라우저가 웹 서버에 요청 전송

2️⃣ 웹 서버는 사용자의 요청 처리 후 결과를 HTML로 생성해 웹 브라우저에 전송

3️⃣ 웹 브라우저는 응답으로 받은 HTML을 분석하여 그 내용을 화면에 그림

4️⃣ 결과적으로 웹 브라우저가 웹 서버와 통신을 하고, 요청 결과는 HTML로 생성되며,

​ 사용자 입장에서는 페이지 이동이 발생

Ajax의 방식

1️⃣ 사용자가 이벤트를 발생 ➡️ 자바스크립트가 DOM을 사용해 필요한 정보를 구함

​ ➡️ XMLHttpRequest 객체를 통해 웹 서버에 요청 전달

2️⃣ 웹 서버가 XMLHttpRequest 객체로부터의 요청을 알맞게 처리하여 그 결과를 XML 등으로 생성하여 XMLHttpRequest에 전송

3️⃣ XMLHttpRequest가 자바스크립트에 서버로부터 도착한 응답을 알리고, 자바스크립트는 응답 데이터와 DOM을 이용해 사용자 화면에 반영

4️⃣ 결과적으로 사용자 입장에서는 페이지 이동이 발생되지 않고, 페이지 내부 변화만 발생

⭐ 웹 서버에서 전적으로 처리되던 데이터의 일부를 웹 브라우저에서도 처리할 수 있게 위임 가능

​ ➡️ 교환되는 데이터의 양과 웹 서버의 데이터 처리량이 감소

​ ➡️ 어플리케이션의 응답 반응 개선

그래서 어떤 차이?

1️⃣ 변경할 부분을 갱신하는데 필요한 데이터만 서버로부터 전송 받음 ➡️ 불필요한 데이터 통신 발생 ❌

2️⃣ 변경할 필요가 없는 부분은 다시 렌더링하지 않음

3️⃣ 클라이언트와 서버와의 통신이 비동기 방식으로 동작 ➡️ 서버에게 요청을 보낸 후 블로킹 발생 ❌

🧑‍💻 그런데 말입니다...

XML은 헤더와 태그 등 여러 요소로 가독성이 떨어지고, 실제 데이터 양에 비해 용량이 크다는 단점❗

➡️ JSON을 더 많이 사용하는 추세

🔥 JSON이란?

JavaScript Object Notation

➡️ 자바스크립트 객체 표기법 (?)

JSON ❓

  • 서버에서 클라이언트로 데이터를 보낼 때 사용하는 양식

  • 자바스크립트 객체 형식을 기반으로 만들어짐

    ➡️ 자바스크립트 문법과 굉장히 유사하지만 텍스트 형식임

  • 클라리언트가 사용하는 언어에 관계없이 통일된 데이터를 주고 받을 순 없을까?

    ➡️ 일정한 패턴을 지닌 문자열을 생성해서 내보냄

    ➡️ 클라이언트가 이를 해석해 데이터를 자기만의 방식으로 온전히 저장 및 표시 가능

    ➡️ 대부분의 프로그래밍 언어에서 JSON 포맷의 데이터를 핸들링할 수 있는 라이브러리 제공

  • 간결하고 통일된 양식 ➡️ 기계와 사람 모두 이해하기 쉬움

  • 용량이 작음

  • 문법 오류에 민감하고, 주석을 지원하지 않으며, 데이터 타입을 강제할 수 있다는 단점 보유

🔥 JSON이 제공하는 정적 프로토타입 메서드

JSON.stringify(value, replacer[optional], space[optional])

  • JavaScript 객체를 JSON 문자열로 변환하는 메서드

  • replacer 파라미터

    • 함수

      • number, string, boolean 타입을 리턴하면 JSON 문자열에 결과 포함됨
      • undefined를 리턴하면 JSON 문자열 결과에 포함되지 않음
      let obj = { 
          drink: 'coffee',
          appetizer: 'banana',
          month: 7,
          date: 20,
          confirm: 'yes'
      }
      
      function func(key, value) {
            //key가 confirm이면 value이 true로  변환
          if(key === 'confirm') return true
        //value가 string 타입이면
          else if(typeof value === 'string') {
                //JSON 문자열 변환 X
              return undefined
          } 
          else return value;
      
      }
      
      let toJSON = JSON.stringify(obj, func);

      "{"month":7, "date":20, "confirm":true}"

    • 배열

      • 배열의 요소는 JSON 문자열에 포함할 key가 됨
      • 배열 요소가 객체의 key가 아니라면 JSON 문자열 변환 시 포함되지 않음
      let obj = { 
          drink: 'coffee',
          appetizer: 'banana',
          reservationMonth: 7,
          reservationDate: 20,
          confirm: 'yes'
      }
      let toJSON = JSON.stringify(obj, ['reservationMonth', 'drink'])

      "{"reservationMonth":7, "drink":"coffee"}"

  • space 파라미터

    • JSON 문자열의 간격을 space 옵션 줄 수 있음

      기본
      
      "{"reservationMonth":7, "drink":"coffee"}"
      
      space 적용 ➡️ JSON.stringify(obj, null, '\t')
      
      {
          "reservationMonth":7,
          "drink":"coffee"
      }

JSON.parse()

  • JSON 문자열을 javascript 객체로 변환하는 메서드

fetch json()

  • fetch API의 응답 객체는 json()을 제공 ➡️ JSON.parse() 대신 사용 가능

  • response.json() 메서드 호출 ➡️ JSON 데이터를 JS 객체로 변환

    fetch(데이터요청 할 서버 url)
    .then(response => response.json())
    .then(data => {
      //데이터 처리 부분
    }

JSON.parse() VS response.json() 차이

➡️ JSON.parse() 에는 응답 바디만을 넣어야 함. 바디와 헤더 모두 들어가면 데이터 읽어오지 못함

➡️ response.json() 에는 응답 헤더가 들어가더라도 바디만 읽어서 불러옴

🔥 Ajax로 HTTP 요청을 보내기 위해 사용할 수 있는 방법

XMLHttpRequest

  • GET 요청 전송

    // XMLHttpRequest 객체 생성
    const xhr = new XMLHttpRequest();
    
    // HTTP 요청 초기화
    xhr.open("GET", "/users");
    
    // HTTP 요청 헤더 설정
    // 클라이언트가 서버로 전송할 데이터의 MIME 타입 지정: json
    xhr.setRequestHeader("content-type", "application/json");
    
    // HTTP 요청 전송
    xhr.send();
  • 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 }));
  • 응답 처리

    // 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);
      }
    };

[부록] Ajax❓ Axios❓ Fetch❓

✏️ Ajax

의미

  • JavaScript를 사용한 비동기 통신, 클라이언트와 서버 간에 데이터를 주고받는 기술
  • 서버와 비동기적으로 통신 ➡️ 필요한 부분만 웹페이지를 다시 불러옴

➡️ Ajax는 JS에서 비동기 HTTP 통신이 가능하게 해준다

➡️ 비동기 통신이란 response와 request를 비동기식으로 다룰 수 있다는 것을 의미

특징

  • JQuery와 함께 쓰면 편리해서 함께 쓰는 경우가 많음
    • 순수 Ajax 사용시 브라우저 간 호환성을 염두해서 코드를 각기 다르게 작성해야 하는 경우가 있는데, JQuery와 사용 시 호환성 보장됨

순수 Ajax

// use Ajax without Jquery

function reqListener (e) {
    console.log(e.currentTarget.response);
}

var oReq = new XMLHttpRequest();
var serverAddress = "https://jsonplaceholder.typicode.com/posts";

oReq.addEventListener("load", reqListener);
oReq.open("GET", serverAddress);
oReq.send();

Ajax + JQuery

// use Ajax with Jquery

var serverAddress = 'https://jsonplaceholder.typicode.com/posts';

// jQuery의 .get 메소드 사용
$.ajax({
    url: ,
    type: 'GET',
    success: function onData (data) {
        console.log(data);
    },
    error: function onError (error) {
        console.error(error);
    }
});

❓ XML HTTP Request ➡️ 요청의 상태나 변경을 구독하려면 Event를 등록해 변경사항 받아야 하고, 요청의 성공이나 실패 여부, 상태 등에 따라 처리하는 로직이 들어가야 함

그래서 Axios와 fetch 등장 ❕

✏️ Axios

의미

  • Promise 기반의 node.js와 브라우저를 위한 HTTP 통신 라이브러리
  • 비동기로 HTTP 통신을 가능케 해주며 promise 객체를 리턴 ➡️ response 데이터 다루기 쉬움
  • 브라우저 호환성 뛰어남

사용 예시

axios({
  method: 'post',
  url: '/user/1120',
  data: {
    firstName: 'Yoonju',
    lastName: 'Kim'
  }
});

✏️ Fetch

의미

  • ES6에 들어온 JS 내장 라이브러리
  • Promise 기반으로 데이터 다루기 쉬움
  • 내장 라이브러리 ➡️ 프레임워크가 안정적이지 않을 때 사용하기 좋음

사용 예시

const url ='http://localhost3000/test`
const option ={
   method:'POST',
   header:{
     'Accept':'application/json',
     'Content-Type':'application/json';charset=UTP-8'
  },
  body:JSON.stringify({
      name:'sewon',
        age:20
  })

  fetch(url,options)
      .then(response => console.log(response))

⭐ 읽어보면 좋을 글이자 출처 : https://velog.io/@kysung95/%EA%B0%9C%EB%B0%9C%EC%83%81%EC%8B%9D-Ajax%EC%99%80-Axios-%EA%B7%B8%EB%A6%AC%EA%B3%A0-fetch

[정리]

✏️ JavaScript에서 클라이언트와 서버 간 데이터를 주고 받기 위해 비동기 HTTP 통신을 하는데 그걸 가능하게 해주는 게 Ajax, Axios, Fetch

✏️ Promise는 그럼 무엇?

  • 비동기 작업의 단위
  • 비동기 처리와 연관있는 것