iOS Development Guide
VIPER 계열 아키텍처 전달 정리
화면 구조 분리, 테스트 전략, 동시성 안정성 관점에서 실무 적용 포인트를 정리한 문서다.
학습 날짜
기록 없음
아키텍처 판단
- 정통 VIPER 100%보다는 VIP 계열(Clean Swift 스타일) + Worker/Router 확장 구조에 가깝다.
- 화면 단위로 View/Interactor/Presenter/Router 책임을 분리한다.
- View는 Presenter만 의존하고, 데이터 조립은 Interactor/Repository에서 담당한다.
권장 호출 흐름
- `View -> Presenter -> Interactor`
- `Interactor -> Presenter -> View`
- Router는 화면 전환과 모듈 조립만 담당한다.
Router + Builder 예시
VC2에서 VC1로 이동할 때는 VC2 라우터가 VC1 Builder를 통해 모듈을 만든 뒤 push한다.
protocol VC1Buildable {
func build(input: VC1Input) -> UIViewController
}
struct VC1Input {
let userID: String
}
final class VC2Router {
weak var viewController: UIViewController?
private let vc1Builder: VC1Buildable
init(vc1Builder: VC1Buildable) {
self.vc1Builder = vc1Builder
}
func routeToVC1(userID: String) {
let vc1 = vc1Builder.build(input: VC1Input(userID: userID))
viewController?.navigationController?.pushViewController(vc1, animated: true)
}
}
테스트 전략
- Presenter는 핵심 단위 테스트 대상으로 두고 `MockView/MockInteractor/MockRouter`로 검증한다.
- 검증 대상은 표시 로직/상태 전이이며, 실제 UI 렌더링 테스트는 별도 UI 테스트로 분리한다.
- 상태 모델은 `idle/loading/error/success`처럼 명시적으로 유지한다.
동시성 보강 포인트
- Repository 내부 공유 상태는 레이스 가능성이 높아 `actor`로 보호한다.
- Interactor에서는 `Task + await`로 actor 경계를 넘는다.
- UI 갱신은 메인 스레드에서만 수행한다.
Q
- Q. Presenter 테스트만으로 충분한가? -> A. 아니다. 표시 로직 검증에는 충분하지만 실제 렌더링/제스처는 UI 테스트가 필요하다.
- Q. actor 메서드 본문이 sync면 await가 불필요한가? -> A. 아니다. actor 경계를 넘는 호출이면 await가 필요하다.
- Q. View가 Interactor를 직접 호출하면 안 되나? -> A. 책임 경계가 무너져 테스트/변경 영향이 커지므로 권장하지 않는다.
관련 문서: iOS 개발 상식 100선