노드JS [Express]

[Node js express 배우기] 노드 JS Express 정리 하면서 배우자.

훈츠 2020. 6. 16. 17:50
반응형

Node js express 정리하면서 배워봅시다. 

 

 

 

 

 

안녕하세요. 훈츠입니다. 노드JS Express 정리해 봅니다. 


글 목록

  • 노드 JS express 간단 소개 및 설치방법 [ 윈도우, 리눅스 ]
  • 노드 JS express 기본 시작 페이지 [ 원리 파악 ]
  • 시작 페이지 전환 
  • Node js VS Express 컨버터시 차이점 
  • CRUD 샘플 구현 Node JS -> Node JS Express 
  • Express 미들웨어 소개 및 만들어서 사용해보기 
  • 에러 처리 
  • 정적 파일 처리 
  • Express 라우터 
  • 프로젝트 보안 처리 (헬멧 적용)
  • 프로젝트 압축 처리 (콤프레션 적용)
  • Express Generator
  • pug 라이브러리 for HTML Coding 

노드 JS express 간단 소개 및 설치방법 [ 윈도우 ]

노드 JS Express 는 노드 JS 의 불편함점을 개선한 프레임 워크 입니다. 노드 JS를 경험해보고 익스프레스를 사용해 보니 Node JS 보다 뭔가 손쉽게 구현 할수 있는게 많고 무엇보다 이후에 나올 익스프레스 미들웨어들이 이러한 부분들을 도움을 주는것 같습니다. 저도 많은 라이브러리들을 경험해본것은 아닌데, 단편적으로 생각나는 부분은, 화면을 변경시킬때 Url 에 쿼리 스트링에 보안을 위해서 path.parse('경로').base 로 세탁을 해줘야 하는 부분을 $:id 로 해결 한다든지 말입니다. 

 

설치법

$ npm install express --save

 

공식사이트 : https://expressjs.com/


노드 JS express 기본 시작 페이지 [ 원리 파악 ]

다음 코드를 입력 하고, 파일이 있는 해당경로에서 node temp.js 를 입력 하시면 됩니다. 

 

1
2
3
4
5
6
7
8
9
10
11
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
const express = require('express')
const app = express()
const port = process.env.PORT || 3000
 
app.get('/', (req, res) => res.send('Hello World!'))
 
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
 
 
cs

위와 같이 결과 노드js express 서버가 인사를 합니다. 

 


페이지 전환 ( req.params.pageId )

 

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
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
const express = require('express')
const app = express()
const port = 3000
 
//MAIN Page 
app.get('/', function (request, response) {
    var input_pageId = ['page1','page2','page3'];
    var html =       
        `<a href="/create/${input_pageId[0]}">page1</a><br>
         <a href="/create/${input_pageId[1]}">page2</a><br>
         <a href="/create/${input_pageId[2]}">page3</a><br>`
        response.send(html);
});
 
//WEB PAGE Content load by pageId
app.get('/create/:pageId', function (request, response) {
    var filteredId = request.params.pageId
    var html = 
        `
        <h1>${filteredId}<h1>
        <a href="/">home</a>
        `
    response.send(html);
});
 
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
 
 
cs

위 코드를 보시면 Node JS 와 가장 큰 차이점은 모듈화가 손쉽다는 점입니다. Node.JS 에서 입력 들어오는 쿼리스트링 값을 가지고 화면 전환을 했지만 Express 에서는 req.page.pageId 를 가지고 합니다. 

 

시작화면

page1 이동 화면 

 

 


Node js VS Express 컨버터시 차이점

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
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//Node js 는 createServer를 사용하고 그안에서 처리 
var http = require('http');
var url = require('url');
var app = http.createServer(function(request,response){
    var _url = request.url;
    var queryData = url.parse(_url,true).query;
    var pathname = url.parse(_url,true).pathname;
    if(pathname === '/'){..코드생략 }
    }else if(pathname === '/create'){
    }else if(pathname === '/create_process'){..코드생략 }
    }else if(pathname === '/update'){..코드생략 }
    }else if(pathname === '/update_process'){..코드생략 }
     else if(pathname === '/delete_process'){..코드생략 }
     else { response.writeHead(404); response.end('not found') } //에러처리
 
//Express 는 express 모듈을 불러오고 app.함수를 가지고처리 
const express = require('express')        
const app = express()
app.get('/', function (request, response) {..코드생략 }
app.get('/page/:pageId', function(request, response){..코드생략 }
app.post('/delete_process', function (request, response){..코드생략 }
app.get('/create', function(request, response){..코드생략 }
app.post('/create_process', function (request, response) {..코드생략 }
app.get('/update/:pageId', function(request, response){..코드생략 }
app.post('/update_process', function(request, response){..코드생략 }
 
 
cs

모듈을 불러오는 부분에서 위와같이 차이가 있고 전체적인 코드를 만드는 구조가 다릅니다. 아래에서 Express 라우터를통해서 각 모듈에 대해 모듈화가 손쉽고 여러가지 미들웨어를 설정하여 좀더 구조적이고 안정적인 프로그램을 만들수 있습니다. 

 


CRUD 샘플 구현 Node JS -> Node JS Express 

노드 JS Express 로 CRUD 를 구현하더라도, HTTP 의 통신규약은 똑같이 적용 되기 때문에 특별히 다른점은 없습니다. 다만 모듈화를 하기 때문에 프로그램 구조가 다르고, 미들웨어의 도움을 받아 조금더 손쉽고 안정적으로 구현이 가능했습니다. 사실 위의 두가지가 익스프레스의 가장 중요한 두가지라고 하네요. 

 

1. 라우터 

2. 미들웨어

 

먼저 프로그램의 구조는 다음과 같습니다.

main.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
41
42
43
44
45
46
47
48
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
// 익스프레스 
const express = require('express');
// 미들웨어 
var bodyParser = require('body-parser');
var helmet = require('helmet')
var compression = require('compression');
// 프로젝트 라우터
var topicRouter = require('./routes/router')
var indexRouter = require('./routes/index')
 
var fs = require('fs');
const port = 3000
const app = express();
 
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false })) //바디파서를 위한 미들웨어
app.use(compression()); //압축을 위한 솔루션
app.use(helmet()); //보안을 위한 솔루션 
 
//현 프로젝트 미들웨어 만들어 사용하기(폴더 이름값을 읽는 함수를 미들웨어로 생성해서 사용)
app.get('*',function(req,res, next){
    fs.readdir('./data', function(err, filelist){
        req.filelist = filelist;
        next();
    });
});
//public 폴더를 정적폴더로 지정 
app.use(express.static('public'));
app.use('/topic', topicRouter);
app.use('/', indexRouter);
 
 
//ERROR Handlers default
app.use(function(req, res, next) {    
    res.status(404).send('Sorry cant find that!');
});
 
//SERVER ERROR(서보 오류발생)
app.use(function (err, req, res, next) {
    console.error(err.stack)
    res.status(500).send('Something broke!')
})
 
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
 
 
cs

코드 리뷰 

 1. 익스프레스 밑 프로젝트에 필요한 미들웨어를 가지고 옵니다. ( 이정도는 기본설치 필요 )

   bodyParser : body를 분석하기 위한 미들웨어, 노드 js 에서는 request.on('data' ,function( ) 콜백으로 오는 body 값을

   더하다가 ('end' 처리 정도 해줬는데 통신이 끊겼을때라든지 그런 경우에 대한 대책도 보안

   이 되는것 같습니다. 지금은 코드의 량이 줄었다? 정도로 bodyParser() 미들웨어를 이해 하고 있습니다. 

   helmet : 보안을 위한 미들웨어 

   compression : 프로젝트 압축을 위한 미들웨어 

 

2. 프로젝트 라우터 설정 

   홈 역활을 하는 index 라우터와 각 CRUD 기능을 담당하고 있는 라우터를 나눴습니다. 이후 다양한 라우

   터를 설계하게 된다면 적절한 이름과 배치를 하면 됩니다. 

 

3. 노드 익스프레스 서버 세팅 

   포트 번호와 익스프레스를 돌릴 이름을 세팅 합니다. 

4. 미들웨어 만들어 사용하기 

   프로젝트에서 공통으로 사용되어질 미들웨어를 만듭니다. 아래 사용된 '*' 이것은 전체 적용 입니다. 

 위 코드는 fs.readdir 로 비동기 함수 입니다. ./data 에 있는 파일목록을 읽어서 콜백으로 filelist를 받아와

 서, 다시 req.filelist 에 돌려줍니다. 이제 프로젝트 어디에서도 req.filelist 를 이용하면 폴더의 파일목록을   읽어올수 있습니다. 

 

5. public 폴더를 정적폴더로 지정해서 사용하기 

  이미지파일, CSS 파일 및 자바스크립트 파일과 같은 정적 파일을 제공하려면 익스프레스에 static 으로 폴더를 지정해야 합니다. 안하면 사용 못해요. ^^;

 

 

6. 서버의 에러 처리를 합니다. 

  사실 익스프레스는 미들웨어 동작에 의해 돌아가는데, 에러 부분도 미들웨어가 적용되어집니다. 두가지

  규칙이 있습니다. 

  첫번째 app.use(function (req, res, next) err 인자값 없을때

이와 같이 페이지 못찾을때처럼 일반 오류처리할때 사용합니다.

 

 두번째 app.use(function (err, req, res, next) err 인자값 있을때

특정 에러에 대해 처리하고 싶을때 사용할수있습니다.

6. 서버 listen 


Express 미들웨어 소개 및 사용 해보기 

앞서 익스프레스에서 가장 중요한 기능부분을 차지하는 미들웨어에 대해 설명을 드렸습니다. 말그대로 남이 개발해놓은 모듈을 사용가능하고, 위 프로젝트 적용했듯이 내가 미들웨어를 만들어서 공용으로 사용할수도 있습니다. 미들웨어의 사용법은 다음과 같습니다. 

 

미들웨어 설명 : https://expressjs.com/en/guide/using-middleware.html

 

Using Express middleware

Using middleware Express is a routing and middleware web framework that has minimal functionality of its own: An Express application is essentially a series of middleware function calls. Middleware functions are functions that have access to the request ob

expressjs.com

위와 같은 형태로 만들어서 사용이 가능합니다. app.get or app.use 같이 설정을 줄수 있고 ('/' or('*' 과 같

이 세팅이 가능합니다. 무엇보다, req, res, next 를 통해서 전달이 가능하다는것 입니다. 

 


에러 처리 

main. js 파일에서 에러처리에 대한 미들웨어를 만들어 두었는데요. 그 부분을 실제 다른 미들웨어에서 어떻게 호출하고 있는지 알려드리겠습니다. 

 

이 부분은 페이지를 찾지 못했을때, 나오는 에러처리 부분이데요. 그래서 라우트를 실행하는 맨 밑바닥에서 호출 하였습니다. 

이와 같이 페이지 못찾을때처럼 일반 오류처리할때 사용합니다.

바로 이부분이 에러값이 인자가 있을때 사용되어지는 미들웨어 입니다. 

특정 에러에 대해 처리하고 싶을때 사용할수있습니다.

실제 인덱스 라우트에서 파일의 리스트를 읽어드리는 부분에, 리스트가 없는 영역이 있을때 해당하는 err값을 저 함수로 전달하고, 에러를 콘솔로 찍는 부분이 수행됩니다. 

router.js 파일


정적 파일 처리 

 정적 파일 처리는 main.js 에서 설명드린데로 public 폴더를 혹은 다른 폴더를 express.static을 이용하여 정적 폴더로 지정후, 이후에는 그안에 있는 파일은 HTML 코드를 그대로 사용하면 됩니다. 

이와 같이 똑같이 사용하면됩니다.


Express 라우터 

 main.js 에서 설명드린대로 프로젝트 구조를 가지고 갈때 index.js 에서 라우터 기능을 이용하기 위해서는 아래 코드가 필요합니다. 그리고 모듈을 export 하고 main.js에서 import 합니다. 

 

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
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
// index.js 파일 
var express = require('express');
var router = express.Router();
var template = require('../lib/template1.js');
 
//WEB PAGE Content load 
router.get('/', function (request, response) {
    var filelist = request.filelist;
    var title = 'Welcome3';
    var descriton = 'Hello, Node.js';
    var list = template.list(filelist)
    var html = template.html(title,list,
        `<h2>${title}</h2>
        <p>${descriton}</p>
        <img src="/images/coding.jpg" style="width:1000px; height:500px; display:block; margin-top:10px;">
        `
        ,
        `<a href="/topic/create">create</a>`
         );
    response.send(html);
    
});
 
module.exports = router
 
cs

설명서 

 1. express.Router 를 불러옵니다. 

 2. 이후 코드는 app. 대신 router. 으로 설정 합니다. 

 3. main.js 에서 사용하기 위해서 router 를 export 합니다. 

 

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
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
// router.js 파일 
var express = require('express');
var router = express.Router();
var fs = require('fs');
var template = require('../lib/template1.js');
var path = require('path');
 
 
//CREATE Method is GET 
router.get('/create', function(request, response){
    var filelist = request.filelist;
    var title = 'WEB - create';
    var list = template.list(filelist)
    var html = template.html(title,list,`
    <form action="/topic/create_process"
        method="POST">
        <p><input type="text" name="title" placeholder="title"></p>
 
        <p><textarea name="description"></textarea></p>
 
        <p><input type="submit"></p>
 
        </form>
    
    `,'');
    response.send(html);
    
});
 
//CREATE PROCESS Method is POST 
router.post('/create_process', function (request, response) {
       var post = request.body;
       var title = post.title;
       var description = post.description;
       
       fs.writeFile(`data/${title}`,description,'utf8',function(err){
           //response.redirect('/?id=${title}');     
           response.redirect(`/topic/${title}`);     
       });
}); 
 
//UPDATE get
router.get('/update/:pageId', function(request, response){
            
    var filteredId = path.parse(request.params.pageId).base; //경로 세탁
    var filelist = request.filelist;
    fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
        var title = filteredId;
        var list = template.list(filelist)
        var html = template.html(title,list,
            `
            <form action="/topic/update_process" method="post">
                <input type="hidden" name="id" value="${title}">
            <p>
                <input type="text" name="title" placeholder="title" value="${title}">
            </p>
            <p>
                <textarea name="description" placeholder="description">${description}</textarea>
            </p>
            <p>
                <input type="submit">
            </p>
            </form>
            `,
            `
            <a href="/topic/create">create</a> 
            <a href="/topic/update/${title}">update</a>
 
            
            `
        );
        response.send(html);
        });
    
});
 
//UPDATE PROCESS Method POST
router.post('/update_process', function(request, response){
    var post = request.body;
        var title = post.title;
        var id = path.parse(post.id).base; //경로세탁 
        var description = post.description;
        fs.rename(`data/${id}`,`data/${title}`, function(error){
            fs.writeFile(`data/${title}`,description, 'utf8',function(err){
                response.redirect(`/topic/${title}`);
            })
        })
});
 
//DELETE Methode is POST
router.post('/delete_process', function (request, response){
    var post = request.body;
    var id = path.parse(post.id).base; //경로세탁 
    fs.unlink(`data/${id}`,function(error){
        response.redirect('/');
    });
}); 
 
//WEB PAGE load 
router.get('/:pageId', function(request, response, next){
    //형식은 'user내가 치는거대로+ Id' ex page를 쳤다면 pageId
    var filelist = request.filelist;
    var filteredId = request.params.pageId
 
    fs.readFile(`data/${filteredId}`,'utf8',function(err,descriton){
    if(err)   {
        next(err);
    } else {
        var title = filteredId;
        var list = template.list(filelist)
        var html = template.html(title,list,
            `<h2>${title}</h2>${descriton}`,
            `
            <a href="/topic/create">create</a>  
            <a href="/topic/update/${title}">update</a>
            
            <form action="/topic/delete_process" method="post">
                <input type="hidden" name="id" value="${title}">
                <input type="submit" value="delete">
            </form>
            `
            );
        response.send(html);
    }
    });
});
 
module.exports = router;
 
 
cs

코드가 조금 길긴 하지만, index.js 와 동일 합니다. 

 


프로젝트 보안 처리 (헬멧 적용)

 웹이든 앱이든 보안이 털리면, 사이트가 마비 혹은 심각한 재산적 피해가 발생할것이라는것은 누구든지 예상이 가능할듯 합니다. 하지만 아직 보안까지 신경쓸 단계가 아니다 보니, 참 어렵네요. ^^; 하지만 익스프레스에서 제공해주는 미들웨어를 적용하는것 만으로 기본 보안이 된다고 하니 설치를 안할수가 없겠네요. 

 

설치법 및 적용법 

 1. npm install --save helmet 

 2. 코드 추가 


프로젝트 압축 처리 ( Compression 적용 )

 모듈및 기타 코멘트들이 모두 포함되어있는 프로젝트를 빈칸과 여러가지 압축을 통해 프로젝트의 크기를 현저히 작게 만들어주는 미들웨어 입니다. 이부분도 당연히 기본 적용이 필요해 보입니다. 적용 자체도 어렵지 않고요. 

 

설치법 및 적용법 

 1. npm install --save compression 

 2. 코드 추가 


Express Generator 적용 

리액트에 create-react-app 처럼 익스프레스 제너레이터는 기본적인 프로젝트 세팅을 해놓은 파일롯 프로젝트 입니다. 저도 사용해 보았는데, 추가적으로 pug 라는 라이브러리에 대한 학습이 필요해 보입니다. 그래도 전문가가 세팅 해놓은 프로젝트를 사용하는것도 저같은 초심자에게는 나쁘지 않을거 같다는생각이 들어 추후 프로젝트 개발시 사용하려고 합니다. 

 

사이트 : https://expressjs.com/en/starter/generator.html

 

Express application generator

Express application generator Use the application generator tool, express-generator, to quickly create an application skeleton. You can run the application generator with the npx command (available in Node.js 8.2.0). $ npx express-generator For earlier Nod

expressjs.com

위와 같은 구조를 가졌다고 합니다.

 


pug 라이브러리 for HTML Coding 

누군가 해놓은 글귀가 생각이 납니다. 좋은 개발자들의 기준은 내가 처음부터 다 개발하는 그런 개발자가 아니라, 남이 짜놓은 라이브러리를 어떻게 잘 조합해서 좋은 프로덕트를 만드는게 진짜 좋은 개발자라고요. 공부 많이 해야겠습니다. ^^

 

pug 라이브러리는 Express Generator App에 적용되어 있어서 한번 사용해보았는데요. HTML 코드를 자바스크립트 처럼 사용할수 있는것 같습니다. 잠깐 보았어요. 다음 사이트에서 확인해보세요. 

 

사이트 : https://pugjs.org/api/getting-started.html

 

Getting Started – Pug

Getting Started Installation Pug is available via npm: $ npm install pug Overview The general rendering process of Pug is simple. pug.compile() will compile the Pug source code into a JavaScript function that takes a data object (called “locals”) as an

pugjs.org


코드 공유 

 

 

rain2002kr/NodeJsExpressSample

node js express 샘플앱 CRUD 적용 . Contribute to rain2002kr/NodeJsExpressSample development by creating an account on GitHub.

github.com

 


감사합니다. 노드JS Express 좋네요. ^^

 

 

 

 

반응형