From ac8a022333eec2d841c2960cf46dc33bf91a25db Mon Sep 17 00:00:00 2001 From: JunYoung Date: Sun, 26 Apr 2026 15:57:36 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat/#327:=20feature=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20example=20=ED=83=80?= =?UTF-8?q?=EA=B9=83=20=EC=B6=94=EA=B0=80=20=ED=9B=84=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MLS/MLS.xcodeproj/project.pbxproj | 161 ++++++++++++++++++ MLS/MLS.xcworkspace/contents.xcworkspacedata | 3 + MLS/MLSRecommendationFeature/.gitignore | 8 + MLS/MLSRecommendationFeature/Package.swift | 80 +++++++++ .../RecommendationMainFactoryImpl.swift | 11 ++ .../RecommendationMainViewController.swift | 27 +++ .../Factories/RecommendationMainFactory.swift | 5 + .../MLSRecommendationFeatureTesting.swift | 2 + .../MLSRecommendationFeatureTests.swift | 6 + .../AppDelegate.swift | 24 +++ .../AccentColor.colorset/Contents.json | 11 ++ .../AppIcon.appiconset/Contents.json | 35 ++++ .../Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 25 +++ .../Base.lproj/Main.storyboard | 24 +++ .../Info.plist | 25 +++ .../SceneDelegate.swift | 34 ++++ .../ViewController.swift | 19 +++ 18 files changed, 506 insertions(+) create mode 100644 MLS/MLSRecommendationFeature/.gitignore create mode 100644 MLS/MLSRecommendationFeature/Package.swift create mode 100644 MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainFactoryImpl.swift create mode 100644 MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift create mode 100644 MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeatureInterface/Factories/RecommendationMainFactory.swift create mode 100644 MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeatureTesting/MLSRecommendationFeatureTesting.swift create mode 100644 MLS/MLSRecommendationFeature/Tests/MLSRecommendationFeatureTests/MLSRecommendationFeatureTests.swift create mode 100644 MLS/MLSRecommendationFeatureExample/AppDelegate.swift create mode 100644 MLS/MLSRecommendationFeatureExample/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 MLS/MLSRecommendationFeatureExample/Assets.xcassets/Contents.json create mode 100644 MLS/MLSRecommendationFeatureExample/Base.lproj/LaunchScreen.storyboard create mode 100644 MLS/MLSRecommendationFeatureExample/Base.lproj/Main.storyboard create mode 100644 MLS/MLSRecommendationFeatureExample/Info.plist create mode 100644 MLS/MLSRecommendationFeatureExample/SceneDelegate.swift create mode 100644 MLS/MLSRecommendationFeatureExample/ViewController.swift diff --git a/MLS/MLS.xcodeproj/project.pbxproj b/MLS/MLS.xcodeproj/project.pbxproj index 2de28dda..c91608bd 100644 --- a/MLS/MLS.xcodeproj/project.pbxproj +++ b/MLS/MLS.xcodeproj/project.pbxproj @@ -33,6 +33,9 @@ 08F7AA012F86745C00EF5C06 /* MLSAuthFeature in Frameworks */ = {isa = PBXBuildFile; productRef = 08F7AA022F86745C00EF5C06 /* MLSAuthFeature */; }; 08F7AA032F86745C00EF5C06 /* MLSAuthFeatureInterface in Frameworks */ = {isa = PBXBuildFile; productRef = 08F7AA042F86745C00EF5C06 /* MLSAuthFeatureInterface */; }; 08F7AA052F86745C00EF5C06 /* MLSAuthFeatureTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 08F7AA062F86745C00EF5C06 /* MLSAuthFeatureTesting */; }; + 08F7DC802F9DEA8100EF5C06 /* MLSRecommendationFeature in Frameworks */ = {isa = PBXBuildFile; productRef = 08F7DC812F9DEA8100EF5C06 /* MLSRecommendationFeature */; }; + 08F7DC822F9DEA8100EF5C06 /* MLSRecommendationFeatureInterface in Frameworks */ = {isa = PBXBuildFile; productRef = 08F7DC832F9DEA8100EF5C06 /* MLSRecommendationFeatureInterface */; }; + 08F7DC842F9DEA8100EF5C06 /* MLSCore in Frameworks */ = {isa = PBXBuildFile; productRef = 08F7DC852F9DEA8100EF5C06 /* MLSCore */; }; 770ADB1F2E433EDA00270506 /* RxKeyboard in Frameworks */ = {isa = PBXBuildFile; productRef = 770ADB1E2E433EDA00270506 /* RxKeyboard */; }; 772199F22E0E7EC800A7B58C /* AuthFeatureInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 772199F12E0E7EC800A7B58C /* AuthFeatureInterface.framework */; }; 772199F32E0E7EC800A7B58C /* AuthFeatureInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 772199F12E0E7EC800A7B58C /* AuthFeatureInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -139,6 +142,7 @@ 08DA58A62E1E5BE3009097A6 /* DictionaryFeature.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DictionaryFeature.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 08DA58A92E1E5BEB009097A6 /* DictionaryFeatureInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DictionaryFeatureInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 08F7A9232F86745C00EF5C06 /* MLSAuthFeatureExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MLSAuthFeatureExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 08F7DC612F9DEA8000EF5C06 /* MLSRecommendationFeatureExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MLSRecommendationFeatureExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 772199F12E0E7EC800A7B58C /* AuthFeatureInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AuthFeatureInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7721A5032E0EE7AE00A7B58C /* BaseFeature.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = BaseFeature.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 77660AD12DD0D361007A4EF3 /* KakaoConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = KakaoConfig.xcconfig; sourceTree = ""; }; @@ -170,6 +174,13 @@ ); target = 08F7A9222F86745C00EF5C06 /* MLSAuthFeatureExample */; }; + 08F7DC722F9DEA8100EF5C06 /* Exceptions for "MLSRecommendationFeatureExample" folder in "MLSRecommendationFeatureExample" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 08F7DC602F9DEA8000EF5C06 /* MLSRecommendationFeatureExample */; + }; 77FA688B2F72C7380064B6EB /* Exceptions for "MLSDesignSystemExample" folder in "MLSDesignSystemExample" target */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( @@ -196,6 +207,14 @@ path = MLSAuthFeatureExample; sourceTree = ""; }; + 08F7DC622F9DEA8000EF5C06 /* MLSRecommendationFeatureExample */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 08F7DC722F9DEA8100EF5C06 /* Exceptions for "MLSRecommendationFeatureExample" folder in "MLSRecommendationFeatureExample" target */, + ); + path = MLSRecommendationFeatureExample; + sourceTree = ""; + }; 77BEB0412DBA84B0002FFCFC /* MLSTests */ = { isa = PBXFileSystemSynchronizedRootGroup; path = MLSTests; @@ -257,6 +276,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 08F7DC5E2F9DEA8000EF5C06 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 08F7DC802F9DEA8100EF5C06 /* MLSRecommendationFeature in Frameworks */, + 08F7DC822F9DEA8100EF5C06 /* MLSRecommendationFeatureInterface in Frameworks */, + 08F7DC842F9DEA8100EF5C06 /* MLSCore in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 77BEB03D2DBA84B0002FFCFC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -360,6 +389,7 @@ 77BEB0412DBA84B0002FFCFC /* MLSTests */, 77FA687B2F72C7360064B6EB /* MLSDesignSystemExample */, 08F7A9242F86745C00EF5C06 /* MLSAuthFeatureExample */, + 08F7DC622F9DEA8000EF5C06 /* MLSRecommendationFeatureExample */, 084A25312DB93A5400C395C0 /* Frameworks */, 087D3EE92DA7972C002F924D /* Products */, ); @@ -372,6 +402,7 @@ 77BEB0402DBA84B0002FFCFC /* MLSTests.xctest */, 77FA687A2F72C7360064B6EB /* MLSDesignSystemExample.app */, 08F7A9232F86745C00EF5C06 /* MLSAuthFeatureExample.app */, + 08F7DC612F9DEA8000EF5C06 /* MLSRecommendationFeatureExample.app */, ); name = Products; sourceTree = ""; @@ -439,6 +470,31 @@ productReference = 08F7A9232F86745C00EF5C06 /* MLSAuthFeatureExample.app */; productType = "com.apple.product-type.application"; }; + 08F7DC602F9DEA8000EF5C06 /* MLSRecommendationFeatureExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 08F7DC732F9DEA8100EF5C06 /* Build configuration list for PBXNativeTarget "MLSRecommendationFeatureExample" */; + buildPhases = ( + 08F7DC5D2F9DEA8000EF5C06 /* Sources */, + 08F7DC5E2F9DEA8000EF5C06 /* Frameworks */, + 08F7DC5F2F9DEA8000EF5C06 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 08F7DC622F9DEA8000EF5C06 /* MLSRecommendationFeatureExample */, + ); + name = MLSRecommendationFeatureExample; + packageProductDependencies = ( + 08F7DC812F9DEA8100EF5C06 /* MLSRecommendationFeature */, + 08F7DC832F9DEA8100EF5C06 /* MLSRecommendationFeatureInterface */, + 08F7DC852F9DEA8100EF5C06 /* MLSCore */, + ); + productName = MLSRecommendationFeatureExample; + productReference = 08F7DC612F9DEA8000EF5C06 /* MLSRecommendationFeatureExample.app */; + productType = "com.apple.product-type.application"; + }; 77BEB03F2DBA84B0002FFCFC /* MLSTests */ = { isa = PBXNativeTarget; buildConfigurationList = 77BEB0482DBA84B0002FFCFC /* Build configuration list for PBXNativeTarget "MLSTests" */; @@ -505,6 +561,9 @@ 08F7A9222F86745C00EF5C06 = { CreatedOnToolsVersion = 26.1.1; }; + 08F7DC602F9DEA8000EF5C06 = { + CreatedOnToolsVersion = 26.1.1; + }; 77BEB03F2DBA84B0002FFCFC = { CreatedOnToolsVersion = 16.2; TestTargetID = 087D3EE72DA7972C002F924D; @@ -567,6 +626,7 @@ 77BEB03F2DBA84B0002FFCFC /* MLSTests */, 77FA68792F72C7360064B6EB /* MLSDesignSystemExample */, 08F7A9222F86745C00EF5C06 /* MLSAuthFeatureExample */, + 08F7DC602F9DEA8000EF5C06 /* MLSRecommendationFeatureExample */, ); }; /* End PBXProject section */ @@ -589,6 +649,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 08F7DC5F2F9DEA8000EF5C06 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 77BEB03E2DBA84B0002FFCFC /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -641,6 +708,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 08F7DC5D2F9DEA8000EF5C06 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 77BEB03C2DBA84B0002FFCFC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -937,6 +1011,72 @@ }; name = Release; }; + 08F7DC742F9DEA8100EF5C06 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = MLSRecommendationFeatureExample/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 26.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.mls.MLSRecommendationFeatureExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 08F7DC752F9DEA8100EF5C06 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = MLSRecommendationFeatureExample/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 26.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.mls.MLSRecommendationFeatureExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 77BEB0462DBA84B0002FFCFC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1081,6 +1221,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 08F7DC732F9DEA8100EF5C06 /* Build configuration list for PBXNativeTarget "MLSRecommendationFeatureExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 08F7DC742F9DEA8100EF5C06 /* Debug */, + 08F7DC752F9DEA8100EF5C06 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 77BEB0482DBA84B0002FFCFC /* Build configuration list for PBXNativeTarget "MLSTests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1203,6 +1352,18 @@ isa = XCSwiftPackageProductDependency; productName = MLSAuthFeatureTesting; }; + 08F7DC812F9DEA8100EF5C06 /* MLSRecommendationFeature */ = { + isa = XCSwiftPackageProductDependency; + productName = MLSRecommendationFeature; + }; + 08F7DC832F9DEA8100EF5C06 /* MLSRecommendationFeatureInterface */ = { + isa = XCSwiftPackageProductDependency; + productName = MLSRecommendationFeatureInterface; + }; + 08F7DC852F9DEA8100EF5C06 /* MLSCore */ = { + isa = XCSwiftPackageProductDependency; + productName = MLSCore; + }; 770ADB1E2E433EDA00270506 /* RxKeyboard */ = { isa = XCSwiftPackageProductDependency; package = 770ADB1D2E433EDA00270506 /* XCRemoteSwiftPackageReference "RxKeyboard" */; diff --git a/MLS/MLS.xcworkspace/contents.xcworkspacedata b/MLS/MLS.xcworkspace/contents.xcworkspacedata index 99fde6a0..f7ebda0c 100644 --- a/MLS/MLS.xcworkspace/contents.xcworkspacedata +++ b/MLS/MLS.xcworkspace/contents.xcworkspacedata @@ -44,6 +44,9 @@ + + diff --git a/MLS/MLSRecommendationFeature/.gitignore b/MLS/MLSRecommendationFeature/.gitignore new file mode 100644 index 00000000..0023a534 --- /dev/null +++ b/MLS/MLSRecommendationFeature/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/MLS/MLSRecommendationFeature/Package.swift b/MLS/MLSRecommendationFeature/Package.swift new file mode 100644 index 00000000..0878963e --- /dev/null +++ b/MLS/MLSRecommendationFeature/Package.swift @@ -0,0 +1,80 @@ +// swift-tools-version: 6.2 +import PackageDescription + +let package = Package( + name: "MLSRecommendationFeature", + platforms: [.iOS(.v15)], + products: [ + // Interface: Presentation 팩토리 프로토콜 + .library( + name: "MLSRecommendationFeatureInterface", + targets: ["MLSRecommendationFeatureInterface"] + ), + // Feature: Presentation + Domain + Data 구현체 + .library( + name: "MLSRecommendationFeature", + targets: ["MLSRecommendationFeature"] + ), + // Testing: 단위 테스트나 Example 앱에서 사용될 Mock 데이터를 제공하는 모듈 + .library( + name: "MLSRecommendationFeatureTesting", + targets: ["MLSRecommendationFeatureTesting"] + ) + ], + dependencies: [ + .package(path: "../MLSCore"), + .package(path: "../MLSDesignSystem"), + .package(url: "https://github.com/ReactorKit/ReactorKit.git", from: "3.2.0"), + .package(url: "https://github.com/ReactiveX/RxSwift.git", from: "6.7.0"), + .package(url: "https://github.com/RxSwiftCommunity/RxKeyboard.git", from: "2.0.0"), + .package(url: "https://github.com/SnapKit/SnapKit.git", from: "5.7.1") + ], + targets: [ + // Interface 모듈 (Presentation 팩토리 프로토콜) + .target( + name: "MLSRecommendationFeatureInterface", + dependencies: [ + .product(name: "MLSCore", package: "MLSCore"), + .product(name: "MLSDesignSystem", package: "MLSDesignSystem"), + .product(name: "RxSwift", package: "RxSwift") + ], + swiftSettings: [.swiftLanguageMode(.v5)] + ), + // Feature 모듈 (Presentation + Domain + Data 구현체) + .target( + name: "MLSRecommendationFeature", + dependencies: [ + "MLSRecommendationFeatureInterface", + .product(name: "MLSCore", package: "MLSCore"), + .product(name: "MLSDesignSystem", package: "MLSDesignSystem"), + .product(name: "ReactorKit", package: "ReactorKit"), + .product(name: "RxSwift", package: "RxSwift"), + .product(name: "RxCocoa", package: "RxSwift"), + .product(name: "RxRelay", package: "RxSwift"), + .product(name: "RxKeyboard", package: "RxKeyboard"), + .product(name: "SnapKit", package: "SnapKit") + ], + swiftSettings: [.swiftLanguageMode(.v5)] + ), + // Testing 모듈 (Mock 객체) + .target( + name: "MLSRecommendationFeatureTesting", + dependencies: [ + "MLSRecommendationFeatureInterface", + .product(name: "RxSwift", package: "RxSwift") + ], + swiftSettings: [.swiftLanguageMode(.v5)] + ), + // Tests 모듈 + .testTarget( + name: "MLSRecommendationFeatureTests", + dependencies: [ + "MLSRecommendationFeature", + "MLSRecommendationFeatureInterface", + "MLSRecommendationFeatureTesting", + .product(name: "RxBlocking", package: "RxSwift") + ], + swiftSettings: [.swiftLanguageMode(.v5)] + ) + ] +) diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainFactoryImpl.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainFactoryImpl.swift new file mode 100644 index 00000000..65ee1aef --- /dev/null +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainFactoryImpl.swift @@ -0,0 +1,11 @@ +import MLSRecommendationFeatureInterface +import MLSCore + +public struct RecommendationMainFactoryImpl: RecommendationMainFactory { + + public init() {} + + public func make() -> BaseViewController { + return RecommendationMainViewController() + } +} diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift new file mode 100644 index 00000000..91ef495e --- /dev/null +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift @@ -0,0 +1,27 @@ +import UIKit + +import MLSCore + +public final class RecommendationMainViewController: BaseViewController { + + // MARK: - Init + + public override init() { + super.init() + } + + // MARK: - Life Cycle + + public override func viewDidLoad() { + super.viewDidLoad() + setupUI() + } +} + +// MARK: - SetUp + +private extension RecommendationMainViewController { + func setupUI() { + view.backgroundColor = .red + } +} diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeatureInterface/Factories/RecommendationMainFactory.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeatureInterface/Factories/RecommendationMainFactory.swift new file mode 100644 index 00000000..7272689b --- /dev/null +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeatureInterface/Factories/RecommendationMainFactory.swift @@ -0,0 +1,5 @@ +import MLSCore + +public protocol RecommendationMainFactory { + func make() -> BaseViewController +} diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeatureTesting/MLSRecommendationFeatureTesting.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeatureTesting/MLSRecommendationFeatureTesting.swift new file mode 100644 index 00000000..0d4fa4b7 --- /dev/null +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeatureTesting/MLSRecommendationFeatureTesting.swift @@ -0,0 +1,2 @@ +// MLSRecommendationFeatureTesting +// 단위 테스트 및 Example 앱에서 사용할 Mock 객체를 제공합니다. diff --git a/MLS/MLSRecommendationFeature/Tests/MLSRecommendationFeatureTests/MLSRecommendationFeatureTests.swift b/MLS/MLSRecommendationFeature/Tests/MLSRecommendationFeatureTests/MLSRecommendationFeatureTests.swift new file mode 100644 index 00000000..5f99b6e9 --- /dev/null +++ b/MLS/MLSRecommendationFeature/Tests/MLSRecommendationFeatureTests/MLSRecommendationFeatureTests.swift @@ -0,0 +1,6 @@ +import Testing +@testable import MLSRecommendationFeature + +@Test func example() async throws { + // Write your test here and use APIs like `#expect(...)` to check expected conditions. +} diff --git a/MLS/MLSRecommendationFeatureExample/AppDelegate.swift b/MLS/MLSRecommendationFeatureExample/AppDelegate.swift new file mode 100644 index 00000000..fb980808 --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/AppDelegate.swift @@ -0,0 +1,24 @@ +import UIKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } +} + diff --git a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AccentColor.colorset/Contents.json b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..23058801 --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/Contents.json b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSRecommendationFeatureExample/Base.lproj/LaunchScreen.storyboard b/MLS/MLSRecommendationFeatureExample/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..865e9329 --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MLS/MLSRecommendationFeatureExample/Base.lproj/Main.storyboard b/MLS/MLSRecommendationFeatureExample/Base.lproj/Main.storyboard new file mode 100644 index 00000000..25a76385 --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MLS/MLSRecommendationFeatureExample/Info.plist b/MLS/MLSRecommendationFeatureExample/Info.plist new file mode 100644 index 00000000..dd3c9afd --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/Info.plist @@ -0,0 +1,25 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + + diff --git a/MLS/MLSRecommendationFeatureExample/SceneDelegate.swift b/MLS/MLSRecommendationFeatureExample/SceneDelegate.swift new file mode 100644 index 00000000..64e1cd19 --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/SceneDelegate.swift @@ -0,0 +1,34 @@ +import UIKit + +import MLSCore +import MLSRecommendationFeature +import MLSRecommendationFeatureInterface + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = (scene as? UIWindowScene) else { return } + + registerDependencies() + + let window = UIWindow(windowScene: windowScene) + self.window = window + + let factory = DIContainer.resolve(type: RecommendationMainFactory.self) + let recommendationVC = factory.make() + let nav = UINavigationController(rootViewController: recommendationVC) + nav.navigationBar.isHidden = true + window.rootViewController = nav + window.makeKeyAndVisible() + } + + // MARK: - Private + + private func registerDependencies() { + DIContainer.register(type: RecommendationMainFactory.self) { + RecommendationMainFactoryImpl() + } + } +} diff --git a/MLS/MLSRecommendationFeatureExample/ViewController.swift b/MLS/MLSRecommendationFeatureExample/ViewController.swift new file mode 100644 index 00000000..580fa59b --- /dev/null +++ b/MLS/MLSRecommendationFeatureExample/ViewController.swift @@ -0,0 +1,19 @@ +// +// ViewController.swift +// MLSRecommendationFeatureExample +// +// Created by SeoJunYoung on 4/26/26. +// + +import UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + + +} + From 85724aacd38cae56623dd1cecec0e72184443452 Mon Sep 17 00:00:00 2001 From: JunYoung Date: Sun, 26 Apr 2026 17:40:07 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat/#327:=20profileView=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RecommendationMainReactor.swift | 35 ++++++++ .../RecommendationMainViewController.swift | 58 +++++++++--- .../Views/RecommendationMainView.swift | 56 ++++++++++++ .../Views/RecommendationProfileView.swift | 89 +++++++++++++++++++ .../AppDelegate.swift | 4 +- 5 files changed, 228 insertions(+), 14 deletions(-) create mode 100644 MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainReactor.swift create mode 100644 MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift create mode 100644 MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainReactor.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainReactor.swift new file mode 100644 index 00000000..895f5cca --- /dev/null +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainReactor.swift @@ -0,0 +1,35 @@ +import ReactorKit +import RxSwift +import RxCocoa + +final class RecommendationMainReactor: Reactor { + + // MARK: - Reactor + enum Action { } + + enum Mutation { } + + struct State { } + + // MARK: - properties + var initialState: State + var disposeBag = DisposeBag() + + // MARK: - init + init() { + self.initialState = State() + } + + // MARK: - Reactor Methods + func mutate(action: Action) -> Observable { + switch action { } + } + + func reduce(state: State, mutation: Mutation) -> State { + var newState = state + + switch mutation { } + + return newState + } +} diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift index 91ef495e..57bf999d 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift @@ -2,26 +2,58 @@ import UIKit import MLSCore -public final class RecommendationMainViewController: BaseViewController { +import SnapKit +import RxCocoa +import RxSwift +import ReactorKit + +final class RecommendationMainViewController: BaseViewController, View { + + typealias Reactor = RecommendationMainReactor + + // MARK: - Properties + var disposeBag = DisposeBag() + + private var mainView = RecommendationMainView() +} - // MARK: - Init +// MARK: - Life Cycle +extension RecommendationMainViewController { + override func viewDidLoad() { + super.viewDidLoad() + + addViews() + setupConstraints() + configureUI() + } +} - public override init() { - super.init() +// MARK: - SetUp +private extension RecommendationMainViewController { + func addViews() { + view.addSubview(mainView) } - // MARK: - Life Cycle + func setupConstraints() { + mainView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } - public override func viewDidLoad() { - super.viewDidLoad() - setupUI() + func configureUI() { + mainView.profileView.configure(imageURL: nil, nickName: "익명의 판타지", job: "도적", level: 275) } } -// MARK: - SetUp - -private extension RecommendationMainViewController { - func setupUI() { - view.backgroundColor = .red +extension RecommendationMainViewController { + func bind(reactor: Reactor) { + bindUserActions(reactor: reactor) + bindViewState(reactor: reactor) + } + + func bindUserActions(reactor: Reactor) { + } + + func bindViewState(reactor: Reactor) { } } diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift new file mode 100644 index 00000000..512fec4c --- /dev/null +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift @@ -0,0 +1,56 @@ +import UIKit + +import MLSDesignSystem + +import SnapKit + +internal final class RecommendationMainView: UIView { + // MARK: - Type + private enum Constant { + } + + // MARK: - Properties + internal let header = Header(style: .main, title: "추천") + internal let profileView = RecommendationProfileView() + + internal let profileImageView: UIImageView = { + let view = UIImageView() + return view + }() + + // MARK: - init + init() { + super.init(frame: .zero) + + addViews() + setupConstraints() + configureUI() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension RecommendationMainView { + func addViews() { + addSubview(header) + addSubview(profileView) + } + + func setupConstraints() { + header.snp.makeConstraints { make in + make.top.horizontalEdges.equalTo(safeAreaLayoutGuide) + } + + profileView.snp.makeConstraints { make in + make.top.equalTo(header.snp.bottom).offset(21) + make.horizontalEdges.equalToSuperview().inset(40) + } + } + + func configureUI() {} +} + diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift new file mode 100644 index 00000000..f6306a12 --- /dev/null +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift @@ -0,0 +1,89 @@ +import UIKit + +import MLSCore +import MLSDesignSystem + +import SnapKit + +internal final class RecommendationProfileView: UIStackView { + // MARK: - Type + private enum Constant { + static let profileImageViewSize: CGFloat = 100 + static let outerStackViewSpacing: CGFloat = 38 + static let verticalStackViewSpacing: CGFloat = 18 + static let horizontalStackViewSpacing: CGFloat = 12 + } + + // MARK: - Properties + internal let profileImageView: UIImageView = .init() + internal let nicknameLabel: UILabel = .init() + internal let jobLabel: UILabel = .init() + internal let levelBadge = Badge(style: .element("")) + internal let editButton: UIButton = { + let button = UIButton() + button.setAttributedTitle(.makeStyledUnderlinedString(font: .korFont(style: .regular, size: 14), text: "수정하기"), for: .normal) + return button + }() + + // MARK: - StackView + private let verticalStackView: UIStackView = .init() + private let horizontalStackView: UIStackView = .init() + + // MARK: - init + internal init() { + super.init(frame: .zero) + + addViews() + setupConstraints() + configureUI() + } + + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension RecommendationProfileView { + func addViews() { + horizontalStackView.addArrangedSubview(jobLabel) + horizontalStackView.addArrangedSubview(levelBadge) + horizontalStackView.addArrangedSubview(editButton) + + verticalStackView.addArrangedSubview(nicknameLabel) + verticalStackView.addArrangedSubview(horizontalStackView) + + self.addArrangedSubview(profileImageView) + self.addArrangedSubview(verticalStackView) + } + + func setupConstraints() { + profileImageView.snp.makeConstraints { make in + make.size.equalTo(Constant.profileImageViewSize) + } + } + + func configureUI() { + self.distribution = .fill + self.alignment = .center + self.spacing = Constant.outerStackViewSpacing + + verticalStackView.axis = .vertical + verticalStackView.alignment = .leading + verticalStackView.spacing = Constant.verticalStackViewSpacing + + horizontalStackView.alignment = .center + horizontalStackView.spacing = Constant.horizontalStackViewSpacing + } +} + +internal extension RecommendationProfileView { + func configure(imageURL: String?, nickName: String, job: String, level: Int) { + ImageLoader.shared.loadImage(stringURL: imageURL) { [weak self] image in + self?.profileImageView.image = image + } + nicknameLabel.attributedText = .makeStyledString(font: .korFont(style: .bold, size: 18), text: nickName) + jobLabel.attributedText = .makeStyledString(font: .korFont(style: .regular, size: 16), text: job) + levelBadge.update(style: .element("Lv.\(level)")) + } +} diff --git a/MLS/MLSRecommendationFeatureExample/AppDelegate.swift b/MLS/MLSRecommendationFeatureExample/AppDelegate.swift index fb980808..59111c9f 100644 --- a/MLS/MLSRecommendationFeatureExample/AppDelegate.swift +++ b/MLS/MLSRecommendationFeatureExample/AppDelegate.swift @@ -1,9 +1,11 @@ import UIKit +import MLSDesignSystem + @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. + FontManager.registerFonts() return true } From 5175fcc163f1f2289add36be91904f0dfea0b4a0 Mon Sep 17 00:00:00 2001 From: JunYoung Date: Wed, 29 Apr 2026 22:14:16 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat/#327:=20=EB=A9=94=EC=9D=B8=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20UI=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MLSDesignSystem/Components/CardList.swift | 2 +- .../RecommendationMainViewController.swift | 20 ++++++ .../Views/CardListCell.swift | 39 +++++++++++ .../Views/RecommendationMainView.swift | 65 ++++++++++++++++++- .../Views/RecommendationProfileView.swift | 1 + 5 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/CardListCell.swift diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CardList.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CardList.swift index f461d117..16101abf 100644 --- a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CardList.swift +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CardList.swift @@ -263,7 +263,7 @@ public extension CardList { rankTag.isHidden = true badge.update(style: type) case .recommended(let rank): - iconButton.isHidden = true + iconButton.isHidden = false dropInfoStack.isHidden = true subTextLabel.isHidden = true badge.isHidden = true diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift index 57bf999d..5ce88462 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift @@ -1,6 +1,7 @@ import UIKit import MLSCore +import MLSDesignSystem import SnapKit import RxCocoa @@ -42,6 +43,9 @@ private extension RecommendationMainViewController { func configureUI() { mainView.profileView.configure(imageURL: nil, nickName: "익명의 판타지", job: "도적", level: 275) + mainView.collectionView.delegate = self + mainView.collectionView.dataSource = self + mainView.collectionView.register(CardListCell.self, forCellWithReuseIdentifier: CardListCell.identifier) } } @@ -57,3 +61,19 @@ extension RecommendationMainViewController { func bindViewState(reactor: Reactor) { } } + +extension RecommendationMainViewController: UICollectionViewDelegate, UICollectionViewDataSource { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return 5 + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CardListCell.identifier, for: indexPath) as? CardListCell else { + return UICollectionViewCell() + } + cell.cardView.setMainText(text: "최대 줄은 두 줄입니다.\n넘어갈시 말줄임 처리 합니다.") + cell.cardView.setImage(image: UIImage(systemName: "person")!, backgroundColor: .green) + cell.cardView.setType(type: .recommended(rank: 1)) + return cell + } +} diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/CardListCell.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/CardListCell.swift new file mode 100644 index 00000000..a58b55d3 --- /dev/null +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/CardListCell.swift @@ -0,0 +1,39 @@ +import UIKit + +import MLSDesignSystem + +import SnapKit + +final class CardListCell: UICollectionViewCell { + + // MARK: - Properties + let cardView = CardList() + + // MARK: - init + override init(frame: CGRect) { + super.init(frame: frame) + + addViews() + setupContstraints() + configureUI() + } + + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension CardListCell { + func addViews() { + contentView.addSubview(cardView) + } + + func setupContstraints() { + cardView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + + func configureUI() { } +} diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift index 512fec4c..04368b4f 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift @@ -1,5 +1,6 @@ import UIKit +import MLSCore import MLSDesignSystem import SnapKit @@ -7,16 +8,57 @@ import SnapKit internal final class RecommendationMainView: UIView { // MARK: - Type private enum Constant { + static let cellHeight: CGFloat = 104 + static let cellSpacing: CGFloat = 8 } // MARK: - Properties internal let header = Header(style: .main, title: "추천") internal let profileView = RecommendationProfileView() - internal let profileImageView: UIImageView = { - let view = UIImageView() + internal let grayBackgroundView: UIView = { + let view = UIView() + view.backgroundColor = .neutral100 return view }() + + internal let collectionView: UICollectionView = { + let layout = CompositionalLayoutBuilder() + .section { + $0.item(width: .fractionalWidth(1), height: .fractionalHeight(1)) + .group(.vertical, width: .fractionalWidth(1), height: .absolute(Constant.cellHeight)) + .buildSection() + .interGroupSpacing(Constant.cellSpacing) + } + .build() + let view = UICollectionView(frame: .zero, collectionViewLayout: layout) + view.backgroundColor = .clear + view.showsVerticalScrollIndicator = false + return view + }() + + internal let informationButton: UIButton = { + let button = UIButton() + let label = UILabel() + label.font = .korFont(style: .regular, size: 16) + label.text = "추천" + let image = UIImageView(image: DesignSystemAsset.image(named: "errorBlack").withTintColor(.primary700)) + + button.addSubview(label) + button.addSubview(image) + + image.snp.makeConstraints { make in + make.size.equalTo(24) + make.verticalEdges.trailing.equalToSuperview() + } + + label.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalToSuperview() + make.trailing.equalTo(image.snp.leading).offset(-3) + } + return button + }() // MARK: - init init() { @@ -38,6 +80,9 @@ private extension RecommendationMainView { func addViews() { addSubview(header) addSubview(profileView) + addSubview(grayBackgroundView) + grayBackgroundView.addSubview(informationButton) + grayBackgroundView.addSubview(collectionView) } func setupConstraints() { @@ -49,6 +94,22 @@ private extension RecommendationMainView { make.top.equalTo(header.snp.bottom).offset(21) make.horizontalEdges.equalToSuperview().inset(40) } + + grayBackgroundView.snp.makeConstraints { make in + make.top.equalTo(profileView.snp.bottom).offset(30) + make.horizontalEdges.bottom.equalToSuperview() + } + + informationButton.snp.makeConstraints { make in + make.top.equalToSuperview().inset(14) + make.trailing.equalToSuperview().inset(16) + } + + collectionView.snp.makeConstraints { make in + make.top.equalTo(informationButton.snp.bottom).offset(14) + make.horizontalEdges.equalToSuperview().inset(16) + make.bottom.equalToSuperview() + } } func configureUI() {} diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift index f6306a12..6842ecfa 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift @@ -64,6 +64,7 @@ private extension RecommendationProfileView { } func configureUI() { + profileImageView.backgroundColor = .red self.distribution = .fill self.alignment = .center self.spacing = Constant.outerStackViewSpacing From a2f337f45ac52e7d6249ae0c0532c6c0452f1d54 Mon Sep 17 00:00:00 2001 From: JunYoung Date: Wed, 29 Apr 2026 22:17:16 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat/#327:=20=EC=83=81=EC=88=98=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EB=B6=88=ED=95=84=EC=9A=94=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C,=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/CardListCell.swift | 13 ++- .../Views/RecommendationMainView.swift | 80 ++++++++++--------- .../Views/RecommendationProfileView.swift | 29 +++---- 3 files changed, 64 insertions(+), 58 deletions(-) diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/CardListCell.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/CardListCell.swift index a58b55d3..f3364133 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/CardListCell.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/CardListCell.swift @@ -5,19 +5,18 @@ import MLSDesignSystem import SnapKit final class CardListCell: UICollectionViewCell { - + // MARK: - Properties let cardView = CardList() // MARK: - init override init(frame: CGRect) { super.init(frame: frame) - + addViews() - setupContstraints() - configureUI() + setupConstraints() } - + required init?(coder: NSCoder) { fatalError("\(#file), \(#function) Error") } @@ -29,11 +28,9 @@ private extension CardListCell { contentView.addSubview(cardView) } - func setupContstraints() { + func setupConstraints() { cardView.snp.makeConstraints { make in make.edges.equalToSuperview() } } - - func configureUI() { } } diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift index 04368b4f..31dea5e0 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationMainView.swift @@ -8,6 +8,15 @@ import SnapKit internal final class RecommendationMainView: UIView { // MARK: - Type private enum Constant { + static let profileTopOffset: CGFloat = 21 + static let profileHorizontalInset: CGFloat = 40 + static let grayViewTopOffset: CGFloat = 30 + static let informationButtonTopInset: CGFloat = 14 + static let informationButtonTrailingInset: CGFloat = 16 + static let informationIconSize: CGFloat = 24 + static let informationLabelIconSpacing: CGFloat = 3 + static let collectionViewTopOffset: CGFloat = 14 + static let collectionViewHorizontalInset: CGFloat = 16 static let cellHeight: CGFloat = 104 static let cellSpacing: CGFloat = 8 } @@ -15,13 +24,13 @@ internal final class RecommendationMainView: UIView { // MARK: - Properties internal let header = Header(style: .main, title: "추천") internal let profileView = RecommendationProfileView() - + internal let grayBackgroundView: UIView = { let view = UIView() view.backgroundColor = .neutral100 return view }() - + internal let collectionView: UICollectionView = { let layout = CompositionalLayoutBuilder() .section { @@ -36,28 +45,19 @@ internal final class RecommendationMainView: UIView { view.showsVerticalScrollIndicator = false return view }() - - internal let informationButton: UIButton = { - let button = UIButton() + + internal let informationButton = UIButton() + private let informationLabel: UILabel = { let label = UILabel() label.font = .korFont(style: .regular, size: 16) label.text = "추천" - let image = UIImageView(image: DesignSystemAsset.image(named: "errorBlack").withTintColor(.primary700)) - - button.addSubview(label) - button.addSubview(image) - - image.snp.makeConstraints { make in - make.size.equalTo(24) - make.verticalEdges.trailing.equalToSuperview() - } - - label.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.leading.equalToSuperview() - make.trailing.equalTo(image.snp.leading).offset(-3) - } - return button + return label + }() + + private let informationIconView: UIImageView = { + let view = UIImageView() + view.image = DesignSystemAsset.image(named: "errorBlack").withTintColor(.primary700) + return view }() // MARK: - init @@ -66,7 +66,6 @@ internal final class RecommendationMainView: UIView { addViews() setupConstraints() - configureUI() } @available(*, unavailable) @@ -82,6 +81,8 @@ private extension RecommendationMainView { addSubview(profileView) addSubview(grayBackgroundView) grayBackgroundView.addSubview(informationButton) + informationButton.addSubview(informationLabel) + informationButton.addSubview(informationIconView) grayBackgroundView.addSubview(collectionView) } @@ -89,29 +90,36 @@ private extension RecommendationMainView { header.snp.makeConstraints { make in make.top.horizontalEdges.equalTo(safeAreaLayoutGuide) } - + profileView.snp.makeConstraints { make in - make.top.equalTo(header.snp.bottom).offset(21) - make.horizontalEdges.equalToSuperview().inset(40) + make.top.equalTo(header.snp.bottom).offset(Constant.profileTopOffset) + make.horizontalEdges.equalToSuperview().inset(Constant.profileHorizontalInset) } - + grayBackgroundView.snp.makeConstraints { make in - make.top.equalTo(profileView.snp.bottom).offset(30) + make.top.equalTo(profileView.snp.bottom).offset(Constant.grayViewTopOffset) make.horizontalEdges.bottom.equalToSuperview() } - + informationButton.snp.makeConstraints { make in - make.top.equalToSuperview().inset(14) - make.trailing.equalToSuperview().inset(16) + make.top.equalToSuperview().inset(Constant.informationButtonTopInset) + make.trailing.equalToSuperview().inset(Constant.informationButtonTrailingInset) + } + + informationIconView.snp.makeConstraints { make in + make.size.equalTo(Constant.informationIconSize) + make.verticalEdges.trailing.equalToSuperview() } - + + informationLabel.snp.makeConstraints { make in + make.centerY.leading.equalToSuperview() + make.trailing.equalTo(informationIconView.snp.leading).offset(-Constant.informationLabelIconSpacing) + } + collectionView.snp.makeConstraints { make in - make.top.equalTo(informationButton.snp.bottom).offset(14) - make.horizontalEdges.equalToSuperview().inset(16) + make.top.equalTo(informationButton.snp.bottom).offset(Constant.collectionViewTopOffset) + make.horizontalEdges.equalToSuperview().inset(Constant.collectionViewHorizontalInset) make.bottom.equalToSuperview() } } - - func configureUI() {} } - diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift index 6842ecfa..a7a622ea 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/Views/RecommendationProfileView.swift @@ -13,7 +13,7 @@ internal final class RecommendationProfileView: UIStackView { static let verticalStackViewSpacing: CGFloat = 18 static let horizontalStackViewSpacing: CGFloat = 12 } - + // MARK: - Properties internal let profileImageView: UIImageView = .init() internal let nicknameLabel: UILabel = .init() @@ -24,20 +24,21 @@ internal final class RecommendationProfileView: UIStackView { button.setAttributedTitle(.makeStyledUnderlinedString(font: .korFont(style: .regular, size: 14), text: "수정하기"), for: .normal) return button }() - + // MARK: - StackView private let verticalStackView: UIStackView = .init() private let horizontalStackView: UIStackView = .init() - + // MARK: - init internal init() { super.init(frame: .zero) - + addViews() setupConstraints() configureUI() } - + + @available(*, unavailable) required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -49,12 +50,12 @@ private extension RecommendationProfileView { horizontalStackView.addArrangedSubview(jobLabel) horizontalStackView.addArrangedSubview(levelBadge) horizontalStackView.addArrangedSubview(editButton) - + verticalStackView.addArrangedSubview(nicknameLabel) verticalStackView.addArrangedSubview(horizontalStackView) - - self.addArrangedSubview(profileImageView) - self.addArrangedSubview(verticalStackView) + + addArrangedSubview(profileImageView) + addArrangedSubview(verticalStackView) } func setupConstraints() { @@ -65,19 +66,19 @@ private extension RecommendationProfileView { func configureUI() { profileImageView.backgroundColor = .red - self.distribution = .fill - self.alignment = .center - self.spacing = Constant.outerStackViewSpacing - + alignment = .center + spacing = Constant.outerStackViewSpacing + verticalStackView.axis = .vertical verticalStackView.alignment = .leading verticalStackView.spacing = Constant.verticalStackViewSpacing - + horizontalStackView.alignment = .center horizontalStackView.spacing = Constant.horizontalStackViewSpacing } } +// MARK: - Configure internal extension RecommendationProfileView { func configure(imageURL: String?, nickName: String, job: String, level: Int) { ImageLoader.shared.loadImage(stringURL: imageURL) { [weak self] image in From 2f19d66a945aeefe44b098c45fd85482b7958c76 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 30 Apr 2026 04:06:19 +0000 Subject: [PATCH 5/9] style/#327: Apply SwiftLint autocorrect --- .../RecommendationMainFactoryImpl.swift | 2 +- .../RecommendationMainReactor.swift | 20 +++++++++---------- .../RecommendationMainViewController.swift | 18 ++++++++--------- .../MLSRecommendationFeatureTests.swift | 2 +- .../AppDelegate.swift | 1 - .../ViewController.swift | 7 ------- 6 files changed, 21 insertions(+), 29 deletions(-) diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainFactoryImpl.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainFactoryImpl.swift index 65ee1aef..c34af806 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainFactoryImpl.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainFactoryImpl.swift @@ -1,5 +1,5 @@ -import MLSRecommendationFeatureInterface import MLSCore +import MLSRecommendationFeatureInterface public struct RecommendationMainFactoryImpl: RecommendationMainFactory { diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainReactor.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainReactor.swift index 895f5cca..4731fcd6 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainReactor.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainReactor.swift @@ -1,35 +1,35 @@ import ReactorKit -import RxSwift import RxCocoa +import RxSwift final class RecommendationMainReactor: Reactor { - + // MARK: - Reactor enum Action { } - + enum Mutation { } - + struct State { } - + // MARK: - properties var initialState: State var disposeBag = DisposeBag() - + // MARK: - init init() { self.initialState = State() } - + // MARK: - Reactor Methods func mutate(action: Action) -> Observable { switch action { } } - + func reduce(state: State, mutation: Mutation) -> State { var newState = state - + switch mutation { } - + return newState } } diff --git a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift index 5ce88462..7af69f72 100644 --- a/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift +++ b/MLS/MLSRecommendationFeature/Sources/MLSRecommendationFeature/Presentation/RecommendationMain/RecommendationMainViewController.swift @@ -3,18 +3,18 @@ import UIKit import MLSCore import MLSDesignSystem -import SnapKit +import ReactorKit import RxCocoa import RxSwift -import ReactorKit +import SnapKit final class RecommendationMainViewController: BaseViewController, View { - + typealias Reactor = RecommendationMainReactor - + // MARK: - Properties var disposeBag = DisposeBag() - + private var mainView = RecommendationMainView() } @@ -22,7 +22,7 @@ final class RecommendationMainViewController: BaseViewController, View { extension RecommendationMainViewController { override func viewDidLoad() { super.viewDidLoad() - + addViews() setupConstraints() configureUI() @@ -54,10 +54,10 @@ extension RecommendationMainViewController { bindUserActions(reactor: reactor) bindViewState(reactor: reactor) } - + func bindUserActions(reactor: Reactor) { } - + func bindViewState(reactor: Reactor) { } } @@ -66,7 +66,7 @@ extension RecommendationMainViewController: UICollectionViewDelegate, UICollecti func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 5 } - + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CardListCell.identifier, for: indexPath) as? CardListCell else { return UICollectionViewCell() diff --git a/MLS/MLSRecommendationFeature/Tests/MLSRecommendationFeatureTests/MLSRecommendationFeatureTests.swift b/MLS/MLSRecommendationFeature/Tests/MLSRecommendationFeatureTests/MLSRecommendationFeatureTests.swift index 5f99b6e9..ca06a023 100644 --- a/MLS/MLSRecommendationFeature/Tests/MLSRecommendationFeatureTests/MLSRecommendationFeatureTests.swift +++ b/MLS/MLSRecommendationFeature/Tests/MLSRecommendationFeatureTests/MLSRecommendationFeatureTests.swift @@ -1,5 +1,5 @@ -import Testing @testable import MLSRecommendationFeature +import Testing @Test func example() async throws { // Write your test here and use APIs like `#expect(...)` to check expected conditions. diff --git a/MLS/MLSRecommendationFeatureExample/AppDelegate.swift b/MLS/MLSRecommendationFeatureExample/AppDelegate.swift index 59111c9f..d179aeef 100644 --- a/MLS/MLSRecommendationFeatureExample/AppDelegate.swift +++ b/MLS/MLSRecommendationFeatureExample/AppDelegate.swift @@ -23,4 +23,3 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } } - diff --git a/MLS/MLSRecommendationFeatureExample/ViewController.swift b/MLS/MLSRecommendationFeatureExample/ViewController.swift index 580fa59b..0bcd93ff 100644 --- a/MLS/MLSRecommendationFeatureExample/ViewController.swift +++ b/MLS/MLSRecommendationFeatureExample/ViewController.swift @@ -9,11 +9,4 @@ import UIKit class ViewController: UIViewController { - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } - - } - From 99a222245dc66eadc0faf3fc2bffa6dfd13d53ac Mon Sep 17 00:00:00 2001 From: JunYoung Date: Thu, 30 Apr 2026 13:10:15 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat/#327:=20bundle=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MLS/MLS.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MLS/MLS.xcodeproj/project.pbxproj b/MLS/MLS.xcodeproj/project.pbxproj index c91608bd..2b3fb597 100644 --- a/MLS/MLS.xcodeproj/project.pbxproj +++ b/MLS/MLS.xcodeproj/project.pbxproj @@ -1065,7 +1065,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.mls.MLSRecommendationFeatureExample; + PRODUCT_BUNDLE_IDENTIFIER = com.donggle.MLS.RecommendationFeatureExample; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; From 8bc32062867c537a956e48e0ccf877c2202defcc Mon Sep 17 00:00:00 2001 From: JunYoung Date: Thu, 30 Apr 2026 13:18:28 +0900 Subject: [PATCH 7/9] =?UTF-8?q?feat/#327:=20=ED=94=84=EB=A1=9C=EB=B9=84?= =?UTF-8?q?=EC=A0=80=EB=8B=9D=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MLS/MLS.xcodeproj/project.pbxproj | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/MLS/MLS.xcodeproj/project.pbxproj b/MLS/MLS.xcodeproj/project.pbxproj index 2b3fb597..95e87f02 100644 --- a/MLS/MLS.xcodeproj/project.pbxproj +++ b/MLS/MLS.xcodeproj/project.pbxproj @@ -1016,8 +1016,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5QTRMS954; ENABLE_USER_SCRIPT_SANDBOXING = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = MLSRecommendationFeatureExample/Info.plist; @@ -1032,8 +1035,10 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.mls.MLSRecommendationFeatureExample; + PRODUCT_BUNDLE_IDENTIFIER = com.donggle.MLS.RecommendationFeatureExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = MLSRecommendationFeatureProvisioningProfileDev; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; @@ -1049,8 +1054,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5QTRMS954; ENABLE_USER_SCRIPT_SANDBOXING = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = MLSRecommendationFeatureExample/Info.plist; @@ -1067,6 +1075,8 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.donggle.MLS.RecommendationFeatureExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = MLSRecommendationFeatureProvisioningProfile; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; From 020b813017a1211840a15e88495d74ebd6f7851d Mon Sep 17 00:00:00 2001 From: JunYoung Date: Thu, 30 Apr 2026 13:23:48 +0900 Subject: [PATCH 8/9] =?UTF-8?q?feat/#327:=20=EC=95=B1=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppIcon.appiconset/AppIcon_1024.png | Bin 0 -> 30469 bytes .../AppIcon.appiconset/Contents.json | 1 + 2 files changed, 1 insertion(+) create mode 100644 MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/AppIcon_1024.png diff --git a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/AppIcon_1024.png b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/AppIcon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..0bf68a80b4afe68674efe1fa9a67d3d407cea220 GIT binary patch literal 30469 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 A?*IS* literal 0 HcmV?d00001 diff --git a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json index 23058801..840dd3de 100644 --- a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,6 +1,7 @@ { "images" : [ { + "filename" : "AppIcon_1024.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" From 758a28a72b2ff61035b9214bfe6f212890975e67 Mon Sep 17 00:00:00 2001 From: JunYoung Date: Thu, 30 Apr 2026 13:27:00 +0900 Subject: [PATCH 9/9] =?UTF-8?q?feat/#327:=20=EC=95=B1=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppIcon.appiconset/AppIcon_1024 (1).png | Bin 0 -> 16615 bytes .../AppIcon.appiconset/AppIcon_1024.png | Bin 30469 -> 0 bytes .../AppIcon.appiconset/Contents.json | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/AppIcon_1024 (1).png delete mode 100644 MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/AppIcon_1024.png diff --git a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/AppIcon_1024 (1).png b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/AppIcon_1024 (1).png new file mode 100644 index 0000000000000000000000000000000000000000..68f3c89085147931577efa21d151f47d6d7597d0 GIT binary patch literal 16615 zcmeIZcT^K?_cl7HfMP*WKtReP0s;ae9fW`)h)7X-4T6AlkY2+BB2onDND&l}-b?5a zkX|B44MsG{9PQ^h;QSfdZXeP<2>_~9TIyTHpL9ukm+ax`# z9|=Lip^yHd&G6sxUkUtI0{@l3|IZRAOZ9vr2b8ETGXzt}RVl&W-L_3H z_-6$_ooW&n&iNPs!r!v%dQ4a9p*k&cMv|cIPUiAAL{Lr}s+VofUj=|kzQ3OT|GgEY zJFEY$!Ad-kfQ#fZDeG4sH{zGz4I)A5Sr@N_m+1iE&%_!@FHCNAxCJ#=B!K-lbxXah zlPBK(QkeNJAyyytG(x~m(ys;gGeB-76?ccq612dC!iogRkWV7p?H$88zKcAa#A>P>z@aB3d))d0PdQk zm3gz%_7?x&hy8yZNvEUFKObcP?l`D(@*VPEj`jSl4DVR`;pYVf1No`vfRf4EQYry! zT}2%B#_#O057!En5$?5XOz9!y)3{ZW)H&TBNl|v}7K|_!rj7WZld2c%0o{{TrJ7cE z03cPF4iIVV=FMwAX%`ya-Cs6#^i>kq1wNcoC~oYiQ|-bL&LqpO*iuvo)~Ms9=6BDO zDsrn^x<`;jN4Rv-mWB?4g z&H$4(rQH5otd6PLcW+c7LJ?P30Kkx)cHB~U4+rv$K3N5RH!Zp(IvBmVs-Jx4ZEtC5 z@-@IHfu@1Rl}N|aN{GX$qMW5mB8&&s^4+M_$;oLs056#HCCU2e?}fRv3k}UPq}-L; zEFSFu?_97Qe_DH7jD=L2{if4}fM}Y<+^siuP-vhBlAi(LoWkWZ_IgO^`^&u#49vN` zF_HaKg{<>ESkB4BVE>n#vhIH#-v}@3dyubxROqj`95Yje0ar908dz`>2C|_NbNGoD z+AcqP$YhsoiHn@qLSa*gRd)lMkH&fOP zCU!6;?&|M$?JTz{SsnKkV<|y@0;@+xL{q*S34V4{YKTQFUvr=R?%Uz{Ch$P+%u@tm zgan@#=up=g-k$Dg4SU<4>wAr9szQhT0j}Mxy8$86%G%3vFCZWys%}p^koySLjN)+x%ldAjKSHkz+=~uh|He zTaaIa#aAkgzBL(vx179S$q{cxp8{Put_9ChKX<);-{GjVVK4wpn(|JCyT>e;$NP;oZ=u$;v4MCwDFJhReVa>HRhK> z`>t$S2S2~q6aGx1Qmv=;AP9Kt{q~q<`NnCKFANkR%i`61*y6!PVGAs5{|ABOUz&IF zm`aV+NRMyb{curpj6}ilM>ZM#)pr_==w1=wVyOS)o1J8SzCH+z9;C5DrxCPC-it(F#EgO1+ z-1+p%F~^Ho8`&h@bws(WK0_u>7!~J`el)LBslPz2LEWL6SPCwO#LFAzn#iI S=9 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 A?*IS* diff --git a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json index 840dd3de..f0d60e38 100644 --- a/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/MLS/MLSRecommendationFeatureExample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "AppIcon_1024.png", + "filename" : "AppIcon_1024 (1).png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024"