Team-TrackUs / study

2 stars 0 forks source link

[Study] 프로젝트에 MVVM 패턴 적용하기 #3

Open sooohi opened 5 months ago

sooohi commented 5 months ago

MVVM 패턴 공부 한 내용 업로드

기한 : 1월 18일 13시까지

sooohi commented 5 months ago

MVVM 패턴 Model + View + View Model MVVM 패턴

  1. 구조
  1. 동작

    • 사용자의 Action들은 View를 통해 들어
    • View에 Action이 들어오면, Command 패턴으로 View Model에 Action을 전달
    • View Model은 Model에게 데이터를 요청
    • Model은 View Model에게 요청 받은 데이터를 응답
    • View Model은 응답 받은 데이터를 가공하여 저장
    • View는 View Model과 Data Binding하여 UI를 갱신
  2. 특징

  1. 장점
  1. 단점

    • View Model 설계가 복잡
    • 데이터 바인딩으로 인한 메모리 소모가 있음
    • 복잡해질수록 ViewModel이 비대해짐
  2. ios 개발이 mvvm으로 넘어가는 이유

    • SwiftUI에서는 View가 Viewmodel을 소유하고, Viewmodel이 Model을 소유하여 구조적인 개선이 이루어짐
    • ViewController가 View, Model의 역할까지 담당하는 UIKit 단점을 극복
    • 모듈화로 인한 테스트가 편리해짐
  3. Data Binding, Command

    • Data Binding : Model고 UI 요소 간의 싱크를 맞추는 패턴. View와 로직이 분리되어 잇어도 한 쪽이 바뀌면 다른 쪽도 업데이트가 이루어져 데이터의 일관성을 유지할 수 있음
    • Command : 여러가지 요소에 대한 처리를 하나의 액션으로 처리할 수 있게 하는 기법
Teoler commented 5 months ago

MVC는 Model, View, Controller로 구성되어있다.

간단히 말하면 사람들 눈에 직접보이는 뷰위 모델이 있고 컨트롤러가 두 뷰의 데이터신호를 관리한다.

-그럼MVVM이란 무엇일까? MVC에서 C가 ViewModel로 바뀐것이다. 뷰 모델은 뷰가 데이터 바인딩되는 속성또는 명령을 구현하며 뷰의 상태변경을 알리는 역할을 한다.

-MVVM

다운로드

View: 화면에 표시되는 구조, 레이아웃 및 모양을 정의

Model: 데이터를 가져오거나 저장하는 역할

ViewModel: 중재자 역할을 하면서 뷰가 데이터 바인딩될 수 있는 속성 및 명령을 구현

-MVVM 동작과정

1.사용자의 Action들은 View를 통해 들어옵니다. 2.View에 Action이 들어오면 ViewModel에 Action을 전달합니다. 3.ViewModel은 Model에게 데이터를 요청합니다. 4.Model은 ViewModel에게 요청받은 데이터를 응답합니다. 5.ViewModel은 응답 받은 데이터를 가공하여 저장합니다. 6.View는 Data Binding을 이용해 UI를 갱신시킵니다.

-MVVM 특징

View : ViewModel = 1 : n

관계로 되어있고 데이터 바인딩을 이용하면 의존성을 줄일 수 있는 장점이 있다.

-써야하는이유?

의존성이 적다(뷰와 뷰모델 사이를 데이터 바인딩하기 때문)

코드재사용가능(중복되는 부분을 모듈화해서 여러 뷰에 가져다 쓸수 있음)

Wegbereiterin commented 5 months ago

MVVM 아키텍쳐 정리

Model: 데이터 구조 그 자체 ViewModel: 비즈니스 로직 모음집 View: UI 모음집

마치 디자이너와 개발자가 나뉘어 있는 것 처럼

View는 UI만 집중하여 상호작용 이벤트를 처리하고, 이를 ViewModel에 전달하여 해당 동작에 대한 비즈니스 로직을 실행 ViewModel은 데이터 가져오기, 변환, 가공, 상태관리 등의 작업을 수행하고 이러한 로직을 통해 View에 표시할 데이터를 적절히 가공하여 제공한다.

예시 1)

Model 모델

스크린샷 2024-01-18 오전 9 51 57

사용할 데이터를 정의

View 뷰

스크린샷 2024-01-18 오전 9 53 09

UI만 집중하여 로직, 함수가 필요한 경우 ViewModel의 함수를 호출하여 사용한다.

ViewModel 뷰모델

스크린샷 2024-01-18 오전 9 52 23

View에서 사용할 함수가 정의 되어있다.

예시 2)

모델

스크린샷 2024-01-18 오전 9 39 28

스크린샷 2024-01-18 오전 9 40 27

뷰모델

스크린샷 2024-01-18 오전 9 39 43

트랙어스 파일에서 View와 ViewModel을 나누어 놓았습니다. 각자 View에서 필요한 로직을 ViewModel에 정의하여 사용하면 좋을 것 같습니다..! 스크린샷 2024-01-18 오전 10 08 15

Wegbereiterin commented 5 months ago

MVVM 패턴 Model + View + View Model MVVM 패턴

  1. 구조
  • Model : 데이터를 다루는 부분. 화면을 표현하는데 필요한 데이터를 관리하며, 사용자가 입력한 데이터를 저장하거나 서버로 받은 데이터를 저장
  • View : 사용자에게 보여지는 UI 부분. 사용자가 화면에서 보는 것들에 대한 구조 배치와 같이 외관에 해당
  • View Model : View를 표현하기 위해 만들어진 View를 위한 Model. View에서 발생하는 이벤트를 감지하고, 해당 이벤트에 맞는 비즈니스 로직을 수행.
  1. 동작
  • 사용자의 Action들은 View를 통해 들어�
  • View에 Action이 들어오면, Command 패턴으로 View Model에 Action을 전달
  • View Model은 Model에게 데이터를 요청
  • Model은 View Model에게 요청 받은 데이터를 응답
  • View Model은 응답 받은 데이터를 가공하여 저장
  • View는 View Model과 Data Binding하여 UI를 갱신
  1. 특징
  • Command 패턴과 Data Binding 두 가지 패턴을 사용하여 구현
  • View와 View Model 사이 의존성을 없앰
  • View Model과 View는 1:n 관계
  1. 장점
  • View와 Moel 사이 의존성이 없어 독립성을 유지할 수 있음
  • 독립성 유지하기 때문에 효율적인 유닛 테스트가 가능
  • View와 ViewModel이 1:n 관계이기 때문에 중복되는 로직을 모듈화 하여 개발할 수 있음(코드 재사용이 가능)
  1. 단점
  • View Model 설계가 복잡
  • 데이터 바인딩으로 인한 메모리 소모가 있음
  • 복잡해질수록 ViewModel이 비대해짐
  1. ios 개발이 mvvm으로 넘어가는 이유
  • SwiftUI에서는 View가 Viewmodel을 소유하고, Viewmodel이 Model을 소유하여 구조적인 개선이 이루어짐
  • ViewController가 View, Model의 역할까지 담당하는 UIKit 단점을 극복
  • 모듈화로 인한 테스트가 편리해짐
  1. Data Binding, Command
  • Data Binding : Model고 UI 요소 간의 싱크를 맞추는 패턴. View와 로직이 분리되어 잇어도 한 쪽이 바뀌면 다른 쪽도 업데이트가 이루어져 데이터의 일관성을 유지할 수 있음
  • Command : 여러가지 요소에 대한 처리를 하나의 액션으로 처리할 수 있게 하는 기법

헷갈리는게 하나 있습니다 ViewModel과 View의 관계가

View : ViewModel = 1 : n ViewModel : View = 1 : n

둘 중 어떤 것 인가욤?

Seokki-Kwon commented 5 months ago

viewModel이 n이 맞지않을까요? 왜냐면 viewModel은 view를 알지못한다는게 특정 view에 대한 종속성이 없다는거라 일방적으로 viewModel을 끌어다쓰는 view가 1 viewModel이 n이지 않을까여(뇌피셜)

Wegbereiterin commented 5 months ago

viewModel이 n이 맞지않을까요? 왜냐면 viewModel은 view를 알지못한다는게 특정 view에 대한 종속성이 없다는거라 일방적으로 viewModel을 끌어다쓰는 view가 1 viewModel이 n이지 않을까여(뇌피셜)

오..

Seokki-Kwon commented 5 months ago

아닌것도 같습니다... 쳐보니깐 1:1이라는 말도 ㅋㅋ 머리아프네요

PinkSoju commented 5 months ago

mvvm 패턴 이미지

MVVM

MVVM 패턴은 다음과 같은 구성 요소

MVVM 패턴은 데이터 바인딩을 통해 View와 ViewModel을 연결하고, ViewModel과 Model을 연결하는 방식으로 동작

PinkSoju commented 5 months ago

SwiftUI 선언형 UI 구조에서 data flow가 양방향으로 이루어진 mvvm 패턴과 단방향으로 이루어진 다른 아키텍처의 사용에 대해서 어떻게 생각하시나요?

PinkSoju commented 5 months ago

SwiftUI에서 View는 자체적으로 Data Binding이 가능한 PropertyWrapper를 지원함.

SwiftUI에서는 뷰에서 데이터 바인딩을 통한 기능을 ViewModel에서 해주고 있지만

사실 View에서 @State 변수로 선언된 값은 모델값의 변경으로 인스턴스 값이 변경된다.

import SwiftUI

struct ContentView: View {
  @State var person = Person()

  var body: some View {
    Text(person.name)
  ...
  }
}

따라서 이미 SwiftUI에서는 View + ViewModel의 기능을 수행하고 있음.

생각보다 MVVM 패턴에 대해서 사람들의 인식이 바뀐 거 같아요. MVC, MVP 패턴에서 MVVM으로 당연하게 써오던 것들의 문제점과 단점들을 보완을 하는 TCA 같은 부분도 같이 공부하면 좋을 거 같습니다.

https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app https://green1229.tistory.com/267

Teoler commented 5 months ago

ViewModel과 View의 관계는 View가1 ViewModel이n라고 이해했습니다 주체를 누구로 보냐에 따라 달라지지만 보통 View를 주체로 보고 다수의 ViewModel에서 View로 코드를 재사용 하기 때문에 View가 여러ViewModel을 가져온다고 생각하면 될거같습니다. 다만 재사용성이 없는 코드에서는 1:1도 가능할거 같네요.

이런 경우도 있네요 ViewModel을 재사용하고, View형식이 같다면 View를 재사용하는 경우도 있기 때문에 M:N의 관계도 성립돼는군요 ㄷㄷ..

Seokki-Kwon commented 5 months ago

MVVM 패턴에 대한 기본적인 내용과 평소에 SwiftUI 에서 MVVM패턴을 이용하면서도 정확히 알지 못하거나 헷갈렸던 점들을 다시한번 정리해봤습니다.

MVVM 패턴이란?

디자인 패턴이란 개발을 할떄 조금더 효율적으로 또는 좋은 구조로 개발을 하기 위한 방법론? 약속? 같은 의미이다. 그 중에서도 MVVM 이라는 패턴에 대하여 이론적으로 한번 알아보고 토의하는 목적으로 작성

Screenshot 2024-01-18 at 10 30 01 AM

MVVM 의 종속성 관계는 다음과 같다.

반면에 ViewModel은 View를 소유하지 않고 Model 또한 View를 알지 못한다. 기존의 Cocoa MVC 에서는 ViewController가 view와 Model 모두를 소유하는 구조인 MVC 패턴과는 다른 구조를 가진다.

Screenshot 2024-01-18 at 10 38 05 AM

데이터 흐름은 다음과 같다. 예를들어 사용자가 인스타같은 소셜앱에서 좋아요를 누르는 기능을 생각해보자 좋아요를 누름(View) -> ViewModel(서버에 좋아요 처리 요청) -> ViewModel의 데이터가 변경됨 -> View에서 변경된 데이터 감지(좋아요 증가)

데이터 바인딩

데이터 바인딩 이라는 말이 데이터를 무언가 동기화 시킨다는 의미로 알고있지만 정확히 알지 못해서 정리. 데이터 바인딩이란 UI상의 데이터와 실제 메모리의 데이터를 일치시키는 기법을 말한다. 만약 버튼을 누르면 카운팅된 숫자를 보여주는 앱이 있다고 가정해보자 버튼을 눌러서 실제 메모리상의 데이터는 1이 증가된 값이 저장되었지만 화면상의 UI에 변화가 없다면 데이터 바인딩이 필요한 상황이라고 말할 수 있다.

그렇다면 단방향, 양방향 데이터 바인딩의 차이는 무엇일까? 단방향 데이터 바인딩이란 한쪽에서 변경이 일어날 때만 데이터가 업데이트 되는 방식이다. HTML(View) 와 JS(Model)이 있다고 가정할때 단방향의 경우 JS(Model)에서 데이터를 변경하여 HTML(View)가 변경된다 HTML->JS 불가능

반면 양방향 데이터 바인딩의 경우 HTML -> JS가 가능하게 된다 양방향 데이터 바인딩은 프레임워크에서 감지하고 있다가 데이터가 변경되는 시점에 View를 리렌더 해준다.

SwiftUI와 Combine

ViewModel 클래스에 @Published, @ObservableObject 와 같은 프로퍼티 래퍼들은 Combine 프레임워크에 구현이 되어있다. Combine이란 시간에 흐름에 따라 발생하는 이벤트를 처리하기 위한 프레임워크이며 이미 Apple의 여러 프레임워크가 Combine기반으로 구현되어 있다. 또한 System Level에 구현이 되어있기 때문에 사용할 수 있는 기능이 많다고 한다. 우선 SwiftUI 와 Combine의 상성이 좋으며 우리가 사용하는 @Published, ObservableObject 등등은 Combine 이라는 프레임워크에 선언이 되어있으며 SwiftUI 에서도 Combine을 import 한다.

레퍼런스

데이터 바인딩의 이해 [Swift] Combine 입문가하기1 — 구성요소

Choe-ju commented 5 months ago

MVVM (Model-View-ViewModel)

MVVM 패턴은 Model, View, ViewModel 세 가지 요소로 구성된 패턴

  1. 분리된 역할: 각 컴포넌트가 독립적으로 작동하므로 코드가 모듈화되어 각 부분을 개별적으로 테스트하고 변경 가능
  2. 테스트 용이성: 뷰 모델은 비즈니스 로직을 포함하며, 뷰와 모델은 주로 UI 및 데이터 관리에 집중해 뷰 모델을 테스트하기 쉬움
  3. 재사용성: 뷰 모델은 뷰에 대한 종속성이 없으므로 여러 뷰에서 재사용 가능
  4. 반응형 프로그래밍과의 통합: MVVM은 반응형 프로그래밍 패러다임과 자연스럽게 통합되어 상태 변화에 따라 UI를 업데이트 용이

장단점

장점

단점

Model: 데이터 및 데이터 조작 로직 처리

struct User {
    var username: String
    var email: String
}

ViewModel : view를 표현하기 위한 로직 관련

import SwiftUI
import Combine

class UserViewModel: ObservableObject {
    @Published var user: User

    init(user: User) {
        self.user = user
    }

    func updateUser(username: String, email: String) {
        user.username = username
        user.email = email
    }
}

View : UI부분

import SwiftUI
import Combine

struct UserView: View {
    @ObservedObject var viewModel: UserViewModel

    var body: some View {
        VStack {
            TextField("Username", text: $viewModel.user.username)
                .padding()

            TextField("Email", text: $viewModel.user.email)
                .padding()

            Button("Update") {
                viewModel.updateUser(username: "viewModel.user.username", email: "viewModel.user.email")
            }
            .padding()
        }
    }
}

struct ContentView: View {
    let user = User(username: "JohnDoe", email: "john@example.com")
    let viewModel: UserViewModel

    init() {
        viewModel = UserViewModel(user: user)
    }

    var body: some View {
        UserView(viewModel: viewModel)
    }
}
Seokki-Kwon commented 5 months ago

MVVM 패턴 Model + View + View Model MVVM 패턴

  1. 구조
  • Model : 데이터를 다루는 부분. 화면을 표현하는데 필요한 데이터를 관리하며, 사용자가 입력한 데이터를 저장하거나 서버로 받은 데이터를 저장
  • View : 사용자에게 보여지는 UI 부분. 사용자가 화면에서 보는 것들에 대한 구조 배치와 같이 외관에 해당
  • View Model : View를 표현하기 위해 만들어진 View를 위한 Model. View에서 발생하는 이벤트를 감지하고, 해당 이벤트에 맞는 비즈니스 로직을 수행.
  1. 동작
  • 사용자의 Action들은 View를 통해 들어�
  • View에 Action이 들어오면, Command 패턴으로 View Model에 Action을 전달
  • View Model은 Model에게 데이터를 요청
  • Model은 View Model에게 요청 받은 데이터를 응답
  • View Model은 응답 받은 데이터를 가공하여 저장
  • View는 View Model과 Data Binding하여 UI를 갱신
  1. 특징
  • Command 패턴과 Data Binding 두 가지 패턴을 사용하여 구현
  • View와 View Model 사이 의존성을 없앰
  • View Model과 View는 1:n 관계
  1. 장점
  • View와 Moel 사이 의존성이 없어 독립성을 유지할 수 있음
  • 독립성 유지하기 때문에 효율적인 유닛 테스트가 가능
  • View와 ViewModel이 1:n 관계이기 때문에 중복되는 로직을 모듈화 하여 개발할 수 있음(코드 재사용이 가능)
  1. 단점
  • View Model 설계가 복잡
  • 데이터 바인딩으로 인한 메모리 소모가 있음
  • 복잡해질수록 ViewModel이 비대해짐
  1. ios 개발이 mvvm으로 넘어가는 이유
  • SwiftUI에서는 View가 Viewmodel을 소유하고, Viewmodel이 Model을 소유하여 구조적인 개선이 이루어짐
  • ViewController가 View, Model의 역할까지 담당하는 UIKit 단점을 극복
  • 모듈화로 인한 테스트가 편리해짐
  1. Data Binding, Command
  • Data Binding : Model고 UI 요소 간의 싱크를 맞추는 패턴. View와 로직이 분리되어 잇어도 한 쪽이 바뀌면 다른 쪽도 업데이트가 이루어져 데이터의 일관성을 유지할 수 있음
  • Command : 여러가지 요소에 대한 처리를 하나의 액션으로 처리할 수 있게 하는 기법

Command 패턴이 뭔가용 알려주세요 해주세요 @sooohi

sooohi commented 5 months ago

MVVM 패턴 Model + View + View Model MVVM 패턴

  1. 구조
  • Model : 데이터를 다루는 부분. 화면을 표현하는데 필요한 데이터를 관리하며, 사용자가 입력한 데이터를 저장하거나 서버로 받은 데이터를 저장
  • View : 사용자에게 보여지는 UI 부분. 사용자가 화면에서 보는 것들에 대한 구조 배치와 같이 외관에 해당
  • View Model : View를 표현하기 위해 만들어진 View를 위한 Model. View에서 발생하는 이벤트를 감지하고, 해당 이벤트에 맞는 비즈니스 로직을 수행.
  1. 동작
  • 사용자의 Action들은 View를 통해 들어�
  • View에 Action이 들어오면, Command 패턴으로 View Model에 Action을 전달
  • View Model은 Model에게 데이터를 요청
  • Model은 View Model에게 요청 받은 데이터를 응답
  • View Model은 응답 받은 데이터를 가공하여 저장
  • View는 View Model과 Data Binding하여 UI를 갱신
  1. 특징
  • Command 패턴과 Data Binding 두 가지 패턴을 사용하여 구현
  • View와 View Model 사이 의존성을 없앰
  • View Model과 View는 1:n 관계
  1. 장점
  • View와 Moel 사이 의존성이 없어 독립성을 유지할 수 있음
  • 독립성 유지하기 때문에 효율적인 유닛 테스트가 가능
  • View와 ViewModel이 1:n 관계이기 때문에 중복되는 로직을 모듈화 하여 개발할 수 있음(코드 재사용이 가능)
  1. 단점
  • View Model 설계가 복잡
  • 데이터 바인딩으로 인한 메모리 소모가 있음
  • 복잡해질수록 ViewModel이 비대해짐
  1. ios 개발이 mvvm으로 넘어가는 이유
  • SwiftUI에서는 View가 Viewmodel을 소유하고, Viewmodel이 Model을 소유하여 구조적인 개선이 이루어짐
  • ViewController가 View, Model의 역할까지 담당하는 UIKit 단점을 극복
  • 모듈화로 인한 테스트가 편리해짐
  1. Data Binding, Command
  • Data Binding : Model고 UI 요소 간의 싱크를 맞추는 패턴. View와 로직이 분리되어 잇어도 한 쪽이 바뀌면 다른 쪽도 업데이트가 이루어져 데이터의 일관성을 유지할 수 있음
  • Command : 여러가지 요소에 대한 처리를 하나의 액션으로 처리할 수 있게 하는 기법

Command 패턴이 뭔가용 알려주세요 해주세요 @sooohi


Command는 UI에서 발생하는 작업을 캡슐화하고, 나중에 실행할 수 있도록 하는 객체입니다. MVVM패턴에서 Command는 주로 ViewModel에 의해 구현되며 아래 세 가지 주요 부분으로 구성됩니다.

요청하신 예시는 아래 코드로 드리겠습니다!

  1. Command 클래스 또는 인터페이스 : 이벤트를 처리하는데 사용되는 명령을 나타냄.

    Command 클래스

    public interface ICommand
    {
    void Execute();
    }
  2. Command 구현체 : Command 클래스 또는 인터페이스의 실제 구현

    Command 구현체

    public class SaveCommand : ICommand
    {
    private ViewModel viewModel;
    
    public SaveCommand(ViewModel vm)
    {
        viewModel = vm;
    }
    
    public void Execute()
    {
        viewModel.SaveData();
    }
    }
  3. Command 트리거 하는 객체 : 버튼이나 다른 사용자 이벤트가 해당 Command를 실행

    Command를 트리거하는 객체

    public class SaveButton
    {
    private ICommand saveCommand;
    
    public SaveButton(ICommand command)
    {
        saveCommand = command;
    }
    
    public void Click()
    {
        // 사용자가 버튼을 클릭하면 연결된 Command의 Execute 메서드를 호출합니다.
        saveCommand.Execute();
    }
    }

버튼 클릭과 Command 연결하기

// ViewModel을 생성합니다.
ViewModel myViewModel = new ViewModel();

// SaveCommand를 생성하고 ViewModel을 주입합니다.
SaveCommand saveCommand = new SaveCommand(myViewModel);

// SaveButton을 생성하고 SaveCommand를 연결합니다.
SaveButton saveButton = new SaveButton(saveCommand);

// 사용자가 버튼을 클릭하면 연결된 SaveCommand의 Execute 메서드가 호출됩니다.
saveButton.Click();

부족한 부분이나 틀린 부분 언제든지 말해주세욤...! @Seokki-Kwon