Odds and Ends
5장 Node.js 강의 정리 - 웹 서버 만들기 본문
[웹 서버 만들기]
1. 간단한 웹 서버 만들기
- http 모듈로 웹 서버를 시작, 노드에 기본으로 들어있는 http모듈로 웹 서버 객체 생성
- createServer() 메소드로 웹 서버 객체 만들고 listen() 메소드로 대기
* listen() 함수란? 서버 실행하여 대기시킴
* close() 함수란? 서버 종료시킴
var http = require('http'); // http 모듈 불러옴
var server = http.createServer(); // 웹서버객체 리턴
// 실제 웹서버, 동작 가능
var host = '자신 WIFI IP주소 넣기'; // 와이파이 변경 시 바꿔줘야함
var port = 3000;
server.listen(port, host, '50000', function(){
console.log('웹서버가 실행되었습니다 -> ' +host +':'+ port);
});
*요청, 응답
var http = require('http');
var server = http.createServer();
var host = '자신 WIFI IP주소 넣기';
var port = 3000;
server.listen(port,host,50000, function(){
console.log('웹서버 실행됨');
});
server.on('connection', function(socket){
console.log('클라이언트가 접속했습니다.');
});
server.on('request', function(req, res){
console.log('클라이언드 요청이 들어왔습니다.');
//console.dir(req);
res.writeHead(200, {"Content-Type":"text/html;charset=utf-8"});
res.write('<h1>웹서버로부터 받은 응답</h1>'); // 실제 웹페이지에 응답 보냄
res.end();
});
- 접속시 connection 이벤트 발생, 요청 받을 시 request이벤트 발생, write()메소드 등을 이용해 응답 전송
**파일을 서버에 읽고 보내기
- POST 방식으로 요청할 때는 request() 메소드 사용
2. 익스프레스로 웹 서버 만들기 - 미들웨어,라우터
var express = require('express');
var http = require('http');
var app = express(); //express 서버 객체
app.set('port',process.env.PORT || 3000); //속성 설정,process.env.PORT은 시스템 환경변수 설정 안되있을 시 3000
var server = http.createServer(app).listen(app.get('port'),function(){ //콜백함수, 웹서버 실행시 동작
console.log('익스프레스로 웹 서버를 실행함 : ' + app.get('port'));
});
Error: Cannot find module 'express' 오류 시 설치해야함
-> npm install express cmd창에 입력해 설치
* 미들웨어란?
: 미들웨어 함수는 req(요청) 객체, res(응답) 객체, 그리고 어플리케이션 요청-응답 사이클 도중 그 다음의 미들웨어 함수에 대한 액세스 권한을 갖는 함수이다.
간단하게 말하면 클라이언트에게 요청이 오고 그 요청을 보내기 위해 응답하려는 중간(미들)에 목적에 맞게 처리를 하는, 말하자면 거쳐가는 함수들이라고 보면 되겠다.
** 서버로 전송 방법 두가지
res.writeHead(200,{"Content-Type":"text/html;charset=utf8"});
res.end('<h1>서버에서 응답한 결과입니다. : '+req.user + '</h1>');
var person = {name:'소녀시대',age:20};
res.send(person);//객체 전송
- writeHead()와 end()로 보내는 법, send()를 이용한 법 두가지가 있다.(전자는 메소드를 많이 호출해야해서 send이용)
* writeHead()란?
: response 객체의 메소드에서 헤더 정보를 응답에 작성해서 내보내는 것. 첫번째 인자는 상태 코드를 지정하고 두번째인수에 헤더 정보를 연관 배열로 정리한 것이다. 여기에서는 {'Content-Type': 'text/plain'}값이 포함되어 있다. 이로 인해 Content-type이라는 헤더 정보에 'text/plain'의 값을 설정하고 있는 것을 알 수 있다. 이것은 응답으로 반송하는 콘텐츠의 종류를 나타내는 헤더 정보로, 이것으로 "이 콘텐츠는 표준 텍스트이다"라는 것이 클라이언트에 전달된다.
[관련 예제 코드]
//app3.js 파일 코드
var express = require('express');
var http = require('http');
var app = express(); // express 서버객체
app.set('port',process.env.PORT || 3000);
app.use(function(req, res, next){ // use는 미들웨어 등록
console.log('첫번째 미들웨어 호출됨.');
req.user = 'mike';
next(); // 이 미들웨어 떠남, 여러개의 미들웨어등록 사용시 이용
});
app.use(function(req,res,next){
console.log('두번째 미들웨어 호출됨');
res.writeHead(200,{"Content-Type":"text/html;charset=utf8"});
res.end('<h1>서버에서 응답한 결과입니다. : '+req.user + '</h1>');
});
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('익스프레스로 웹 서버를 실행함 ' + app.get('port'));
});
//app6.js 파일
var express = require('express');
var http = require('http');
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(function(req, res, next){
console.log('첫번째 미들웨어 호출됨');
var userAgent = req.header('User-Agent');
var paramName = req.query.name;
res.send('<h3>서버에서 응답 User-Agent -> '+userAgent+'</h3><h3>Param Name -> ' + paramName+'</h3>')
});
http.createServer(app).listen(app.get('port'), function(){
console.log('익스프레스에서 웹서버를 실행함' + app.get('port'));
});
3. 미들웨어 사용하기
1. static 미들 웨어 : 특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
//static 사용 코드, 특정 폴더 지정해 보안 기능
var express = require('express');
var http = require('http');
var static = require('serve-static');//1.static 불러오기
var path = require('path');
var app = express();
app.set('port', process.env.PORT || 3000);
app.use('/public',static(path.join(__dirname,'public'))); // 2.static함수로 실행, 폴더 지정, __dirname 실행 장소 의미
//app.use(static(path.join(__dirname,'public'))); // 2.static함수로 실행, 폴더 지정, __dirname 실행 장소 의미
app.use(function(req, res, next){
console.log('첫번째 미들웨어 호출됨');
var userAgent = req.header('User-Agent');
var paramName = req.query.name;
res.send('<h3>서버에서 응답 User-Agent -> '+userAgent+'</h3><h3>Param Name -> ' + paramName+'</h3>')
});
http.createServer(app).listen(app.get('port'), function(){
console.log('익스프레스에서 웹서버를 실행함' + app.get('port'));
});
지금부터는 실행할 시에 Postman을 이용한다.
* Postman 설치하기
- 이미지와 같이 입력하고 send 버튼을 입력하면 다음과 같은 결과를 확인할 수 있다.
//app7.js 파일
var express = require('express');
var http = require('http');
var static = require('serve-static');//1.static 불러오기
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
app.set('port', process.env.PORT || 3000);
app.use('/public',static(path.join(__dirname,'public'))); // 2.static함수로 실행, 폴더 지정, __dirname 실행 장소 의미
//app.use(static(path.join(__dirname,'public'))); // 2.static함수로 실행, 폴더 지정, __dirname 실행 장소 의미
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.use(function(req, res, next){
console.log('첫번째 미들웨어 호출됨');
var userAgent = req.header('User-Agent');
var paramId = req.body.id || req.query.id;
res.send('<h3>서버에서 응답 User-Agent -> '+userAgent+'</h3><h3>Param Name -> ' + paramId+'</h3>')
});
http.createServer(app).listen(app.get('port'), function(){
console.log('익스프레스에서 웹서버를 실행함' + app.get('port'));
});
: 미들웨어란 클라이언트의 요청이 들어왔을 때 중간에 가로채서 필요한 기능을 수행해주는 것이다.
4. 요청 라우팅하기
: express 로딩했을 때, Router() 함수 실행 가능. 여기서 요청 패스를 발생시키고 콜백함수 지정
* 요청 패스에 따라 라우팅 - 요청패스에 해당하는 함수를 실행
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인</title>
</head>
<body>
<h1>로그인</h1>
<br>
<form method="post" action="/process/login"> <!--action이 요청 패스가 된다.-->
<table>
<tr>
<td>
<label>아이디</label>
<td><input type="text" name="id"></td>
</td>
<td>
<label>비밀번호</label>
<td><input type="password" name="password"></td>
</td>
</tr>
</table>
<input type="submit" value = "전송" name="">
</form>
</body>
</html>
//app8.js 파일
//static 사용 코드, 특정 폴더 지정해 보안 기능
var express = require('express');
var http = require('http');
var static = require('serve-static');//1.static 불러오기
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
app.set('port', process.env.PORT || 3000);
app.use('/public',static(path.join(__dirname,'public'))); // 2.static함수로 실행, 폴더 지정, __dirname 실행 장소 의미
//app.use(static(path.join(__dirname,'public'))); // 2.static함수로 실행, 폴더 지정, __dirname 실행 장소 의미
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
var router = express.Router();
router.route('/process/login').post(function(req, res){ // 콜백함수
console.log('/process/login 라우팅 함수에서 받음');
var paramId = req.body.id || req.query.id;
var paramPassword = req.body.password || req.query.password;
res.writeHead(200, {"Content-Type":"text/html;charset=utf8"});
res.write("<h1>서버에서 로그인 응답</h1>");
res.write("<div><p>"+paramId+"</p></div>");
res.write("<div><p>"+paramPassword+"</p></div>");
res.end();
});
app.use('/', router); // 미들웨어로 등록
app.use(function(req, res, next){
console.log('첫번째 미들웨어 호출됨');
var userAgent = req.header('User-Agent');
var paramId = req.body.id || req.query.id;
res.send('<h3>서버에서 응답 User-Agent -> '+userAgent+'</h3><h3>Param Name -> ' + paramId+'</h3>')
});
http.createServer(app).listen(app.get('port'), function(){
console.log('익스프레스에서 웹서버를 실행함' + app.get('port'));
});
app.all('*', function(req, res){
res.status(404).send('<h1>요청하신 페이지는 없어요.</h1>');
});
[에러처리]
- 지정한 페이지 X, 아무거나 요청으로 입력하면 아래와 같은 결과가 뜨도록 하는 코드이다.
5. 쿠키와 세션 관리하기
: 쿠키는 클라이언트 웹 브라우저에 저장되는 정보, 세션은 웹 서버에 저장되는 정보
- cookie-parser 미들웨어 사용
- 로그인같은 것 만들 때 쿠키 사용
- 서버가 브라우저의 정보를 받아서 필요할 때 사용
https://www.npmjs.com/package/cookie-parser
- 구글에서 정보 검색하여 보는 법, 위의 링크에서 cookie-parser에 대한 정보 확인 가능
* express-session이란?
: express-session은 Node.js의 프레임워크인 Express를 사용할 때 세션을 관리할 수 있도록 하는 미들웨어
var expressSession = require('express-session');
app.use(expressSession({
secret:'my key',
resave:true,
saveUninitialized:true
}));
아래 세 옵션은 기본적으로 요구되는 옵션으로, 특별한 경우가 아니라면 기본적으로 세 옵션을 모두 사용하면 된다.
- sercret: 반드시 필요한 옵션으로 세션을 암호화하여 저장함
- resave: 세션이 변경되지 않아도 계속 저장됨(덮어쓰기) 기본 값은 true이지만 false로 사용할 것을 권장하고있음
- saveUninitialized: 세션을 초기값이 지정되지 않은 상태에서도 미리 만들어 저장함
6. 파일 업로드 기능 만들기
[multer 미들웨어를 이용한 파일 업로드]
- 파일 업로드시 POST 방식으로 요청해야하며 body-parser 미들웨어 사용 필요
- fs, cors 모듈도 사용
- ExpressExample폴더에 uploads 폴더를 만들고 이곳에 업로드 되는 파일을 넣는다.
[서버에서 파일 업로드하는 예제]
//app13.js 파일
var express = require('express')
, http = require('http')
, path = require('path');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
// 파일 업로드용 미들웨어 불러들이기
var multer = require('multer');
var fs = require('fs');
var app = express();
app.use('/public', express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieParser());
app.use(expressSession({
secret: 'my key',
resave: true,
saveUninitialized: true
}));
// multer 미들웨어 사용하기
var upload = multer({
dest: 'uploads',
putSingleFilesInArray: true,
limits: {
files: 10,
fileSize: 1024*1024
},
rename: function (fieldname, filename) {
return filename + Date.now();
},
onFileUploadStart: function (file) {
console.log('파일 업로드 시작 : ' + file.originalname);
},
onFileUploadComplete: function (file, req, res) {
console.log('파일 업로드 완료 : ' + file.fieldname + '-> ' + file.path);
},
onFileSizeLimit: function (file) {
console.log('파일 크기 제한 초과 : %s', file.originalname);
}
});
app.post('/process/login', function(req, res) {
console.log('/process/login 처리함.');
var paramId = req.param('id');
var paramPassword = req.param('password');
if (req.session.user) {
// 이미 로그인된 상태
console.log('이미 로그인되어 상품 페이지로 이동합니다.');
res.redirect('/public/product.html');
} else {
// 세션 저장
req.session.user = {
id: paramId,
name: '소녀시대',
authorized: true
};
}
res.writeHead('200', {'Content-Type': 'text/html;charset=utf8'});
res.write('<h1>로그인 성공</h1>');
res.write('<div><p>Param id : ' + paramId + '</p></div>');
res.write('<div><p>Param password : ' + paramPassword + '</p></div>');
res.write('<br><br><a href="/public/product.html">상품 페이지로 돌아가기</a>');
res.end();
});
app.get('/process/logout', function(req, res) {
console.log('/process/logout 호출됨.');
if (req.session.user) {
// 로그인된 상태
console.log('로그아웃합니다.');
req.session.destroy(function(err) {
if(err) throw err;
console.log('세션을 삭제하고 로그아웃되었습니다.');
res.redirect('/public/login2.html');
});
} else {
// 로그인 안 된 상태
console.log('아직 로그인되어 있지 않습니다.');
res.redirect('/public/login2.html');
}
});
app.get('/process/users/:id', function(req, res) {
// 토큰 정보를 가져옴
var paramId = req.params.id;
console.log('/process/users와 토큰 %s를 사용해 처리함.', paramId);
res.writeHead('200', {'Content-Type': 'text/html; charset=utf8'});
res.write('<h1>Express 서버에서 응답한 결과입니다.</h1>');
res.write('<div><p>Param id : ' + paramId + '</p></div>');
res.end();
});
// 쿠키 정보를 확인함
app.get('/process/showCookie', function(req, res) {
console.log('/process/showCookie 호출됨.');
res.send(req.cookies);
});
// 쿠키에 이름 정보를 설정함
app.get('/process/setUserCookie', function(req, res) {
console.log('/process/setUserCookie 호출됨.');
// 쿠키 설정
res.cookie('user', {
id: 'mike',
name: '소녀시대',
authorized: true
});
// redirect 로 응답
res.redirect('/process/showCookie');
});
app.get('/process/product', function(req, res) {
console.log('/process/product 호출됨.');
if (req.session.user) {
res.redirect('/public/product.html');
} else {
res.redirect('/public/login2.html');
}
})
app.post('/process/photo', upload.any('photo'), function(req, res) {
console.log('/process/photo 호출됨.');
var files = req.files;
// 현재의 파일 정보를 저장할 변수 선언
var originalname = '',
name = '',
mimetype = '',
size = 0;
if (Array.isArray(files)) { // 배열에 들어 있는 경우
console.log('배열에 들어 있는 파일 개수 : %d', files.length);
for (var index = 0; index < files.length; index++) {
originalname = files[index].originalname;
name = files[index].name;
mimetype = files[index].mimetype;
size = files[index].mimetype;
}
} else { // 배열에 들어가 있지 않은 경우 (현재 설정에서는 해당 없음)
console.log('파일 개수 : 1');
originalname = files[index].originalname;
name = files[index].name;
mimetype = files[index].mimetype;
size = files[index].size;
}
console.log('현재 파일 정보 : ' + originalname + ', ' + name + ', ' + mimetype + ', ' + size);
// 클라이언트에 응답 전송
res.writeHead('200', {'Content-Type': 'text/html;charset=utf8'});
res.write('<h3>파일 업로드 성공</h3>');
res.write('<hr/>');
res.write('<p>원본 파일 이름 : ' + originalname + ' -> 저장 파일 이름 : ' + name + '</p>');
res.write('<p>MIME TYPE : ' + mimetype + '</p>');
res.write('<p>파일 크기 : ' + size + '</p>');
res.end();
});
// 모든 router 처리 끝난 후 404 오류 페이지 처리
/*var errorHandler = expressErrorHandler({
static: {
'404': './public/404.html'
}
});*/
//app.use( expressErrorHandler.httpError(404));
//app.use( errorHandler );
app.all('*', function(req, res) {
res.send(404, '<h1>ERROR - 페이지를 찾을 수 없습니다.</h1>');
});
app.use(function(req, res, next) {
console.log('첫 번째 미들웨어에서 요청을 처리함.');
var userAgent = req.header('User-Agent');
var paramName = req.param('name');
res.writeHead('200', {'Content-Type': 'text/html;charset=utf8'});
res.write('<h1>Express 서버에서 응답한 결과입니다.</h1>');
res.write('<div><p>User-Agent : ' + userAgent + '</p></div>');
res.write('<div><p>Param name : ' + paramName + '</p></div>');
res.end();
});
http.createServer(app).listen(3000, function() {
console.log('Express 서버가 3000번 포트에서 시작됨.');
});
'Node.js 강의 정리' 카테고리의 다른 글
4장 Node.js 강의 정리 - Node의 기본 기능 (0) | 2021.07.02 |
---|---|
3장 Node.js 강의 정리 - Node.js의 자바스크립트 (0) | 2021.07.01 |
2장 Node.js 강의 정리 - 간단한 Node.js (0) | 2021.07.01 |
1장 Node.js 강의 정리 - Node.js 설치와 예제 (0) | 2021.06.29 |