🩵 아키텍처란?
아키텍처는 시스템 전체를 이해하고 설계하기 위한 체계적인 방법이며, 기본적으로 시스템의 구조와 조직을 결정하는 과정입니다.
다양한 측면에서 시스템을 분석하고 설계함으로써 특정 문제나 요구사항에 대한 효과적인 해결책을 찾아냅니다.
✔️ 구조 설계
- 아키텍처는 기본적으로 컴포넌트와 모듈의 구조를 결정합니다.
- 이는 각각의 역할과 책임을 명확히 정의하고, 이들이 어떻게 상호 작용하는지를 결정하는 과정을 포함합니다.
✔️ 상호 작용 및 데이터 흐름
- 컴포넌트 간의 상호 작용과 데이터의 흐름을 명확히 정리합니다.
- 이는 시스템의 효율성과 일관성을 유지하는 데 중요한 역할을 합니다.
✔️ 기능, 성능, 보안, 확장성, 유지보수성 고려
- 아키텍처는 시스템이 수행해야 하는 기능을 충족시키는 것뿐만 아니라,
- 성능, 보안, 확장성, 유지보수성 등과 같은 다양한 측면에서도 최적의 해결책을 제시합니다.
✔️ 시스템의 유연성과 확장성 고려
- 미래에 대비하여 시스템이 쉽게 변화하고 확장될 수 있도록 아키텍처를 설계합니다.
- 이는 기술의 변화나 추가적인 요구사항에 대응할 수 있도록 하는 것을 의미합니다.
✔️ 시스템 생명 주기 고려
- 아키텍처는 시스템의 전체 생명 주기를 고려하여 설계됩니다.
- 초기 개발 단계부터 유지보수 및 업그레이드 단계까지의 효과적인 관리가 가능하도록 구성됩니다.
아키텍처의 목적은 시스템을 효과적으로 구축하고 유지보수할 수 있는 설계도를 제공하는 것이며,
이를 통해 안정성과 성능을 극대화하며 시스템을 지속적으로 향상시킬 수 있도록 합니다.
🩵 MVC
MVC(Model-View-Controller) 디자인 패턴은 애플리케이션의 객체에 모델, 뷰 또는 컨트롤러의 세 가지 역할 중 하나를 할당합니다.
패턴은 애플리케이션에서 개체가 수행하는 역할을 정의할 뿐만 아니라 개체가 서로 통신하는 방식도 정의합니다.
세 가지 유형의 객체는 각각 추상적인 경계로 서로 분리되어 있으며, 이러한 경계를 넘어 다른 유형의 객체와 통신합니다.
MVC는 Cocoa 애플리케이션 디자인 패턴의 기본이라고 보는 사람들이 많습니다.
쉽게 확장할 수 있고, 재사용이 용이하므로 인터페이스를 잘 정의할 수 있습니다.
✔️ Model
모델 객체는 애플리케이션에 관련된 데이터를 캡슐화하고 해당 데이터를 처리하는 로직을 정의합니다.
예를 들면 게임 캐릭터의 기본적인 정보같은 것들 말이죠.
struct GameUser {
var name: String
var job: String
var hp: Int
var mp: Int
}
다른 모델 객체와 관계를 가질 수 있으므로 애플리케이션의 모델 계층이 하나 이상일 수 있습니다.
struct Pet {
var name: String
var type: String
var level: Int
var hp: Int
var owner: GameUser?
// 펫이 사용자에게 특별한 스킬을 제공하는 기능이 있다면?
func provideSpecialSkill(to user: GameUser) {
}
}
이 예시에서는 GameUser라는 사용자 정보를 정의하고, Pet이라는 펫 정보를 정의하고 있습니다.
Pet에서는 owner를 통해 GameUser와 관계를 맺고 있죠.
var player: GameUser = GameUser(name: "Yen", job: "Developer", hp: 100, mp: 50)
var pet: Pet = Pet(name: "Gamza", type: "Dog", level: 5, health: 80, owner: player)
이런 식으로 Pet 객체는 owner로 GameUser를 할당받을 수 있게됩니다.
또한, 일대다(One-to-Many) 관계를 가질 수 있습니다.
- GameUser는 여러 마리의 반려동물을 소유할 수 있습니다.
- Pet은 단 하나의 주인(GameUser)만을 가질 수 있습니다.
모델 객체는 특정 문제 영역과 관련된 지식과 전문 지식을 나타내기 때문에 유사한 문제 영역에서 재사용할 수 있습니다.
이상적으로 모델 객체는 데이터를 표시하고 사용자가 해당 데이터를 편집할 수 있도록 하는 뷰 객체에 대한 명시적인 연결이 없어야 합니다.
즉, UI 문제에 관여하면 안 됩니다.
데이터를 생성하거나 수정하는 뷰 계층의 사용자 작업은
ViewController 객체를 통해 전달되어서 모델 객체가 생성되거나 업데이트됩니다.
모델 객체가 변경되면(예: 네트워크 연결을 통해 새 데이터가 수신됨) 적절한 뷰 객체를 업데이트하는 컨트롤러 객체에 알려주기만 합니다.
✔️ View
뷰(View) 객체는 사용자가 애플리케이션과 상호작용할 때 보이는 부분을 담당하는 객체입니다.
주로 화면에 UI 요소를 표시하고 사용자 입력에 응답합니다.
- UI 구현
- 뷰 객체는 자체적으로 화면에 그려지며, 사용자 인터페이스의 일부를 표현합니다.
- 이는 주로 UI 요소들을 렌더링하고 배치하는 역할을 수행합니다.
- 모델 데이터 표시 및 편집
- 주된 목적 중 하나는 애플리케이션의 모델 객체의 데이터를 사용자에게 표시하는 것입니다.
- 예를 들어, 데이터베이스의 정보를 목록이나 테이블 형태로 보여주는 역할을 합니다.
- 또한 사용자가 편집 가능한 UI 요소(텍스트 필드, 버튼 등)를 통해 모델의 데이터를 수정할 수 있도록 합니다.
- 하지만 컨트롤러 객체와는 분리되어 있습니다.
- 컨트롤러 객체와의 상호작용:
- 뷰 객체는 애플리케이션의 컨트롤러 객체와 상호작용하여 모델 데이터의 변경을 감지하고, 사용자 입력에 대한 응답을 처리합니다.
- 변경된 데이터는 컨트롤러를 통해 모델로 전달되어야 하며, 사용자가 시작한 변경 사항(예: 텍스트 필드에 입력된 텍스트)도 마찬가지로 컨트롤러를 통해 처리됩니다.
- 작업 수행 X
- 뷰 객체는 주로 화면의 표현과 사용자 입력을 다루는데 중점을 둡니다.
- 따라서 뷰 객체 자체에서 실제로 어떤 작업을 수행하는 것은 아니며, 이러한 작업은 주로 모델과 컨트롤러에게 위임됩니다.
✔️ ViewController
컨트롤러 객체는 애플리케이션 내의 뷰 객체와 모델 객체 간의 중개자 역할을 수행합니다.
이를 통해 사용자 인터페이스와 데이터 처리 간의 효율적인 상호작용을 담당합니다.
import UIKit
class GameUser {
var name: String
var score: Int
init(name: String, score: Int) {
self.name = name
self.score = score
}
}
class GameViewController: UIViewController {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var scoreLabel: UILabel!
@IBOutlet weak var increaseScoreButton: UIButton!
var currentUser: GameUser = GameUser(name: "Player1", score: 0)
override func viewDidLoad() {
super.viewDidLoad()
// 초기화면 설정
updateUI()
}
@IBAction func increaseScoreButtonTapped(_ sender: UIButton) {
// 버튼이 눌렸을 때의 동작
currentUser.score += 10
updateUI()
}
func updateUI() {
// UI 업데이트
nameLabel.text = "Player: \(currentUser.name)"
scoreLabel.text = "Score: \(currentUser.score)"
}
}
위의 코드에서 GameViewController는 게임 사용자(GameUser)와 관련된 데이터를 표시하고 수정하는 역할을 합니다.
- GameUser 클래스는 게임 사용자의 이름과 점수를 나타내는 간단한 모델입니다.
- GameViewController는 사용자 인터페이스의 요소들을 정의한 IBOutlet들과 사용자의 상호작용에 대응하는 IBAction 메서드를 가지고 있습니다.
- increaseScoreButtonTapped 메서드는 버튼이 눌렸을 때 호출되며, 현재 사용자의 점수를 증가시키고 UI를 업데이트합니다.
- updateUI 메서드는 UI를 현재 상태에 맞게 업데이트합니다.
위의 예시로 알 수 있듯이,
뷰 컨트롤러 객체는 사용자 인터페이스와 데이터 모델 간의 상호작용을 다루는 것이 주 역할입니다.
- 중개자
- 컨트롤러는 뷰 객체와 모델 객체 사이에서 중개자 역할을 수행합니다.
- 사용자의 입력이 발생하면 컨트롤러가 이를 해석하고 그에 따른 작업을 수행합니다.
- 뷰에서 모델로의 변경 사항 전달
- 사용자가 뷰에서 어떤 동작을 수행하면, 컨트롤러는 이 동작을 해석하고 모델에 대한 변경을 수행합니다.
- 즉, 뷰에서 발생한 이벤트나 사용자 입력을 해석하여 모델 데이터를 갱신합니다.
- 모델에서 뷰로의 데이터 전달
- 모델 객체의 상태가 변경되면, 컨트롤러는 이를 감지하고 새로운 데이터를 뷰에 전달합니다.
- 이를 통해 뷰는 최신의 데이터로 업데이트되어 사용자에게 정확한 정보를 제공할 수 있습니다.
- 응용 프로그램 설정 및 조정
- 컨트롤러는 응용 프로그램의 초기 설정 및 환경 조정과 관련된 작업을 담당합니다.
- 예를 들어, 사용자 환경 설정, 테마 변경, 뷰 전환 등의 작업을 처리할 수 있습니다.
- 수명 주기 관리:
- 다른 객체들의 수명 주기를 관리하고 필요에 따라 생성, 소멸을 조절합니다.
- 특히, 뷰나 모델이 새로 생성되거나 해제될 때, 이러한 작업을 컨트롤러가 처리합니다.
override func viewDidLoad() {
super.viewDidLoad()
// 뷰가 로드된 후의 초기화 작업 수행
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// 뷰가 나타나기 전에 수행할 작업 처리
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// 뷰가 사라지기 전에 수행할 정리 작업 처리
}
deinit {
// 뷰 컨트롤러가 메모리에서 해제될 때 수행할 작업 처리
}
🤫 정리 - MVC
MVC는 애플리케이션의 아키텍처를 세 가지 주요 부분으로 나누어 설계하는 디자인 패턴입니다.
- Model: 애플리케이션의 데이터와 비즈니스 로직을 담당
- View: 사용자에게 보여지는 UI를 표현하며, Model의 상태를 표시
- Controller: 모델과 뷰 간의 상호 작용을 관리하고 사용자 입력을 처리하여 Model을 업데이트하거나 뷰를 업데이트
MVC는 각 컴포넌트 간의 역할을 명확히 구분하여 코드의 재사용성과 유지보수성을 향상시키는 데 기여합니다.
그러나 너무 많은 로직이 컨트롤러에 집중되는 경우 오히려 복잡해지는 문제점이 발생할 수 있습니다.
MVC는 컨트롤러 객체에 많은 책임이 부과될 수 있다는 단점을 가지고 있습니다.
모델 관련 로직도 컨트롤러에서 작업되기 때문에 유지보수성도 떨어질 수 있구요.
MVVM(Model-View-View Model)은 이러한 MVC의 한계를 극복하고,
데이터 바인딩을 활용하여 뷰와 뷰모델 간의 강력한 연결을 제공합니다.
(뷰 모델에서 비지니스 로직을 전부 처리하게 되어 더 명확한 역할 분리가 가능해져요)
다음 게시글에서는 MVVM 패턴의 상세한 구성과 장점에 대해 더 자세히 살펴보겠습니다!
Model-View-Controller
Retired Document Important: This document may not represent best practices for current development. Links to downloads and other resources may no longer be valid. Model-View-Controller The Model-View-Controller (MVC) design pattern assigns objects in an ap
developer.apple.com
'iOS > Swift' 카테고리의 다른 글
[Swift] Core Data(1) - 사용 설정하기 (0) | 2024.02.02 |
---|---|
[Swift] filter() vs first() - 차이점, 시간복잡도, 디버깅 (1) | 2024.01.29 |
[Swift] 네트워크 통신(2) - URLSession(GET)과 Decodable 프로토콜 (1) | 2024.01.04 |
[Swift] 네트워크 통신(1) - URL과 REST API (1) | 2024.01.04 |
[Swift] Delegate Pattern에서 AnyObject를 사용하는 이유는? (0) | 2024.01.02 |