티스토리 뷰
[Clean Architecture] iOS Clean Architecture + MVVM 개념과 예제
eungding 2020. 7. 17. 16:02repository패턴이란 <- 이 포스팅에서 iOS-Clean-Architecture-MVVM 코드를 예제로 썼는데요,
iOS-Clean-Architecture-MVVM 코드를 좀 더 자세히 살펴보려고 합니다-!!
Clean Architecture and MVVM on iOS 에 이 프로젝트에 대한 설명도 적어두셨더라구요 👍
Part1. Clean Architecture 개념
우선 Clean Architecture + MVVM은 말그대로 MVVM에 Clean Architecture를 접목시킨 것입니다
그럼 우선 Clean Architecture란 어떤 건지 먼저 알아봅시다-!
Robert C Martin(Uncle Bob)님이 제안하셨는데, 아래사진처럼 앱 아키텍쳐를 구성한 것을 Clean Architecture라고 합니다.
엉클밥님의 블로그 글 (한글번역) , 엉클밥님의 강연영상 에 자세히 설명되어있는데
간단히 정리해볼게요-!
1) 원들의 관계
- 가장 바깥쪽의 원은 저수준의 구체적인 상세 정보를 담는다. 안쪽으로 이동해가면서 소프트웨어는 추상화 되고 고수준의 정책을 캡슐화한다
- 소스 코드는 안쪽을 향해서만 의존할 수 있다.
- 안쪽의 원은 바깥쪽의 원에 대해 전혀 알지 못한다. 특히, 바깥쪽의 원에서 선언된 어떠한 이름을 안쪽 원에서 참조해서는 안된다.
- 바깥쪽 원의 어떠한 것도 안쪽의 원에 영향을 줘선 안된다.
2) 각 원들에 대한 설명
안쪽 원부터 보겠습니다.
1. Entities (= Enterprise Business Rules)
- 비즈니스 모델
- 엔티티는 메서드를 갖는 객체 일 수도 있고 데이터 구조와 함수의 집합일 수도 있습니다.
- 예제 프로젝트에서는 이런 모델을 엔터티라고 하더라구요...!
2. Use cases (= Application Business Rules)
- 애플리케이션 고유 비즈니스 규칙을 포함하며 시스템의 모든 유스케이스를 캡슐화하고 구현한다.
- 엔티티로 부터의 혹은 엔티티에서의 데이터 흐름을 조합한다.
- 이 계층의 변경이 엔티티에 영향을 주지 않을 것을 기대하며 데이터베이스, UI 또는 공통의 프레임워크의 변경으로부터 영향 받지 않을 것도 기대한다.
(위에서 말한 안쪽의 원은 바깥쪽의 원에 대해 전혀 알지 못한다. 를 말하고 있네요)
- 예제 프로젝트의 UseCase는 모델(엔터티)을 사용하여 비즈니스 로직을 실행하는 Layer입니다.
3. Controllers, Gateway, Prestenters (= Interface Adapter)
- 유스케이스와 엔티티에 있어 용이한 형식으로부터 데이터베이스나 웹 등 외부의 기능에 용이한 형식으로 데이터를 변환한다.
- 예제 프로젝트에서는 Presentation 레이어에 Coordinator, ViewModel, ViewController 등이 들어있습니다.
4. Devices, Web, UI, DB, External Interfaces (= Frameworks & Drivers)
- 데이터베이스나 웹 프레임워크 등 일반적으로 프레임워크나 도구로 구성된다.
- 대개, 이 계층에는 안쪽의 원과 통신할 연결 코드 이외에는 별다른 코드를 작성하지 않는다.
- 예제 프로젝트에서는 이 Layer에 Network, CoreData 등이 있더라구요
Part 2. Clean Architecture + MVVM에 적용된 Clean Architecture 컨셉
우선 오해의 소지를 해결하고 가겠습니다.
Repositories 폴더가 Domain아래에도 있고 Data아래에도 있는데요...!
Domain > Interfaces > Repositories에 있는 파일들은 모두 프로토콜이고
Data > Repositories 에 있는 파일들은 Domain > Interfaces > Repositories의 프로토콜들을 채택한 클래스들입니다.
아래 그림처럼 Repository는 Domain Layer와 Data Layer 중간쯤에 있어서
저렇게 프로젝트가 구성되었다고 생각하시면 됩니다-!!
그리고 각각의 Layer들을 그룹핑한 것을 자세히 살펴볼게요!
1. Domain Layer
- 클린아키텍쳐 원에서 Entities과 Use Cases를 묶어서 Domain Layer라고 합니다.
- 이 레이어는 다른 레이어들에게 어떠한 영향도 받지 않습니다.
- 다른 프로젝트에 의하여서 재사용 될 수 있습니다.
- Entities(비즈니스 모델), Use Cases, Repository Interfaces들이 이 Layer에 들어가있습니다.
2. Presentation Layer
- 클린아키텍쳐 원에서 Presenters와 UI를 묶어서 Presentation Layer라고 합니다.
- UI (UIViewControllers or SwiftUI Views) 와 ViewModels (Presenters)이 이 Layer이 들어가있습니다.
- 뷰모델은 하나이상의 Use cases를 execute하기때문에 Presentation Layer는 Domain Layer를 의존합니다.
3. Data Layer
- 클린아키텍쳐 원에서 DB와 API를 묶어서 Data Layer라고 합니다.
- Repository프로토콜에 대한 구현(Repository Implementations)과 Data Sources들이 이 Layer에 들어가있습니다.
- Repository는 다른 Data Sources (로컬 DB 또는 API) 로부터 데이터를 처리하는 책임이 있습니다.
- Data Layer는 API 응답으로 받은 JSON Data를 Domain Layer에 있는 모델로 변환하는 작업이 들어있습니다. 그래서 Data Layer는 Domain Layer를 의존합니다.
위에서 말한 것을 총 정리하면 이런 그림으로 표현할 수 있습니다.
Part 3. Clean Architecture + MVVM의 데이터 플로우
Data Flow
1. View(UI)는 ViewModel(Presenter) 의 메소드를 콜합니다.
2. ViewModel은 UseCase를 실행합니다.
3. Use Case는 User와 Repository로부터 데이터를 조합합니다.
4. 각각의 Repository는 Remote Data (Network) 또는 Persistent DB Storage Source 또는 In-memory Data (Remote or Cached) 로부터 데이터를 가져옵니다.
5. 정보는 다시 View(UI)로 흘러서 (Information flows back to the View(UI)) 우리는 새로운 화면을 보게 됩니다.
Data Flow + 예제
1. View(UI)는 ViewModel(Presenter) 의 메소드를 콜합니다.
뷰컨트롤러는 뷰모델을 가지고 있고
검색어를 검색하면 아래 함수에서 viewModel의 메소드를 콜합니다.
2. ViewModel은 UseCase를 실행합니다.
viewModel은 Usecase를 가지고 있고
didSearch메소드가 불리면 update메소드를 부르고
update메소드에서는 reset이랑 load를 부릅니다.
load함수에서는 useCase를 실행합니다.
3. Use Case는 User와 Repository로부터 데이터를 조합합니다.
UseCase는 execute함수안에서 Repository한테 movieList를 가져오라고 요청합니다.
4. 각각의 Repository는 Remote Data (Network) 또는 Persistent DB Storage Source 또는 In-memory Data (Remote or Cached) 로부터 데이터를 가져옵니다.
레파지토리는 서버로부터 데이터를 가져와서 넘겨주네요
5. 정보는 다시 View(UI)로 흘러서 (Information flows back to the View(UI)) 우리는 새로운 화면을 보게 됩니다.
뷰컨트롤러의 바인드함수에서 뷰모델의 items를 옵져빙해서 화면을 갱신해줍니다.
Part 4. 각 Layer를 framework로 나누기
각각의 Layer를 framework로 나눌 수 있다고 합니다.
이렇게 만든 다음에
코코아 팟을 이용하여 앱에 각각의 framework를 넣어주면 된다고 합니다.
working example here <- 여기에 그렇게 해놨는데, 열어보면 이렇게 프로젝트가 구성되어있어요.
그리고 각 Layer에 대한 의존성이 있는 Layer는 해당 프레임워크를 import해서 씁니다.
예를 들어 Data Layer는 Domain Layer에 대한 의존성이 있으니까 (즉 Domain 프레임워크에 있는 MoviesPage라는 모델을 써야하니까)
import Domain 해줬어요-!
그외 ) DTO 라는 개념
이 프로젝트에서 DTO라는 것을 만들어서 사용하고 있었던 것이 특이했어요-!
DTO란 Data Transfer Object의 약자이고 JSON response를 Domain으로 매핑하는 중간자 역할입니다.
DataLayer에 DTO가 있고
API쪽에서는 DTO모델을 쓰고 completion handler에서만 domain쪽 모델로 바꿔서 쓰더라구요,,!
[ 더보면 좋을 것 ]
위의 글 스포합니다 🍈 현실 경험 나눔 너무 좋았어요-!!
woowabros.github.io/tools/2019/10/02/clean-architecture-experience.html
'🍏 > Architecture, DesignPattern' 카테고리의 다른 글
[CleanSwift] 클린스위프트 템플릿 살펴보기 (0) | 2021.07.02 |
---|---|
[DI] DI Container, IOC Container 개념과 예제 (3) | 2020.09.07 |
[Design Pattern] Repository패턴이란 (0) | 2020.07.17 |
[CleanSwift] 클린스위프트(Clean Swift)에 대해 알아보자 (1) | 2020.04.29 |
[DI] DI Tree, DI Graph (의존성 트리, 의존성 그래프)를 만드는 방법 (1) | 2020.01.17 |
- Total
- Today
- Yesterday
- flutter 앱 출시
- Sketch 누끼
- cocoapod
- flutter build mode
- ribs
- METAL
- Flutter Spacer
- 구글 Geocoding API
- flutter dynamic link
- 장고 Custom Management Command
- 플러터 얼럿
- Django Heroku Scheduler
- DRF APIException
- github actions
- drf custom error
- Django FCM
- 플러터 싱글톤
- Django Firebase Cloud Messaging
- PencilKit
- SerializerMethodField
- Watch App for iOS App vs Watch App
- Python Type Hint
- ipad multitasking
- Flutter 로딩
- Flutter getter setter
- 장고 URL querystring
- flutter deep link
- Flutter Clipboard
- Flutter Text Gradient
- Dart Factory
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |