애플리케이션의 구조를 세 가지 역할로 분리해서 유지 보수성, 확장성을 올리는 디자인 패턴
MVC를 잘못 구현하면 Massive ViewController 문제에 직면할 수 있음 !!
데이터, 비즈니스 로직 담당
앱의 상태를 표현
UI와는 완전히 독립적
일반적으로 구조체 || 클래스로 구현
Codable, Equatable을 준수하는 경우 많음
ex)
struct User: Codable {
let id: Int
let name: String
let email: String
}
사용자에게 보여지는 UI 요소
데이터를 표시하고 입력을 받지만 직접적인 비즈니스 로직을 가지지 않음
상태를 갖지 않고 Controller의 명령에 따라 갱신
ex)
UILabel, UIButton, UITableView, UICollectionView 등 UIKit 컴포넌트
커스텀 뷰는 UIView를 서브클래싱
class ProfileView: UIView {
let nameLabel = UILabel()
// Layout 및 UI 설정
}
Model과 View를 연결하는 중개자 역할
사용자 입력 처리
비즈니스 로직의 일부를 갖는 경우도 많지만 MVC 위반이 될 수 있음
가장 복잡해질 가능성이 높은 부분
ex)
class ProfileViewController: UIViewController {
var user: User?
override func viewDidLoad() {
super.viewDidLoad()
loadUser()
}
func loadUser() {
// API or Model 호출
user = User(id: 1, name: "Doha", email: "doha@example.com")
updateUI()
}
func updateUI() {
profileView.nameLabel.text = user?.name
}
}
사용자 입력(View) → Controller로 전달
Controller가 입력을 처리하고 Model을 업데이트
Model의 변경 사항을 Controller가 감지하거나 호출해서 View를 업데이트
View는 Controller의 지시에 따라 UI를 재구성
모든 역할(View, Model, 비즈니스 로직)이 ViewController에 몰리면 복잡해짐
해결 :
→ Model은 정확히 분리하고
View는 UIView 서브클래스로 모듈화
비즈니스 로직은 Service, Manager, ViewModel 등으로 분리
View는 Controller를 참조하지 않아야 하고 delegate나 closure로 이벤트 전달
class LoginView: UIView {
var onLoginButtonTapped: (() -> Void)?
@objc func loginButtonPressed() {
onLoginButtonTapped?()
}
}
| 항목 | MVC | MVVM | VIPER |
|---|---|---|---|
| 복잡도 | 낮음 | 중간 | 높음 |
| 테스트 용이성 | 낮음 | 높음 | 매우 높음 |
| View와의 의존도 | 높음 | 낮음 | 매우 낮음 |
| 적합한 앱 규모 | 소형~중형 | 중형~대형 | 대형 |
한계 :
ViewController가 책임을 지게 되기 쉬움
컴포넌트 간 경계가 모호해지면 테스트, 유지보수 어려움
보완 :
ViewModel을 도입한 MVVM으로 진화
Service Layer, Network Layer 분리
MVP || VIPER로 확장 고려
| TIP | 설명 |
|---|---|
| DIP 적용 | Controller가 Model |
| Model은 순수해야 함 | UI나 네트워크 레이어에 의존하지 않도록 설계 |
| 뷰는 Dumb하게 | View는 Controller가 주는 데이터만 보여주는 구조로 구성 |
| Delegate & Closure 활용 | View ↔ Controller 간 통신은 느슨하게 구성 |
| 분리 가능한 UI는 UIView로 추출 | Cell, CustomView을 외부에서 주입받도록 설계 |
| 역할 | 책임 | 특징 |
|---|---|---|
| Model | 데이터, 상태 | 비즈니스 로직 담당, 테스트 용이 |
| View | UI, 사용자 입력 | Controller 지시만 수행 |
| Controller | 중개자 | 이벤트 처리 및 데이터 흐름 제어 |
MVC는 구조적 분리를 지키지 않으면 개발 속도와 유지 보수에 안 좋은 영향을 줌
MVC랑 밀접한 관련이 있는 아키텍처 패턴,
MVVM은 MVC의 한계랑 문제점을 보완하기 위해 발전된 형태
MVVM은 MVC를 기반으로 진화한 아키텍처 패턴이
둘 다 모델을 중심으로 데이터 흐름을 분리함
| 항목 | MVC | MVVM | 설명 |
|---|---|---|---|
| 구조 | Model - View - Controller | Model - View - ViewModel | 세 개의 책임 분리 |
| 목적 | 관심사 분리 | 관심사 명확한 분리 | |
| Model | 데이터, 비즈니스 로직 담당 | ||
| View | 사용자 인터페이스 담당 | ||
| 테스트 용이성 | 중간 | 높음 | Controller의 역할 분리도가 다름 |