각각의 함수가 어떻게 등장하였고, 어떤 이점을 갖는지, 어떻게 쓰는지 확인하기 전에 비동기 처리의 개념을 짚고 가자.
동기(Synchronous)와 비동기(Asynchronous)는
프로세스의 수행 순서 보장에 대한 메커니즘
이다.
동기(Synchronous)란 무엇일까?
추상적으로 생각했을때 동기는 동시에 발생하는 것
으로 생각하기 쉽다. 그리고 비동기는 (비)동기, 즉 동기에 반(反)하기 때문에 동기가 아닌 것
으로 쉽게 생각 할 수 있다.
동기의 의미를 보기 위해 어원인 Synchronous 의 의미를 보면
synchronous [adjective]
: happening, existing, or arising at precisely the same time
정확하게 같은 시간에 일어나고, 존재하고, 발생하는
이다.
이를 위해 동기 방식은 현 프로세스의 응답과 다음 프로세스의 요청
을 요구한다.
이에 반해 비동기 방식은 요청을 보낸 후 응답과 관계 없이 다음 동작을 실행한다.
동기와 비동기 개념을 익히기 위해 가장 많이 보는 함수 setTimeout
을 활용하여 학습해보자.
console.log("First");
setTimeout(()=>{
console.log("Second");
}, 5000);
console.log("Last");
다음 코드의 결과는 아래와 같다
자바스크립트는 싱글스레드로 실행되지만, 비동기식 처리 모델인 Web API
와 함께 동작한다.
다음 문서를 통해 확인해보면,
그림과 같이 setTimeout() 함수를 담당하는 것을 알 수 있다.
이와 같이 자바스크립트는 수행 시간이 걸리는 프로세스를 넘기고, 비동기적
으로 실행하는 것이다.
서론이 길지만 필수적으로 이해해야하는 개념이라 생각이 들어 정리를 하였다.
ES6 이전의 비동기 처리를 위해 콜백 패턴을 활용, 자바스크립트의 동기적인 코드 수행을 위해 콜백 함수를 계속 중첩함으로써 나온 현상.
콜백으로 인한 단점은 다음과 같다
이에 ES6
에서 부터는 Promise
가 등장 하였다.
Promise는 3가지의 상태(states)를 갖는다.
- 대기(pending): 이행하거나 거부되지 않은 초기 상태
- 이행(fulfilled): 연산이 성공적으로 완료됨
- 거부(rejected): 연산이 실패함
let myFirstPromise = new Promise((resolve, reject) => {
setTimeout(function(){
resolve("Success!"); // Yay! Everything went well!
}, 250);
});
myFirstPromise.then((successMessage) => {
console.log("Yay! " + successMessage);
});
다음 예제에서 new Promise()
메서드 호출은 대기(pending) 상태를 갖게한다.
resolve
와 reject
는 콜백 함수의 인자이며 reslove()
와 함께 이행(fulfilled) 상태가 된다.
이때 처리 결과 값은 아래의 then()
을 통해 받을 수 있다.
이때 발생하는 오류는 거부(rejected) 상태에서 reject
메서드가 호출되어 catch()
를 통해 처리 할 수 있다.
async & await
는 비동기 코드를 쓰고Promise
를 더 읽기 쉬워지게 만든다
function hello() { return "Hello" };
hello();
다음과 같은 함수는 async
키워드와 함께 아래와 같이 변할 수 있다.
let hello = async () => { return "Hello" };
이제 이 함수는 Promise
를 반환하게 된다.
hello().then(console.log)
결과는 위를 통해 확인 해 볼 수 있다.
즉 async
는 함수와 같이 사용시, 결과를 직접 반환하는 것이 아니라 Promise
를 반환하게 된다.