자바스크립트를 사용하다보면 여러 특이한 장면을 볼 수 있습니다.
예를 들어 이런 코드를 실행하고 싶다 칩시다.
//1+1을 하고 1초를 쉰 후 2+2를 하고 그 후 3+3을 했으면 좋겠다!
console.log(1+1)
setTimeout(function(){console.log(2+2)},1000) //setTimeout = 몇초동안 쉬고 실행하라는뜻
console.log(3+3)
어디 자바스크립트로 한번 짜봅시다. 결과가 어떻게 나올까요?
첫쨰줄이 실행된 후 1초 쉰 후에 2번째 줄이 실행되는건 맞는데 그걸 기다려주지 않고 3번째 줄이 실행됩니다.
이처럼 자바스크립트는 다른언어랑 다르게 좀 특이한데요 오늘은 이러한 자바스크립트의 동작 원리에 대해 알아보겠습니다.
웹브라우저
위 사진은 웹브라우저를 나타낸건데요
웹브라우저가 뭐냐?
⇒ 우리가 html css javascript로 짠 코드를 실행해주는 엔진입니다.
근데 이제 그냥 실행해주진 않고 규칙에 의해 실행시켜주는데요
먼저 스택이라는 공간이 있는데 우리가 작성한 코드를 한줄한줄 스택이라는 공간에 넣고 한줄한줄 실행을 해줍니다.
그리고 이제 코드를 실행할때 저기 i처럼 변수들을 만나게 되는데 저런 변수들은 힙 안에 저장해서 스택해서 호출해서 사용하게 됩니다.
자바스크립트 엔진의 스택에서는 한번에 코드를 한줄밖에 실행을 못시킵니다. 그래서우리는 자바스크립트는 싱글쓰레드기반이다 라고 합니다.
⇒ 싱글스레드 : 나의 프로세스에서 한가지 작업을 실행하기 위해 순차적으로 실행되는 하나의 흐름
근데 이제 setTimeout같은 코드는 바로 실행을 할 수 없는 코드이기 때문에 이런것들은 스택에 집어넣어서 실행을 하지 않습니다.
이런 코드들은 잠깐 대기실로 보내놓습니다.
이런 대기실을 Web Api라고 합니다.
(Web Api ⇒ 개발자가 브라우저 상에 쉽게 개발할 수 있도록 도와주는 객체 모음들)
(대기실로 보내는 코드에는 대표적으로 Ajax요청코드, setTimeout, 이벤트 리스터 등이 있습니다.)
자바스크립트 엔진 자체는 원래 동기적으로 작동
하지만 자바스크립트가 비동기작업을 할 수 있는 이유? ⇒ web API 를 이용하면 됨
그럼 이제 1초가 지나갔을 때 대기실에 있는 코드를 옮겨와야하는데요
다만 이제 옮기는 조건이 있는데요
스택이 텅 비었을 때만 옮겨질 수 있습니다.
스택이 비어있으면 큐에서 스택으로 하나 보내는 방식으로 진행된다는 것이죠.
자 이제 아까 짯던 코드를 다시 보겠습니다.
1.첫번째 줄은 바로 스택에서 처리를 하게 될겁니다.
2.두번째 줄에는 setTimeout이 있으므로 바로 실행할 수 없기 때문에 대기실로 이동을 시켜둡니다
3.세번째 줄에서 3+3을 실행합니다.
4.이제 1초가 지났으니 대기실에 있던 코드를 콜백큐로 옮기고 콜백큐에서 스택으로 올린 후 처리하게 됩니다.
그래서 이런식으로 작동하게 되는겁니다!
4-1 근데 이 과정을 이벤트 루프라는게 해줍니다
Event Loop는 Stack과 Callback Queue를 상태를 계속 감시하며 Stack에 함수들이 존재하지 않는다면 Callback Queue에 있는 비동기 함수들을Stack에 밀어 넣게 됩니다. 그 후 Stack에서 비동기 함수를 실행시키게 됩니다.
이벤트 루프 덕에 자바스크립트가 호출 스택이 하나인 싱글 스레드임에도 여러 가지 일을 동시에 처리하는 것처럼 동작할 수 있게 되는데요,
이를 동시성(Concurrency)라고 표현합니다!
• 동시성(Concurrency) : 여러 작업이 마치 동시에 일어나는 것처럼 보이는 것
즉, 모든 건 순차적으로 하나의 스레드(콜 스택) 안에서 돌아가고 우리는 그저 이 시간 차가 너무 작아서 동시에 돌아간다고 착각을 하는 것입니다.
.
그럼 이러면 어떨까요?
//그럼 setTimout을 0초로하면?
//0초만 쉰다면 어떻게 될까?
console.log(1+1)
setTimeout(function(){console.log(2+2)},0) //setTimeout = 몇초동안 쉬고 실행하라는뜻
console.log(3+3)
결과는 똑같습니다
시간이 중요한 게 아니라 setTimeout 함수가 Web API가 지원하는 비동기 함수라는 점이 중요합니다!
즉, 바로 Stack에 쌓이는 게 아니라 Web API에서 비동기 처리된 후 콜백함수를 콜백 Queue로 이동했다가 Stack에 호출되는 과정이기 때문에 결과는 변하지 않음!
또다른 예시를 보겠습니다
이제 자바스크립트를 쓸때 for 반복문을 많이 쓰는데요,
이제for반복문을 수천개를 돌려서 자바스크립트가 10초정도 걸리는 연산을 하면 안됩니다.
Why..?
이렇게 10초정도 걸리는 연산이 스택에 쌓인 상태에서 그 후 버튼클릭, ajax요청, setTimeout같은 작업을 시키면 작동이 안됩니다.
왜냐하면 저런 함수들은 대기실→큐로 이동한 후 스택으로 가서 실행되는 방식인데, 아까 말했듯이 스택이 비어있어야만 큐→스택으로 이동하기 때문에 버튼같은걸 눌러도 아무런 반응이 없게 됩니다.
실제 브라우저에서는 이렇게 응답이 안된다고 오류가 나거나 할겁니다. ⇒ 브라우저 프리징
그렇기 때문에 스택을 바쁘게 만들면 안되고, 큐도 바쁘게 만들면 안된다고합니다.
'JS' 카테고리의 다른 글
[JS] 함수형 프로그래밍의 이해 (0) | 2024.03.05 |
---|
댓글