Node.js란

박종대·2022년 9월 30일
0

Javascript / Typescript

목록 보기
4/4

Node.js

Node.js는 chrome v8 javascript 엔진으로 빌드된 javascript 런타임 이라고 정의되어 있습니다. 정의를 보면 node.js는 자바스크립트 실행기가 맞습니다. 그런데 Node.js는 V8 엔진과 더불어 libuv 라는 라이브러리를 사용하여 이벤트 기반, 논 블로킹 I/O 모델을 구현하고 있다고 말합니다. 이에 대해 자세히 알아보겠습니다.

용어 정의

넘어가기 전에 용어들을 명확히 짚고 넘어가야 할 것 같습니다.

  • 이벤트 기반 : 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식, 미리 지정해둔 작업이라 함은 콜백함수나 이벤트 리스너 등이 될 수 있다.
  • 논 블로킹 I/O : 이전 작업이 완료될 때 까지 대기하지 않고 다음 작업을 바로 수행하는 것.
  • 호출 스택(Call Stack) : 실제 실행할 작업들이 쌓여있는 스택
  • 백그라운드 : 타이머나 이벤트 리스너들이 대기하는 곳이고 여러 작업이 동시에 수행될 수 있다.
  • 태스크 큐 : 백그라운드에서 처리된 작업의 콜백함수가 콜 스택으로 가기 전에 대기하는 큐
  • 이벤트 루프 : 호출 스택이 비어 있으면 태스크 큐에서 호출 스택으로 하나씩 불러오는 로직을 담당하는 것.

구조


대략적인 구조를 그림으로 표현해봤습니다. Task Queue같은 경우 여러개의 Queue로 구성되어 있지만 편의상 하나의 큐인 것처럼 그렸습니다. Node 구조를 이해하기 위해 프로그램 하나를 작성해 보겠습니다.

const exec = () => console.log('실행');

console.log('시작');
setTimeout(exec, 0);
console.log('완료');

javascript 개발을 조금 해보신 분이라면 시작 -> 완료 -> 실행 순으로 출력됨을 금방 알 수 있을 겁니다. 이를 Node 구조에 맞춰서 분석해보겠습니다.

호출 스택에는 log -> setTimeout -> log 순서대로 쌓일 것입니다. 하지만 setTimeout에서는 0초 후라는 timer가 background로 이동하게 됩니다. setTimeout은 호출 스택에서 사라졌으니 다음 log인 완료가 출력되게 됩니다. 아직 실행이라는 결과가 출력되기 전인데 말입니다.

background에서는 timer가 timeout 되면 callback 함수인 exec를 task queue로 보냅니다. 그리고 event loop는 호출 스택이 비어 있으면 task queue에서 선입 선출로 task를 호출 스택으로 올려 보냅니다. 이제서야 exec 콜백 함수가 실행되어 '실행' 이라는 메세지가 출력되게 됩니다.

여기서 중요한 점은 event loop는 호출 스택이 비어 있으면 task queue에서 task를 올려 보낸다고 했습니다. 그래서 console.log() 의 실행이 모두 끝나야만 exec 콜백함수가 실행될 수 밖에 없는 구조였던 것입니다. console.log() 를 몇백번 실행해도 결과는 똑같을 것입니다.

이용

원래 Event loop 구조나 Task queue의 구조는 훨씬 복잡합니다. 하지만 개략적으로 돌아가는 방식에 대해 알아봤습니다. 그럼 이런 구조를 알았으니 실전에서 이용을 해야겠습니다. 어떻게 이용할 수 있을까요?

Node의 구조 덕분에 논 블로킹으로 콜백 함수들을 비동기로 실행할 수 있습니다. 즉, 처리 결과를 기다리지 않고도 다음 작업을 진행할 수 있다는 의미입니다.

A의 작업 결과가 B의 작업에 쓰인다면 B 입장에서는 A의 작업 결과를 기다려야만 합니다. 그런데 A의 작업 결과와 B의 작업 결과에 연관성이 없다면 A와 B의 작업은 서로를 기다릴 필요 없이 비동기로 실행하는 것이 이득일 것입니다.

예를 들어 3+3 task, 4+4 task 두 개의 task가 있다고 했을 때 3+3의 결과와 4+4의 결과는 전혀 연관이 없습니다. 둘은 비동기로 실행하는 것이 이득일 것입니다.

이 때 문제가 발생할 수 있는 점은, 서로 연관은 없지만 그래도 실행된 순서대로 결과를 받고 싶은 경우가 있을 수 있습니다. 만약 3+3 task가 5초, 4+4 task가 3초 걸린다라고 가정했을 때 3+3 task를 먼저 실행했지만 4+4 task의 결과가 2초 먼저 와버리는 현상이 발생할 수 있습니다.

이런 경우를 해결하기 위해 Javascript에서는 Promise라는 개념이 존재합니다. Promise는 중요한 개념이기 때문에 따로 게시글을 작성하도록 하겠습니다.

profile
Frontend Developer

0개의 댓글