카테고리 없음

Node.js 공부하기) MVC

DevOhwa 2022. 9. 29. 22:27
반응형

유데미 강의를 바탕으로 정리한 글이며, 한글이 어색한경우는 괄호에 영어표현을 넣었다. 

+ 부족한 부분들은 구글링하여 추가하였다. 

 

MVC구조

 

 

MVC

Model View Controller의 약자. 

Model : 

객체나 데이터를 나타내는 코드의 한부분. 데이터를 저장하거나 파일로부터 데이터를 주고받는 등. 데이터 관련 작업을(saving, fetching..etc) 할 수 있도록한다. 

 

View:

사용자가 보게 되는 화면을 책임진다. html 자료에 올바른 내용을 렌더링해서 사용자에게 보내는 역할을 한다. 애플리케이션 코드와 분리되어있으며 view를 생성하기 위해서 템플릿 엔진에 주입하는 데이터와 약간만 통합되어있다. 

 

Controllers:

Model과 View사이의 연결점이다. view는 애플리케이션 논리와 상관이 없고 model은 데이터를 저장하고 가져오는 역할을 하기 때문에 controller가 model과 함께 데이터를 저장하거나 저장 프로세스를 유발(trigger)한다. view에서 가져온 데이터를 전달하는 경우도 controller가 돕게된다. 컨트롤러는 중개인으로 중간논리를(contain in-between logic) 포함한다. 

컨트롤러는 작업할 모델과 rendering할 뷰를 정의하는 역할을 하는것이다. 그리고 이것이 바로 패턴이다. 

컨트롤러는 일부 로직이 분리되어서 다른 미들웨어 기능으로 이동한다. 

 

(참고) Routes는 이들과 어떤 관계일까?

라우트는 경로에 따른 http method에 따라서 어떤 컨트롤러 코드를 실행할지 정의한다. 

 

 

MVC 흐름

크게보면 Model은 데이터에 관련된 행위들만 담당하고, View는 사용자에게 보여주는 화면(UI), Controller는 Model 과  View사이를 이어주는 인터페이스 역할을 한다. Model이 데이터를 어떻게 처리할지 알려주는 역할을 한다고 보면된다. 

 

MVC 구동원리

Browser(사용자)가 웹 서버에 웹 어플리케이션 실행을 요청한다. 그럼 DB로부터 필요한 데이터를 받은 Model객체를 Controller를 통해 View에 담아 응답을 보낸다.

 

 

MVC의 장점

 - 기능별로 코드를 분리하기 때문에 하나의 파일에 코드가 모이는것을 방지한다. 따라서 가독성과 코드의 재사용이 증가한다.

 - 유지보수가 용이하다.

 - 각 구성요소들을 독립시켜 협업을 할 때 맡은 부분의 개발에만 집중할 수 있기 때문에  개발의 효율성을 높여준다.

 

 

MVC의 단점

 - 완벽한 의존성 분리가 어렵다. 모델과 뷰사이에 컨트롤러를 통해서 소통을 이루기 때문에 의존성이 완전히 분리 될 수 없기 때문이다. 

 - 설계 단계가 복잡하며 설계 시간이 오래 걸린다. 

 

 

 

 

---강의바탕예시들 ---

controllers

router.get('/add-product', (req, res, next) => {
  res.render('add-product', {
    pageTitle: 'Add Product',
    path: '/admin/add-product',
    formsCSS: true,
    productCSS: true,
    activeAddProduct: true
  });
});

mvc 구조를 배우기 전에도 router로 위와같은 미들웨어 함수들을 사용한다. 이것도 전형적인 컨트롤러 논리라고 볼수 있다. 한줄뿐이지만 데이터와 교류하고 있고, 뷰를 반환하는것이 컨트롤러를 구성하는 in-between logic이다. 

그렇지만  routes 파일에 모든것을 넣으면 큰 파일이 되므로 여러파일에 넣어야한다. 

 

<admin.js> 

: 컨트롤러에 추가한 routes를 불러오기 위함.

const productsController = require('../controllers/products')

router.get('/add-product', productsController.getAddProduct);

router.get(''~, productsController.getAddProduct); 은 express 라우터에 함수를 저장하라고 알려주는것이다. 

 

<controllers(folder) - products.js>

: 제품컨트롤러 파일에서 함수 내보내기를 하기위해 exprots를 사용.  그리고 이름은 직관적으로 getAddProduct라고 지어준다. 내맘임

exports.getAddProduct = (req, res, next) => {
    res.render('add-product', {
      pageTitle: 'Add Product',
      path: '/admin/add-product',
      formsCSS: true,
      productCSS: true,
      activeAddProduct: true
    });
  }

 

 

 

Model

모델의 형태는 전적으로 내가 원하는대로 정의할 수 있다. 

module.exports = function Product(){
}

예를 들면 위와같이 constructor function을 exports할 수 있다. 

혹은 ES5 constructor function을 이용하여 호출한뒤 새로운 객체들을 생성할 수 있다. ES6라면 class를 생성할 수 도있다.  

module.exports = class Product { 
}

 

module.exports = class Product{
    //constructor의 title은 아래 인수와 같이 맞출필요없고 t라고 해줘도 된다. 
    constructor(title) {
        this.title = title;
    }
}

 

 

controller의 products.js에서 새로운 상수인 Product를 추가하여 클래스를 임포트한다. 이름은 자유롭게 설정가능하지만, 통상적으로 클래스에 해당하는 경우는 첫글자로 대문자를 사용한다. 

const Product = require('../models/product')

 

 

postAddproduct에서 Product 상수와 동일하게 생성해준다. 그리고 그안에 req.body.title을 전달하면 제출된 입력값의 이름으로 아래 적힌 title을 가져가게 된다. (그 title은 view안에있는 add-product.ejs에 있는 title)

controllers/product

 

add-product.ejs