Node.js의 특징을 요약하면 아래와 같다.
- javaScript를 브라우저가 아닌 서버 환경에서 실행할 수 있게 한다.
- 브라우저에서 사용할 수 없는 네트워크, 스트림, 파일 시스템 접근 등 서버 측 개발에 필요한 다양한 기능을 제공한다.
- 비동기 I/O 모델을 채택하고 있으며, 이를 관리하기 위해 이벤트 루프라는 개념을 사용한다. (*사실 이건 자바스크립트의 특징이며 node.js는 자바스크립트를 실행할 수 있도록 만든 환경이기 때문에 자바스크립트 특징을 그대로 사용하고 확장한 것)
- npm(Node Package Manager)를 통해 수 많은 외부 라이브러리를 쉽게 설치하고 사용한다.
이제 각 특징에 대해 알아보자.
런타임
기존의 자바스크립트는 웹 브라우저 안에서만 동작했지만, Node.js는 자바스크립트를 서버 측에서 실행할 수 있도록 해주는 런타임 환경으로, 서버 측에서도 사용할 수 있도록 만들어졌다.
Node.js는 런타임 환경이라고 했는데, 런타임(runtime)이 무엇일까?
런타임 환경은 특정 언어로 짜여진 프로그램을 실행할 수 있는 환경을 말하며, 프로그램이 실행될 때 필요한 기본적인 라이브러리, API, 메모리 관리, I/O (입출력)등을 포함한다. 위에서도 잠깐 언급했듯이 원래 자바스크립트는 브라우저에서만 실행되는 클라이언트 측 스크립팅 언어로 설계되어 있었지만, V8 JavaScript 엔진(구글 크롬 브라우저에서 사용되는 엔진)을 기반으로 자바스크립트를 브라우저가 아닌 서버측에서 실행할 수 있도록 만든것이다.
이벤트 기반 비동기 I/O
이벤트와 이벤트 기반 동작의 개념은 아래와 같다.
-
이벤트 : 웹 브라우저 상에서 일어나는 모든 일들을 의미한다. 클릭, 드래그, 새로고침 등 페이지상에서 일어날 수 있는 모든 행위들이 이벤트가 된다.
-
이벤트 기반 동작 : 이벤트 발생 시 해당 이벤트에 미리 설정한 작업을 수행하는 작업 방식을 말한다.
이벤트와 이벤트 기반 동작 방식을 정리하면 아래와 같이 정리할 수 있다.
- 이벤트에 따른 작업을 미리 지정한다.
- 사용자로부터 이벤트가 발생한다.
- 이벤트에 등록된 이벤트 기반 동작을 실행한다.
조금 더 개발자 용어로 수정한다면 아래와 같이 정리 할 수 있다.
- 이벤트 리스너에 콜백 함수를 등록한다.
- 클라이언트로부터 이벤트가 발생한다.
- 이벤트에 등록된 콜백함수를 호출해서 작업을 실행한다.
Node.js에서는 이러한 이벤트들을 관리하고 실행하기 위해 이벤트 루프(Envent Loop)라는 매커니즘을 사용한다. 이벤트 루프는 한번의 여러개의 이벤트가 발생했을 때 이벤트에 대한 콜백함수 호출 순서를 판단하는 역할을 하며, 이벤트 큐(Event queue)를 감시하고 큐에 있는 이벤트를 하나씩 처리한다. 예를 들어 파일 읽기 작업이 요청오면, 파일 읽기가 완료된 후 실행될 (이벤트 리스너에 미리 넣었던)콜백함수가 큐에 추가되고 이벤트 루프가 하나씩 처리한다.
위와 같은 이벤트 기반 동작은 비동기 I/O(입출력)로 동작하고 이로 인해 여러 클라이언트의 요청을 동시에 처리할 수 있도록 해주며, I/O 작업(파일 읽기/쓰기, 네트워크 요청 등)이 완료될 때까지 기다릴 필요 없이 다른 작업을 계속 진행 할 수 있다.
그리고 노드에서 입출력 작업은 다른 작업과 동시에 실행될 수 있는데, 이러한 동작을 논 블로킹 입출력 모델이라고 부른다.
- 블로킹 : 한 작업이 시작되면 끝날 때까지 다른 요청은 작업을 수행하지 못하고 기다려야하는 방식
- 논 블로킹 : 이전 작업이 끝나지 않아도 요청이 오는대로 수행하는 방식
싱글 스레드
Node.js는 싱글 스레드(Single Threaded) 아키텍처를 사용한다.
하나의 스레드가 모든 작업을 처리하지만, 비동기 작업과 이벤트 루프 덕분에 많은 요청을 효율적으로 처리한다. 이벤트 루프는 작업을 처리할 때까지 블로킹되지 않기 때문에 하나의 스레드가 많은 수의 비동기 작업을 관리할 수 있다. 예를 들어 데이터베이스 쿼리를 보내고 그 결과를 기다리는 동안 Node.js는 다른 클라이언트의 요청을 처리할 수 있다.
장/단점
장점은 아래와 같다.
- 자바스크립트를 동일하게 사용해서 서버단 로직을 처리할 수 있다는게 가장 큰 장점
- 논 블로킹 I/O 와 단일 스레드 이벤트 루프를 통한 높은 처리 성능
- 이벤트 기반 비동기 방식이라 서버에 대한 부담이 적다
- npm을 이용해 자신이 필요한 라이브러리와 패키지를 검색하고 설치할 수 있기 때문에 개발속도와 효율성이 크게 향상됨
단점은 아래와 같다.
- 이벤트 기반 비동기 방식이라 서버단 로직이 복잡한 경우 콜백 함수의 늪에 빠질 수 있다.
- 코드를 순차적으로 실행하는 것이 아니라 비동기 방식으로 이벤트를 보내고, 응답(이벤트)이 오면 처리하는 방식이기 때문에 java개발을 했던 방식으로 설계하고(동기식) 개발하면 큰 문제가 발생한다.
- 단일 스레드기 때문에 하나의 작업 자체가 많이 걸리는 웹 서비스에는 어울리지 않는다.
- 코드가 수행되어야 코드에 에러가 있는지 알 수 있으며 에러가 난 경우 프로세스가 내려가기 때문에 테스트가 엄청 중요하다.