비동기(asynchronous) 방식의 동작 원리




웹을 공부하다가, 이벤트 루프 콜백 함수가 비동기 적으로 동작한다고 했을 때

내부에서 어떤식으로 돌아가는지 궁금했었다.

비동기로 동작하면 그냥 순서에 상관 없이 실행되는구나~ 하면서 넘겼는데

멀티 스레드에서는 각 스레드 별로 함수를 실행하면 되는데

싱글 스레드 환경에서는 동작 방식이 아무래도 납득이 가지 않았다.


그러던중 다음과 같은 컨퍼런스 영상을 보고 

비동기 방식의 동작원리에 대해서 어느정도 생각해보게 되었다.


https://www.youtube.com/watch?v=8aGhZQkoFbQ






자바 스크립트에서 함수를 실행 시키면 함수가 call stack에 쌓이며 

LIFO(Last in First out)방식으로, 나중에 들어온 함수부터 처리하게 된다.

이는 자바 스크립트 뿐만 아니라 다른 언어에서도 거의 동일하게 볼 수 있다.





이 때, 다음과 같이 무한 루프를 순회하면 call stack의 용량이 초과되며

'stack overflow' 상태로 오류가 발생한다.

크롬 개발자 창에서는 

'RangeError : Maxmum call stack size exceeded'

경고가 뜬다





자바 스크립트는 싱글스레드로 동작하므로 1개의 call stack에서 함수를 처리한다.

그렇다면 위와 같은 예제에서는 어떻게 동작하는 걸까

stack이 1개 이기때문에 jquery로 getSync 함수를 호출하면

해당 함수가 리턴 될때 까지 로딩상태에 빠지게 된다.

그때까지 아래의 bar와 qux는 동작하지 못한다.


bar와 qux로 순서가 넘어왔을때도 비슷한 상황이 된다.

이와 같은 상황이 지속된다면, 클라이언트에서는 사용자가 원하는 시간내에

view를 응답하지 못하게 되며, 좋은 서비스를 제공하지 못한다.







그렇다면 이와 같은 문제를 해결할 수 있는 방법은 무엇일까.

바로 비동기 콜백 함수이다.

위의 그림은 비동기 콜백 함수의 예제이다.

setTimeout은 1개의 콜백함수와 1개의 숫자를 인자로 받는데,

입력한 숫자만큼의 시간이 지났을 때 콜백 함수가 동작하게 된다.

(인자는 1000이 1초가 된다)


결론부터 말하면 setTimeout 함수가 먼저 stack에 등록되었다가 실행되면서 사라지고

바로 밑의 console.log('JSConfEU')가 실행된 후,

5초가 지난뒤 setTimeout의 콜백함수의 내용인 console.log('there')이 실행된다.





동작 원리는 다음과 같다.

setTimeout은 위와 같이 call stack에 쌓인다.

그리고 비 동기적으로 동작하기때문에 setTimeout의 Timer를 

브라우저가 제공하는 webapi에 등록한다.


그리고 call stack에서 setTimeout은 사라지게 된다.

이 후, 가장 밑줄의 console.log('JSConfEU')가 실행되고 stack에서 사라진다.

물론, main 함수도 코드가 끝까지 실행되었으므로 stack에서 사라진다.





webapi에 등록된 타이머는 계속 동작하다가 5초가 되었을때 동작을 중지하고

콜백함수를 task queue로 전달한다.

queue는 FIFO(First in First out)의 구조를 가졌으므로

stack와 다르게 먼저 들어온 함수가 우선권을 가진다.





task queue에서 대기중이던 콜백함수는 stack에 아무런 함수가 쌓이지 않았을 때

queue에서 빠져나와 call stack으로 넘어가 실행되게 된다.

이와 같은 동작 원리로 웹의 비동기 처리가 완성된다.


원본 영상에서는 애니메이션 효과로 다이나믹하게 동작 원리를 설명한다.

또한 예제를 보여주며 실제로 어떤식으로 보여지는지 설명해준다.

자막은 없지만, 공대생들이 사용하는 언어가 그리 어렵지 않으므로

동영상을 시청해 보는것을 추천한다.

저작자 표시
신고

+ Recent posts

티스토리 툴바