iOS프로젝트/Funch(넥스터즈)

모듈화 리팩토링 과정에서 고민했던 것들

lgvv 2024. 9. 24. 00:50

모듈화 리팩토링 과정에서 고민했던 것들

 

Tuist 3.x 버전으로 사용한게 마지막이라 4.x 버전으로 학습하고 변경해보고자 함.

최근 모듈화 관련 글과 다른 사람들이 사용한 Tuist 프로젝트를 여럿 보면서 어떤 부분은 기존에 내가 사용하던 부분보다 나은 점도 많다고 느낌.

매번 모듈화에 같은 구조를 사용했는데, 다른 사람들이 작성한 프로젝트를 참고해 해당 구조로 구성하여 작성해보면서 장단점에 대해서 고민해보고자 함.

 

글의 순서

  • 프로젝트 모듈화 구조 스크린샷
  • 리팩토링 시작 전 생각 정리
  • NetwrokSDK 모듈에 대해서
  • feature에서 ui를 분리한 이유
  • 화면전환 어떻게 할 것인지
  • 이미 구현된 UI가 필요한 경우는 어떻게 할 것인가?
  • 관리하는데 드는 비용에 대한 고민
  • 마무리 소감

 

프로젝트 모듈화 구조 스크린샷

 

 

리팩토링 시작 전 생각 정리

  • 기존 작성된 코드에서 더 나은 방법이나 스타일이 있더라도, 새롭게 만드는게 아닌 기존 코드를 유지한 채 모듈화에 집중하는 방향으로 진행할 것.
  • 개발 환경은 macOS 15, XCode 16, Tuist 4점대.
  • Tuist에서 권장하는 mise 사용할 것.
  • 기간은 1달 이내로 끝낼 것.
  • Core, Shared, Feature, UI, App 5가지 레이어로 분리
    • Core: 제일 아래 레이어에 위치해 동일 레이어 간 다른 영역에도 의존하지 않음.
    • Feature: 사실상 Domain
      • 기능을 여러 Presentation 레이어에서 사용할 수 있도록 만듦.
      • 서비스에서 특정 UI만 필요한 경우가 있는데, 순환참조를 줄이고자 Presentation 레이어 (UI)를 분리
    • Shared: TCA로 친다면 Dependency로 구현되는 Client들
      • UI가 없는 친구들
    • UI: Presentation 레이어
      • 분리한 이유: 단순하게 UI만 필요한 경우가 있는데, Feature에 있을 때 순환참조 생기는 경우 있어서 수정
    • App: 앱 스토어에 배포할 앱 서비스들
      • 여러개를 조합해서 여러 앱을 만들 수 있도록 설계
  • 그냥 Core, NetworkSDK, Domain, Feautre(+ feature interface), App으로 구성하는게 나아 보임.
    • 여러 프로젝트의 구조를 분석하고 해당 구조에서 장점이라고 생각했던 부분들을 직접 적용해보니까, 재사용과 확장 모듈 의존성, 네이밍 등에 대해서 고민이 많았는데, 위 형태가 제일 나아 보임.

 

 

NetwrokSDK 모듈에 대해서

서비스를 운영하다 보면 동일한 api가 여러 영역 혹은 기능에서 필요함.

  • 여러 Feature에는 Data, Domain, Presnetation이 속하는데, Data에는 RepositoryImpl이 들어있었음.
  • 하지만, 하나의 권한 조회 API가 있을 경우 여러 Repository에서 사용 될 경우 Feature가 늘어나거나, 이미 구현된 해당 Feature를 의존하거나 등등 여러 방법으로 해결할 수 있기는 함.
  • 하지만, NetworkSDK를 만들어서 구현부에 대한 관리 포인트를 확실하게 하나로 둘 경우 네트워크 영역 개발에 따른 피로감을 줄일 수 있기에 이 방향으로 설계하고자 함.
  • 리팩토링 적용 여부
    • NetworkSDK를 만들어서 Spec 단위로 관리하면 편리하여 시도.
    • 경로만 함께 관리하고, 구현부는 나중에 옮기는 방향으로 단계별로 진행 예정.

 

feature에서 ui를 분리해 본 이유

사실상 Feature가 Domain의 역할을 하게 되면서 UI를 갖기가 애매해짐.

  • 또한 UI가 Feature에 있는 구조에서는 화면전환이 아니라, 단순히 해당 UI가 필요하면 그 UI가 구현된 Feature를 의존하거나(의존성 순환 문제 발생 가능) 별도의 모듈을 두는 방법(별도 모듈 만드는 비용)으로 처리할 수 있음.
  • 의존성을 고민하는 비용이 개인적으로 꽤나 높은 비용이라고 생각되어서 UI 레이어를 분리해서 개발.

 

화면전환 어떻게 할 것인지

Coordinator 모듈을 통해 적당한 사이즈로 쪼개 관리하는 방향으로 설계하여 해결.

  • 기존 서비스에서 A UI -> B UI 였지만, 운영되면서 B UI -> A UI가 될 수도 있음 (A UI를 구현하는 비용이 매우 크다고 가정)
  • 직접 드는게 아니라 화면 전환은 Coordinator 모듈을 통해 처리함.

 

이미 구현된 UI가 필요한 경우는 어떻게 할 것인가?

이런 부분을 고려해 Shared라는 레이어를 두었음.

  • 사내에서 리스트 UI와 관련한 모든 부분을 묶어서 제공하는 케이스가 있었는데, 사실 유틸, 기능, 컴포넌트 등과 관련한 기능들을 매우 많이 제공해주고 있음. 애플의 EventKit과 비슷함.
  • 이런 부분들을 Shared에 두어서 처리하기로 결정.

 

관리하는데 드는 비용에 대한 고민

모듈이 너무 많을 경우 파악하기가 힘들고, 인지할 수 있는 범위를 넘어설 경우 소통에 비용이나 파악하고 관리하는데 드는 비용이 생각보다 너무 크다고 느낌.

  • 적절한 모듈 수를 유지하는게 좋다고 판단했고, Feature를 사실상 도메인의 기능으로 변경함.
  • 1년 전, 3점대로 학습했던 구조에서는 Feature에 UI, Domiain, Data를 모두 구현했었는데, 이 구조에서부터 시작해서 네이밍이 조금 애매하지 않나 싶음. Feature보단 Domain이 더 적절하지 않을까?

 

마무리 소감

처음 학습했을 때 잡았던 구조로만 계속 작업하면서 여기에 고착화 된 느낌을 받아 다른 사람들은 실제로 어떻게 사용하고 있는지 많이 찾아보고 적용해 보았음. 기존 짜여진 코드를 해당 새로운 구조로 이식할 때, 모듈의 특정 기능만 필요할 때, 순환 참조 문제, 모듈 구조에 의한 관리 비용, 테스트 등 여러가지 형태를 학습하고 직접 사용해보면서 장단점도 느꼈고, 하면서 특정 문제를 해결하는데 더 다양한 시각을 얻게 된 것 같음.

프로젝트 옮기는걸 너무 오랜기간 잡고 있을 수 없어서 1개월 정도로 기한을 정해두고 시도한거라 ~하면 더 좋을거 같은데? 한 부분도 있었지만, 적당히 만족스럽게 마무리.

 

이후에는 프로젝트에서 벗어나서 Tuist 내에서 Fastlane이라 confing, 모듈별로 더 작은 앱을 잘 만드는 방법에 대해서 집중해보고자 함.