자바스크립트에서의 실행의 지연을 시키기 위하여 쓰이는 함수들을 살펴 보자!
setTimeout() 함수
setTimeout() 함수는 두번째 인자로 넘어온 마이크로 초만큼 기다린 후, 첫번째 인자로 넘어온 함수를 호출해줍니다.
console.log("before");
setTimeout(() => console.log("after"), 3000);
→ setTimeout(function/code, delay, arg1~)
- function/code - 실행하고자 하는 코드로, 함수 또는 문자열 형태이다. 거의 이 자리에 함수가 들어간다. 문자열을 넣을 경우 코드가 길어지기 때문에 함수를 넣는다. 문자열을 넣는 경우 익명 화살표 함수를 사용한다.
- delay - 실행 전 대기 시간으로, 단위는 밀리초(millisecond, 1000밀리초 = 1초)이며 기본값은 0이다.
- arg1 - 함수에 전달할 인수이다.
→ 기본적으로 자바스크립트의 실행 환경은 프로그램의 실행을 최대한 막지 않는(non-blocking) 방식, 즉 비동기(asynchronous)로 코드를 실행해준다. 나중에 실행해야 할 코드는 옆으로 잠깐 치워놓았다가, 당장 실행이 가능한 다음 코드를 먼저 처리 후에, 다시 때가되면 원래 코드를 실행해준다.
동기 지연
function sleep(ms) {
const wakeUpTime = Date.now() + ms;
while (Date.now() < wakeUpTime) {}
}
function test() {
console.log("before");
sleep(3000);
console.log("after");
}
→ 자바스크립트에서 이렇게 동기적인(synchronous) 방식으로 코딩을 하게 되면 치명적인 성능 문제로 이어질 수 있다. 왜냐하면 싱글 쓰레드에서 이런 식으로 프로그램의 실행이 막히면 애플리케이션이 그 시간동안 사용자에게 응답할 수 없는 상태가 되기 때문이다.
이 방법은 테스트 환경에서 일부로 이러한 병목 현상을 시뮬레이션하는 극히 제한된 용도로만 써야하며 상용 환경에서는 가급적 사용을 피해야한다.
비동기 지연 - Promise
자바스크립트에서는 비동기 프로그래밍 모델이므로, 프로그램이 실행이 막히지 않도록 지연 함수를 구현해야 한다. setTimeout()함수와 promise를 함께 써보았다.
function sleep(ms) {
return new Promise((r) => setTimeout(r, ms));
}
async function test() {
console.log("before");
await sleep(3000).then(() => console.log("after"));
console.log("done!");
}
→ 비동기 방식으로 지연을 주기에 setTimeout() 함수만 사용했을 때 다음에 나오는 코드의 실행을 막지 않는다.
async/await
Promise의 경우then() 메서드의 인자로 넘기는 콜백 함수 내에서 조건문이나 반복문을 사용하거나, 여러 개의 Promise를 병렬로 또는 중첩해서 호출해야하는 경우들이 발생하게 된다. 이럴 경우, 다단계 들여쓰기를 해야할 확률이 높아지며 코드 가독성은 점점 떨어지게 된다.
Promise의 이러한 불편한 점들을 해결하기 위해 ES7(ES2017)에서 async/await 키워드가 추가되었다. async/await 키워드를 사용하면 비동기 코드를 마치 동기 코드처럼 보이게 작성할 수 있다.
async키워드가 function 앞에 붙었다는 것을 알 수 있습니다. 그리고 Promise를 리턴하는 모든 비동기 함수 호출부 앞에는 await 키워드가 추가되었습니다.
await 키워드는 async키워드가 붙어있는 함수 내부에서만 사용할 수 있으며 비동기 함수가 리턴하는 Promise로 부터 결과값을 추출한다. 즉, await키워드를 사용하면 결과값을 얻을 수 있을 때까지 기다려줍니다. 따라서 일반적인 동기 코드 처리와 동일한 흐름으로 (함수 호출 후 결과값을 변수에 할당하는 식으로) 코드를 작성할 수 있으며, 따라서 코드를 읽기도 한결 수월해진다.
async function test() {
console.log("before");
await sleep(3000);
console.log("after");
console.log("done!");
}