1. 서버
서버는 네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램이다.
서버는 클라이언트가 요청을 하면 응답을 한다.
2. 자바스크립트 런타임
Node.js는 크롬 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임이다. Node.js는 이벤트 기반, 논블로킹 I/O 모델을 사용해 가볍고 효율적이다. Node.js의 패키지 생태계인 npm은 세계에서 가장 큰 오픈 소스 라이브러리 생태계이다.
런타임은 특정 언어로 만든 프로그램들을 실행할 수 있는 환경을 뜻한다. 즉, 노드는 자바스크립트 프로그램을 컴퓨터에서 실행할 수 있게 해준다.
기존에는 인터넷 브라우저 위에서만 실행할 수 있었다. 그 외의 환경에서는 속도 문제가 있었으나 구글이 V8 엔진을 사용하여 크롬을 출시하자 속도 문제가 해결되었고, 2009년 V8 엔진 기반의 노드 프로젝트가 시작 되었다.
Node.js Core library 위에 Node.js Bindings가 있고, 그 위에 V8(오픈소스 자바스크립트 엔진)/libuv(비동기 I/O)이 있다.
노드는 V8과 더불어 libuv라는 라이브러리를 사용한다. V8과 libuv는 C와 C++로 구현되어 있다. 자바스크립트 코드는 노드가 V8과 libuv에 자동으로 연결해준다. libuv라이브러리는 노드의 특성인 이벤트 기반, 논블로킹 I/O 모델을 구현하고 있다.
3. 이벤트 기반
이벤트 기반(event-driven)이란 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식이다. 이벤트로는 클릭이나 네트워크 요청 등이 있을 수 있다.
이벤트가 발생할 때 수행할 것을 미리 지정해두는데, 이것을 이벤트 리스너(event listener)에 콜백(callback) 함수를 등록한다고 한다.
이벤트가 발생하면 이벤트 리스너에 등록해둔 콜백 함수를 호출한다. 발생한 이벤트가 없거나 발생했던 이벤트를 다 처리하면 노드는 다음 이벤트가 발생할 때까지 대기한다.
여러 이벤트가 동시에 발생했을 때, 어떤 순서로 콜백 함수를 호출할지를 이벤트 루프가 판단한다.
- 이벤트 루프: 이벤트 발생 시 호출할 콜백 함수들을 관리하고, 호출된 콜백 함수의 실행 순서를 결정하는 역할을 담당한다. 노드가 종료될 때까지 이벤트 처리를 위한 작업을 반복하므로 루프라고 불린다.
- 태스크 큐: 이벤트 발생 후 호출되어야 할 콜백 함수들이 기다리는 공간이다. 콜백들이 이벤트 루프가 정한 순서대로 줄을 서 있으므로 콜백 큐라고도 부른다.
- 백그라운드: 타이머나 I/O 작업 콜백 또는 이벤트 리스터들이 대기하는 곳이다.
4. 논블로킹 I/O
이벤트 루프를 잘 활용하면 오래 걸리는 작업을 효율적으로 처리할 수 있다. 오래 걸리는 함수를 백그라운드로 보내서 다음 코드가 먼저 실행되게 하고, 그 함수가 다시 태스크 큐를 거쳐 호출 스택으로 올라오기를 기다리는 방식이다. 이 방식이 논블로킹 방식이다. 논블로킹이란 이전 작업이 완료될 때까지 멈추지 않고 다음 작업을 수행함을 뜻한다.
하지만 싱글 스레드라는 한계 때문에 자바스크립트의 모든 코드가 이 방식으로 시간적 이득을 볼 수 있는 것은 아니다. 현재 노드 프로세스 외의 다른 컴퓨팅 자원을 사용할 수 있는 I/O 작업이 주로 시간적 이득을 많이 본다.
I/O는 입력/출력을 의미한다. 파일 시스템 접근이나 네트워크 요청 같은 작업이 I/O의 일종이다. 이러한 작업을 할 때 노드는 논블로킹 방식으로 동작한다.
블로킹과 논블로킹 말고도 동기와 비동기라는 개념도 있는데, 가볍게 이야기하면 동기와 블로킹이 유사하고 비동기와 논블로킹이 유사하다.
setTimeout(콜백, 0)은 코드를 논블로킹으로 만들기 위해 사용하는 기법 중 하나이다. 노드에서는 다른 방식을 주로 사용한다. setTimeout의 콜백 함수가 태스크 큐로 보내지므로 순서대로 실행이 되지 않고, 다음 작업이 먼저 실행된 후 오래 걸리는 작업이 완료된다.
5. 싱글 스레드
싱글 스레드에서는 주어진 작업을 혼자서 처리해야 하고, 멀티 스레드에서는 여러 개의 스레드가 일을 나눠서 처리한다.
한 번에 한 가지 일밖에 처리 못하므로 논블로킹이 중요하다.
예를 들면, 점원 한 명이서 주문을 차례대로 받고 요리가 완성되면 완료된 순서대로 손님에게 서빙한다. 주문한 순서와 서빙하는 순서가 일치하지 않을 수도 있다. (싱글 스레드) 점원 한 명이서 많은 일을 처리할 수 있지만, 점원이 없어지거나 주문을 받는데 시간이 오래 걸리면 버거울 수 있다.
멀티 스레드 방식에서는 손님이 올 때마다 점원이 한 명씩 맡아 주문을 받고 서빙한다. 손님의 수가 늘어날 수록 점원의 수가 늘어나고, 손님 수가 줄어들었을 때 노는 점원이 생기면 점원을 고용하거나 기존 직원을 해고하는데 비용이 발생한다.
그렇다면 점원 여러밍이 모두 논블로킹 방식으로 주문을 받으면 어떨까? 실제로 그렇다.
노드도 싱글 스레드 여러 개를 이용해 멀티 스레딩과 비슷한 기능을 하게 할 수 있다. 엄밀히 말하면, 멀티 스레딩보다는 멀티 프로세싱에 가깝다.
- 프로세스는 운영체제에서 할당하는 작업의 단위이다. 노드나 인터넷 브라우저 같은 프로그램은 개별적인 프로세스이다. 프로세스 간에는 메모리 등의 자원을 공유하지 않는다.
- 스레드는 프로세스 내에서 실행되는 흐름의 단위이다. 하나의 프로세스는 스레드를 여러 개 가질 수 있다. 스레드들은 부모 프로세스의 자원을 공유한다. 즉, 같은 메모리에 접근할 수 있다.
스레드를 작업을 처리하는 일손으로 표현하기도 하는데, 노드 프로세스는 일손이 하나인 셈이다. 요청이 많이 들어오면 한 번에 하나의 요청을 처리한다. 블로킹이 심하게 일어나지만 않는다면 하나로도 충분하다.
노드 프로세스도 내부적으로는 스레드를 여러 개 가지고 있다. 하지만 직접 제어할 수 있는 스레드는 하나뿐이므로 흔히 싱글 스레드라고 부르는 것이다.
노드는 스레드를 늘리는 대신, 프로세스 자체를 복사해 여러 작업을 동시에 처리하는 멀티 프로세싱 방식을 택했다. 자바스크립트 언어 자체가 싱글 스레드 특성을 띄고 있기 때문이다.
'👻 Review > 도서 후기' 카테고리의 다른 글
처음 배우는 ReactNative (0) | 2021.08.07 |
---|---|
[Node.js 교과서 정리] 2. 서버로서의 노드 (0) | 2021.05.21 |