Node란
Node란? Chrome V8 engine으로 빌드된 Javascript 런타임
서버
노드를 통해 다양한 자바스크립트 애플리케이션을 실행할 수 있지만, 노드는 서버 애플리케이션을 실행하는 데에 제일 많이 사용된다.
기존에는 자바스크립트 프로그램을 브라우저 위에서만 작동시킬 수 있었다.
브라우저 외의 환경에서 자바스크립트를 실행시키기 위한 노력이 많이 있었으나, 자바스크립트의 실행 속도 문제 때문에 모두 큰 호응을 얻지 못했다.
하지만 2008년 구글이 v8엔진을 사용하여 크롬을 출시하자, 기존의 브라우저 엔진과 비교해 상당히 빠른 속도로 인해 많은 호응을 얻었고, 라이언 달은 2009년 노드프로젝트를 시작하였다.
노드는 v8과 더불어 libuv 라는 라이브러리를 사용한다. v8과 libuv 는 C, C++로 구현 되어 있다.
libuv 라이브러리는 노드의 특성인 이벤트 기반, 논블로킹 I/O 모델을 구현하고 있다.
이벤트 기반
이벤트 기반이란 이벤트가 발생할 때 미리 이벤트 리스너에 등록해준 작업을 수행하는 방식을 의미한다.
코드를 위에서 부터 한 줄 씩 실행하는데, 호출하는 코드를 만나면 호출 스택에 넣는다. 그리고 함수가 실행이 완료되면 호출스택에서 지워진다.
- 이벤트 루프 : 이벤트 발생시 호출할 콜백 함수를 관리, 호출된 콜백 함수의 실행순서를 겨정, 노드가 종룓될 때까지 이벤트 처리를 위한 작업을 반복
- 백그라운드 : setTimeout같은 타이머나 이벤트 리스너들이 대기하는 곳 자바스크립트가 아닌 다른 언어로 작성된 프로그램이라고 봐도 된다.
- 태스크 큐 :이벤트 발생 후 백그라운드에서는 태스크 큐로 타이머나 이벤트 리스너의 콜백 함수를 보낸다. 정해진 순서대로 콜백들이 줄을 서 있으므로 콜백 큐라고도 부른다. 콜백들은 보통 완료된 순서대로 줄을 서 있지만 특정한 경우에는 순서가 바뀌기도 한다.
호출스택을 이용하여 setTimeout 함수의 실행과정을 설명해보자
const run = () => {
console.log("3초 후 실행");
};
console.log('시작');
setTimeout(run, 3000);
console.log("끝");
먼저 전역 컨택스트인 anonymous가 호출스택에 들어감. 그 뒤 setTimeout이 들어감
호출스택에 들어간 순서와 반대로 실행되므로, setTImeout이 먼저 실행된다.
실행되면 타이머와 함께 run 콜백을 백그라운드로 보내고 setTimeout은 호출 스택에서 빠진다. 그 다음으로 anonymous가 호출 스택에서 빠진다.
백그라운드에서는 3초를 센 후 run함수를 태스크 큐로 보낸다.
3초를 세었다는 것은 백그라운드에 맡겨진 작업이 완료된 것으로 이해해도 된다.
태스크큐는 실제로는 여러 개의 큐로 이루어져 있다.
이벤트 루프에서는 정해진 규칙에 따라 콜백 함수들을 호출 스택으로 부른다.
호출 스택에서 anonymous까지 실행이 완료되어 호출스택이 비어있으면 태스크 큐에서 함수를 가져와 호출스택에 넣고 실행한다.
호출스택으로 올려진 run 이 실행되고, 이벤트 루프는 태스크 큐에 콜백 함수가 들어올 때까지 계속 대기한다.
만약 호출 스택에 함수들이 너무 많이 들어 있으면 3초가 지난 후에도 run 함수가 실행되지 않을 수 있다.
이벤트 루프는 호출 스택이 비어 있을 때만 태스크 큐에 있는 run함수를 호출 스택으로 가져온다.
이렇듯 setTimeout 의 시간이 정확하지 않을 수도 있다.
논블로킹 I/O
이벤트 루프를 잘 활용하면 오래 걸리는 작업을 효울적으로 처리할 수 있다.
작업에는 두 가지 종류가 있는데 동시에 실행될 수 있는 작업과 동시에 실행된 수 없는 작업이 있다.
자바스크립트의 코드는 동시에 실행될 수 없다. 하지만 자바스크립트에서 돌아가는 것이 아닌 I/O작업은 동시에 처리될 수 있다.
이런 작업을 할 때 노드는 논블로킹 방식 (이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행함.) 을 제공
(블로킹은 이전 작업이 끝나야만 다음 작업을 수행할 수 있는 것을 의미 )
논블로킹을 이용하면 여러 작업을 동시에 처리하여 빨리 끝낼 수 있는데
이런 I/O작업을 최대한 묶어서 백그라운드로 넘겨야 시간이 절약된다.
예시로는 오래 걸리는 함수를 setTimeout을 0초를 걸어 백그라운드로 보내버리는 법이 있다.
이는 코드를 논블로킹으로 만들기 위해 사용하는 기법이다. (사실 노드에서는 다른 방식을 주로 이용함.)
===> 예제
- 바꾸기 전
const longRunningTask = () => {
//오래 걸리는 작업
console.log('작업 끝');
}
console.log('시작');
longRunningTask();
console.log("다음 작업");
- 바꾼 후
const longRunningTask = () => {
//오래 걸리는 작업
console.log('작업 끝');
}
console.log('시작');
setTImeout(longRunningTask(),0);
console.log("다음 작업");
논 블로킹 방식으로 코드를 작성하더라도 코드가 전부 직접 작성한 것이라면 전체 소요시간이 짧아지지는 않는다.
코드가 전부 동시에 실행지 않기 떄문.
단순히 실행 순서만 바뀌었음.
하지만 오래 걸리는 작업을 처리하는 경우 이를 이용해 간단한 작업들이 대기하는 상황을 막을 수 있다는 점에 의의가 있다.
그리고 이는 동시성과 같은 의미가 아니다.
동시성은 동시 처리가 가능한 작업을 논블로킹 처리해야 얻을 수 있다.
'Back-end > Node.js' 카테고리의 다른 글
Sequelize 사용하기 (0) | 2021.10.18 |
---|---|
multipart/form-data를 처리하는 패키지 비교 (1) | 2021.10.07 |
Node에서의 Module (0) | 2021.08.09 |
PM2로 무중단 배포하기 (2) | 2021.07.17 |
Node-sass 6.0.0 incompatible with ^4.0.0. (0) | 2021.05.20 |