본문 바로가기

Swift

확장(extension)을 이용해서 테이블 뷰 리팩토링하기


왜 이런 방법을 생각했나



아래의 화면 보자









대부분의 앱은 이런 식으로 ViewController 안에 TableView를 포함하고 있다.


iOS에서 TableView는 'TableView Protocol'에 따라서 몇 개의 필수 함수를 구현해서 사용한다. (numberOfRowsInSection, cellForRowAt 같은)


우리는 Obj-C 때부터, 이렇게 ViewController 안에 테이블 뷰가 존재하는 경우 TableView 구현 내용이 상당 부분을 차지하면서 ViewController의 코드 흐름을 방해하는 느낌을 강하게 받아 왔다. 만일 다중 Table의 경우에는 이 문제는 더 심각해진다.


우리는 TableView를 사용할때 TableView의 내용만 따로 분리 할 수 있는 좋은 방법이 없나 찾아보게 되었다.







확장(extension)



이 문제도 MVVM 디자인 패턴과 확장(extension)을 이용해서 해법을 찾을 수 있었다.

방식 자체는 MVVM 디자인 패턴과 비슷하니 아래의 내용을 알고 있으면 구현에 도움이 된다.


MVVM 디자인 패턴과 확장(extension) 알아보기



방식은 간단하다. ViewModel 방식을 이용해서 데이터 소스 부분을 ViewModel에 포함 시키고, 확장을 이용해서 TableView Delegate 함수를 구현하였다.







실제 적용 방법







이 소스는 리팩토링 전의 소스이다. 내용의 상당 부분이 테이블 뷰에 관련된 내용임을 알 수 있다. 이제 TableView에 관련된 소스를 모두 추출하여 ViewModel 클래스를 하나 만들 것이다. 아래와 같이 클래스를 구성하였다.








해당 TableView에서 사용될 ViewModel 클래스를 만들었다. 해당 클래스를 만들때 필요한 사항은 테이블에 그려질 데이터와 TableView가 포함되어 있는 View Controller이다.


이 앱은 TableView를 그릴때 헤더 정보가 있기때문에 데이터는 헤더와 데이터 소스 두가지 이다.


이렇게 클래스를 구성했으면 이제 ViewModel을 확장해서 TableView Protocol을 구현한다.

여기서 필요한게 TableView가 속해 있는 ViewController이다. 컨트롤러를 인수로 받아서 뷰를 그리는데 사용한다.








완성된 소스는 위와 같다.

이제 ViewModel을 TableView에 연결해 보자.






엄청 간단하다. 이제 ViewController 내에는 TableView를 구현하는 소스가 사라졌다.(전체 완성 소스는 밑에 있다.)











그래서 뭐가 좋아졌니?



우리는 TableView도 ViewController가 사용하는 View 중 하나일 뿐인데 소스 상에서 "많은 부분"을 사용하고 있는점이 뭔가 자연스럽게 느껴지지 않았다.

또한 기존 방식은 코드를 흐름대로 이해하는데 방해가 된다.


TableView Delegate 소스를 MARK한다고 생각하면 이 문제가 더 잘 이해가 된다. 대체 MARK한 소스 묶음을 어디에 놓을 거지? 


소스 맨 앞?? 아니면 맨 뒤?? 


어디에 놔도 구조상으로 자연스럽지 않다.



위와 같은 방식으로 코딩을 할 경우,


첫째로 이제 TableView도 UILabel이나 UIButton과 같이 본래의 "분량(?)"을 차지하게 된다는 장점이 있다.

ViewController중간에 길게 늘어진 TableView Delegate 함수가 없어지므로,


두번째  ViewController 소스 코드의 흐름이 자연스럽게 되었다.









ViewController는 해당 화면이 실행되면 순서대로 라벨과 테이블을 구성해서 뷰에 보여준다. 또한 TableView관련 소스가 빠지면서 컨트롤러의 역할에 좀더 충실해 진다.





세번째로 TableView의 활용이 좀더 유연해졌다는 점이다.











이 앱에서 해당 테이블을 사용하는 컨트롤러는 두 개다. 위 이미지에서 주황색으로 표시된 뷰는 동일한 테이블뷰를 사용하는 ViewController이다. 보통 이럴경우 이 테이블을 같이 사용하기 위해서는 상속 외에는 손쉬운 방법이 없다.

그러나 이 방법을 사용하면, 이제 TableView를 재사용하기가 매우 유연해진다. 해당 테이블을 사용하고자 하는 컨트롤러는 위에서 만든 ViewModel을 이용하기만 하면 된다!










프로젝트 내의 모든 TableView를 해당 방식으로 변경하였다. 좀 더 구조화된 모습이다. 이제 나머지 프로젝트에도 이 방법을 적용하면, 인수인계 해야 할 내용이 하나 더 줄어들게 되었다!!! 😆








물론 ViewModel을 사용하는것은 파일의 갯수를 늘린다는 점에서 오히려 단점이 될 수도 있다.

하지만 프로젝트가 커질수록 중요한 부분은 파일의 갯수가 아니라,


잘 구조화된 소스이다.


이런 구조화의 이점은 유지보수에만 해당되는 것이 아니며,

새로운 앱의 개발때에도 적용할 수 있다는 점에서 상당히 훌륭한 구조라 생각된다.



결론적으로



한번 써봐도 좋을거 같습니다! 추천!