비동기적 실행을 알아보기 전에 자바스크립트의 코드 실행과정을 알아보겠습니다.
JavaScript는 싱글스레드 언어이다. callstack이 1개, 한번에 하나의 작업만 수행한다는 의미이다.
call stack은 스택 형태의 저장소로 JavaScript 엔진은 함수 호출과 관련된 정보를 이 곳에서 관리한다.
function stack3() {
console.log('function stack3 is called')
throw new Error('에러발생!!')
}
function stack2() {
console.log('function stack2 is called')
stack3()
}
function stack() {
console.log('function stack is called')
stack2()
}
stack()
3개의 함수 stack , stack2, stack3이 있다.
function overflow() {
overflow()
}
overflow()
해당함수는 overflow()함수를 재귀호출하는 코드이다.
실행이 되면 계속 함수가 돌고돌아 callstack에 멈추지 않고 쌓이게 되어 callstack size가 초과되는 오류가 발생한다.
웹 브라우저에서 16ms 안에 코드의 실행이 완료되지 않으면 화면이 뚝뚝 끊기는 현상이 발생한다. 하지만 모든 작업을 16ms 안에 처리할 수 없다. 그래서 어떤 이벤트가 일어날 때까지 기다리거나, 큰 데이터를 처리의 완료를 기다리거나 이와 같은 상황에서 브라우저는 다음과 같은 순서로 일을 처리한다.
setTimeout(() => {
console.log('B');
}, 0); // 작업 큐에 callback이 추가됨
console.log('A');
A
B
해당 코드에서 브라우저는 setTimeout의 callback을 작업 큐에 등록하고 callstack이 비워진 후 작업 큐의 callback을 가져와 실행한다.
자바스크립트는 코드가 호이스팅된 이후 코드가 작성된 순서대로 동기적으로 우선 실행된다.
하지만 웹에서는 사용자가 어떤 행동을 할지 예측할 수 없기 때문에 비동기적인 코드 실행이 필요하다.
callback 함수란?
다른 함수의 파라미터로 전달되거나 객체의 프로퍼티로 사용 등 나중에 호출되어 사용되는 함수를 의미한다.
console.log('1');
setTimeout(function() {
console.log('2')
}, 1000)
console.log('3')
// 결과
1
3
2
해당 코드가 동기적으로 실행되면 console.log('1')을 실행하고 setTimeout을 만났을때 브라우저 API로 전달 후 Task Queue에서 대기 하다가 console.log('3')을 실행하고 1초가 지난후 setTimeout 함수를 실행하도록 한다. 이때 비동기적으로 실행된 함수를 callback 함수라고 한다.
코드 실행에 있어 비동기성을 관리하는 일반적인 방법이다.
JavaScript에서 코드가 비동기적으로 작동하는 경우
매우 유연하고 편리한 비동기식 언어이지만 비동기적 언어를 순차적으로 사용하면 콜백지옥
에 갇히게 된다.
setTimeout(function() {
console.log('A');
setTimeout(function() {
console.log('B');
setTimeout(function() {
console.log('C');
setTimeout(function() {
console.log('D');
}, 4000);
}, 3000);
}, 2000);
}, 1000);
해당코드는 타이머를 순차적으로 실행하는 callback 함수 구조이다.
이 콜백지옥
의 문제는 우선 가독성이 너무 떨어지고 에러가 발생시 어느 부분에서 문제가 발생했는지 파악 및 수정이 어렵다.