안녕세계

[SK고용디딤돌] Node.js (2/10) - 5주차 본문

[SK고용디딤돌] Node.js (2/10) - 5주차

Junhong Kim 2016. 8. 5. 17:55
728x90
반응형

[NPM - MIME]

npm install mime





[ 예제(1) BasicWebServer ]

/**
* Created by Tacademy on 2016-08-05.
*/
var http = require('http');
var path = require('path');
var fs = require('fs');
var url = require('url');
var querystring = require('querystring');
var mime = require('mime');
var port = parseInt(process.argv[2]) || 8888;

http.createServer(function(request, response) {
var pathname = url.parse(request.url).pathname; // /images/1.jpg
var filename = path.basename(pathname) === 'img' ? '' : path.basename(pathname); // 1.jpg , img일경우 imagepath /img 가 또 붙으므로 공백처리
var imagedir = 'img';
// __dirname : C:\Didimdol\WebstormProjects\Node.js\BasicWebServer
// imagepath : C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\img\1.jpg
var imagepath = path.join(__dirname, imagedir, filename);

fs.stat(imagepath, function(err,stats) {
var mimeType = mime.lookup('.html'); // default 지정 -> text/html
if (err) {
// 404 (없는 페이지)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Not Found!!!</h1>"); // write + end를 합쳐서 써도 됨
return;
} else {
if (stats.isDirectory()) {
// 403 (금지)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Forbidden!!!</h1>"); // write + end를 합쳐서 써도 됨
} else if (stats.isFile()){
// 200 (정상)
mimeType = mime.lookup(filename); // image/jpeg , mime type 다시 지정
response.writeHead(200, {'Content-Type' : mimeType})
var is = fs.createReadStream(imagepath); // (1) 읽기 스트림을 만들어서.
is.pipe(response); // (2) 읽은걸 바로쓴다. (쓰기 스트림이 필요 없음)
} else {
// 500 (내부 서버 에러)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Internal Server Error!!!</h1>"); // write + end를 합쳐서 써도 됨
}
}
});
// C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\ __dirname에 들어 있다.
// , __dirname\img\1.jpg 가 된다
// C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\img\1.jpg
})
.listen(port, function() {
console.log("Server running.. at", port);
});


< 정적 자원에 대한 서비스코드 >

정적자원 :html, 이미지, 동영상 등 파일로 존재하는 자원들

우린 정적자원을 path를 이용해서 스티름을 연결해서 보내준다.

정적자원에 최적화된 서버는 웹서버.

아파치,엔진엑스 같은 경우 정적자원에 최적화된 서버다.

동적자원 서비스는 nodejs나 톰캣이 최적화.


특정 URL /cak?op=add&arg1=1&arg2=2


[ 예제(2) BasicWebServer ]

/**
* Created by Tacademy on 2016-08-05.
*/
var http = require('http');
var path = require('path');
var fs = require('fs');
var url = require('url');
var querystring = require('querystring');
var mime = require('mime');
var port = parseInt(process.argv[2]) || 8888;

http.createServer(function(request, response) {
var mimeType = mime.lookup('.html'); // default 지정 -> text/html
var urlObj = url.parse(request.url); // url 객체 반환
var pathname = urlObj.pathname; // /images/1.jpg
if (pathname.match(/\/images\/*/gi)) { // 정규 표현식 쓰기위해서 /.../gi 안에 패턴을 쓴다 ( /gi 대소문자 구분 안함, /g 대소문자 구분)
var filename = path.basename(pathname) === 'img' ? '' : path.basename(pathname); // 1.jpg , img일경우 imagepath /img 가 또 붙으므로 공백처리
var imagedir = 'img';
// __dirname : C:\Didimdol\WebstormProjects\Node.js\BasicWebServer
// imagepath : C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\img\1.jpg
var imagepath = path.join(__dirname, imagedir, filename);

fs.stat(imagepath, function(err,stats) {
if (err) {
// 404 (없는 페이지)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Not Found!!!</h1>"); // write + end를 합쳐서 써도 됨
return;
} else {
if (stats.isDirectory()) {
// 403 (금지)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Forbidden!!!</h1>"); // write + end를 합쳐서 써도 됨
} else if (stats.isFile()){
// 200 (정상)
mimeType = mime.lookup(filename); // image/jpeg , mime type 다시 지정
response.writeHead(200, {'Content-Type' : mimeType})
var is = fs.createReadStream(imagepath); // (1) 읽기 스트림을 만들어서.
is.pipe(response); // (2) 읽은걸 바로쓴다. (쓰기 스트림이 필요 없음)
} else {
// 500 (내부 서버 에러)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Internal Server Error!!!</h1>"); // write + end를 합쳐서 써도 됨
}
}
});
}
else if(pathname.match(/\/calc\?*/gi)) { // 정규 표현식 쓰기위해서 /.../gi 안에 패턴을 쓴다 ( /gi 대소문자 구분 안함, /g 대소문자 구분)
var queryStringObj = querystring.parse(urlObj.query); // 쿼리스트링 객체 반환 { op: 'add', arg1: '1', arg2: '2' }
var arg1 = parseInt(queryStringObj["arg1"]) || 0; // NaN 값 나올 수 있으므로 default 지정
var arg2 = parseInt(queryStringObj["arg2"]) || 0;
var op = queryStringObj["op"];
if(op === "add")
var result = add(arg1, arg2);

response.writeHead(200, {'Content-Type': mimeType});
response.end('<h1>' + result + '</h1>');
}
// C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\ __dirname에 들어 있다.
// , __dirname\img\1.jpg 가 된다
// C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\img\1.jpg
}).listen(port, function() {
console.log("Server running.. at", port);
});

function add(x, y) {
return x + y;
}



[ 예제(3) 모듈 만들어서 사용 ]

/**
* Created by Tacademy on 2016-08-05.
*/
var http = require('http');
var path = require('path');
var fs = require('fs');
var url = require('url');
var querystring = require('querystring');
var mime = require('mime');
var port = parseInt(process.argv[2]) || 8888;
var calc = require('./calc');

http.createServer(function(request, response) {
var mimeType = mime.lookup('.html'); // default 지정 -> text/html
var urlObj = url.parse(request.url); // url 객체 반환
var pathname = urlObj.pathname; // /images/1.jpg
if (pathname.match(/\/images\/*/gi)) { // 정규 표현식 쓰기위해서 /.../gi 안에 패턴을 쓴다 ( /gi 대소문자 구분 안함, /g 대소문자 구분)
var filename = path.basename(pathname) === 'img' ? '' : path.basename(pathname); // 1.jpg , img일경우 imagepath /img 가 또 붙으므로 공백처리
var imagedir = 'img';
// __dirname : C:\Didimdol\WebstormProjects\Node.js\BasicWebServer
// imagepath : C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\img\1.jpg
var imagepath = path.join(__dirname, imagedir, filename);

fs.stat(imagepath, function(err,stats) {
if (err) {
// 404 (없는 페이지)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Not Found!!!</h1>"); // write + end를 합쳐서 써도 됨
return;
} else {
if (stats.isDirectory()) {
// 403 (금지)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Forbidden!!!</h1>"); // write + end를 합쳐서 써도 됨
} else if (stats.isFile()){
// 200 (정상)
mimeType = mime.lookup(filename); // image/jpeg , mime type 다시 지정
response.writeHead(200, {'Content-Type' : mimeType})
var is = fs.createReadStream(imagepath); // (1) 읽기 스트림을 만들어서.
is.pipe(response); // (2) 읽은걸 바로쓴다. (쓰기 스트림이 필요 없음)
} else {
// 500 (내부 서버 에러)
response.writeHead(404, {'Content-Type' : mimeType});
response.end("<h1>Internal Server Error!!!</h1>"); // write + end를 합쳐서 써도 됨
}
}
});
}
else if(pathname.match(/\/calc\?*/gi)) { // 정규 표현식 쓰기위해서 /.../gi 안에 패턴을 쓴다 ( /gi 대소문자 구분 안함, /g 대소문자 구분)
var queryStringObj = querystring.parse(urlObj.query); // 쿼리스트링 객체 반환 { op: 'add', arg1: '1', arg2: '2' }

var arg1 = parseInt(queryStringObj["arg1"]) || 0; // NaN 값 나올 수 있으므로 default 지정
var arg2 = parseInt(queryStringObj["arg2"]) || 0;
var op = queryStringObj["op"];
var result = calc[op](arg1, arg2);

response.writeHead(200, {'Content-Type': mimeType});
response.end('<h1>' + result + '</h1>');
}
// C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\ __dirname에 들어 있다.
// , __dirname\img\1.jpg 가 된다
// C:\Didimdol\WebstormProjects\Node.js\BasicWebServer\img\1.jpg
}).listen(port, function() {
console.log("Server running.. at", port);
});

/**
* Created by Tacademy on 2016-08-05.
*/
function add(x, y) {
return x + y;
}

function subtract(x, y) {
return x - y;
}

function multiply(x, y) {
return x * y;
}

function divide(x, y) {
return x / y;
}

module.exports.add = add;
module.exports.subtract = subtract;
module.exports.multiply = multiply;
module.exports.divide = divide;


1. 클라이언트 요청 분석 http, url, path, querystring

1-1) URL 파싱

1-2) 경로 판별

1-2-1) /image

1-2-1-1) 파일이름 찾기

특정 디렉토리에서 파일 존재여부 검사

fs모듈을 이용해서 파일의 존재 여부 검사

존재하면 서비스, (200) 존재하지 않으면 에러처리(404), 디렉토리일경우(403)

일반 파일일 경우 읽기 스트림과 연결한 뒤 파이프 객체를 통해서 응답객체에 연결

헤더 컨텐트 타입을 정확하게 지정

1-2-1) /calc




[ 기본 서버 선생님 주석 ]

// http 서비스를 위한 http 기본모듈 로딩
var http = require('http');
// 경로 조작을 위한 path 기본모듈 로딩
var path = require('path');
// 파일의 존재 여부를 검사하고, 스트림 조작을 위한 fs 기본모듈 로딩
var fs = require('fs');
// http 요청 메시지 분석을 위한 url 기본모듈 로딩
var url = require('url');
// 쿼리스트링 분석을 위한 querystring 기본모듈 로딩
var querystring = require('querystring');
// MIME 타입 정보 생성을 위한 mime 확장모듈 로딩 (확장모듈이므로 npm을 이용한 설치 필요)
var mime = require('mime');
// 계산 기능을 가진 사용자 정의 확장 모듈을 경로를 이용해 로딩
var calc = require('./calc');

// 명령 프롬프트에서 전달 받은 인자를 포트 번호로 사용
// 값이 전달되지 않거나 숫자가 아닌 값이 전달되면 기본 포트로 8888을 사용
var port = parseInt(process.argv[2]) || 8888;

// http 서비스 객체를 생성
// request 이벤트에 대한 리스너 함수를 인자로 전달
// request 이벤트가 발생하는 리스너 함수에 IncomingMessage 객체와 ServerResponse 객체가 전달됨
http.createServer(function(req, res) {
// 응답을 위한 기본 MIME 타입을 정의
var mimeType = mime.lookup('.html');
// 요청 객체의 url 정보를 분석해 Url 객체 생성
var urlObj = url.parse(req.url);
// Url 객체에서 경로 정보 추출
var pathname = urlObj.pathname;
// 경로가 /images/로 시작 할 경우의 처리 로직 구현
if (pathname.match(/\/images\/*/gi)) {
var filename = path.basename(pathname) === 'img' ? '' : path.basename(pathname);
var imagedirname = 'img';
var imagepath = path.join(__dirname, imagedirname, filename);

// 실제 파일시스템에 파일이 존재하는지 검사
fs.stat(imagepath, function (err, stats) {

// 파일이 존재하지 않으면 404 오류 처리
if (err) {
res.writeHead(404, {'Content-Type': mimeType});
res.end("<h1>Not Found!!!</h1>");
return;
}

// 파일이 존재할 경우 디렉토리 파일인지 검사
// 디렉토리 파일일 경우 403 오류 처리
if (stats.isDirectory()) {
res.writeHead(403, {'Content-Type': mimeType});
res.end("<h1>Forbidden!!!</h1>");
// 일반 파일일 경우 MIME 정보를 파일에 맞게 변경
// 파일에 대한 읽기스트림을 생성하고 응답객체와 연결(pipe)
} else if (stats.isFile()) {
mimeType = mime.lookup(filename);
res.writeHead(200, {'Content-Type': mimeType});
var is = fs.createReadStream(imagepath);
is.pipe(res);
} else {
res.writeHead(500, {'Content-Type': mimeType});
res.end("<h1>Internal Server Error!!!</h1>");
}
});
}
// 경로가 /calc?로 시작 할 경우의 처리 로직 구현
else if (pathname.match(/\/calc\?*/gi)) {
// Url 객체의 query 정보를 분석해 쿼리스트링 객체 생성
var querystringObj = querystring.parse(urlObj.query);
// 쿼리스트링 객체에서 클라이언트가 전달한 값을 추출
var arg1 = parseInt(querystringObj["arg1"]) || 0;
var arg2 = parseInt(querystringObj["arg2"]) || 0;
var op = querystringObj["op"];
var result = calc[op](arg1, arg2);

// 200 OK 응답 처리
res.writeHead(200, {'Content-Type': mimeType});
res.end('<h1>' + result + '</h1>');
}

}).listen(port, function() {
console.log("Server running... at ", port);
});


[ 예제(4) 우리들이 만든 서버! ]

배열은 같은 키값으로 여러개 

/**
* Created by Tacademy on 2016-08-05.
*/
// http 서비스를 위한 http 기본모듈 로딩
var http = require('http');
// 경로 조작을 위한 path 기본모듈 로딩
var path = require('path');
// 파일의 존재 여부를 검사하고, 스트림 조작을 위한 fs 기본모듈 로딩
var fs = require('fs');
// http 요청 메시지 분석을 위한 url 기본모듈 로딩
var url = require('url');
// 쿼리스트링 분석을 위한 querystring 기본모듈 로딩
var querystring = require('querystring');
// MIME 타입 정보 생성을 위한 mime 확장모듈 로딩 (확장모듈이므로 npm을 이용한 설치 필요)
var mime = require('mime');
// 계산 기능을 가진 사용자 정의 확장 모듈을 경로를 이용해 로딩
var calc = require('./calc');
// 명령 프롬프트에서 전달 받은 인자를 포트 번호로 사용
// 값이 전달되지 않거나 숫자가 아닌 값이 전달되면 기본 포트로 8888을 사용
var port = parseInt(process.argv[2]) || 8888;
// http 서비스 객체를 생성
// request 이벤트에 대한 리스너 함수를 인자로 전달
// request 이벤트가 발생하는 리스너 함수에 IncomingMessage 객체와 ServerResponse 객체가 전달됨
http.createServer(function(request, response) {
// 응답을 위한 기본 MIME 타입을 정의
var mimetype = mime.lookup('./html');
// 요청 객체의 url 정보를 분석해 Url 객체 생성
var urlObj = url.parse(request.url);
// Url 객체에서 경로 정보 추출
var pathname = urlObj.pathname;
// 경로가 /images/로 시작 할 경우의 처리 로직 구현
if(pathname.match(/\/images\/*/gi)) {
// 실제 파일시스템에 파일이 존재하는지 검사
var filename = path.basename(pathname) === 'img' ? '' : path.basename(pathname);
var imagedirname = 'img';
var imagepath = path.join(__dirname, imagedirname, filename);

fs.stat(imagepath, function(err, stats) {
// 파일이 존재하지 않으면 404 오류 처리
if(err) {
response.writeHead(403, {'Content-Type' : mimetype});
response.end('<h1>Not Found!!!</h1>');
return;
}
// 파일이 존재할 경우 디렉토리 파일인지 검사
// 디렉토리 파일일 경우 403 오류 처리
if(stats.isDirectory()) {
response.writeHead(403, {'Content-Type' : mimetype + '; charset=UTF-8'});
response.end('<h1>Forbidden!!!</h1>');
return;
}
// 일반 파일일 경우 MIME 정보를 파일에 맞게 변경
// 파일에 대한 읽기스트림을 생성하고 응답객체와 연결(pipe)
else if(stats.isFile()) {
mimetype = mime.lookup(filename);
response.writeHead(200, {'Content-Type' : mimetype});
var is = fs.createReadStream(imagepath);
is.pipe(response);
}
});
}
// 경로가 /calc?로 시작 할 경우의 처리 로직 구현
else if(pathname.match(/\/calc\?*/gi)) {
// Url 객체의 query 정보를 분석해 쿼리스트링 객체 생성
var querystringObj = querystring.parse(urlObj.query);
// 쿼리스트링 객체에서 클라이언트가 전달한 값을 추출
var op = querystringObj['op'];

// if /calc?op=sum...
if(request.url.match(/\/calc\?op=sum+/gi)) {
var argArray = querystringObj['arg']; // 같은 키값으로 여러개 보내준다.
for (var i = 0; i < argArray.length; i++) { // 숫자 처리
argArray[i] = parseInt(argArray[i]) || 0;
}
var result = calc[op](argArray);
response.end('<h1> sum : ' + result + '</h1>');
}
else if (request.url.match(/\/calc\?op=(add|subtract|multiply|divide)&arg1=\d+&arg2=\d+/gi)) { // +1개 이상
var arg1 = parseInt(querystringObj['arg1']) || 10;
var arg2 = parseInt(querystringObj['arg2']) || 10;
var result = calc[op](arg1, arg2);
// 200 OK 응답 처리
response.writeHead(200, {'Content-Type': mimetype});
response.end('<h1> etc op : ' + result + '</h1>');
}
}
else {
response.writeHead(404, {'Content-Type' : mimetype});
response.end('<h1>NO No</h1>');
}
}).listen(port, function() {
console.log("Server running.. at", port);
});











728x90
반응형
Comments