Node.js는 왜 비동기 처리 방식을 이용할까?

zooneon·2021년 3월 19일
3

오늘 아침, 학교 선배와 운동을 끝내고 집으로 가는 길에 얘기를 하다가 이건 블로그각이다! 라는 생각이 들어 바로 글을 쓰게 됐다. (유튜브각을 찾은 유튜버가 이런 마음일까..)

학교 선배는 원래 Java기반 Spring 프레임워크를 사용하였는데, 이번에 인턴을 하게 되면서 Javascript기반의 Node.js를 공부하고 있다고 하였다.

공부를 하면서 Node.js의 비동기 처리 방식에 익숙해지지 않는다라는 말을 하였고, 왜 Node.js 애플리케이션은 DB 접근과 같은 요청을 비동기적으로 처리할까? 라는 주제로 얘기를 나누었다.

자바스크립트의 작동 원리를 바탕으로 간단하게 정리하면 좋을 것 같다는 생각이 들었다.


먼저 비동기 작업을 어떻게 처리하는지 간단하게 알아보자

⚙️ 비동기 처리 방식

Javascript 엔진은 Javascript로 작성한 코드를 해석하고 작동하는 인터프리터이다.

대표적인 엔진으로는 Google의 V8 엔진이 있으며, 크롬과 Node.js에서 사용한다.

자바스크립트는 기본적으로 싱글 쓰레드(Single-Thread) 기반 언어이다.

즉, 한 번에 한 가지 일만 처리할 수 있다.

싱글 쓰레드 기반의 자바스크립트가 비동기 작업을 어떻게 처리하는지 영역별 설명을 통해 알아보자

Call Stack

호출 스택(Call Stack)은 실행되는 순서를 기억하는 자료구조이다.

만약 함수를 실행하면 호출 스택에 들어가고, 그 함수 안에서 다른 함수를 호출했다면 호출한 함수도 스택에 쌓인다.

함수의 작업이 끝나고 반환되면 스택에서 제거되고, 이런 작업이 반복되는 방식으로 작동한다.

스택의 자료구조적인 특성을 이용하여 작업들을 처리하는 원리인 것이다.

작업을 처리하는 호출 스택이 하나이기 때문에 자바스크립트는 싱글 쓰레드 기반 언어라고 불린다.

Memory Heap

동적으로 생성된 인스턴스(객체)가 저장되는 공간이다.

또한 작업들이 진행되면서 생성되는 변수나 함수들이 저장되는 공간으로 사용된다.

Task Queue

자바스크립트 런타임 환경에서는 처리해야 하는 작업들을 임시로 저장하는 큐(queue)가 있는데 그게 바로 Task Queue이다.

자바스크립트에서 비동기 요청이 들어오면 호출 스택(Call Stack)으로 들어가서 바로 처리하는 것이 아닌, Task Queue로 들어가게 된다.

호출 스택에 있는 일들이 모두 처리되고 비게 될 경우 Task Queue에 있는 작업들을 들어온 순서대로 dequeue하여 호출 스택에 넣는다.

Event Loop

이벤트 루프는 자바스크립트가 비동기 작업을 처리할 수 있게 해주는 핵심 역할을 한다.

이벤트 루프는 우선 호출 스택에 작업이 있는지 확인한다.

작업이 있으면 호출 스택에 있는 작업을 먼저 실행하고, 호출 스택에 있는 작업이 모두 끝나면(호출 스택이 비어 있으면) Task Queue를 확인하여 대기 중인 작업들을 순서대로 호출 스택에 넣는다.

이런 식으로 이벤트 루프는 호출 스택에 현재 실행 중인 작업이 없는지와 작업 큐에 대기 중인 작업이 있는지 반복적으로 확인한다.

while (queue.waitForMessage()) {
  queue.processNextMessage()
}

MDN 문서에서는 이벤트 루프를 이 코드로 설명하고 있다.

즉, 처리해야하는 작업이 있으면 while문 안으로 들어가 해당 작업을 처리하고, 다시 큐로 돌아와 대기 중인 작업이 있는지 확인하는 것이다.


이런 방법으로 자바스크립트는 비동기 작업을 처리하고, 비동기 작업을 통해 작업들이 동시에 일어나는 것처럼 보이게 한다.

자바스크립트는 싱글 쓰레드지만 브라우저와 Node.js의 도움을 받아 비동기적으로 작업을 처리할 수 있게 되었다.

그렇다면 왜 비동기 처리 방식을 이용할까?

❓ 왜 비동기 처리 방식을 이용할까?

자바스크립트는 위에서 계속 말했듯이 싱글 쓰레드 기반 언어이다.

그렇기 때문에 기본적으로 한 번에 하나의 작업을 처리할 수 있다.

근데 만약 IO 작업이나 DB 접근과 같이 시간이 오래 걸리는 작업을 싱글 쓰레드로, 그것도 동기적으로 처리한다면 작업이 끝날 때까지 다른 작업을 못 하고 대기만 해야한다.

이는 상당히 비효율적이고, 사용자도 상당히 큰 불편을 호소할 것이다.

비동기 방식의 장점으로는 병렬 처리를 쓰레드로 처리하지 않으므로 멀티 쓰레드가 갖는 자원적인 문제에서 자유롭다는 점이다.

하지만 이벤트를 처리하는 Event Loop는 싱글 쓰레드로 이루어져 있기 때문에 이벤트가 비동기적으로 처리되더라도 작업 자체가 오래 걸린다면 서버 전체에 영향을 줄 수 있다는 단점도 있다.


작동 원리에 대해 너무 간단하게 정리해서 자세한 내용은 나중에 따로 작성해봐야겠다.

나도 전에 Node.js를 사용해봤던 경험이 있지만, 왜 진작 이런 의문을 갖지 않았었나 라는 생각이 들었다.

그래도 이번 기회에 생각해 볼 수 있어 너무 좋았고, 학교 선배에게 너무 감사할 따름이다.

역시 혼자 공부하는 것보다 이렇게 다른 사람과 얘기하고, 생각을 공유할 때 더 많이 배우는 것 같다.

그리고 이번 기회를 계기로 어떤 공부를 하더라도 더 많은 의문을 갖고 공부해야겠다는 생각이 들었다.


📚 참고

profile
블로그 이전했습니다. https://blog.zooneon.dev

0개의 댓글