Leon Chaewon Kong's dev blog

Node.js의 특징

목차

1. 개요

  • 1.1 Node.js 소개
  • 1.2 Node.js에 대한 흔한 오해

2. 주요 특징

  • 2.1 Non-Blocking I/O와 Event-Driven
  • 2.2 단일 스레드

3. Node.js의 장점과 단점

  • 3.1 Node.js의 장점
  • 3.2 Node.js의 단점

4. 마치며
출처 및 참고문헌

1. 개요

1.1 Node.js 소개

Node.js는 Google에 의해 개발된 Chrome의 V8 엔진을 이용한다. V8엔진은 빠른 속도로 JavaScript를 해석하고 기계가 인식할 수 있는 코드로 변환하는 역할을 담당하는 엔진이다. 지속적으로 성능이 향상되고 있다.

주지하다시피 Node.js는 JavaScript를 이용한다. 주요 특징으로는 Non-Blocking I/O와 단일 스레드, 이벤트 기반의 비동기 처리 등이 있다.

1.2 Node.js에 대한 흔한 오해

Node.js는 웹서버가 아니다. Node.js는 Chrome V8 엔진을 이용한 JavaScript 런타임이다. 물론 Node.js로 서버를 구현할 수 있다. 마치 Python으로 서버를 구현할 수 있는 것처럼 말이다. Node.js로 서버를 구현하기 위해서는 HTTP 서버를 직접 작성해야 한다.

2. 주요 특징

2.1 Non-Blocking I/O와 Event-Driven

I/O에는 Blocking과 Non-Blocking이 있다. 파일이든 HTTP 요청이든 I/O에는 처리하는 시간이 소요된다. Blocking I/O의 경우, 여러개의 요청이 있을 때 하나의 요청을 처리한 후 다음 요청을 처리한다. 요청이 처리되는 대기시간 동안 모든 작업은 일시 중단된다. 반면 Non-Blocking I/O에서는 하나의 요청을 실행하고, 결과값을 기다리는 동안 다른 요청들도 순차적으로 실행한다. 결과값이 돌아오는 순서대로 처리 결과를 출력한다.

한편, Event-Driven이란 이벤트에 따라 프로그램의 실행을 제어하는 구현방식을 말한다. 어떤 이벤트가 발생하는지 살펴보다가 해당 이벤트가 발생할 경우 Callback 함수(혹은 원하는 작업)을 실행하는 방식을 말한다.

생활의 예로 보면 은행에 자동이체를 등록하는 상황을 생각할 수 있습니다. 25일에 월급이 입금되기 때문에 월급이 입금(이벤트 발생, 통장 상태 변화)되면, 각종 대출과 적금, 공과금을 내도록(원하는 작업, 콜백 함수 실행) 등록해두면 매월 자동으로 이체가 실행되는 것입니다.

출처: Hun’s Story, “Node.js에 대하여”

Node.js는 비동기 작업(Non-Blocking I/O)를 구현하기 위해 Event Loop를 이용해 작업을 처리한다. 아래 예시를 통해 의미를 살펴보자.

console.log("Start!");
setTimeout(() => console.log("First Timeout"), 2000);
setTimeout(() => console.log("Second Timeout"), 1000);
console.log("All Tasks Finished");

위와 같은 코드를 보자. 만약 Blocking I/O 였다면 출력 내용은 아래와 같았을 것이다.

Start!
First Timeout
Second Timeout
All Tasks Finished

그러나 Non-Blocking I/O와 비동기 처리에서는 실제로 아래와 같은 순서로 작업이 진행된다.

Start!
All Tasks Finished
Second Timeout
First Timeout

우선 작업들이 Call Stack에 올라간다. 이후 하나씩 실행되는데 모든 작업이 실행되어 Call Stack이 비게 되면 Callback Queue에 담긴 Callback 함수들을 Call Stack으로 가져와 처리한다. Callback이란 해당 작업이 처리완료되어야 실행되는 함수다. 즉, Callback Queue에 있는 Callback 함수들은 **우리가 짠 코드의 순서대로 담겨 있는 것이 아니라, 실행이 완료된 순서대로 담겨 있다. **

setTimeout함수 2개를 보면 “First Timeout”은 2초, “Second Timeout”은 1초 뒤에 console.log가 실행되도록 규정되어 있다.

따라서 Callback Queue에는 두번째 setTimeout이 먼저 올라가게 되는 것이다.

Node.js의 대부분의 I/O와 내부 모듈들은 비동기적인 처리를 지원한다. 이를 통해 Node.js는 단일 스레드(Single Thread) 모델을 채용하여 고성능의 빠른 처리를 가능케 하였다.

2.2 단일 스레드

일반적인 서버에서는 처리량이 많아지면 여러개의 스레드를 돌려 이를 동시에 처리한다. 스레드가 여러개 만들어지면 메모리 사용량이 늘어나고 CPU 등 자원이 낭비되게 된다.

반면, Node.js는 단일 스레드 모델을 기반으로 하고 있다. 하나의 스레드가 request를 받으면 이를 처리하고, 데이터베이스 접근이나 File I/O처럼 작업에 시간이 걸리는 경우 요청을 보내놓고 다음 작업을 처리하다가 요청한 작업이 끝나면 이벤트를 받아서 처리한다.

CPU는 요청한 작업이 끝난 후 오는 응답을 기다리며 대기하지 않고 지속적으로 다른 작업들을 처리하므로 연산 처리 능력이 낭비되지 않는다.

물론 Node.js가 실제로 단일 스레드인 것은 아니다. 단일 스레드의 경우 다중 코어 CPU가 전제되는 현재, 다중 코어를 모두 활용해 효율적인 일처리를 하기에 어려움이 있다. Node.js는 클라이언트로부터 들어오는 요청들을 단일 스레드로 받고, 내부적으로는 다중 스레드로 작업을 수행한다.

중요한 것은 이 스레드를 개발자가 아닌 플랫폼이 관리해 준다는 것이다. 개발자는 스레드 하나를 관리하듯 프로그래밍하면 플랫폼이 여러 스레드를 효율적으로 운용하게 된다.

3. Node.js의 장점과 단점

3.1 Node.js의 장점

  1. 고성능
    Node.js는 싱글 스레드 모델로 CPU 사용량은 비교적 낮지만 짧은 시간에 대량의 클라이언트 요청을 처리해야 하는 웹 어플리케이션에 적합하다.
  2. 프론트엔드와 백엔드를 같은 언어로 관리
    JavaScript 만으로 프론트엔드와 백엔드를 모두 구현하므로 코드를 관리하는 것이 용이하고, 프론트엔드 개발자가 백엔드까지 개발할 수 있다. 웹개발자들이 익숙한 JavaScript 기반이므로 새로운 언어를 습득하거나 새로운 언어를 사용할 수 있는 개발자를 뽑지 않아도 웹 어플리케이션 개발이 가능하다.
  3. 노 버퍼링
    Node.js 어플리케이션엔 데이터 버퍼링이 없고, 데이터를 chunk로 출력한다.
  4. 발달된 커뮤니티와 효율적인 패키지 관리
    광범위하고 매우 발달된 커뮤니티와 수많은 라이브러리, 프레임워크 등이 빠른 개발을 가능하게 한다. 또, 사용하는 라이브러리나 미들웨어 등을 package.json에 json 형식으로 관리해주어 패키지 관리가 효율적이고 효과적이다.


3.2 Node.js의 단점

  1. CPU 사용률이 높은 어플리케이션에서 서버에 부하가 발생 가능
    싱글 스레드 모델이기 때문에 CPU 부하가 커질수록 처리되면 효율성이 크게 체감된다.
  2. 잦은 Callback과 JavaScript 특유의 한계로 인한 낮은 코드 가독성
    JavaScript라는 불완전한 언어의 한계로 인해 낮은 가독성과 비교적 빈번한 버그 등의 문제가 발생한다.
  3. 실행 전 에러 확인 불가능
    컴파일시 에러를 확인하는 것이 불가능하며 실행해봐야 에러 여부를 알 수 있다.
  4. C, C++ 기반 서버보다 낮은 성능
    V8 엔진이 C++로 짜여져 있고, JavaScript를 컴파일하기에 C++로 짜여진 서버보다는 느리다.
  5. Garbage Collection시 서버의 일시적 정지
    V8 엔진은 Garbage Collection을 기반으로 메모리를 관리하는데 이 과정에서 서버가 순간적으로 멈출 수 있다.



4. 마치며

Node.js는 V8 엔진을 활용한 자바스크립트 런타임이다. Non-Blocking I/O와 Event-Driven, 단일 스레드 모델 등을 바탕으로 하여 짧은 시간에 대량의 요청을 처리하는 서버에서 높은 성능을 보인다. JavaScript 단일 언어로 프론트엔드와 백엔드 모두가 개발 가능하기 때문에 쉽고 빠르게 웹 풀스택 개발이 가능하다.

한편 싱글 스레드 모델로 인해 요청에 대한 CPU 부하가 커질수록 효율성이 체감된다. Garbage Collection시 서버가 일시적으로 정지하는 문제 또한 가진다.

Node.js는 Netflix, LinkedIn, Uber, PayPal, eBay 등의 기업에서 사용될 만큼 웹 개발에서 널리 사용된다. 적합한 장소에서 사용할 경우 최상의 성능과 편리한 개발을 도모할 수 있을 것이다.

출처 및 참고문헌