Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
4cada68
refactor: separate action/states - #211
clxxrlove Mar 19, 2026
8458e92
refactor: AuthReducer 중첩 Action 패턴 적용 - #211
clxxrlove Apr 14, 2026
4b7bfa3
refactor: MainTabReducer 중첩 Action 패턴 적용 - #211
clxxrlove Apr 14, 2026
310c692
refactor: Onboarding Reducer 중첩 Action 패턴 적용 - #211
clxxrlove Apr 14, 2026
f6a04d0
refactor: NotificationReducer 중첩 Action 패턴 적용 - #211
clxxrlove Apr 14, 2026
71f6c33
refactor: EditGoalListReducer 중첩 Action/State 패턴 적용 - #211
clxxrlove Apr 14, 2026
9df9a5a
refactor: MakeGoalReducer 인스턴스 상수를 static let으로 변환 - #211
clxxrlove Apr 14, 2026
7a3ce09
refactor: ProofPhotoReducer 중첩 Action/State 패턴 적용 - #211
clxxrlove Apr 14, 2026
8362b7e
refactor: StatsReducer 중첩 Action/State 패턴 적용 - #211
clxxrlove Apr 14, 2026
0327d8d
refactor: StatsDetailReducer 중첩 Action/State 패턴 적용 - #211
clxxrlove Apr 14, 2026
53a1f4b
refactor: GoalDetailReducer 중첩 Action/State 패턴 적용 - #211
clxxrlove Apr 14, 2026
0453548
refactor: SettingsReducer 중첩 Action/State 패턴 적용 - #211
clxxrlove Apr 14, 2026
d980ccd
refactor: AppCoordinator action 경로 업데이트 - #211
clxxrlove Apr 14, 2026
b63951c
docs: 중첩 Action/State Reducer 패턴 문서화 및 네이밍 컨벤션 업데이트 - #211
clxxrlove Apr 14, 2026
e6cd487
fix: ProofPhotoReducer Swift.Data → Foundation.Data, AVCaptureSession…
clxxrlove Apr 14, 2026
67bcf34
fix: 리팩토링 이후 regression 및 action/state 경로 오류 수정 - #211
clxxrlove Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Projects/App/Sources/Reducer/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ struct AppCoordinator {
// pending 딥링크가 있으면 처리
if let pendingDeepLink = state.pendingNotificationDeepLink {
state.pendingNotificationDeepLink = nil
effects.append(.send(.route(.mainTab(.notificationDeepLinkReceived(pendingDeepLink)))))
effects.append(.send(.route(.mainTab(.view(.notificationDeepLinkReceived(pendingDeepLink))))))
}

return .merge(effects)
Expand Down Expand Up @@ -209,7 +209,7 @@ struct AppCoordinator {
}

state.pendingNotificationDeepLink = nil
return .send(.route(.mainTab(.notificationDeepLinkReceived(deepLink))))
return .send(.route(.mainTab(.view(.notificationDeepLinkReceived(deepLink)))))

case .route(.auth(.delegate(.loginSucceeded))):
return .merge(
Expand Down Expand Up @@ -256,7 +256,7 @@ struct AppCoordinator {

if let pendingDeepLink = state.pendingNotificationDeepLink {
state.pendingNotificationDeepLink = nil
effects.append(.send(.route(.mainTab(.notificationDeepLinkReceived(pendingDeepLink)))))
effects.append(.send(.route(.mainTab(.view(.notificationDeepLinkReceived(pendingDeepLink))))))
}

return .merge(effects)
Expand Down
87 changes: 63 additions & 24 deletions Projects/Feature/Auth/Sources/Reducer/AuthReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,46 +34,85 @@ public struct AuthReducer {
}

public enum Action {
case appleLoginButtonTapped
case kakaoLoginButtonTapped
case googleLoginButtonTapped
case loginResponse(Result<AuthResult, Error>)
case dismissError
case delegate(Delegate)
// MARK: - View (사용자 이벤트)
public enum View {
case appleLoginButtonTapped
case kakaoLoginButtonTapped
case googleLoginButtonTapped
case dismissError
}

// MARK: - Response (비동기 응답)
public enum Response {
case loginResponse(Result<AuthResult, Error>)
}

// MARK: - Delegate (부모에게 알림)
@CasePathable
public enum Delegate {
case loginSucceeded(AuthResult)
}

case view(View)
case response(Response)
case delegate(Delegate)
}

public init() {}

public var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .appleLoginButtonTapped:
return Self.handleLogin(provider: .apple, state: &state)
case .view(let viewAction):
return reduceView(state: &state, action: viewAction)

case .response(let responseAction):
return reduceResponse(state: &state, action: responseAction)

case .delegate:
return .none
}
}
}
}

// MARK: - View

case .kakaoLoginButtonTapped:
return Self.handleLogin(provider: .kakao, state: &state)
private extension AuthReducer {
func reduceView(
state: inout State,
action: Action.View
) -> Effect<Action> {
switch action {
case .appleLoginButtonTapped:
return Self.handleLogin(provider: .apple, state: &state)

case .googleLoginButtonTapped:
return Self.handleLogin(provider: .google, state: &state)
case .kakaoLoginButtonTapped:
return Self.handleLogin(provider: .kakao, state: &state)

case .loginResponse(.success(let result)):
return Self.handleLoginSuccess(state: &state, result: result)
case .googleLoginButtonTapped:
return Self.handleLogin(provider: .google, state: &state)

case .loginResponse(.failure(let error)):
return Self.handleLoginFailure(state: &state, error: error)
case .dismissError:
state.errorMessage = nil
return .none
}
}
}

case .dismissError:
state.errorMessage = nil
return .none
// MARK: - Response

case .delegate:
return .none
}
private extension AuthReducer {
func reduceResponse(
state: inout State,
action: Action.Response
) -> Effect<Action> {
switch action {
case .loginResponse(.success(let result)):
return Self.handleLoginSuccess(state: &state, result: result)

case .loginResponse(.failure(let error)):
return Self.handleLoginFailure(state: &state, error: error)
}
}
}
Expand All @@ -98,9 +137,9 @@ private extension AuthReducer {
return .run { send in
do {
let authResult = try await authClient.signIn(provider)
await send(.loginResponse(.success(authResult)))
await send(.response(.loginResponse(.success(authResult))))
} catch {
await send(.loginResponse(.failure(error)))
await send(.response(.loginResponse(.failure(error))))
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions Projects/Feature/Auth/Sources/View/AuthView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ public struct AuthView: View {
"로그인 실패",
isPresented: Binding(
get: { store.errorMessage != nil },
set: { _ in store.send(.dismissError) }
set: { _ in store.send(.view(.dismissError)) }
)
) {
Button("확인") {
store.send(.dismissError)
store.send(.view(.dismissError))
}
} message: {
Text(store.errorMessage ?? "")
Expand Down Expand Up @@ -119,7 +119,7 @@ private extension AuthView {
private extension AuthView {
var kakaoLoginButton: some View {
Button {
store.send(.kakaoLoginButtonTapped)
store.send(.view(.kakaoLoginButtonTapped))
} label: {
HStack(spacing: Spacing.spacing6) {
Image.Icon.Symbol.kakao
Expand All @@ -142,7 +142,7 @@ private extension AuthView {

var googleLoginButton: some View {
Button {
store.send(.googleLoginButtonTapped)
store.send(.view(.googleLoginButtonTapped))
} label: {
HStack(spacing: Spacing.spacing6) {
Image.Icon.Symbol.google
Expand All @@ -169,7 +169,7 @@ private extension AuthView {

var appleLoginButton: some View {
Button {
store.send(.appleLoginButtonTapped)
store.send(.view(.appleLoginButtonTapped))
} label: {
HStack(spacing: Spacing.spacing6) {
Image.Icon.Symbol.apple
Expand Down
Loading
Loading