Node.js | Node.js 스크립트 기본 | 기본 스크립트와 http 객체


그럼 앞전에 작성한 스크립트를 보면서 Node.js 스크립트에 대한 기본에 대해서 설명하겠다. (아래의 코드 참조)

var http = require('http');
 
var server = http.createServer();
server.on('request', doRequest);
server.listen(process.env.PORT, process.env.IP);
console.log('Server running!');
 
// 요청 처리
function doRequest(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write('Hello World\n');
    res.end();
}

기본 스크립트와 http 객체

1. http 개체 로드

var http = require('http');

먼저 최초에 해야 하는 것은 필요한 라이브러리들의 로드이다. 이것은 “require"함수를 사용한다. 인수에 가져올 개체 이름을 지정하여 해당 개체가 로드되어 반환된다. 이것을 변수에 대입하여 이용한다.

여기에서는 “http"라는 개체를 로드 이고, 이것은 말 그대로 HTTP의 각종 기능을 요약한 것이다. 여기에서 서버 개체를 만든다.

2. Server 개체 생성

var server = http.createServer();

http 오브젝트의 “createServer"메서드를 호출하여 http.Server 개체를 만든다. 이것이 Node.js의 “서버"가 되는 부분이다. 이 개체를 준비하고 필요한 설정을 하여 서버로 실행한다. 여기에서는 인수없이 호출하고 있지만, 다음과 같이 작성 할수 있다

http.createServer(function(XX){
    ……필요한 처리……
}).listen(XX);

아마도 Node.js 사이트 및 기타 해설 사이트를 보면 대부분이 이 작성법에 대해 있는 것이다. createServer 인수에 서버에서 요청을 받았을 때의 처리하는 함수를 작성한다. 그리고, 이 후에 listen이라는 대기하기 위한 메소드도 계속 작성되고 있다.

이 작성에는 전혀 문제가 없지만, 모두 한 덩어리로 작성되어 있기 때문에, 익숙해지기 전에는 조금 이해하기 어려울 것이기에, 여기에서는 쉽게 “createServer에 때로는 인수없이, 나중에 필요한 처리를 작성한다"라고만 기억하도록 하자.

3. 요청 처리 설정

server.on('request', doRequest);

http.Server 개체에는 다양한 이벤트가 준비되어 있으며, 그 처리를 통합하는 방법도 준비되어 있다. “on"이라는 메소드는 지정된 이벤트 처리를 통합하는 것으로, 첫번째 인수에 이벤트 이름을, 두번째 인수에 통합 처리(함수)를 각각 지정한다.

여기에서는 “request"라는 이벤트에 “doRequest"라는 함수를 할당한다. request라는 것은 http.Server 객체가 클라이언트의 요청을 받았을 때 발생하는 이벤트로, 이를테면 여기에 “브라우저에서 서버에 액세스할 때 서버 응답 처리"를 포함한다.

4. 대기 시작

server.listen(1234);

http.Server 개체의 준비가 되면, “listen” 메소드를 실행한다. 그러면 서버는 대기 상태가 되고, 클라이언트에서 요청이 있으면 그것을 받아 처리할 수 있다. 인수는 포트 번호를 지정하고 있다. 두번째 인수로서 호스트 이름을 지정하거나, 세번째 인수에 백 로그를 지정하거나, 네번째 인수에 콜백 함수를 제공할 수도 있지만, 우선 “첫번째 인수에 포트 번호"인 것만 기억해두면 충분하다.

5. 콘솔에 출력

console.log( 'Server running!');

listen에서 대기 시작했던 곳으로 메시지를 콘솔에 출력한다. console은 콘솔 작업을 하기 위한 개체로 “log"로 로그 출력을 할 수 있다. 약간의 디버깅 용으로 로그 출력을 사용하면 편리하다.

요청 처리를 위한 함수

이것으로 http.Server 객체의 작성, 준비, 대기 시작까지의 흐름은 대체로 알 수 있었다. 남은 것은 “요청을 받았을 때의 처리"의 내용이다.

앞의 예제에서는 “doRequest"라는 함수를 정의해 두고, 이를 on 메소드에서 “request"이벤트에 조합했다. 이 request 이벤트에서 수행하는 작업이야말로 클라이언트의 요청을 처리하기 위한 것이다.

이 함수는 아래 같은 형태로 정의되어 있습니다.

function 함수명 (req, res) {
    ...... 필요한 처리 ......
}

인수는 두 개체가 전달된다. 각각 다음과 같다.

  • request

    • 첫번째 인수는 ‘request’ 객체가 전달된다. 이는 http.IncomingMessage라는 객체에서 클라이언트의 요청에 대한 기능을 정리하고 있다.
  • response

    • 두번째 인수는 “response"개체가 전단된다. 이는 http.serverResponse라는 개체에 서버에서 클라이언트로 리턴되는 응답에 대한 기능을 정리하고 있다.

이 request와 response를 사용하여, 요청을 받았을 때의 처리를 만든다. 여기에서는 다음과 같은 처리를 한다.

헤더 정보 내보내기

res.writeHead(200, {'Content-Type': 'text/plain'});

“writeHead"는 response 객체의 메소드에서 헤더 정보를 응답에 작성해서 내보내는 것이다. 첫번째 인자는 상태 코드를 지정하고 두번째인수에 헤더 정보를 연관 배열로 정리한 것이다.

여기에서는 {'Content-Type': 'text/plain'}값이 포함되어 있다. 이로 인해 Content-type이라는 헤더 정보에 'text/plain'의 값을 설정하고 있는 것을 알 수 있다. 이것은 응답으로 반송하는 콘텐츠의 종류를 나타내는 헤더 정보로, 이것으로 “이 콘텐츠는 표준 텍스트이다"라는 것이 클라이언트에 전달된다.

컨텐츠 내보내기

res.write('Hello World\n');

HTTP에는 헤더 정보의 다음에 바디 부분이 되는 콘텐츠를 작성하고 있는데, 이 내용 내보내기를 하고 있는 것이 response 객체의 “write"이다. 인수에 지정한 값이 바디 부분의 컨텐츠로 작성된다.

이 write는 여러번 호출 할 수 있다. 이것을 호출하여 작성을 하더라도, 아직 콘텐츠는 종료하지 않으므로, 계속해서 write으로 추가 작성할 수 있다.

컨텐츠 출력 완료(응답 종료)

res.end();

내용 내보내기가 완료되면 마지막으로 response의 “end"를 호출하여 콘텐츠 출력을 완료한다. 여기에서는 단지 end를 호출하고 있을 뿐이지만, 인수로 내보낼 내용의 값을 지정할 수 있다. 그러면 인수의 값을 쓴 후에 내용을 완료한다.

이 end로 인해 응답 처리는 종료되고, 그 요청의 처리가 완료된다. “writeHead”, “write”, “end"의 3개가 있으면, 클라이언트에 반환 내용은 모두 쓸 수 있다.