[JS] 동기/비동기 작업, 이벤트 루프에 대해서

Y_Y·2024년 1월 29일
0

JavaScript

목록 보기
5/5
post-thumbnail

서론

프로젝트를 진행하다가 문득 자바스크립트의 동작 원리가 궁금했다.

자바스크립트는 싱글스레드 언어인데 비동기 처리를 어떻게 하는거지?

여기서 궁금증이 출발하여 같이 일하는 벡엔드 동료와 얘기를 해보는데 백그라운드 스레드가 비동기를 처리한다는 얘기를 들었다. 그렇다면 백그라운드 스레드는 어디에 있는거지? 싱글스레드인 자바스크립트가 다른 스레드를 더 사용할 순 없고... 명확한 팩트인 자바스크립트는 싱글스레드 언어이다를 바탕으로 추론을 진행하였지만 논의끝에 도달한 결론이 틀렸기 때문에 자세하게 알아보고자 한다.

본론

자바스크립트는 싱글스레드 언어이다.

먼저 문장을 이해하려면 단어를 이해해야 하기 때문에 스레드가 무엇인지 생각해보자.

스레드는 프로그램을 실행했을 때 프로세스가 진행되는데 이때 프로세스에서 사용되는 작업의 최소단위를 스레드라고 한다.

그러면 자바스크립트는 프로그램이 실행됐을 때 하나의 스레드를 사용하여 프로그램을 동작한다고 이해할 수 있다.

그렇다면, 단순하게 생각해본다면 작업을 하나로만 한다고 이해했을 때 순차적으로 하나 시작하면 하나 마무리하는 방식인가?라고 고민할 수 있을 것이다.

  let count = 0;
  function foo() {
    console.log('foo', count++);
    setTimeout(() => console.log('setTimeout', count), 0);
    bar();
  }
  function bar() {
    console.log('bar', count++);
  }

  console.log('start');
  foo()
  bar()
  console.log('end')

/** output
start
foo 0
bar 1
bar 2
end
setTimeout 3
*/

위 코드를 실행했을 때 출력 값은 저렇게 star, end 이후에 setTimeout 3 이라고 출력이 되는데,

앞서 언급한 방식대로 이해했더라면 아래처럼 출력되어야 하지 않을까? 생각해볼 수 있다.

/** output
start
foo 0
setTimeout 1
bar 2
bar 3
end
*/

결과값을 보면 setTimeout 안에 있는 console.log 함수가 설정한 시간 후에 따로 출력되는 모습을 알 수 있는데 어떻게 된 걸까?

어떻게 비동기 처리를 하나요?

결론부터 말하자면 자바스크립트를 실행했을 때 런타임 환경에서 비동기 로직들을 따로 처리해주는 것이다.

setTimeout이라는 함수가 런타임 환경에서 실행하고 있기 때문에 비동기적으로 코드가 실행되는 것이다.

자바스크립트를 실행했을 때 그 언어를 실행시켜주는 환경이 있을 것인데, 런타임 환경이라고 부른다. 런타임 환경은 Browser(주로 크롬 사파리와 같은) 또는 Node.js가 있다.

크롬을 예를 들자면 프로그램이 브라우저 상에서 실행 됐을 때 Chrome V8 엔진을 이용해 코드를 실행하고 크롬 브라우저에서 DOM 관리, 이벤트 처리, 네트워크 통신 등을 담당한다.

약간 더 깊게 들어가보자

자바스크립트의 동작원리

자바스크립트의 동작원리를 살펴보면 스택 하나를 가지고 저장되어 있는 일들을 한 번에 하나씩만 처리할 수 있다. 여기서 중요한 규칙은 메시지 큐의 작업은 항상 콜스택이 비었을 때 실행된다는 점이다.

  • Stack: 함수를 호출했을 때 콜스택이 쌓이는 스택 영역
  • Queue: 런타임이 처리해야할 일들을 줄 세우는 메시지(태스크, 콜백) 큐
  • Heap: 객체들을 저장하기 위한 메모리 영역 힙

setTimeout 같은 타이머 함수는 설정한 시간 후 콜백을 바로 실행하지 않고 메시지 큐로 보내기 때문에 실행 시간이 정확히 보장되지 않는다

Event Loop

그리고 위 그림에서 보면 Event Loop라는게 있는데 매우 중요한 요소이다. Event Loop는 stack이 텅 비었을 때(main 코드가 다 실행된 후) 비로소 큐에 있는 로직들을 처리한다.

Event Loop 특징

이벤트 루프의 특징 중에 다음 메세지를 실행하기 이전에 기존 메세지의 실행을 완료한다는 특징이 있다.

이와 같은 특징 덕분에 JS는 공유자원에 대해서 뮤택스와 세마포어와 같은 선점의 기능을 제공하지 않아 동작의 추론이 쉽지만, 단점으로 메시지를 처리할 때 너무 오래 걸리면 웹 애플리케이션이 클릭이나 스크롤과 같은 사용자 상호작용을 처리할 수 없다는 점이 있다.

그래서 예를 들어 브라우저는 "스크립트 응답 없음" 대화상자를 표시해서 이 문제를 완화할 수 있고, 따라서 우리는 메시지 처리를 가볍게 유지하고, 가능하다면 하나의 메시지를 여러 개로 나누는게 현명할 것이다.

메인 스레드와 이벤트 루프에 한해서는 동시성이 없다고 할 수 있지만 런타임 환경 덕분에 동시성이 있다고 할 수 있다.

결론

따라서 자바스크립트는 싱글스레드 언어라고 하는 것이다.

글이 잘 읽히지 않는다면, Blocking-Non Blocking & Synchronous-Asynchronous, 동시성과 병렬성에 대해서 이해하고 출처를 참고해보면 좋을 것 같다.

TMI

프로젝트를 진행하며 많이 배우기도 하고 느낀점도 많았지만 많이 함축해서 생각을 말해보자면, 기술적인 부분에서 크게 와닿았던 것은 기초가 탄탄해야 한다는 것이었다. 코드를 작성할 때 왜 그렇게 작성했는지 분명히 알아야하고, 프레임워크나 라이브러리를 사용하지 않고 바닐라 JS로 작성할 수 있도록 해야 어느 환경에서든 살아남고 그만큼 능력있는 개발자라고 인정받을 수 있지 않을까 싶다.

기술 발전 속도가 매우 빠른 현재 도태되지 않기 위해 변하지 않는 것들에 집중해서 적응력과 습득력이 뛰어난 개발자가 되도록 하자.

살아남았다는 것은 강하다는 것

출처

자바스크립트 동작 원리에 대한 깊은 이해
동시성과 병렬성의 차이
Javascript 동작원리 (Single thread, Event loop, Asynchronous)
MDN Event Loop
유튜브 코딩애플 자바스크립트 동작원리

profile
남을 위해(나를 위해) 글을 쓰는 Velog

0개의 댓글