[JS] 자바스크립트는 싱글스레드인데 어떻게 멀티스레드처럼 동작할 수 있을까?
포스트
취소

[JS] 자바스크립트는 싱글스레드인데 어떻게 멀티스레드처럼 동작할 수 있을까?

JavaScript는 싱글 스레드 기반 언어인데, 어떻게 멀티 스레드처럼 동작할까?? 내가 알고 있는 부분을 정리하면서 추가적으로 공부를 하고싶어서 작성하게 되었다.

스레드가 정확하게 뭔데?

스레드(thread)

프로세스의 실행 가능한 작은 단위. 프로그램에서 일어나는 개별적인 동작 또는 작업 흐름

  • 각 스레드는 독립적으로 실행될 수 있다.
  • 같은 프로세스 내의 스레드들은 메모리와 자원을 공유한다.
  • 어떤 프로세스든 하나 이상의 스레드가 수행된다.

단일 스레드 (Single Thread)

  • 프로그램 내의 작업들이 순차적으로 하나씩 처리된다.
  • CPU 및 메모리를 적게 사용한다.
  • 하나의 작업이 오래 걸리게 되면, 그 작업이 완료될 때까지 기다리고 다른 작업을 처리하기 때문에 시간이 오래 걸리게 된다.

멀티 스레드 (Multi Thread)

  • 프로그램 내의 작업들이 동시에 처리된다.
  • 하나의 스레드가 블로킹 상태에 있을 때, 다른 스레드가 독립적으로 실행되기 때문에 더 나은 사용자 경험을 제공한다.
  • 여러 개의 스레드가 한번에 실행되기 때문에 자원 공유로 인한 동시성 문제가 발생한다.
    • 동시성 : 여러 작업들이 동시에 수행되는 능력. 이로 인해 스레드 간의 동기화나 경쟁 상태와 같은 문제가 발생할 수 있다.


어떻게 멀티스레드처럼 동작하는 지 살펴보기 전에 이해를 돕기 위해 자바스크립트의 런타임 과정을 살펴보면 좋을 것 같아 넣게 되었다.

자바스크립트 런타임이란?

자바스크립트 런타임은 자바스크립트 코드가 실행되는 환경이다. 웹 브라우저의 내부는 가장 대표적인 자바스크립트 런타임 환경으로 V8이나 SpiderMonkey과 같은 내장엔진을 포함하고 있다.

또한, Node.js와 같은 서버 측 환경에서도 자바스크립트 코드를 실행할 수 있다.

자바스크립트 런타임 환경에서 중요한 역할을 하는 구성요소

이 각각의 구성요소는 자바스크립트의 실행과 관련한 특별한 역할을 담당하며, 이들은 서로 상호작용하면서 자바스크립트 코드의 비동기적 실행을 지원한다.

  1. 메모리 힙(Memory Heap) : 객체들이 할당되는 공간
  2. 콜 스택(Call Stack) : 함수의 호출을 추적하는 공간
  3. 이벤트 루프(Event Loop) : 콜 스택 내의 함수가 모두 실행되었는지를 주기적으로 확인. 콜 스택이 비어 있을 때마다 이벤트 루프는 태스크 큐에서 함수를 가져와 콜 스택에 푸시한다.
  4. 태스크 큐(Task Queue) : 이벤트 핸들러나 setTimeout 같은 비동기 작업의 결과를 대기시키는 공간
  5. 웹 API(Web APIs) : 브라우저에서 제공하는 API. 브라우저의 무언가를 조작할 때 도와주는 역할

자바스크립트 코드가 실행되면, 제일 먼저 메모리 힙과 콜 스택이 초기화가 된다. 그리고 코드 실행 중 웹 API와 같은 비동기 함수들을 만나게 되면, 해당 함수들은 백그라운드에서 처리되고 완료가 되었을 경우 태스트 큐로 콜백을 전송한다. 이벤트 루프는 콜 스택이 비어있을 때마다 태스크 큐의 함수를 콜 스택으로 이동시킨다.


그런데 어떻게 멀티 스레드처럼 동작하는 것처럼 보여?

자바스크립트는 실제로 멀티 스레드로 동작하지 않지만, 이벤트 루프, 웹 API, 백그라운드 스레드 등의 메커니즘과 비동기 프로그래밍 패턴 덕분에 멀티 스레드처럼 보이게된다.

  1. 웹 API와 백그라운드 스레드 :
    • 웹 브라우저에서 제공하는 웹 API는 setTimeout, XMLHttpRequest, fetch와 같은 비동기 함수들을 백그라운드에서 실행시킨다.
    • 이러한 함수들은 메인 스레드를 블로킹하지 않고 백그라운드 스레드에서 작업을 처리하며, 그 결과를 태스크 큐에 넣는다.
  2. 이벤트 루프와 태스크 큐 :
    • 이벤트 루프는 메인 스레드에서 실행되며 콜 스택이 비었을 때 태스크 큐에 있는 작업을 콜 스택으로 가져와 실행한다.
    • 이 메커니즘 덕분에 비동기 작업의 결과를 순차적으로 처리할 수 있으며, 여러 비동기 작업들이 동시에 일어나는 것처럼 느껴진다.
  3. 비동기 처리 :
    • promiseasync/await을 사용하여 비동기 작업의 결과나 예외 상황을 효과적으로 다룰 수 있다.
    • 이를 통해 비동기 로직을 동기적인 코드처럼 깔끔하게 작성할 수 있다.


결론

“자바스크립트의 동작 방식들이 멀티 스레드처럼 보일 뿐 실제로 그렇게 동작하는 것이 아니지만, 다양한 방법으로 멀티 스레드 동작처럼 작동하게 한다.”



Reference

자바스크립트의 동작 원리

싱글스레드(Single thread) vs 멀티스레드 (Multi thread)

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.