아키텍처 패턴

Ahyeon, Jung·2023년 12월 24일
0
post-custom-banner

MVC, MVVM, MVP

MVC(Model-View-Controller)

  • Model: 데이터와 비즈니스 로직을 관리
  • View: 사용자에게 표시되는 인터페이스를 담당
  • Controller: 모델과 뷰 간의 상호 작용을 조정하고 사용자 입력을 처리
    MVC는 각 구성 요소가 서로 독립적이어야 하며, 모델과 뷰 간에 직접적인 연결이 없어야함
    사용자 입력에 대한 응답으로 컨트롤러가 동작하며, 모델이 엄데이트되면 뷰가 갱신됨
    일반적으로 html, css를 View, 컨트롤러를 js, 백에서 받아온 데이터를 Model로 생각
// 데이터와 비즈니스 로직을 담당하는 View
class UserModel {
  constructor(name) {
    this.name = name;
  }

  updateName(newName) {
    this.name = newName;
  }
}
// 사용자에게 표시되는 인터페이스를 담당하는 View
class UserView {
  render(user) {
    console.log(`사용자 이름: ${user.name}`);
  }
}
class UserController {
  constructor(model, view) {
    this.model = model;
    this.view = view;
  }

  handleNameChange(newName) {
    this.model.updateName(newName);
    this.view.render(this.model);
  }
}

MVVM(Model-View-ViewModel)

  • Model: 데이터와 비즈니스 로직을 관리
  • View: 사용자에게 표시되는 인터페이스를 담당
  • ViewModel: 뷰를 표현하기 위한 뷰의 상태와 행동을 캡슐화하고, 뷰와 모델간의 통신을 중계
    데이터 바인딩을 사용하여 뷰모델과 뷰 간에 간단한 통신을 가능하게 함
    뷰모델은 주로 사용자 인터페이스의 상태를 유지하고 뷰에서 모델로의 변환 작업을 처리
// 뷰를 표현하기 위한 상태와 행동을 캡슐화하는 View Model
class UserViewModel {
  constructor(model) {
    this.model = model;
  }

  get name() {
    return this.model.name;
  }

  set name(newName) {
    this.model.updateName(newName);
  }
}

MVP(Model-View-Presenter)

  • Model: 데이터와 비즈니스 로직을 관리
  • View: 사용자에게 표시되는 인터페이스를 담당
  • Presenter: 뷰와 모델 간의 중간 매개체. 사용자 입력을 처리하고 모델에서 데이터를 가져와 뷰에 업데이트하는 역할
    뷰와 모델 간의 직접적인 연결을 피하면서 프레젠터를 통해 중재하도록 설계. 사용자 입력에 대한 로직은 프레젠터에서 처리되고, 뷰는 단순히 사용자 인터페이스를 표시하는 역할만 수행
// 뷰와 모델 간의 중간 매개체로 동작하며 사용자 입력을 처리하고 모델에서 데이터를 가져와 뷰에 업데이트하는 Presenter
class UserPresenter {
  constructor(model, view) {
    this.model = model;
    this.view = view;
  }

  handleNameChange(newName) {
    this.model.updateName(newName);
    this.view.render(this.model.name);
  }
}

Controller, View Model, Presenter

Controller

사용자 입력을 감지하고 모델과 뷰를 업데이트하는 역할
사용자 입력을 처리하고 모델과 뷰 간의 상호 작용을 조정하는 것이 주된 목적

  • 사용자의 액션을 감지하고 이에 대한 응답을 결정
  • 모델의 업데이트를 담당하고, 모델이 변경되었을 때 뷰를 업데이트
  • 일반적으로 컨트롤러와 뷰는 직접적으로 통신

ViewModel

뷰에 필요한 데이터를 제공하고, 뷰와 모델 사이의 중간 매개체 역할
뷰를 표현하기 위한 상태와 행동을 캡슐화하여 뷰와 모델 간의 결합을 완화하는 것이 주된 목적

  • View를 표현하기 위한 데이터를 제공
  • 사용자 인터페이스의 상태와 동작을 캡슐화하고, 뷰에 바인딩되어있는 데이터를 조작
  • 주로 양방향 데이터 바인딩을 통해 뷰와 자동으로 동기화

Presenter

사용자의 입력을 처리하고, 모델과 뷰 간의 중개자 역할
뷰와 모델 간의 결합을 느슨하게 유지하면서 사용자 입력을 처리하고 뷰를 업데이트하는 것이 주된 목적

  • 사용자 입력을 처리하고, 이에 대한 응답으로 모델을 업데이트하며 뷰를 업데이트
  • 뷰와 모델 간의 직접적인 의존성을 피하기 위해 중간 역할을 수행
  • MVP 패턴에서는 일반적으로 뷰와 모델 사이의 인터페이스 역할

다시보기

MVC


1. 사용자의 action이 Controller로 들어온다.
2. Controller는 사용자의 action을 확인하고, Model을 업데이트
3. Controller는 Model을 나타내줄 View를 선택
4. View는 Model을 이용하여 화면을 나타냄

Controller가 Model을 업데이트하고 View를 선택하면 View가 Model을 나타냄
View와 Model 사이의 의존성이 높아 어플이케이션이 커질 수록 복잡하고 유지보수가 어려움

/src
  /components
    UserView.js
    UserController.js
  /models
    UserModel.js
  /views
    App.js
import React from 'react';
import UserModel from '../models/UserModel';
import UserView from '../components/UserView';

class UserController extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      user: new UserModel('Ahhyeon'),
    };
  }

  handleNameChange = (newName) => {
    this.state.user.updateName(newName);
    this.forceUpdate();
  }

  render() {
    return (
      <div>
        <UserView user={this.state.user} />
        <button onClick={() => this.handleNameChange('Ahyeon')}>Change Name</button>
      </div>
    );
  }
}

export default UserController;

MVVM

  1. 사용자의 action이 View를 통해 들어옴
  2. View에 action이 들어오면, 캡슐화하여 View Model에 Action을 전달
  3. View Model은 Model에게 데이터를 요청
  4. Model은 View Model에게 요청받은 데이터를 응답
  5. View Model은 응답받은 데이터를 가공하여 저장
  6. View는 View Model과 Data Binding하여 화면을 나타냄

View와 Model의 의존성이 없음
캡슐화와 양방향 바인딩을 통해 View와 View Model의 의존성이 없음
각각의 부분이 독립적이기 때문에 모듈화하여 개발 가능

/src
  /components
    UserView.js
    UserViewModel.js
  /models
    UserModel.js
  /views
    App.js
// View
import React from 'react';

class UserView extends React.Component {
  render() {
    // 양방향 바인딩
    return <div>User Name: {this.props.userViewModel.name}</div>;
  }
}

export default UserView;

// View Model
import React from 'react';
import UserModel from '../models/UserModel';

class UserViewModel extends React.Component {
  constructor(model) {
    super();
    this.model = model;
  }

  get name() {
    return this.model.name;
  }

  set name(newName) {
    this.model.updateName(newName);
  }
}

export default UserViewModel;

MVP

  1. 사용자의 action이 View를 통해 들어옴
  2. View는 Presenter에게 데이터를 요청
  3. Presenter는 Model에게 데이터를 요청
  4. Model은 Presenter에서 요청받은 데이터를 응답
  5. Presenter는 View에게 데이터를 응답
  6. View는 Presenter가 응답한 데이터를 이용하여 화면을 나타냄
import React from 'react';
import UserModel from '../models/UserModel';
import UserView from '../components/UserView';

class UserPresenter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      user: new UserModel('John Doe'),
    };
  }

  handleNameChange = (newName) => {
    this.state.user.updateName(newName);  // View Model을 업데이트
    this.forceUpdate();
  }

  render() {
    return (
      <div>
        // View에 전달 
        <UserView userName={this.state.user.name} />
        <button onClick={() => this.handleNameChange('Ahyeon')}>Change Name</button>
      </div>
    );
  }
}

export default UserPresenter;

그 외의 패턴

Flux 패턴

단방향 데이터 흐름을 유지하여 상태 관리를 간소화하는 데 중점을 둔 패턴

  • Action: 사용자 또는 시스템 이벤트
  • Dispatcher: 액션을 받아 상태를 변경하고, 등록된 스토어에 변경 사항을 전파
  • Store: 애플리케이션의 상태를 저장하고 변경된 상태를 뷰에 전달
  • View: 사용자 인터페이스를 표시하고, 스토어의 데이터를 표시

Redux 패턴

Flux 패턴을 기반으로 하되, 단순한 구조와 불변성을 강조하여 상태관리를 효과적으로 처리하는 데 중점을 둔 패턴

  • Action: 상태 변경을 설명하는 객체
  • Reducer: 현재 상태와 액션을 받아 새로운 상태를 반환
  • Store: 애플리케이션의 상태를 저장하고, 리듀서를 통해 상태를 변경
  • View: 상태를 표시하고, 스토어의 상태 변경을 구독하여 업데이트

Singleton 패턴

어플리케이션 전반에서 단일 객체 인스턴스만을 생성하고 이에 접근하는 패턴

Observer 패턴

객체 간 일대다 의존성을 정의하여 한 객체의 상태가 변경되면 종속 객체에 자동으로 알릴 수 있게 하는 패턴

profile
https://a-honey.tistory.com/
post-custom-banner

0개의 댓글