Event-driven의 이해

Socket.IO 뿐만 아니라 여러 Node.js 패키지의 근간은 이벤트로 구성되어 있습니다.
이러한 개발 패러다임은 기존의 PHP, ASP, JSP에서 Server-side 개발을 진행하던 것과는  근본적으로 차이가 있어서 새로운 개념에 대한 이해가 필요합니다.

기존의 패러다임

기존의 개발 패러다임은 사용자의 요청이 들어오면 동일한 코드를 처음부터 성실하게 실행하는 것에 초점을 둔 것입니다. 때문에 여러 사용자가 동시간에 접속을 하게 되면 각각 독립적인 작동을 가능케 하기 위하여, Process를 Fork하거나 Thread를 Run하는 방법을 사용한 것 (OS의 구현에 의지)입니다.

문제는 공유할 수 있는 자원을 독립적으로 가지게 됨으로써 낭비가 발생한다는 것과, (동접자 상승에 비례하여 메모리 점유율 상승) 여러 Process간에 문맥전환 (Context Switching)이 발생하여 CPU 사용률이 증가하게 되는 점이 있습니다. 이런 문제로 인해 동접자가 많은 사이트에서는 사용자의 요청들을 처리하는데, 서버의 높은 가용성을 필요로 했기 때문에 비용으로 직결되게 되었습니다.

Node.js가 1개의 Thread로 빠른 서비스 할 수 있게 된 배경에는 이벤트 개념이 있습니다. 이는 Pub/Sub 패턴으로 알려져 있으며, 사실 누구나 한번쯤 구현해봤을 패턴입니다.

MFC나 Android 처럼 GUI 환경의 Client를 구현해보았다면, 언제 발생할지 모르는 마우스 클릭 등의 Event를 처리하기 위해서 EventListener를 추가하는 것을 해보셨을 것입니다. 이 방식은 언제 일어날지 모르는 사건을 컴퓨터가 하염없이 기다리는 것이 아니라. 발생시 미리 등록한 함수를 실행시키라는 것으로 대신하는 것입니다.

Node.js는 Client단의 Event에서 주로 활용하던 이런 패턴을, 웹서비스를 구현하는데 기반으로 사용하였다는 점만 다른 것입니다.
웹 서버는 구동시 사용자의 요청을 대기하는 구조로 구성되어 있습니다. 바로 “요청 대기”에서 차이가 있습니다. Apache 같은 웹 서버는 클라이언트를 대기하다가 새로운 요청이 들어오면 새 Thread를 생성하여 분기하는데 비해, Node는 이후에 CPU와 관계없이 시간이 걸리는 처리 (I/O, Network bound)들을 전부 EventListener로 미루기 때문에 흐름이 끊기지 않고 응답이 빠르게 됩니다. 그래서 1개의 프로세스로 동일한 (더 빠른) 작업이 가능하게 되는 것입니다.

비록 순서대로 실행되는 방식에 비해 코드를 구성하는 것이 어렵지만, 프로그램의 성능을 더 이상 하드웨어에만 의존할 수는 없게 되었기 때문에 효율적인 프로그래밍 방식을 적극적으로 학습하여야 합니다.