기존 아키텍처 및 개선의 필요성
domain layer + presentation layer + mvvm

파란색 선: 의존
기존 아키텍처는 이런 모습으로 구현되어 있었습니다.
의존성이 내부로 향하는 것이 클린 아키텍처의 핵심이라 하면, 문제는 없었습니다.
다만, 개발을 빠르게 하다보니 이것이 지켜지지 않는 문제들이 있었습니다.
뷰컨에 모델이 들어간다던지, 네비게이션을 직접 한다던지 등등 SRP를 어기는 코드가 있었습니다.
또한, 뷰모델에 많은 로직이 들어가 있었는데 뷰와 관련된 로직이 포함된 뷰모델을 테스트하기 어려운 문제도 있었습니다.
따라서, 코드를 리팩토링하고 data layer를 추가해서 테스트 가능한 영역을 구분하기로 결정했습니다.
개선된 아키텍처

개선된 구조의 모습입니다.
데이터 흐름은 presentation → domain → data 이지만, domain이 repository protocol에 의존하게끔 해서 의존성은 domain으로만 향하게끔 했습니다.
적용
저는 이 프로젝트에서 마이페이지 화면과 기능을 주로 담당했습니다. 따라서, 마이페이지 메인화면을 위주로 리팩토링해보겠습니다.



폴더 구조는 이렇게 변경했습니다.
모든 케이스를 다 적용하고 포스팅하기는 어려울 것 같아서, 마이페이지에서 알림 읽었는지 여부를 확인하는 기능만 작성하겠습니다.
* CheckNotificationStatusUseCase → FetchNotificationCheckStatusUseCase 변경
- MyPageRepository (Data) #1
struct MyPageRepository: MyPageRepositoryInterface {
func fetchNotificationCheckStatus() async throws -> NotificationCheckStatus {
try await APIClient.fetchNotificationCheckStatus()
}
}
- MyPageRepositoryInterface (Domain) #2
protocol MyPageRepositoryInterface {
func fetchNotificationCheckStatus() async throws -> NotificationCheckStatus
}
- FetchNotificationCheckStatusUseCase (Domain) #3
struct FetchNotificationCheckStatusUseCase {
let repository: MyPageRepositoryInterface
func execute() async throws -> NotificationCheckStatus {
return try await repository.fetchNotificationCheckStatus()
}
}
#1, #3은 #2를 의존합니다.
- MyPageViewModel
private let fetchNotificationCheckStatusUseCase: FetchNotificationCheckStatusUseCase
init(coordinator: MyPageCoordinator, userId: Int64? = nil, repository: MyPageRepositoryInterface) {
self.coordinator = coordinator
self.userId = userId
self.fetchNotificationCheckStatusUseCase = .init(repository: repository)
}
// use
let notificationCheckStatus = try await fetchNotificationCheckStatusUseCase.execute()
notificationCheckStatusSubject.send(notificationCheckStatus)
마무리
이렇게 구조를 개선하고 살짝 코드를 작성해봤습니다.
현재 프로젝트가 막 변경사항이 많지 않아서 구조 변경에 대한 베네핏을 직접 경험하진 못했습니다. 하지만, 뷰모델에 있던 로직을 data layer로 옮기고, data layer의 class들이 변경되고, 테스트코드를 작성하고 ,, 이런 과정들을 거치다 보면 유연한 변경이라는 이점을 얻을 수 있지 않을까 생각합니다.
'iOS > Refactoring' 카테고리의 다른 글
| [UIKit/Refactoring] 전시 화면 데이터 처리 관련 로직 개선하기 (0) | 2024.08.17 |
|---|---|
| [UIKit/Refactoring] MyPageViewModel getAllItems() 함수 개선하기 (0) | 2024.08.10 |
| [UIKit/Refactoring] 홈 화면 UX 개선하기 (리사이징, 메모리 캐싱) (0) | 2024.07.27 |
| [UIKit/Refactoring] MyPageProfileEditViewModel 코드 개선하기 (2) (0) | 2024.07.17 |
| [UIKit/Refactoring] MyPageProfileEditViewModel 코드 개선하기 (1) (0) | 2024.07.13 |