비동기 JavaScript

동기식


동기식 코드는 코드가 하나씩 순서대로 실행되는 것을 말합니다. 일반적으로 콜스택에 쌓여서 메인쓰레드에서 실행됩니다.

각각의 라인들은 그 각각의 라인들이 끝날때 까지 다음 코드는 실행되지 못합니다. 이러한 일을 BLOCKING 이라고 합니다.

비동기식

비동기식은 동기식과 다릅니다. 비동기식 코드는 특별한 코드들만 해당됩니다. 다른 코드들은 대부분이 동기식 코드입니다.
예를 들어 setTimeout은 비동기식 코드로서 백그라운드에서 동작합니다. 백그라운드에서 동작하는동안 다른 동기식코드들은 메인쓰레드에서 잘동작합니다. 비동기식 코드는 동기식코드들 BLOCKING 하지않아 non-blocking 코드라고 합니다. 다른 코드들의 진행을 막지않아서 비동기식 코드는 백그라운드에서 실행이 되는 동시에 동기식코드는 막힘없이 순서대로 실행됩니다. 후에 백그라운드 실행이 끝나면 동기식코드의 실행이 끝나길 기다렸다가 콜스택에 합류하여 코드를 마칩니다.

img.src = 'dog.jpg';
img.addEventListener('load',function (){
  img.classList.add('fadeIn');
});

위 코드에서도 img.src = 'dog.jpg' 부분은 비동기식 코드입니다. 이미지 변수에 이미지를 넣는 것 자체가 자바스크립트에서 비동기식으로 짜여졌기 때문입니다. load 이벤트는 이미지 로딩이 끝나야 발생하는데 이때문에 load 이벤트는 이미지 로딩이 끝날때 까지 또 다른 load이벤트를 발생시킬수 없습니다. 이러한 비동기식 코드가 여러개 일때 비동기식 코드는 다른 비동기식 코드를 기다리지 않습니다. 그냥 동시다발적으로 실행되고 어떤 코드가 언제 끝날지 모르는 코드입니다.

비동기식 코드는 해당 코드가 끝난 다음 실행되어야하는 콜백함수를 인수로 반드시 제공해야합니다. (하지만 이러한 addEventListener 같은 콜백 함수를 받는 함수들 자체가 비동기식 코드를 유발하지 않습니다.) 이러한 콜백함수로 비동기식 코드를 그나마 순서대로 처리 할수 있습니다.

콜백지옥

LoadScript('1.js', function(){
  LoadScript('2.js', function(){
    LoadScript('3.js', function(){
      ...
  }
}

위 코드는 콜백함수로 비동기식 코드를 계속 불러들여 멸망의 피라미드라고 불리는 콜백지옥을 쌓았습니다. 콜백지옥은 다음과 같은 단점을 갖습니다. 그리고 특징이 나타납니다.

  • 코드 삼각형모양으로 길어졌다가 줄어듭니다.
  • 코드가 매우 지저분해서 가독성이 매우 떨어지고 이해하기 어렵습니다.
  • 그러므로 더 많은 버그가 있고 재사용하기 어려워지는 나쁜 코드가 됩니다.

이러한 콜백지옥을 방지하는 방법이 몇가지 있습니다.

  • 콜백함수를 전역필드로 함수를 선언하여 분리한다.
  • promise
  • ...
LoadScript('1.js', loadScript2);
function loadScript2 () {
	LoadScript('2.js', loadScript3);  
}
function loadScript3 () {
    LoadScript('3.js', loadScript4);
}...

위와 같은 코드는 콜백지옥의 피라미드 구조를 벗어나지만 동작구조는 같아 집니다. 하지만 네임스페이스도 이상해지고 이러한 코드는 재사용하기가 매우 난감합니다.

AJAX

AJAX 란 Asynchronous JavaScript and XML 의 약자입니다. XML이란 구시대적 웹 통신 파일확장자 명입니다. 요즘에는 JSON 파일을 사용하지만 이전에는 XML을 사용했습니다. 하지만 AJAX라는 단어가 고착되어서 웹서버와 동적으로 데이터를 주고 받을 수 있게 요청을 보내는 기능으로 불립니다.

API

API란 그냥 허용된 소프트웨어 끼리 서로 데이터를 주고 받는 것을 의미하며 그러한 소프트웨어 자체를 의미합니다. API라는 것은 실로 광범위 해서 웹개발에 사용되는 API도 많습니다.

  • DOM API, Geolocation API
  • 사용자가 만든 클래스도 API가 될수 있습니다.
  • 온라인 API라는 것은 사용자가 웹 서버에 올려놓고 통신하는 일반적인 API입니다. 그냥 이러한 것을 API라고 많이 합니다.

AJAX 요청

XMLHttpRequest

XML 이라는 것은 위에도 말했다시피 웹서버와 통신하는 데이터의 유형을 부르는 명칭입니다. XML이라는 데이터 유형은 구식데이터로서 요즘에는 JSON 데이터 유형을 주로 사용합니다.

  • 실제 XML을 사용하는 코드를 보아도 당황하지 말것
  • XML 코드를 이용해서 비동기 코드가 어떻게 이뤄지는지 살펴볼것

한번 XML 코드를 살펴봅니다.


const btn = document.querySelector('.btn-country');
const countriesContainer = document.querySelector('.countries');

///////////////////////////////////////

const getCountryData = function (country) {
  const xml = new XMLHttpRequest();
  xml.open('Get', `https://restcountries.eu/rest/v2/name/${country}`);
  xml.send();

  xml.addEventListener('load', function () {
    const [data] = JSON.parse(this.response);
    console.log(data);
    const html = `
    <article class="country ${data.name}">
    <img class="country__img" src="${data.flag}" />
    <div class="country__data">
      <h3 class="country__name">${data.name}</h3>
      <h4 class="country__region">${data.region}</h4>
      <p class="country__row"><span>👫</span>${(
        +data.population / 1000000
      ).toFixed(1)} people</p>
      <p class="country__row"><span>🗣️</span>${data.languages[0].name}</p>
      <p class="country__row"><span>💰</span>${data.currencies[0].name}</p>
    </div>
  </article>
    `;
    countriesContainer.insertAdjacentHTML('beforeend', html);
    countriesContainer.style.opacity = 1;
  });
};

getCountryData('uk');
getCountryData('china');
getCountryData('usa');

XML은 XMLHttpRequest 라는 객체의 생성자를 통해서 만들어지는 객체를 통해 통신을 할수 있습니다.

  1. xml.open 함수로 Get , Post를 정하고 url를 넣어 통신채널을 엽니다.

  2. xml.send 함수로 데이터를 보내면 이 데이터가 보내어지고 받게되면 load라는 이벤트가 생깁니다.

  3. xml객체는 load 이벤트를 받으면 하게되는 addEventListener 함수의 콜백함수로 데이터를 받으면 하게되는 함수를 만듭니다.

위 과정을 모두 하는 getCountryData라는 함수를 만들고 3개를 일률적으로 실행시켜 봅니다.

xml에서 send는 비동기 코드로서 동작합니다. send를 하면 백그라운드에서 동작하므로 data = xml.send()라는 코드는 작성될수 없습니다. 값이 없는데 넣는것이 안됩니다. data는 undefined를 반환하게 될 것 입니다.

통신 채널을 여는 순서는 3개의 국가가 순서입니다. 하지만 send후 load이벤트가 발생하는 순서는 제각각입니다. 따라서 addEventListener로 콜백함수로 처리되는 함수를 살펴보면 받은 데이터로 html 카드를 작성해서 보이게 합니다.

이 순서를 보면 load 이벤트의 발생순서를 알수 있습니다.

이렇게 브라우저를 새로 고침할때마다 순서가 달라집니다. 비동기 코드는 어떤코드가 늦게 끝날지 알수 없습니다. 이러한 문제를 해결하는 방법으로서 콜백함수가 있습니다.

웹서버에 접근하는 과정

간략하게 사용자가 웹서버에 접근하는 과정을 그려봅시다.

  1. 사용자 즉, 클라이언트는 DNS서버에 자신의 주소를 지정 받습니다. 이렇게 지정받은 주소는 IP주소 및 포트번호로서 http 프로토콜은 443번 포트로 예약되어 있습니다.

  2. 웹서버와 통신하기 위한 TCP/IP 소켓이 연결됩니다. 하나의 채널로서 이 채널위로 HTTP 프로토콜로 데이터가 송수신 됩니다. TCP/IP는 큰 데이터를 여러개의 패킷 단위로 나누어서 송수신하면서 병목현상을 막아주면서 빠르게 데이터를 송수신하며 도착지에서 패킷을 다시 큰 데이터로 합치는 과정이 있어 안전하게 데이터 관리가 가능합니다.

  3. 클라이언트가 HTTP 프로토콜로 웹서버에 요청을 보냅니다. HTTP 프로토콜의 내용은

  • start line : GET 요청, 요청 타깃, http 버전
  • header : host등.. 매우 다양한 내용
  • body : POST 요청시 사용하는데, 보내야할 데이터 양이 많으면 body가 사용됩니다. body에는 오로지 보내는 데이터들만 들어갑니다.
  1. 이러한 요청을 바탕으로 웹서버에서 요청하는 데이터를 받아서 다시 HTTP 프로토콜을 기반으로 답변을 줍니다. 이때 답변에는
  • start line : http 버전, 상태코드, 상태 메세지

  • header : 답변 형식의 header 내용

  • body : 답변 데이터

    이러한 내용이 들어가게 됩니다.

    https 프로토콜과 http의 중요한 차이점은 tls 혹은 ssl로 http 프로토콜의 암호화가 보장되느냐 입니다.

    자세한 내용은 OSI 7계층 정리시 정리하겠습니다.

profile
일상을 기록하는 삶을 사는 개발자 ✒️ #front_end 💻

0개의 댓글