iOS 공부를 하면서 MVC나 MVVM 등, 다양한 패턴에 대해서 들어 보셨을 겁니다.
그런데 이런 패턴을 적용하는 이유가 뭐지?? 그냥 돌아가기만 하면 되는 거 아닌가??
라는 생각을 했었지만...
프로젝트의 크기가 커진다면? → 에러가 난 부분을 찾는 것과 로직 파악이 어렵다 (분명 내가 짠 코드인데...?)
함께 협업하는 상황이라면? → 잇시 이거 누가 짰어! (그 코드를 이해하는 데 어려움이 발생)
문제점은 여러가지가 있겠지만 그 중에서도 위의 문제가 중요하다고 생각합니다.
적절한 비유는 아니지만... 만약 자취를 한다고 생각하면!
혼자 산다! 그러면 뭐 대충(?) 살겠죠. 분명 내가 던져 놓은 물건인데 필요할 때에는 꼭 찾기 어렵고...
하지만 함께 산다! 서로 민폐가 되지 않기 위해서 규칙을 정하고,
함께 쓰는 물건은 특정 장소에 두고 하겠죠?(아마도...)
함께 틀을 잡고, 말하지 않아도 어떤 물건이 어디 있는지 쉽게 파악할 수 있고... 뭐 이런 느낌입니다.
그럼 좋은 아키텍처는 무엇일까요?
Balanced distribution of responsibilities among entities with strict roles
- 각 객체들의 역할이 분명하며 일이 치중되어 있지 않아야 한다!
Testability usually comes from the first feature.
- 말 그대로 테스트를 하기에 용이한가!
Ease of use and a low maintenance cost.
- 사용성이 편리하며 유지보수 비용이 낮은지!
- 간결한 코드, 그리고 적절한 네이밍 사용 등으로 의사소통이 되는 코드가 사용성이 편리하다고 볼 수 있습니다.
모든 요소를 꼭 갖춰라! 그런 것도 아니고, 또 그렇게 설계하기도 어려운 것이 사실이지만,
어느정도 이 요소를 맞춰서 구현을 한다면 조금 더 수월하고 시간을 아끼면서 협업을 할 수 있습니다.
결국에는 높은 재사용성을 얻어! 이해하기 쉬워져! 독립적으로 테스트 하기도 쉬워져! 입니다.
실무 프로젝트에서 적용을 해보긴 했지만 개념 정리가 필요하다고 생각해서 살짝 정리해 보기로 했습니다.
자 우선 우리가 일반적으로 알고 있는 MVC 패턴에 대해서 먼저 알아볼까요? (네!)
MVC
Model, View 그리고 Controller의 약자입니다.
MVC, MVVM, MVP 패턴들에서 공통적으로 가지고 있는 요소가 있습니다.
Model : 데이터를 다루는 부분입니다. 데이터를 파싱하기 위해 필요한 데이터 구조를 정의합니다.
View : 말 그대로 화면에 보여지는 UI를 다룹니다.
Controller(ViewModel/Presenter) : 위의 Model과 View를 이어주는 역할을 합니다.
일반적인 흐름은 View에서 사용자의 입력을 받아 Controller에게 전달하고,
Controller는 그 입력에 따라 Model을 변경시키고,
그 Model을 토대로 View를 갱신하는 거죠
MVC의 로직입니다.
사진만 봐도 Model과 Controller, 그리고 View 사이 밀접하게 연결되어 있다는 게 느껴지죠?
View에서 Controller에 입력을 보내면 Controller는 Model의 상태를 변경시킵니다.
그런데 이 변경된 모델을 View에서 직접 가져오는 그런 구조입니다.
LifeCycle 뿐만 아니라 다른 로직을 다 Controller에 때려박았기(?) 때문에 프로젝트가 커진다면 Controller의 코드 양 또한 방대해 지겠죠?
그리고 서로 독립성이 없기 때문에 테스트하기 어렵고 재사용성 또한 떨어집니다.
음... 그러면 이 패턴은 안 쓰는 게 좋은 것 아닌가? 생각할 수 있지만,
규모가 작은 프로젝트에서 사용하기에 좋은 패턴이라고 생각합니다.
왜냐면 다른 디자인 패턴은 Model, View, Controller 외에 추가해야 할 것들이 많고,
그렇게 추가적인 작업이 많기 때문에 큰 프로젝트에서나 효율성을 발휘하기 때문입니다.
Apple은 CocoaMVC 패턴을 내놓게 됩니다.
View와 Model 사이의 연관성이 사라졌죠?
View가 Model에서 직접 데이터를 가져오는 것이 아니라 Controller가 관리하게 되었습니다!
그런데 우리는 개발을 할 때 ViewController를 사용합니다.
이름만 봐도 View와 Controller 사이 독립성이 없다는(긴밀하게 연결되어 있다는) 것을 알 수 있습니다.
그래서 실제로는 이런 구조가 나오게 되죠.
Model은 독립성이 있지만, View와 Controller는 여전히 긴밀한 관계(?)를 유지하고 있습니다!
그렇기 때문에 View와 Controller르 따로 테스트 하는 것은 어렵겠죠?
또한 View와 Model을 Controller가 혼자 관리하기 때문에 코드가 Controller에 치중될 수 있습니다. (큰 프로젝트에서 사용한다면 아찔하겠죠...)
개발자들에게 친숙하며 개발 속도가 빠르다는 장점이 있지만,
프로젝트의 규모가 커지면 유지보수 하기에 어렵다는 단점이 있습니다.
MVVM
MVC와 비교해 보면 C가 빠지고 VM이 추가되었습니다.
MVC의 View와 Controller 사이의 의존성이 높다는 문제를 해결하기 위해 등!장! 했습니다.
ViewController를 View로 보고,
Controller의 로직은 ViewModel로 옮겼다고 생각하시면 됩니다.
우선 로직을 볼까요?
View
이제 View는 단순히 인터페이스를 위한 로직(그냥... UI를 관리하는 코드)과 생명주기 코드만을 다룹니다.
MVVM에서는 ViewController를 View로 봅니다.
ViewModel
Presentation Logic이 포함되어 있습니다.
UI와 관련된 요소들에 접근할 때에는 UIKit을 import하죠?
하지만 ViewModel는 UIKit을 사용하지 않고도 Model과 View 요소를 업데이트 합니다! (UI와 독립적으로 테스트를 할 수 있습니다.)
Model이 얻어 온 데이터를 View에 맞게 가공/처리하는 역할을 담당합니다.
Model이 변경되면 자동으로 View도 변경될 수 있도록 데이터 바인딩을 합니다. (데이터 일관성 유지!)
데이터 바인딩은 뷰와 로직이 따로 나뉘어 있지만, 한 쪽이 변하면 다른 한 쪽도 함께 변하는 것입니다.
View가 ViewModel을 소유합니다.
Model
데이터를 다루는 부분입니다. 데이터를 파싱하기 위해 필요한 데이터 구조를 정의합니다.
초기값과 비즈니스 로직을 관리합니다. 이 때, 값이 변경되면 뷰나 뷰 컨트롤러에게 알립니다.
ViewModel이 Model을 소유하며, View와는 독립적입니다.
이제 View와 Controller를 분리했으니 독립성이 생겼습니다!
그렇기 때문에 각각 독립적으로 테스트를 할 수 있게 되었습니다.
MVVM은 View와 Controller를 분리했기 때문에 테스트하기에 용이하다는 장점이 있습니다.
하지만 이렇게 설계하기 어렵다는 단점이 있죠...
왜냐면 구조만 정의해놨지 규격화 된 것이 없기 때문에 처음에 배우기도 어렵고 개발자에 따라 설계 방식이 다 다르기 때문입니다,,
그리고 데이터 바인딩을 할 때 여러 방법(KVO, Delegation, Property Observer)을 사용하지만,
그 중에서도 RxSwift를 많이 사용하기 때문에 배워야 할 것이 정말 많아져서 장벽이 높습니다.
참고
'iOS > 디자인패턴' 카테고리의 다른 글
디자인패턴 - 싱글턴 패턴(Singleton Pattern) (0) | 2023.02.01 |
---|