2017년 11월 24일 금요일

Chapter8. HTTP 서버



학습 목표


  1. HTTP 모듈을 이용해서 서버를 작성할 수 있습니다.
  2. HTTP 요청을 분석하는 코드를 작성할 수 있습니다.
  3. HTTP 응답 메시지를 작성하는 코드를 작성할 수 있습니다.
  4. 정적 파일 요청과 서비스 제공하는 서버를 작성할 수 있습니다.


1. HTTP 서버

◎ HTTP 서버 구동 코드
var http = require('http');
var server = http.createServer(function(req, res) {
    res.end('Hello World');
}).listen(3000);

2. HTTP 요청

◎ HTTP 요청
  • 클라이언트 요청 분석
  • request 이벤트 리스너의 파라미터
  • req : IncomingMessage
    var server = http.createServer(function(req, res) {} )
▷ 클라이언트 요청 분석
▷ IncomingMessage
  • message.url : 요청 url, 경로와 쿼리 문자열
  • message.method : 요청 메소드
  • message.headers : 요청 메소드의 헤더
  • message(streamable) : 요청 메시지 바디
▷ 요청 URL 경로와 쿼리 문자열 분석
▷ URL 분석하기 : URL 모듈
var url = require('url');
url.parse(req.url, true);

▷ 요청 메시지 헤더 분석
▷ 헤더 정보 : request.header
var headers = request.headers;
headers.host;
headers.content-type;
headers.user-agent;
. . .

▷ 요청 메시지 바디 분석
  • IncomingMessage의 data 이벤트 사용
  • POST 요청을 다루는 장에서 다룬다.
◎ HTTP 요청 출력
▷ 요청 내용 콘솔에 출력하기
var server = http.createServer(function(req, res) {
    console.log('HTTP Method : ' + req.method);
    console.log('HTTP URL : ' + req.url);
    console.log('== HEADERS ==');
    console.log(req.headers);

    res.end('Hello Node.js');
});

3. HTTP 응답

◎ 응답 메시지

  • 응답 메시지 : http.ServerResponse
  • 상태 코드와 상태 메시지
  • 응답 메시지 헤더
  • 응답 메시지 바디
▷ 메시지 상태
response.statusCode
response.statusMessage

▷ 메시지 헤더
response.writeHead(statusCode[, statusMessage][, headers])
response.removeHeader(name)
response.getHeader(name)
response.setHeader(name, value)

▷ 메시지 바디
response.end([data][, endcoding][, callback])
response.write(chunk[, encoding][, callback])

▷ HTTP 상태 코드와 메시지
// 200 OK
response.statusCode = 200;
response.statusMessage = 'OK';

// 404 Error
response.statusCode = 404;
response.statusMessage = 'Not found';

▷ 응답 메시지 헤더

▷ 응답 코드, 메시지 헤더 작성 함수 : writeHead
res.writeHead(200, {'Content-Length': body.length,
                          'Content-Type': 'text/plain'});

▷ 헤더 작성하기 : setHeader
res.setHeader("Content-Type", "text/html");
res.setHeader("Content-Length", body.length);

▷ 응답 메시지 바디
▷ 응답 메시지 종료
response.write(chunk[, endcoding][, callback])
response.end()

▷ 응답 메시지 작성 시 주의

▷ 응답 메시지 종료 - 클라이언트 대기 - timeout
http.createServer(function(req, res) {
    res.write('Hello Node.js');
    res.end(); // 응답 메시지를 완료시켜주어야 한다.
});

▷ 메시지 헤더는 메시지 바디 작성 전에
res.write('Hello World');
// 바디를 작성한 이후에 헤더를 작성하면 에러가 발생한다.
res.setHeader('Conent-Type', 'text/plain');

4. HTTP 서버 작성

◎ 정적 파일 요청
▷ 정적인 컨텐츠(이미지, html, 음악 등) 요청
  • 미리 작성된 파일로 응답
▷ 요청 예
  • http://myServer.com/image/cat.jpg
  • http://myservice.net/music/sing.mp3
▷ 요청 경로
  • req.url
▷ 요청 경로 분석
  • path 모듈
▷ 정적 파일 요청 : 응답
  • 정적 파일 찾기
  • 파일 로딩, 응답
▷ fs 모듈
  • fs.readFile(FILEPATH, CALLBACK);
▷ 응답 메시지에 파일 내용 쓰기
  • res.write();
  • res.end();
▷ 정적 파일 요청에 대한 응답
fs.access(path, fs.F_OK, function(exist) {
    fs.readFile(path, function(err, data) {
        res.end(data);
    });
});

◎ 정적 파일 요청
  • 정적 파일 요청에 대한 응답
  • 정적 파일 체크
  • 상태 코드
  • 컨텐츠 타입
▷ 파일이 없으면?

▷ 404 에러 처리 코드
fs.access(path, fs.R_OK, function(err) {
    // 접근 불가능 시 404 에러
    if( err ) {
        res.statusCode = 404;
        res.end('Not Found');
        return;
    }
}

▷ 정적 파일 응답
fs.access(path, fs.F_OK, function(err) {
    if( err ) {
        res.statusCode = 404;
        res.end('Not found');
        return;
    }
    fs.readFile(path, function(err, data) {
        res.statusCode = 200;
        res.setHeader('Content-type', 'image/jpg');    // 이미지라면
        res.end(data);
    });
});

▷ 스트림 파이프
  • 입력 스트림 : fs.createReadStream()
  • 출력 스트림 : res
    fs.createReadStream(path).pipe(res);
▷ 파미콘 : 웹 사이트의 아이콘 이미지
▷ 파비콘 요청
  • GET /favicon.ico
▷ 파비콘 응답 코드
if( request.url == '/favicon.ico' ) {
    // 파비콘 처리
    return;
}

▷ 컨텐츠 타입
var server = http.createServer(function(req, res) {
    if(req.url == '/favicon.ico') {}
    else if(req.url == '/image.png' ) {
        res.writeHeader(200, {'Content-Type':'image/png'});
        fs.read...
    }
    else if(req.url == '/music.mp3') {
        res.writeHeader(200, {'Content-Type':'audio/mp3'});
        fs.createReadStrea...
    }
    else if(req.url == '/movie.mp4') {
        res.writeHead(200, {'Content-Type':'video/mp4'});
        fs.createReadStream...
    }
});

◎ 정적 파일 서비스
▷ 요청 URL의 경로를 실제 파일 경로 매핑
  • myServier.com/resource/image.png -> ./resources/image.png
  • myServier.com/resource/audio.mp3 -> ./resources/audio.mp3
▷ 요청 url에서 경로 생성
URL로부터 파일의 패스 정보를 가져와서 바로 파일에 대한 경로를 만들어 줄 수 있다.
파일을 찾고 파일에 대한 읽기위한 경로를 만드는 과정이 단순해짐.

var pathUtil = require('path');
var path= __dirname + pathUtil.sep + 'resources' + req.url;

◎ 웹 페이지 서비스
▷ 요청
  • 인덱스 요청
  • 파비콘 요청
  • JS와 css요청
  • 이미지 요청 : <img>
▷ 서비스 용 html
<html>
<link rel="stylesheet" type="text/css" href='public/style.css'>
<body>
    <h1>Hello Kitty</h1>
    <img src='image/cat.jpg'>
</body>
</html> 

html요청
css 요청
image 요청
파비콘 요청 에 대한 응답 처리를 모두 해주저야 한다.

▷ 서버 코드
var server = http.createServer(function(req, res) {
    if(req.url == '/favicon.ico') {
        // 파비콘 응답
    }
    else if(req.url == '/') {
        // 기본 페이지 : index.html
        fs.createReadStream('./public/index.html').pipe(res);
    }
    else {
        var path = __dirname + req.url;
    }
})

◎ 서비스
▷ 서비스
▷ URL 쿼리 문자열 : 합계 구하기
http://127.0.0.1:3000/count?start=1&end=10

▷ 서버 코드
// URL 분석 : 쿼리 문자열
var parsed = url.parse(request.url, true);
var query = parsed.query;

// start와 end
var start = parseInt(query.start);
var end = parseInt(query.end);

if(입력값 오류) {
    response.statusCode = 404;
    response.end('Wrong Parameter');
}
else {
    // 합계 구하기
    response.statusCode = 200;
    response.end('Result : ' + result);
}

학습 정리

◎ 지금까지 'HTTP 서버'에 대해 살펴보았습니다.
  • HTTP 요청
    클라이언트의 HTTP 요청을 분석했습니다.
  • HTTP 응답
    클라이언트에게 HTTP 응답 메시지를 작성하고 전송하는 방법을 알아봤습니다.
  • HTTP 서버
    다양한 형태의 HTTP 서버 작성 방법을 알아봤습니다.
   



2017년 11월 13일 월요일

Chapter7. HTTP 통신


학습 목표


  1. HTTP 통신의 특징을 이해할 수 있습니다.
  2. HTTP 통신을 다루는 HTTP 모듈 사용 방법을 알 수 있습니다.
  3. HTTP 서버와 클라이언트 클래스와 주요 메소드를 알 수 있습니다.

1. HTTP 통신

◎ HTTP
  • 웹(WWW)의 주역!
  • HTTP : Hyper Text Transfer Protocol
  • 하이퍼 텍스트 - 하이퍼 링크로 논리적으로 연결된 문서
  • ex) HTML
◎ HTTP 통신의 특징
▷ HTTP 통신
  • 요청(Request)
  • 응답(Response)
▷ 요청과 응답 과정
  • 웹 브라우저 → 주소 입력 → 요청 → 웹 서버 → 응답 → 웹 브라우저
◎ HTTP 통신

◎ URL
▷ 리소스의 위치 : URL(Uniform Resource Locator)
  • http://username:password@host:8080/directory/file?query#ref:
◎ URL 인코딩
▷ URL에 허용되는 문자
  • 알파벳, 숫자, 하이픈, 언더스코어, 점 틸드
▷ URL 인코딩하기
  • https://www.google.com/search?q=아이폰
  • https://www.google.com/search?q=%EC%95%84%EC%9D%B4%ED%8F%B0
◎ 웹 브라우저에서 요청/응답 확인해보기
▷ 웹브라우저
  • 개발자 도구


2. HTTP 요청

◎ HTTP 메시지 구조
▷ 요청 메시지
  • 요청 라인
  • 요청 헤더
  • 요청 바디(엔티티)
http body를 사용하지 않는 요청 메시지

◎ 요청 라인
  • 요청 메소드
  • 요청 URL
  • HTTP 버전
    GET http://en.wikipedia.org/wiki/The_Scream HTTP/1.1
◎ HTTP 메소드
  • HTTP 메소드 : 리소스를 다루는 행위
    GET : 리소스를 얻어오는 요청
    POST : 리소스 전송 요청
    PUT : 저장 요청(수정)
    DELETE : 삭제
    . . . 
◎ 요청 헤더

  • 헤더는 키 : 값 방식으로 작성
▷ 주요 요청 헤더
Accept : 클라이언트가 받을 수 있는 컨텐츠
Cookie : 쿠키
Content-Type : 메시지 바디(엔티티)의 종류
Content-Length : 메시지 바디의 길이
if-Modified-Since : 특정 날짜 이후에 변경됐을 때만

◎ 요청 정보 전달
▷ URL을 이용해서 요청 정보 전달
  • GET 메소드, TRACE 메소드 : 메시지 바디를 사용하지 않으므로 URL만으로 클라이언트가 원하는 정보를 전달
▷ 경로와 쿼리 스트링 사용
  • http://idols.com/snsd/taeyon.png
  • http://idols.com/q?group=snsd&name=jessica
▷ 메시지 바디를 사용하지 않는다.

◎ 요청 정보 전달
▷ URLEncoded 방식
▷ 메시지 헤더(컨텐츠 타입)
  • application/x-www-form-urlencoded
▷ 메시지 바디 : 쿼리 문자열
▷ 메시지 예
Content-Type : application/x-www-form-urlencoded
title=Madmax&Director=George+Miller

◎ 요청 정보 전달
▷ JSON/XML
▷ 메시지 헤더(컨텐츠 타입)
  • application/json
▷ 메시지 예
Content-Type:application/json
{
    "name":"iu", "best":"좋은 날"
}

◎ 요청 정보 전달
▷ 멀티 파트를 이용한 요청 정보 전달
  • 바이너리 파일을 올리는 경우에 주로 사용
  • 하나의 메시지 바디에 파트를 나눠서 작성
▷ 메시지 헤더

  • 컨텐츠 타입 ; 파트 구분자(boundary)
  • multipart/form-data; boundary=frontier
▷ 각 파트별 컨텐츠 타입
▷ 파트로 구성된 바디

◎ 요청 정보 전달
▷ 요청 정보 전달
  • 메시지 바디를 사용 여부
  • 바디의 인코딩 방식
▷ URL로 요청 정보 전달 : 바디 분석 불필요

3. HTTP 응답

◎ HTTP 메시지 구조
▷ 응답 메시지
  • 응답 라인
  • 응답 헤더
  • 응답 바디
◎ HTTP 메시지
◎ 응답 메시지
▷ 응답 라인
  • 버전
  • 상태 코드
  • 상태 메시지 → HTTP/1.1 200 OK
◎ 상태 코드
▷ 상태 코드 : 서버의 응답 코드
▷ 대 분류
  • 1xx : 정보
  • 2xx : 성공
  • 3xx : 리다이렉션
  • 4xx, 5xx : 오류
▷ 상태 코드 : 2xx
  • 200 : OK. 요청 성공
  • 201 : Created. 생성 요청 성공
  • 202 : Accepted : 요청 수락. 요청 처리는 보장 안됨
  • 203 : Non-authoritavive Information
  • 204 : Non Content...
▷ 상태 코드 : 3xx
  • 300 : Multiple choices. 여러 리소스에 대한 요청 결과 목록
  • 301, 302, 303 : Redirect. 리소스 위치가 변경된 상태
  • 304 : Not Modified. 리소스가 수정되지 않았음...
▷ 상태 코드 : 4xx
  • 400 : Bad Request. 요청 오류, 요청을 처리하는 필수 데이터가 없는 경우
  • 401 : Unauthorized. 권한 없는 상태
  • 403 : Forbidden. 요청 거부 상태
  • 404 : Not Found. 리소스가 없는 상태...
▷ 상태 코드 : 5xx
  • 500 : Internal Server Error. 서버가 요청 처리를 못하는 상태
  • 501 : Not Implemented. 서버가 지원하지 않는 요청
  • 503 : Service Unavailable. 과부하 등으로 당장 서비스가 불가능한 상태 ...
◎ 응답 메시지 헤더
▷ 응답 메시지 헤더
▷ 주요 헤더 필드
  • Content-Type : 바디 데이터의 타입
  • Content-Length : 바디 데이터 크기
  • Set-Cookie : 쿠키 설정
  • ETag : 엔티티 태그
◎ 응답 메시지 바디
▷ 바디 데이터
  • HTML
  • XML/JSON
  • Octet Stream 등
▷ 바디 기록 방식 : Content-Type 헤더 필드

▷ 컨텐츠 타입
  • 메시지 헤더에 기록
  • 필드 이름 content-type
  • 대분류/소분류
▷ 주요 컨텐츠 타입
  • text/plain, text/html
  • application/xml, application/json
  • image/png, image/jpg
  • audio/mp3, video/mp4
◎ 응답 메시지
▷ HTML 응답 메시지 헤더
  • content-type:text/html
▷ HTML 응답 메시지 바디
<html>
<body>
<h1>Hello Node.js</h1>
</body>
</html>

▷ HTML 응답 메시지 헤더
  • content-length: 73228
  • content-type: image/jpeg
▷ HTML 응답 메시지 바디 - 이미지를 헥사타입으로 출력

◎ 응답 메시지
  • 컨텐츠 타입이 안 맞으면?
  • 컨텐츠 타입 : application/json
  • 실제 바디 데이터 : 이미지
  • 제대로 표현하지 못한다.

4. HTTP 모듈

◎ HTTP 모듈
▷ HTTP 모듈, 기본 모듈
  • var http = require('http');
▷ HTTP 서버
  • 클라이언트의 요청 메시지 수신
  • 클라이언트에게 응답 메시지 전송
▷ HTTP 클라이언트
  • 서버로 요청 메시지 전송
  • 서버의 응답 메시지 수신
◎ HTTP 모듈 클래스
▷ 서버용 클래스
  • http.Server : HTTP 서버
  • http.IncomingMessage : HTTP 서버의 요청 메시지, Readable Stream
  • http.ServerResponse : HTTP 서버의 응답 클래스
▷ HTTP 클라이언트
  • http.Client : HTTP 클라이언트
  • http.ClientRequest : HTTP 클라이언트 요청 메시지
  • http.IncomingMessage : HTTP 서버의 응답 메시지, Readable Stream
◎ HTTP 모듈

5. HTTP 서버

◎ HTTP 서버
▷ HTTP 서버
  • http.Server
▷ HTTP 서버 생성
  • var server = http.createServer([requestListener])
▷ HTTP 서버 주요 이벤트
  • request : 클라이언트의 요청 도착
  • connection : 소켓 연결
  • close : 서버 종료
▷ HTTP 서버 메소드
  • server.listen()
  • server.close()
  • server.setTimeout()
◎ HTTP 서버
▷ HTTP 서버 동작시키기

  • 서버 객체 생성
  • 클라이언트 접속 대기(listening)
    var server = http.createServer();
    server.listen(PORT);
▷ 포트
  • 0~1023 : well-known port, 미리 정의된 포트, 관리자 권한 필요
  • 1024 ~ 49151 : registered port
  • 49151 ~ 65535 : dynamic port
▷ 포트 바인딩 실패
  • 이미 사용 중
  • 권한 없음
▷ 서버와 이벤트 리스너
var http = require('http');
var server = http.createServer();
server.on('request', function(request, response) {
});
server.on('connection', function(socket) {
    console.log('connection event');
});
server.on('close', function() {
    console.log('close');
});
server.listen(3000);

▷ HTTP 서버 request 이벤트 리스너
var http = require('http');
var server = http.createServer(function(req, res) {
    res.end('Hello World');
}).listen(3000);

웹 브라우저 : http://127.0.0.1:3000

6. HTTP 클라이언트

◎ HTTP 클라이언트
▷ 클라이언트 객체
  • http.create([port][, host]) // deprecated
▷ 클라이언트 요청
  • http.request(options[, callback])
▷ 바디 없이 요청 보내기(GET)
  • http.get(options[, callback])

학습정리

◎ 지금가지 'HTTP 통신'에 대해 살펴보았습니다.
  • HTTP 통신
    요청과 응답 메시지를 사용하는 HTTP 통신을 알아봤고, 메시지 구조를 알아봤습니다.
  • HTTP 모듈
    HTTP 통신 기능을 제공하는 HTTP 모듈을 알아봤습니다.
  • HTTP 서버
    HTTP 모듈 중 서버를 작성하는 클래스와 이벤트를 알아봤습니다.
  • HTTP 클라이언트
    HTTP 모듈 중 클라이언트를 작성하는 데 필요한 기능을 간단히 알아봤습니다.