MVC란 Model-View-Controller의 약자로 애플리케이션을 세 가지 역할로 구분한 개발 방법론입니다.
controllers
에서는 미들웨어 함수를 분리해서 관리해 줄 것입니다.
models
에서는 DB 생성을 관리해주는 곳으로 이전에 배운 Schema 정의를 해 준 폴더와 동일합니다.
view
에는 화면에 보여지는 파일들(html 파일)을 관리해주는 폴더입니다.
위의 그림처럼 사용자가 controller를 조작하면 controller는 model을 통해서 데이터를 가져오고
그 정보를 바탕으로 시각적인 표현을 담당하는 View를 제어해서 사용자에게 전달하게 됩니다.
위의 개념을 WEB에 적용 시!
사용자가 웹사이트에 접속 (Users)
Controller는 사용자가 요청한 웹페이지를 서비스하기 위해서 모델을 호출 (Manipulates)
Model은 데이터베이스나 파일과 같은 데이터 소스를 제어한 후 그 결과를 Return
Controller는 Model이 리턴한 결과를 View에 반영 (Updates)
데이터가 반영된 View는 사용자에게 보여짐 (Sees)
사용자가 보는 페이지, 데이터처리, 그리고 이 2가지를 중간에서 제어하는 컨트롤,
이 3가지로 구성되는 하나의 애플리케이션을 만들면 각각 맡은 바에만 집중을 할 수 있게 됩니다.
공장에서도 하나의 역할들만 담당을 해서 처리를 해서 효율적이게 됩니다. 프로그래밍에서도 마찬가지입니다.
서로 분리되어 각자의 역할에 집중해 개발한다면, 유지보수성, 애플리케이션의 확장성,
그리고 유연성이 증가하고, 중복코딩이라는 문제점 또한 사라지게 됩니다.
서비스 로직을 제외한 MVC 패턴을 적용한 api 예제를 만들어보자 !
index.js
// const express = require('express') // 옛날방식 => commonjs
import express from "express"; // 요즘방식 => module
import { ProductController } from "./mvc/controllers/product.controller.js";
import { CouponController } from "./mvc/controllers/coupon.controller.js";
const app = express(); // express에 있는 기능을 app에 담아줌 - > api만드는 기능 생성
// 상품 API
const productController = new ProductController()
app.post("/products/buy", productController.buyProduct); // 상품 구매하기 API
app.post("/products/refund", productController.refundProduct); // 상품 환불하기 API
// 쿠폰(상품권) API
const couponController = new CouponController()
app.post("/coupons/buy", couponController.buyCoupon)
// 게시판 API
// app.get("/boards/...")
app.listen(3000); // 리슨 기다린다 (포트번호)
CouPonController
import { CashService } from "./services/cash.service.js"
export class CouponController{
buyCoupon = (req, res) => {
console.log(req.body)
// 1. 가진돈 검증하는 코드 (대략 10줄 => 2줄 )
const cashService = new CashService()
const hasMoney = cashService.checkValue()
// 2. 상품권 구매하는 코드
if(hasMoney){
res.send("상품권 구매 완료!!")
}
}
}
ProductController
import { CashService } from "./services/cash.service.js";
import { ProductService } from "./services/product.service.js";
export class ProductController {
buyProduct = (req, res) => {
console.log(req.body)
// 1. 가진돈 검증하는 코드 (대략 10줄 정도 => 2줄)
const cashService = new CashService();
const hasMoney = cashService.checkValue();
// 2. 판매여부 검증하는 코드 (대략 10줄 정도 => 2줄)
const productService = new ProductService();
const isSoldOut = productService.checkSoldOut();
// 3. 상품 구매하는 코드
if (hasMoney && !isSoldOut) {
res.send("상품 구매 완료!!");
}
};
refundProduct = (req, res) => {
// 1. 판매여부 검증하는 코드 (대략 10줄 정도 => 2줄)
const productService = new ProductService();
const isSoldOut = productService.checkSoldOut();
// 2. 상품 환불하는 코드
if (isSoldOut) {
res.send("상품 환불 완료!!");
}
};
}
CashService
// 서비스 로직은 미구현
export class CashService {
checkValue = () => {
// 1. 가진돈 검증하는 코드 (대략 10줄 정도)
// ...
// ...
// ...
// ...
};
}
ProductSevice
// 서비스 로직은 미구현
export class ProductService {
checkSoldOut = () => {
// 1. 판매여부 검증하는 코드 (대략 10줄 정도)
// ...
// ...
// ...
// ...
};
}
rest-api를 사용했던 퍼사드 패턴과 살짝 유사하지만 훨씬 간결하고 구조가 명확한것을 볼 수 있다