[Nodejs]O’REILLY 정리 - 2
비동기 함수와 Node 이벤트 루프
기본적으로 Node에서는 애플리케이션은 단일 쓰레드(또는 프로세스)에서 실행되며 모든 이벤트들이 비동기로 처리 된다.
Apache와 같은 통상적인 웹 서버는 들어오는 요청을 처리하는 방법에 두 가지가 존재한다.
첫 번째는 각 요청을 요청이 만족될 때까지 별도의 프로세스에 할당하는 것이며, 두 번째는 각 요청마다 별도의 쓰레드를 만드는 것이다.
첫 번째 접근방법(prefork 멀티 쓰레딩 모델 혹은 prefork MPM 이라고 함)은 Apache 설정 파일에 지정된 수만큼의 자식 프로세스를 생성할 수 있다.
별도 프로세스를 생성할 때의 장점은 요청을 통해 접근하는 애플리케이션(예: PHP 애플리케이션)이 쓰레드 세이프(thread-safe) 할 필요가 없다는 것이고,
단점은 각 프로세스가 메모리를 많이 사용하게 되고 확장성이 떨어진다는 것이다.
두번째 접근방법(worker MPM이라고 함)은 하이브리드 프로세스-쓰레드 접근방법을 구현한 것이다.
들어오는 각 요청들은 새로운 쓰레드를 통해 처리된다. 메모리 관점에서는 보다 효율적이지만,
모든 애플리케이션이 쓰레드 세이프하도록 요구한다.
PHP 언어 자체는 이제 쓰레드 세이프하지만, 함께 사용되는 수많은 다른 라이브러리들 역시 그렇다는 보장은 없다.
어느 접근방법을 사용하든 둘 다 요청에 대해 병렬적으로 응답한다.
다섯명이 동시에 웹 애플리케이션에 접근하고 서버가 적절하게 구성된경우, 웹 서버는 다섯 개의 요청을 모두 동시에 처리한다.
Node는 이와 달리, Node 애플리케이션을 시작하면 실행을 위해 단일 쓰레드를 생성하고 애플리케이션이 요청을 처리할 준비가 될 때까지 기다린다.
Node가 요청을 받으면, 현재 요청에 대한 코드 처리가 완료될 때까지는 다른 요청이 처리될 수 없다. 이러한 방식이 비효율적인 것 같지만, Node는 이벤트 루프와 콜백 함수를 통해 비동기로 동작한다. 이벤트 루프는 특정 이벤트를 기본적으로 폴링하면서 적절하게 이벤트 핸들러를 호출하는 기능이며, node에서는 콜백 함수가 이 이벤트 핸들러다.
다른 단일 쓰레드 애플리케이션과는 달리, Node 애플리케이션이 요청을 받은 후 리소스들에 요청(데이터베이스 요청 또는 파일 접근)을 보내야 하는 경우 Node는 요청을 하더라도 응답을 받을 때까지 기다리지 않고 요청에 콜백 함수를 연결한다. 요청된 항목에 대해 준비(또는 완료)되면 이벤트가 발생하여 요청된 동작의 결과나 요청된 리소스를 처리하기 위한 관련 콜백 함수가 호출 된다.
다섯 명이 동시에 Node 애플리케이션에 접근하고 애플리케이션이 파일 리소스에 접근해야 할 경우 Node는 각 요청에 대한 응답 이벤트에 콜백 함수를 연결시킨다. 각 요청에 대한 리소스가 사용 가능해지면 콜백 함수가 호출되어 각 사용자들의 요청이 순서대로 처리된다. 그 동안에 Node 애플리케이션은 동일 애플리케이션 혹은 다른 애플리케이션에 대한 다른 요청들도 처리할 수 있다.
애플리케이션이 요청을 병렬적으로 처리하지는 않지만, 얼마나 바쁜 상태인지와 어떻게 디자인 되었는지에 따라 일반적으로 대부분의 사람들은 응답이 지연된다는 것을 전혀 느끼지 못할 것이다. 무엇보다도 Node 애플리케이션은 메모리 및 다른 한정된 리소스들을 매우 적게 사용한다.
비동기로 파일 읽기
Node의 비동기 특성에 대한 예제 1-2) 이전에 만든 helloworld.js를 실제로 열어 그 내용을 클아이언트에게로 출력한다.
// load http module
var http = require('http');
var fs = require('fs');
// create http server
http.createServer(function (req, res) {
// open and read in helloworld.js
fs.readFile('helloworld.js', 'utf8', function(err, data) {
res.writeHead(200, {'Content-Type': 'text/plain'});
if (err)
res.write('Could not find or open file for reading\n');
else
// if no error, write JS file to client
res.write(data);
res.end();
});
}).listen(8124, function() { console.log('bound to port 8124');});
console.log('Server running on 8124/');
- File System 모듈 은 파일 내용을 열고 접근하는 것을 비롯한 POSIX 파일 기능을 래핑한 것이다.
- 비동기 동작 두 가지 : readFile 메서드에 연결된 콜백함수 와 listen 메서드에 연결된 콜백 함수
- listen 메서드는HTTP 서버 개체에게 지정된 포트에 대해 연결을 대기하기 시작하라고 알려준다. Node는 연결이 맺어지는 것을 대기하는 동안 차단되지 않으므로, 연결이 맺어지고 나면 콜백 함수를 제공하기만하면 된다. 연결이 맺어지면 listening 이벤트가 발생해서 콜백 함수가 호출되고 콘솔에 메시지가 출력된다.
- 파일에 접근하는 것은 상대적으로 시간이 걸리는 동작이므로, 다중의 클라이언트가 단일 쓰레드 애플리케이션에 접근하면 파일 접근이 차단되어 문제에 빠져 사용이 불가능하게 된다. 이렇게 되지 않으려면 파일을 열고 내용을 읽는 것이 비동기로 수행되어야 한다. 파일 내용을 버퍼로 읽고 나면( 또는 도중 오류가 발생하면) readFile 메서드에 전달된 콜백 함수가 호출된다. 오류가 있을 경우에는 오류가, 그렇지 않을 경우에는 데이터가 전달된다.
- 콜백 함수 내에서는 오류를 확인하고, 오류가 없을 경우에는 클라이언트에 대한 응답으로 데이터를 쓰게 된다.
Leave a comment