JS는 싱글 스레드 언어인데, 싱글 스레드의 특징은?
- 한 번에 하나의 일만 수행할 수 있는 것
- 문맥 교환(context switching)이 필요하지 않다.
- 프로그래밍 난이도가 쉽고 CPU 및 메모리를 적게 사용한다.
- 단순 CPU만을 사용하는 계산 작업은 오히려 멀티 스레드보다 더 효율적일 수 있다.
- 멀티 스레드는 번갈아가면서 작업을 수행해서 더 느릴 수도 있다.
- 연산량이 많은 작업을 할 경우 그 작업이 완료되어야 다른 작업을 할 수 있어서 멀티 스레드가 필요해진다.
- 에러 처리를 못 할 경우 멈춘다.
프로세스(Process)
- 프로그램이 메모리 상에서 실행될 때 작업의 단위
- 프로그램이 실행되는 순간 활동하기 위한 무대를 프로세스라고 할 수 있다.
스레드(Thread)
- 프로세스가 할당 받은 자원을 이용하는 실행의 단위, 프로세스 내에 여러 개가 생길 수 있다.
- 예를 들어, 브라우저를 프로세스라고 생각하면 블로그 글 작성하는 스레드1, 유튜브 영상 틀어놓기 스레드2
- 멀티 스레드의 경우 스레드 간에 자원을 공유하고 자원의 생성 및 관리의 중복성을 최소화하여 수행 능력을 향상시킨다.
- 각각의 스레드는 독립적인 작업을 수행해야하기 때문에 고유한 스레드 ID, 프로그램 카운터, 레지스터 집합, 스택을 갖고 있다.
문맥 교환
- 현재까지의 작업 상태나 다음 작업에 필요한 각종 데이터를 저장하고 읽어오는 작업
- 하나의 프로세스가 CPU를 사용 중인 상태에서 다른 프로세스가 CPU를 사용하도록 하기 위해, 이전의 프로세스의 상태를 보관하고 새로운 프로세스의 상태를 적재하는 작업
싱글 스레드란 한 번에 하나의 일만 수행할 수 있는 것을 말한다. 자바스크립트의 모든 코드들은 창수에서 줄 선 손님이 일을 끝내야 그 다음 손님이 일을 볼 수 있다. 또한, 일을 다 본 손님은 다시 줄을 서지 못합니다.
자바스크립트는 원래 웹페이지의 보조적인 기능을 수행하려고 만들어진 언어이다. 멀티 스레드인 자바는 다소 무겁고 어렵다는 인식도 있고 동시성 문제가 있다보니, 복잡한 시나리오를 신경쓸 필요 없는 싱글 스레드 형식이 채택되었다.
실제로 구글 Chrome 브라우저는 기존 웹 페이지에서 동시성 문제를 일으킬 수 있다는 이유로 단일 웹 사이트 페이지의 자바스크립트 코드가 동시에 실행되는 것을 허용하지 않는다.
자바스크립트의 메인 스레드인 이벤트 루프
가 싱글 스레드이기 때문에 싱글 스레드라고 부른다. 하지만 이벤트 루프만 독립적으로 실행되지는 않고 웹 브라우저나 NodeJS같은 멀티 스레드 환경에서 실행된다. 즉, 자바스크립트 자체는 싱글스레드이지만 자바스크립트 런타임은 싱글 스레드가 아니다.
자바스크립트 런타임 자체에서 비동기 API를 지원하는가?
아니다. 정확히는 자바스크립트 엔진을 구동하는 런타임 환경에서 담당한다. 즉, 브라우저 혹은 Node.js가 담당한다.
런타임
- 프로그램이 실행되고 있을 때 존재하는 곳, 구동되는 환경
- 자바스크립트는 브라우저에서 작동하는 자바스크립트 측면도 있고 Node.js에서 구동되는 측면도 있다. 여기서 브라우저와 Node.js를 런타임이라고 한다.
자바스크립트는 비동기 작업을 통해 여러 요청들을 처리하게 된다.
자바스크립트의 비동기 런타임 과정에 대해서 알아보자. 아래 그림에 나와있는 것들이 코드 실행을 도와준다.
Call Stack : 자바스크립트에서 수행해야 할 함수들을 순차적으로 스택에 담아 처리
Web API : 웹 브라우저에서 제공하는 API로 AJAX나 Timeout등의 비동기 작업을 실행
Task Queue :Callback Queue
라고도 하며 Web API에서 넘겨받은 Callback 함수를 저장
Event Loop : Call Stack이 비어있다면 Task Queue의 작업을 Call Stack으로 옮김
실제로 비동기 코드를 작동시켜보자.
console.log("맨 처음 실행");
setTimeout(() => console.log("async console 1초후 실행"), 1000);
console.log("이건 언제 실행?");
// 맨 처음 실행
// 이건 언제 실행?
// async console 1초후 실행
문자열이 출력된 순서를 보면 코드 입력된 순서와는 다르게 async console 1초후 실행
이 나중에 출력된다. 아래 그림을 보면서 순서대로 알아보자.
setTimeout이 실행되면 Web API에서 Timeout(Node.js에는 Timers)이 timer를 생선한다.
setTimeout의 시간을 0초로 하면?
결과는 변하지 않는다. 시간이 중요한 게 아니라 setTimeout 함수가 Web API가 지원하는 비동기 함수라는 점이 중요하다.
즉, 바로 Call Stack에 쌓이는 게 아니라 Web API에서 비동기 처리된 후 콜백함수를 Task Queue로 이동했다가 Call Stack에 호출된다.
참조
gil0127 | 싱글스레드(Single thread) vs 멀티스레드 (Multi thread)
eunjin | [OS] 싱글스레드, 멀티스레드의 의미
cyheum | TIL. 싱글스레드 vs 멀티스레드 11/20
suzy-thetraveler | 프로세스와 스레드의 차이? (+완벽 개념정리, 멀티프로세스<멀티 스레드?)
vincent | Javascript 동작원리 (Single thread, Event loop, Asynchronous)
CHANYEONG | 자바스크립트는 왜 싱글 쓰레드일까?
하이퍼포머 | 자바스크립트는 왜 싱글 스레드를 선택했을까? 프로세스, 스레드, 비동기, 동기, 자바스크립트 엔진, 이벤트루프