[Lecture 3] MVVM and the Swift type system


MVVM

Model, View, ViewModel로 구성된 디자인 아키텍처이다. 

지금 배우고 있는 SwiftUIMVVM 디자인 아키텍처를 따르고 있다. 

 

디자인 아키텍처?

상호작용 방식을 명확하게 하는 디자인 패러다임. 간단하게 개발 방법 및 규칙을 정해놓은 것이라고 보면 된다.

 

Model

모델에는 데이터와 로직이 담겨있다. 즉 Memorize 앱에서는 카드 자체와 점수를 계산하는 로직들이 담긴다고 보면 된다.

 

View

사용자에게 모델을 보여주는 부분이다. 

 

ViewModel

모델과 뷰를 바인딩해주는 역할을 한다. 여기서 중요한 점은 뷰모델은 뷰의 존재를 몰라야 한다. 즉 모델의 자료변경이 일어나면 해당 부분에 대해서 공표하기(Publish)만 할 뿐이다. 뷰는 뷰모델의 알림을 감지한 뒤 해당 변경이 자신이 나타내는 정보에 해당하는 사항이라면 새로운 뷰를 그려내어 변경된 부분을 사용자에게 보여준다.

 

반대로 사용자의 의도에 의해 모델의 변경이 일어난다면, 뷰는 곧바로 모델에게 알리는 것이 아니다. 뷰모델이 알아챌 수 있는 함수를 호출하여 뷰모델에게 의도를 전달한다. 뒤이어 뷰모델은 모델에게 변경을 지시하여 모델의 변경이 완료된다. 즉 뷰는 직접적으로 모델에 접근하여 변경을 일으킬 수 없다.

 

전체적인 구조와 이때 사용되는 키워드는 다음과 같다. 각 키워드가 어떻게 동작하는지는 뒤에 이어질 수업에서 나올 예정인가 보다.

 

Structure and Class

구조체와 클래스는 하나의 주제로 묶인 자료의 모음이다.

기본적으로 변수와 상수, 그리고 함수를 정의할 수 있다는 점이 둘의 공통점이지만 둘은 어떤 방식으로 이용하느냐에 따라 큰 차이점이 존재한다.

 

Value type and Reference Type

가장 큰 차이점이 바로 구조체는 값 타입, 클래스는 참조 타입이라는 점이다. 

 

구조체는 할당 혹은 인자로서 넘겨주게 되면 그 자체의 값이 복사되어 사본이 넘어간다. 따라서 해당 부분을 값 타입이라 부른다. 물론 복사가 일어날 때마다 사본이 생성되는 것은 아니고, 사본의 변경이 일어나면 그때서야 복사가 일어난다고 한다. 해당 부분은 copy on wirte이라는 정책으로 불린다.

 

클래스는 할당 혹은 인자로서 넘겨주게 되면 해당 객체를 가리키는 포인터가 생성된다. 여기서 메모리의 힙 영역 관리를 위해 swiftARC 정책에 의해 포인터의 개수를 모니터링하다가 포인터의 증감에 따라 개수가 0이 되면 메모리 해제가 일어나게 된다.

 

Initializer

구조체와 클래스 모두 자동적으로 "무료" 생성자가 주어지게 되는데, 여기서 구조체는 각 인자를 초기화할 수 있는 반면 클래스는 그렇지 못하다고 한다.

 

mutable

구조체의 경우 속성 변경이 일어나는 함수를 작성 시 mutating이라는 키워드를 적는다. copy on wirte 정책으로 인해 해당 부분의 변경이 일어나는지 확인해야 하기 때문이다. 중요한 점은 객체 또한 var로 선언해야 변경이 가능하다.

struct A{
    var value = "a"
    mutating func changeValueTo(newVlaue:String){
        self.value = newVlaue
    }
}

var a = A()

print(a.value)
a.changeValueTo(newVlaue: "A")
print(a.value)

//출력 결과
//a
//A

 

반면 클래스의 경우 속성 자체가 변수로 선언되어 있다면, 객체가 let으로 선언이 되어도 변경이 되는 것을 볼 수 있다.

class B{
    var value = "b"
    func changeValueTo(newVlaue:String){
        self.value = newVlaue
    }
}

let b = B()

print(b.value)
b.changeValueTo(newVlaue: "B")
print(b.value)

//출력 결과
//b
//B

 

Usage

swift의 공식문서를 보면 클래스보단 구조체의 사용을 지양한다고 적혀있다. 여러 가지 이유가 있겠지만, 클래스의 무분별한 사용으로 인해 포인터끼리 참조되는 순환 참조로 인한 메모리 누수를 피하기 위함이 아닐까 생각한다. 

 

Lecture 3에서는 이에 대한 이야기는 언급하지 않았고, swift에서 마주하는 대다수가 구조체이며, 클래스는 ViewModel의 구현에 사용된다고 하였다. Model에 저장된 Data의 바인딩이 주목적이므로 자료의 공유가 빈번하게 일어나기 때문에 포인터를 넘기는 것이 더 효율적이기 때문이라고 생각한다.

 

참고 영상

https://www.youtube.com/watch?v=--qKOhdgJAs&list=PLpGHT1n4-mAsxuRxVPv7kj4-dQYoC3VVu&index=6

+ Recent posts