모듈화 리팩토링 과정에서 고민했던 것들
Tuist 3.x 버전으로 사용한게 마지막이라 4.x 버전으로 학습하고 변경해보고자 함.
하나의 설계 방법보단 여러가지 설계들을 보면서 느끼고 경험하는 것이 중요하다고 해서 기존 쓰던 방식을 완전히 배제하고 다른 사람들이 사용하는 방식을 따라하는 수준 + 내 스타일 적용 요정도로 해보고자 함.
글의 순서
- 프로젝트 모듈화 구조 스크린샷
- 리팩토링 시작 전 생각 정리
- NetwrokSDK 모듈에 대해서
- feature에서 ui를 분리한 이유
- 화면전환 어떻게 할 것인지
- 이미 구현된 UI가 필요한 경우는 어떻게 할 것인가?
- 관리하는데 드는 비용에 대한 고민
- 마무리 소감
프로젝트 모듈화 구조 스크린샷
리팩토링 시작 전 생각 정리
- 깃헙에 레포 돌아다니면서 다른 사람들이 사용하는 Tuist 참고하면서 그 사람들의 플로우를 적용해 볼 것
- 내가 평소에 사용하던 방식 금지!
- 다양한 설계 방법을 배우고, 느끼고, 경험해보는 것이 최대 목표!!
- 기간은 최대 1개월 !
- 개발 환경: macOS 15, Xcode 16.0, Tuist 4 버전
- Tuist에서 권장하는 mise 사용할 것.
NetwrokSDK 모듈에 대해서
서비스를 운영하다 보면 동일한 api가 여러 영역 혹은 기능에서 필요한데, 네트워크 구현까지 한곳에 모으는게 더 관리가 용이하다고 느낌
- 여러 Feature에는 Data, Domain, Presnetation이 속하는데, Data에는 Repository를 구현한 객체가 위치함
- 하지만, 하나의 권한 조회 API가 있을 경우 여러 Repository에서 사용 될 경우 Feature가 늘어나거나, 이미 구현된 해당 Feature의 인터페이스를 통해 의존하는 방법도 존재
- 인터페이스를 분리하고 관리하는 것 자체의 비용이 생각보다 피로한 작업인 것 같아서, 개인적으로는 네트워크 구현은 한곳에 몰아두는게 의존성관리도 용이하고 더 낫다고 느낌
feature에서 ui를 분리해 본 이유
다른 사람들이 한 모듈화를 참고 하다보니까, 디자인시스템의 목적이 아닌 UI를 모듈 단위로 분리해서 관리하는 것도 확인해봄. RIBs에서도 UI가 옵셔널하니까 여기서도 옵셔널하게 분리한게 아닐까 싶음
- 또한 UI가 Feature에 있는 구조에서는 화면전환이 아니라, 단순히 해당 UI가 필요하면 그 UI가 구현된 Feature를 의존하거나(의존성 순환 문제 발생 가능) 별도의 모듈을 두는 방법(별도 모듈 만드는 비용)으로 처리할 수 있음.
- 의존성을 고민하는 비용이 개인적으로 꽤나 높은 비용이라고 생각되어서 UI 레이어를 분리해서 개발.
분리해 보고 난 느낀점
- 장점: 특정 UI만 공통이고, 서로 차이가 있는 정책 및 기능으로 구현해야 하는 경우에는 하나의 Feautre에 속해있을 때보다 괜찮다는 생각이 들었음.
- 단점: 모듈이 너무 많아지고, UI만 존재할경우 DesignSystme 레이어도 존재하여 어딘가에 위치시키기가 애매해지는 것 같다는 생각이 듦. UI만 제공하고 기능 처리는 다른 곳에 위임하겠다는 목적이 있는 것 같은데, 이럴 경우 UI 모듈 자체 수정도 쉽지 않아서 이건 단점으로 느껴짐
- 트레이드 오프가 있지만, 여러 설계를 시도해 보아서 서비스에 따라 더 적합한 시스템을 적용하는 걸로.
화면전환 어떻게 할 것인지
Coordinator을 통합해 두어서 모든 화면 전환을 자유롭게 가져갈 수 있도록 설계
- Coordinator Pattern은 트리형태로 구성되어서 AFeature가 이동할 수 있는 화면은 B, C로 정의하고, BFeature가 이동할 수 있는 화면은 C, D로 각각 들고 있는 형태도 존재하는걸로 앎
- 각 Feature에서 Coordiantor를 관리할 때 장점
- 각각 나누어 둘 경우 특정 Feature에서 이동할 수 있는 화면을 명확히 제어할 수 있음
- 각 Feature에서 Coordiantor를 관리할 때 단점
- 화면 이동 경로가 A -> (B,C)와 B -> (C,D) 이렇게 기획되어 운영되다가 (B -> (A, C, D) B - A는 뒤로가기 행위가 아님)의 경로가 서비스적으로 추가될 경우 모듈 수정의 비용이 너무 큼.
- 앱 루트에서 통합관리할 때
- 앱 Root에서는 CoordinatorInteface 통해서상단에서 자유롭게 수정할 경우 TransitionDelegate 을 활용한 커스텀 화면 전환 등도 더 자유롭게 활용 가능하며, 다양한 화면전환 지원 가능
- 또한 하나의 서비스에서 앱 A, 앱 B를 지원하는 서비스일 경우에는 스킴 등을 정의해 다른 서비스에서 들어왔을 경우 별도로 Coordinator를 두어 이동을 제한하도록 만들기도 더 간편함
이미 구현된 UI가 필요한 경우는 어떻게 할 것인가?
다른 사람들의 프로젝트를 참고하면서 DesignSystem은 컴포넌트만을 담당하고 Shared에서 조금 더 세부 구현이 포함된 UI를 가지는 경우가 존재했음
- 적용해 보면서 EventKit처럼 쓰는 느낌이라서 괜찮았음
- 근데 DesignSystem 내부에서 더 잘게 쪼개진 단위의 컴포넌트와 세부 구현이 조금 더 가미된 컴포넌트로 관리해도 괜찮을 것 같다는 생각도 들었음
관리하는데 드는 비용에 대한 고민
모듈이 너무 많을 경우 파악하기가 힘들고, 인지할 수 있는 범위를 넘어설 경우 소통에 비용이나 파악하고 관리하는데 드는 비용이 생각보다 너무 크다고 느낌. 모노레포로 가는게 제일 속 시원한 듯.
- Tuist 3버전으로 처음 학습할 때는 Feature 마다 Presentation, Domiain, Data를 모두 구현해주는 구조로 공부했음
- 서비스를 운영하다 보니 특정 도메인 레이어만 필요한 경우, 데이터 레이어만 필요한 경우가 자꾸 생겨서, Domain 레이어와 Data 레이어를 별도로 분리하고 Feature는 Domiain을 조합해 ViewModel, View 형태로 가져가는게 더 나아보임.
마무리 소감
처음 학습했을 때 잡았던 구조로만 계속 작업하면서 여기에 고착화 된 느낌을 받아 다른 사람들은 실제로 어떻게 사용하고 있는지 많이 찾아보고 적용해 보았음. 기존 짜여진 코드를 해당 새로운 구조로 이식할 때, 모듈의 특정 기능만 필요할 때, 순환 참조 문제, 모듈 구조에 의한 관리 비용, 테스트 등 여러가지 형태를 학습하고 직접 사용해보면서 장단점도 느꼈고, 하면서 특정 문제를 해결하는데 더 다양한 시각을 얻게 된 것 같음.
프로젝트 옮기는걸 너무 오랜기간 잡고 있을 수 없어서 1개월 정도로 기한을 정해두고 시도한거라 ~하면 더 좋을거 같은데? 한 부분도 있었지만, 객체지향 책에서 알려준 것처럼 하나의 설계 방법보단 다양한 설계 방법들을 알고 있는게 중요하다고 해서 이것저것 시도한 실험에 가까운 모듈화였음.
결론적으로는 Core, DB, NetworkSDK, Coordiantor, Domain, Feautre, App으로 구성하는게 적정한 선에서 가장 생산성이 좋다고 느껴짐.
'project > Funch(넥스터즈)' 카테고리의 다른 글
SwiftUI 하위뷰에서 상위뷰로 DelegatePattern을 활용해 이벤트 전달하기 (0) | 2024.09.29 |
---|---|
Coordinator 모듈을 통해 UI 모듈간 순환참조 해결하기 (0) | 2024.09.24 |
SwiftUI 화면 dismiss 상황에서 흰 화면 나타나는 문제 (1) | 2024.09.22 |
Swift Concurrency를 적용하면서 발생한 동시성 문제 (0) | 2024.09.20 |
지하철 검색 기능에 캐싱 로직 도입하기 (0) | 2024.09.20 |