모델-뷰-컨트롤러(MVC) 패턴은 스위프트 이전에 등장한 고전적인 아키텍처 패턴으로, 데이터, 사용자 인터페이스 및 제어 논리를 분리하는 데 사용됩니다. iOS 개발 역사에서 Apple은 Objective-C 및 Swift 애플리케이션 구축을 위한 주요 아키텍처 패턴으로 MVC를 선언했습니다.
표준 MVC의 주요 문제는 시간이 지남에 따라 컨트롤러가 "대규모 뷰 컨트롤러(Massive View Controller)"가 되어, 비즈니스 로직, 모델과의 상호작용, 사용자 입력 처리 및 심지어 표시 로직까지 통합하게 됩니다. 이로 인해 코드의 가독성, 재사용성 및 테스트 가능성이 낮아집니다.
스위프트에서 MVC는 컨트롤러로 UIViewController 클래스를 사용하고, 모델은 구조체 또는 클래스로, UIView는 인터페이스 구축에 사용됩니다. 컨트롤러는 모델과 뷰를 연결하여 데이터 변경 시 인터페이스 업데이트를 시작합니다.
코드 예제:
struct User { let name: String let age: Int } class UserView: UIView { let nameLabel = UILabel() func display(user: User) { nameLabel.text = "\(user.name), \(user.age)세" } } class UserController: UIViewController { var user: User? var userView: UserView! override func loadView() { userView = UserView() view = userView } override func viewDidLoad() { super.viewDidLoad() if let user = user { userView.display(user: user) } } }
주요 특징:
MVC에서 뷰와 모델 간의 직접적인 의존성을 허용할 수 있나요?
아니요, 뷰는 모델과 직접적으로 상호작용해서는 안 됩니다. 모든 통신은 오직 컨트롤러를 통해 이루어져야 하며, 그렇지 않으면 모델이 뷰에 대해 "알게" 되어 책임 분리 원칙이 위반되고 확장성이 저해됩니다.
컨트롤러가 데이터와 비즈니스 로직을 포함할 수 있나요?
컨트롤러가 비즈니스 로직을 포함할 수 있다는 오해가 자주 발생합니다. 사실, 비즈니스 로직은 모델이나 별도의 서비스로 옮기는 것이 좋으며, 컨트롤러는 오직 뷰의 생명주기 관리와 데이터 조정만 담당해야 합니다.
대규모 컨트롤러(Massive View Controller) 문제를 어떻게 해결할까요?
대규모 컨트롤러 문제를 해결하기 위해 데이터 처리를 컨트롤러에서 모델이나 서비스로 이동하고, 델리게이트, 위임 패턴 및 조합을 사용하십시오. 뷰 설정을 위한 별도의 클래스를 만들거나 표시 로직을 뷰에 직접 넣으십시오.
프로젝트에서 컨트롤러는 사용자 데이터, 처리 및 표시 코드를 모두 포함하고 있었습니다. 다른 컨트롤러에서 로직을 재사용하는 것이 불가능했고, 비즈니스 로직 테스트가 매우 어려웠습니다.
장점:
단점:
모델은 데이터와 비즈니스 로직만 담당하고, 뷰는 인터페이스를 그리며, 컨트롤러는 이들을 연결합니다. 구성 요소를 재사용하고, 테스트 및 애플리케이션을 더 빠르게 확장할 수 있는 가능성이 생겼습니다.
장점:
단점: