본문 바로가기

Swift

프로토콜 지향 MVVM 디자인 패턴 적용하기





보통 iOS 프로젝트를 개발하다 보면 반드시 만나게 되는 문제가 있다. 바로 의도하지 않게 특정 클래스가 비대해 지면서 코드 관리가 점점 어렵게 되는 문제이다. 또한 iOS는 MVC 모델 패턴을 적용하기가 어중간하다. 하지만 디자인 패턴을 무시하고 코딩을 하다 보면 결국 유지보수 비용이 한도 끝도 없이 늘어나기 마련이다. 그러다보면 결국 스크롤을 한참 해야하는 소스들이 생겨난다.


디자인 패턴이 정확하게 적용되지 않은 소스의 문제점은

  • 파악하기 쉽지 않은 코드
  • 재활용이 어려운(거의 불가능한) 소스
  • 본인조차 나중에 코드를 보면 바로 알아보기가 어렵다는 문제

등을 가지고 있다. 

이런 문제를 해결하고, 재사용과 향상 가능한 코드를 만들기 위해 고민하던 중 스위프트 커뮤니티에 자주 등장하는 MVVM 모델 패턴이 눈에 들어왔다. 
프로젝트에 적용 방법을 고민하던 중에 결정적인 글을 발견하고 실제 프로젝트에 적용해 보았다.


윗글의 내용은 3가지 핵심 내용으로 요약할 수 있다

- 프로토콜
- 확장(extension)
- ViewModel의 사용

이 3가지를 이용해서 기존의 불완전한 MVC 패턴에서 MVVM 패턴으로 소스코드의 디자인 패턴을 변경해 보았다.
MVVM 디자인 패턴에 대한 글은 널려 있기에, 실제로 개발/운영에 얼마나 영향을 미치는가 직접 프로젝트를 이용해 검증해 보았다.






[ MVVM 패턴을 적용할 Alis 앱 ]


이 앱은, 간단하게 할 일 목록 앱이다. 할 일의 리스트가 존재하고 할 일을 등록하는 페이지와 셋업 페이지가 있다.
가장 먼저 할 일은 뷰를 구성하는데 가장 많고 공통으로 쓰이는 세 개의 프로토콜을 정의하는 일이다.


이 3개의 프로토콜로 리스트의 모든 뷰를 그릴 수 있었다. 






이 프로토콜을 가지고 아래의 소스를 리팩토링할 것이다.






이 소스는 메인테이블 뷰를 그리는 리팩토링 하기 전의 소스이다.
뭔가 기능별로 나눠놓은 거 같긴 한데 뭔가 어색하고 구려 보인다.


셀을 한번 자세히 보자. 보통 디자인이 복잡하면 복잡할수록 뷰를 그리는 코드가 길어지고 가독성이 떨어지게 된다. 




메인 테이블 뷰의 셀에는 2개의 이미지 뷰와, 3개의 라벨이 존재한다.
이 각 뷰를 그려줄 뷰 모델을 5개 생성했다.
















뭔가 보기 명확해졌다. 이제 뷰를 그리는 해당 아이템의 모든 값이 뷰 모델에서 수정할 수 있게 되었다. 
이제 해당 뷰 모델을 셀과 연결해 보자.




뭔가 굉장히 심플하고 명확해졌다. 이제 뷰컨트롤러는 해당 뷰를 그리는데 들어가는 코드가 무엇인지 알 필요가 없어졌다.
뷰 컨트롤러는 모델을 뷰모델에만 넘겨주면, 뷰 모델이 화면에 뷰를 그려준다.

이러한 방법의 또 한 가지 장점이 바로 UI 테스트 이다. 이제 UI가 올바로 나오는지를 테스트하려면 해당 뷰모델에 해당하는 테스트 코드를 작성하면 된다.




자 그러면 이렇게 작성된 코드는 재사용이 가능할까? 위 내용이 반복 사용이 가능하고 포괄적인 디자인 모델 패턴이 될 수 있는지 테스트하기 위해서 프로젝트 하나를 새로 만들었다.





이 프로젝트는 쉽게 이야기해서 가계부로, 간단하게 리스트인 홈 뷰, 데이터 추가 뷰, 레포트 뷰, 메뉴 뷰 총 4개의 구조로 이루어져 있다.
해당 프로젝트는 위 Alis 앱에서 작업한 프로토콜을 그대로 가져왔으며, 추가적으로 UIViewController 프로토콜과 UITextField 프로토콜을 추가하였다.




프로토콜을 재활용하면서 확장을 사용했다. 여기서 재미난 점은, 텍스트필드 프로토콜은 결국 TextPresentable 프로토콜을 상속받는 다는 점이다.

결국 앱은 글자와 이미지 두 가지 이다.
이로써 프로토콜 지향 MVVM 디자인 패턴의 기본적인 소스코드는 계속해서 다듬고 재사용할 수 있다는 것을 알게 되었다.






나머지 부분은 Alis와 거의 완전하게 동일하다. 두 앱은 전혀 다른 앱이지만, 내부 구조에 대해서는 거의 동일한 구조를 가지고 있다.

그렇기 때문에 Alis앱을 유지 보수해본 사람은, Alfred 앱도 유지 보수하는데 아무런 문제가 없었다.


결국 프로토콜 지향 MVVM 디자인 패턴은, 기존에 기능별로 패턴을 쪼개는 것이 매우 어려웠던 MVC 모델 패턴과는 다르게,  자신의 할 일을 정확하게 나눈 코딩이 가능하다.

이제 뷰 컨트롤러는 기존 목적과 같이 모델과 뷰를 이어주는 역활에 충실하게 되며,
뷰를 그리는 부분을 상당 부분 포함하는 것에서 벗어나 단순히 모델만 뷰모델로 넘겨주는 역할에 국한된 것이다.

우리는 이로써 명확성과 캡슐화를 더 분명하게 지키게 되었다.

보통 뷰의 글자의 크기나, 색상, 폰트 등을 수정할 때, 이전같이 MVC 모델 패턴을 사용하면 해당 부분이 어디에 있는지 명확하지 않다.
만일 복수의 프로젝트를 가지고 있다면 프로젝트마다 위치를 기억하는 것은 매우 어려운 문제이다. 

하지만 이와 같은 방법을 사용하면 항상, 어디에 해당 소스가 있는지 정확하게 알 수 있다. 
우리는 뷰 부분을 수정할때는 언제나 뷰모델만 뒤지면 된다. 이것은 매우 큰 장점이다.
(물론 이럴 경우 합의된 클래스 명과 변수명 등을 잘 지켜야 한다)





나름의 결론 - 이런거 하면 뭐가 좋을까?




장인이라 하면 떠오르는 것이, 오랜 시간 기술을 갈고 닦아 마침내 기술의 정점에 이르는 사람이다. 난 프로그래머도 이 장인을 꿈꿀 수 있는 한 분야라고 믿어 의심치 않는다. 하지만 지난 10년간 개발을 해 오면서 재활용 가능하고 숙련되고 발전하는 프로그래밍적 기술을 사용한다는 것이 엄청나게 어렵다는 사실을 새삼 깨닫게 되었다. (특히 특정 회사에 소속된 프로젝트를 진행하면서 저런 캡슐화, 디자인 패턴, 명확성 등을 지키기는 더 어렵다)

하지만 진짜로 중요한 사실은 마구잡이로는 레벨업 하기가 쉽지 않다는 점이다.

이러한 방법론에 입각한 코딩 방식은, 마구잡이로 코딩하는 것을 방지한다.
또한 변수나 클래스의 이름이나 위치, 구조등을 만들때도 한번 더 생각해게 만든다.
확실한것은, 경험에 근거한 10년차의 1년차 같은 코딩 같은 잘못된 방법을 어느정도 예방할 수 있는 방법임에는 틀림 없는 점이다.

결론적으로 이러한 장점을 남(?)겼다

  • 매우 분명한 구조화
  • 정확한 용어로 설명 가능한 코드의 디자인 패턴
  • 그리고 인수인계할 양의 감소(?)

뷰모델을 생성하는 것이 때로는 번거롭기도 하지만, 그러한 단점보다는 아직까지는 장점이 훨씬더 많은 것 같다.



해당 방법론을 추천합니다!!!