본문 바로가기
JavaScript 이론/비동기프로그래밍(Asynchronous)

#2 비동기적인 자바스크립트 실행

by 혀닙 2022. 3. 7.

목차

  1. 동기적 자바스크립트
  2. 비동기적 자바스크립트
  3. 비동기 코드스타일1 - 콜백
  4. 비동기 코드스타일2 -프로미스
  5. 코드의 동기/비동기적 실행 선택

 

#1. 동기적 자바스크립트

비동기적인 자바스크립트를 이해하려면 동기적인 자바스크립트가 무엇인지 알아야 한다.

앞선 게시글을 보았다면 자바스크립트가 싱글 쓰레드라는 것을 알게 되었을 것이다.

 

싱글쓰레드, 동기적 코드 실행이 어떤 의미인지 예제와 함께 살펴 보자

const btn = document.querySelector('button');
btn.addEventListener('click', () => {
  alert('ok를 눌러야만 다음 화면을 보여드려요');

  let p = document.createElement('p');
  p.textContent = 'ok를 눌렀으니 렌더 해드림';
  document.body.appendChild(p);
});

 

위의 블럭에서 코드는 동기적(순차적)으로 실행된다.

  1. DOM에 미리 정의된 버튼 엘리먼트를 참조하여 btn이라는 변수에 담음
  2. btn변수에 클릭 이벤트 리스너 속성을 더해서 버튼을 클릭했을 때, 아래의 3~6를 순차적으로 실행함
  3. alert() 메세지 나타남
  4. ok를 눌러서 alert 메세지가 사라지면 <p> 엘리먼트를 생성하여 p라는 변수에 담음
  5. p의 속성으로 text contetnt 생성
  6. document body에 문장 추가

 

위 코드의 실행에서

한번에 오직 하나의 작업이 메인쓰레드에서 처리되며, 각 작업을 처리하는 동안 렌더링은 일시적으로 정지된다.

(자바스크립트는 싱글 쓰레드 이기 때문!)

 

그래도 아직 코드의 동기적 실행이 확 와닿지 않는다면,

위의 코드를 실행하여 alert 메세지가 떴을 때 ok 버튼을 누르지 말아보자....

코드의 동기적 실행이 어떤 의미인 지 알게 될 것이다.

 

 

#2. 비동기적 자바스크립트

블로킹과 관련된 여러 이유들 때문에 많은 웹 API 기능들은 비동기 코드를 사용하여 실행되고 있다.

 

비동기 코드 사용의 예시

  • 네트워크에서 파일 가져오기
  • 데이터베이스에 접속해서 특정 데이터 가져오기
  • 웹 캠에서 비디오 스트림에 접근하기
  • 디스플레이를 VR 헤드셋으로 브로드 캐스팅하기

자바스크립트의 비동기 코드 스타일은 크게 두 가지로 나뉜다.

고전적인 방법으로는 콜백함수를 사용한 방식이 있고 새로운 방식으로는 Promise객체를 사용하는 방식이 있다.

그렇다면 천천히 알아보도록 하자.

 

#3. 비동기 코드스타일 1 - 콜백

callbacks은 백그라운드에서 코드 실행을 시작할 함수를 호출할 때 인자값으로 지정된 함수이다.

백그라운드 코드 실행이 끝나면 callback 함수를 호출하여 작업이 완료됐음을 알리거나, 다음 작업을 실행하게 할 수 있다.

callbacks은 고전적인 방법이며, 여전히 많은 곳에서 사용이 되고있다.

 

예제를 재탕해보도록 하자.

 

예제1.

const btn = document.querySelector('button');
btn.addEventListener('click', () => {
  alert('ok를 눌러야만 다음 화면을 보여드려요');

  let p = document.createElement('p');
  p.textContent = 'ok를 눌렀으니 렌더 해드림';
  document.body.appendChild(p);
});

위의 코드에서 addEventListener함수의 두번째 매개변수가 바로 콜백함수이다.

위의 코드에서는 콜백함수를 바로 적었지만, 매개변수로 함수명만을 작성하고 함수는 별도로 분리하여 작성하는 것도 가능하다.

 

어쨋든 중요한 것은 콜백 함수를 다른 함수의 인자값으로 전달할 때,

인자값으로는 함수의 참조만을 전달할 뿐이며 즉시 실행되지 않는다는 것이다.

즉, 함수의 body에서 콜백 되며, 정의된 함수는 때가되면 콜백 함수를 실행하는 역할을 한다.

 

콜백은 함수가 실행되는 순서와 함수간에 전달되는 데이터를 제어할 수 있다.

또한 경우에 따라서는 다른 함수로 데이터를 전달하여, 응답받은 데이터에 따라 어떤 작업을 수행할지 지정할 수 있다.

 

하지만, 모든 콜백함수가 비동기적으로 실행되지는 않는다.

 

예제를 살펴보자

const favoriteSingers = ['sia', 'emile sande', 'skylar grey', 'andra day', 'jessie j']
favoriteSingers.forEach((name,idx)=>{
	console.log(`${idx}.${name}`)
})

// 0.sia debugger
// 1.emile sande
// 2.skylar grey
// 3.andra day
// 4.jessie j

 

forEach() 메서드의 매개변수는 콜백함수이며, 콜백 함수는 인덱스와 이름이라는 두개의 매개변수가 있다.

하지만 위의 예시에서 코드는 비동기로 처리 되지 않으며 즉시 실행된다.

 

 

#4. 비동기 코드스타일2 - 프로미스(Promise)

프로미스는 오늘날의 Web APIs에서 사용되는 새로운 코드 스타일이다.

프로미스는 비동기 작업의 성공과 실패 여부를 나타내는 객체이다.

즉, 성공과 실패의 중간 상태라고 볼 수 있다.

 

4-1. 프로미스 결과값의 사용

(1) then() 메서드

  • 인자값으로 이전 작업이 성공했을 때 수행할 작업을 나타내는 콜백함수를 작성하며, 콜백함수는 이전 작업의 성공 결과를 전달받는다.
  • 즉, 성공했을 떄의 코드를 콜백 함수 안에 작성하면 된다.
  • 각각의 then() 메서드는 서로 다른 promise를 반환하며 then()메서드를 여러번 사용하여 연쇄적인 작업을 수행하게 할 수 있다.
  • 이말인 즉슨, chaining을 통해 여러 비동기 작업을 차례대로 수행할 수 있게 된다.

 

 

(2) catch() 메서드

  • then() 이 하나라도 실패하면 실행된다.
  • 블록 안에서 error 객체 사용가능하며, 이를 통해 발생한 오류에 대한 확인이 가능하다.
  • 동기 방식의 try...catch문과 유사하지만 try...catchansdms promise와는 함께 사용 불가

 

4-2. 이벤트큐

  • 비동기 작업(node JS 내장함수/프로미스와 같은 )은 이벤트 큐에 들어간다

 

4-3. 프로미스

  • 콜백의 함수 형태로 전달하는 것이 아닌, 콜백함수를 장착하고 있는 반환된 객체
  • 여러 개의 연쇄적인 비동기 작업 수행 시 .then()메서드 사용하여 체이닝 가능
  • 프로미스 콜백은 이벤트 큐에 배치되는 순서대로 호출됨
  • .catch() 로 에러처리 가능

 

 

#5. 코드의 동기적/비동기적 실행 선택

가장 기본적인 형태의 자바스크립트

  • 동기적(synchronous)
  • 블록킹(blocking)
  • 싱글쓰레드(single-threaded)

라는 특징을 가지고 있다.

 

 

하지만, 웹 브라우저

어떤 이벤트* 발생 시, 비동기적으로 호출되어야만 하는 함수를 입력할 수 있게 하는 함수들과 APIs를 정의한다.

*시간의 경과, 유저의 마우스 사용, 또는 네트워크를 통한 데이터 확인

즉, 메인스레드를 중지하거나 blocking하지 않고 코드에서 동시에 여러 작업을 수행할 수 있게 한다.

 

 

따라서, 코드를 동기적으로 실행할 지, 비동기적으로 실행할 지는 작업자가 구현하려는 작업에 따라 달라질 것이다.

 

어떤 일은 즉시 로드되고 즉시처리되어야 하는 경우가 있다.

예를 들어 웹 페이지에 사용자 정의 스타일을 적용하는 것과 같은 일들.

 

반면 데이터 베이스를 쿼리하고, 결과를 사용하여 템플릿을 채우는 것과 같은 시간이 소요되는 작업을 수행해야 한다면

이러한 작업은 메인쓰레드에서 밀어내어 비동기식으로 진행하는 것이 좋을 것이다.

댓글