RxSwift

[RxSwift Community] RxFlow 사용하기 전에...

Developer.Paul() 2021. 6. 11. 17:23

이번 포스팅에서는 RxCommunity 중에서 가장 인기가 많은 RxFlow에 대해서 알아보려고 합니다. Coordinator Pattern에 대한 글을 적다가 포기했는데, 이게 쉽게 쓰면 엄청 쉽고 복잡하게 쓰면 정말 복잡하게 쓰게 되는... 말 그대로 너무 다양하게 구현할 수 있기 때문에 기본적인 개념을 익히는게 중요한데, 이런 글은 이미 많아서 스킵했습니다. 혹시 Coordinator Pattern의 이점이나 컨셉이 궁금하신 분들은 Khanlou님의 글을 정독해보시는걸 추천드립니다:)

 

https://github.com/RxSwiftCommunity/RxFlow

 

RxSwiftCommunity/RxFlow

RxFlow is a navigation framework for iOS applications based on a Reactive Flow Coordinator pattern - RxSwiftCommunity/RxFlow

github.com

예제는 아래 링크에 있습니다:)

https://github.com/Developer-Paul-t/RxSwift

 

Developer-Paul-t/RxSwift

Contribute to Developer-Paul-t/RxSwift development by creating an account on GitHub.

github.com

이번 RxFlow 예제는 이제까지 포스팅한 RxCommunity 라이브러리를 함께 사용해서 제작한 뉴스앱입니다. 시작하시기 전에 https://newsapi.org 링크로 들어가셔서 로그인을 하시면 개인 Token을 받으실 수 있으니 사용하시면 되겠습니다:) RxFlow는 몇 번을 나눠서 포스팅할 예정이니 천천히 읽어봐주세요.

 

 

1. Coordinator의 필요성

 

 

위의 코드는 RxFlow를 적용하기 전, MainViewController에 있는 코드입니다. 우리에게 아주 익숙한 화면 전환 로직이죠. 하지만 개선점이 보이는 코드이기도 합니다. 매번 어떤 뷰로 갈 때마다 위의 코드를 반복해야 하고 또 수정이 필요할 때는 우리가 적었던 코드를 하나 하나 수정해야 하기 때문입니다. 기술부채가 늘어나게 되죠. 이 로직만 따로 관리할 수는 없을까요? 이 질문에 대한 대답을 Coordinator Pattern이 하고 있습니다. 자세한 내용은 Khanlou님의 글을 참고해 보세요.

 

https://khanlou.com/2015/01/the-coordinator/

 

Khanlou | The Coordinator

January 20, 2015 The Coordinator One of the biggest problems with the big view controllers is that they entangle your flow logic, view logic, and business logic. When a table cell is selected, that delegate method typically looks like this: - (void)tableVi

khanlou.com

https://khanlou.com/2015/10/coordinators-redux/ 

 

Khanlou | Coordinators Redux

October 5, 2015 Coordinators Redux I wrote about coordinators at the beginning of the year, but the idea has matured a lot since then, and I’d like to reintroduce the topic with all of my learnings from the last few months. This is adapted from a talk I

khanlou.com

 

2. RxFlow의 필요성

하지만 이런 Coordinator Pattern을 사용할 때, 몇 가지 단점이 있습니다. 첫 번째로 매번 새로운 프로젝트를 시작할 때마다 코디네이터 패턴을 새로 짜야 합니다. 앱의 화면 전환에 어울리는 코디네이터를 고민하고 짜고 구현하는데 생각보다 시간이 많이 듭니다. 두 번째는 boilerplate code가 많아진다는 겁니다. 물론 하드 코딩을 피할 수 있지만, 코디네이터를 작성하고 사용하면서 stack이 쌓이게 되면 그만큼 boilerplate code가 많아집니다. RxFlow 이런 Coodinator Pattern의 단점을 보완하고 Reactive Programming의 장점을 받아, 행복한 코딩(?)을 할 수 있게 만들어줍니다... ! 한번 익혀놓으면 모든 프로젝트에 빠르게 적용가능하고 기술부채도 줄여주니 금상첨화죠! 하지만 러닝커브가 극악입니다.

 

3. RxFlow를 배우기 전에

그렇기 때문에 아래 keyword를 먼저 눈으로 익힌다면 도움이 될 겁니다.당장은 이해되지 않더라도 고민하며 읽어보시면 다음 글을 이해하시는데 도움이 되실 것 같습니다:)

 

Step
Step은 '상태'를 의미합니다. Step은 navigation을 lead 할 수 있는 '키'입니다. RxFlow는 이 키를 추상화해서 '상태'로 표현한 뒤, 이 상태에 따라서 다르게 동작하도록 구현되어 있습니다. 이 상태는 공유되지도 않으며, 앱에서는 한정되어 있습니다. 또 단일 값을 가질 수 있기 때문에 가장 적합한 enum으로 정의합니다. 그리고 각 상태를(Step) case로 구분합니다. case를 구분할 때는 각 경우의 수가 유사한 방식으로 구현되는건 의미가 없습니다. detail1과 detail2는 같은 목적을 가진 상태입니다. 차라리 detailIsNeeded(with: ID)로 associatedValue와 함께 정의해주는 것이 좋습니다. 굳이 두 가지 상태로 나눌 필요가 없는거죠. 하지만 추천하는 방식은 아닙니다. 이건 뒤에서 더 이야기하죠. 아무튼 RxFlow는 이 상태의 변화에 주목하고 있다는 사실을 기억하세요!

 

Flow
Flow는 '공간'을 의미합니다. 이 공간에서 무엇을 보여주던가 어디로 가던가하는 navigate가 일어납니다. 상태는 공간에 따라서 그 결과가 달라집니다. 예를 들어, thumbs up이 어떤 나라에서는 칭찬이고 어떤 나라에서는 욕인 것처럼요! 마찬가지로 Step은 그 Step이 현재 있는 Flow가 어디냐에 따라서 navigate의 결과가 달라집니다. 한편, 이 둘(Flow, Step)만 있으면 우리가 원하는 navigation action을 실행할 수 있습니다. Step이 변화되면 그것을 실제로 실행하는 기능(push, present)은 Flow에 있습니다.

 

Stepper
Stepper는 Flow 안에서 step을 방출하는 모든 것(anything)입니다. step을 방출한다? stepper! 새로운 상태로의 변화를 알려줘야 하는 ViewController, ViewModel, Custom 구조체, 클래스 등 누구나 이 프로토콜을 채용하면 Stepper가 될 수 있습니다.

 

Presentable
Presentable은 프로토콜인데, UIViewController나 Flow, Window와 같이 보여질 수 있는 것들을 추상화한 것입니다. 위의 세 요소는 Presentable을 extension에서 채택하고 있습니다. RxFlow에서 우리가 직접 구현하는 것보다 파라미터에서 마주할 일이 더 많을 겁니다.

 

FlowContributor & FlowContributors
이 두 형제는 enum으로 정의되어 있습니다. Flow의 결과물을 가지고 새로운 Flow로 가서 새로운 Step으로 새로운 navigate를 하거나 부모나 앞선 Flow로 가서 동일한 동작을 반복하기도 합니다. 이름 그대로 Flow의 생성과 활동에 기여합니다. 앞서 말씀드렸다시피 Flow가 활동하기 위해서는 Step이 필요합니다. 그래서 Flow와 Step을 가지고 있습니다.

 

FlowCoordinator
FlowCoordinator는 RxFlow에서 기본으로 제공하는 요소입니다. FlowCoordinator의 역할은 앱의 모든 네비게이션을 관리하는 것입니다. 일반적으로 SceneDelegate나 AppDelegate에 인스턴스를 생성해서 가장 기반이 되는 Stepper와 Flow를 파라미터로 받습니다. 그리고 FlowCoordinator를 통해 하위 Flow에 대한 트리를 형성해 앱 전체를 관장합니다.

 

다음 글에서는 step by step으로 RxFlow를 적용해보면서 개념을 하나하나 익혀나가보겠습니다:)