From b57bf9c3b5c11288601d5be123d5ebc724c9bdda Mon Sep 17 00:00:00 2001 From: Roy Date: Mon, 26 Oct 2026 12:36:27 +0900 Subject: [PATCH] =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20Feature=EC=9D=98?= =?UTF-8?q?=20=EC=97=AD=ED=95=A0=EB=B3=84=20Interface=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Class Feature의 단일 classUseCase 참조를 화면 역할에 맞는 Interface 의존성으로 분리합니다. 참여와 추천 화면은 필요한 두 Interface만 주입하고 리포트 미리보기도 결과 Interface에 맞춥니다. --- .../Reducer/ClassAIChatFeature.swift | 2 +- .../Reducer/ClassAIVoteFeature.swift | 2 +- .../Reducer/ClassBattleFlowFeature.swift | 2 +- .../Reducer/ClassDeadlineEditFeature.swift | 2 +- .../Reducer/ClassDetailFeature.swift | 6 ++-- .../ClassJoin/Reducer/ClassJoinFeature.swift | 15 +++++----- .../Reducer/ClassMyOpinionsFeature.swift | 2 +- .../Reducer/ClassOwnerDashboardFeature.swift | 2 +- .../Reducer/ClassRecommendFeature.swift | 29 ++++++++++--------- .../Reducer/ClassReportFeature.swift | 2 +- .../ClassReport/View/ClassReportView.swift | 2 +- .../Reducer/ClassSettingFeature.swift | 2 +- .../Reducer/ClassTicketFeature.swift | 2 +- .../MyClass/Reducer/MyClassFeature.swift | 2 +- 14 files changed, 37 insertions(+), 35 deletions(-) diff --git a/Projects/Feature/Class/Sources/ClassAIChat/Reducer/ClassAIChatFeature.swift b/Projects/Feature/Class/Sources/ClassAIChat/Reducer/ClassAIChatFeature.swift index 698eeb0f..dc168d66 100644 --- a/Projects/Feature/Class/Sources/ClassAIChat/Reducer/ClassAIChatFeature.swift +++ b/Projects/Feature/Class/Sources/ClassAIChat/Reducer/ClassAIChatFeature.swift @@ -168,7 +168,7 @@ public struct ClassAIChatFeature { case response } - @Dependency(\.classUseCase) private var debateUseCase + @Dependency(\.classDebateUseCase) private var debateUseCase public var body: some Reducer { Reduce { state, action in diff --git a/Projects/Feature/Class/Sources/ClassAIVote/Reducer/ClassAIVoteFeature.swift b/Projects/Feature/Class/Sources/ClassAIVote/Reducer/ClassAIVoteFeature.swift index ea9f1235..26fb536b 100644 --- a/Projects/Feature/Class/Sources/ClassAIVote/Reducer/ClassAIVoteFeature.swift +++ b/Projects/Feature/Class/Sources/ClassAIVote/Reducer/ClassAIVoteFeature.swift @@ -176,7 +176,7 @@ public struct ClassAIVoteFeature { @Dependency(\.uuid) private var uuid @Dependency(\.battleUseCase) private var battleUseCase - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classBattleUseCase) private var classUseCase public var body: some Reducer { Reduce { state, action in diff --git a/Projects/Feature/Class/Sources/ClassBattleFlow/Reducer/ClassBattleFlowFeature.swift b/Projects/Feature/Class/Sources/ClassBattleFlow/Reducer/ClassBattleFlowFeature.swift index b1452489..d974bfd8 100644 --- a/Projects/Feature/Class/Sources/ClassBattleFlow/Reducer/ClassBattleFlowFeature.swift +++ b/Projects/Feature/Class/Sources/ClassBattleFlow/Reducer/ClassBattleFlowFeature.swift @@ -177,7 +177,7 @@ public struct ClassBattleFlowFeature { } @Dependency(\.uuid) private var uuid - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classBattleUseCase) private var classUseCase @Dependency(\.battleUseCase) private var battleUseCase @Dependency(\.audioPlayer) private var audioPlayer diff --git a/Projects/Feature/Class/Sources/ClassDeadlineEdit/Reducer/ClassDeadlineEditFeature.swift b/Projects/Feature/Class/Sources/ClassDeadlineEdit/Reducer/ClassDeadlineEditFeature.swift index 26e10d13..20fed5d9 100644 --- a/Projects/Feature/Class/Sources/ClassDeadlineEdit/Reducer/ClassDeadlineEditFeature.swift +++ b/Projects/Feature/Class/Sources/ClassDeadlineEdit/Reducer/ClassDeadlineEditFeature.swift @@ -104,7 +104,7 @@ public struct ClassDeadlineEditFeature { case save(UUID) } - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classRoomUseCase) private var classUseCase @Dependency(\.date) private var date @Dependency(\.uuid) private var uuid diff --git a/Projects/Feature/Class/Sources/ClassDetail/Reducer/ClassDetailFeature.swift b/Projects/Feature/Class/Sources/ClassDetail/Reducer/ClassDetailFeature.swift index 7f496f9c..02a8b47f 100644 --- a/Projects/Feature/Class/Sources/ClassDetail/Reducer/ClassDetailFeature.swift +++ b/Projects/Feature/Class/Sources/ClassDetail/Reducer/ClassDetailFeature.swift @@ -94,7 +94,7 @@ public struct ClassDetailFeature { case deleted(Int, ClassError?) } - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classRoomUseCase) private var classRoomUseCase public var body: some Reducer { Reduce { state, action in @@ -234,9 +234,9 @@ extension ClassDetailFeature { state.errorMessage = nil switch action { case let .delete(id): - return .run { [classUseCase] send in + return .run { [classRoomUseCase] send in do { - try await classUseCase.deleteClass(id: id) + try await classRoomUseCase.deleteClass(id: id) await send(.inner(.deleted(id, nil))) } catch { await send(.inner(.deleted(id, ClassError.from(error)))) diff --git a/Projects/Feature/Class/Sources/ClassJoin/Reducer/ClassJoinFeature.swift b/Projects/Feature/Class/Sources/ClassJoin/Reducer/ClassJoinFeature.swift index d7bda912..0bcb3fca 100644 --- a/Projects/Feature/Class/Sources/ClassJoin/Reducer/ClassJoinFeature.swift +++ b/Projects/Feature/Class/Sources/ClassJoin/Reducer/ClassJoinFeature.swift @@ -154,7 +154,8 @@ public struct ClassJoinFeature { case nameOwner(UUID) } - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classRoomUseCase) private var classRoomUseCase + @Dependency(\.classMemberUseCase) private var classMemberUseCase @Dependency(\.uuid) private var uuid public var body: some Reducer { @@ -250,9 +251,9 @@ extension ClassJoinFeature { state.activeFindRequestID = requestID state.errorMessage = nil state.nicknameErrorMessage = nil - return .run { [classUseCase, instanceID = state.instanceID] send in + return .run { [classRoomUseCase, instanceID = state.instanceID] send in let result = await Result { - try await classUseCase.fetchClassPreview(joinCode: code) + try await classRoomUseCase.fetchClassPreview(joinCode: code) } .mapError(ClassError.from) guard !Task.isCancelled else { return } @@ -266,9 +267,9 @@ extension ClassJoinFeature { state.activeJoinRequestID = requestID state.errorMessage = nil state.nicknameErrorMessage = nil - return .run { [classUseCase, instanceID = state.instanceID] send in + return .run { [classRoomUseCase, instanceID = state.instanceID] send in let result = await Result { - try await classUseCase.joinClass(joinCode: code, nickname: nickname) + try await classRoomUseCase.joinClass(joinCode: code, nickname: nickname) } .mapError(ClassError.from) guard !Task.isCancelled else { return } @@ -287,9 +288,9 @@ extension ClassJoinFeature { state.activeOwnerRequestID = requestID state.errorMessage = nil state.nicknameErrorMessage = nil - return .run { [classUseCase, room = state.preview] send in + return .run { [classMemberUseCase, room = state.preview] send in let result = await Result { () async throws -> ClassRoom in - _ = try await classUseCase.updateMyDisplayName(classID: roomID, name: nickname) + _ = try await classMemberUseCase.updateMyDisplayName(classID: roomID, name: nickname) guard let room else { throw ClassError.invalidCode } return room } diff --git a/Projects/Feature/Class/Sources/ClassMyOpinions/Reducer/ClassMyOpinionsFeature.swift b/Projects/Feature/Class/Sources/ClassMyOpinions/Reducer/ClassMyOpinionsFeature.swift index c9c6e3c4..a7819431 100644 --- a/Projects/Feature/Class/Sources/ClassMyOpinions/Reducer/ClassMyOpinionsFeature.swift +++ b/Projects/Feature/Class/Sources/ClassMyOpinions/Reducer/ClassMyOpinionsFeature.swift @@ -74,7 +74,7 @@ public struct ClassMyOpinionsFeature { case fetch } - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classBattleUseCase) private var classUseCase public var body: some Reducer { Reduce { state, action in diff --git a/Projects/Feature/Class/Sources/ClassOwnerDashboard/Reducer/ClassOwnerDashboardFeature.swift b/Projects/Feature/Class/Sources/ClassOwnerDashboard/Reducer/ClassOwnerDashboardFeature.swift index 3e87f44c..107eb195 100644 --- a/Projects/Feature/Class/Sources/ClassOwnerDashboard/Reducer/ClassOwnerDashboardFeature.swift +++ b/Projects/Feature/Class/Sources/ClassOwnerDashboard/Reducer/ClassOwnerDashboardFeature.swift @@ -376,7 +376,7 @@ public struct ClassOwnerDashboardFeature { case openFeedback(ClassOwnerMember) } - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classResultUseCase) private var classUseCase @Dependency(\.uuid) private var uuid public var body: some Reducer { diff --git a/Projects/Feature/Class/Sources/ClassRecommend/Reducer/ClassRecommendFeature.swift b/Projects/Feature/Class/Sources/ClassRecommend/Reducer/ClassRecommendFeature.swift index 0472d4fa..7c757696 100644 --- a/Projects/Feature/Class/Sources/ClassRecommend/Reducer/ClassRecommendFeature.swift +++ b/Projects/Feature/Class/Sources/ClassRecommend/Reducer/ClassRecommendFeature.swift @@ -132,7 +132,8 @@ public struct ClassRecommendFeature { case select } - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classRecommendationUseCase) private var classRecommendationUseCase + @Dependency(\.classTopicDraftUseCase) private var classTopicDraftUseCase public var body: some Reducer { Reduce { state, action in @@ -242,9 +243,9 @@ extension ClassRecommendFeature { if state.viewState == .loading || state.viewState == .error { state.viewState = .loading } - return .run { [classUseCase] send in + return .run { [classRecommendationUseCase] send in let result = await Result { - try await classUseCase.fetchRecommendedBattles(filter: filter) + try await classRecommendationUseCase.fetchRecommendedBattles(filter: filter) } .mapError(ClassError.from) await send(.inner(.battles(result))) @@ -254,9 +255,9 @@ extension ClassRecommendFeature { case let .createDraft(filter): state.isLoading = true state.viewState = .loading - return .run { [classUseCase] send in + return .run { [classTopicDraftUseCase] send in let result = await Result { - try await classUseCase.createTopicDraft(filter: filter) + try await classTopicDraftUseCase.createTopicDraft(filter: filter) } .mapError(ClassError.from) guard !Task.isCancelled else { return } @@ -267,12 +268,12 @@ extension ClassRecommendFeature { case let .suggest(draftID): state.isLoading = true state.viewState = .loading - return .run { [classUseCase] send in + return .run { [classTopicDraftUseCase] send in let result = await Result { - let draft = try await classUseCase.suggestTopicDraft(id: draftID, filter: nil) + let draft = try await classTopicDraftUseCase.suggestTopicDraft(id: draftID, filter: nil) guard !Task.isCancelled else { throw CancellationError() } await send(.inner(.suggestionStarted(draft))) - return try await Self.pollSuggestion(draft: draft, useCase: classUseCase) + return try await Self.pollSuggestion(draft: draft, useCase: classTopicDraftUseCase) } .mapError(ClassError.from) guard !Task.isCancelled else { return } @@ -283,10 +284,10 @@ extension ClassRecommendFeature { case let .poll(draftID): state.isLoading = true state.viewState = .loading - return .run { [classUseCase] send in + return .run { [classTopicDraftUseCase] send in let result = await Result { - let draft = try await classUseCase.fetchTopicDraft(id: draftID) - return try await Self.pollSuggestion(draft: draft, useCase: classUseCase) + let draft = try await classTopicDraftUseCase.fetchTopicDraft(id: draftID) + return try await Self.pollSuggestion(draft: draft, useCase: classTopicDraftUseCase) } .mapError(ClassError.from) guard !Task.isCancelled else { return } @@ -296,9 +297,9 @@ extension ClassRecommendFeature { case let .select(draftID, batchNo, candidateID): state.isLoading = true - return .run { [classUseCase] send in + return .run { [classTopicDraftUseCase] send in let result = await Result { - try await classUseCase.selectTopicDraft(draftID: draftID, batchNo: batchNo, candidateID: candidateID) + try await classTopicDraftUseCase.selectTopicDraft(draftID: draftID, batchNo: batchNo, candidateID: candidateID) } .mapError(ClassError.from) guard !Task.isCancelled else { return } @@ -368,7 +369,7 @@ extension ClassRecommendFeature { private static func pollSuggestion( draft: ClassTopicDraft, - useCase: any ClassInterface + useCase: any ClassTopicDraftInterface ) async throws -> ClassTopicDraft { var current = draft for _ in 0 ..< 90 where current.suggestStatus == "GENERATING" { diff --git a/Projects/Feature/Class/Sources/ClassReport/Reducer/ClassReportFeature.swift b/Projects/Feature/Class/Sources/ClassReport/Reducer/ClassReportFeature.swift index a63fa5b3..67501506 100644 --- a/Projects/Feature/Class/Sources/ClassReport/Reducer/ClassReportFeature.swift +++ b/Projects/Feature/Class/Sources/ClassReport/Reducer/ClassReportFeature.swift @@ -170,7 +170,7 @@ public struct ClassReportFeature { case generate(UUID) } - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classResultUseCase) private var classUseCase @Dependency(\.uuid) private var uuid public var body: some Reducer { diff --git a/Projects/Feature/Class/Sources/ClassReport/View/ClassReportView.swift b/Projects/Feature/Class/Sources/ClassReport/View/ClassReportView.swift index 57e19131..c4a87739 100644 --- a/Projects/Feature/Class/Sources/ClassReport/View/ClassReportView.swift +++ b/Projects/Feature/Class/Sources/ClassReport/View/ClassReportView.swift @@ -827,7 +827,7 @@ private extension ClassReportView { ) return Store(initialState: state) { ClassReportFeature() - .dependency(\.classUseCase, repository) + .dependency(\.classResultUseCase, repository) } } diff --git a/Projects/Feature/Class/Sources/ClassSetting/Reducer/ClassSettingFeature.swift b/Projects/Feature/Class/Sources/ClassSetting/Reducer/ClassSettingFeature.swift index 510cdae8..a11a6f2d 100644 --- a/Projects/Feature/Class/Sources/ClassSetting/Reducer/ClassSettingFeature.swift +++ b/Projects/Feature/Class/Sources/ClassSetting/Reducer/ClassSettingFeature.swift @@ -185,7 +185,7 @@ public struct ClassSettingFeature { } @Dependency(\.date) private var date - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classRoomUseCase) private var classUseCase public var body: some Reducer { BindingReducer() diff --git a/Projects/Feature/Class/Sources/ClassTicket/Reducer/ClassTicketFeature.swift b/Projects/Feature/Class/Sources/ClassTicket/Reducer/ClassTicketFeature.swift index eb8123c8..86650ddf 100644 --- a/Projects/Feature/Class/Sources/ClassTicket/Reducer/ClassTicketFeature.swift +++ b/Projects/Feature/Class/Sources/ClassTicket/Reducer/ClassTicketFeature.swift @@ -113,7 +113,7 @@ public struct ClassTicketFeature { case existingTicket(UUID) } - @Dependency(\.classUseCase) private var ticketUseCase + @Dependency(\.classTicketUseCase) private var ticketUseCase public var body: some Reducer { BindingReducer() diff --git a/Projects/Feature/Class/Sources/MyClass/Reducer/MyClassFeature.swift b/Projects/Feature/Class/Sources/MyClass/Reducer/MyClassFeature.swift index 18067c71..2f8a350f 100644 --- a/Projects/Feature/Class/Sources/MyClass/Reducer/MyClassFeature.swift +++ b/Projects/Feature/Class/Sources/MyClass/Reducer/MyClassFeature.swift @@ -104,7 +104,7 @@ public struct MyClassFeature { case left(Int) } - @Dependency(\.classUseCase) private var classUseCase + @Dependency(\.classRoomUseCase) private var classUseCase public var body: some Reducer { Reduce { state, action in