이번엔 제목 그대로 "Node.js + 익스프레스" 환경에서 MVC 함께 써보려고 합니다.
처음 Express framework를 다룰 때, 대부분의 코드를 router에 직접 코딩했었는데요. 어떻게 해야 더 이쁘게 코딩할 수 있을까 고민한 것이 계기입니다.
원래 MVC 모델
응용 프로그램(애플리케이션)을 M (Model) V (View) C (Controller) 3개로 분할하여 구축하는 개발 방법론입니다.
- Model : 응용 프로그램 데이터, 비즈니스 규칙, 논리 함수, 로직
- View : 그래프, 그림 등 임의의 (임시) 정보 표현
- Controller : 입력을 받아 model과 view 명령으로 변환
익스프레스
Express는 웹 및 모바일 애플리케이션을 위한 일련의 강력한 기능을 제공하는 간결하고 유연한 Node.js 웹 애플리케이션 프레임워크입니다.
위에서 설명한 대로, Express framework는 어디까지나 최소한의 기능만 제공하므로 모듈을 적절히 조합하면, 굉장히 유연하게 결과물을 만들어 낼 수 있습니다.
잘 보면서 따라 하기
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var db = require('../config/db');
router.get('/users/index', (req, res, next) => {
var sql = 'select * from users';
try {
const connection = mysql.createConnection(db);
connection.connect();
connection.query(sql,
(error, results, fields) => {
if (error == null) {
res.render('index.ejs',
{
content: results
});
}else{
throw(error);
}
}
);
connection.end();
} catch(e) {
res.render('index.ejs',
{
content: {error: e},
});
}
});
Express framework에서 작성된 코드를 검토할 때 흔히 볼 수 있는 형태입니다. 주로 이런 느낌의 코드를 자주 접하게 됩니다.
당연히 위의 코드도 실행에 문제는 없습니다만, 양이 많아지면 코드의 질은 장담할 수 없다고 생각합니다.
다른 언어로 MVC 프레임워크 이용한 개발한 분들에게도 위화감이 드는 코드일 겁니다.
하고 싶은 일
익스프레스(Express)를 소위 MVC 프레임워크 스럽게 사용하고 싶어요.
해봐요
빨리 시작해 볼게요. 사용자 정보를 표시하는 페이지를 예로 들어 코드를 작성해 봅니다.
전제 사항
- Node.js 버전 : 10.15.1
- Express 버전 : 4.16.0
- 데이터베이스 : MySQL 5.7
디렉터리 구성
├── app.js
├── bin
│ └── www
│
├── config
│ └── db.js
│
├── controllers
│ └── UserController.js
│
├── models
│ └── Users.js
│
├── views
│ └── index.ejs
│
├── routes
│ └── routes.js
├── package.json
├── public
express-generator를 구축하고,
들을 추가합니다.
라우팅 설정
routes / routes.js
var express = require('express');
var router = express.Router();
var userController = require('../controllers/UserController')
router.get('/users', userController.doGetUser);
router.post('/users/regist', userController.doRegistUser);
module.exports = router;
라우팅은 routes.js 파일에 작성합니다.
HTTP 요청(리퀘스트 request)의 엔드포인트(end point)를 어떤 모듈에서 처리할지 작성되어 있습니다.
node.js 예제 소스 중, 세 번째 줄에서 이른바 controller를 읽습니다.
Controller 작성
controllers / UserController.js
const express = require('express');
const Users = require('../models/Users');
const Views = '../views/'
module.exports = {
doGetUser: function (req, res, next) {
Users.getUser(id).then((result) => {
res.render(Views + 'index.ejs',{users: result});
});
}
}
Controller는 router에서 받은 요청(request)에 대해 Model 작업을 수행하고 결과를 View에 전달합니다.
두 번째 줄에서 Model을 읽고 있습니다.
Model 작성
models / User.js
const mysql = require('mysql');
const db = require('../config/db');
const table = 'users';
module.exports = {
getUser: function () {
return new Promise ((resolve, reject) => {
const con = mysql.createConnection(db);
con.query(
`select id, name, date_format(birthdate,"%Y/%m/%d")
as birthdate from ${table}`, (err, result, fields) =>
{
if ( err ) {
reject(err);
} else {
resolve(result);
}
});
con.end();
});
},
}
Model은 DB에서 값을 가져와 Controller에 반환합니다.
View 작성
<table>
<tbody>
<th>No</th>
<th>이름</th>
<th>생년월일</th>
<% for( var i in users ){ %>
<tr>
<td><%= users[i].id %></td>
<td><%= users[i].name %></td>
<td><%= users[i].birthdate %></td>
</tr>
<% } %>
</tbody>
</table>
Controller에서 받은 데이터를 사용하여 렌더링합니다.
정리
더 나은 작성 방법이 있을 거라고 생각하며, 위와 같이 MVC 모델을 적용할 수 있다고 생각합니다.
router에서 모든 처리 과정을 작성(코딩)할 때와 비교하면 매우 깔끔하며, 유지 보수도 쉬워질 것으로 예상합니다.
그렇다는 것은, 개인적으로 "Node.js + 익스프레스 framework에서 MVC 함께 써보기"는 충분히 유용하다는 것입니다.
그럼 또 만나요!