[iOS] MVC, MVVM Architecture Pattern

nnnyeong·2021년 7월 29일
0

iOS

목록 보기
3/17

근무중 view controller 가 너무너무 비대해 지는 걸 느꼈다ㅜ
이런 저런 이유로 화면 만드는 것도 코드로 하는게 이젠 더 편한터라 거의 모든 양의 코드가 VC 안에 미친듯이 들어가있는 모습이닼ㅋㅋㅋ

아키텍쳐 수정이 필요하려나 싶어서 iOS MVC 패턴 개선 방법을 찾아보았고
MVC(massive view controller..ㅋㅋ) 를 개선시킬만한 MVVM 아키텍처 패턴에 대해 공부해보았다!




MVC

그 전에 iOS 개발의 기본적인 아키텍처인 MVC 에 대해 알아보자!
MVC 는 Model - View - Controller 를 나타낸다. 스토리보드에서 화면을 짜고 서버나 로컬 DB 에서 받아온 데이터를 이리 저리 알맞게 다듬어 view controller 에서 storyboard 에 연결된 label, imageview 등에 적용시키는 작업을 해봤다면 이 패턴의 구조를 쉽게 이해할 수 있을 것이다.
나 역시 그렇고, 사실 고백하자면 MVC 이외의 패턴으로 앱을 설계해본적이 있나 싶다 ㅎ,,

MVC에선 ViewModel 사이에서 Controller가 양쪽을 모두 업데이트 한다. View 그저 화면에 요소를 나타내기만 하고, Model 은 앱에서 사용되는 데이터를 읽고 쓰는 역할만을 담당한다.

또한 View는 오로지 Controller에 의해서만 업데이트 되기에 ViewController가 매우 밀접하게 연결되어 있고
이러한 방식으로 동작하다보니 왠만한 일은 모두 Controller 에서 진행된다는 문제가 생긴다!

예를들면, 서버에서 받아온 json 데이터(model)를 디코딩 하여 파싱하고, 원하는 형태의 배열로 만들고, 이를 다시 뷰에 올리는 과정이나
사용자의 interaction 을 통해 들어온 정보들을 확인, 검사해서 model에 반영시키는 과정이라던가,

화면에 보이는 것과 데이터 이외에는 모두 View Controller 에서 진행되다보니 MVC 패턴을 Massive View Controller 라고 말할 지경이다.

앱이 조금만 커지게 되면 자연스레 이런 문제가 발생하게 되고, 나역시 근무 중에 한 VC 내에서 함수를 수정하려고 하면 도대체 이게 어디있나 싶어서 프로젝트 전체에 command+shift+F 를 달고 살았던 기억이 있다ㅋㅋ..

이러한 상황은 단순히 controller 가 커진다는 문제 뿐 아니라 테스트를 진행하기에도 어려워진다는 단점이 생긴다! (학생때는 몰랐지만, 개발을 하면 할 수록 테스팅이 참 중요하다는걸 많이 느낀다..!)




MVVM

이러한 MVC 패턴의 단점에 대한 대안으로 MVVM 패턴이 있고 MVVM은 Model- View - ViewModel 로 이루어져 있다.

  • Model은 다른 클래스들이 데이터 변경에 대한 notification을 보내지만이들과 직접 통신하지 않음
  • ViewModel은 Model과 통신하며 데이터로 View로 내보냄
  • ViewController는 View Life Cycle을 처리하고, 데이터를 UI 구성요소에 bind할 때만 View Model 및 View와 통신함

데이터를 관리하는 Model 에 변화가 생기면 이는 ViewModel 에게 자동으로 notify 되고, ViewModel 과 사전에 binding된 View가 업데이트 된다.

반대로 View로 어떠한 이벤트가 들어오면 이는 ViewModel에게 알려지고, 이를 감지한 ViewModel은 Model의 내용을 수정한다.

MVC 패턴에서와 다르게 ViewModel에는 UI와 관련된 정보가 전혀 포함되지 않고 View에 대해 아무것도 관여하지 않는다. View에 와 ViewModel에는 밀접하지 않아 View와 Controller 각각 유닛테스트가 가능해진다!!




Example

좀더 구체적인 예시가 필요한 것 같아 여러 포스팅을 참고해 간한 테이블 뷰로 구현 해 보았다!

사람의 이름, 나이, 신장을 테이블 뷰로 나타내고자 한다!
먼저 구조체 Person 을 정의하고, 이 Person 데이터를 관리하는 PersonViewModel 을 간단히 정의했다

import Foundation

struct Person {
    var name : String
    var age : Int
    var height : Double
}

struct PeopleModel {
    
    func getPeopleData() -> [Person] {
        return [
            Person(name: "Ed", age: 28, height: 178.2),
            Person(name: "Alex", age: 27, height: 163.5),
            Person(name: "Jake", age: 41, height: 172.0),
            Person(name: "June", age: 27, height: 164.3)
        ]
    }
}

class PeopleViewModel: NSObject {
    let model : PeopleModel = PeopleModel()
    let peopleData : [Person]!
    
    override init() {
        peopleData = model.getPeopleData()
    }
    
}

PeopleViewModel이 지금은 그저 여러 사람 데이터를 가지고 있을 뿐이지만 하지만, 새로운 사람을 추가할 수도 기존의 사람 데이터를 수정할 수도 있는 역할을 할 것이다.

storyboard 에선 간략히 prototype cell을 구성하고 연결 해 주었다!

PeopleViewController

import UIKit


class PeopleTableViewCell: UITableViewCell {
    
    @IBOutlet weak var blueLabel: UILabel!
    @IBOutlet weak var greenLabel: UILabel!
    @IBOutlet weak var orangeLabel: UILabel!
 
}


class PeopleTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var peopleTableView: UITableView!
    
    private let peopleViewModel = PeopleViewModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        peopleTableView.delegate = self
        peopleTableView.dataSource = self
        
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        peopleViewModel.peopleData.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "PeopleTableViewCell") as! PeopleTableViewCell
        
        cell.blueLabel.text = peopleViewModel.peopleData[indexPath.row].name
        cell.greenLabel.text = "\(peopleViewModel.peopleData[indexPath.row].age) 세"
        cell.orangeLabel.text = "\(peopleViewModel.peopleData[indexPath.row].height) cm"
        
        return cell
    }
}

MVC 패턴에서는 ViewController 가 데이터를 직접 가지고 있고, 이를 관리하였지만, MVVM 패턴에선 PeopleViewModel을 통해 접근만 할 뿐 데이터를 직접 관여하지는 않는 모습이다!

VC의 코드가 많이 줄어든 것을 느낄 수 있을 것이다! 데이터를 파싱한다거나, 저장한다거나, 하는 모든 과정은 PeopleViewModel에게 주어진다!

앱을 실행시켜보면,

의도한 대로 잘 나온다!



간단한 예를 통해 볼 때는 별 차이가 없어 보일 수 있지만, 거대해지는 VC를 생각하면 아주 유용하게 쓰일 수 있을 것 같다!
쉬는 동안 MVVM 패턴을 적용해서 앱을 설계 해 볼 생각이다!




RxSwift #4 — RxSwift 를 이용한 MVVM 패턴
[Design Pattern] iOS 디자인 패턴 1탄 (MVC/MVVM/VIPER/MVC-C/MVVM-C)
간단한 예제로 살펴보는 iOS Design/Architecture Pattern: MVVM
[Swift] MVC와 MVVM 패턴

profile
주니어 개발자까지 ☄️☄️

0개의 댓글