Join hangouts and make friends wherever you are!
Project Duration: 2022.05.10 ~
App Release : Soon
1. UIKit + RxSwift๋ฅผ ์ด์ฉํ MVVM ๋์์ธ ํจํด
View๋ฅผ ๋ด๋นํ๋ UIViewController๋ UIView์ ViewModelType ํ๋กํ ์ฝ์ ์ค์ํ๋ ViewModel์ด 1:1 ๋์ํ๋ ๊ตฌ์กฐ
View์ ์๋ bind() ํจ์์์ View์์ ๋ฐ์ํ ๋ค์ํ ์ด๋ฒคํธ๋ฅผ ์์ ํ๊ณ ์๋ ViewModel์ Input์ Bindingํ๊ณ ์
๋ ฅ ๋ฐ์ ์ด๋ฒคํธ๋ฅผ ViewModel์์ ์ฒ๋ฆฌํ๊ณ ViewModel์ Output์ ๋ค์ View์ Bindingํ์ฌ ์ ์ ์๊ฒ ๋ณด์ฌ์ง ๋ฐ์ดํฐ๋ฅผ ํ์
protocol ViewModelType {
associatedtype Dependency
associatedtype Input
associatedtype Output
var dependency: Dependency { get }
var disposeBag: DisposeBag { get set }
var input: Input { get }
var output: Output { get }
init(dependency: Dependency)
}
class ViewModel: ViewModelType {
struct Dependency {}
struct Input {}
struct Output {}
let dependency: Dependency
var disposeBag = DisposeBag()
let input: Input
let output: Output
init(dependency: Dependency) {
self.dependency = dependency
// MARK: Streams
/*
input & output ๋ฑ ๋ก์ง์ ์ํด ํ์ํ ์คํธ๋ฆผ ์์ฑ
*/
// MARK: Input & Output
self.input = Input()
self.output = Output()
// MARK: Binding
/*
๋น์ฆ๋์ค ๋ก์ง
*/
}
}
class ViewController: UIViewController {
// MARK: Properties
private let viewModel: ViewModel
private let disposeBag = DisposeBag()
// MARK: Lifecycle
init(viewModel: ViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
bind()
}
// MARK: Bind
private func bind() {
/*
1. View์์ ๋ฐ์ํ๋ Event๋ฅผ ViewModel์ Input์ ๋ฐ์ธ๋ฉ
2. ์ด๋ฒคํธ ์ฒ๋ฆฌ ํ ์ ์ ์๊ฒ ๋ณด์ฌ์ง ๋ฐ์ดํฐ๋ฅผ ViewModel์ Output์์ UI Component์ ๋ฐ์ธ๋ฉ
*/
}
}
2. ์ ์ฒด์ ์ธ Layer ์ค๊ณ
Layer | Components | Description |
---|---|---|
Presentation* | View + ViewModel | MVVM |
Domain* | ViewModel + Repository(Interface) + Entity | Business Logic |
Data* | Repository(Implementation) + Network + DB | Data Repository |
์ฑ์ ์ ๋ฐ์ ์ธ Layer๋ "Clean Architecture + MVVM"๋ฅผ ์ฐธ๊ณ ํ์ฌ ์ค๊ณํ์์ต๋๋ค.
์ฐธ๊ณ ํ ์๋ฃ์์๋ ViewModel๊ณผ UseCase๋ฅผ ๋ถ๋ฆฌํ์ฌ
ViewModel์ View๋ฅผ ๊ทธ๋ฆฌ๋ Presentation ์์ญ์
UseCase๋ ๋น์ฆ๋์ค๋ก์ง๊ณผ ๊ด๋ จ๋ Domain์์ญ์ ๋ก์ง์ ๋ถ๋ฆฌํ๊ณ ์์ง๋ง,
์ด ํ๋ก์ ํธ์์๋ ViewModel์ด ๋ ๋ก์ง์ ๋ชจ๋ ๋ด๋นํ๊ณ ์์ต๋๋ค.
3. ๋คํธ์ํฌ Layer ์ค๊ณ
๋คํธ์ํฌ ๊ด๋ จ Layer๋ "Testableํ URLSession ์ค๊ณ"๋ฅผ ์ฐธ๊ณ ํ์ฌ ์ค๊ณํ์์ต๋๋ค.
๋์ ๋น๋๋ก ๋ฐ๋ณต์ ์ผ๋ก ๋คํธ์ํฌ ํจ์๋ฅผ ํธ์ถํด์ผํ๊ธฐ ๋๋ฌธ์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๊ฐ๋
์ฑ์ด ์ข์ ๋คํธ์ํฌ Layer๋ฅผ ๋ง๋ค๊ณ ์ถ์์ต๋๋ค.
๋ํ, API ํธ์ถ์ ์๋ฒ์ ๋ํ ์์กด์ฑ์ ๋์ฌ Unit Test๋ฅผ ๋ถ๊ฐ๋ฅํ๊ฒ ๋ง๋ค๊ธฐ ๋๋ฌธ์ URLSession์ด ์๋ URLSessionable์ด๋ผ๋ ํ๋กํ ์ฝ์ ์์กดํ์ฌ Mock ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ์ฌ Test ๊ฐ๋ฅํ ์ ๋คํธ์ํฌ Layer ๋ฐฉ์์ ์ฑํํ์์ต๋๋ค.
๐ FirebaseAuth: Firebase JWTํ ํฐ ์ธ์ฆ
๐ GoogleSignIn: Google ์์ ๋ก๊ทธ์ธ
๐ FacebookLogin: Facebook ์์ ๋ก๊ทธ์ธ
๐ AuthenticationServices: Apple ์์ ๋ก๊ทธ์ธ
๐ FirebaseMessaging: Firebase Cloud Messaging ์๋ฆผ
๐ FirebaseRemoteConfig: Firebase Remote Config, ๊ธด๊ธ ๊ณต์ง ํ์ , ์ฑ ์ต์๋ฒ์ ํ์ธ
๐ FirebaseAnalytics: Firebase Analytics, ๋ก๊ทธ ์์ง
๐ RxSwift: Data Stream์ ๊ด์ฐฐํ๋ฉฐ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ ์ ๊ณต
๐ RxDataSources: Animatable UITableViewCell๊ณผ UICollectionViewCell์ Binding
๐ RxCLLocationManager: ์์น ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๋ CLLocationManager์ Rx Wrapper
๐ RxKeyboard: ํค๋ณด๋ ๋์ด๋ฅผ Rx์ ์ด๋ฒคํธ๋ก ๋ฐฉ์ถ
๐ SnapKit: ์ฝ๋ ๊ธฐ๋ฐ UI ์ค๊ณ
๐ Kignfishier: ๋คํธ์ํฌ ๋น๋๊ธฐ ์ด๋ฏธ์ง ๋ถ๋ฌ์ค๊ธฐ ๋ฐ ์ด๋ฏธ์ง ์บ์ฑ
๐ Lottie: JSON ์ ๋๋ฉ์ด์
๐ ProgressHUD: ๋คํธ์ํฌ ํต์ ์ค ์ธ๋์ผ์ดํฐ ํ์
๐ YPImagePicker: ๋ฉํฐ์ด๋ฏธ์ง ๋ฐ Crop ๊ธฐ๋ฅ ์ง์
ํด๋น Commit ์์ ์์๋ ์๋ฒ ๊ฐ๋ฐ์ด ์๋ฃ๋์ง ์์ ์๋ฃ ์์ ์ด์ ์ ๋์ ํ์ธ์ ์ํ์๋ ๊ฒฝ์ฐ,
"Data - Repository ๊ตฌํ์ฒด ์ค์ API ๋ชจ๋ ์ ํ" Commit ์ด์
Mock Data๋ฅผ ๋ฐํํ๋ Commit์ Cloneํ์ฌ ์ฌ์ฉํด์ฃผ์๊ธธ ๋ฐ๋๋๋ค.
๋ํ, ๋ฏธ๋ฆฌ ํ์ํ ๋ด์ฉ์ผ๋ก API Endpoint๋ฅผ ์ ์ํ์๊ธฐ ๋๋ฌธ์ ์ค์ ์ฐ๋ ํ์ธ์ด ํ์ํ๊ณ ,
ํ์์ EndPoint ์์ ์ด ํ์ํ ๊ฒ์
๋๋ค.
์์ ์ ํด๋น ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ Bappy - Data - Network์ APIEndpoints.swift ๋ฐ ํ์ ๋๋ ํ ๋ฆฌ
DataMapping์ ๊ฐ RequestDTO ๋ฐ ResponseDTO๋ค์ ๋ด์ฉ ์ผ๋ถ๋ฅผ ์์ ํด์ฃผ์๋ฉด ๋ฉ๋๋ค.
๋ก๊ทธ์ธ, ํ์๊ฐ์ , ํ๋กํ ์์ , ์ด๋ฏธ์ง ๋ถ๋ฌ์ค๊ธฐ API๋ ์๋ฒ์ ์ฐ๋์ ํ์ธํ์์ต๋๋ค.