비동기적 프로그래밍
23 Feb 2021비동기적 프로그래밍의 필요성은 여러가지의 이유로 필요합니다. 예를 들면 사용자의 입력과 같은 것들은 대부분이 비동기적 실행이 필요합니다. 하지만 자바스크립트에서는 자바 스크립트의 본성 때문에 더 필요하다고 볼 수 있습니다. 자바 스크립트 어플리케이션은 단일 스레드에서 작동합니다. 즉, 한번에 한가지의 동작만을 할 수 있다는 것을 의미합니다.
자바스크립트의 비동기적 프로그래밍에는 뚜렷한 구분이 있는 3가지의 페러다임이 있습니다.
- 콜백
- 프라미스
- 제너레이터
사용자 입력 외에도 비동기적 처리를 할 경우가 몇 가지 있습니다.
- Ajax 요청을 비롯한 네트워크 요청
- 파일을 읽고 쓰는 등의 파일 시스템 작업
- 의도적으로 시간 지연을 사용하는 기능
콜백
콜백을 간단히 설명하면 호출함수 입니다. 언제 끝날지 모르는 비동기적 실행이 끝났을때를 인지하고 그때 실행되는 함수를 콜백함수라고 합니다.
스코프와 비동기적 실행
함수를 실행하면 스코프도 함께 생성된다는 것은 다들 아는 사실일 것입니다. 비동기적 실행에서도 스코프 내 어디서 변수가 선언 되는냐에 따라 실행결과가 많이 달라집니다.
function countdown() {
let i
console.log("count down!!")
for (i = 5; i >= 0; i--) {
setTimeout(function () {
console.log(i === 0 ? "go!" : i)
}, (5 - i) * 1000)
}
}
// count down!
// -1
// -1
// -1
// -1
// -1
// -1
우리가 원하는 것은 5로 시작하는 카운트 다운 후에 go가 출력되는 것입니다. 하지만 -1 만 6번 반복되서 출력될 뿐입니다. 이 이유에 대해서 먼저 얘기하면 for문이 실행 될때마다 같은 i를 공유하기 때문입니다. 사실상 비동기 함수인 setTimeout이 실행되는것은 for문이 끝난 후에 실행 되기때문에 그 때는 공유하고 있는 변수인 i 가 -1이 되었기 때문에 i가 6번 반복합니다.
이를 해결할 수 있는 방법은 iife와 반복문 내에 i를 선언하는 2가지의 방법이 있습니다.
function countdown() {
console.log("count down!!")
for (let i = 5; i >= 0; i--) {
setTimeout(function () {
console.log(i === 0 ? "go!" : i)
}, (5 - i) * 1000)
}
}
// count down!!
// 5
// 4
// 3
// 2
// 1
// go!
function countdown() {
let i
for (i = 5; i >= 0; i--){
(function (x) {
setTimeout(function() {
console.log(x === 0 ? "go" : x)
}, (5-x)*1000)
})(i)
}
} // IIFE로 처리하면 다음과 같이 처리 할 수있다. 하지만 ES6로 들어오면서 블록스코프가 생겼기때문에 IIFE의 활용도가 조금 떨어지긴합니다.
i 변수를 for문 내에 선언 함으로써 for문이 한번 반복 될때마다 다른 i를 가지기 때문에 원하는 결과를 얻을 수 있게 됩니다.