2015년 4월 20일 월요일

Mac, Node.js 학습 5일차] 웹 개발

웹 브라우즈를 통한 웹 서비스 작성을 학습한다.

1. http 모듈
웹 개발을 위한 모듈로써 웹 서버를 위한 server 객체, response 객체등을 생성하기 위한 모듈이다.
웹개발을 위한 기본 개념인 http request(요청)/response(응답)에 대한 상세내역은 다음 사이트에서 참조한다.(Jonic:HTTP 프로토콜 분석)

  - 특정 웹 페이지에 대한 http 요청/응답에 대한 상세 정보 보기
    . 사파리 : 페이지에서 우클릭 > 요소점검으로 표시된 창의 우측 "리소스"에서 확인
    . 크롬 : 페잊에서 우클릭 > 요소점검으로 표시된 창의 "Network" 탭에서 확인

2. Server 객체
server 객체를 생성해서 웹 서버를 실행한다. 웹 브라우즈에서 http request에 대해서 business logic을 처리후 웹 브라우즈로 http response 를 보내준다.
  - 객체 Method
    . listen(port, [callback]); : 서버 실행
    . close() : 서버 종료
  - 객체 Event
    . connection : 클라이언트가 접속할때 발생하는 이벤트
    . request : 클라이언트가 요청할때 발생하는 이벤트
    . close : 클라이어트가 접속을 끊을 발생하는 이벤트
    . checkContinue : 클라이언트가 지속적으로 연결하고 있을때 발생하는 이벤트로써 client에서 Expect: 100-continue와 함께 request 할때 발생함
    . upgrade : 클라이언트가 upgrade(?)를 요청할때 발생하는 이벤트
    . clientError : 클라이언트에서 오류가 발생할 때 발생하는 이벤트

  - 사용 예
baesunghan:~/Documents/workspace/nodejs$cat node.server1.js
// 모듈을 추출합니다.
var http = require('http');

// 웹 서버 객체 생성
var server = http.createServer();


// 서버 객체에 event 연결
server.on('request', function() {
console.log('Request On');
});
server.on('connetion', function() {
console.log('Connection on');
});
server.on('close', function() {
console.log('Close on');
});

// 서버 실행
server.listen(18080, function() {
console.log('Server running at http://127.0.0.1:18080/');
});
baesunghan:~/Documents/workspace/nodejs$

    => 웹 브라우즈에 아무런 응답이 없음, 이는 response 이벤트가 정의되지 않아서 일어나는 것임, 서버 console에는 로그가 표시됨.
    => 이상한 것은 "Connection on" 메시지가 서버 console 창에 출력되지 않음. 추후 확이 필요함.
    => 서버 종료는 Ctrl + C로 종료해야 아래 오류 발생하지 않음.

  - listen EADDRINUSE 오류 처리
    . 최초 실행은 정상 실행되었음, 서버를 Ctrl + Z로 종료함
baesunghan:~/Documents/workspace/nodejs$node node.server1.js
Server running at http://127.0.0.1:18080/
Request On
Request On
^Z
[1]+  Stopped                 node node.server1.js
baesunghan:~/Documents/workspace/nodejs$
    . 이후 다시 해당 서버를 실행했지만 다음 오류가 발생함.
baesunghan:~/Documents/workspace/nodejs$node node.server1.js
events.js:85
      throw er; // Unhandled 'error' event
            ^
Error: listen EADDRINUSE
    at exports._errnoException (util.js:746:11)
    at Server._listen2 (net.js:1146:14)
    at listen (net.js:1172:10)
    at Server.listen (net.js:1257:5)
    at Object.<anonymous> (/Users/baesunghan/Documents/workspace/nodejs/node.server1.js:20:8)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
baesunghan:~/Documents/workspace/nodejs$

    => 발생 이유는 서버가 정상 종료되지 않아 18080에 대한 서버가 실행중임, 아래 내용 프로세스 확인 후 kill 한 후 다시 실행한다.
baesunghan:~/Documents/workspace/nodejs$ps -ef | grep node
  501   760   449   0 12:56PM ttys000    0:00.12 node node.server1.js
  501   807   797   0  1:08PM ttys001    0:00.00 grep node
baesunghan:~/Documents/workspace/nodejs$kill -9 760
baesunghan:~/Documents/workspace/nodejs$ps -ef | grep node
  501   811   797   0  1:11PM ttys001    0:00.00 grep node
baesunghan:~/Documents/workspace/nodejs$

3. response 객체
웹 서버에서 클라이언트로 응답하기 위한 객체
  - 제공 메소드
    . wirteHead(statusCode, object);  : 응답 헤더를 작성
    . end([data], [encoding]) : 응답 본문을 작성
  - 사용 예
baesunghan:~/Documents/workspace/nodejs$cat node.server1.js
// 모듈을 추출합니다.
var http = require('http');

// 웹 서버 객체 생성
var server = http.createServer(function(request, response) {
response.writeHead(200, { 'Content-Type': 'text/html'});
response.end('<h1>Hello World!!!')
});

  - 일반적으로 html 파일을 읽어서 클라이언트로 제공하는 방식 사용함
  - html 파일 사용 예
baesunghan:~/Documents/workspace/nodejs$cat node.server1.js
// 모듈을 추출합니다.
var http = require('http');
var fs = require('fs');

// 웹 서버 객체 생성
var server = http.createServer(function(request, response) {
// read html file
fs.readFile('htmlsample.html', function(error, data) {
response.writeHead(200, { 'Content-Type': 'text/html'});
response.end(data);

});
});

  -  이미지나 미디어 파일 사용 예
baesunghan:~/Documents/workspace/nodejs$cat node.server2.js
// 모듈을 추출합니다.
var http = require('http');
var fs = require('fs');

// 웹 서버 객체 생성
var server = http.createServer(function(request, response) {
// read html file
fs.readFile('flower.jpg', function(error, data) {
response.writeHead(200, { 'Content-Type': 'image/jpeg'});
response.end(data);

});
});

  - response객체의 응답 메시지를 위한  Context-Type : MIME 형식, 상세 참조(MIME Types List - FreeFormatter.com)
    . text/plain : 기본적인 텍스트
    . text/html : HTML 문서
    . text/css : CSS 문서
    . text/xml : XML 문서
    . image/jpeg : JPG/JPEG 이미지 파일
    . image/png : PNG 이미지 파일
    . video/mpeg : MPEG 비디오 파일
    . audio/mp3 : MP3 음악 파일


4. 쿠키 생성
일정 기간동안 서버나 클라이언트에 접속에 관련된 정보를 저장하는 역할을 합니다. 로그인시 이전 접속 id를 기억하는 기능 등을 사용할때 쿠키를 사용함.
  - 사용 : response 객체에 Set-Cookie로 key=value; 형태로 저장합니다
  - 사용 예
// 모듈을 추출합니다.
var http = require('http');
var fs = require('fs');

// 웹 서버 객체 생성
var server = http.createServer(function(request, response) {
// read html file
fs.readFile('flower.jpg', function(error, data) {
response.writeHead(200, { 
'Content-Type': 'image/jpeg',
'Set-Cookie': ['id=bsh', 'name=Toven']});
response.end(data);

});
});

5. 페이지 이동(redirection)
특정 페이지를 호출시 다른 페이지로 이동할 경우 사용함.
  - 사용 : response 객체에 StatusCode : 302, Location 항목값 설정
  - 사용 예
baesunghan:~/Documents/workspace/nodejs$cat node.server2.js
// 모듈을 추출합니다.
var http = require('http');
var fs = require('fs');

// 웹 서버 객체 생성
var server = http.createServer(function(request, response) {
// read html file
fs.readFile('flower.jpg', function(error, data) {
response.writeHead(302, { 
'Content-Type': 'text/html',
'Set-Cookie': ['id=bsh', 'name=Toven'],
'Location': 'http://wechatmanager.co.kr'});
response.end(request.headers.cookie);

});
});

6. request 객체
클라이언트에서 호출시 request 이벤트가 발생하고 request 객체가 생성됨
  - 객체 속성
    . method : 클라이언트의 요청 방식, GET/POST/PUT
    . url : 클라이언트가 요청한 url
    . headers : 요청 메시지의 header 정보
    . trailers : 메시지 트레일러 정보
    . httpVersion : HTTP Protocol 버젼 정보

6.1 url 속성을 사용한 페이지 구분 처리
클라이언트에서 호출하는 url 정보에 따라서 각기 다른 페이지가 표시되도록 처리하는 방식
  - 사용 예
baesunghan:~/Documents/workspace/nodejs$cat app01.js
// 모듈을 추출합니다.
var http = require('http');
var fs = require('fs');
var url = require('url');

// 웹 서버 객체 생성
var server = http.createServer(function(request, response) {

var pathname = url.parse(request.url).pathname;
var filename = "";
console.log(pathname);

if (pathname == "/") {
filename = 'index.html';
} else if (pathname == '/other') { 
filename = 'other.html';
}
// read html file
fs.readFile(filename, function(error, data) {
response.writeHead(200, { 'Content-Type': 'text/html'});
response.end(data);

});
});

// 서버 실행
server.listen(18080, function() {
console.log('Server running at http://127.0.0.1:18080/');
});
baesunghan:~/Documents/workspace/nodejs$

 이외에도 method 속성(GET, POST 등)을 이용한 방법, GET 호출 매개변수, POST 호출 매개변수 방법등으로 페이지 구분 처리가 가능함.
   - 사용 예
baesunghan:~/Documents/workspace/nodejs$cat app02.js
// 모듈을 추출합니다.
var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring');

// 웹 서버 객체 생성
var server = http.createServer(function(request, response) {
console.log(request.method);
var pathname = '';
var filename = "";
if (request.method == 'GET') {
// Get 으로 넘어온 파라메타에서 page에 값을 추룰해서 파일로 읽는다.
var query = url.parse(request.url).query;
var param = qs.parse(query);
console.log('query : %s', query);
console.log('querystring : %s', param);
console.log('query : page value : %s', query.page);
console.log('query string : page value : %s', param.page);
filename = param.page + '.html';
console.log(filename);
// read html file
fs.readFile(filename, function(error, data) {
response.writeHead(200, { 'Content-Type': 'text/html'});
response.end(data);

});

} else if (request.method == 'POST') {
request.on('data', function(data) {
var param = qs.parse(data);
response.writeHead(200, { 'Content-Type': 'text/html'});
response.end(param);
})

}
});

// 서버 실행
server.listen(18080, function() {
console.log('Server running at http://127.0.0.1:18080/');
});
baesunghan:~/Documents/workspace/nodejs$

    => parammeter로 넘어온 query 값 parsing을 위해서 querystring을 이용하여 JSON 으로 객체화한다. 반대 처리는 query.stringify를 이용하면 된다. [참조 : 3일차 학습 중 4. Query String 모듈]

댓글 없음:

댓글 쓰기