컴퓨터에서 실행할 수 있는 파일들 (Ex. 윈도우의 exe 파일)을 프로그램이라고 하는데, 이 프로그램이 실행중인 상태, 즉 컴퓨터가 어떤 일을 하고 있는 상태를 프로세스라고 합니다.
운영체제가 여러 개의 프로세스를 함께 실행하고 있기 때문에 멀티태스킹이 가능한 것입니다.
하지만 컴퓨터가 여러 개의 프로세스를 함께 실행하는 것 만으로는 충분하지 않습니다.
예를 들어서 브라우저를 실행했습니다. 브라우저도 프로그램이므로 하나의 프로세스입니다. 브라우저가 일을 할 때도 게임을 다운받는 동시에 다른 페이지를 돌아다니고, 동시에 유튜브에서 영상도 볼 수 있어야 합니다.
다시 말하면 한 프로세스 내에서도 다른 여러개의 작업이 동시에 진행될 필요가 있는 것입니다. 이 여러개의 작업을 스레드라고 합니다.
자바스크립트는 싱글 스레드로 동작하는 언어입니다.
즉 한번에 하나의 작업만 수행할 수 있다는 의미입니다.
한번에 하나의 작업을 수행하는 것을 동기, 하나의 작업을 수행하며 그동안 다른 작업을 수행하는 것을 비동기라고 합니다. 하나의 작업을 수행하면서 다른 작업을 수행한다는 것은 스레드가 여러개 진행되고 있다는 말이 됩니다. 즉 동기는 싱글 스레드, 비동기는 멀티 스레드인 것입니다.
아래 코드를 보고 결과가 어떻게 나올지 예상해 보세요.
console.log("Hello");
setTimeout(() => {
console.log("Bye");
}, 3000);
console.log("Hello Again");
자바스크립트는 싱글 스레드이므로 다음과 같은 결과값이 나와야 합니다.
하지만 실제 결과값은
이렇게 나옵니다. 즉 자바스크립트는 비동기적으로 동작한다는 것입니다. 싱글 스레드인 자바스크립트에서 이것이 가능한 이유는 무엇일까요?
자바스크립트 엔진의 구조도는 다음 그림과 같습니다.
Memory Heap은 메모리 할당이 일어나는 곳, Call Stack은 코드 실행에 따라 호출 스택이 쌓이는 곳입니다. 그림과 같이 자바스크립트는 단일 Call Stack을 가지고 있으므로 싱글 스레드라고 불리는 것입니다.
아래 코드와 그림을 보며 Call Stack에 함수가 쌓이는 순서를 확인해 봅시다.
보시는 바와 같이 스택의 형태로 호출된 함수를 추가하고 (Push) 실행된 함수를 제거 (Pop) 하는 형태입니다. 이렇게 자바스크립트는 다른 함수가 실행되고 있을때는 그 함수가 종료되기 직전까지 다른 작업이 중간에 끼어들 수 없습니다. 이것을 Run-to-completion 이라고 합니다.
그럼에도 불구하고 자바스크립트가 비동기적으로 동작할 수 있는 이유는 자바스크립트는 자바스크립트 엔진으로만 돌아가는 것이 아니기 때문입니다.
자바스크립트 엔진 밖에서도 자바스크립트 실행에 관여하는 요소들이 있는데, 각각 Web API와 Task Queue, Event Loop라고 합니다.
Web API 는 브라우저에서 제공되는 API이며 (여기서 의미하는 API는 이미 만들어진 코드의 집합체라고 볼 수 있으며, 개발자들이 만들기 어렵고 힘든 부분을 쉽게 구현하도록 하는 프로그램이라고 볼 수 있습니다. 마치 집에서 가구를 만들 때 직접 디자인하고, 재료를 구하고, 재단하고, 못을 박고 하는 등 혼자서 모든 것을 하는 대신 가구 만들기 키트를 사는 것과 같다고 보면 됩니다.) AJAX나 setTimeOut 등의 비동기 작업을 실행합니다.
아래 코드를 예시로 순서를 이해해 보겠습니다.
console.log("Hi!"); // 1번
const timeout = () => console.log("5 Seconds Later"); // 2번
setTimeout(timeout, 5000); // 3번
console.log("Hello!"); // 4번
Task Queue는 Web API에서 전달받은 콜백 함수(2번)를 저장합니다.
Event Loop는 Call Stack이 비어있는지, Task Queue에 콜백 함수가 존재하는지 모니터링하고 Call Stack이 비어있다면 Task Queue의 콜백 함수를 Call Stack으로 옮겨줍니다.
아래 사이트를 참고하시면 흐름을 이해하는데 도움이 될 것입니다.
자바스크립트 동작 흐름을 시뮬레이션으로 보여주는 사이트
출처
프로세스는 뭐고 스레드는 뭔가요?
자바스크립트의 동작원리: 엔진, 런타임, 호출 스택
비동기적 Javascript – 싱글스레드 기반 JS의 비동기 처리 방법
JavaScript가 뭔가요?