MCP Servers (Context7, etc.): For structured documentation guide, see
llms.txt
Xcode ν νλ¦Ώμ μ€μΉνλ©΄ CoreFlow μ»΄ν¬λνΈλ₯Ό λΉ λ₯΄κ² μμ±ν μ μμ΅λλ€.
-
μ μ₯μλ₯Ό λ€μ΄λ‘λνκ³ μμΆμ ν΄μ ν©λλ€.
-
tooling λλ ν λ¦¬λ‘ μ΄λν©λλ€.
cd CoreFlow/tooling- tooling λλ ν 리 λ΄λΆ μ€μΉ μ€ν¬λ¦½νΈλ₯Ό μ€νν©λλ€.
./install-xcode-template.shμ€μΉ ν Xcodeμμ File β New β File... (βN)μ μ ννλ©΄ CoreFlow ν νλ¦Ώμ μ¬μ©ν μ μμ΅λλ€.
ν΄λΉ λΌμ΄λΈλ¬λ¦¬λ iOS μ ν리μΌμ΄μ κ°λ° μ μν€ν μ² κ²°μ μ 볡μ‘λλ₯Ό μ΅μννκΈ° μν΄ λ§λ€μ΄μ‘μ΅λλ€. λ³΄ν΅ μ ν리μΌμ΄μ κ°λ° μ λ€μκ³Ό κ°μ μν€ν μ²λ€μ΄ κ³ λ €λ©λλ€.
MVVM, MVC, MVVM-C, RIBs, TCA ..
κ°κ°μ μν€ν μ²μ λ¨μ λ§μ μμ ν΄λ³΄κ² μ΅λλ€.
ν° μκ° μμ΄ μμνκΈ° μ’μ ν¨ν΄λ€μ λλ€. νμ§λ§ νλ‘μ νΈμ κ·λͺ¨κ° 컀μ§μλ‘ μ± μμ΄ κ³Όμ€λ κ°μ²΄λ€μ΄ μ¦κ°νκ² λμ΄ λ³΅μ‘ν μ½λλ² μ΄μ€κ° λ§λ€μ΄μ§κ³ ν μ€νΈλ μ΄λ ΅μ΅λλ€.
μ½λλ€μ΄ν°λ μΌλ°μ μΌλ‘ ViewControllerμ λ΄λΉκ²μ΄μ
μ±
μμ λ΄λΉνκ³ , κΈ°λ₯ κ³μΈ΅μ ꡬμ±νλ μν μ μνν©λλ€.
νμ§λ§ κ·Έ κ΅¬μ‘°κ° μ ννλμ΄ μμ§ λͺ»ν©λλ€.
μλ₯Ό λ€μ΄ νΉμ Coordinator κ³μΈ΅μ μ‘΄μ¬νλ κ°μ²΄μ μ κ·Όνκ³ μΆμ κ²½μ° λ€μν λ°©μμ΄ κ°λ₯ν©λλ€.
μ§μ ν΄λΉ κ°μ²΄λ₯Ό μ°Έμ‘°ν μ μκ³ , Coordinator κ³μΈ΅μ μ΄λνμ¬ μ κ·Όν μλ μμ΅λλ€.
μ΄λ¬ν μμ λ‘μμ λλ‘λ νμ
μ λμ²ν νλ¦μ λ§λ€κ³ μ μ§λ³΄μνκΈ° μ΄λ €μ΄ μ½λλ₯Ό λ³μ΅λλ€.
κ°μ₯ μ ννλ ν¨ν΄μ΄λΌκ³ λ§ν μ μμ΅λλ€.
νμ§λ§ λ무 무κ²μ΅λλ€. μμ‘΄κ΄κ³λ₯Ό μ΅μννκΈ° μν΄ λ§μ μΆμνκ° μ‘΄μ¬ν©λλ€.
RIB λ΄λΆμμλ μΆμνλ κ°μ²΄λ€ κ° μν΅μ μν μΈν°νμ΄μ€λ₯Ό ꡬνν ν μν΅μ μμν μ μλ€λ μ μμ 볡μ‘λμ 곡μκ° ν½λλ€.
κ·Έλ‘ μΈν λ¬λμ»€λΈ μμ 무μνμ§ λͺ»ν μμ€μ
λλ€.
RIBsλ RxSwiftλ‘ κ΅¬νλμ΄ μμ΅λλ€. κ²μ¦λ λΌμ΄λΈλ¬λ¦¬λ₯Ό κΈ°λ°μΌλ‘ νμ§λ§ μ₯κΈ°μ μΈ μ§μμ 보μ₯ν μ μμ΅λλ€.
μμ μ μΈ κ΅¬μ‘°μ κ°λ ₯ν μΆμνκ° μ‘΄μ¬νμ§λ§, 곡μκ° λ§μ΄ λλ μν€ν
μ²μ
λλ€.
리λμ μ»΄ν¬μ§μ λ± κΈ°μ‘΄ iOS κ°λ°μμλ μ 곡νμ§ μμλ μλ‘μ΄ ν¨λ¬λ€μμ μ 곡ν©λλ€. νμ§λ§ ν΄λΉ λΌμ΄λΈλ¬λ¦¬ κ°λ°μμκ² μ§λμΉκ² μμ‘΄μ μ΄λΌλ μ μ΄ λ¬Έμ μ λλ€. μλ§μ λ§€ν¬λ‘μ μΆμν λ±μ μ¬μ©μκ° λ΄λΆ λμμ μ΄ν΄νκΈ° μ΄λ ΅κ² ν©λλ€. ν₯ν μ§μ λ° λ³λμ¬νμΌλ‘ μΈν μνμ΄ ν° λΌμ΄λΈλ¬λ¦¬λΌκ³ μκ°ν©λλ€.
CoreFlowλ μμμ μμ λ λ¬Έμ λ€μ ν΄κ²°νκ³ μ λ§λ€μμ΅λλ€.
- μ ννλ ν¨ν΄κ³Ό ꡬ쑰λ₯Ό μ 곡νλ©° μ΄ν΄νκΈ° μ½μ΅λλ€.
- κ³Όλν μΆμνλ₯Ό μ¬μ©νμ§ μμ΅λλ€. κ°μ²΄ κ° μμ‘΄μ± κ΄λ¦¬λ μ κ·Ό μ§μ μ μ¬μ©μ μ§ν₯ν©λλ€.
Combineκ³ΌSwift ConcurrencyκΈ°λ°μΌλ‘ ꡬννμ¬ μ₯κΈ°μ μΈ μμ μ±μ΄ λμ΅λλ€.- RIBsμμ μ 곡νλ
LeakDetector,WorkflowκΈ°λ₯μ μ§μν©λλ€.
CoreFlowλ μΈ κ°μ§ μ»΄ν¬λνΈ(Flow, Core, Screen)λ‘ κ΅¬μ±λ©λλ€.
μ΄ μΈ κ°μ§ μμλ‘ κ΅¬μ±λ μ§ν©μ CoreFlowλΌκ³ λͺ
μΉν©λλ€.
μλλΆν° κ° κ΅¬μ±μμμ λν κ°λ΅ν μ€λͺ μ΄ μμ΅λλ€. λ μμΈν λͺ μΈλ docs λλ ν°λ¦¬ λ΄λΆ λ¬Έμλ₯Ό μ°Έκ³ ν΄μ£ΌμΈμ.
Flow κ°μ²΄λ Coreμ Screen λ κ°μ²΄λ₯Ό μ°Έμ‘°νλ©° νΈλ¦¬ ꡬμ±μ μ€μ¬μ΄ λ©λλ€. λ€λ₯Έ Flowλ₯Ό μ§μ μ μΌλ‘ μ°Έμ‘°νλ 주체λ‘, λ΄λΉκ²μ΄μ λ° μΈν°λμ μ μ°κ²°ν©λλ€.
CoreFlowμ ν΅μ¬μ μΈ λ‘μ§μ΄ μμΉν©λλ€.
μ΄μ λλΆμ΄ CoreFlowμ μ€ν¬λ¦°μ΄ μ‘΄μ¬νλ κ²½μ° Reactorμ μν λ μνν©λλ€.
Reactor ν¨ν΄μ λ¨λ°©ν₯ μν€ν
μ²λ₯Ό κΈ°λ°μΌλ‘ νλ λμμΈ ν¨ν΄μΌλ‘,
μ μλ €μ§ νλ μμν¬μΈ ReactorKitκ³Ό TCAλ₯Ό μ°Έκ³ νμ¬ μ μνμμ΅λλ€.
Screenμ UIViewControllerλΌκ³ μκ°νμλ©΄ λ©λλ€.
Coreμ μνλ₯Ό ꡬλ
νκ³ μμΌλ©°, λ·°μ μ‘μ
μ Coreμ μ λ¬ν μ μμ΅λλ€.
Procedureλ RIBsμ Workflowμ μ μ¬ν κΈ°λ₯μΌλ‘, μ±μ νλ¦μ λ¨κ³λ³λ‘ μ μν μ μμ΅λλ€.
ν΄λΉ κΈ°λ₯μ μ¬μ©νμ¬ μ±μ λ°μΉνλ‘μ° λ° λ₯λ§ν¬ λΆμμ ν΅ν νλ¦μ μμ½κ² λ§λ€μ΄λΌ μ μμ΅λλ€.
Combine κΈ°λ°μ 체μ΄λ APIλ₯Ό μ 곡νμ¬ λ³΅μ‘ν λΉλκΈ° νλ¦μ μ μΈμ μΌλ‘ ννν μ μμ΅λλ€.
Procedureλ₯Ό μμλ°μ μν¬νλ‘μ°λ₯Ό μ μν©λλ€.onStepμ 체μ΄λνμ¬ κ° λ¨κ³λ₯Ό μ°κ²°ν©λλ€.commit()μΌλ‘ μν¬νλ‘μ°λ₯Ό νμ ν©λλ€.start()λ‘ μ€νν©λλ€.
final class DefaultProcedure: Procedure<RootStepAction> {
override init() {
super.init()
onStep { rootStepAction in
rootStepAction.waitForOnboarding()
}
.onStep { rootStepAction, _ in
rootStepAction.waitForLogin()
}
.onStep { rootStepAction, user in
rootStepAction.presentMain(user: user)
}
.commit()
}
}κ° λ¨κ³μμ μ€νν μ‘μ
μ νλ‘ν μ½λ‘ μ μν©λλ€.
κ° λ©μλλ AnyPublisher<(NextAction, Value), Never>λ₯Ό λ°ννμ¬ λ€μ λ¨κ³λ‘ κ°μ μ λ¬ν©λλ€.
protocol RootStepAction {
func waitForOnboarding() -> AnyPublisher<(RootStepAction, Void), Never>
func waitForLogin() -> AnyPublisher<(RootStepAction, User), Never>
func presentMain(user: User) -> AnyPublisher<(MainStepAction, Void), Never>
}StepAction νλ‘ν μ½μ ν΄λΉ νλ¦μ κ΄μ₯νλ Coreκ° μ±ννμ¬ κ΅¬νν©λλ€.
Coreλ μ΄λ―Έ routerλ₯Ό ν΅ν΄ νλ©΄ μ νμ μ μ΄νκ³ , μμ Flowμ Listenerλ₯Ό ꡬννμ¬ μλ£ μμ μ μ μ μμΌλ―λ‘ StepActionμ μν μ μννκΈ°μ κ°μ₯ μ ν©ν©λλ€(κΆμ₯).
extension RootCore: RootStepAction {
func waitForOnboarding() -> AnyPublisher<(RootStepAction, Void), Never> {
router?.routeToOnboarding()
return onboardingFinished
.compactMap(\.self)
.map { (self, ()) }
.eraseToAnyPublisher()
}
func waitForLogin() -> AnyPublisher<(RootStepAction, User), Never> {
router?.routeToLogin()
return loginFinished
.compactMap(\.self)
.map { user in (self, user) }
.eraseToAnyPublisher()
}
}final class RootCore: Core<RootAction, RootState, RootFlow> {
override func reduce(state: inout RootState, action: RootAction) -> Effect<RootAction> {
switch action {
case .viewDidLoad:
DefaultProcedure()
.start(self) // RootStepActionμ μ€μνλ selfλ₯Ό μ λ¬
.store(in: &store)
return .none
}
}
}μ΄ ν¨ν΄μ μ¬μ©νλ©΄ Onboarding β Login β Mainκ³Ό κ°μ μ±μ μ 체 νλ¦μ λͺ ννκ² μ μνκ³ κ΄λ¦¬ν μ μμ΅λλ€.
Reactor μν μ μννλ Coreμ κ²½μ° Actionμ κΈ°λ°μΌλ‘ κ²°μ λ μ΅μ’
μνλ₯Ό κ²μ¦ν μ μμ΅λλ€.
νλμ Actionμ μ μ‘νλλΌλ Core λ΄λΆμμ Effectκ° μλ‘μ΄ Actionμ λ°νν μ μμ΅λλ€.
λ°λΌμ μ΅μ’
μνκ° κ²°μ λκΈ°κΉμ§ λκΈ°κ° νμν©λλ€.
Actionμ μ μ‘ν μ΄ν exhaust()μ νΈμΆνμ¬ μ΅μ’
μν κ²°μ μ κΈ°λ€λ¦΄ μ μμ΅λλ€.
ν΄λΉ ν¨μκ° λ¦¬ν΄λ μ΄ν currentStateλ‘ μ΅μ’
μνμ μ κ·Όν μ μμ΅λλ€.
import Testing
@testable import YourApp
import CoreFlow
@MainActor
struct CoreTests {
@Test
func testActionFlow() async throws {
// 1. Core μΈμ€ν΄μ€ μμ±
let sut = SutCore(initialState: .init(step: 0))
// 2. ν
μ€νΈ λͺ¨λ νμ±ν
sut.enableTestMode()
// 3. Action μ μ‘
sut.send(.step1)
// 4. λͺ¨λ Effectκ° μλ£λ λκΉμ§ λκΈ°
try await sut.exhaust(timeout: 5)
// 5. μ΅μ’
μν κ²μ¦
#expect(sut.currentState.step == 4)
}
}public final class SutCore: Core<SutAction, SutState> {
public override func reduce(state: inout SutState, action: SutAction) -> Effect<SutAction> {
switch action {
case .step1:
state.step = 1
return .run { send in
await send(.step2) // Effectκ° μλ‘μ΄ Action λ°ν
}
case .step2:
state.step = 2
return .run { send in
await send(.step3)
}
case .step3:
state.step = 3
return .run { send in
await send(.step4)
}
case .step4:
state.step = 4
return .none // μ΅μ’
μν
}
}
}μ μμμμ .step1 μ‘μ
μ μ μ‘νλ©΄ Effect 체μΈμ ν΅ν΄ .step2 β .step3 β .step4κΉμ§ μμ°¨μ μΌλ‘ μ€νλ©λλ€.
exhaust()μ λͺ¨λ Effectκ° μλ£λμ΄ λ μ΄μ μ§ν μ€μΈ μμ
μ΄ μμ λ 리ν΄λ©λλ€.