이번에 한달 전에 잠깐 맛만 보았던 동기와 비동기를 좀 더 맛을 보는 시간을 가졌습니다.
먼저 동기랑 비동기의 차이부터 정리해보겠습니다!
자바스크립트는 싱글스레드 프로그래밍 언어다. 즉 자바스크립트 엔진은 하나의 스레드에서 한번에 1개의 명령만 수행이 가능하다는 뜻입니다!
음... 그러면 불러오는데 오래걸리는 명령이 들어오면 그 뒤에 들어오는 명령도 같이 기다려야한다는 뜻이죠!
그림으로 보면 이해가 좀 쉽습니다.
명령1이 실행되고 그 다음 명령2, 명령3, 명령4 순서로 실행되게됩니다.
원래 서로 연관성이있어서 순서가 중요하다면 괜찮겠지만 서로 연관이 없는 경우라면 어떨까요 아마 제일 오래걸리는 명령1이 실행될때까지 아무 것도 못하고 기다리기만 해야 할 것입니다.
현실 예로 들면 커피숍에서 첫번째 사람이 커피를 주문하고 그 사람이 주문한 커피가 나올때까지 다음 사람은 주문을 못하고 전 사람이 주문한 커피가 나와야 주문이 가능한 방식입니다.
그렇다면 자바스크립트는 무조건 순서대로 밖에 수행못하는 건가요?
아니요!
자바스크립트에서도 밑에서 설명할 callback
, promise
, async / wait
등을 이용해 주 스레드를 블로킹하지 않고 비동기 프로그래밍이 가능합니다!
그 말은 즉 아래의 그림처럼 서로 실행시간의 영향을 안받고 실행이 가능하다는 뜻입니다!
그렇게된다면 명령1이 로딩되는 중에도 명령2,3,4를 실행 할 수 있을 것이고 기다리지 않고 다른작업을 할 수도 있을 겁니다.
아까 들었던 커피숍 예시에서는 첫번째 손님이 커피를 주문하면 진동벨을 받고 옆으로 빠지고 다음 사람이 계속해서 주문을 하는 방식이겠죠?
그러면 비동기 방식에 순서가 필요한 경우에는 어떻게 할까요?
비동기 방식에도 순서가 필요할때가 있을 겁니다.
예로 외출준비를 간단하게 예시로 들어보겠습니다.
const 외출준비 = (string) => {
setTimeout(
() => {
console.log(string)
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
외출준비("씻기")
외출준비("옷입기")
외출준비("출발하기")
}
printAll()
위의 코드를 실행하면 우리가 원하는 순서가 아닌 아래와 같이 실행 때마다 다른 결과 값이 나올겁니다!
씻기
출발하기
옷입기
이러한 비동기 방식에 순서를 줄때 어떤 방식이 있을까요?
먼저 익숙한 callback이 있습니다.
콜백을 통해 위의 문제를 해결해 보겠습니다.
const 외출준비 = (string, callback) => {
setTimeout(
() => {
console.log(string)
callback()
},
Math.floor(Math.random() * 100) + 1
)
}
const printall = () => {
외출준비('씻기', () => {
외출준비('옷입기', () => {
외출준비('출발하기', () => {})
})
})
}
위처럼 콜백을 이용하면 비동기에서도 원하는 값을 순서에 맞게 가져올 수 있게 됩니다.
하지만 콜백에는 큰 단점이 있습니다.
바로 콜백지옥입니다.
콜백 지옥은 비동기 처리 로직을 위해 콜백 함수를 연속해서 사용할 때 발생하는 문제입니다.
만약 모든 명령이 서로 연관이 있어 순서를 이어서 정해줘야한다면 위의 사진과 같이 콜백안에 콜백이 계속 들어가게 됩니다. 이러한 구조는 가독성도 떨어지고 수정하기도 어렵습니다.