1. Reactorkit ์๊ฐ
Reactorkit์ Swift๋ก ์์ฑ๋ ๋ฆฌ์กํฐ๋ธ ํ๋ก๊ทธ๋๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, ์ฃผ๋ก ์ํ ๊ด๋ฆฌ์ ๋ฐ์ดํฐ ํ๋ฆ ์ ์ด๋ฅผ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ iOS ์ฑ ๊ฐ๋ฐ์์ ๋ฆฌ์กํฐ๋ธ ํจํด์ ์ฑํํ์ฌ ์ผ๊ด๋ ์ํ ๊ด๋ฆฌ์ ๋ฐ์ํ UI ์ ๋ฐ์ดํธ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
์ด๋ฒ ๊ธ์์๋ Reactorkit์ ๊ธฐ๋ณธ ๊ฐ๋
๊ณผ ์๋ ๋ฐฉ์, ์ด๋ค ์ฅ์ ์ด ์๋์ง ๋ฆฌ๋๋ฏธ๋ฅผ ๋ฒ์ญํด๋ณด๋ฉฐ ์๊ฐํด๋๋ฆฌ๋ ค๊ณ ํฉ๋๋ค.
2. Reactorkit์ ๊ธฐ๋ณธ ๊ฐ๋
Reactorkit์ ์ ์
ReactorKit์ Flux์ Reactive ํ๋ก๊ทธ๋๋ฐ์ ์กฐํฉ์ด๋ผ๊ณ ํฉ๋๋ค. ์ฌ์ฉ์์ก์ ๊ณผ ๋ทฐ์ ์ํ๋ ๊ด์ฐฐ ๊ฐ๋ฅํ ์คํธ๋ฆผ์ ํตํด ๊ฐ ๋ ์ด์ด์ ์ ๋ฌ๋ฉ๋๋ค. ์ด ์คํธ๋ฆผ์ ๋จ๋ฐฉํฅ์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ต๋๋ค. ๋ทฐ๋ ์ก์ ๋ง ๋ด๋ณด๋ผ ์ ์๊ณ , ๋ฆฌ์กํฐ๋ ์ํ๋ง ๋ด๋ณด๋ผ ์ ์๋ ๊ฒ ์ฒ๋ผ ๋ง์ ๋๋ค!
Reactorkit์ ์๋ ๋ฐฉ์
์๋ ๋ฐฉ์์ ๊ฐ๋ณ๊ฒ! ์์ฃผ ๊ฐ๋ณ๊ฒ ์ดํดํด๋ณผ๊น์?!
์ด์ ์ ์์ฑํ ๋ฐ์ ๊ฐ์ด Reactorkit์ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ๋ฐ๋ฆ
๋๋ค.
1) ์ฌ์ฉ์์ Action์ด ๋ฐ์ํ๋ฉด, ์ด ์ก์ ์ Reactor๋ก ์ ๋ฌ๋ฉ๋๋ค.
2) Reactor๋ action์ ๋ํ State๋ฅผ ๋ฐํํ๊ณ ,
3) ์ด State๊ฐ View์ ๋ฐ์๋์ด UI๊ฐ ์ ๋ฐ์ดํธ๋ฉ๋๋ค.
Reactorkit์ ๋์์ธ ๋ชฉํ
Reactorkit์ ๋์์ธ ๋ชฉํ๋ ๋ค์๊ณผ ๊ฐ๋ค๊ณ ๊ธฐ์ ๋์ด ์์ต๋๋ค.
- ํ ์คํธ ๊ฐ๋ฅ์ฑ : ReactorKit์ ์ฒซ ๋ฒ์งธ ๋ชฉ์ ์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ทฐ์์ ๋ถ๋ฆฌํ๋ ๊ฒ์ ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๋ฅผ ํ ์คํธ ๊ฐ๋ฅํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ๋ฆฌ์กํฐ๋ ๋ทฐ์ ๋ํ ์ข ์์ฑ์ด ์์ต๋๋ค. ๋ฐ๋ผ์ ๋ฆฌ์กํฐ๋ฅผ ํ ์คํธํ๊ณ ๋ทฐ ๋ฐ์ธ๋ฉ์ ํ ์คํธํ๋ฉด ๋ฉ๋๋ค.
- ์๊ท๋ชจ๋ก ์์ ๊ฐ๋ฅ : ReactorKit์ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋จ์ผ ์ํคํ ์ฒ๋ฅผ ๋ฐ๋ฅผ ํ์๊ฐ ์์ต๋๋ค. ReactorKit์ ํน์ ๋ทฐ์ ๋ํด ๋ถ๋ถ์ ์ผ๋ก ์ฑํ๋ ์ ์์ต๋๋ค. ๊ธฐ์กด ํ๋ก์ ํธ์์ ReactorKit์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ชจ๋ ๊ฒ์ ๋ค์ ์์ฑํ ํ์๊ฐ ์์ต๋๋ค.
- ๊ฐ๊ฒฐํ ์ฝ๋ : ReactorKit์ ๊ฐ๋จํ ์์ ์ ์ํด ๋ณต์กํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ํผํ๋ ๋ฐ ์ค์ ์ ๋ก๋๋ค. ReactorKit์ ๋ค๋ฅธ ์ํคํ ์ฒ์ ๋นํด ๋ ์ ์ ์ฝ๋๊ฐ ํ์ํฉ๋๋ค. ๋ฐ๋ผ์ ๊ฐ๋จํ๊ฒ ์์ํ๊ณ ํ์ฅํด๋ณผ ์ ์์ต๋๋ค.
3. Reactorkit์ ๊ตฌ์ฑ
View๋ data๋ฅผ ๋ณด์ฌ์ฃผ๋ ์ญํ ์ ๋ด๋นํฉ๋๋ค. ๋ทฐ ์ปจํธ๋กค๋ฌ์ ์ ์ ๋ทฐ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค. ๋ทฐ๋ ์ฌ์ฉ์ ์ ๋ ฅ์ ์์ ์คํธ๋ฆผ์ ๋ฐ์ธ๋ฉํ๊ณ ๋ทฐ ์ํ๋ฅผ ๊ฐ UI ์ปดํฌ๋ํธ์ ๋ฐ์ธ๋ฉํฉ๋๋ค. ๋ทฐ ๋ ์ด์ด์๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์์ต๋๋ค. ๋ทฐ๋ ๋จ์ง ์ก์ ์คํธ๋ฆผ๊ณผ ์ํ ์คํธ๋ฆผ์ ๋งคํํ๋ ๋ฐฉ๋ฒ์ ์ ์ํฉ๋๋ค.
๋ทฐ๋ฅผ ์ ์ํ๋ ค๋ฉด ๊ธฐ์กด ํด๋์ค๊ฐ View๋ผ๋ ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๋๋ก ํ๋ฉด ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ํด๋์ค๋ ์๋์ผ๋ก reactor๋ผ๊ณ ์ด๋ฆ์ด ์ง์ ๋ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ์ด ํ๋กํผํฐ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ทฐ ์ธ๋ถ์์ ์ฃผ์ ํฉ๋๋ค.
class ProfileViewController: UIViewController, View {
var disposeBag = DisposeBag()
}
profileViewController.reactor = UserViewReactor() // reactor ์ฃผ์
reactor ํ๋กํผํฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉด bind(reactor:)๊ฐ ํธ์ถ๋ฉ๋๋ค. ์์ ์คํธ๋ฆผ๊ณผ ์ํ ์คํธ๋ฆผ์ ๋ฐ์ธ๋ฉ์ ์ ์ํ๊ธฐ ์ํด ์๋์ ๋ฉ์๋๋ฅผ ๊ตฌํํ์ธ์.
func bind(reactor: ProfileViewReactor) {
// action (View -> Reactor)
refreshButton.rx.tap.map { Reactor.Action.refresh }
.bind(to: reactor.action)
.disposed(by: self.disposeBag)
// state (Reactor -> View)
reactor.state.map { $0.isFollowing }
.bind(to: followButton.rx.isSelected)
.disposed(by: self.disposeBag)
}
2) Reactor
Reactor๋ ๋ทฐ์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ UI ๋ ๋ฆฝ์ ์ธ ๋ ์ด์ด์ ๋๋ค. Reactor์ ๊ฐ์ฅ ์ค์ํ ์ญํ ์ ๋ทฐ๋ก๋ถํฐ ์ ์ด ํ๋ฆ์ ๋ถ๋ฆฌํ๋ ๊ฒ์ ๋๋ค. ๋ชจ๋ ๋ทฐ๋ ํด๋น ๋ทฐ์ ๋์ํ๋ Reactor๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ๋ชจ๋ ๋ก์ง์ ํด๋น Reactor์ ์์ํฉ๋๋ค.
Reactor๋ ๋ทฐ์ ๋ํ ์์กด์ฑ์ด ์๊ธฐ ๋๋ฌธ์ ์ฝ๊ฒ ํ ์คํธํ ์ ์์ต๋๋ค.
Reactor๋ฅผ ์ ์ํ๋ ค๋ฉด Reactor ํ๋กํ ์ฝ์ ์ค์ํด์ผ ํฉ๋๋ค. ์ด ํ๋กํ ์ฝ์ ์ธ ๊ฐ์ง ํ์ (Action, Mutation, State)์ ์ ์ํ ๊ฒ์ ์๊ตฌํ๋ฉฐ, initialState๋ผ๋ ์์ฑ์ ํ์๋ก ํฉ๋๋ค.
Action์ ์ฌ์ฉ์ ์ํธ์์ฉ์ ๋ํ๋ด๊ณ , State๋ ๋ทฐ ์ํ๋ฅผ ๋ํ๋ ๋๋ค. Mutation์ Action๊ณผ State ์ฌ์ด์ ๋ค๋ฆฌ ์ญํ ์ ํฉ๋๋ค. Reactor์ ๋ด๋ถ์์๋ ์ก์ ์คํธ๋ฆผ์ ์ํ ์คํธ๋ฆผ์ผ๋ก ๋ณํํ๋ ๋ ๋จ๊ณ, ์ฆ mutate()์ reduce()๋ฅผ ํตํด ์ด๋ฅผ ์ํํฉ๋๋ค.
class ProfileViewReactor: Reactor {
// Action: ์ ์ ์ ์ก์
์ ํํ
enum Action {
case refreshFollowingStatus(Int)
case follow(Int)
}
// Mutation: ์ํ ๋ณํ๋ฅผ ํํ
enum Mutation {
case setFollowing(Bool)
}
// State: ํ์ฌ ๋ทฐ ์ํ๋ฅผ ํํ
struct State {
var isFollowing: Bool = false
}
// ์ด๊ธฐ ์ํ ์ง์
let initialState: State = State()
}
3) Reactor - mutate()
mutate()๋ Action์ ๋ฐ์์ Observable<Mutation>์ ๋ฐํํฉ๋๋ค.
func mutate(action: Action) -> Observable<Mutation>
๋น๋๊ธฐ ์์ ์ด๋ API ํธ์ถ๊ฐ์ side effect๋ค์ ์๋์ ๋ฉ์๋์์ ์ํ๋ฉ๋๋ค.
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case let .refreshFollowingStatus(userID): // receive an action
return UserAPI.isFollowing(userID) // create an API stream
.map { (isFollowing: Bool) -> Mutation in
return Mutation.setFollowing(isFollowing) // convert to Mutation stream
}
case let .follow(userID):
return UserAPI.follow()
.map { _ -> Mutation in
return Mutation.setFollowing(true)
}
}
}
4) Reactor - reduce()
reduce()๋ State์ Mutation์ผ๋ก๋ถํฐ ์๋ก์ด State๋ฅผ ๋ฐํํฉ๋๋ค.
func reduce(state: State, mutation: Mutation) -> State
reduce() ๋ฉ์๋๋ ์์ ํจ์์ ๋๋ค. ๋ฐ๋ผ์ ๋ฉ์๋ ๋ด๋ถ์์๋ ์ค์ง ์๋ก์ด State๋ฅผ ๋๊ธฐ์ ์ผ๋ก ๋ฐํํ๋ ์์ ๋ง ์ํํด์ผ ํฉ๋๋ค. ์ด ํจ์ ๋ด์์๋ side effects๋ฅผ ์ํํ์ง ์์์ผ ํฉ๋๋ค.
func reduce(state: State, mutation: Mutation) -> State {
var state = state // create a copy of the old state
switch mutation {
case let .setFollowing(isFollowing):
state.isFollowing = isFollowing // manipulate the state, creating a new state
return state // return the new state
}
}
5) Reactor - transform()
transform()๋ ๊ฐ ์คํธ๋ฆผ์ ๋ณํํ๋ฉฐ, ์ธ๊ฐ์ง์ ๋ฉ์๋๊ฐ ์์ต๋๋ค.
func transform(action: Observable<Action>) -> Observable<Action>
func transform(mutation: Observable<Mutation>) -> Observable<Mutation>
func transform(state: Observable<State>) -> Observable<State>
์ด ๋ฉ์๋๋ค์ ๊ตฌํํ์ฌ ๋ค๋ฅธ Observable ์คํธ๋ฆผ๊ณผ ๋ณํํ๊ฑฐ๋ ๊ฒฐํฉํ ์ ์์ต๋๋ค.
๋์ฑ ์์ธํ ๋ด์ฉ์ Global States์ ์ฐธ๊ณ ํด์ฃผ์ธ์!
4. Reactorkit์ ์ฅ์
Reactorkit์ ์ฅ์ ์ ์๋์ ๊ฐ์ด Reactorkit์ด ๋์์ธ๋ ๋ชฉ์ ์์๋ถํฐ ํ์ฅ๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
- ์ผ๊ด๋ ์ํ ๊ด๋ฆฌ: ๋ชจ๋ ์ํ ๋ณํ๊ฐ ์ ์๋์ด์์ด ์์ธก ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค.
- ํ
์คํธ ์ฉ์ด์ฑ: ๋ทฐ์ ๋ก์ง์ด ๋ถ๋ฆฌ๋์ด์์ด ์ํ ๋ณํ์ ์ก์
์ ํ
์คํธํ๊ธฐ ์ฝ์ต๋๋ค.
- ํ์ฅ์ฑ ๋ฐ ์ ์ง๋ณด์ ์ฉ์ด์ฑ: ๋ชจ๋ํ๋ ๊ตฌ์กฐ ๋๋ถ์ ํ์ฅ๊ณผ ์ ์ง๋ณด์์ ์ฉ์ดํฉ๋๋ค.
5. ๋ง๋ฌด๋ฆฌ
์ง๊ธ๊น์ง Reactorkit์ ๊ฐ๋ณ๊ฒ ์์๋ณด์์ต๋๋ค. ์ข ์ข ํ์ฌ์ ์ฐ๋์ฌํญ์์ ์ ํด๋ณผ ์ ์์๋ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ดํด๋ณด๋, ํ๊ตญ ๊ฐ๋ฐ์๋ถ๋ค์ด ๋ง๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๋ ์ ์ด ์ฐธ ์ธ์์ ์ด์์ต๋๋ค ๐
ํด๋น ๊ธ์ ํตํด Reactorkit์ ์ดํดํ๋๋ฐ ๋์์ด ๋์ จ๊ธธ ๋ฐ๋ผ๋ฉฐ, ๋ค์์๋ ๋ฆฌ๋๋ฏธ์ ์์์ ์๋ ToDoList ์ฑ ๊ฐ๋ฐ์์ ํ์ฉํด๋ณด๊ณ ๋ค์ ๋์์ค๊ฒ ์ต๋๋ค. ๐ฃ
'๐ Apple > iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS] Alamofire๋ก Multipart ์ด๋ฏธ์ง ํต์ ํ๊ธฐ | post | Swift (0) | 2024.02.13 |
---|---|
[iOS] ํ์ด์ด๋ฒ ์ด์ค ๊ตฌ๊ธ ๋ก๊ทธ์์/ํ์ํํด | Swift | Firebase Google Login (0) | 2024.01.13 |
[iOS] ๊ฐ๋ฐํ ๋ ์ ์ฉํ ์ฌ์ดํธ ๋ชจ์ ๐ (0) | 2023.12.31 |
[iOS] ATS(App Transport Security), ATS์ค์ ๋ฐฉ๋ฒ (0) | 2023.12.28 |
[iOS] Singleton ํจํด์ ํ์ฉํ๋ ๊ฒฝ์ฐ (0) | 2023.12.21 |