[NODE] 개발을 빠르고 쉽게 만들어주는 도구들을 알아보자! - 3. Express 구조를 뜯어보자!

저번시간에 Express-generator을 통해 한번에 만들었던 폴더들을 하나하나 순서대로 뜯어보겠습니다. 그전에 기본적인 Express 폴더에 대해 짚고 넘어가는게 좋겠죠?

Express의 기본 구조

bin/www

서버 구동을 위한 기본적인 코드로 구성되어있습니다. app.js 파일을 가져와 HTTP 객체와 연동하는 작업을 해줍니다.

public

UI 설정(html/js/css 관련)에 들어가는 assets 의 폴더와 파일들로 구성되어 있습니다.

routes

url 을 연결해서 로직과 연결해주는 폴더입니다.

view

템플릿 jade 파일이 담겨있는 공간입니다. jade 엔진을 통해 html로 변환해 효율적으로 코드를 짤 수 있습니다.

app.js

서버 설정 파일이 담겨있습니다. bin/www 가 이 파일을 읽고 http 와 연결해줍니다.

package.json

패키지 관리 파일. 프로그램 이름, 버전 등 노드 프로그램의 정보를 이 파일에 담아놓습니다. 사용하는 모듈 목록을 알 수 있습니다.

bin/www

서버 구동을 위한 기본적인 코드입니다. node app.js를 시작하면 컴파일러는 서버를 키기 위해 가장 먼저 이 파일을 해석하죠. 하나하나 찬찬히 뜯어보겠습니다.


#!/usr/bin/env node


//1. http 통신을 위한 모듈을 추출합니다.
var app = require('../app');
var debug = require('debug')('meanapp:server');
var http = require('http');

//2. 통신할 포트를 설정합니다. 3000으로 설정해 주네요.
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);


// 3. 추출한 http 모듈의 미들웨어로 서버를 생성합니다.
var server = http.createServer(app);

// 4.통신을 위해 3000 번 포트로 응답을 듣습니다.
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

// 5. 파이프 이름 또는 포트 번호를 반환합니다.
function normalizePort(val) {
 var port = parseInt(val, 10);
 if (isNaN(port))
   return val;

 if (port >= 0)
   return port;
 return false;
}
// 6. 에러시 로그를 반환합니다.
function onError(error) {
 if (error.syscall !== 'listen') {
   throw error;
}

 var bind = typeof port === 'string'
   ? 'Pipe ' + port
  : 'Port ' + port;

 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;
}
}
// 7. 성공시 값을 반환합니다.
function onListening() {
 var addr = server.address();
 var bind = typeof addr === 'string'
   ? 'pipe ' + addr
  : 'port ' + addr.port;
 debug('Listening on ' + bind);
}

이 파일에서 처음 추출했던 var app = require('../app');에 해당하는 app.js를 살펴볼까요?

app.js

1. var ~ = require('~')


var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser')
var bodyParser = require('body-parser');
var sassMiddleware = require('node-sass-middleware');

var index = require('./routes/index');
var users = require('./routes/users');

require('~') 함수는 모듈을 로딩하는 함수입니다. c와 비교하자면 import java.util.~이런것과 비슷하려나요?

express-generator가 package.json에 명시한 외부 모듈(=라이브러리)와, 사용자가 직접 만든 내부 모듈을 app.js에서 사용할 수 있도록 만들어 줍니다.

index.js


var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
 res.render('index', { title: 'Express' });
});

module.exports = router;

모듈은 라이브러리와 같다고 보면 됩니다. node.js에서는 라이브러리를 모듈이라고 지칭하죠. 외부에서 개발자들이 만든 모듈 외에,Express-generator은 기본적으로 내장 모듈을 만들어줍니다. 대표적인 샘플이 ./routes/index.js의 내용인데요. 마지막에 module.exports = router;을 명시하여 이 파일을 모듈로 사용할 수 있습니다.

1. var app = express();


var app = express();

express 라이브러리를 해당 파일에 임폴트 (require)했으니, 실행시켜야겠죠? 실행시킨 express(); 를 app 에 넣어줍니다.

2. app.set()


// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

생성한 express에서 제공하는 .set() 메서드는 템플릿 엔진을 렌더링 하는 함수입니다.

  • 'views' : 템플리트가 있는 디렉토리 경로를 설정해 줍니다.

  • 'view engine': 사용할 템플리트 엔진을 설정해 줍니다.

app.use()


app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(sassMiddleware({
 src: path.join(__dirname, 'public'),
 dest: path.join(__dirname, 'public'),
 indentedSyntax: true, // true = .sass and false = .scss
 sourceMap: true
}));
app.use(express.static(path.join(__dirname, 'public')));

// 라우팅을 로드합니다.
app.use('/', index);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
 var err = new Error('Not Found');
 err.status = 404;
 next(err);
});

// 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');
});

위에 require 로 import한 모듈을 express() 함수 안에서 사용하겠다고 선언하는 내용입니다. 이 모듈들의 각각의 내용은 따로 정리하여 올리겠습니다. 자 이제 app.js의 순서대로 살펴보겠습니다. app.set()에서 설정한 View 엔진 부터 둘러보겠습니다.

app/views/index.js


<!DOCTYPE html>
<html>
 <head>
   <title><%= title %></title>
   <link rel='stylesheet' href='/stylesheets/style.css' />
 </head>
 <body>
   <h1><%= title %></h1>
   <p>Welcome to <%= title %></p>
 </body>
</html>

ejs파일입니다. ejs는 embed javascript의 약자로 <%= %>의 표현식 안에 javascript 문법을 넣어 정적인 html 문서를 동적으로 사용할 수 있습니다.

Routing


app.use('/', index);
app.use('/users', users);

app.js에서는 app.use()를 통해 라우팅을 로드합니다. app.use('/',index)에서 / 는 라우트의 경로를 의미합니다. / 의경로로부터 시작하는 라우팅인데, 한번 파일을 보겠습니다.

app/routes/index.js


var express = require('express');
var router = express.Router();
// 1.
router.get('/', function(req, res, next) {
 // 2.
 res.render('index', { title: 'Express' });
});
module.exports = router;
router.get('/', func)

index.js 파일 .get() 함수로 라우팅 경로를 지정해 줍니다. 예를들어 use('/').get('/') 경로이므로 localhost:3000의 경로에 나오는 페이지를 보여줍니다.

res.render('index', { title: 'Express' });

res.render()는 해당 라우팅 요청이 들어왔을때 보여줄 뷰 페이지를 말해줍니다. index.ejs의 파일에 있는 html 문서가 보여집니다. {} 안에 있는 내용은 html에 전달해줄 값들을 명시해 둔 내용입니다.

크게 express-generator로 만든 모듈을 살펴보았습니다. 수고하셨습니다!

참고자료


[NODE] 개발을 빠르고 쉽게 만들어주는 도구들을 알아보자! - 2. Express.js 프레임워크 설치 및 실행

이전장에서 프레임워크, 라이브러리, 플랫폼의 개념을 살펴보았는데요. 대표적인 Node.js의 프레임워크인 Express.js에 대해 알아보겠습니다.

Express.js

Express.js 는 http와 Connect 컴포넌트를 기반으로 Node.js에서 사용하는 웹 프레임워크 입니다. 가장 많이 사용하는 프레임워크이며, 안정적이기 때문에 웹 규모에 관게 없이 웹 서버를 구축할 수 있습니다.

설치


$ npm install -g express

express-generator

express-generator는 Express 웹 프레임워크의 구조를 만들어주는 Express Application Generator Tool입니다. Express 프레임워크의 구조를 신속하게 작성하기 위해 사용합니다.

설치


$ npm install -g express-generator

위 명령어가 설치가 완료되면, Express 프레임워크 구조를 설정해주는 커맨드 명령어를 실행할 수 있습니다.

명령어 확인하기


$ express -h

express-generator가 성공적으로 설치되어있다는 것을 확인할 수 있는 명령어 입니다. 아래는 명령어 내용들을 확인할 수 있습니다

result


Usage: express [options] [dir]
Options:

      --version       output the version number
  -e, --ejs           add ejs engine support
      --pug           add pug engine support
      --hbs           add handlebars engine support
  -H, --hogan         add hogan.js engine support
  -v, --view <engine> add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
  -c, --css <engine>   add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
      --git           add .gitignore
  -f, --force         force on non-empty directory
  -h, --help           output usage information

express -h 로 옵션을 확인해 보니, view 와 css의 부분은 default로 jadecss가 설정이 되어있는 것을 알수있네요. 한번 확인해볼까요 ?

myapp/views/index.jade
myapp/public/stylesheets/style.css

의 파일을 확인할 수 있습니다.

Express-generator로 express framework 생성하기

간단하게 만들어보고 Express-generator 가 만들어준 파일을 분석해 보겠습니다.

1. 설치

굉장히 간단합니다. express 프로젝트이름 형식으로 폴더 구조를 만들어 줍니다


$ express myapp
result

결과 로그를 확인해 봅시다.


$ express myapp

// 1.
warning: the default view engine will not be jade in future releases
warning: use `--view=jade' or `--help' for additional options

// 2.
  create : myapp
  create : myapp/package.json
  create : myapp/app.js
  create : myapp/public
  create : myapp/routes
  create : myapp/routes/index.js
  create : myapp/routes/users.js
  create : myapp/views
  create : myapp/views/index.jade
  create : myapp/views/layout.jade
  create : myapp/views/error.jade
  create : myapp/bin
  create : myapp/bin/www
  create : myapp/public/javascripts
  create : myapp/public/images
  create : myapp/public/stylesheets
  create : myapp/public/stylesheets/style.css

// 3.
  install dependencies:
    $ cd myapp && npm install

  run the app:
    $ DEBUG=myapp:* npm start
1. 뷰 엔진이 jade가 아니라는 warning이 뜨는데, jade가 이제는 pug라는 이름으로 바뀌어서 나는 에러인 것 같습니다.
2. express 명령어로 만들어진 폴더의 구조를 보여줍니다. 기본 설정되어있는 jade view 엔진과 css가 되어있고, routes,view,bin,public 의 폴더와 package.json,app.js의 다양한 파일들을 만들어 주네요. 뒤에 살펴보겠습니다.
3. 의존하는 라이브러리를 설치하는 명령어와, app을 실행하는 명령어를 알려주고 있습니다.

2. 설치

바로 실행시키면 express-generator가 package.json에 넣어준 의존성 모듈이 설치가 안되서 에러가 납니다. 설치 후 실행해 봅시다.


$ cd myapp && npm install

3. 실행


$ DEBUG=myapp:* npm start

실행 한 후 로그창을 확인해보면

result


> myapp@0.0.0 start /NODEJS/BLOG/using-express-generator/myapp
> node ./bin/www
myapp:server Listening on port 3000 +0ms

서버가 실행되었다는 결과창을 알려주고,

http://localhost:3000/ 로 들어가보면

의 문구를 확인할 수 있습니다.

View,CSS 설정 바꿔서 만들어보기

Express는 jade, css 를 default 로 제공해주지만, 저는 MEAN 스택을 공부하고 있기 때문에 jade 가 아닌 ejs와, sass를 설정하겠습니다. jade,ejs 는 정적인 html 파일을 동적으로 바꿔주는 템플릿 엔진인데요. MEAN 스택과 템플릿 엔진 부분은 나중에 따로 올리겠습니다.

1. 설치

위에 express -h 명령어에 봤던 것 중, 필요한 값을 명령어에 한번에 연결시켜 설치해 줍니다.


$ express meanapp --view=ejs --css sass --git
결과


create : .
  create : ./package.json
  create : ./app.js
  create : ./.gitignore
  create : ./public
  create : ./routes
  create : ./routes/index.js
  create : ./routes/users.js
  create : ./views
  create : ./views/index.ejs
  create : ./views/error.ejs
  create : ./bin
  create : ./bin/www
  create : ./public/javascripts
  create : ./public/images
  create : ./public/stylesheets
  create : ./public/stylesheets/style.sass
실행시켜보기

바로 실행시키면 express-generator가 package.json에 넣어준 의존성 모듈이 설치가 안되서 에러가 납니다. 설치 후 실행해 봅시다


$ npm install
$ npm start

위에 실행파일처럼 잘 뜨는것을 확인할 수 있었습니다. 다음장에서는 Express에서 만들어준 구조를 자세히 살펴보겠습니다



웹사이트를 구축할 경우 밑바닥부터 하나하나 만드는 것은 오래 걸리고, 복잡하며, 유지보수하기 어렵습니다. 이런 불편한 점을 개선시키기 위해 손쉽고 빠른 프로젝트 개발을 위한 여러가지 도구들이 존재합니다. 대표적으로 프레임워크와 라이브러리를 알아봅시다! 

프레임워크 , 라이브러리, 플랫폼

프레임워크, 라이브러리, 플랫폼은 개발 공부를 하면서 많이 듣게 되는 단어 중 하나인데요. 비슷한 것 같지만 굉장히 헷갈리는 개념들 중 하나입니다. 차이점이 뭘까요?




프레임워크


프레임워크는 프로젝트의 구조를 잡아주는 역할을 합니다. 필수적으로 필요한 구조를 잡아주기 때문에 프레임워크 만으로도 프로젝트는 돌아가며 이에 필요한 라이브러리를 포함하고 있습니다. 프레임워크로 구조를 잡아주면, 여러 규칙이 존재하기 때문에 프레임워크의 틀에 맞춘 프로젝트의 개발을 해야합니다.




라이브러리




라이브러리는 프로젝트 시 필요한 기능들을 모아둔 도구입니다. 전체적인 프로젝트 구조에서 기능을 제공해 줍니다. 선택적으로 필요한 부품입니다. 라이브러리는 필요한 하나의 기능 단위를 말하기 때문에 선택적으로 필요한 부분을 설치해서 사용합니다.



프레임워크 vs 라이브러리

프레임워크라이브러리의 차이를 간단하게 말하면 프레임워크는 구조를 잡아주기 때문에 프로젝트가 돌아가지만, 라이브러리는 도구이기 때문에 돌아가지 않습니다.

건축으로 예를들어볼까요?




건물을 지을때, 건축물을 올리기위해 철골을 쌓아놓고 건축을 시작합니다. 이를 Scaffolding이라고 하죠.

웹사이트 제작시에도 이런 철골 작업이 필요합니다.

웹을 프레임워크 없이 밑바닥 부터 구축한다면 시간도 오래걸리고, 보통 협업을 하기 때문에 다른사람들에게 남들에게 내가 만든 프로젝트 구조를 설명해줘야 합니다.

이런 불편함을 해결하기 위해 기본적인 구조를 한번에! 잡아주는 역할이 프레임워크 입니다.





건축으로 비교하자면 집에 가장 필요한 기본적인 ,화장실,거실같은 구조만 갖춘 형태로 만들어줍니다.

웹프레임워크 또한 웹사이트가 실행이 될 수 있도록 하는 기본적인 라이브러리들만 가지고 웹사이트를 만들어줍니다. 그럼 라이브러리는 어떤존재들일까요?





라이브러리

라이브러리는 이런 기본적인 웹사이트를 더 편안하고, 예쁘게 만들어주는 도구라고 생각하면 됩니다.

기본적인 건축이 끝나서 입주를 할 수있다고 가정해봅시다. 사람이 살 수 있는 상태이지만 가구나 가전용품들이 필요하겠죠? 침대이불이 필요하고, 예쁘게 꾸미고 싶다면 벽지 또는 리빙 가구들로 꾸밀 수 있습니다.

라이브러리는 기본적으로 웹사이트가 돌아가게 만든 프레임워크에 `세탁기`,`비데`,`냉장고` 와같은 기능과 같습니다. 라이브러리를 하나하나 구축하는게 아닌 누군가 만든 기능을 가져다 사용함으로써  원하는 사이트를 더욱 빠르게 구축할 수 있습니다.




플랫폼

소프트웨어에서의 플랫폼의 정의는 프로젝트가 실행되는 환경을 말합니다. Node.js 또한 플랫폼입니다.

건축으로 말하면 내진설계방식..? 이런게 되려나요 ㅎㅎ

Node.js의 실행 환경
  • 네트워크 애플리케이션(특히 서버 사이드) 개발에 사용되는 소프트웨어 플랫폼
  • Javascript 언어 사용
  • Non-blocking I/O와 단일 스레드
  • 내장 HTTP 서버 라이브러리를 포함하고 있어 별도의 소프트웨어 없이 동작하는 것이 가능
  • 웹 서버의 동작에 있어 더 많은 통제 가능

자 이제 기본적인 개념을 알았다면, 다음 페이지에서 Node.js에서 사용되는 프레임워크 중 가장 대표적인 Express.js를 알아봅시다~!

참고 자료


+ Recent posts