2017년 10월 28일 토요일

Node.js 공부[5]

5챕터-웹 서버 만들기

노드에서는 웹 서버를 만들 때 필요한 http 모듈이 있는데, 이 모듈을 사용하면 HTTP프로토콜로 요청하는 내용과 응답을 모두 처리할 수 있다. 
그러나 쉽고 빠르게 웹 서버를 구성하려면 익스프레스(Express)를 사용하는 것이 좋다.

간단한 웹 서버 만들기

1
2
3
4
5
6
7
8
9
10
11
var http = require('http');
//웹서버 객체 만들기
var server = http.createServer();
//웹서버를 시작하여 192.168.0.5 IP와 3000번 포트에서 대기
var host = '192.168.0.2';
var port =3000;
server.listen(port, host, '50000',function(){
    console.log('웹 서버가 시작되었습니다. : %s, %d',host, port);
});
cs

웹브라우저에 요청할 때 어떤 이벤트가 발생하는 지 예제를 통해 볼 수 있다.
on()메소드는 이벤트를 처리할 때 가장 기본적인 메소드이다. 이 메소드로 connection, request, close 이벤트를 처리할 수 있는 콜백 함수를 각각 등록해 두면 상황에 맞게 호출된다.
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
var http = require('http');
var server = http.createServer();
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("<html>");
    res.write("<head>");
    res.write("<title>응답 페이지</title>");
    res.write("</head>");
    res.write("<body>");
    res.write("<h1>node 응답 페이지</h1>");
    res.write("</body>");
    res.write("</html>");
    //end는 응답을 모두 보냈다는 것을 의미하며 일반적으로는 end()가 호출될 때 클라이언트로 응답을 전송한다.
    res.end();  
    
});
//서버 종료 이벤트 처리
server.on('close'function(){
    console.log('서버가 종료 됩니다.');
});
cs

파일을 스트림으로 읽어 응답 보내기
파일은 스트림 객체로 읽어 들일 수 있고 웹서버의 응답 객체도 스트림으로 데이터를 전송할 수 있기 때문에 두 개의 스트림은 파이프로 서로 연결할 수 있다.
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
var http = require('http');
var fs = require('fs');
var server = http.createServer();
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 = 'aa.jpg';
    var infile = fs.createReadStream(filename, {flage: 'r'});
    
    //파이프로 연결하여 알아서 처리하도록  설정
    infile.pipe(res);
    
});
//서버 종료 이벤트 처리
server.on('close'function(){
    console.log('서버가 종료 됩니다.');
});
cs

서버에서 다른 웹사이트의 데이터를 가져와 응답하기
http모듈을 사용해 GET방식으로 다른 사이트에 데이터를 요청하는 코드이다.
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){
    //응답처리
    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

POST방식으로 데이터를 요청하는 코드이다.
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-unlencoded';
req.data = "q=actor";
opts.headers['Content-Lenth'= req.data.length;
req.on('error'function(err){
    console.log("오류발생:"+ err.message);
});
//요청 전송
req.write(req.data);
req.end();
cs

익스프레스로 웹 서버 만들기

http모듈만 사용해 웹 서버를 구성하면 많은 것들을 직접 만들어야 한다. 하지만 express모듈을 사용하면 간단한 코드로 웹서버의 기능을 구현할 수 있다. 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//여기서 express모듈은 웹 서버를 위해 만들어진 것이므로 http모듈 위에서 동작한다. 따라서 함께 불러줘야함.
var express = require('express')
, http = require('http');
//익스프레스 객체 생성
var app = express();
//기본 포트를 app객체에 속성으로 지정
app.set('port', process.env.PORT || 3000);
//Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
    console.log('익스프레스 서버를 시작했습니다: ' +app.get('port'));
});
cs
전 단계에서 http모듈로 웹 서버를 만들 때 createServer() 메소드로 웹 서버 객체를 만들고, listen() 메소드를 호출하여 클라이언트의 요청을 대기하도록 설정하였다. 익스프레스를 사용한 것도 같지만 차이점으로 createServer()메소드에 전달되는 파리미터로 app객체를 전달하는 것이 있다. app객체는 익스프레스 서버 객체이다.
이 객체의 주요 메소드로는
set(name, value) : 서버 설정을 위한 속성 지정, set()메소드로 지정한 속성은 get()으로 꺼내어 확인 할 수 있음
get(name) : 서버 설정을 위해 지정한 속성을 꺼내온다.
use([path,] function[, function...]) : 미들웨어 함수를 사용한다,
get([path,] function) : 특정 패스로 요청된 정보를 처리한다.


미들웨어로 클라이언트에 응답보내기
노드에서는 미들웨어를 사용하여 필요한 기능을 순차적으로 실행할 수 있다. 
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
var express = require('express')
, http = require('http')
var app = express();
app.use(function(req, res, next){
    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>Express 서버에서' +req.user+ '가응답한 결과입니다.</h1>');
});
http.createServer(app).listen(3000function(){
    console.log('Express 서버가 3000번 포트에서 시작됨');
})
cs
>>각각의 미들웨어 안에서 마지막에 next() 메소드를 호출하여 다음 미들웨어로 처리 결과를 넘겨준다. 

또한 익스프레스에는 send(), redirect() 등 응답객체 메소드가 있다.
1
2
3
4
5
6
7
8
9
10
app.use(function(req, res, next){
    //send()로 JSON데이터 전송하기
    res.send({name:'소녀시대', age:20});
});
app.use(function(req, res, next){
    //redirect()로 페이지 이동하기
    res.redirect('http://google.co.kr');
});
cs

익스프레스에서 요청 객체에 추가한 헤더와 파라미터 알아보기
클라이언트에서는 요청 파라미터를 함께 보낼 수 있다. 이때 GET방식으로 요청했다면 요청파라미터들은 요청 객체의 query 객체 안에 들어간다. 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var express = require('express')
, http = require('http')
var app = express();
app.use(function(req, res, next){
    console.log('첫 번째 미들웨어에서 요청을 처리함.');
    
    var userAgent = req.header('User-Agent');
    var paramName = req.query.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(3000function(){
    console.log('Express 서버가 3000번 포트에서 시작됨');
})
cs
요청 파라미터를 주소에 입력해주면 
http://localhost:3000/?name=mike
이러한 창이 뜬다. 

미들웨어 사용하기

지금까지 use()메소드로 설정하는 미들웨어 함수 안에 코드를 직접 넣어 클라이언트로 응답을 전달했다. 하지만 모든 기능을 직접 만들어야한다면 쉽지 않으므로, 익스프레스에는 미리 만들어 둔 여러 미들웨어를 제공한다.

static 미들웨어: 특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 만들어 줌
1
2
3
var static = require('serve-static');
...
app.use(static(path.join(__dirname, 'public')));

cs
이런식으로 지정해주면 public 폴더안의 파일들을  바로 접근할 수 있는 듯
public/index.html
ex) http://localhost:3000/index.html 와 같은 주소로 바로 접근 가능

body-parser 미들웨어: POST로 요청했을 때 요청 파라미터를 확인할 수 있음.
>>클라이언트가 POST방식으로 요청할 때 본문 영역에 들어있는 요청 파라미터들을 파싱하여 요청 객체의 body속성에 넣어준다.
public/login.html
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
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>로그인 테스트</title>
    </head>
    
<body>
    <h1>로그인</h1>
    <br>
    <form method="POST">
        <table>
            <tr>
                <td><label>아이디</label></td>
                <td><input type="text" name="id"></td>
            </tr>
            
            <tr>
                <td><label>비밀번호</label></td>
                <td><input type="password" name="password"></td>
            </tr>
        </table>
        <input type="submit" value="전송" />
    </form>
</body>
</html>
cs
app.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
//Express 기본 모듈
var express = require('express')
, http = require('http')
, path = require('path');
//Express 미들 웨어
var bodyParser = require('body-parser')
, static = require('serve-static');
//익스프레스 객체 생성
var app = express();
//기본 속성 설정
app.set('port', process.env.PORT || 3000);
//body-parser를 사용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({extended: false}));
//body-parser를 사용해 application.json 파싱
app.use(bodyParser.json());
app.use(static(path.join(__dirname, 'public')));
//미들웨어에서 파라미터 확인
app.use(function(req, res, next){
    console.log('첫 번째 미들웨어에서 요청을 처리함.');
    
    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>Express서버에서 응답한결과입니다. </h1>');
    res.write('<div><p>paramId : ' + paramId + '</p></div>');
    res.write('<div><p>Param Password: '+ paramPassword + '</p></div>');
    res.end();
});
http.createServer(app).listen(3000function(){
    console.log('Express 서버가 3000번 포트에서 시작됨');
})
cs
>>예제를 실행해 보면 login창에서 전송버튼을 누르면 입력한 파라미터들이 다음 창에서 표시된다. 

요청 라우팅하기

다른 요청이 들어왔을 때도 use()메소드로 설정한 미들웨어 함수가 항상 호출되기 때문에 요청 url이 무엇인지 일일이 확인해야 하는 번거로움이 생긴다. 이 문제를 해결하는 것이 라우터 미들웨어(router middleware)라고 한다.
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
//Express 기본 모듈
var express = require('express')
, http = require('http')
, path = require('path');
//Express 미들 웨어
var bodyParser = require('body-parser')
, static = require('serve-static');
//익스프레스 객체 생성
var app = express();
//기본 속성 설정
app.set('port', process.env.PORT || 3000);
//body-parser를 사용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({extended: false}));
//body-parser를 사용해 application.json 파싱
app.use(bodyParser.json());
app.use(static(path.join(__dirname, 'public')));
//라우터 객체 참조
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>Express서버에서 응답한결과입니다. </h1>');
    res.write('<div><p>paramId : ' + paramId + '</p></div>');
    res.write('<div><p>Param Password: '+ paramPassword + '</p></div>');
    res.write("<br><a href='/login2.html'>로그인 페이지로 돌아가기</a>")
    res.end();
})
// 라우터 객체를 app객체에 등록
app.use('/', router);
// 등록되지 않은 패스에 대해 페이지 오류 응답
app.all('*'function(req, res) {
    res.status(404).send('<h1>ERROR - 페이지를 찾을 수 없습니다.</h1>');
});
http.createServer(app).listen(3000function(){
    console.log('Express 서버가 3000번 포트에서 시작됨');
})
cs


오류를 처리할 수 있는 미들웨어도 있다.
epress-error-handler 미들웨어 이다. 
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
56
57
58
59
60
61
//Express 기본 모듈
var express = require('express')
, http = require('http')
, path = require('path');
//Express 미들 웨어
var bodyParser = require('body-parser')
, static = require('serve-static');
//오류 핸들러 사용
var expressErrorHandler = require('express-error-handler');
//익스프레스 객체 생성
var app = express();
//기본 속성 설정
app.set('port', process.env.PORT || 3000);
//body-parser를 사용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({extended: false}));
//body-parser를 사용해 application.json 파싱
app.use(bodyParser.json());
app.use(static(path.join(__dirname, 'public')));
//라우터 객체 참조
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>Express서버에서 응답한결과입니다. </h1>');
    res.write('<div><p>paramId : ' + paramId + '</p></div>');
    res.write('<div><p>Param Password: '+ paramPassword + '</p></div>');
    res.write("<br><a href='/login2.html'>로그인 페이지로 돌아가기</a>")
    res.end();
})
// 라우터 객체를 app객체에 등록
app.use('/', router);
// 404 에러 페이지 처리
var errorHandler = expressErrorHandler({
    static: {
      '404''./public/404.html'
    }
});
app.use( expressErrorHandler.httpError(404) );
app.use( errorHandler );
http.createServer(app).listen(3000function(){
    console.log('Express 서버가 3000번 포트에서 시작됨');
})
cs


토큰과 함께 요청한 정보 처리하기
/get()메소드를 호출하면서 동시에 /process/users/:id 패스를 처리하는 예제이다. http://localhost:3000/process/users/2 주소를 입력하면 users 뒤에있는 2가 아이디로 접근한다.
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
// Express 기본 모듈 불러오기
var express = require('express')
  , http = require('http')
  , path = require('path');
// Express의 미들웨어 불러오기
var bodyParser = require('body-parser')
  , static = require('serve-static');
// 익스프레스 객체 생성
var app = express();
// 기본 속성 설정
app.set('port', process.env.PORT || 3000);
// body-parser를 이용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({ extended: false }))
// body-parser를 이용해 application/json 파싱
app.use(bodyParser.json())
app.use('/public', static(path.join(__dirname, 'public')));
// 라우터 사용하여 라우팅 함수 등록
var router = express.Router();
router.route('/process/users/:id').get(function(req, res) {
    console.log('/process/users/:id 처리함.');
    // URL 파라미터 확인
    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.use('/', router);
// 등록되지 않은 패스에 대해 페이지 오류 응답
app.all('*'function(req, res) {
    res.status(404).send('<h1>ERROR - 페이지를 찾을 수 없습니다.</h1>');
});
// Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});
cs

쿠키와 세션 관리하기

사용자가 로그인 상태인지 아닌지 확인하고 싶을 때에는 쿠키나 세션을 사용한다.  쿠키는 클라이언트 웹 브라우저에 저장되는 정보이며, 세션은 웹 서버에 저장되는 정보이다.
익스프레스에서는 cookie-parser 미들웨어를 사용하면 쿠키를 설정하거나 확인할 수 있다.
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
56
57
58
59
60
61
62
63
// Express 기본 모듈 불러오기
var express = require('express')
  , http = require('http')
  , path = require('path');
// Express의 미들웨어 불러오기
var bodyParser = require('body-parser')
  , static = require('serve-static');
var cookieParser = require('cookie-parser')
// 익스프레스 객체 생성
var app = express();
// 기본 속성 설정
app.set('port', process.env.PORT || 3000);
// body-parser를 이용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({ extended: false }))
// body-parser를 이용해 application/json 파싱
app.use(bodyParser.json())
app.use('/public', static(path.join(__dirname, 'public')));
// 라우터 사용하여 라우팅 함수 등록
var router = express.Router();
router.route('/process/showCookie').get(function(req, res) {
    console.log('/process/showCookie 호출됨');
    
    res.send(req.cookies);
});
router.route('/process/setUserCookie').get(function(req, res) {
    console.log('/process/setUserCookie 호출됨');
    
    //쿠키 설정
    res.cookie('user', {
        id: 'mike',
        name'소녀시대',
        authorized: true
    });
    
    //redirect로 응답
    res.redirect('/process/showCookie');
});
app.use('/', router);
// 등록되지 않은 패스에 대해 페이지 오류 응답
app.all('*'function(req, res) {
    res.status(404).send('<h1>ERROR - 페이지를 찾을 수 없습니다.</h1>');
});
// Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});
cs
크롬의 개발자 도구에서 어플리케시연 - cookies 항목을 클릭하면 쿠기 정보가 보인다.

이번엔 세션이다. 세션도 상태정보를 저장하는 역할을 하지만 쿠키와 달리 서버쪽에 저장된다. 대표적인 예로는 로그인했을때 저장되는 세션을 들 수 있다.
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Express 기본 모듈 불러오기
var express = require('express')
  , http = require('http')
  , path = require('path');
// Express의 미들웨어 불러오기
var bodyParser = require('body-parser')
  , cookieParser = require('cookie-parser')
  , static = require('serve-static')
  , errorHandler = require('errorhandler');
// 에러 핸들러 모듈 사용
var expressErrorHandler = require('express-error-handler');
// Session 미들웨어 불러오기
var expressSession = require('express-session');
// 익스프레스 객체 생성
var app = express();
// 기본 속성 설정
app.set('port', process.env.PORT || 3000);
// body-parser를 이용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({ extended: false }))
// body-parser를 이용해 application/json 파싱
app.use(bodyParser.json())
app.use('/public', static(path.join(__dirname, 'public')));
// cookie-parser 설정
app.use(cookieParser());
// 세션 설정
app.use(expressSession({
    secret:'my key',
    resave:true,
    saveUninitialized:true
}));
// 라우터 사용하여 라우팅 함수 등록
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;
    
    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='/process/product'>상품 페이지로 이동하기</a>");
        res.end();
    }
});
// 로그아웃 라우팅 함수 - 로그아웃 후 세션 삭제함
router.route('/process/logout').get(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');
    }
});
// 상품정보 라우팅 함수
router.route('/process/product').get(function(req, res) {
    console.log('/process/product 호출됨.');
    
    if (req.session.user) {
        res.redirect('/public/product.html');
    } else {
        res.redirect('/public/login2.html');
    }
});
app.use('/', router);
// 404 에러 페이지 처리
var errorHandler = expressErrorHandler({
    static: {
      '404': './public/404.html'
    }
});
app.use( expressErrorHandler.httpError(404) );
app.use( errorHandler );
// Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});
cs
세션이 만들어지면 connect.sid 쿠기가 브라우저에 저장된다.

파일 업로드 기능 만들기

파일을 업로드할 때는 멀티파트(multipart)포맷으로 된 파일 업로드 기능을 사용한다.

여기에선 multer 미들웨어로 파일을 업로드하는 방법을 알아본다. 
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Express 기본 모듈 불러오기
var express = require('express')
  , http = require('http')
  , path = require('path');
// Express의 미들웨어 불러오기
var bodyParser = require('body-parser')
  , cookieParser = require('cookie-parser')
  , static = require('serve-static')
  , errorHandler = require('errorhandler');
// 에러 핸들러 모듈 사용
var expressErrorHandler = require('express-error-handler');
// Session 미들웨어 불러오기
var expressSession = require('express-session');
// 파일 업로드용 미들웨어
var multer = require('multer');
var fs = require('fs');
// 클라이언트에서 ajax로 요청했을 때 CORS(다중 서버 접속) 지원
var cors = require('cors');
// 익스프레스 객체 생성
var app = express();
// 기본 속성 설정
app.set('port', process.env.PORT || 3000);
// body-parser를 이용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({ extended: false }))
// body-parser를 이용해 application/json 파싱
app.use(bodyParser.json())
// public, uploads 폴더 오픈
app.use('/public', static(path.join(__dirname, 'public')));
app.use('/uploads', static(path.join(__dirname, 'uploads')));
        
// cookie-parser 설정
app.use(cookieParser());
// 세션 설정
app.use(expressSession({
    secret:'my key',
    resave:true,
    saveUninitialized:true
}));
// 클라이언트에서 ajax로 요청했을 때 CORS(다중 서버 접속) 지원
app.use(cors());
//multer 미들웨어 사용: 미들 웨어 사용 순서 중요 body-parser > multer > router
// 파일제한: 10개, 1G
var storage = multer.diskStorage({
    //destination: 업로드한 파일이 저장될 폴더를 지정
    destination: function(req, file, callback){
        callback(null'uploads')    
    },
    filename: function(rqe, file, callback){
        callback(null, file.originalname + Date.now());
    }
});
var upload = multer({
    storage: storage,
    limits: {
        files:10,
        fileSize: 1024 * 1024 * 1024
    }
});
// 라우터 사용하여 라우팅 함수 등록
var router = express.Router();
router.route('/process/photo').post(upload.array('photo',1),function(req,res){
    console.log('photo 호출됨');
    
    try{
        var files = req.files;
        
        console.dir('#=== 업로드된 첫번째 파일 정보=====#')
        console.dir(req.files[0]);
        console.dir('#======#')
        
        //현재의 파일 정보를 저장할 변수 선언
        var originalname = '',
            filename = '',
            mimetype ='',
            size =0;
        
            if(Array.isArray(files)){ //배열에 들어가 있는 경우(설정에서 1개의 파일도 배열에 넣게 했음)
                console.log("배열에 들어있는 파일 갯수 :%d", files.length);
                
                for(var index =0; index < files.length; index++){
                    originalname = files[index].originalname;
                    filename = files[index].filename;
                    mimetype = files[index].mimetype;
                    size = files[index].size;
                    
                }
            }else//배열에 들어가 있지 않는 경우(현재 설정에서는 해당 없음)
                console.log("파일 갯수: 1");
                
                originalname = files[index].originalname;
                filename = files[index].filename;
                mimetype = files[index].mimetype;
                size = files[index].size;
            }
        
        console.log('현재 파일 정보:'+originalname+','+ filename+','+mimetype+',' +size);
        
        //클라이언트에 응답 전송
        res.writeHead('200', {'Content-Type':'text/html;charset=utf8'});
        res.write('<h1>파일 업로드  성공</h1>');
        res.write('<hr/>');
        res.write('<p>원본 파일이름:' +originalname+'-> 저장 파일명:'+filename +'</p>');
        res.write('<p>MIME TYPE:' +mimetype+ '</p>');
        res.write('<p>파일 크기:' +size+ '</p>');
        res.end();
        
    }catch(err){
        console.dir(err.stack);
    }
});
app.use('/', router);
// 404 에러 페이지 처리
var errorHandler = expressErrorHandler({
    static: {
      '404''./public/404.html'
    }
});
app.use( expressErrorHandler.httpError(404) );
app.use( errorHandler );
// Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

cs
파일을 업로드했을 때 업로드한 파일의 정보는 배열 객체로 저장된다. 여기서는 for문으로 배열 객체의 요소들인 파일 이름이나 크기를 하나씩 확인한다. 

업로드버튼을 눌러 웹서버로 요청하면 업로드 기능을 담당하는 multer 미들웨어를 거쳐 라우팅 함수쪽으로 전달된다. 요기선 파일이름을 변경하여 uploads폴도어 저장된다. 이 과정에서 확인된 정보는 응답으로 보내저 업로드 결과를 볼 수 있다. 

댓글 없음:

댓글 쓰기