Back Ground

Node - Express-generator 빠르게 설치 [ express 구조 ] 본문

Javascript/Node.js

Node - Express-generator 빠르게 설치 [ express 구조 ]

Back 2019. 2. 25. 00:40


익스프레스 프레임워크는 익스프레스 외에도 많은 패키지를 사용하므로

입문자 입장에서는 필요한 패키지를 찾아서 설치하기가 어렵기때문에 

프레임워크에 필요한 package.json을 만들어주고 기본 폴더 구조까지 잡아주는 패키지가 있다.

바로 Express-generator이다.



[콘솔]

npm i -g express-generator

( npm i  == npm install)





설치가 완려되었다면 새 익스프레스 프로젝트를 생성해본다.

새로 프로젝트를 만들고자 하는 폴더로 이동해서 express <프로젝트 이름>을 입력한다.


[콘솔]

express learn-express --view=pug



  ( ... ) 

   create : learn-express\views\layout.pug

   create : learn-express\app.js

   create : learn-express\package.json

   create : learn-express\bin\

   create : learn-express\bin\www


   change directory:

     > cd learn-express


   install dependencies:

     > npm install


   run the app:

     > SET DEBUG=learn-express:* & npm start


생성된 폴더 및 파일명과 함께 다음에 입력해야 할 명령어를 알려준다.


--view=pug란?

6.5절에서 템플릿 엔진에 대해 살펴볼텐데, Express-generator는 기본적으로 jade를 템플릿 엔진으로 설치한다.

하지만 jade는 Pug로 개명한 지 오래되었다.

따라서 옛 버전인 Jade 대신 최신 버전인 Pug를 설치하기 위해하여 express-generator에 옵션을 주었다.


Pug 대신 EJS를 템플릿 엔진으로 사용하고 싶다면 --view=ejs를 입력하세요.

pug란 https://backback.tistory.com/331





이제 learn-express라는 폴더가 생성되었을 것이다.
폴더에 들어가서 npm 모듈들을 설치한다.

콘솔에서는 다음과 같이 두 가지 명령어를 한번에 실행할 수도 있다.
폴더 이동 명령어와 npm설치 명령어를 동시에 실행한다.
명령어 사이에 &&를 붙이면 된다.




[콘솔]

cd learn-express && npm i


폴더 구조를 간단히 살펴보면 다음과 같다.

app.js 파일이 핵심적인 서버 역할을 한다. bin폴더의 www파일은 서버를 실행하는 스크립트이다. 

public 폴더는 외부(브라우저 등의 클라이언트)에서 접근 가능한 파일들을 모아둔 곳이다. 

이미지, 자바스크립트, CSS 파일들이 들어 있다. 

routes폴더는 주소별 라우터들을 모아둔 곳이고, views 폴더는 템플릿 파일을 모앙둔 곳이다.


앞으로 서버의 로직은 모두 routes 폴더 안의 파일에 작성할 것이고,

화면 부분은 views 폴더 안에 작성할 것이다.

나중에 데이터베이스를 배우면 데이터 부분은 models 폴더를 만들어 그 안에 작성하게 된다.


이렇게 구조가 명확하게 구분되어 있어 서버를 관리하기 용이한다.



MVC패턴과도 비슷하다. 라우터 컨트롤러라고 본다면 말이다.


코드를 살펴보기에 앞서 익스프레스를 먼저 실행해보도록 하자.

package.json의 scripts에 start속성이 있고, 

속성값으로 node ./bin/www 가 적혀 있다.

따라서 npm run start 명령어로 서버를 실행할 수 있다. 

그런데 start 명령어는 특별하므로 그냥 npm start만으로도 서버를 실행할 수있다.



[콘솔]

npm start

http://localhost:3000으로 접속된다.









express 초기 폴더 구조










Express 구조 이해 


익스프레스는 코드가 여러개의 파일로 분산되어 있다.

각 부분마다 맡은 역할이 나눠져 있어 보기에. 좋고 관리하기 좋다.


먼저 핵심 파일인 bin/www


bin/www

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
#!/usr/bin/env node
 
/**
 * Module dependencies.
 */
 
var app = require('../app');
var debug = require('debug')('learn-express:server');
var http = require('http');
 
/**
 * Get port from environment and store in Express.
 */
 
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
 
/**
 * Create HTTP server.
 */
 
var server = http.createServer(app);
 
/**
 * Listen on provided port, on all network interfaces.
 */
 
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
 
/**
 * Normalize a port into a number, string, or false.
 */
 
function normalizePort(val) {
  var port = parseInt(val, 10);
 
  if (isNaN(port)) {
    // named pipe
    return val;
  }
 
  if (port >= 0) {
    // port number
    return port;
  }
 
  return false;
}
 
/**
 * Event listener for HTTP server "error" event.
 */
 
function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }
 
  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;
 
  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}
 
/**
 * Event listener for HTTP server "listening" event.
 */
 
function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}
 
cs


bin/www 파일은 

http 모듈에 express모듈을 연결하고,

포트를 지정하는 부분이다


희한하게 www파일에는 js 확장자가 붙어 있지 않다.


또한, #!/usr/bin/env node라는 주석이 첫줄에 달려있다. 

www 파일을 콘솔 명령어로 만들 수 있는데, 이때 이 주석이 사용된다.


전역 설치 후 rimraf와 같이 명령어로도 실행 할 수 있는 것이다.



Rimraf 란

Node.js를위한 UNIX 명령은 rm -rf

깊은 삭제 (같은 rm -rf) 파일 및 디렉토리의 비동기 딥 삭제를 제공 Node.js를에 대한 모듈 .rimraf 실행 파일은 rm -rf 쉘 명령 대신 더 빠른 대체 파일입니다.

자료 :

출처 : https://stackoverrun.com/ko/q/12430822






[코드설명]

www 파일에서 핵심적인 부분만 따로 살펴 보면

1
2
3
4
5
6
7
8
9
10
11
12
var app = require('../app');
var debug = require('debug')('learn-express:server');
var http = require('http');
 
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
 
var server = http.createServer(app);
 
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
cs


  1. 먼저 app, debug, http모듈들을 가져온다. debug모듈은 콘솔에 로그를 남기는 모듈이다.

  2. app.set('port',port); 로 서버가 실행될 포트를 설정한다. process.env 객체에 PORT 속성이 있다면 그 값을 사용하고,
    없다면 기본값으로 3000번 포트를 이용하도록 되어 있다.
    이렇게 app.set(키 , 값)을 사용해서 데이터를 저장할 수 있다.
    나중에 데이터를 app.get(키)로 가져올 수 있다.

  3. http.createServer에 불러온 app 모듈을 넣어준다. app 모듈이 createServer메서드의 콜백 함수 역할을 한다.

  4. listen을 하는 부분은 http웹 서버와 동일하다.
    기존 서버를 구동했던 것과 동일하게 포트를 연결하고 서버를 실행한다.
    익스프레스는 그저 콜백 함수 부분을 조금 다르게 만드는 것이다

 















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
41
42
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
 
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
 
var app = express();
 
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine''pug');
 
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
 
app.use('/', indexRouter);
app.use('/users', usersRouter);
 
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});
 
// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env'=== 'development' ? err : {};
 
  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
 
module.exports = app;
 
cs



[코드설명]

1
var app = express();
cs


 express 패키지를 호출하여 app 변수 객체를 만들었다.

이제 이 변수에 각종 기능을 연결한다.



1
2
3
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine''pug');
cs

 

app.set 메서드로 익스프레스 앱을 설정 할 수 있다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
 
app.use('/', indexRouter);
app.use('/users', usersRouter);
 
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});
 
// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env'=== 'development' ? err : {};
 
  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
cs


중간 부분 app.use로 시작하는 코드가 많은데,

미들웨어를 연결하는 부분이다. 



1
module.exports = app;
cs

 

마지막에는 app 객체를 모듈로 만들었다.

이것이 bin/www에서 사용된 app 모듈이다.





익스프레스 구조도


클라이언트의 요청을 받아서 처리한 후 

다시 클라이언트에게 응답한다 (기존 http 서버와 같다)

하지만 중간에 미들웨어들을 거친다는 것이 다르다










출처 : node.js 교과서









Comments