[Javascript] | Synchronous & Asynchronous

myway_7·2022년 2월 26일
0
post-thumbnail

Synchronous VS Asynchronous (동기 VS 비동기)

From MDN...

Synchronous Javascript

기본적으로 Synchronous의 의미는 다음과 같다

실시간, 즉각적인 커뮤니케이션

자바스크립트를 예로 들면, 우리가 콘솔창에 console.log(”어떤 메시지...”)를 입력하고 실행시키면 콘솔창에는 내가 입력한 메시지가 즉각 출력된다. 이러한 명령의 실행과 그 결과가 즉각적으로 발생하는 작업, 일을 동기적 작업이라고 말한다.

Programming 관점에서 동기적이라는 것의 의미를 보면

const btn = document.querySelector('button');
btn.addEventListener('click', () => {
  alert('You clicked me!');

  let pElem = document.createElement('p');
  pElem.textContent = 'This is a newly-added paragraph.';
  document.body.appendChild(pElem);
});

위의 코드를 실행시키면 alert 창이 뜬 후 확인 버튼을 클릭하기 전 까지, 다른 동작, 작업의 실행이 불가능하다.

즉, 작성되어 있는 일련의 작업들이, 이전의 작업이 Complete 된 이후에 그 다음 작업이 진행된다.

자바스크립트는 기본적으로 Single Thread(단일 프로세싱 루트) 방식이기 때문에 동시에 병렬로 여러 작업을 실행하지 못하고 한번에 단일의 작업만 수행한다.

여기서 많은 블로그 글 조차도 헷갈리게 작성되는 부분이 발생한다.

즉각적인 실행, 작성된 코드의 순차적 실행이 synchronous라며? 근데 앞의 작업이 완료될 때 까지 기다리는건 비동기적 작업 수행이 아닌가?

여기서 앞서 설명한 동기적 실행의 의미를 다시 생각해보자.

명령의 실시간 입력과 실행

여기에 단일 스레드라는 자바스크립트의 특성이 결합되어 어떤 명령이 수행될 때, 명령이 입력되면 바로 수행되고, 그 명령이 완료된 후 그 다음 작업이 진행된다.

물론 위의 예시에서는 alert() 함수를 사용하여, 마치 promise 객체를 다룰 때 처럼 비동기 적으로 상황을 표현했지만, alert가 완료 된 후 다음에 작성되어있는 작업이 실행됨을 보여주기 위함이다.

Asynchronous Javascript

위에서 설명한 자바스크립트의 이러한 특성 때문에, 많은 Web API 에서는 Asynchronous 방식의 코드 동작을 채택한다.

Asynchronous 의 의미는

❇️프로그램이 작업이 완료될 때까지 기다리지 않고 원래 작업과 함께 그 다음의 작업을 수행하는 특성 (출처: MDN - Asynchronous)

자바스크립트에서 기본적으로 비동기 동작을 하는 몇 가지 함수가 있는데 대표적으로 fetch()가 있다.

fetch() 함수는 데이터를 다른 곳에서 받아오는 함수로서 외부 서버 등에서 다운로드 받는 경우, 소요시간이 필연적으로 발생한다. 이 때문에 작업이 완료될 때 까지 기다린 후 다음 작업을 수행하도록 설계된다면, 다운로드 받는 시간동안 사용자는 웹브라우저에서 어떠한 동작도 실행시킬 수 없다.

이러한 문제를 해결하기 위해 웹 환경은 기본적으로 fetch() 함수가 자바스크립트 문서에서 처음 읽히고 실행되면, 그 다운로드 작업의 완료는 백그라운드에서 실행되고 메인 작업 흐름에서는 fetch() 함수 다음으로 작성된 작업이 순차적으로 실행된다.

이렇게 본래의 작업 흐름에서 벗어나, 즉각적인 결과물이 반환되지 않는 작업은 백그라운드에서 완료될 때 까지 실행되고, 메인 작업 흐름은 그 다음의 작업을 계속해서 수행해 나아가는 방식을 비동기적 자바스크립트 실행이라고 정의한다.

  • 예시
    let response = fetch('myImage.png'); // fetch is asynchronous
    let blob = response.blob();
    // display your image blob in the UI somehow
    • fetch 함수가 백그라운드에서 이미지를 다운로드 하는 동안, fetch() 함수 호출 이후 즉각 그 다음의 response.blob() 작업이 실행된다
    • blob() 작업은 다운로드 한 이미지에 의존하여 실행되는 작업이므로, 해당 작업의 실행은 에러를 발생시킨다.

이렇게 비동기 작업은, 이전의 작업 완료까지 기다리지 않고 시간이 걸리는 작업을 병렬적으로 처리하는 것을 의미한다.

하지만, 효율적인 작업의 처리는 장점이지만, 위의 예시처럼 이러한 비동기 작업에 의존적인 다른 작업의 경우 비동기 작업 완료 후 실행되도록 조치하지 않는다면 에러를 발생시킨다는 번거로움이 있다.

자바스크립트에서는 ECMA Script 2015를 통해 Promise를 정식으로 지원하여 이러한 비동기 작업의 불편함을 해소하고, 나아가 콜백지옥이라는 개미지옥으로 부터 사용자를 구원하기 위해 노력하였다.

수 많은 동기 & 비동기 관련 블로그 글들....

동기, 비동기 관련하여 수 많은 블로그 글들이 존재한다.

하지만 위에서 언급한 Promise를 비롯하여, 비동기 작업들을 처리하는 과정에 대한 잘못된 이해로 동기, 비동기를 이상하게 설명하는 글들이 매우 많다.

대표적인 설명으로

동기 실행: 코드의 작성 순서대로 명령이 실행되는 방식
비동기 실행: 일의 순차적인 작업, 논리적인 순서에 맞도록 작업이 실행되는 방식

동기 실행의 경우, 비동기 작업에 대한 설명을 찾아보면서 “백그라운드에서 실행되고 그 다음 작업은 바로 실행된다” 는 설명 때문에, 코드 순서가 뒤바뀌면서 실행되는게 비동기 구나 이해한 경우에 저렇게 설명하는 것으로 보이고,

비동기 실행의 경우, 가장 많은 예가 Promise로 설명하고 있는데 promise의 경우 .then 을 쓰면서 코드 순서와 별개로 일의 진행 순서에 맞춰 코드가 실행되도록 만든 예시들 때문에 저렇게 설명하는 것으로 예상된다.

저런 설명들 때문에 나도 초기에 개념이 뒤섞여 머릿속에서 꽤나 고생을 했다.

이것만 기억하자

  1. 동기 실행은 “작업의 호출과 그 결과의 즉각적인 반환” 특성을 의미한다. (예: console.log 찍으면 콘솔에 바로 결과 나타나는 것)
  2. 비동기 실행은 네트워크 통신 처럼 작업 완료에 시간이 필요한 작업의 경우 메인 작업 영역에서 벗어나 백그라운드에서 작업의 완료까지 계속되는 방식을 의미한다. (이러한 비동기 작업은 기본적으로 자바스크립트의 단일 스레드 특성 때문에 작업의 효율을 위해 탄생한 설계 방식이라는 점을 기억하자)
  3. 가장중요
    비동기 작업에서 발생하는 문제를 해결하기 위해 (위의 예시처럼, 비동기 작업의 반환결과를 이용하는 다음 작업이 있는 경우), 이전에는 콜백체인, 현재는 Promise를 이용하여 비동기 작업이 완료된 후 그 결과를 받아 다음 작업이 실행되도록 강제한다.
profile
[...Way to FrontEnd Web Developer]

0개의 댓글