Javascript

비동기 프로그래밍 (feat. callback, Promise, async/await) 1부

마손리 2022. 11. 30. 04:24
 
이번 포스트에서는 비동기 프로그래밍의 정의, 목적에 대해 중점을 두고 이야기 해보고 다음포스트에서는 callback, Promise, async/await의 비교 예제를 중점으로 다루겠습니다.

 

비동기가 있다면 동기도 있겟지??

자바스크립트는 싱글스레드를 사용하므로써 프로그램을 위에서 아래 순으로 한줄씩 실행이 된다.

즉, 이전줄의 코드가 완료되기 전까지는 완료되기 전까지는 다음줄의 코드가 실행되지 않는다.

장점으로는 에러 발생시 프로그램은 즉각 작동 중지되며 다음줄의 코드가 실행되지 않으며 에러 발생지를 바로 알수가 있다.

(*싱글스레드: 단일 프로세스로 하나의 작업을 위해 순차적으로 처리 진행 [다음 혹은 다다음 포스트 예정])

 

비동기 프로그래밍은 다른 데이터들과 상호작용 하지않고 간단한 코드들로만 구성이 되있을경우 좋아보이지...만 API로 다른곳에서 데이터를 받아온다거나 다른 포멧의 장치들(카메라나 마이크등)을 이용하게될때 그 데이터들을 받아오는 시간동안 그와 상관없는 프로그래밍들 또한 기다려야된다는 단점이 발생하게 됩니다.

 

그래서 비동기를 사용한다!

비동기 프로그래밍은 동기 프로그래밍과 반대로 코드들을 병렬적으로 처리하며 코드들이 위에서 아래로 순차적으로 '실행'은 되지만 그 결과까지는 기다리지않고 다음줄의 코드가 실행됩니다. 

자바스크립트에서 비동기를 사용하는 방법은 3가지로 callback, Promise, async/await이 있습니다.

 

callback?

Promise와 async/await이 나오기전 비동기를 처리할 유일한 방법이었습니다.

mdn에서의 callback 정의는 "A callback function is a function passed into another function as an argument"이라 하는데

(출처:https://developer.mozilla.org/en-US/docs/Glossary/Callback_function)

여기서 눈여겨 볼것은 콜백함수는 클로저와 다르게 하나의 argument로 실행이 된다는 것입니다.

 

const doSomething = () => {alert("Done somthing")}
document.querySelector('#example').addEventListener('click', doSomething)

간단한예시로 addEventListener가 있습니다.

보시는 바와 같이 example이라는 id를 가진 버튼을 클릭시 doSomething이라는 함수가 '콜백'되어 실행되도록 argument로 전달된다는 것입니다.

예제 처럼 "클릭후 무언가를 한다."와 같이 한가지만의 행동만 약속되었다면 callback으로도 큰 무리없이 코드를 작성했겠 지만 두 개 이상의 비동기 작업을 순차적으로 실행해야 하는 상황이 발생한다면 우리가 흔히 알고있는 '콜백 지옥'이 만들어집니다. 그래서 나온것이 Promise!!

 

Promise!!

callback 함수를 개선시킨 방식으로 ES6를 통해 도입되었습니다. (콜백 지옥으로 얼마나 고생을 했으면...)

callback 함수를 인자로 전달해주는 방식이 아닌 .then을 이용하여 말그대로 '그 다음' 실행을 할 함수를 첨부해주는 방식입니다. 여기서부터는 조금 복잡해질 수 있는데, Promise는 대기, 이행, 거부, 이 3가지의 상태를 가지게됩니다. 간단히 설명하자면 대기는 처리중의 상태, 이행은 Promise가 성공적으로 완료되었을때, 거부는 실패하였을때의 상태가 됩니다.

 

const example = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("이행 되었다.");
  }, 200);
});

const nextFn = (result) => console.log(result);

example.then((returnedValue) => nextFn(returnedValue));

예시에서 눈여겨 볼점은 (callback보다 뭔가 더 복잡해젔다??, callback과의 비교는 다음 포스트에...) .then 메소드 입니다.

위처럼 Promise는 .then을 이용하여 다음 실행할 함수를 불러옵니다. 또한 Promise의 상태(성공, 실패여부)에 따라 결과를 다르게 할수도 있습니다.

 

하지만... callback을 개선시켰다지만... 아 몰라! 이것도 어려워 복잡해! 더 쉬운거 줘~

해서 나온것이 async/await !!

 

async/await

const promise = new Promise((resolve) => {
  setTimeout(() => {
    resolve("결과");
  }, 200);
});

const example = async () => {
  const result = await promise;
  console.log(result);
};

example();

미칫다, XXcking awesome! 사랑스러워! 넌 스페셜해!

필요 함수를 async로 선언한 후 promise를 await식을 포함시켜주면 다음으로 넘어가지 않고 결과값을 기다려줍니다!!

(물론 .then의 기능과 같지만 보라! 가독성이 얼마나 좋아젔는가! 역시 귀찮음은 문명을 발전시키는구나)

 

async함수는 ES7에 Promise를 보안한 방식으로 나왔으며, try/catch를 이용하여 Promise의 이행과 거부상태 또한 다룰수 있습니다.

 

각 비동기의 사용방식 비교는 다음 글에서 포스팅 하겠습니다~ (스크롤 압박때문에... 절대 진짜 네이버 귀찮아서 아님)

 

(다음글: https://mason-lee.tistory.com/5)