오늘은 자바스크립트 런타임에 대한 이야기다. 원래 생각도 안하고 있었는데, 런타임에 이런이런 에러가 생길 수도 있다. 같은 얘기는 많이 했지만 그래서 런타임이 뭔지는 얘기를 안했어서 한번 이야기 해볼까 한다. 조금 어렵게 들릴 수도 있지만 일단 한번 시작해보자.
1. 스레드 (Thread)
오늘 얘기할 JavaScript의 런타임을 얘기하려고 하면, 이 스레드라는 개념에 대해서 확실히 정리가 되어있어야한다. 그리고 이걸 이해하기 위해선 큐, 스택, 힙이 뭔지에 대해서도 알고 있어야하는데 일단 큐, 스택은 설명을 해둔게 있으니 그걸 보면 될 것 같고, heap은 조만간 정리해서 올려두도록 하겠다.
<큐 / 스택 정리된 게시물 >
2023.04.17 - [Dev/Algorithm] - [Algorithm] 큐와 스택(Queue, Stack) 그리고 트리(Tree)
일단 아주 간단하게 설명해서 Thread는 업무를 처리할 수 있는 팔이 몇개 있는지를 말해준다고 생각하면 되겠다.
Single Thread 같은 경우엔 팔이 하나 뿐이라 병렬로 업무를 처리할 수 없고, Multi Thread를 지원한다는건 병렬로 업무를 처리할 수 있다고 생각하면 될 것 같다.
우리가 사용하는 JavaScript는 Single Threaded 언어라고 한다. 그런데 우리가 자바스크립트를 사용하는 것을 생각해보면 한번에 여러일을 하는 것처럼 보이는 비동기처리를 지원하고, 한번에 많은 요청을 처리하거나 할 수가 있는데 왜 어째서 Single Thread 언어라고 하는지 의문이 생길거다. 조금 한번 자세히 들여다보자.
2. JS 엔진과 Browser
JavaScript 런타임을 정리한 그림이 바로 위에 있는 그림이다. 저 모든 요소들이 자바스크립트 런타임 환경이고, 자바스크립트 자체는 Single Thread 지만, 그걸 극복할 수 있게 해주는게 이 JavaScript 런타임에 있다고 보면 되겠다.
1) JS 엔진
일단 엔진의 작동 원리를 이야기 해보자. 위의 그림에서 heap 과 stack 이 들어있는 V8박스를 보면 되겠다. 기본적으로 자바스크립트가 실행 될 때 엔진에선 heap과 stack 이 존재한다. heap의 경우 개발자가 정의한 변수 등 객체들이 저장되는 위치라고 보면 되겠고, stack의 경우엔 실행시킬 함수를 쌓아뒀다가, stack의 기본 원리 LIFO에 따라서 제일 마지막에 들어간 함수부터 실행시킨다.
이 stack의 개수가 몇개냐 에 따라서 Single Thread / Muiti Thread 여부를 결정한다고 보면 되겠는데, stack의 수가 많을 수록 한번에 꺼내서 실행 시킬 수 있는 함수의 수가 늘어나기 때문에, 앞에서 이야기한 예시에 빗대면 팔이 여러 개가 된다고 볼 수 있다.
하여튼 이 엔진은 순차적으로 함수를 실행시킨다는 특징이 있는데, 당연히 예외라는게 있다. 시간이 오래걸린다고 이미 정해져있는 몇가지 케이스의 경우엔 일단 stack에 바로 넣지 않고, 잠시 대기 시켰다가 빨리 끝나는 함수들을 모두 실행시킨 뒤에 실행시키게 되는데, 여기가 중요하다.
2) Web API / Event Loop
앞서 말한 예외, 시간이 오래걸린다고 이미 정해져 있는 몇 가지가 Web API라고 보면 된다. 이는 자바스크립트 엔진에 포함 되지 않고, 브라우저에서 제공하는 것들로 Request를 날리고 Ajax, Event를 감지하는 EventListener (event가 DOM 에 들었기 때문에 위의 그림에서는 DOM이라고 표현한 듯), 잠시 기다렸다 함수를 실행시킬 수 있게 해주는 setTimeout() 과 같은 것들이 있다. 이런 케이스들의 경우 바로 stack으로 가지 않고 callback Queue라는 곳에 들어 있다가, stack이 비어있게 되면 가장 처음 넣은 것부터 하나하나 stack으로 보내주게 되는데, 이 역할을 해주는게 event loop다.
즉, event loop를 통해서 비동기 처리가 가능해진다고 보면 되겠다. Web API에 해당하는 코드들이 미뤄져있다가 실행시킬 수 있는 상태가 되면, stack이 비워진 뒤 callback Queue에 들어간 순서대로 실행이 되는 원리로 말이다.
3. 우리가 개발할 때 시간 복잡도 같은 것을 고려해야하는 이유
이게 내 의문이었는데, 허구헌 날 이직하겠다고 코테 풀고 있다보니, 아니 근데 프론트는 화면에 데이터를 잘 보여주기만 하면 되는데, 도대체 왜 굳이 시간 복잡도를 고려해가면서, 함수 실행 시간을 단축시키는 최적화가 필요한걸까? 라는 생각이 들었었다.
그게 여기에 있었다. Web API에 해당하는 녀석들은 당연히 미뤄지고, callback Queue에 담기겠지만 그게 아닐 경우엔 당연하게도 stack에 바로 실행 될 함수로 들어가게 된다. 근데 만일 실행에 시간이 상당히 오래걸리는 복잡한 함수가 구현 되어있다면, 그 함수가 끝날때까진 어떤 것도 실행할 수없는 상태가 된다. 예를 들어 실행하는데 10초 이상이 걸리는 함수가 있다고 하면, 거기서 10초 이상을 소모하고 있기 때문에 그 10초가 넘는 시간동안은 다른 작업을 진행할 수 없어 버튼을 클릭하더라도 반응이 없게 되는 것.
이로 인해 페이지가 응답이 없다. 이런 메세지가 뜨면서 뻗어버리는 증상이 생기는거다.
'Dev > JavaScript' 카테고리의 다른 글
[JavaScript] 생성자 함수 (0) | 2023.06.29 |
---|---|
[JavaScript] 정규표현식 (0) | 2023.06.28 |
[JavaScript] ASCII Code (0) | 2023.06.26 |
[JavaScript] Arrow Function (0) | 2023.06.24 |
[JS] slice() (0) | 2023.06.16 |