코드를 구성하기 위해 특정 패턴을 따른다. 코드와 코드가 수행하는 기능을 논리적으로 분리하는 방법이다.
- 사용자가 편집하길 원하는 모든 데이터를 가지고 있어야 한다.
- 뷰나 컨트롤러에 대해서 어떤 정보도 알지 말아야 한다.
- 변경이 일어나면, 변경 통지에 대한 처리방법을 구현해야만 한다.
- 모델이 가지고 있는 정보를 따로 저장해서는 안된다.
- 모델이나 컨트롤러와 같이 다른 구성요소들을 몰라야 된다.
- 변경이 일어나면 변경통지에 대한 처리방법을 구현해야만 한다.
-
모델이나 뷰에 대해서 알고 있어야 한다.
-
모델이나 뷰의 변경을 모니터링 해야 한다.
-
온라인 샵을 가정하고 이번 챕터를 진행해보자!
-
routes/shop.js
router.get('/', (req, res, next) => { // 데이터와 통신 : model const products = adminData.products; // veiw 보내줌 : controller res.render('shop', { prods: products, pageTitle: 'Shop', path: '/', hasProducts: products.length > 0, activeShop: true, productCss: true }); });
-
모든 로직을 controllers 폴더로 분리하기
exports.getAddProduct = (req, res, next) => { res.render('add-product', { pageTitle: 'Add Product', path: '/admin/add-product', productCSS: true, formCSS: true, activeAddProduct: true }); };
-
controllers/products.js
const products = []; exports.getAddProduct = (req, res, next) => { res.render('add-product', { pageTitle: 'Add Product', path: '/admin/add-product', productCSS: true, formCSS: true, activeAddProduct: true }); }; exports.postAddProdcut = (req, res, next) => { products.push({ title: req.body.title }); res.redirect('/'); console.log('2222', products); }; exports.getProducts = (req, res, next) => { res.render('shop', { prods: products, pageTitle: 'Shop', path: '/', hasProducts: products.length > 0, activeShop: true, productCss: true }); };
-
routes/shop.js
const products = []; exports.getAddProduct = (req, res, next) => { res.render('add-product', { pageTitle: 'Add Product', path: '/admin/add-product', productCSS: true, formCSS: true, activeAddProduct: true }); }; exports.postAddProdcut = (req, res, next) => { products.push({ title: req.body.title }); res.redirect('/'); console.log('2222', products); }; exports.getProducts = (req, res, next) => { res.render('shop', { prods: products, pageTitle: 'Shop', path: '/', hasProducts: products.length > 0, activeShop: true, productCss: true }); };
-
/routes/admin.js
const express = require('express'); const path = require('path'); const proudctsController = require('../controllers/products'); const router = express.Router(); router.get('/add-product', proudctsController.getAddProduct); router.post('/add-product', proudctsController.postAddProdcut); module.exports = router;
-
models/product.js 생성
기본의 입력받은 데이터 처리하는 js 파일 생성
const products = []; module.exports = class Product { constructor(t) { this.title = t; } save() { products.push(this); } static fetchAll() { return products; } };
-
controllers/product.js 수정
const Product = require('../models/product'); exports.getAddProduct = (req, res, next) => { res.render('add-product', { pageTitle: 'Add Product', path: '/admin/add-product', productCSS: true, formCSS: true, activeAddProduct: true }); }; exports.postAddProdcut = (req, res, next) => { const product = new Product(req.body.title); product.save(); res.redirect('/'); }; exports.getProducts = (req, res, next) => { const products = Product.fetchAll(); res.render('shop', { prods: products, pageTitle: 'Shop', path: '/', hasProducts: products.length > 0, activeShop: true, productCss: true }); };
-
models/product.js
const fs = require('fs'); const path = require('path'); const p = path.join( path.dirname(process.mainModule.filename), 'data', 'products.json' ); const getProductsFromFile = cb => { fs.readFile(p, (err, fileContent) => { if (err) { return cb([]); } else { cb(JSON.parse(fileContent)); } }); }; module.exports = class Product { constructor(t) { this.title = t; } save() { getProductsFromFile(products => { products.push(this); fs.writeFile(p, JSON.stringify(products), err => { console.log(err); }); }); } static fetchAll(cb) { getProductsFromFile(cb); } };
-
- 데이터를 표현하고 관리하고 저장하고 업데이트함.
- 어디에 저장하든 괜찮다. (메모리, 저장공간, 데이터베이스)
- 유저가 보는 프론트
- 많은 로직을 담는것 보다 간단히 해야한다.
- 모델과 뷰를 연결
- 라우터 역할