From 61686b495b0ba5c3a33fb127834aca76b0c4dc55 Mon Sep 17 00:00:00 2001 From: "gnoes.ios" Date: Thu, 6 Aug 2026 18:59:10 +0900 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20Domain=20Auth=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=EB=A5=BC=20Model/Client/Error=EB=A1=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Projects/Domain/Sources/Auth/{ => Client}/AuthClient.swift | 0 Projects/Domain/Sources/Auth/{ => Error}/AuthError.swift | 0 Projects/Domain/Sources/Auth/{ => Model}/AuthProvider.swift | 0 Projects/Domain/Sources/Auth/{ => Model}/AuthSession.swift | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename Projects/Domain/Sources/Auth/{ => Client}/AuthClient.swift (100%) rename Projects/Domain/Sources/Auth/{ => Error}/AuthError.swift (100%) rename Projects/Domain/Sources/Auth/{ => Model}/AuthProvider.swift (100%) rename Projects/Domain/Sources/Auth/{ => Model}/AuthSession.swift (100%) diff --git a/Projects/Domain/Sources/Auth/AuthClient.swift b/Projects/Domain/Sources/Auth/Client/AuthClient.swift similarity index 100% rename from Projects/Domain/Sources/Auth/AuthClient.swift rename to Projects/Domain/Sources/Auth/Client/AuthClient.swift diff --git a/Projects/Domain/Sources/Auth/AuthError.swift b/Projects/Domain/Sources/Auth/Error/AuthError.swift similarity index 100% rename from Projects/Domain/Sources/Auth/AuthError.swift rename to Projects/Domain/Sources/Auth/Error/AuthError.swift diff --git a/Projects/Domain/Sources/Auth/AuthProvider.swift b/Projects/Domain/Sources/Auth/Model/AuthProvider.swift similarity index 100% rename from Projects/Domain/Sources/Auth/AuthProvider.swift rename to Projects/Domain/Sources/Auth/Model/AuthProvider.swift diff --git a/Projects/Domain/Sources/Auth/AuthSession.swift b/Projects/Domain/Sources/Auth/Model/AuthSession.swift similarity index 100% rename from Projects/Domain/Sources/Auth/AuthSession.swift rename to Projects/Domain/Sources/Auth/Model/AuthSession.swift From 3931899961c1178d62f3bd5686b326af6a336de6 Mon Sep 17 00:00:00 2001 From: "gnoes.ios" Date: Thu, 6 Aug 2026 18:59:18 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=EC=98=A8=EB=B3=B4=EB=94=A9=20User?= =?UTF-8?q?=20Domain=20=EA=B3=84=EC=95=BD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/User/Client/UserClient.swift | 18 +++++++++++++++++ .../Domain/Sources/User/Error/UserError.swift | 10 ++++++++++ .../Domain/Sources/User/Model/Gender.swift | 7 +++++++ .../Domain/Sources/User/Model/Interest.swift | 11 ++++++++++ .../Sources/User/Model/OnboardingDraft.swift | 20 +++++++++++++++++++ .../Sources/User/Model/UserProfile.swift | 20 +++++++++++++++++++ 6 files changed, 86 insertions(+) create mode 100644 Projects/Domain/Sources/User/Client/UserClient.swift create mode 100644 Projects/Domain/Sources/User/Error/UserError.swift create mode 100644 Projects/Domain/Sources/User/Model/Gender.swift create mode 100644 Projects/Domain/Sources/User/Model/Interest.swift create mode 100644 Projects/Domain/Sources/User/Model/OnboardingDraft.swift create mode 100644 Projects/Domain/Sources/User/Model/UserProfile.swift diff --git a/Projects/Domain/Sources/User/Client/UserClient.swift b/Projects/Domain/Sources/User/Client/UserClient.swift new file mode 100644 index 0000000..b063ff2 --- /dev/null +++ b/Projects/Domain/Sources/User/Client/UserClient.swift @@ -0,0 +1,18 @@ +import Foundation +import ThirdParty + +@DependencyClient +public struct UserClient: Sendable { + public var completeOnboarding: @Sendable (OnboardingDraft) async throws -> AuthSession +} + +extension UserClient: TestDependencyKey { + public static let testValue = UserClient() +} + +public extension DependencyValues { + var userClient: UserClient { + get { self[UserClient.self] } + set { self[UserClient.self] = newValue } + } +} diff --git a/Projects/Domain/Sources/User/Error/UserError.swift b/Projects/Domain/Sources/User/Error/UserError.swift new file mode 100644 index 0000000..354d473 --- /dev/null +++ b/Projects/Domain/Sources/User/Error/UserError.swift @@ -0,0 +1,10 @@ +import Foundation + +public enum UserError: Error, Equatable, Sendable { + case network + case unauthorized + case validation(message: String) + case updateFailed + case storage(message: String) + case unknown(message: String) +} diff --git a/Projects/Domain/Sources/User/Model/Gender.swift b/Projects/Domain/Sources/User/Model/Gender.swift new file mode 100644 index 0000000..32288ec --- /dev/null +++ b/Projects/Domain/Sources/User/Model/Gender.swift @@ -0,0 +1,7 @@ +import Foundation + +public enum Gender: String, Equatable, Hashable, Sendable, Codable { + case male + case female + case other +} diff --git a/Projects/Domain/Sources/User/Model/Interest.swift b/Projects/Domain/Sources/User/Model/Interest.swift new file mode 100644 index 0000000..cd9bc3d --- /dev/null +++ b/Projects/Domain/Sources/User/Model/Interest.swift @@ -0,0 +1,11 @@ +import Foundation + +public struct Interest: Equatable, Hashable, Sendable, Codable { + public var id: String + public var name: String + + public init(id: String, name: String) { + self.id = id + self.name = name + } +} diff --git a/Projects/Domain/Sources/User/Model/OnboardingDraft.swift b/Projects/Domain/Sources/User/Model/OnboardingDraft.swift new file mode 100644 index 0000000..064a847 --- /dev/null +++ b/Projects/Domain/Sources/User/Model/OnboardingDraft.swift @@ -0,0 +1,20 @@ +import Foundation + +public struct OnboardingDraft: Equatable, Sendable { + public var nickname: String + public var gender: Gender + public var birthDate: Date + public var interestIDs: [String] + + public init( + nickname: String, + gender: Gender, + birthDate: Date, + interestIDs: [String] + ) { + self.nickname = nickname + self.gender = gender + self.birthDate = birthDate + self.interestIDs = interestIDs + } +} diff --git a/Projects/Domain/Sources/User/Model/UserProfile.swift b/Projects/Domain/Sources/User/Model/UserProfile.swift new file mode 100644 index 0000000..29dbc7e --- /dev/null +++ b/Projects/Domain/Sources/User/Model/UserProfile.swift @@ -0,0 +1,20 @@ +import Foundation + +public struct UserProfile: Equatable, Sendable, Codable { + public var nickname: String + public var gender: Gender + public var birthDate: Date + public var interestIDs: [String] + + public init( + nickname: String, + gender: Gender, + birthDate: Date, + interestIDs: [String] + ) { + self.nickname = nickname + self.gender = gender + self.birthDate = birthDate + self.interestIDs = interestIDs + } +} From 303ef384a2f930f4c2307437a184e2777b46d152 Mon Sep 17 00:00:00 2001 From: "gnoes.ios" Date: Thu, 6 Aug 2026 18:59:18 +0900 Subject: [PATCH 3/4] =?UTF-8?q?test:=20User=20Domain=20=EA=B3=84=EC=95=BD?= =?UTF-8?q?=20=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Domain/Tests/User/UserClientTests.swift | 11 +++ .../Domain/Tests/User/UserModelTests.swift | 70 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 Projects/Domain/Tests/User/UserClientTests.swift create mode 100644 Projects/Domain/Tests/User/UserModelTests.swift diff --git a/Projects/Domain/Tests/User/UserClientTests.swift b/Projects/Domain/Tests/User/UserClientTests.swift new file mode 100644 index 0000000..5d58f8a --- /dev/null +++ b/Projects/Domain/Tests/User/UserClientTests.swift @@ -0,0 +1,11 @@ +import Domain +import XCTest + +final class UserClientTests: XCTestCase { + func test_UserClient_testValue는_빈_클라이언트로_생성() { + // @DependencyClient 는 testValue = UserClient() 를 기본 제공한다. + // 미구현 endpoint 호출 시 issue를 내므로, 생성 가능성만 검증한다. + _ = UserClient.testValue + XCTAssertTrue(true) + } +} diff --git a/Projects/Domain/Tests/User/UserModelTests.swift b/Projects/Domain/Tests/User/UserModelTests.swift new file mode 100644 index 0000000..353bb16 --- /dev/null +++ b/Projects/Domain/Tests/User/UserModelTests.swift @@ -0,0 +1,70 @@ +import Domain +import XCTest + +final class UserModelTests: XCTestCase { + func test_성별_rawValue와_동등성() { + XCTAssertEqual(Gender.male.rawValue, "male") + XCTAssertEqual(Gender.female.rawValue, "female") + XCTAssertEqual(Gender.other.rawValue, "other") + XCTAssertEqual(Gender.male, Gender.male) + } + + func test_관심사_동등성_비교() { + let a = Interest(id: "sports", name: "운동") + let b = Interest(id: "sports", name: "운동") + XCTAssertEqual(a, b) + } + + func test_관심사_codable_왕복() throws { + let original = Interest(id: "music", name: "음악") + let data = try JSONEncoder().encode(original) + let decoded = try JSONDecoder().decode(Interest.self, from: data) + XCTAssertEqual(decoded, original) + } + + func test_프로필_동등성_비교() { + let birthDate = Date(timeIntervalSince1970: 0) + let a = UserProfile( + nickname: "모지", + gender: .female, + birthDate: birthDate, + interestIDs: ["sports", "music"] + ) + let b = UserProfile( + nickname: "모지", + gender: .female, + birthDate: birthDate, + interestIDs: ["sports", "music"] + ) + XCTAssertEqual(a, b) + } + + func test_프로필_codable_왕복() throws { + let original = UserProfile( + nickname: "모지", + gender: .other, + birthDate: Date(timeIntervalSince1970: 1_000), + interestIDs: ["travel"] + ) + let data = try JSONEncoder().encode(original) + let decoded = try JSONDecoder().decode(UserProfile.self, from: data) + XCTAssertEqual(decoded, original) + } + + func test_온보딩초안_동등성_비교() { + let birthDate = Date(timeIntervalSince1970: 2_000) + let a = OnboardingDraft( + nickname: "모지", + gender: .male, + birthDate: birthDate, + interestIDs: ["food"] + ) + let b = OnboardingDraft( + nickname: "모지", + gender: .male, + birthDate: birthDate, + interestIDs: ["food"] + ) + XCTAssertEqual(a, b) + } +} From 7d36da080ce5e8a11ac9ba6f60679a5de472fa64 Mon Sep 17 00:00:00 2001 From: "gnoes.ios" Date: Thu, 6 Aug 2026 18:59:18 +0900 Subject: [PATCH 4/4] =?UTF-8?q?docs:=20Domain=20README=20User=20=ED=8F=AC?= =?UTF-8?q?=ED=8A=B8=20=EB=AC=B8=EC=84=9C=20=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Projects/Domain/README.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Projects/Domain/README.md b/Projects/Domain/README.md index 2123bb9..47d95f2 100644 --- a/Projects/Domain/README.md +++ b/Projects/Domain/README.md @@ -5,6 +5,7 @@ ## 현재 상태 - Auth 포트 추가 (`AuthSession`, `AuthError`, `AuthProvider`, `AuthClient`) +- User 포트 추가 (`UserProfile`, `OnboardingDraft`, `Gender`, `Interest`, `UserError`, `UserClient`) ## 이후 패턴 - `Domain//{Model,Client,Error}` @@ -20,14 +21,22 @@ - UseCase 층 없음 ## 주요 진입점 -- `Sources/Auth/AuthClient.swift` -- `Sources/Auth/AuthSession.swift` -- `Sources/Auth/AuthError.swift` -- `Sources/Auth/AuthProvider.swift` +- `Sources/Auth/Client/AuthClient.swift` +- `Sources/Auth/Model/AuthSession.swift` +- `Sources/Auth/Model/AuthProvider.swift` +- `Sources/Auth/Error/AuthError.swift` +- `Sources/User/Client/UserClient.swift` +- `Sources/User/Model/UserProfile.swift` +- `Sources/User/Model/OnboardingDraft.swift` +- `Sources/User/Model/Gender.swift` +- `Sources/User/Model/Interest.swift` +- `Sources/User/Error/UserError.swift` ## 테스트 포인트 - 세션 동등성/Codable 왕복 - `AuthClient.testValue` 기본 unimplemented 동작 (`@DependencyClient`) +- User model 동등성/Codable 왕복 +- `UserClient.testValue` 기본 unimplemented 동작 (`@DependencyClient`) ## 관련 문서 - [ARCHITECTURE.md](../../docs/ARCHITECTURE.md)