최근 당근페이로 이동하면서 신규 앱 개발을 시작하게 되었습니다.
신규 앱은 당근마켓과 다른 도메인의 서비스로 요구사항이 다르기 때문에, 짧은 기간동안 신규 앱에 사용할 개발 스택에 대한 고민을 시작했습니다.
여러 고민 끝에 당근마켓과는 다른 개발 스택을 사용하기로 결정했습니다.
(대표적으로 ReactorKit 과 UIKit 을 사용하게 되었습니다.)
오늘은 그 중 UIKit (FlexLayout & PinLayout) 을 사용하게 된 과정과 그에 대한 활용에 대해 적어보려고 합니다.
기존 앱 개발 — Texture 사용
먼저 당근마켓에서는 Texture 라는 UI Framework 를 사용하고 있었습니다.
Texture 는 많은 분들이 아시다시피 Facebook (Meta) 에서 만들어 Pinterest 에서 관리하고 있는 프레임워크로 UI 성능 개선, 셀 자동 높이 계산, 선언형 UI 구성이 가능하다는 장점을 가지고 있습니다. (여러 편의 기능이 추가되는건 덤!)
당근마켓에서 동네생활 이라는 커뮤니티 서비스를 개발할 때는 이러한 이점들을 적극적으로 활용할 수 있었습니다. 복잡한 피드를 구성하거나 동적으로 UI 를 변경할 때 간편하게 처리할 수 있었습니다.
또한 커뮤니티 서비스에 필요한 여러 기능들을 Texture 에서 제공하는 기능으로 쉽게 구현할 수 있었습니다.
신규 앱 개발 — UIKit 사용
이처럼 여러 장점을 가진 Texture 였지만 신규 앱 개발에는 사용하지 않기로 했습니다.
대표적으로 아래의 3가지 이유가 있었습니다.
1. 신규 멤버에게 큰 진입장벽
Texture 를 처음 사용하는 신규 멤버에게는 진입장벽이 되었습니다.
FlexBox 형태의 레이아웃 방식과 Texture 만의 LifeCycle 을 같이 학습해야 했습니다.
한국어 위키를 적어서 가이드를 했었지만.. Texture 에서 성능향상을 위해 Background thread 를 같이 활용하기 때문에 많은 분들이 이에 대한 어려움을 겪었습니다.
2. 작성 화면(Form) 에 부적합한 방식
Texture 는 리스트형 UI 을 구현할 때는 편리하지만, 작성 화면을 구현할 때는 까다로운 부분이 많습니다.
먼저 UITextField 같은 1줄 입력 컴포넌트가 지원되지 않고, 섬세한 애니메이션, 사이즈 변경, 스크롤 처리가 어려웠습니다. 이로 인해 일부 화면에서는 부자연스러운 동작이 발생하기도 했습니다. (화면이 깜빡이거나 튀는 현상)
신규 앱의 경우 작성 화면이 많기 때문에 View Life Cycle 을 섬세하게 다룰 수 있는 UIKit 을 사용하는게 적합했습니다.
3. 관리 부재
메인테이너 분들의 이직 등의 이유로 Texture 의 관리가 이루어지지 않고 있었습니다. iOS 13 부터 버그 수정 정도의 작업만이 이루어졌고, iOS 15 부터는 여러 크리티컬한 문제들이 해소되고 있지 않습니다.
새로운 UI 구성 방법
UIKit 을 사용하기로 결정하면서 어떻게 레이아웃을 구성할지 고민하기 시작했습니다.
N 년 전에 개발할 때는 AutoLayout의 성능 문제를 해결하기 위해, 셀 혹은 컴포넌트는 직접 frame 을 계산해 레이아웃을 구성했습니다.
최근에는 UI 에 사용할 수 있는 많은 도구가 생긴 것 같아, 조금 더 좋은 방식이 있는지 찾아보았습니다.
그 중 후보군이 된 것은 아래와 같습니다.
- SnapKit : AutoLayout 을 더 편하게 사용 가능
- FlexLayout & PinLayout : Texture 와 동일한 FlexBox 형태
- Anchor & frame (순정) : 순정이 최고야
- ~SwiftUI~ : 안정성 문제로 안녕..
가볍게 결정하면 이후에 합류할 동료에게 고통을 선사할 수 있을 것 같아, 지인분들을 대상으로 간단한 설문조사를 해보았습니다.
- 답변 1 : 스토리보드
- 답변 2 : 기본적인 앵커와 스토리보드만 사용하다가 SwiftUI 로 넘어가기
- 답변 3 : PinLayout & FlexLayout
- 답변 4 : SwiftUI
- 답변 5 : frame 계산
- 답변 6: 스토리보드를 기본으로, 필요에 따라 앵커 사용
- 답변 7: SnapKit 사용
- 답변 8: SnapKit & FlexLayout & PinLayout 모두 사용
예상과 다르게 다양한 결과를 얻을 수 있었습니다.
여러 회사에서 UI 구현에 다양한 도구를 사용하시는 것 같아.. 편하게 마음에 드는 것으로 고를 수 있었습니다 :D
FlexLayout
결국 사용하기로 결정한 것은 FlexLayout 입니다. 곧 SwiftUI 를 사용할 수 있는 만큼 가급적 선언형과 유사한 방식으로 작성할 수 있으며 렌더링 퍼포먼스가 빠른 도구를 선택했습니다.
FlexLayout 은 Texture 와 동일하게 Yoga 를 기반으로 만들어졌고, 아래의 사진처럼 빠른 성능을 보여주고 있었습니다.
FlexLayout 은 PinLayout 과 같이 사용하면 더 간편하게 사용할 수 있었습니다.
FlexLayout 은 FlexBox 의 역할을 하는 Container 를 만들고 레이아웃을 잡는 형태이기 때문에 레이아웃을 조절하기 전에 Container 의 사이즈를 먼저 지정해야 합니다. 이 때 PinLayout 을 이용해 이 Container 의 레이아웃을 간편하게 지정할 수 있습니다.
FlexLayout 에 대한 가벼운 사용 방법은 아래의 코드를 참고해주시면 됩니다.
SwiftUI Preview 활용하기
새롭게 UI 를 작성하게 되면서 SwiftUI Preview 도 함께 사용했습니다.
문제가 있는지 가끔씩 Preview 가 동작하지 않았지만, 일반적인 경우에는 잘 동작하여 UI 를 구현하기 더 간편해졌습니다.
Preview 는 별도의 빌드 과정을 거치기 때문에 프로젝트가 가볍지 않으면 사용하기 어려울 수 있습니다. (필자는 모듈화를 통해 해결)
먼저 BaseViewController 를 아래처럼 구성했습니다. ViewController 와 View 를 분리하여 ViewController 에 과도하게 많은 코드가 작성되지 않게 만들었습니다.
그 다음 SwiftUI Preview 를 사용할 수 있도록 만들어주는 UIViewPreview 를 만들고 각 화면에서 그것을 활용했습니다.
마무리
UI 를 그리는 방법이 다양해지면서 서비스에 맞는 선택을 하는게 더 중요해진 것 같습니다. 구현 방식을 한가지로 통일하는게 좋을 수도 있겠지만, 각 팀원들이 선호하는 방식을 자유롭게 사용하며 좋은 기준을 만들어 가려고 합니다. 현재는 홀로 개발 중이기에 어렵지만요 하핳 (동료를 기다립니다..)
FlexLayout 를 UICollectionViewCell 에 사용할 때 까다로운 부분도 있습니다. FlexLayout 예제에서는 sizeForItemAt 에 사용할 더미 Cell 인스턴스를 만들어서 사이즈를 계산하고 있었는데, 더 좋은 방법이 있을지는 연구가 필요할 것 같습니다.
여기까지 신규 앱에 사용할 UI 구현 방법을 정하고 활용하는 방법에 대해 이야기해보았습니다. 다음에는 FlexLayout 과 PinLayout 을 잘 활용할 수 있는 방법에 대해 적어보겠습니다.
UI 구현에 대한 더 좋은 의견이 있으시다면, 커멘트 남겨주시면 감사합니다.