Node.js란?


크롬 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임입니다. 이벤트기반, 논블로킹 I/O모델을 사용해 가볍고 효율적입니다.

Node.js 공식 사이트에서 위와같이 설명하고 있습니다.

입문자들은 Node.js가 서버프레임워크 혹은 자바스크립트로 서버를 짜기위해 공부해야하는 무언가로 생각하실 수 있습니다.

저또한 마찬가지였습니다.

소개글에도 알 수 있듯이 서버로만 사용되는것이 아니므로 서버라는 단어가 없습니다.

단지 자바스크립트라는 컴퓨터 언어로 만든 프로그램을 실행할 수 있게 만들어주는 환경일뿐입니다. (= 자바스크립트 런타임)




그럼 왜? Node.js을 사람들이 주로 서버로 활용하는지 Node.js의 특징을 정리하며 알아보겠습니다.




첫번째로, 이벤트루프를 활용한 논블로킹 I/O 입니다.


이벤트 루프를 알기전에 위에서 언급한 이벤트 기반에대해 알고 넘어가겠습니다.

이벤트 기반이란 이벤트가 발생할때 미리 지정해둔 작업을 수행하는 방식을 말하는것입니다.

여기서 여러 이벤트가 발생할때 어떤 순서로 작업을 수행할지 이벤트 루프가 판단을 하게 됩니다.


http://latentflip.com/loupe에서 발췌한 예제를 통해 설명을 하겠습니다.

아래와 같은 버튼 클릭 이벤트와 이벤트에대한 콜백 함수와 로그 및 콜백함수가 코드로 이루어져있습니다.


● Call Stack 영역은 코드가 순차적으로 읽히면서 쌓이게되는 영역이며

Web Apis(Background) 콜백 또는 이벤트 리스너들이 Call Stack에서 읽힌 후 대기하는 영역이며

Callback Queue (Task Queue) Web Apis(Background)에서 작업이 완료되면 호출되어야할 함수들이 대기하는 영역입니다.



처음 코드를 실행시키면 이벤트 리스너 Call Stack에 등록 -> Web Apis(Background) 영역에서 대기 -> 'Hi' 로그 함수 Call Stack 에서 즉시 실행 -> 'Click the button' 로그 함수 Call Stck 등록 및 Web Apis(Background) 영역에서 5초동안 작업 시작 -> 'Welcome to loupe' 로그함수 Call Stck 에서 즉시실행 -> 'Click the button' 로그함수 5초 대기 작업 후 Callback Queue에 등록 -> Call Stack 으로 넘어와서 실행



위와같은 순으로 코드가 실행되는것을 확인하실 수 있습니다.


여기서 이벤트 루프란? Call Stack이 비어있으면 Callback Queue (Task Queue)에서 함수를 하나씩 가져와 Call Stack에 넣고 실행하는 것을 말합니다. 루프이기때문에 Task Queue에 함수가 대기를 하던 안하던 확인 후 있다면 Call Stack에 넣고 실행을 반복합니다.


이제 이벤트 루프를 활용하여 어떻게 논블락킹 I/O 가 이루어지는지 살펴보겠습니다.


우선 논블로킹란 이전 작업이 완료될때까지 멈춰져있지 않고 다음작업을 실행하는것을 말합니다.



위와 같이 클릭 리스너가 등록되어있다고 가정할때 클릭 이벤트 발생시 콜백 함수가 작업이 완료되면 Callback Queue로 전송 및 이벤트 루프에의해 호출이되기 때문에 한 작업이 완료될때까지 기다리는것이 아닌 다음작업을 수행할수 있습니다.


실생활에서 간단하게 예를 들어본다면 논블로킹은 카페 시스템이며 블로킹은 푸드트럭 시스템으로 볼 수 있다고 생각됩니다.


두 시스템 모두 점원이 한명이라고 가정했을때 카페는 점원이 주문을 받고 진동벨로 이벤트가 끝나는 시점을 알려줌으로서 고객은 자리에 앉아 자신의 일을 할수 있고 점원은 주문에 대한 음료가 나오기전에 다른 주문을 받아 같은 방식으로 처리할수 있습니다.
하지만 푸드트럭의 경우 주문이 들어오면 음식이 나올때까지 고객은 줄에 서있는채로 음식을 기다리며 점원은 음식이 나올때까지 다른 손님의 주문을 원활히 받을 수가 없습니다. (때문에 점점 길어지는 줄때문에 새로운 고객은 겁을 먹고 다른데로 가게 되는것 같습니다 ...)


위의 예를 보고 점원을 늘리면 다 해결되는거잖아? 라고 생각하실수 있습니다.


그렇다면 다음 다음 단락까지 이 글을 읽어보셔야하며 왜 논블로킹 I/O가 중요한지 더욱 느끼실 수 있습니다.




둘째, 싱글스레드


스레드란? 프로세스 내에서 실행되는 흐름의 단위이며 부모프로세스의 자원을 공유합니다. 다시말하면 같은 메모리에 접근할 수 있습니다.

프로세스란? 운영체제에서 할당하는 작업의 단위이며 쉽게말해 실행중인 프로그램이라고 할수 있습니다. 인터넷브라우저 같은 프로그램은 개별적인 프로세스이기 때문에 자원을 공유하지 않습니다.


이제 스레드가 무엇인지 정의는 알았으니 쉽고 친숙하게 요약하자면, 프로그램내에서 작업을 처리해주는 일손입니다.


점원을 늘리면 다 해결되는거잖아? -> 멀티 스레드 의 한계점을 설명하겠습니다.


손님(동시 접속자)에 따라 점원(스레드)을 증가/감소시킨다면?

  1. 점원을 고용하고 해고하는데도 비용이 발생.
  2. 서버자원은 한정적이기 때문에 동시접속자만큼 스레드를 증가시킬 수 없음. (서버를 업그레이드하거나 Load-Balancing으로 해소 가능)
  3. 자원을 공유하기때문에 공유자원 접근 문제가 발생. thread-unsafe라고 표현하기도 함.


하지만 멀티스레드에서 오는 장점도 분명히 존재합니다. 이제 싱글스레드의 장단점을 설명하면서 멀티스레드의 장점도 자연스럽게 공부해보도록하겠습니다.


자바스크립트와 Node.js는 싱글스레드인것을 한번쯤은 들어보셨을 것입니다. 때문에 한번에 하나의 작업밖에 처리하지 못하지만 위에서 설명한 이벤트루프를 활용한 논블로킹I/O를 통해 고성능 병렬처리가 가능합니다.

또한 멀티스레드에 비해 자원을 적게 사용하는 장점이 있으며 공유자원 접근문제에도 자유롭습니다.


하지만 싱글스레드이므로 시간(연산)이 오래걸리는 작업을 한다면 서버전체의 성능이 저하됩니다. (cluster, pm2를 사용하여 멀티프로세싱 혹은 AWS Lambda, Google Cloud Function으로 해소 가능)

또한 에러를 제대로 처리하지 못하면 서버전체가 멈추어버립니다.


각각의 장단점속에서 왜 Node.js가 폭발적으로 성장하고 있는지 아직 이해가 안되시는 분들도 있을것입니다.


제가 생각하는 가장큰 이유는 자바스크립트이기때문에 웹사이트와 서버를 하나의 언어로 개발할수 있기때문에 생산성이 중요한 기업들에게 사랑받고 있습니다.

또한, 웹서버가 내장되어있어 입문자들이 쉽게 입문할수 있기 때문이라고 생각합니다.


끝으로 어떤것이 최고다. 라는 정답은 없습니다. 서비스의 특징에따라 가장 적합한 아키텍쳐를 설계할수 있는 인사이트를 가지는것이 중요하다고 생각되며 오늘의 글의 도움이 되었으면 좋겠습니다.