지난 글에서는 탭탭이 리팩토링을 본격적으로 시작하게 된 배경과, 그 첫 단계로 코드 구조를 도식화하고 문서화하기로 결정한 이유에 대해 이야기했습니다.
이번 글에서는 그 연장선상에서, 탭탭의 코드 구조를 어떻게 정리하고 개선해 나갈 것인지, 그리고 구조 개선을 통해 어떤 문제들을 해결하고자 하는지에 대해 조금 더 구체적으로 이야기해보려 합니다.
코드 일관화
탭탭은 현재 TCA를 기반으로 구현되어 있습니다. 다만 프로젝트 전반을 살펴보면, TCA를 사용하고 있음에도 불구하고 일관성이 떨어지는 부분들이 존재합니다.
1. 앱 진입점
현재 앱 진입점은 TCA가 아닌 일반적인 SwiftUI의 앱 진입 방식으로 구현되어 있으며, 성능상 문제나 이슈는 없지만, 앱 전체 구조의 일관성이 떨어지고 상태 관리가 흩어져 유지보수가 어려워진다는 한계가 있었습니다. 이에 따라 앱 진입점 또한 TCA로 컨버팅하여 하나의 피처로 관리하고, 앱 전체 흐름을 동일한 아키텍처 안에서 추적할 수 있도록 개선할 필요가 있다고 판단했습니다.
2. 구현 방식이 제각각
또한 UI 구현에서도 일관성이 부족했습니다. 어떤 화면은 TCA의 sheet를 통해 관리되고, 어떤 화면은 overlay로, 또 일부는 기존 UIKit 기반의 모달 방식으로 구현되어 있어, 동일한 목적의 UI임에도 구현 방식이 제각각인 상태였습니다. 이로 인해 화면 전환 로직을 파악하거나 수정할 때 맥락을 이해하는 데 시간이 소요되고, 이해하기 어렵다는 문제가 있었습니다. 이에 따라 동일한 목적의 UI를 어떻게 구현하고 관리할 것인지에 대한 기준을 명확히하고, TCA의 상태 관리 흐름 안에서 UI를 일관되게 관리할 수 있도록 구조를 개선할 필요가 있다고 판단했습니다.
3. 레거시 코드

마지막으로 레거시 코드입니다. 초기 구현 과정에서는 사용되었지만 현재는 더 이상 사용되지 않거나, 특정 플로우에서만 부분적으로 남아 있는 코드들이 존재했고, 이러한 코드들은 실제 동작 여부와 상관 없이 전체 구조 이해를 방해하는 요소로 남아있습니다.
특히 TCA가 업데이트되면서 이미 deprecated 된 API나 패턴을 사용하는 코드들이 일부 남아 있었고, 이는 현재 TCA 사용 방식과 맞지 않습니다. 이에 따라 TCA 업데이트에 맞춰 deprecated 된 코드들을 제거하고 현재 기준에 맞는 구현 방식으로 정리하는 작업이 필요하다고 판단했습니다.
이펙트 처리
TCA에서 이펙트 처리는 Dependency를 통해 관리하는 것이 일반적인 구조이지만, 현재 탭탭의 일부 클라이언트에서는 그 역할과 책임이 과도하게 집중되어 있는 문제가 있습니다. 특히 SwiftData를 관리하는 클라이언트는 중복되는 메소드, 사용하지 않는 메소드들을 포함하고 고 있습니다.
1. 일관성 부족
어떤 메소드는 내부에서 정렬된 값을 반환하는 반면, 어떤 메소드는 단순히 데이터를 가져온 뒤 Feature 단에서 정렬을 수행하는 등 일관성이 부족한 부분이 있었습니다. 이러한 구조는 이펙트의 역할을 예측하기 어렵게 만들고, 새로운 기능을 추가하거나 기존 로직을 수정할 때 불필요한 공수가 발생하는 원인이 되었습니다.
2. 클라이언트가 있음에도 불구하고 사용하지 않음
특정 이펙트를 담당하는 클라이언트가 이미 존재함에도 불구하고, 일부 피쳐에서는 이를 사용하지 않고 직접 UserDefaults에 접근하거나 별도의 로직을 구현하고 있었습니다. 이 역시 데이터 접근 방식이 피쳐마다 달라지는 결과를 만들었고, 의존성 관리 측면에서도 문제가 있다고 판단하였습니다.
이에 따라 각 클라이언트가 담당해야 할 책임의 범위를 명확히 정의하고, 이펙트는 단일한 기준과 역할을 갖도록 정리하는 것을 목표로 하고 있습니다.
네비게이션 로직 수정

탭탭의 네비게이션 로직은 기존에 LinkNavigator라는 외부 서드파티 라이브러리를 통해 구현되어 있었습니다. 각 피처를 구현할 때마다 단위별로 라우터를 정의하고, 이를 다시 연결하고 관리해야 했기 때문에 네비게이션 구조가 커질수록 관리 비용이 증가하는 문제가 있었습니다. 단순한 화면 추가에도 여러 파일과 설정을 함께 수정해야 했고, 이는 피쳐 개발 시 불필요한 공수와 복잡도를 증가시키는 요소로 작용하고 있다고 판단하였습니다.

1. 구조적 복잡도와 개발 비용
라우터 중심의 네비게이션 구조는 명시적이라는 장점이 있지만, TCA 기반 상태 흐름과 분리되어 있어 실제 화면 전환이 어떤 상태 변화에 의해 발생하는지 파악하기 어려운 경우가 많았습니다. 결과적으로 네비게이션을 추가하거나 수정할 때마다 기존 흐름을 추적하는 데 많은 시간이 필요했고, 이는 개발 속도와 유지보수성 모두에 부담이 되었습니다.
2. 서드파티 라이브러리에 대한 의존성 최소화
TCA와 LinkNavigator는 각각 독립적으로 업데이트되기 때문에, 한쪽의 변경이 다른 쪽과 충돌할 가능성이 있습니다. 외부 라이브러리와의 결합은 장기적으로 안정성을 저해할 수 있는 요소라고 판단했습니다.
이에 따라 네비게이션 역시 TCA의 상태 기반 흐름 안에서 직접 관리하는 방향이, 구조적 일관성과 유지보수 측면에서 더 적절하다고 판단하게 되었습니다.
모듈화 구조 수정

탭탭은 현재 Tuist를 통해 프로젝트를 모듈화하여 관리하고 있습니다. 다만 모듈화를 도입하던 초기에는 왜 모듈화가 필요한지, 그리고 각 모듈이 어떤 역할과 책임을 가져야 하는지에 대한 명확한 정의 없이 구조를 먼저 구성하게 되었습니다. 그 결과, 개발을 진행하면서도 모듈화를 통해 얻고자 했던 이점을 체감하기 어려운 상태가 이어졌습니다.
1. 모듈의 역할과 책임
현재의 모듈 구조를 살펴보면, 각 모듈의 역할과 책임이 명확하게 구분되어 있지 않고, 특정 기능이나 로직이 여러 모듈에 걸쳐 분산되거나 중복되는 문제들이 존재했습니다. 예를 들면, 도메인 계층에는 순수한 모델과 인터페이스만 존재해야 함에도 불구하고, 실제 구현체가 함께 포함되어 있는 경우가 있었고, 이로 인해 모듈 간 의존성을 파악하기 어렵고, 기능 수정이나 확장 시 어떤 모듈을 수정해야 하는지 판단하는 데에도 추가적인 이해가 필요했습니다.
2. Feature 모듈

피쳐 모듈 역시 모듈화의 이유를 충분히 살리지 못한 구조를 가지고 있었습니다. 현재 구조는 각 피쳐가 개별 모듈로 분리되어 있는 형태가 아니라, Feature라는 하나의 모듈 안에 피쳐별로 폴더링만 되어 있는 방식이었습니다. 즉, 물리적으로는 하나의 모듈이며 논리적으로만 피쳐가 구분되어 있는 상태였습니다.
이러한 구조는 모듈화가 제공하는 장점을 기대하기 어렵습니다. 예를 들어 특정 피쳐 하나만 테스트 하거나 수정을 하고 싶을 경우에도, 해당 피쳐만 빌드하는 것이 아니라 Feature 모듈 전체를 빌드해야 했고, 이는 빌드 시간 증가와 테스트 지연으로 이어졌습니다. 결과적으로 피쳐 단위의 독립적인 개발과 검증이 어려워졌고, 모듈화가 의도했던 효과를 충분히 얻지 못하고 있습니다.
이에 따라 각 피처를 명확한 단위로 분리하고, 독립적으로 빌드 및 테스트할 수 있는 구조로 개선할 필요가 있다고 판단했습니다. 아래는 탭탭 팀이 모듈화 개선으로 기대하는 효과들입니다.
1. 독립적인 빌드와 테스트 가능
각 피쳐를 개별 모듈로 분리함으로써, 특정 피쳐만 선택적으로 빌드하거나 테스트할 수 있어 개발 속도를 향상시킬 수 있을 것으로 기대합니다. (예를 들어, SearchView 빌드하고 싶을 때.. 앱 진입점으로 가서 앱 진입점 수정하는 불편함...! 너무 컸어요...)
2. 빌드 속도 개선
각 피쳐를 개별 모듈로 분리함으로써, 특정 피쳐만 선택적으로 빌드하거나 빌드 속도를 향상시킬 수 있을 것으로 기대합니다.
3. 책임과 경계 명확화
모듈 단위로 책임을 정의함으로써, 기능별 의존성을 명확히 하고 코드 구조를 이해하기 쉽게 만들 수 있을 것이라 기대합니다.
'탭탭 - TapTap > 리팩토링' 카테고리의 다른 글
| [리팩토링] 07. SwiftDataClient 리팩토링 - 중복 코드 제거 (0) | 2026.02.12 |
|---|---|
| [리팩토링] 06. 모듈 개선 (0) | 2026.02.03 |
| [리팩토링] 05. Swift Concurrency로 메모리 누수와 Callback 지옥을 해결해보자 (온보딩 리팩토링). (0) | 2026.01.19 |
| [리팩토링] 03. 구조개선 - App진입점을 TCA로 컨버팅 (1) | 2026.01.15 |
| [리팩토링] 01. TapTap 리팩토링을 시작하다. - 도식화 및 문서화 (1) | 2026.01.05 |