일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 알고리즘
- Bookmark
- 독립영화플랫폼
- til
- Django Blog
- passport.js
- Exercism
- 북마크앱
- 장고
- Node.js
- ART_Cinema
- python
- join()
- Algorithm
- 장고 프로젝트 순서
- 자바스크립트
- 장고 개발 순서
- mongodb
- 프로젝트
- 개발
- 북마크만들기
- Blog
- 예술영화추천
- Django
- MYSQL
- 타사인증
- 파이썬 웹프로그래밍 장고
- 장고 프로젝트
- MyPick31
- JavaScript
- Today
- Total
Juni_Dev_log
(node.js) [Part.5] 웹 서버 만들기 - 간단한 웹 서버 만들기 본문
노드에 기본적으로 들어 있는 http 모듈을 사용하면 웹 서버 기능을 담당하는 서버 객체를 만들 수 있다.
http 모듈을 로딩했을 떄 반환되는 객체에는 createServer() 메소드가 정의되어 있다.
따라서, 이 메소드를 호출하면 서버객체를 만들 수 있다. ch05_test1.js 를 만들고 코드를 입력한다.
1
2
3
4
5
6
7
8
9
10
|
var http = require('http');
// 웹 서버 객체를 만든다.
var server = http.createServer();
// 웹 서버를 시작하여 3000번 포트에서 대기한다.
var port = 3000;
server.listen(port, function(){
console.log('웹 서버가 시작되었습니다. : %d', port);
})
|
cs |
http 모듈에 들어 있는 서버 기능을 사용하려면 먼저 require() 메소드로 http 모듈을 불러온다.
그런 다음 모뮬 이름과 똑같은 http 변수를 만든 후 이 변수에 할당한다.
이 http 객체의 createServer() 메소드를 호출하면 서버 객체가 반환된다. 이 서버 객체의 listen() 메소드를 호출하면 웹 서버가 시작된다.
서버를 시작할 때는 포트를 3000번으로 지정하여 해당 포트에서 클라이언트의 요청을 대기한다. listen() 메소드를 호출할 때 전달하는 두 번째 파라미터는 콜백 함수로, 웹 서버가 시작되면 호출된다.
ch05_test1.js 파일을 실행해면 콘솔 창에 로그가 출력되면서 웹 서버가 시작된다.
만약 서버를 중지하고 싶다면 콘솔 창 위쪽 탭에 있는 흰색 사각형을 누르면 된다.
웹 서버를 만들었다. 하지만, 웹 브라우저에서 이 웹 서버로 무언가를 요청했을 때 아직까지는 웹 서버가 해줄 수 있는 것이 아무것도 없다.
그래도 지금 실행한 것이 웹 서버이니 이 웹 서비스가 어떤 과정으로 만들어졌는지 다시 한 번 자세히 살펴보자.
웹 서버는 일반적으로 웹 브라우저라고 하는 클라이언트에서 HTTP 프로토콜로 요청한 정보를 처리한 후 응답을 보내주는 역할을 한다. 이때 PC나 서버 기계에 있는 6만개가 넘는 포트들 중에서 하나를 사용하는데, 여기에서는 3000번 포트를 사용했다.
웹 서버를 만들어 실행하는 과정을 보면,
① createServer() 메소드를 호출하여 웹 서버 객체를 만든다.
② listen() 메소드를 호출하여 지정 포트에서 대기하도록 설정한다.
createServer() 메소드로 만든 서버 객체에서 사용할 수 있는 대표적인 메소드는 다음과 같다.
메소드 이름 | 설명 |
listen(port, [hostname], [backlog], [callback]) | 서버를 실행하여 대기시킨다. |
close([callback]) | 서버를 종료시킨다. |
그런데 PC나 서버기계에 이더넷 카드가 여러 개 있는 경우에는 서버에서 사용할 수 있는 인터넷 주소, 즉 IP 주소가 여러 개 존재한다. 이렇게 IP 주소가 여러 개 있는 경우에는 특정 IP 를 지정하여 서버를 실행해야 할 때도 있다.
이런 경우에는 listen() 메소드를 호출하면서 IP를 직접 지정한다.
다음 코드를 사용하면 IP와 함께 백로그(실질적으로 동시 접속 연결 수를 결정하는 정보)를 지정할 수 있다.
앞에서 입력한 listen() 메소드 부분의 코드 앞에 // 기호를 추가하여 주석처리 후, 다음과 같이 입력한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var http = require('http');
// 웹 서버 객체를 만든다.
var server = http.createServer();
// 웹 서버를 시작하여 3000번 포트에서 대기한다.
var port = 3000;
// 웹 서버를 시작하여 192.168.0.5 IP에 대기한다.
var host = '192.168.0.5';
server.listen(port, host, '50000', function(){
console.log('웹 서버가 시작되었습니다. : %s, %d',host,port);
})
|
cs |
IP 정보는 임시로 192.168.0.5 로 넣었지만 사용자가 사용하는 PC가 인터넷에 연결되었을 때의 IP 주소로 바꾸어 지정해야한다.
내 PC 의 IP를 알고 싶은가?
명령 프롬프트를 열고 ipconfig/all 을 입력하면 확인할 수 있다.
클라이언트가 웹 서버에 요청할 때 발생하는 이벤트 처리하기
만약 웹 브라우저가 이 웹 서버에 접속한 후 데이터를 요청하면 그때마다 적절한 이벤트가 발생하므로 다양한 상황에 맞추어 콜백함수를 각각 등록하면 된다.
다음은 서버 객체에서 사용할 수 있는 주요 이벤트들이다.
이벤트 이름 | 설명 |
connection | 클라이언트가 접속하여 연결이 만들어질 때 발생하는 이벤트들이다. |
request | 클라이언트가 요청할 때 발생하는 이벤트입니다. |
close | 서버를 종료할 때 발생하는 이벤트이다. |
이 외에도 여러가지 이벤트가 있지만 클라이언트가 접속할 때 발생하는 connection 이벤트와 클라이언트가 특정 패스로 요청할때 발생하는 request 이벤트가 가장 자주 사용된다.
웹 브라우저에서 요청할 때 어떤 이벤트가 발생하는 지 보기 위해서 ch05_test2.js 를 만들어본다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
var http = require('http');
// 웹 서버 객체를 만든다.
var server = http.createServer();
// 웹 서버를 시작하여 3000번 포트에서 대기하도록 설정한다.
var port = 3000;
server.listen(port, function(){
console.log('웹 서버가 시작되었습니다. : %d',port);
});
// 클라이언트 연결 이벤트 처리
server.on('connection', function(socket){
var addr = socket.address();
console.log('클라이언트가 접속했습니다. : %s, %d',addr.address, addr.port);
});
// 클라이언트 요청 이벤트 처리
server.on('request', function(req,res){
console.log('클라이언트 요청이 들어왔습니다.');
console.dir(req);
});
// 서버 종료 이벤트 처리
server.on('close', function(){
console.log('서버가 종료됩니다.');
});
|
cs |
웹 브라우저와 같은 클라이언트가 웹 서버에 연결되면 connection 이벤트가 발생한다.
그러므로 on() 메소드를 호출할 때 첫 번째 파라미터로 connection 이벤트 이름을 전달하고 두 번째 파라미터로 콜백 함수를 전달한다.
연결이 만들어져 콜백함수를 호출할 때는 socket 객체가 파라미터로 전달된다. 이 객체는 클라이언트 연결 정보를 담고 있으므로 address() 메소드를 호출하여 클라이언트의 IP와 포트 정보를 확인할 수 있다.
클라이언트가 특정 패스로 요청을 하면 request 이벤트가 발생한다.
이때도 앞에서 알아본 on() 메소드를 사용해 이벤트를 처리한다. 콜백 메소드로 전달되는 요청 객체를 console.dir() 메소드로 화면에 출력하면 어떤 정보가 들어있는지 확인할 수 있다.
이 파일을 실행하고 웹 브라우저를 연 다음, 주소 창에 http://localhost:3000/ 를 입력해서 사이틀 열어본다.
웹 브라우저에는 아무런 반응이 없지만 콘솔 창에는 다음과 같은 결과가 출력된다.
클라이언트가 접속한 IP와 포트를 알 수 있고, 클라이언트가 요청을 했을 때, 콜백 함수에 전달되는 req 객체에 들어있는 다양한 정보도 확인할 수 있다.
파일을 실행할 때, EADDRINUSE 라는 오류가 발생하는가?
서버를 실행할 때 다음과 같은 오류가 발생하면서 서버가 시작되지 않는 경우가 있다.
이것은 이미 같은 포트에서 서버가 시작되었기 때문에 발생하는 문제이다.
이 경우 이전에 실행했던 서버를 종료해야한다. 왼쪽 탭을 열어보면 아직도 서버가 작동하고 있다는 것을 볼 수 있다.
태탭의 상단에 있는 중지 아이콘을 누르거나 탭을 없애버리면 서버가 종료된다.
그런데 웹 브라우저에서 페이지를 열어도 서버에서 아무런 응답을 보내주지 않기 때문에 웹 브라우저에서는 결과 페이지를 볼 수 없다. 서버에서 응답을 보내도록 request 이벤트를 처리하는 콜백함수에 다음과 같이 입력한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
var http = require('http');
// 웹 서버 객체를 만든다.
var server = http.createServer();
// 웹 서버를 시작하여 3000번 포트에서 대기하도록 설정한다.
var port = 3000;
server.listen(port, function(){
console.log('웹 서버가 시작되었습니다. : %d',port);
});
// 클라이언트 연결 이벤트 처리
server.on('connection', function(socket){
var addr = socket.address();
console.log('클라이언트가 접속했습니다. : %s, %d',addr.address, addr.port);
});
// 클라이언트 요청 이벤트 처리
server.on('request', function(req,res){
console.log('클라이언트 요청이 들어왔습니다.');
res.writeHead(200, {"Content-Type":"text/html; charset=utf-8"});
res.write("<!DOCTYPE html>");
res.write("<html>");
res.write(" <head>");
res.write(" <title>응답 페이지</title>");
res.write(" </head>");
res.write(" <body>");
res.write(" <h1>노드제이에스로부터의 응답 메세지</h1>");
res.write(" </body>");
res.write("</html>");
res.end();
});
// 서버 종료 이벤트 처리
server.on('close', function(){
console.log('서버가 종료됩니다.');
});
|
cs |
웹 브라우저를 열고 http://localhost:3000/ 또는 IP 주소를 확인하는 경우에는 IP 주소를 지정하여 주소를 입력하고 서버에 접속하면 응답 페이지가 나온다.
res 객체의 writeHead(), write(), end() 메소드를 사용하면 클라이언트로 응답을 보낼 수 있다.
이 중에서 end() 메소드는 응답을 모두 보냈다는 것을 의미하며, 일반적으노느 end()메소드가 호출될 때 클라이언트로 응답을 전송한다.
이렇게 해서 클라이언트가 웹 서버에 요청을 보내고 응답을 받을 수 있는 기능을 만들어보았다.
이를 정리해보자면 다음과 같다.
on() 메소드는 이벤트를 처리할 때 사용하는 가장 기본적인 메소드이다. 이 메소드로 connection, request, close 이벤트를 처리할 수 있는 콜백 함수를 각각 등록해두면 상황에 맞게 자동 호출된다.
클라이언트가 요청을 해 왔을 때 발생하는 request 이벤트를 처리할 수 있게 등록해 둔 콜백함수에서는 res 객체를 사용해서 클라이언트로 응답을 보낸다.
res객체를 사용해서 응답을 보낼 때 사용하는 주요 메소드는 다음과 같다.
메소드 이름 | 설명 |
writeHead(statusCode[, statusMessage][, headers]) | 응답으로 보낼 헤더를 만든다. |
write(chunk[,encoding][,callback]) | 응답 본문(body) 데이터를 만든다. 여러 번 호출할 수 있다. |
end([data][,encoding][,callback]) | 클라이언트로 응답을 전송한다. 파라미터에 데이터가 들어있다면 이 데이터를 포함시켜 응답을 전송한다. 클라이언트의 요청이 있을 때 한 번은 호출되어야 응답을 보내며, 콜백함수가 지정되면 응답이 전송된 후 콜백함수가 호출된다. |
request 이벤트를 처리하는 콜백 함수에서 클라이언트로 응답을 보내는 방법에 대해 알아보았다.
그런데 request 이벤트를 사용해서 클라이언트로 응답을 보내지 않고 서버 객체를 만들 때 사용하는 createServer() 메소드 호출 부분에 응답을 보내는 코드를 바로 입력할 수 있다.
ch05_test3.js 파일을 복사하여 ch05_test4.js 를 만든다. 그리고 다음같이 createServer() 메소드를 호출할 때 전달하는 콜백함수에 request 이벤트를 처리할 때 사용했던 코드를 똑같이 붙여넣어본다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
var http = require('http');
// 웹 서버 객체를 만든다.
var server = http.createServer(function(req,res){
console.log('클라이언트 요청이 들어왔습니다.');
res.writeHead(200, {"Content-Type":"text/html; charset=utf-8"});
res.write("<!DOCTYPE html>");
res.write("<html>");
res.write(" <head>");
res.write(" <title>응답 페이지</title>");
res.write(" </head>");
res.write(" <body>");
res.write(" <h1>노드제이에스로부터의 응답 메세지</h1>");
res.write(" </body>");
res.write("</html>");
res.end();
});
// 웹 서버를 시작하여 3000번 포트에서 대기하도록 설정한다.
var port = 3000;
server.listen(port, function(){
console.log('웹 서버가 시작되었습니다. : %d',port);
});
// 클라이언트 연결 이벤트 처리
server.on('connection', function(socket){
var addr = socket.address();
console.log('클라이언트가 접속했습니다. : %s, %d',addr.address, addr.port);
});
// 서버 종료 이벤트 처리
server.on('close', function(){
console.log('서버가 종료됩니다.');
});
|
cs |
request 이벤트를 처리하는 코드를 삭제하고 해당 부분의 코드를 createServer()를 할 때 코드에 입력하면 똑같은 결과가 나타난다.
이 방법은 request 이벤트를 처리하는 콜백 함수에서 응답을 보내는 것과 다르지 않다. 하지만 때에 따라서 이렇게도 처리할 수 있다는 것을 알아두자.
클라이언트에서 요청이 있을 때 파일 읽어 응답하기
fs 모듈로 파일을 다루는 방법은 이미 첫째 파트에서 알아보았다.
파일을 읽이 위해 readFile() 메소드를 사용하거나 파일을 스트림 객체로 읽을 수 있다.
이제 클라이언트의 요청이 들어왔을 때 파일을 읽고 응답하는 방벙블 알아보자. 먼저 적당한 이미지 파일을 인터넷에서 다운로드하여 이름을 붙인다.
ch05_test3.js 파일을 복사하여 ch05_test5.js 를 만들고 다음과 같이 입력한다.
이 코드는 이미지 파일을 읽어 클라이언트 쪽으로 응답을 보낸다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
var http = require('http');
var fs = require('fs');
// 웹 서버 객체를 만든다.
var server = http.createServer();
// 웹 서버를 시작하여 3000번 포트에서 대기하도록 설정한다.
var port = 3000;
server.listen(port, function(){
console.log('웹 서버가 시작되었습니다. : %d',port);
});
// 클라이언트 연결 이벤트 처리
server.on('connection', function(socket){
var addr = socket.address();
console.log('클라이언트가 접속했습니다. : %s, %d',addr.address, addr.port);
});
// 클라이언트 요청 이벤트 처리
server.on('request', function(req, res){
console.log('클라이언트 요청이 들어왔습니다.');
var filename = "cat.png";
fs.readFile(filename, function(err, data){
if(err) throw err;
res.writeHead(200, {"Content-Type":"image/png"});
res.write(data);
res.end();
});
});
// 서버 종료 이벤트 처리
server.on('close', function(){
console.log('서버가 종료됩니다.');
});
|
cs |
파일을 다루어야 하기 때문에 코드의 가장 위쪽에서 require() 메소드로 fs 모듈을 읽어 들인다.
on() 메소드를 호출하여 request 이벤트를 처리하고 클라이언트의 요청이 들어오면 readFile() 메소드로 cat.png 파일을 읽어들인다.
readFile() 메소드는 비동기 방식으로 처리된다. 따라서 파일을 모두 읽으면 콜백 함수 안의 data 객체로 파일 내용이 전달된다. 콜백 함수 안에서는 응답객체의 write() 메소드를 사용해서 파일 내용을 클라이언트로 전송한다.
그리고 HTTP 헤더 중에서 Content-Type 헤더 값으로 image/png 를 넣어 이미지 데이터임을 표시한다.
파일을 실행한 후 웹 브라우저를 열고 사이트에 접속하면 다음과 같이 사진이 보인다.
코드를 몇 줄 입력하지도 않았는데 웹 브라우저에 고양이 이미지가 보인다.
이것은 웹 서버를 다루는 코드나 파일을 다루는 코드가 많은 기능을 포함하고 있으면서도 쉽게 사용할 수 있도록 만들어졌기 때문이다.
이미지 파일을 읽어 응답을 보내는 과정을 다시 정리하면 다음과같다.
이런 이미지 파일 이외에도 일반 텍스트 파일이나 음악 파일 등을 같은 방식으로 클라이언트에 전송할 수 있다.
만약, 음악 파일을 읽어 응답으로 보내고 싶다면 각각의 Content-Type 헤더 값만 적절한 MIME Type 으로 설정하면 된다. Content-Type 에 설정할 수 있는 대표적인 MIME Type은 다음과 같다.
Contetn Type의 값 | 설명 |
text/plain | 일반 텍스트 문서 |
text/html | HTML 문서 |
text/css | CSS 문서 |
text/xml | XML 문서 |
image/jpeg, image/png | JPEG 파일, PNG 파일 |
video/mpeg, audio/mp3 | MPEG 비디오 파일, MP3 음악 파일 |
application/zip | ZIP 압축 파일 |
파일을 스트림으로 읽어 응답 보내기
지금까지 파일을 읽어 응답 보내는 과정을 코드로 만들어보았는데, 이 과정을 더 간단하게 만드는 방법이 파이프이다.
파일은 스트림 객체로 읽어 들일 수 있고 웹 서버의 응답 객체도 스트림으로 데이터를 전송할 수 있기 때문에 두 개의 스트림은 파이프로 서로 연결할 수 있다.
다시 말해, 파일을 스트림 객체로 읽어 들인 후, pipe() 메소드로 응답 객체와 연결하면 별다른 코드 없이도 파일에 응답을 보낼 수 있다.
ch05_test5.js 파일을 복사하여 ch05_test6.js 파일로 만든 후, 클라이언트 요청을 처리하는 콜백 함수의 코드를 다음과 같이 수정한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
var http = require('http');
var fs = require('fs');
// 웹 서버 객체를 만든다.
var server = http.createServer();
// 웹 서버를 시작하여 3000번 포트에서 대기하도록 설정한다.
var port = 3000;
server.listen(port, function(){
console.log('웹 서버가 시작되었습니다. : %d',port);
});
// 클라이언트 연결 이벤트 처리
server.on('connection', function(socket){
var addr = socket.address();
console.log('클라이언트가 접속했습니다. : %s, %d',addr.address, addr.port);
});
// 수정한 부분 // 클라이언트 요청 이벤트 처리
server.on('request', function(req, res){
console.log('클라이언트 요청이 들어왔습니다.');
var filename = "cat.png";
var infile = fs.createReadStream(filename, {flags:'r'});
// 파이프로 연결하여 알아서 처리하도록 설정하기
infile.pipe(res);
});
// 서버 종료 이벤트 처리
server.on('close', function(){
console.log('서버가 종료됩니다.');
});
|
cs |
이 파일을 실행한 후 웹 브라우저에서 요청을 보내면 같은 결과를 확인할 수 있다.
똑같은 기능을 더 적은 양의 코드로 만들었으니 이 방법이 더 좋다고 생각할 수 있다. 하지만, 실제로 이 방법으로 코딩을 했을 때 헤더를 설정할 수 없는 등의 제약이 생기기 때문에 필요할 때만 사용하길 권장한다.
파일을 버퍼에 담아두고 일부분만 읽어 응답 보내기
이번에는 파일을 버퍼에 담아 일정 크기만큼 읽어 응답을 보내는 방법에 대해 알아보자.다음 코드는 파일을 스트림으로 읽은 후 일정 크기의 데이터를 읽어 응답을 보내는 방식이다.스트림에서 파일을 읽을 때 버퍼의 크기를 정하면 파일을 버퍼 크기만큼씩 읽어 응답할 수 있다. 그런 다음 마지막에 end() 메소드를 호출하여 응답으로 전송할 수 있다.ch05_test6.js 파일의 클라이언트 요청 처리 부분을 다음과 같이 수정한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
var http = require('http');
var fs = require('fs');
// 웹 서버 객체를 만든다.
var server = http.createServer();
// 웹 서버를 시작하여 3000번 포트에서 대기하도록 설정한다.
var port = 3000;
server.listen(port, function(){
console.log('웹 서버가 시작되었습니다. : %d',port);
});
// 클라이언트 연결 이벤트 처리
server.on('connection', function(socket){
var addr = socket.address();
console.log('클라이언트가 접속했습니다. : %s, %d',addr.address, addr.port);
});
// 클라이언트 요청 이벤트 처리
server.on('request', function(req, res){
console.log('클라이언트 요청이 들어왔습니다.');
var filename = "cat.png";
var infile = fs.createReadStream(filename, {flags:'r'});
var filelength = 0;
var curlength = 0;
fs.stat(filename, function(err, stats){
filelength = stats.size;
});
// 헤더 쓰기
res.writeHead(200, {"Content-Type":"image/png"});
// 파일 내용을 스트림에서 읽어 본문 쓰기
infile.on('readable', function(){
var chunk;
while(null != (chunk = infile.read())){
console.log('읽어 들인 데이터 크기 : %d 바이트',chunk.length);
curlength += chunk.length;
res.write(chunk,'utf8',function(err){
console.log('파일 부분 쓰기 완료 : %d, 파일 크기 : %d', curlength, filelength);
if(curlength >= filelength){
//응답 전송하기
res.end();
}
});
}
});
});
// 서버 종료 이벤트 처리
server.on('close', function(){
console.log('서버가 종료됩니다.');
});
|
cs |
코드의 양이 조금 많아졌다. 그 이유는 파일을 읽기 전에 먼저 파일을 열고, 그다음에 스크림에서 일정 크기만큼 읽어 응답을 보내는 방식이기 때문이다.
응답 객체의 end() 메소드를 호출하는 시점은 write() 메소드가 종료되는 시점이어야한다.
따라서, write() 메소드에 콜백 함수를 전달하여 쓰기가 완료된 시점을 확인한다. 그 콜백 함수 안에서는 파일의 크기만큼 응답 객체에 쓰기를 모두 완료했는지 확인하고, 응답 객체에 쓰는 작업이 모두 완료되었다면 end() 메소드를 호출하여 응답데이터를 전송한다.
이 파일을 실행하고 웹 브라우저에서 접속한다면 앞의 코드처럼 똑같은 결과를 보여준다.
서버에서 다른 웹 사이트의 데이터를 가져와 응답하기
지금까지 일정 크기만큼 파일을 읽어 응답을 보내는 코드를 만들고 실행해보았다.
이제 우리의 관심사는 웹 서버를 만들어 웹 브라우저나 스마트폰 앱에서 들어오는 요청에 응답하는 것이다.
하지만, 서버에서는 다시 다른 웹 사이트를 접속하여 데이터를 가져온 후 응답하는 과정이 필요할 때도 있다. 이 경우에는 서버에서 HTTP 클라이언트 기능도 사용하게 된다.
그럼 간단한 HTTP 클라이언트를 만들려면 어떻게 해야할까? http 모듈은 서버기능 이외에 클라이언트 기능도 제공한다.
즉, HTTP 클라이언트가 GET 과 POST 방식으로 다른 웹 서버에 데이터를 요청할 수 있다.
다음은 HTTP 모듈을 사용해 GET 방식으로 다른 사이트에 데이터를 요청하는 코드이다.
ch05_test7.js 파일을 새로 만든 후, 다음과 같이 입력한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
var http = require('http');
var options = {
host: 'www.google.com',
port: 80,
path: '/'
};
var req = http.get(options, function(res){
//응답처리
var resData = '';
res.on('data', function(chunk){
resData += chunk;
});
res.on('end', function(){
console.log(resData);
});
});
req.on('error',function(err){
console.log('오류 발생 : ' + err.message);
});
|
cs |
http 객체의 get() 메소드를 사용하면 다른 사이트에 요청을 보내고 응답을 받아 처리할 수 있다.
get() 메소드의 첫 번째 파라미터(options)는 다른 사이트의 정보를 담고 있는 객체이다. 그리고 두 번째 파라미터(function)는 콜백함수이다. 응답 데이터를 받을 때는 data 이벤트와 end 이벤트로 처리하면된다.
데이터를 받고 있는 상태에서는 data 이벤트가 발생하므로 이때 받은 데이터를 모두 resData 변수에 담아 둔다.
end 이벤트를 처리하면 응답 데이터를 모두 받은 후에 콘솔 창에 출력할 수 있다.
이 파일을 실행하면 다음처럼 구글 사이트에서 온 응답을 볼 수 있다.
(코드 원본을 보고싶다면, 명령 프롬프트 창에서 실행하면된다.)
웹 서버에서 다른 서버로 요청할 때의 과정을 정리하면 다음과 같다.
다른 서버로부터 응답을 받을 때는 data 이벤트가 발생한다. 수신 데이터의 용량에 따라서 data 이벤트는 한 번 또는 여러 번 발생할 수 있다.
데이터 수신이 완료되면 end 이벤트가 방생한다.
POST 방식으로 요청할 경우에는 request() 메소드를 사용한다. 이 request() 메소드는 get() 메소드와 사용방식이 약간 다르다. 특히 요청을 보내려면 요청 헤더와 본문을 모두 직접 설정해야한다.
다음은 http 모듈을 사용해서 POST 방식으로 다른 사이트에 데이터를 요청하는 코드이다.
ch05_test8.js 파일을 만들고 코드를 작성한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
var http = require('http');
var opts = {
host : 'www.google.com',
port : 80,
method : 'POST',
path : '/',
headers : {}
};
var resData = '';
var req = http.request(opts,function(res){
// 응답 처리
res.on('data',function(chunk){
resData += chunk;
});
res.on('end',function(){
console.log(resData);
});
});
opts.headers['Content-Type'] = 'application/x-www-form-urlencoded';
req.data = 'q=actor';
opts.headers['Content-Length'] = req.data.length;
req.on('error',function(err){
console.log('오류 발생 : ' + err.message);
});
// 요청 전송
req.write(req.data);
req.end();
|
cs |
GET 방식과 POST 방식의 차이점은 무엇일까?
웹 서버에 요청을 보내는 방식은 GET, POST, PUT, DELETE 등 여러가지가있다.
인터넷 표준으로 정해 둔 이러한 요청 방식을 메소드라고 부른다. HTTP 요청 포맷을 크게 보면 헤더(Header)와 본문(Body) 부분으로 나뉘는데, GET 방식은 헤더 부분에 요청들을 넣어 보내고 POST 방식은 본문 부분에 요청 정보를 넣어서 보낸다.
이 두 가지 방식은 기능상으로는 요청 정보를 보낸다는 점에서는 같지만, 보안 등의 이슈가 있을 때나 파일을 요청 정보로 넣어 보내야하는 경우에는 POST 방식을 주로 이용한다.
구글 사이트에 요청할 때 필요한 요청 파라미터는 요청 객체의 data 속성으로 설정한다. 이 속성에 따라서 Content-Length 헤더의 값이 달라지므로 request() 메소드로 만든 요청 객체에 이 정보를 추가로 설정한다.
요청 할 때는 write() 메소드로 요청 본문 데이터를 req 객체에 쓴 후, end() 메소드로 사용해 전송한다.
이 파일을 실행하면 구글 사이트에서는 POST 요청을 받지 못하기 때문에 오류가 발생한다. 하지만 POST 메소드로 요청할 수 있는 다른 사이트에서는 정상적인 응답을 받을 수 있다.
웹 서버를 만들 때 사용하는 http 모듈의 기능은 더 많다. 하지만 실무에서는 웹 서버를 구성할 때, express 모듈을 주로 사용하므로 http 모듈은 이정도만 이해하면된다.
다만 express 모듈을 사용하더라도 express 모듈은 http 모듈을 기초로 만들어진 것이므로 어느 정도 이해하고 넘어간다.
'Theorem (정리) > node.js' 카테고리의 다른 글
(node.js) [Part.5] 웹 서버 만들기 - 미들웨어 사용하기 (0) | 2020.12.08 |
---|---|
(node.js) [Part.5] 웹 서버 만들기 - 익스프레스로 웹 서버 만들기 (0) | 2020.12.08 |
(node.js) Do it! 도전문제(1), (2) (0) | 2020.12.07 |
(node.js) [Part.4] 노드의 기본 기능 알아보기 - 로그 파일 남기기 (0) | 2020.12.06 |
(node.js) [Part.4] 노드의 기본 기능 알아보기 - 파일 다루기 (0) | 2020.12.06 |