-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/#27 검색api연결 #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The head ref may contain hidden characters: "feat/#27-\uAC80\uC0C9API\uC5F0\uACB0"
Feat/#27 검색api연결 #32
Changes from all commits
6cd9430
b5a727b
f621801
01ea00c
d69609e
c15d13c
10ff3bf
46d8ad7
5499b48
03011c9
0366fe5
cd57a20
c815f59
a913109
9e9f6ca
2371266
35e412f
bd69f96
fdf4f82
324c9c8
6976e21
7b00c43
ad4ecba
bbce5b0
1d42a4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "AppIcon~ios-marketing.png", | ||
| "filename" : "AppIcon_Spring_IOS_1024.png", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# PNG 파일 존재 여부 확인
fd -e png "AppIcon_Spring_IOS_1024" --search-path Projects/App/Resources/Assets.xcassets/AppIcon.appiconset
# 전체 AppIcon.appiconset 디렉터리 구조 확인
echo "=== AppIcon.appiconset 디렉터리 내용 ==="
ls -la Projects/App/Resources/Assets.xcassets/AppIcon.appiconset/Repository: YAPP-Github/27th-App-Team-1-iOS Length of output: 451 🏁 Script executed: #!/bin/bash
# Contents.json 파일의 구조 확인 (dark/tinted 변형 확인)
cat -n Projects/App/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json | head -40Repository: YAPP-Github/27th-App-Team-1-iOS Length of output: 983
새 아이콘 파일이 디렉터리에 존재합니다. 그러나 Dark 및 Tinted 모양 변형에 대해 🤖 Prompt for AI Agents |
||
| "idiom" : "universal", | ||
| "platform" : "ios", | ||
| "size" : "1024x1024" | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,9 @@ | ||||||||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||||||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13142" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> | ||||||||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||||||||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> | ||||||||||
| <device id="retina6_12" orientation="portrait" appearance="light"/> | ||||||||||
| <dependencies> | ||||||||||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/> | ||||||||||
| <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/> | ||||||||||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24504"/> | ||||||||||
| <capability name="Named colors" minToolsVersion="9.0"/> | ||||||||||
| <capability name="Safe area layout guides" minToolsVersion="9.0"/> | ||||||||||
| <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | ||||||||||
| </dependencies> | ||||||||||
|
|
@@ -12,37 +13,35 @@ | |||||||||
| <objects> | ||||||||||
| <viewController id="01J-lp-oVM" sceneMemberID="viewController"> | ||||||||||
| <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> | ||||||||||
| <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> | ||||||||||
| <rect key="frame" x="0.0" y="0.0" width="393" height="852"/> | ||||||||||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | ||||||||||
| <subviews> | ||||||||||
| <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Copyright © 2026 NDGL-iOS. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd"> | ||||||||||
| <rect key="frame" x="0.0" y="626.5" width="375" height="20.5"/> | ||||||||||
| <fontDescription key="fontDescription" type="system" pointSize="17"/> | ||||||||||
| <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | ||||||||||
| <nil key="highlightedColor"/> | ||||||||||
| </label> | ||||||||||
| <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="App" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb"> | ||||||||||
| <rect key="frame" x="0.0" y="202" width="375" height="43"/> | ||||||||||
| <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/> | ||||||||||
| <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | ||||||||||
| <nil key="highlightedColor"/> | ||||||||||
| </label> | ||||||||||
| <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="LaunchLogo.png" translatesAutoresizingMaskIntoConstraints="NO" id="cNo-yc-A0v"> | ||||||||||
| <rect key="frame" x="160.66666666666666" y="397" width="72" height="108"/> | ||||||||||
| <color key="backgroundColor" name="green300"/> | ||||||||||
| <constraints> | ||||||||||
| <constraint firstAttribute="height" constant="108" id="5e9-NY-PMN"/> | ||||||||||
| <constraint firstAttribute="width" constant="72" id="y5A-m1-kTT"/> | ||||||||||
| </constraints> | ||||||||||
| </imageView> | ||||||||||
| </subviews> | ||||||||||
| <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | ||||||||||
| <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/> | ||||||||||
| <color key="backgroundColor" name="green300"/> | ||||||||||
| <constraints> | ||||||||||
| <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/> | ||||||||||
| <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/> | ||||||||||
| <constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/> | ||||||||||
| <constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/> | ||||||||||
| <constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/> | ||||||||||
| <constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="x7j-FC-K8j"/> | ||||||||||
| <constraint firstItem="cNo-yc-A0v" firstAttribute="centerY" secondItem="Bcu-3y-fUS" secondAttribute="centerY" id="lzf-rq-KXE"/> | ||||||||||
| <constraint firstItem="cNo-yc-A0v" firstAttribute="centerX" secondItem="Bcu-3y-fUS" secondAttribute="centerX" id="tjh-yU-7rh"/> | ||||||||||
|
Comment on lines
+31
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. safeArea 기준 중앙 정렬 → 화면 기준으로 변경 권장 현재 🛠️ 수정 제안: safeArea → 루트 뷰 기준 중앙 정렬- <constraint firstItem="cNo-yc-A0v" firstAttribute="centerY" secondItem="Bcu-3y-fUS" secondAttribute="centerY" id="lzf-rq-KXE"/>
- <constraint firstItem="cNo-yc-A0v" firstAttribute="centerX" secondItem="Bcu-3y-fUS" secondAttribute="centerX" id="tjh-yU-7rh"/>
+ <constraint firstItem="cNo-yc-A0v" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="lzf-rq-KXE"/>
+ <constraint firstItem="cNo-yc-A0v" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="tjh-yU-7rh"/>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
| </constraints> | ||||||||||
| <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/> | ||||||||||
| </view> | ||||||||||
| </viewController> | ||||||||||
| <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> | ||||||||||
| </objects> | ||||||||||
| <point key="canvasLocation" x="53" y="375"/> | ||||||||||
| </scene> | ||||||||||
| </scenes> | ||||||||||
| <resources> | ||||||||||
| <image name="LaunchLogo.png" width="72" height="108"/> | ||||||||||
| <namedColor name="green300"> | ||||||||||
| <color red="0.45098042488098145" green="0.81568628549575806" blue="0.54509806632995605" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | ||||||||||
| </namedColor> | ||||||||||
| </resources> | ||||||||||
| </document> | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // | ||
| // UIViewController+.swift | ||
| // Core | ||
| // | ||
| // Created by 최안용 on 2/18/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import UIKit | ||
|
|
||
| public extension UIViewController { | ||
| func hideKeyboard() { | ||
| let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard)) | ||
| tap.cancelsTouchesInView = false | ||
| view.addGestureRecognizer(tap) | ||
| } | ||
|
Comment on lines
+12
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🛡️ 중복 등록 방지 수정안 func hideKeyboard() {
+ guard !(view.gestureRecognizers?.contains(where: { $0 is UITapGestureRecognizer }) ?? false) else { return }
let tap = UITapGestureRecognizer(target: self, action: `#selector`(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}🤖 Prompt for AI Agents |
||
|
|
||
| @objc | ||
| func dismissKeyboard() { | ||
| view.endEditing(true) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // | ||
| // URLHelper.swift | ||
| // Core | ||
| // | ||
| // Created by 최안용 on 2/20/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import UIKit | ||
|
|
||
| public struct URLHelper { | ||
| public static func openURL(_ urlString: String) { | ||
| guard let url = URL(string: urlString) else { return } | ||
| UIApplication.shared.open(url) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // | ||
| // TemplatesSearchUsecase.swift | ||
| // Domain | ||
| // | ||
| // Created by 최안용 on 2/19/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| public protocol TemplatesSearchUsecaseProtocol { | ||
| func searchTemplate(keyword: String, page: Int?, size: Int?) async throws -> [TripInfo] | ||
| } | ||
|
|
||
| public extension TemplatesSearchUsecaseProtocol { | ||
| func searchTemplate( | ||
| keyword: String, | ||
| page: Int? = nil, | ||
| size: Int? = nil | ||
| ) async throws -> [TripInfo] { | ||
| try await self.searchTemplate(keyword: keyword, page: page, size: size) | ||
| } | ||
| } | ||
|
Comment on lines
+15
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 프로토콜 요구 메서드와 동일한 기본 시그니처를 가진 extension 기본 구현 → 무한 재귀 위험
현재 권장 해결책은 extension 내 기본 파라미터를 가진 메서드의 이름을 바꿔 프로토콜 요구 메서드와 명확히 구분하는 것입니다. 예를 들어 🐛 무한 재귀를 방지하는 수정 제안 public extension TemplatesSearchUsecaseProtocol {
- func searchTemplate(
- keyword: String,
- page: Int? = nil,
- size: Int? = nil
- ) async throws -> [TripInfo] {
- try await self.searchTemplate(keyword: keyword, page: page, size: size)
- }
+ // 편의 메서드: page/size 없이 키워드만으로 검색 (프로토콜 요구 메서드와 다른 시그니처)
+ func searchTemplate(keyword: String) async throws -> [TripInfo] {
+ try await searchTemplate(keyword: keyword, page: nil, size: nil)
+ }
}🤖 Prompt for AI Agents |
||
|
|
||
| public final class TemplatesSearchUsecase { | ||
| private let travelTemplateRepository: TravelTemplateRepositoryInterface | ||
|
|
||
| public init(travelTemplateRepository: TravelTemplateRepositoryInterface) { | ||
| self.travelTemplateRepository = travelTemplateRepository | ||
| } | ||
| } | ||
|
|
||
| extension TemplatesSearchUsecase: TemplatesSearchUsecaseProtocol { | ||
| public func searchTemplate(keyword: String, page: Int?, size: Int?) async throws -> [TripInfo] { | ||
| try await travelTemplateRepository.searchTemplate(keyword: keyword, page: page, size: size) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,10 +17,11 @@ enum HomeSectionKind: Int, CaseIterable { | |
| var headerTitle: String { | ||
| switch self { | ||
| case .category: | ||
| "인기 여행 따라가기" | ||
| return "인기 여행 따라가기" | ||
| case .recommendedTrip: | ||
| "나혜주님께 추천하는\n따라가기 여행 콘텐츠에요!" | ||
| default: "" | ||
| let nickname = UserDefaults.standard.string(forKey: "nickname") ?? "알 수 없음" | ||
| return "\(nickname)님께 추천하는\n따라가기 여행 콘텐츠에요!" | ||
|
Comment on lines
+22
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for "nickname" key usage across the codebase
rg -n '"nickname"' --type swift -A2 -B2Repository: YAPP-Github/27th-App-Team-1-iOS Length of output: 2041 🏁 Script executed: #!/bin/bash
# Examine the HomeSectionKind.swift file to confirm current state
find . -name "HomeSectionKind.swift" -type fRepository: YAPP-Github/27th-App-Team-1-iOS Length of output: 169 🏁 Script executed: #!/bin/bash
# Look for UserDefaults patterns across the codebase
rg -n 'UserDefaults\.standard' --type swift | head -30Repository: YAPP-Github/27th-App-Team-1-iOS Length of output: 1010
코드에 ♻️ 제안
- var headerTitle: String {
+ func headerTitle(nickname: String? = nil) -> String {
switch self {
case .category:
return "인기 여행 따라가기"
case .recommendedTrip:
- let nickname = UserDefaults.standard.string(forKey: "nickname") ?? "알 수 없음"
- return "\(nickname)님께 추천하는\n따라가기 여행 콘텐츠에요!"
+ let name = nickname ?? "알 수 없음"
+ return "\(name)님께 추천하는\n따라가기 여행 콘텐츠에요!"
default: return ""
}
}🤖 Prompt for AI Agents |
||
| default: return "" | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,14 +70,22 @@ final class RootInteractor: PresentableInteractor<RootPresentable>, RootInteract | |
| if let uuid = self.tokenRepository.get(.uuid) { | ||
| let loginResult = try await self.authRepository.login(uuid: uuid) | ||
| self.tokenRepository.save(loginResult.accessToken, for: .accessToken) | ||
|
|
||
| // 임시 | ||
| UserDefaults.standard.set(loginResult.uuid, forKey: "uuid") | ||
| UserDefaults.standard.set(loginResult.nickname, forKey: "nickname") | ||
| } else { | ||
| let fcmToken = self.tokenRepository.get(.fcmToken) ?? UUID().uuidString | ||
| let signupResult = try await self.authRepository.signup( | ||
| info: SignupInfo(fcmToken: fcmToken) | ||
| ) | ||
| self.tokenRepository.save(signupResult.uuid, for: .uuid) | ||
| self.tokenRepository.save(signupResult.accessToken, for: .accessToken) | ||
|
|
||
|
|
||
| // 임시 | ||
| UserDefaults.standard.set(signupResult.uuid, forKey: "uuid") | ||
| UserDefaults.standard.set(signupResult.nickname, forKey: "nickname") | ||
|
Comment on lines
+73
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UUID·닉네임을
"임시" 표시가 있더라도 이 패턴이 다른 모듈에 의해 의존될 경우 제거가 어려워질 수 있으니, 가능한 한 빠르게 올바른 경로(Keychain/ 🤖 Prompt for AI Agents |
||
|
|
||
| let loginResult = try await self.authRepository.login(uuid: signupResult.uuid) | ||
| self.tokenRepository.save(loginResult.accessToken, for: .accessToken) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| // | ||
| // SearchResultPresentationModel.swift | ||
| // SearchFeature | ||
| // | ||
| // Created by 최안용 on 2/18/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| import Domain | ||
|
|
||
| struct SearchResultPresentationModel { | ||
| let resultTrip: [SearchResultPresentationModel.ResultTrip] | ||
|
|
||
| struct ResultTrip: Hashable { | ||
| let id: Int | ||
| let title: String | ||
| let thumbnailUrl: String | ||
| let creator: String | ||
| let schedule: String | ||
| let country: String | ||
| let city: String | ||
| } | ||
| } | ||
|
|
||
| extension TripInfo { | ||
| func toSearchResultModel() -> SearchResultPresentationModel.ResultTrip { | ||
| return SearchResultPresentationModel.ResultTrip( | ||
| id: self.id, | ||
| title: self.title, | ||
| thumbnailUrl: self.thumbnailUrl, | ||
| creator: self.creator, | ||
| schedule: "\(self.nights)박 \(self.days)일", | ||
| country: self.country, | ||
| city: self.city | ||
| ) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 361
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 2825
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 441
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 4035
X_API_KEY를 Info.plist에서 조건부로만 읽도록 수정하고, demoInfoPlist에도 추가하세요.원래 우려했던 xcconfig 보안 설정은 올바릅니다.
.gitignore에서*.xcconfig를 제대로 차단하고 있으며, CI 워크플로우에서 비공개 저장소로부터 해당 파일을 주입하고 있습니다. 그러나 두 가지 실행 문제가 있습니다:NetworkConfiguration.apiKey (Projects/Modules/Networks/Sources/Foundation/NetworkConfiguration.swift:25-26)는 모든 빌드에서
X_API_KEY를 읽으려 시도합니다. 팀의 지침에 따르면 DEBUG 모드에서만 읽어야 합니다. DEBUG가 아닐 때는 조건부로 처리하거나 경고하도록 수정하세요.demoInfoPlist (Plugins/EnvPlugin/ProjectDescriptionHelpers/InfoPlist.swift:39-64)에는
X_API_KEY가 정의되어 있지 않습니다. 반면 demo 타겟이 비-DEBUG 빌드에서 AuthAPI, TravelTemplateAPI 등을 호출하면 Info.plist 조회 실패로 런타임 크래시가 발생합니다. demoInfoPlist에도X_API_KEY항목을 추가하거나, 해당 APIs 호출을 DEBUG 모드로 제한하세요.🤖 Prompt for AI Agents