Node.js 와 개발 프레임워크(1) – Node.js

By | Y2017Y2017-5M-D

어느날, 모 처로 부터 Full Stack 개발이 편한 프레임워크가 있다는 소개를 받는다.

솔깃하지 않은가? OS / WAS 까지의 셋업 및 커스터마이즈, 튠업이 얼마나 험난한 길인지 안다면 말이다.

이름 하여 Node.js 와 관련 프레임워크.

우선 Node.js 로 부터 시작해보자

  • 한글위키: https://ko.wikipedia.org/wiki/Node.js
  • 영문위키: https://en.wikipedia.org/wiki/Node.js

영문 위키를 확인해보면,  Node.js 의 몇 가지 중요한 특성을 알 수 있는데

  • Threading –  기존의 WAS 와는 다르게 non-blocking I/O 호출에 기반한 Single Threading 을 사용한다.  기본적으로 Node.js 는 Event Driven 방식의 구조로 되어 있으며, Subject(주 개체)-Observer(의존개체) 간에 자동으로 Notify() 와 같은 method 호출을 하여 상태변화를 공유한다(Observer Pattern).  Tomcat 과 같은 기존 WAS 의 경우CPU 시간을 나눠 쓰기 위한 시분할 멀티스레딩(Time division Multithreading) 을 통해 thread pool 을 이용한다. 따라서 각 스레드를 번갈아 가며 실행시키기 위한 컨텍스트 스위칭(Context Switching)에 대한 비용을 발생시키는데 비해, Single Threading 방식은 이에 대한 비용이 발생하지 않게 된다. 대신 단일 스레드 환경에서 다중 요청에 대한 높은 동시성을 유지하기 위해 I/O 호출은 반드시 Callback 을 호출하여야 한다(Context Switching 대신 단일 event loop 에서 callback 을 사용하여 스레드를 반환하는 것). 이 부분은 libuv 가 고정 크기의 thread pool 을 가지고 non-blocking 비동기 I/O 에 대한 책임을 지게 된다.
     한편으로 단일 스레드 기반의 구조로 인해 Node.js 기반으로 시스템 자원의 수직 확장(CPU 코어 수 증가와 같은) 에 대해 대응하기 위해서는 추가적인 모듈에 의지하여야 한다 (cluster, StrongLoop Process Manager or pm2).
    다만, libuv 스레드 풀의 기본 숫자를 늘려서 운영체제에서 다중 코어를 이용하여 분산처리 하는 것처럼 쓸 수 있다고 한다 (즉, 직접적인 스레드-물리적 CPU 관리가 아닌 운영체제에서 간접적으로 관리하게 되는 것으로 이해된다).
    Node.js 의 병렬 작업은 thread pool 에 의해서 관리되는데 작업 실행을 위한 스레드는 스레드 큐에 넣어져 대기하게 된다. 네트워킹과 같은 non-blocking 작업은 OS 의 커널 레벨의 non-blocking I/O 로 변환되어 실행되지만 파일 I/O 와 같이 blocking 이 필요한 작업은 해당 스레드 내에서 blocking mode 로 처리되게 된다. 각 스레드는 작업이 완료되면 callback 호출로 주 스레드에게 작업이 다 되었음을 통지하게 되는데, 이 callback 은 일렬로(serial) 발생하므로, 긴 작업에 대해서는 Event loop 가 고정되어 버리게 된다.
    (이러면 Event Lock 이 발생하는게 아닌가??)
  • V8 – JS(ECMA Script) 를 실시간 번역(Interpret) 하면 역시 시간 및 비용이 발생하므로 C++ 로 개발된 V8 엔진이 Native Code 로 변환시켜 성능을 향상시켰다. Google 이 만들었다고 한다. Chrome 용으로.
    (JVM 내의 Jit compiler 와 같은 구조이다 – 그러고 보니 Java 가 interpret 언어였음을 잊어버린지 꽤 오래 된 것 같다. 자바는 인터프리터? 컴파일?)
  • Unified API – 브라우저와 결합하여 json 기반의 DB – Mongo, CouchDB, Postgres 등을 지원하며, json 과 함께 통합된 자바스크립트 개발 스택과 함께 사용될 수 있다고 한다. 그리고, MVC, MVP, MVVM 과 같은 서버 측 개발 패턴에 대응하여 서버 측과 클라이언트 측에서 같은 모델과 인터페이스를 재활용 할 수 있다.
    (실제 구현 환경을 보면, server-side biz logic 와 typescript 를 이용한  client-side 가 유기적으로 결합되어 있음을 알 수 있으며, 재활용이 용이하다)
  • Event loop – 이건 아까 thread 에서 이미 이야기 되었던 것으로,  각 커넥션은 상대적으로 무거운 OS 나 스레드가 커넥션을 다루는 것이 아니라 OS 에서 커넥션에 발급된 callback 을 이용하여 (Node.js 가 OS 에 등록되는 이유이다) event loop 방식으로 동작하므로, heap allocation 크기가 작으며 callback 을 별도로 정의하는 대신, 서버가 callback 정의 끝에 event loop을 넣으므로서 event loop 가 종료되게 된다. 따라서 별도의 추가적인 callback 이 필요하지 않게 된다.

488 total views, 1 views today

댓글 남기기