이호준 멘토님의 우당탕탕 멘토링 -3.1-

지난 번 포스트 에서 내준 이호준 멘토님의 숙제를 시작해보자 !!

숙제는 총 세 가지.

  1. 분석했던 앱들 중에서 다섯 개 전부가 아니어도 괜찮으니 오늘 보여드렸던 것보다 한 스텝씩 더 나아간 수준의 분석.
  2. 앱의 화면을 여러 가지 모듈을 이용해 구성하고, 필터를 넣으면 특정 모듈의 데이터만 바뀔 수 있도록 만들어 올 것.
  3. 최대한 많은 부분에서 스마트폰만이 가지고 있는 기능을 자세히 분석해올 것.

 

순서는 중요하지 않으니 일단 마음이 끌리는 대로 해봐야겠다.

 

MVC, MVC를 파헤치자!!

먼저 마음이 끌렸던 건 모듈화를 통해 하나의 뷰 안에 여러 가지 모듈을 붙여보기.

그런데 막상 하고자 하니 그간 ios/swift를 배우면서 아이폰 앱 개발자들은 주로 어떤 방식으로 MVC를 적용하여 개발을 하는지가 궁금했고, 몰라서 답답한 경험이 있다.

그래서 ! 먼저 할 것은 swift의 MVC~ 파헤치기~~

 

우리가 알고 있는 MVC

글을 쓰는 시점에서 내가 이해하는 MVC가 일반적으로 이해하고 있는 MVC가 맞는지 궁금해서 그것부터 확인했다.

내가 이해하고 있었던 MVC는

Model에서 json같은 데이터를 받아오기 위한 데이터 구조를 정의하고,

Controller에서 받아온 데이터를 가공하고,

View에서 가공한 데이터를 보여준다 이다.

 

그래서 검색을 했더니 자료를 금방 찾을 수 있었다.

여기에 대해 아주 좋은 reference image가 있어서 첨부한다.

 

위 그림이 MVC의 모든 것을 말해주지는 않지만 충분히 잘 설명한다고 생각한다.

내가 위에서 언급한 MVC 개념에는 view가 사용자의 동작을 인식하고 Model이 바뀌면 view에서 직통으로 model로부터 상태 정보를 받아온다는 것?

 

ios 개발은 MVC 패턴을 적용하기 힘들다

라는 게 내 생각이다.

왜냐하면 Model은 작성할 수 있어도 view와 controller를 떼어놓기가 참 불편한 부분이 많기 때문이다.

어떤 점이 불편하냐면 viewController라는 클래스 파일에 예를 들어 화면의 버튼을 연결해서 버튼을 예쁘게 꾸미는 코드를 입력하곤 하는데 viewController에는 사실 데이터를 가공하고 view를 수정하는 코드도 들어가기 때문이다.

그러니까 View와 Controller가 독립하여 존재하기가 힘들다고 생각했다.

 

역시 나와 같은 생각을 하는 사람은 많았고, 이런 생각을 잘 나타낸 블로그도 소개한다.

여기를 클릭하면 해당 블로그에 들어갈 수 있다.

 

해당 블로그 글에 따르면 Apple은 이것을 미리 인지하고 아키텍쳐를 다음과 같이 제시했다고 한다.

이 MVC 패턴의 이름은 Cocoa MVC이다.

(애플은 왜 이렇게 Cocoa를 좋아하는지 모르겠다. 프레임워크의 이름도 cocoaPods이니..)

 

 

그런데 해당 블로그에서 말하는 것도 그렇고 내 생각도 그렇고 위 구조는 너무 불편하다.

왜냐하면

\1. 테스트하기가 힘들다. Model은 따로 떼어놓고 테스트가 가능하다지만 view와 controller는 따로 테스트하기가 힘들다.

\2. view와 Contorller 가 붙어있다 보니 한 파일의 코드가 너무 길어진다.

 

MVVM 을 만나다

MVVM(Model - View - ViewModel) 을 알아보기 이전에는 MVC 패턴에 대해서만 알고 있었다.

MVC 에 대해 설명하는 블로그를 뒤지는 와중에 와주셔서 영광입니다 블로그 의 주인이자 cadet인 yepark이

'ios는 MVVM을 많이 쓰는 것 같더라' 라는 말을 해서 찾아보게 됐다.

 

이제 MVVM이 무엇인지, 하나씩 파헤쳐보자.

 

'M'VVM의 Model

MVVM 아키텍쳐에서 Model은 데이터 구조를 정의하고 ViewModel에게 결과를 알려준다.

여기서의 Model은 View와 이어지지 않는다.

 

M'V'VM 의 View

MVVM의 View는 흔히 사용하는 ViewController에 코드를 작성한다.

view는 사용자와의 상호작용을 통해 이벤트가 일어나면 ViewModel에게 알려주며,

ViewModel이 업데이트 요청한 데이터를 보여준다.

 

MV'VM' 의 ViewModel

ViewModel은 사용자의 상호작용을 view가 보내주면 그에 맞는 이벤트를 처리하고,

Model의 Read Update Delete를 담당한다.

 

기존의 MVC랑 조금 다른 건 알겠는데... 아직은 크게 감이 안 온다.

좀 더 살펴보자 !

 

 

위는 MVVM을 잘 나타내는 이미지이다.

기존의 View는 단순히 유저 인터페이스를 표시하기 위한 로직만을 담당하고, 그 외에는 메소드 호출 정도만 있는 게 이상적이다.

ViewModel은 기존의 UIKit을 import 할 필요도 없이 데이터 update 및 뷰 요소를 업데이트 한다.

Model은 데이터 구조를 갖고 있다.

 

이러한 MVVM 패턴의 장점은 View - Model - ViewModel 모두 독립적으로 테스트가 가능하다는 것.

반면 단점은 설계가 어렵다는 것과 뷰에 대한 처리가 복잡해지면 뷰모델도 거대해진다는 것.

(그런데 기존의 MVC는 혼자서 한 2주짜리 프로젝트에서도 한 파일의 코드가 길~~어졌으니... MVVM처럼 나누는 게 훨씬 코드 보기에 편할 것 같다.)

 

이제 좀 감이 온다.

다만 파일을 어떻게 나누는지 예제가 더 필요할 것 같다.

그래서 한번 MVVM 을 직접 구현한 예제를 많이 찾아봤는데,

대부분의 블로그들이 내가 배우지 않은 RxSwift를 이용하거나 단순히 예제로 보기엔 너무 큰 코드 내에서 예를 들고 있었다.

그래서 직접 MVVM 과 RxSwift를 배워보려고 강의까지 사서 듣고 난 후에

MVVM에 대해 조금 쉬운 버전으로 예제를 작성했고, 아래 블로그에 모두 정리해두었다.

 

https://42kchoi.tistory.com/292

 

내 설명으로 충분하지 않다면 아래 블로그들의 설명이 도움이 될 수 있을 것이다.

  1. 블로그1
  2. 블로그2
  3. 블로그3

 

모듈로 구성한 뷰를 만들어보자

여러 가지 모듈로 구성한 뷰를 만들어보자.

하나의 뷰 컨트롤러 안에 여러 가지 모듈이 들어가야 하며,

각각의 모듈은 서로 영향을 끼쳐선 안 된다.

 

어떻게 이것을 만들 수 있을까 고민을 하고 이것저것 해보았다.

여러 자료들을 찾아보고, 적용해보고 실패했다.

(그와중에 눈이 너무 건조해져서 며칠 동안은 제대로 화면을 쳐다볼 수가 없었다.)

 

그렇게 여러 시도를 해보다 결국 돌아돌아 처음 시도했던 방법을 확장시켜 쓰게됐다.

그 방법은 container view 를 이용해 화면을 구성하는 것이었다.

containerView는 어떤 view 안에 viewController를 하나 더 넣을 수 있게 만들어준다.

만약 어떤 뷰 안에 containerView를 네 개 넣는다면 다음과 같은 그림이 형성된다.

 

스크린샷 2021-04-06 오후 2 42 57

 

내가 처음 이 방법을 사용했다가 이건 안 된다고 생각하고 다른 방법을 찾아보려 했던 이유는

특정 뷰의 높이값이 고정된다면 저 방법이 아주 유용하게 쓰이겠지만

동적으로 변경되어야 한다면 적용하기 어렵겠다는 생각이 들어서였다.

그러나 그렇게 짧게 생각할 문제가 아니라 좀더 깊게 생각을 했어야 했다. 결국엔 해당 방법을 적용하게 됐으니..

 

최종적으로 결정한 방법을 한번 설명해보겠다.

먼저 각각의 뷰들은 높이 값을 처음에는 고정할 필요가 있다.

이 때 높이 값을 고정하는 요소를 height constraint 라고 하는데, 아래 이미지를 보면 무엇이 height constraint인지 바로 알 수 있을 것이다.

 

스크린샷 2021-04-06 오후 2 47 48

 

저렇게 높이값을 고정하고 아무 조치도 취하지 않은 채로 실행하면 내용물이 아무리 많아도 딱 저 높이만큼만 화면에 출력된다.

그러나 변경된 높이값을 받아서 해당 높이값을 그에 맞게 바꾼다면 어떨까?

결론부터 말하자면 우리가 원하는 대로 내용물에 맞게 높이값이 동적으로 변한다.

그럼 어떻게 높이값을 변경시킬 수 있을까?

 

이해를 돕기 위해 여러 개의 view를 가지고 있는 viewController를 parentViewController라고 하고,

parentViewController를 구성하는 여러 개의 view를 childViewController라고 하겠다.

 

먼저 parentViewController에서 해당 높이 constraint를 @IBOutlet weak var someViewHeightConstraint: NSLayoutConstraint! 처럼 변수로 받아온다.

그리고 ChildViewController에서 내용물이 모두 그려지는 시점(주로 viewDidAppear)에 전체 컨텐츠의 높이를 parentViewController에 알려준다.

알려주는 방법은 NotificationCenter를 이용했다.(아직 RxSwift의 observable이 무엇인지 잘 모르기에.)

 

그렇다면 parentViewController에서는 해당 Notification이 있을 때마다 someViewHeightConstraint.constant 값을 변경해주면 끝이다.

내 경우에는 화면을 한없이 늘려보고 싶어서 parentViewController안에 미리 scrollView를 올려놓고 그 안에 containerView들을 담았다.

 

위와 같은 원리로 총 네 개의 containerView들을 쌓아봤다.

그리고

첫 번째 viewController에는 label을 하나 올려놓고 AAAAAAAAAAAAAA... 같은 텍스트를,

두 번째 viewController에는 label을 하나 올려놓고 BBBBBBBBBBBBB... 같은 텍스트를,

세 번째 viewControlle에는 오렌지 색 cell을 가지는 collectionView를 올려놓았다.

마지막 네 번째 viewController에는 회색 cell을 가지는 tableView를 올렸다.

첫 번째 두 번째는 글자수를 아주 많이 넣어 높이를 늘렸고,

세, 네 번째는 높이를 좀 더 크게 하기 위해 cell의 개수를 많이 줬다.

그렇게 만들어본 화면은 다음과 같다.

 

ABCD

그럼 이걸 왜 만들어서 쓰는걸까?

멘토님께서는 위에서 내가 만든 것처럼 각각의 뷰들을 모듈화하여 만들어오라고 하셨다.

그럼 이걸 왜 만들었을까?

바로 1, 2, 3, 4 번 각각의 view들은 다른 부서의 요청에 의해

내용물뿐만 아니라 위치까지 자주 바뀌어야 하기 때문이다.

 

구현해놓고 보니 별 것 아니지만 그래도 이것을 구현하기 위해 노력했던 것도 바로 내용 및 순서를 자유자재로 바꾸기 위해서다.

내용이야 해당 viewController 안에 있는 로직만 바꾸면 되지만 높이는 어떻게 바꿀 수 있을까 고민했고,

그 결론이 constraint.constant를 변경하는 것이었다.

그렇다면 내 의도대로 한번 각각의 모듈의 위치를 바꾸어보자.

지금 화면은 A - B - CollectionView(오렌지색) - tableView(회색) 으로 구성돼 있다.

이 순서를 A - CollectionView(오렌지색) - B - tableView(회색) 으로 바꾸어보자.

그러니까 B와 CollectionView의 위치를 바꾸어보자는 것.

아니 내용도 바꾼다고 생각할 겸 collectionView의 색도 초록색으로 바꾸자.

이것을 해내는 데에 걸리는 시간도 재보겠다.

 

변경한 화면은 다음과 같다.

 

ACBD

그리고 위치를 바꾸는 데 걸린 시간은 정확히 1분 2초 18이었다. (01:02:18)

어떻게 한 건지 궁금한 분들을 위해 글의 맨 아래에 상세한 방법을 적어두겠다.

 

아직까지는 추측이지만 멘토님께서 의도하신 건 이렇게 아주 단시간 안에 모듈을 바꿔보라는 것이었다.

만약 이것을 모듈화하지 않았다면 위와 같이 순서를 바꾸는 데 더 많은 시간이 걸렸을 것이고,

위 예제에서 바꾼 건 단순히 label과 collectionView 의 위치를 바꾼 것과 동일하지만

해당 모듈을 구성하는 내용이 복잡해지면 복잡해질수록 구현에 걸리는 시간은 곱절로 늘어갈 것이다.

이 차이를 두고 멘토님은 내일이 있고 없고의 차이 라고 하셨다. 내일이 없다는 건 오늘 집 못가고 계속 코딩만 해야 하기 때문이다.

(뭔가 멘토님 말씀을 공자의 논어 몇 편 무슨 구절같이 말하는 것 같다 ... ㅋㅋ)

 

이게 만약 프론트엔드에서 자주 쓰는 프레임워크(

페이스북에서는 라이브러리라고 주장.

)인 React였다면 화면을 Component로 쌓아올려 모듈화를 쉽게 이루어낼 수 있다. 그냥 해당 프레임워크가 그렇게 구성하도록 했으니까.

그러나 app은 그렇지 않다. app에서는 한 화면이 하나의 component가 된다. 그러니까 내가 이렇게 하나의 화면을 여러 개의 viewController로 쪼갠 것은 component 하나를 또 다른 component들로 다시 쪼갰다고 볼 수 있다.

 

후기 및 다음 할 것

후기

(먼저 업계에서 어떤 일이 비일비재하고 그에 맞추어 개발자들이 뷰를 구성해야 하는 방식에 대해 알려주신 멘토님께 감사드립니다.)

Module이라는 단어에 대해 잘 알지 못해 해당 단어가 나올 때마다 약간 당황하고 뇌정지가 왔었는데, 이제는 직관적으로 바로 이해할 수 있겠다는 자신감이 생겼다.

그리고 다른 프로젝트를 할 때 오늘 화면을 구성한 방법을 무조건 적용해봐야겠다.

그리고 MVVM을 미리 공부해간 것이 크게 도움이 되지는 않았다..ㅠ 하지만 프로젝트를 하게 된다면 반드시 MVVM 아키텍쳐를 적용하겠다는 생각이다.

마지막으로 Observable이라는 개념을 아직 잘 알지 못해서 NotificationCenter를 쓰고 있는데, 아마도 RxSwift를 배우고 나면 notificationCenter를 더 쉬운 방식으로 대체할 수 있을 것이다. 그러니 한번 배워봐야겠다.

 

다음 할 것

iOS 디바이스를 좀더 연구할 것이다. 어떤 센서가 있는지 조사하고, 해당 센서들로부터 정보를 얻어오는 연습을 할 것이다.

또한 GPS, Bluetooth, NFC, Device 자체 정보 등 smartPhone 에만 있다고 생각하는 것들을 위주로 탐색해야겠다.

 

마지막 예제에서 어떻게 위치를 바꾸었을까?

마지막 예제에서 어떻게 위치를 바꾸었는지 이미지를 첨부하여 소개한다.

 

스크린샷 2021-04-06 오후 3 59 36

 

스크린샷 2021-04-06 오후 4 01 01

 

스크린샷 2021-04-06 오후 4 02 39

 

스크린샷 2021-04-06 오후 4 03 43

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기
// custom