포스트

[Swift] 모듈화를 통해 물리적으로 3-Layer 분리하기

[Swift] 모듈화를 통해 물리적으로 3-Layer 분리하기

팝풀 프로젝트에서는 MVVM 기반으로 시작했지만, ViewModel이 점점 복잡해지고 로직이 뭉치면서 유지보수가 어려워지고 있었다.

이를 개선하기 위해 클린 아키텍처의 개념을 도입했지만, 실제로는 논리적으로만 레이어를 구분했을 뿐, 물리적인 분리 없이 코드가 뒤엉켜 있었다.

이로 인해 팀원들이 의존성 방향을 인지하지 못하고 코드를 작성하면서 결합도가 높아졌고, 자연스럽게 아키텍처의 방향성과 일관성도 무너지기 시작했다.

대표적으로 다음과 같은 문제들이 있었다.

  • PresentationLayer에서 Domain이 아닌 DataLayer의 구현체(Service)를 직접 참조하면서, 레이어 간 의존성이 뒤엉켜 있었다.
  • ViewModel에서 하나의 화면을 구성하기 위해 여러 UseCase가 필요했지만, 의존성 주입이 일관되지 않고 번거로운 방식으로 이뤄지고 있었다.
  • DTO와 Entity가 명확히 구분되지 않아, Domain과 Presentation 레이어에서 직접 DTO를 가져다 쓰는 경우가 빈번하게 발생했다.

결국 우리는 이 문제를 해결하고자 모듈화를 통해 물리적으로도 3-Layer 구조를 분리하기로 했다.

[GitHub PR] 팝풀 3-Layer 클린아키텍처 모듈화

[REFACTOR] 3-Layer 기반 클린아키텍처로 모듈화

🏡 아키텍처 구조

팝풀의 클린아키텍처 구조도

1차적으로 팀과 회의를 거처 기존에 의도했던 아키텍처 구조와 개선점을 고려한 새로운 아키텍처 구조를 만들었다.

3-Layer 아키텍처를 물리적으로 분리하면서, 각 레이어가 명확히 역할을 분리하도록 구성했다.

1
Presentation → Domain → Data

또한 공통 유틸성 코드는 Core 모듈에 위치시켜, 공통적으로 사용하는 타입 또는 유틸리티에 접근할 수 있도록 했다.

🤔 주요 고민과 해결

1. 의존성 주입의 정립과 DIContainer 도입

기존에는 각 ViewModel에서 직접 구현체를 생성하거나 가져다 쓰는 방식이었지만, 이는 테스트가 어렵고 재사용이 힘든 구조였다.

그래서 의존성 주입을 위한 방법으로 DIContainer를 도입하고, 이를 통해 필요한 인스턴스를 등록-주입받는 구조로 전환했다.

또한 @Dependency 프로퍼티 래퍼를 통해 DI를 보다 간결하게 표현할 수 있게 되어, ViewModel이 의존성에 대해 덜 알게 되는 구조를 만들 수 있었다.

팝풀의 DIContainer 도입기

PropertyWrapper를 이용한 DIContainer 만들기 - Layer간 의존성 흐름 개선하기

2. DTO와 Entity의 분리

DataLayer에서 사용하는 DTO를 Domain과 Presentation에서 직접 가져다 쓰는 경우가 많아, 레이어 간 결합도가 매우 높아졌다.

이를 해결하기 위해 DTO는 DataLayer에서만 존재하도록 하고, Domain에서는 Entity로 변환된 형태만을 사용하도록 기준을 세웠다.

toDomain() 메서드를 통해 변환 과정을 명시함으로써, 레이어 간 역할과 책임을분명하도록 수정하였다.

🏁 마무리

처음에는 뭐 public이랑 import만 잔득 추가해주면 금방 끝날줄 알았지만 장차 2주의 기간동안 팀원과 분담을 하면서 진행했었다.

이 과정에서 발생하는 문제를 나만의 문제라 느껴지지 않도록 자주 미팅을 진행하며 방향성에 대해 얘기했다.

또 추가 작업이 필요한 경우 팀이 문제를 헷갈려하지 않도록 요구사항 정리 문서도 열심히 작성해서 전달드리기도 했다.

여러 요구사항 중 하나

이번 모듈화를 통해 각 레이어의 책임을 명확히 분리하고, 의존성 방향성을 일관되게 유지할 수 있었다.

하지만 아직 개선해야 할 부분도 존재한다.

  • DataLayer 내에서 네트워크 로직까지 담당하고 있는 Data 모듈 세분화
  • 일부 서비스 로직이 Core 모듈에 남아 있는 구조를 UseCase 단으로 옮겨 레이어 간 역할 추가 분리
  • 공통 패키지의 의존 방식을 static에서 dynamic으로 전환해 중복 포함을 방지

하지만 우선은 이번 과정을 통해 단순한 구조 개선을 넘어서 팀 전체의 아키텍처 방향성을 공유하는 계기가 될 수 있었고, 팀과 함께 높은 유지보수성의 코드를 만들어갈 수 있는 기반을 마련할 수 있었던것 같다.

🔗 레퍼런스

해당 자료를 찾아보며 도움이 됐던 링크

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.