[ADR][가상] 아키텍처 의사 결정 기록: 도메인 단위의 API 코드를 모듈로 분리하기
Contents:
도메인 단위의 API 코드를 모듈로 분리하기
작성일 : 2025-09-16
작성자 : 안정민
상태
- 수락됨(Accepted)
배경
현재 우리 앱의 모든 도메인(예: 사용자, 상품, 주문) 네트워크 API는 단일 모듈 내에서 관리되고 있습니다. 초기에는 모든 API를 한 곳에서 관리하여 의존성 추가가 간편하다는 장점이 있었습니다.
하지만 서비스 규모가 확장되고 API의 수가 급격히 증가함에 따라 다음과 같은 문제들이 발생하고 있습니다.
-
빌드 시간 증가: 프로젝트 규모가 커지면서 전체 API 모듈을 빌드하는 데 소요되는 시간이 증가했습니다. 특정 기능 개발 시 일부 API만 필요함에도 불구하고, 전체 코드를 컴파일해야 하므로 개발 생산성이 저하되고 있습니다.
-
강한 결합도(High Coupling): 특정 도메인에서만 사용되어야 할 모델(Response DTO 등)이 다른 도메인에서 무분별하게 참조되거나, 공통 모델 수정 시 연관 없는 도메인까지 영향을 받는 사례가 발생하고 있습니다. 이는 코드의 예측 가능성을 떨어트리고 유지보수 비용을 증가시키는 주요 원인입니다.
-
낮은 응집도(Low Cohesion): 단일 모듈 내에 여러 도메인이 혼재하여 관련 없는 코드들이 물리적으로 함께 위치하게 됩니다. 이로 인해 특정 도메인의 기능을 파악하고 수정하기가 점점 더 어려워지고 있습니다.
이러한 문제들은 결국 개발 속도 저하와 잠재적인 버그 발생 가능성 증가로 이어져, 프로젝트의 장기적인 확장성과 안정성을 저해하고 있습니다.
결정
하나의 프로젝트(NetworkFeatureAPI)에서 각 도메인별 API 코드를 별도의 프레임워크 타겟(NetworkDomainAPI)으로 분리하여 모듈화합니다.
예를 들어, 기존 NetworkAPI 모듈을 UserAPI, ProductAPI, OrderAPI 등과 같이 도메인 경계를 기준으로 명확하게 분리합니다. 각 Feature 모듈은 자신이 직접적으로 사용하는 API 모듈에만 의존하게 됩니다. 또한, 개수가 적은 도메인 API는 MiscAPI 모듈로 통합 관리합니다.
결정 이유
이 아키텍처 결정의 핵심적인 이유는 ‘배경’ 섹션에서 제기된 빌드 시간, 결합도, 응집도 문제를 근본적으로 해결하기 위함입니다.
-
독립적인 빌드: 각 도메인 API를 별도의 프레임워크로 분리하면, 특정 기능을 개발할 때 관련된 모듈만 선택적으로 빌드할 수 있습니다. 이는 전체 프로젝트의 증분 빌드 시간을 획기적으로 단축시켜 개발 사이클을 가속화합니다.
-
명확한 경계 설정: 모듈화는 각 도메인 간에 물리적인 경계를 설정합니다. Swift의 접근 제어(Access Control)를 통해 모듈 외부로 노출할 코드를 명시적으로 관리할 수 있으며, 이는 다른 도메인의 모델이나 로직을 부주의하게 참조하는 것을 원천적으로 방지하여 결합도를 낮춥니다.
-
관심사의 분리: 하나의 모듈은 하나의 도메인에만 집중하게 됩니다. 이를 통해 관련 있는 코드들이 한곳에 모여 응집도가 높아지고, 코드의 가독성, 유지보수성, 그리고 테스트 용이성이 향상됩니다.
결과
이 결정을 통해 다음과 같은 긍정적, 부정적 결과를 예상합니다.
- 긍정적 영향
-
빌드 시간 단축: Feature 개발 시 필요한 도메인 API 모듈만 빌드하게 되므로, 전체 프로젝트의 컴파일 시간이 의미 있게 감소합니다.
-
의존성 관리 개선: 모듈 간 접근 제어를 통해 불필요한 상호 참조를 원천적으로 차단할 수 있습니다. 이는 코드의 결합도를 낮추고, 각 모듈의 독립성을 보장합니다.
-
코드 재사용성 및 응집도 향상: 각 도메인 API 모듈 내에서 관련된 enum, struct, 유틸리티 등을 함께 관리하게 되므로 코드의 응집도가 높아지고, 해당 도메인 내에서의 재사용성이 극대화됩니다.
-
명확한 책임 분리: 각 팀이나 개발자가 특정 도메인 API에 대한 소유권을 가지고 책임감 있게 코드를 관리할 수 있는 환경이 조성됩니다.
-
- 부정적 영향
-
초기 설정 및 마이그레이션 비용: 기존 코드를 새로운 모듈 구조로 분리하고, CI/CD 파이프라인을 수정하는 데 초기 리소스가 투입됩니다.
-
API 탐색의 어려움: API 모듈의 수가 증가함에 따라, 신규 입사자나 다른 도메인 개발자가 특정 API가 어느 모듈에 위치하는지 파악하는 데 약간의 시간이 걸릴 수 있습니다.
-
예상되는 리스크 및 대응책
- 리스크 1: 여러 도메인에서 공통으로 사용해야 하는 모델(예: AccountInfo, UserInfo) 처리의 어려움.
- 대응책: APICommon 또는 APIShareDTO와 같은 공용 모듈을 별도로 생성합니다. 이 모듈에 여러 도메인에서 공유되어야 하는 최소한의 데이터 모델과 로직을 배치하여 중복을 방지합니다.
- 리스크 2: 모듈 수가 많아져 API를 찾기 어려워지는 문제 (언급된 부정적 영향).
- 대응책:
- 명확한 네이밍 컨벤션 수립: 모듈과 파일, 타입 이름에 대한 명확한 규칙을 정립합니다. (예: [DomainName]API, [DomainName]Request)
- API 모듈 맵(Map) 문서화: 어떤 모듈이 어떤 책임을 가지는지 정리한 간단한 문서를 Confluence 등에 작성하여 팀 전체가 참고할 수 있도록 합니다.
- 대응책:
- 리스크 3: 순환 참조(Circular Dependency) 발생 가능성.
- 대응책: 모듈 설계 시 의존성 방향을 단방향(예: Feature -> API)으로 유지하는 원칙을 수립하고, 코드 리뷰 시 이를 철저히 검토합니다.
구현 계획
본 계획은 점진적으로 진행하여 안정성을 확보합니다.
- 1단계: 기반 설정
- APICommon 공용 모듈 타겟 생성 및 공통 모델 이전.
- 새로운 API 모듈을 위한 Xcode 프로젝트 템플릿 및 가이드라인 문서 작성.
- CI/CD 설정에 신규 모듈 타겟을 추가하는 방식 테스트.
- 2단계: 파일럿 마이그레이션
- 의존성이 비교적 적고 영향 범위가 작은 1~2개의 도메인(예: NoticeAPI)을 선정하여 신규 모듈로 분리합니다.
- 이 과정에서 발생하는 문제점을 기록하고 해결책을 가이드라인에 반영합니다.
- 3단계: 전체 마이그레이션
- 나머지 도메인들을 병렬적으로 또는 순차적으로 신규 모듈로 이전합니다.
- 각 Feature 모듈의 의존성을 기존 단일 모듈에서 신규 도메인 모듈들로 교체합니다.
- 4단계: 안정화 및 정리
- 기존의 단일 NetworkAPI 모듈을 완전히 제거합니다.
- 최종적으로 빌드 시간 및 프로젝트 구조 개선 효과를 측정하고 회고를 진행합니다.
비용 및 이점
비용
- 개발 시간: 마이그레이션 및 안정화 기간 동안 투입되는 개발 리소스.
- 학습 곡선: 팀원들이 새로운 모듈 구조와 의존성 규칙에 적응하는 데 필요한 시간.
이점
- 생산성 향상: 빌드 시간 단축으로 인해 개발 및 테스트 주기가 빨라져 장기적인 개발 생산성이 크게 향상됩니다.
- 품질 향상: 낮은 결합도는 코드 변경 시 사이드 이펙트를 줄여주어 앱의 안정성을 높입니다.
- 확장성 확보: 신규 도메인 추가 시 독립된 모듈로 개발할 수 있어, 프로젝트가 커져도 복잡도가 급격히 증가하는 것을 방지합니다.
결정 후 모니터링
이 결정의 성공 여부를 측정하기 위해 다음 지표를 지속적으로 모니터링합니다.
- 정량적 지표:
- 클린 빌드 시간: 마이그레이션 전후의 Xcode 클린 빌드 시간을 측정하여 비교.
- 증분 빌드 시간: 주 기능 개발 시 코드 변경 후 소요되는 빌드 시간을 측정.
- 정성적 지표:
- 개발자 만족도 설문: 분기별로 새로운 구조에 대한 개발자들의 만족도와 불편 사항에 대한 설문을 진행.
- 코드 리뷰: 코드 리뷰 시 불필요한 의존성 추가나 아키텍처 원칙 위반 사례가 줄어드는지 확인.