Swift

Swift - 소프트웨어 아키텍처 (MVP, VIPER)

iosos 2023. 7. 6. 17:26

* Swift 소프트웨어 아키텍처

- Swift 언어로 애플리케이션을 구조화하는 방법과 관련된 원칙과 패턴 모음

- 소프트웨어 아키텍처를 적용함으로써 모듈성, 유지보수성, 확장성을 개선할 수 있음 

- MVC, MVVM, MVP, VIPER 

 


* MVP (Model - View - Presenter)

- 사용자 인터페이스(UI)를 모델, 뷰, 프리젠터로 구성하여 역할을 분리하는 방식 

 

1. Model 

- 데이터와 비즈니스 로직을 담당 

- 데이터를 가져오고 수행하며 비즈니스 규칙을 적용하여 데이터를 처리 

 

 

2. View 

- 사용자 인터페이스를 표시하고 사용자 입력을 받음 

- 프리젠터로부터 전달받은 데이터를 화면에 표시하고 사용자의 동작을 감지하여 프리젠터에 전달 

 

 

3. Presenter

- 모델과 뷰 사이에서 중개자 역할

- 모델로부터 데이터를 가져와 뷰에 전달하고, 사용자 입력을 받아 모델에 전다랗여 데이터 업데이트 

- 뷰와 모델 간의 의존성을 없애고, 역할을 분리하여 테스트와 유지보수가 용이함 

 

 

동작)

- 사용자의 action이 view를 통해 들어옴

- view는 데이터를 presenter에 요청하고 presenter는 model에게 데이터 요청

- model은 요청받은 데이터를 응답하고 presenter는 view에게 데이터 응답 

- view는 응답 받은 데이터 화면에 표시 

 

 

장단점)

- MVC 패턴의 단점이었던 View와 Model 사이의 의존성을 Presenter를 통해 해결했지만, View와 Presenter 사이의 의존성이 높아짐

 

 

 

 

예)

 

1. 모델(Model)

import Foundation

// 모델 (Model)
struct MVP_User {
    let name: String
    let age: Int
}

- Presenter와 View에서 필요한 데이터 제공

 

 

 

 

2. 뷰(View)

import Foundation

// 뷰 (View)
protocol MVP_UserProfileView: AnyObject {
    func showUserName(_ name: String)
    func showUserAge(_ age: Int)
}

- 사용자 인터페이스를 업데이트하는 메서드를 정의

- View가 Presenter와 상호작용하며 데이터를 전달받아 화면에 표시할 수 있도록 함 

 

 

 

 

 

3. 프레젠터(Presenter)

import Foundation

// 프리젠터 (Presenter)
class MVP_UserProfilePresenter {
    private let user: MVP_User
    private weak var view: MVP_UserProfileView?

    init(user: MVP_User, view: MVP_UserProfileView) {
        self.user = user
        self.view = view
    }

    func updateUserProfile() {
        view?.showUserName(user.name)
        view?.showUserAge(user.age)
    }
}

- 사용자 데이터를 가지고 있는 'MVP_User' 객체와 View와 상호작용하기 위한 'MVP_UserProfileView' 프로토콜 속성을 가짐

- 'updateUserProfile()' 메서드는 사용자 프로필을 업데이트하는 역할 수행

- 사용자 이름과 나이를 뷰에 전달하여 뷰에서 화면에 표시하도록 설정 

 

 

4. ViewController

import UIKit

class MVP_UserProfileViewController: UIViewController, MVP_UserProfileView {

    
    
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var ageLabel: UILabel!
    
    
    private var presenter: MVP_UserProfilePresenter!

       override func viewDidLoad() {
           super.viewDidLoad()

           let user = MVP_User(name: "MVP길동", age: 24)
           presenter = MVP_UserProfilePresenter(user: user, view: self)
           presenter.updateUserProfile()
       }

       func showUserName(_ name: String) {
           nameLabel.text = name
       }

       func showUserAge(_ age: Int) {
           ageLabel.text = "\(age)"
       }
   }

- 'MVP_User' 를 생성하고 'MVP_UserProfilePresenter' 를 통해 사용자 프로필 업데이트 

- 'showUserName()', 'showUserAge()' 메서드는 'MVP_UserProfileView' 프로토콜의 요굿항을 구현한 것 

 

 

 


* VIPER (View - Interactor - Presenter - Entity - Router)

- 각각 다른 역할을 가진 컴포넌트로 구성되어 소프트웨어 구조와 유지보수 향상에 도움을 줌 

- 단일 책임 원칙 (SRP)를 기반으로 함

- SRP : 작성된 클래스는 하나의 기능만 가지며 클래스가 제공하는 모든 서비스는 그 하나 책임을 수행하는 데 집중되어야 한다는 원칙 

- 응집도는 높고 결합도는 낮은 형태로, 역할 단위의 구분이 명확함 

- 변경이 필요한 부분을 쉽게 식별하고 수정할 수 있음 

- 복잡한 애플리케이션에 적합하며, 확장 가능하고 유지보수가 용이한 소프트웨어 아키텍처를 구축하는 데 도움을 줌 

 

1. View

- 사용자 인터페이스를 담당하며, 사용자의 입력을 받고 presenter에 전달

- UI를 구성하고 업데이트하기 위한 인터페이스 정의 

 

 

2. Interactor 

- 비즈니스 로직 담당

- 데이터를 처리하고 엔티티와 상호작용하며, 네트워크 호출, 데이터베이스 작업 등과 같은 기능 수행

 

 

3. Presenter

- view와 interactor 간의 중개자 역할 수행

- 사용자의 입력을 처리하고 interactor로부터 데이터를 가져와 뷰에 전달 

- view로부터 액션을 받아 interactor에 전달하여 비즈니스 로직 수행 

 

 

4. Entitiy

- 애플리케이션의 데이터 모델을 나타냄

- 비즈니스 로직을 처리하는 데 필요한 데이터를 캡슐화하고 Interactor와 상호작용

 

 

5. Router

- 화면 간의 전환과 라우팅 담당

- 다른 VIPER 모듈로 전환과 같은 네비게이션 기능 제공 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

참고)

https://beomy.tistory.com/43 

https://janechoi.tistory.com/12