Skip to content

Commit 222dade

Browse files
authored
[#539] LoginView에 TCA를 적용한다 (#541)
* test: LoginView 기능 테스트 추가 * refactor: TCA의 Store과 매칭방지를 위해 기존의 Store -> StorePattern로 수정 * test: TCA용으로 주입부만 수정 * chore: DevLog 에이전트 검증 규칙 정리 * chore: LoginViewModel 제거 * refactor: LoginFeature 구현 및 적용 * refactor: 콤마 린트 해결 * refactor: LoginFeature Store 주입 구조 개선 * refactor: SignInUseCase에 Sendable 채택 * refactor: Sendable 채택 * refactor: UserDefaults에 대해 Sendable 래퍼 구현 및 적용 * refactor: Firebase에 대해 Sendable 래퍼 구현 및 적용 * refactor: Store에서 State 프로퍼티 래퍼 제거
1 parent 5ee94f4 commit 222dade

52 files changed

Lines changed: 688 additions & 264 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.hermes/skills/devlog-architecture-harness/SKILL.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Ask the user before editing when:
7777
- WidgetCore would depend on Domain, Data, Infra, Persistence, Presentation, or App.
7878
- Presentation would depend on Data, Infra, Persistence, or App.
7979
- Data would gain concrete SDK or storage implementation details.
80-
- The Presentation `Store` flow or reducer responsibility would change.
80+
- The Presentation `StorePattern` flow or reducer responsibility would change.
8181
- A compile fix requires relaxing the intended architecture.
8282
- The change is outside the requested issue or PR scope.
8383

@@ -88,16 +88,15 @@ When the boundary is clear:
8888
- Keep the diff limited to the requested task.
8989
- Preserve existing logic unless the user explicitly approved logic changes.
9090
- Prefer existing DevLog naming and layer patterns.
91-
- Preserve the existing Presentation `Store` pattern: `@MainActor`, `State`, `Action`, `SideEffect`, and `send -> reduce -> run`.
91+
- Preserve the existing Presentation `StorePattern`: `@MainActor`, `State`, `Action`, `SideEffect`, and `send -> reduce -> run`.
9292
- Do not introduce unrelated cleanup.
9393
- Do not change lockfiles unless dependency resolution is part of the task.
9494

9595
### 5. Verify
9696

9797
For Swift/iOS code changes:
9898

99-
- Use Xcode Local MCP for the build.
100-
- If Xcode Local MCP is unavailable, say so and ask before using another path unless the user already approved a fallback.
99+
- Follow the repository `AGENTS.md` Verification section.
101100
- Inspect the final diff for architecture-scope drift.
102101

103102
For docs-only or harness-only changes:

.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,12 @@ flowchart TD
123123
| `DevLogWidgetCore` | widget data contracts and pure snapshot logic | Core | Adding Domain, Data, Infra, Persistence, Presentation, or App dependency |
124124
| `DevLogWidgetExtension` | WidgetKit rendering and timeline plumbing | WidgetCore | Calling app/domain services directly |
125125

126-
## Presentation Store flow
126+
## Presentation StorePattern flow
127127

128128
```mermaid
129129
flowchart LR
130130
View["SwiftUI View"]
131-
ViewModel["ViewModel / Store"]
131+
ViewModel["ViewModel / StorePattern"]
132132
Send["send(Action)"]
133133
Reduce["reduce(with:)"]
134134
State["State update"]

.hermes/skills/devlog-architecture-harness/references/devlog-workflow-rules.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ This reference holds DevLog-specific working rules that should live with the pro
1010

1111
## Verification
1212

13+
- Follow `AGENTS.md` for the canonical lint and build verification policy.
14+
- Run Homebrew SwiftLint (`swiftlint`) on changed Swift files.
15+
- Lint production Swift files with the applicable source `.swiftlint.yml` config.
16+
- Lint test Swift files with `.swiftlint-tests.yml` or the module `Tests/.swiftlint.yml` that inherits from it. Do not use the root production config for tests.
1317
- Prefer Xcode Local MCP for iOS project code changes.
1418
- If Xcode Local MCP is unavailable or fails because of session transport, state that explicitly before using a fallback.
1519
- This repository is workspace-based. Prefer workspace/scheme context over standalone project builds when dependencies cross module projects.
@@ -61,9 +65,9 @@ This reference holds DevLog-specific working rules that should live with the pro
6165
- For example, keep the app-facing Domain query separate from an Infra-facing Data query when that avoids Domain coupling in service protocols.
6266
- Firebase-specific error detection belongs in Infra; Data should handle domain-level errors after mapping.
6367

64-
## Presentation Store
68+
## Presentation StorePattern
6569

66-
- Preserve the existing `Store` shape: `@MainActor`, `State`, `Action`, `SideEffect`, `send -> reduce -> run`.
70+
- Preserve the existing `StorePattern` shape: `@MainActor`, `State`, `Action`, `SideEffect`, `send -> reduce -> run`.
6771
- Reducers compute state and return side effects.
6872
- I/O belongs in `run` or injected services.
6973
- Do not leave reducer-era helper methods behind after moving work into `run`.

AGENTS.md

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ These instructions apply only to the repository root.
1818

1919
## Naming and Swift style
2020

21-
- Set variables named after a type using the type's full name in camel case.
2221
- In Swift, do not write explicit type annotations unless required.
2322
- Use `opfic` in new Swift file headers.
2423
- Prefer `<` and `<=` over `>` and `>=` when writing comparisons, if the condition can be expressed clearly that way.
@@ -37,7 +36,7 @@ Treat this repository as a Tuist-generated, workspace-based modular iOS app. The
3736
4. Classify the change as mechanical, architectural, or ambiguous.
3837
5. For ambiguous architecture changes, stop and ask the user before editing.
3938
6. Keep the diff limited to the requested architecture scope.
40-
7. After Swift/iOS code changes, verify with Xcode Local MCP.
39+
7. After Swift/iOS code changes, follow the Verification section.
4140
8. Report the changed files, architecture decision, and verification result.
4241

4342
### Current layer map
@@ -53,10 +52,10 @@ Treat this repository as a Tuist-generated, workspace-based modular iOS app. The
5352
- `Widget/DevLogWidgetExtension`: WidgetKit UI, widget providers, entries, timelines, and extension resources. It should consume WidgetCore outputs rather than app/domain services directly.
5453
- `Firebase/functions`: TypeScript Cloud Functions. Deploy updated functions one by one separately.
5554

56-
### Store flow
55+
### StorePattern flow
5756

58-
- Preserve the existing Presentation `Store` pattern.
59-
- `Store` is `@MainActor` and uses `State`, `Action`, `SideEffect`, and the `send -> reduce -> run` flow.
57+
- Preserve the existing Presentation `StorePattern`.
58+
- `StorePattern` is `@MainActor` and uses `State`, `Action`, `SideEffect`, and the `send -> reduce -> run` flow.
6059
- Reducers should compute state and return side effects.
6160
- I/O belongs in `run` or injected services, not in reducer state computation.
6261
- Ask before changing reducer, side-effect, or ViewModel responsibility boundaries.
@@ -86,7 +85,10 @@ These may proceed after inspection when they do not change architecture meaning:
8685

8786
## Verification
8887

89-
- If iOS project code changes, test build with Xcode Local MCP.
88+
- If Swift files change, run Homebrew SwiftLint (`swiftlint`) on the changed Swift files.
89+
- For production Swift files, use the applicable source `.swiftlint.yml` config.
90+
- For test Swift files, use `.swiftlint-tests.yml` or the module `Tests/.swiftlint.yml` that inherits from it. Do not lint tests with the root production config.
91+
- If iOS project code changes, verify with Xcode Local MCP when it is available.
9092
- If Xcode Local MCP is unavailable, state that explicitly before using a fallback.
9193
- Do not claim architecture work is complete without checking the diff scope.
9294
- Do not spend time on unrelated generated project or lockfile churn. Keep generated workspace/project and `Package.resolved` changes out of source control unless they are part of an explicitly approved dependency-lock policy.
@@ -98,10 +100,3 @@ These may proceed after inspection when they do not change architecture meaning:
98100
- Treat `AGENTS.md` and `.hermes/skills/devlog-architecture-harness` as the canonical DevLog AI working rules.
99101
- If global memory conflicts with this repository, follow this repository.
100102
- For PR, commit, Xcode project, CI, widget, Store, localization, or release workflow details, read `.hermes/skills/devlog-architecture-harness/references/devlog-workflow-rules.md`.
101-
102-
## Sub-agent use
103-
104-
- Consider sub-agent use on every non-trivial task.
105-
- Use sub-agents only for independent research, verification, or disjoint implementation work.
106-
- Do not use sub-agents for sequential steps, overlapping file edits, or tightly coupled refactors.
107-
- The main agent remains responsible for planning, integration, final verification, and user communication.

Application/DevLogApp/Sources/App/DevLogApp.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct DevLogApp: App {
2929
networkConnectivityUseCase: container.resolve(ObserveNetworkConnectivityUseCase.self),
3030
systemThemeUseCase: container.resolve(ObserveSystemThemeUseCase.self),
3131
trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self),
32+
signInUseCase: container.resolve(SignInUseCase.self),
3233
widgetURLTab: { MainTab(widgetURL: $0) },
3334
windowEvent: windowEvent,
3435
pushNotificationTodoIdPublisher: PushNotificationRoute.shared.observe(),

Application/DevLogCore/Sources/ActivityKind.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import Foundation
99

10-
public enum ActivityKind: String, Hashable {
10+
public enum ActivityKind: String, Hashable, Sendable {
1111
case created
1212
case completed
1313
case deleted

Application/DevLogCore/Sources/Logger.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import Foundation
99
import os.log
1010

11-
public final class Logger {
11+
public final class Logger: Sendable {
1212
private let subsystem: String
1313
private let category: String
1414
private let osLog: OSLog

Application/DevLogCore/Sources/TodayDisplayOptions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77

88
import Foundation
99

10-
public struct TodayDisplayOptions: Equatable {
11-
public enum DueDateVisibility: String, CaseIterable, Equatable {
10+
public struct TodayDisplayOptions: Equatable, Sendable {
11+
public enum DueDateVisibility: String, CaseIterable, Equatable, Sendable {
1212
case all
1313
case withDueDateOnly
1414
case withoutDueDateOnly
1515
}
1616

17-
public enum FocusVisibility: String, CaseIterable, Equatable {
17+
public enum FocusVisibility: String, CaseIterable, Equatable, Sendable {
1818
case all
1919
case focusedOnly
2020
}

Application/DevLogData/Sources/Protocol/AuthService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import Combine
99
import Foundation
1010

11-
public protocol AuthService {
11+
public protocol AuthService: Sendable {
1212
var uid: String? { get }
1313
var providerIDs: [String] { get }
1414
var currentUserEmail: String? { get }

Application/DevLogData/Sources/Protocol/AuthenticationService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import Foundation
99

10-
public protocol AuthenticationService {
10+
public protocol AuthenticationService: Sendable {
1111
func signIn() async throws -> AuthDataResponse
1212
func signOut(_ uid: String) async throws
1313
func deleteAuth(_ uid: String) async throws

0 commit comments

Comments
 (0)