Skip to content

Feature/search 검색 화면 구현#7

Merged
Roy-wonji merged 14 commits intodevelopfrom
feature/search
Oct 31, 2025
Merged

Feature/search 검색 화면 구현#7
Roy-wonji merged 14 commits intodevelopfrom
feature/search

Conversation

@Roy-wonji
Copy link
Contributor

@Roy-wonji Roy-wonji commented Oct 31, 2025

🔗 관련 이슈


✨ 작업 내용

  • 검색 화면 구현
  • 탭바 연걀

📸 Showcase

추가되 이미지 추가된 이미지 추가된 이미지
Simulator Screenshot - iPhone 16e - 2025-10-31 at 13 48 58 Simulator Screenshot - iPhone 16e - 2025-10-31 at 13 49 01 Simulator Screenshot - iPhone 16e - 2025-10-31 at 13 49 07

Close Issues 🔒 (닫을 Issue)

Close #5

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 새로운 검색 기능 추가 - 미디어 유형별 필터링 지원 (음악, 영화, 팟캐스트)
    • 탭 기반 네비게이션 인터페이스 구현 (홈, 검색)
    • 최근 검색 기록 및 트렌딩 항목 표시
    • 검색 결과의 카테고리별 필터링 및 개수 표시
  • Chores

    • 네트워크 서비스 모듈 구조 개선
    • 프레젠테이션 계층 모듈화 진행

# Conflicts:
#	Projects/Core/Data/DataInterface/Sources/MusicSearchRepositoryProtocol.swift
#	Projects/Core/Data/Repository/RepositoryTests/Sources/MockMusicSearchRepositoryTests.swift
#	Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift
#	Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift
#	Projects/Core/Domain/DomainInterface/Sources/MusicSearchUseCaseProtocol.swift
#	Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift
#	Projects/Core/Domain/UseCase/UseCaseTests/Sources/MusicSearchUseCaseTests.swift
@Roy-wonji Roy-wonji added ⚒️ 테스트 테스트 코드 작성 ✨ 기능추가 새로운 기능 추가 🎨 디자인 UI 디자인 작업 labels Oct 31, 2025
@auto-assign auto-assign bot requested review from Peter1119 and minneee October 31, 2025 04:53
@coderabbitai
Copy link

coderabbitai bot commented Oct 31, 2025

PR 분석

Walkthrough

프로젝트는 검색 화면(Search 모듈) 및 탭 관리(RootTab 모듈) 기능을 추가하고, Service 모듈을 NetworkService로 이름 변경하며, 검색 저장소에 새로운 searchMedia 메서드를 추가합니다. 또한 프리젠테이션 계층을 재구성하고 의존성을 업데이트합니다.

Changes

코호트 / 파일(들) 변경 요약
모듈 구조 업데이트
Plugins/DependencyPlugin/ProjectDescriptionHelpers/TargetDependency+Module/Modules.swift, MusicBandscape.xcworkspace/contents.xcworkspacedata, Projects/Presentation/Presentation/Project.swift
Presentation에 Search, RootTab 케이스 추가; Data 계층의 Service → NetworkService 변경; 워크스페이스 프로젝트 참조 재구성
NetworkService 모듈 신규
Projects/Core/Data/NetworkService/*
Service에서 NetworkService로 전체 이름 변경: 프로젝트 파일, 스킴, Project.swift, MusicSearchService.swift 구현 포함
Repository 업데이트
Projects/Core/Data/Repository/*
NetworkService 의존성 교체; MusicSearchRepository에 searchMedia() 메서드 추가; MockMusicSearchRepository 업데이트
도메인 엔티티 확장
Projects/Core/Domain/Entity/Sources/SearchCategory.swift, MediaType.swift, TrendingItem.swift, MusicItemEntity.swift
SearchCategory, MediaType, TrendingItem 새로 추가; MusicItem에 mediaType 필드 추가 및 필터링/정렬 메서드 추가
도메인 인터페이스 및 UseCase
Projects/Core/Domain/DomainInterface/Sources/MusicSearchUseCaseProtocol.swift, Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift
searchMedia() 및 getCategoryCount() 메서드 추가
데이터 모델 변경
Projects/Core/Data/Model/Sources/ITunesSearchResponseDTO.swift
ITunesTrack 속성을 non-optional에서 optional로 변경 (trackId, artistName, trackName 등)
RootTab 모듈 신규
Projects/Presentation/RootTab/*
RootTab 프레젠테이션 모듈 신규 추가: RootTabReducer, RootTabBarView, MainTab enum, 완전한 Xcode 프로젝트 구조
Search 모듈 신규
Projects/Presentation/Search/*
Search 프레젠테이션 모듈 신규 추가: SearchReducer, SearchView, SearchCoordinator 및 관련 컴포넌트 (SearchBar, SearchResultsList, SearchCategoryFilter, NoResultsView 등) 포함
App 계층 업데이트
Projects/App/Sources/Reducer/AppReducer.swift, Projects/App/Sources/View/AppView.swift
home(HomeCoordinator) → tabBar(RootTabReducer) 변경; 라우팅 및 뷰 참조 업데이트
Detail 화면 리팩터링
Projects/Presentation/Detail/Sources/View/Component/NavigationArrowButton.swift, ScalingHeaderDetailView.swift
NavigationArrowButton을 이미지에서 버튼으로 변경; ScalingHeaderDetailView에 store 파라미터 추가 (closeure 기반 → action 기반)
Home 화면 업데이트
Projects/Presentation/Home/Sources/Main /Reducer/HomeReducer.swift, SearchBarView.swift
didTriggerInitialFetch 플래그 추가; tapSearch navigation 케이스 추가; SearchBarView에 action 파라미터 추가
프로젝트 파일 (pbxproj) 업데이트
Projects/App/MusicBandscape.xcodeproj/project.pbxproj, Projects/Core/Core/Core.xcodeproj/project.pbxproj, Projects/Presentation/Presentation/Presentation.xcodeproj/project.pbxproj, 기타
NetworkService, Search, RootTab 프레임워크 참조 추가; Service.framework 참조 제거; 빌드 페이즈 및 의존성 재구성
빌드 스킴 업데이트
MusicBandscape.xcworkspace/xcshareddata/xcschemes/MusicBandscape-Workspace.xcscheme
NetworkService, RootTab, Search 관련 BuildActionEntry 및 TestableReference 추가
테스트 계획 및 테스트 코드
Projects/App/MusicBandscapeTests/Sources/MusicBandscapeTestPlan.xctestplan, Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift, Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift
테스트 대상 재구성; SearchReducer 테스트 및 HomeReducer 테스트 확대
문서 업데이트
README.md
구현 미리보기, 설계 의사결정, 아키텍처 설명, 메모리 관리 분석 섹션 추가

Sequence Diagram(s)

sequenceDiagram
    participant App as AppView
    participant RootTab as RootTabReducer
    participant Home as HomeCoordinator
    participant Search as SearchCoordinator
    
    App->>RootTab: store initialization (selectedTab: .home)
    activate RootTab
    RootTab->>Home: scope to homeCoordinator
    RootTab->>Search: scope to searchCoordinator
    deactivate RootTab
    
    Home->>Home: User navigates
    Home->>RootTab: dispatch switchTapBar view action
    activate RootTab
    RootTab->>RootTab: selectedTab = .search
    deactivate RootTab
    
    App->>Search: render SearchCoordinatorView (selectedTab == .search)
    activate Search
    Search->>Search: User searches music
    Search->>Search: Fetch results via searchMedia()
    Search->>Search: Category filtering & counts
    deactivate Search
    
    Search->>Search: User selects music item
    Search->>Search: Push detail route
    activate Search
    Search->>Search: Render DetailView
    deactivate Search
Loading
sequenceDiagram
    participant SR as SearchReducer
    participant SU as MusicSearchUseCase
    participant REPO as MusicSearchRepository
    participant NS as NetworkService
    
    SR->>SR: User inputs search text & submits
    SR->>SU: searchMedia(query, category)
    activate SU
    SU->>REPO: searchMedia(query, media, entity)
    activate REPO
    REPO->>NS: .searchMusic(media, entity)
    activate NS
    NS-->>REPO: ITunesSearchResponseDTO
    deactivate NS
    REPO->>REPO: Map to [ITunesTrack]
    REPO-->>SU: [ITunesTrack]
    deactivate REPO
    SU->>SU: Domain mapping
    SU-->>SR: [MusicItem]
    deactivate SU
    SR->>SR: Update filteredSearchResults
    SR->>SR: getCategoryCount(results, category)
    SR->>SR: Update category counts
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

주의 깊게 검토할 영역:

  • SearchReducer 및 SearchCoordinator: 새로운 라우팅 로직, 상태 관리, 카테고리 필터링 복잡성 (Projects/Presentation/Search/Sources/Reducer/ 및 Coordinator/)
  • RootTabReducer: 탭 전환 로직 및 coordinator 통합 (Projects/Presentation/RootTab/Sources/Reducer/RootTabReducer.swift)
  • AppReducer 변경: home → tabBar 전환 및 기존 routing 재구성 (Projects/App/Sources/Reducer/AppReducer.swift)
  • 모듈 의존성 재구성: Service → NetworkService 마이그레이션 전반 (여러 Repository, UseCase 파일)
  • 데이터 모델 변경: ITunesTrack 필드들이 optional로 변경되었으며, null 처리 로직 검증 필요 (Projects/Core/Data/Model/Sources/ITunesSearchResponseDTO.swift)
  • 프로젝트 파일 대량 변경: pbxproj 파일들의 일관성 확인 필요 (특히 새 프레임워크 참조 및 빌드 페이즈)

Possibly related PRs

  • Feature/splash #4: Modules.swift enum에서 Presentation 모듈 경로 수정 (Splash 추가) — 모듈 구조 변경과 관련
  • Feature/home #6: 워크스페이스/프로젝트 모듈 wiring 업데이트 및 Presentation 프로젝트 추가 — 모듈 신규 추가와 관련

Suggested reviewers

  • minneee
  • Peter1119

Poem

🐰 탭바 위에 검색 창을 열고,
NetworkService로 갈아입고,
카테고리 필터로 음악을 걸러내며,
새로운 RootTab에서 모든 게 한데 뭉쳐서,
깔끔한 아키텍처 춤을 춘다! ✨🎵

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed PR 제목 "Feature/search 검색 화면 구현"은 작업의 핵심 목표를 명확하고 간결하게 설명하고 있습니다. "Feature/search" 접두사는 기능 추가의 성격을 나타내고, "검색 화면 구현"이라는 한국어 설명은 변경 사항의 주요 내용을 직접적으로 전달합니다. 여러 지원 모듈(RootTab, 아키텍처 개선 등)이 포함되어 있지만, 제목은 검색 화면 구현이라는 주요 목표에 충실하게 초점을 맞추고 있습니다.
Linked Issues Check ✅ Passed 연결된 issue #5의 모든 주요 요구사항이 코드 변경으로 충족되었습니다. 검색 화면 구현 [검색 화면 UI 컴포넌트 완전 구현, SearchView, SearchBar, SearchCategoryFilter 등], 검색 결과 없음 화면 구현 [NoResultsView, RecentSearchesSection, TrendingSection 추가], 검색 API 연결 [MusicSearchUseCase에 searchMedia 메서드 추가, 저장소 계층 전체에 구현됨]이 모두 코드베이스에 반영되어 있습니다. 추가로 tab bar 연결(RootTabReducer, RootTabBarView) 및 도메인 엔티티 확장(SearchCategory, MediaType, TrendingItem)도 일관되게 구현되었습니다.
Out of Scope Changes Check ✅ Passed 변경 사항들이 검색 화면 구현과 관련 목표를 지원하기 위해 필요한 범위 내에서 이루어졌습니다. Service에서 NetworkService로의 이름 변경은 새로운 네트워크 서비스 구조를 명확히 하는 것이고, RootTab 모듈 추가는 PR 본문에 명시된 tab bar 연결 요구사항을 충족하는 것이며, ITunesTrack 속성 변경과 도메인 엔티티 확장은 검색 기능을 지원하기 위한 데이터 모델 개선입니다. 홈 모듈 업데이트도 SearchBar 통합을 위한 필수 변경입니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/search

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17a0acf and 476633d.

📒 Files selected for processing (2)
  • Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (3 hunks)
  • Projects/Presentation/Home/Sources/Main /Reducer/HomeReducer.swift (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift
🧰 Additional context used
🧬 Code graph analysis (1)
Projects/Presentation/Home/Sources/Main /Reducer/HomeReducer.swift (2)
Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (1)
  • searchMusic (59-61)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (1)
  • searchMusic (27-30)
🔇 Additional comments (6)
Projects/Presentation/Home/Sources/Main /Reducer/HomeReducer.swift (6)

27-27: 초기 fetch 중복 방지 플래그가 리셋되지 않습니다.

didTriggerInitialFetch 플래그는 중복 fetch를 방지하는 좋은 패턴이지만, 한 번 true로 설정되면 다시 false로 리셋되지 않습니다. 이는 뷰가 사라졌다가 다시 나타날 때 데이터를 다시 가져오지 않는다는 의미입니다.

만약 홈 화면으로 돌아올 때마다 최신 데이터를 가져와야 한다면, 뷰가 사라질 때 이 플래그를 리셋하는 액션을 추가하거나, 또는 상위 레벨에서 State를 재생성하는 방식을 고려해주세요.

현재 의도가 "앱 실행 중 한 번만 fetch"인지, 아니면 "탭 전환 시마다 refetch 필요"인지 확인이 필요합니다.


64-67: CancelID를 enum으로 개선한 것은 좋은 변경입니다.

struct 대신 연관 값을 가진 enum으로 변경하여 타입 안정성이 향상되었습니다. fetchAll과 개별 시즌별 fetch를 구분하여 취소할 수 있어 더 세밀한 제어가 가능합니다.


111-112: LGTM!

didTriggerInitialFetch 플래그를 사용한 중복 fetch 방지 로직이 올바르게 구현되었습니다. 첫 번째 onAppear에서만 fetch를 트리거합니다.


123-135: 동시 fetch 패턴으로 성능이 개선되었습니다.

모든 시즌을 순차적으로 가져오던 방식에서 withTaskGroup을 사용한 동시 fetch로 변경하여 초기 로딩 성능이 크게 개선되었습니다.

다만, 각 시즌의 결과가 독립적으로 도착하므로 사용자는 화면에 데이터가 하나씩 나타나는 것을 볼 수 있습니다.

UX 관점에서 확인이 필요합니다:

  • 부분 로딩(partial loading)이 의도된 UX인지?
  • 아니면 모든 시즌 데이터가 로드될 때까지 전체 로딩 인디케이터를 표시해야 하는지?

부분 로딩이 허용되지 않는다면, 완료 카운터를 State에 추가하여 모든 fetch가 완료되었을 때를 추적하는 것을 고려해주세요.


137-150: LGTM!

fetchMusic의 cancellation ID가 새로운 enum 구조와 일관되게 업데이트되었습니다. 시즌별로 독립적인 취소가 가능합니다.


57-57: 설계가 정확합니다 - tapSearch 액션이 올바르게 처리되고 있습니다.

스크립트 결과를 통해 확인된 바:

  • HomeView (line 62): store.send(.navigation(.tapSearch)) 액션 전송
  • HomeReducer (line 162-163): .none 반환 (의도적인 pass-through)
  • HomeCoordinator (line 73-74): .routeAction(id: _, action: .home(.navigation(.tapSearch))) 인터셉트하여 .view(.switchTapBar) 이펙트 전송

HomeReducer에서 .none을 반환하는 것은 의도된 설계입니다. 이 액션은 로컬 상태 변화가 필요 없으므로 HomeReducer를 통과하고, 실제 탭 전환 네비게이션은 HomeCoordinator에서 처리됩니다. 이는 올바른 계층 분리 아키텍처 패턴입니다.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

181-256: README의 WeaveDI 코드 예제가 실제 구현과 불일치합니다. 수정이 필요합니다.

검증 결과, 라인 243-256의 세 가지 WeaveDI 패턴 중 두 가지가 실제 프로젝트에서 사용되지 않습니다:

  • 라인 243-250 (@Injected(\.userUseCase) Property Wrapper): 프로젝트에서 미사용
  • 라인 252-256 (UnifiedDI.register(\.userUseCase) KeyPath 기반 등록): 프로젝트에서 미사용

실제 프로젝트는 DependencyKey extension 패턴(liveValue/previewValue 구조)을 사용하고 있습니다. MusicDetailUseCase, MusicSearchUseCase 파일을 참고하여 README 예제를 실제 패턴으로 수정하세요. 또한 UserUseCase, UserRepository는 프로젝트에 존재하지 않는 가상 예제이므로, 실제 클래스(MusicDetailUseCase 등)로 대체하는 것이 더 명확합니다.

🧹 Nitpick comments (10)
Projects/Presentation/Detail/Sources/View/Component/NavigationArrowButton.swift (1)

24-37: 접근성 개선을 위한 Button 래퍼 사용은 좋은 변경입니다.

하지만 Line 31의 .font() 수정자는 불필요합니다. Image.resizable().frame()을 함께 사용할 경우, 이미지 크기는 frame 수정자로 제어되며 .font() 수정자는 효과가 없습니다.

다음 diff를 적용하여 불필요한 수정자를 제거하세요:

       Image(systemName: "chevron.left")
         .resizable()
         .scaledToFit()
         .frame(width: 16, height: 24)
-        .font(.pretendardFont(family: .semiBold, size: 20))
         .foregroundStyle(.white)
         .padding(16)
         .background(Color.lightGray100.opacity(0.6))
         .clipShape(Circle())
README.md (1)

111-111: 그래프 이미지 경로를 상대 경로로 수정 권장

현재 /graph.png(절대 경로)는 GitHub에서 렌더링될 때 루트 도메인 기준으로 해석되어 깨질 수 있습니다. 상대 경로 ./graph.png 또는 graph.png로 변경하는 것이 안정적입니다.

-<img src="/graph.png" width="500" height="800" alt="graph" />
+<img src="./graph.png" width="500" height="800" alt="graph" />
Projects/Core/Domain/Entity/Sources/MediaType.swift (1)

11-14: 중복된 문자열 값을 제거할 수 있습니다.

SwiftLint가 지적한 대로, enum case 이름과 문자열 값이 동일할 때는 명시적인 값을 생략할 수 있습니다.

다음 diff를 적용하여 코드를 간소화할 수 있습니다:

 public enum MediaType: String, Codable, CaseIterable {
-  case music = "music"
-  case movie = "movie"
-  case podcast = "podcast"
-  case other = "other"
+  case music
+  case movie
+  case podcast
+  case other
 }
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)

30-37: 파라미터 추적 형식 확인 필요

Line 35에서 파이프 구분자(|)를 사용하여 파라미터를 결합하고 있습니다. 실제 검색 쿼리에 파이프 문자가 포함될 경우 테스트 검증 시 혼란을 야기할 수 있습니다.

구조화된 형태로 파라미터를 추적하는 것을 고려해보세요:

+public private(set) var receivedSearchMediaCalls: [(query: String, media: String, entity: String)] = []

 public func searchMedia(
   query: String,
   media: String,
   entity: String
 ) async throws -> [ITunesTrack] {
-  self.receivedQueries.append("\(query)|\(media)|\(entity)")
+  self.receivedSearchMediaCalls.append((query, media, entity))
   return try result.get()
 }
Projects/Core/Domain/Entity/Sources/Mapper/Extension+ITunesTrack.swift (1)

24-38: MediaType 매핑 로직 개선 제안

현재 구현은 kind 필드를 소문자로 변환하여 매핑하고 있으며, "feature-movie"와 "movie"를 모두 처리합니다.

예상치 못한 kind 값에 대한 로깅이나 추적을 추가하는 것을 고려해보세요:

let mediaType: MediaType = {
  guard let kind = kind else { return .other }
  
  switch kind.lowercased() {
  case "song":
    return .music
  case "feature-movie", "movie":
    return .movie
  case "podcast":
    return .podcast
  default:
    // 예상치 못한 kind 값을 로깅하여 향후 지원이 필요한 타입 파악
    print("⚠️ Unknown media kind: \(kind)")
    return .other
  }
}()
Projects/Presentation/Home/Sources/Coordinator/Reducer/HomeCoordinator.swift (1)

77-77: 주석 처리된 코드 정리 필요

Line 77의 주석 처리된 goBackToRoot() 호출을 제거하거나, 의도적으로 남겨둔 것이라면 그 이유를 TODO 주석으로 명확히 해주세요.

 case .routeAction(id: _, action: .detail(.navigation(.backToHome))):
-//        state.routes.goBackToRoot()
   return .send(.view(.backToRoot))
Projects/Presentation/Search/Sources/Main /View/Component/TrendingCard.swift (1)

39-39: 고정 높이 검토 제안

현재 카드 높이가 92로 고정되어 있습니다. 제목이 길어질 경우 잘릴 수 있으므로 다음을 고려해보세요:

  1. Text.lineLimit(2)와 함께 최소/최대 높이 사용
  2. 또는 동적 타입 크기에 따라 높이 조정
.frame(minHeight: 92)
// 또는
.frame(height: 92)
Text(item.title)
  .font(.pretendardFont(family: .semiBold, size: 16))
  .foregroundStyle(.white)
  .lineLimit(2)
Projects/Presentation/Search/Sources/Main /View/Component/TrendingSection.swift (1)

13-18: 하드코딩된 항목을 외부로 추출하는 것을 고려해보세요.

현재 Trending 항목들이 하드코딩되어 있습니다. 향후 유지보수성을 위해 이러한 항목들을 ViewModel이나 별도의 configuration으로 분리하는 것을 고려해볼 수 있습니다.

Projects/Presentation/Home/Sources/Main /View/Component/SearchBarView.swift (1)

5-5: 불필요한 기본값 제거를 고려하세요.

Line 5의 action 프로퍼티에 기본 빈 클로저 = { }가 할당되어 있지만, 이니셜라이저에서 항상 값을 설정하므로 이 기본값은 불필요합니다.

다음과 같이 수정할 수 있습니다:

-  private var action: () -> Void = { }
+  private var action: () -> Void
Projects/Presentation/Search/Sources/Main /View/Component/NoResultsView.swift (1)

52-68: 제안 태그 반복 생성 리팩터링 제안

suggestions 배열이 선언만 되고 사용되지 않고 있습니다. 배열을 ForEach로 순회하도록 바꾸면 중복된 코드가 사라지고, 제안 목록이 바뀌어도 한 곳만 수정하면 되어 유지보수성이 좋아집니다.

-        HStack(spacing: 12) {
-          SuggestionTag(text: "Top Hits") {
-            onSuggestionTap("Top Hits")
-          }
-
-          SuggestionTag(text: "K-Pop") {
-            onSuggestionTap("K-Pop")
-          }
-
-          SuggestionTag(text: "Jazz") {
-            onSuggestionTap("Jazz")
-          }
-
-          SuggestionTag(text: "Podcasts") {
-            onSuggestionTap("Podcasts")
-          }
-
-          Spacer()
-        }
+        HStack(spacing: 12) {
+          ForEach(suggestions, id: \.self) { suggestion in
+            SuggestionTag(text: suggestion) {
+              onSuggestionTap(suggestion)
+            }
+          }
+
+          Spacer()
+        }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9cb6a1 and 698c6ba.

⛔ Files ignored due to path filters (3)
  • Docs/Screenshots/home.png is excluded by !**/*.png
  • Docs/Screenshots/search.png is excluded by !**/*.png
  • graph.png is excluded by !**/*.png
📒 Files selected for processing (92)
  • MusicBandscape.xcworkspace/contents.xcworkspacedata (2 hunks)
  • MusicBandscape.xcworkspace/xcshareddata/xcschemes/MusicBandscape-Workspace.xcscheme (9 hunks)
  • Plugins/DependencyPlugin/ProjectDescriptionHelpers/TargetDependency+Module/Modules.swift (2 hunks)
  • Projects/App/MusicBandscape.xcodeproj/project.pbxproj (17 hunks)
  • Projects/App/MusicBandscapeTests/Sources/MusicBandscapeTestPlan.xctestplan (2 hunks)
  • Projects/App/Sources/Reducer/AppReducer.swift (4 hunks)
  • Projects/App/Sources/View/AppView.swift (1 hunks)
  • Projects/App/Sources/View/ContentView.swift (2 hunks)
  • Projects/Core/Core/Core.xcodeproj/project.pbxproj (10 hunks)
  • Projects/Core/Data/DataInterface/DataInterface.xcodeproj/project.pbxproj (14 hunks)
  • Projects/Core/Data/DataInterface/Sources/MusicSearchRepositoryProtocol.swift (1 hunks)
  • Projects/Core/Data/Model/Sources/ITunesSearchResponseDTO.swift (2 hunks)
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/project.pbxproj (28 hunks)
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService-Debug.xcscheme (1 hunks)
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService-Prod.xcscheme (1 hunks)
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService-Stage.xcscheme (1 hunks)
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService.xcscheme (1 hunks)
  • Projects/Core/Data/NetworkService/Project.swift (1 hunks)
  • Projects/Core/Data/NetworkService/Sources/MusicSearchService.swift (3 hunks)
  • Projects/Core/Data/Repository/Project.swift (1 hunks)
  • Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj (23 hunks)
  • Projects/Core/Data/Repository/RepositoryTests/Sources/MockMusicSearchRepositoryTests.swift (3 hunks)
  • Projects/Core/Data/Repository/Sources/Detail/MusicDetailRepository.swift (1 hunks)
  • Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1 hunks)
  • Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (2 hunks)
  • Projects/Core/Domain/DomainInterface/DomainInterface.xcodeproj/project.pbxproj (13 hunks)
  • Projects/Core/Domain/DomainInterface/Sources/MusicSearchUseCaseProtocol.swift (1 hunks)
  • Projects/Core/Domain/Entity/Entity.xcodeproj/project.pbxproj (7 hunks)
  • Projects/Core/Domain/Entity/Sources/Mapper/Extension+ITunesTrack.swift (1 hunks)
  • Projects/Core/Domain/Entity/Sources/MediaType.swift (1 hunks)
  • Projects/Core/Domain/Entity/Sources/MusicItemEntity.swift (5 hunks)
  • Projects/Core/Domain/Entity/Sources/SearchCategory.swift (1 hunks)
  • Projects/Core/Domain/Entity/Sources/TrendingItem.swift (1 hunks)
  • Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (1 hunks)
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj (24 hunks)
  • Projects/Core/Domain/UseCase/UseCaseTests/Sources/MusicDetailUseCaseTests.swift (1 hunks)
  • Projects/Core/Domain/UseCase/UseCaseTests/Sources/MusicSearchUseCaseTests.swift (2 hunks)
  • Projects/Presentation/Detail/Sources/View/Component/NavigationArrowButton.swift (1 hunks)
  • Projects/Presentation/Detail/Sources/View/Component/ScalingHeaderDetailView.swift (2 hunks)
  • Projects/Presentation/Detail/Sources/View/DetailView.swift (2 hunks)
  • Projects/Presentation/Home/Home.xcodeproj/project.pbxproj (4 hunks)
  • Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (2 hunks)
  • Projects/Presentation/Home/Sources/Coordinator/Reducer/HomeCoordinator.swift (3 hunks)
  • Projects/Presentation/Home/Sources/Main /Reducer/HomeReducer.swift (2 hunks)
  • Projects/Presentation/Home/Sources/Main /View/Component/SearchBarView.swift (2 hunks)
  • Projects/Presentation/Home/Sources/Main /View/HomeView.swift (1 hunks)
  • Projects/Presentation/Presentation/Presentation.xcodeproj/project.pbxproj (12 hunks)
  • Projects/Presentation/Presentation/Project.swift (1 hunks)
  • Projects/Presentation/Presentation/Sources/Exported/PresentationExported.swift (1 hunks)
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Debug-Info.plist (1 hunks)
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Info.plist (1 hunks)
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Prod-Info.plist (1 hunks)
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Stage-Info.plist (1 hunks)
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTabTests-Info.plist (1 hunks)
  • Projects/Presentation/RootTab/Project.swift (1 hunks)
  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.pbxproj (1 hunks)
  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.xcworkspace/contents.xcworkspacedata (1 hunks)
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Debug.xcscheme (3 hunks)
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Prod.xcscheme (3 hunks)
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Stage.xcscheme (3 hunks)
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab.xcscheme (4 hunks)
  • Projects/Presentation/RootTab/RootTabTests/Sources/Test.swift (1 hunks)
  • Projects/Presentation/RootTab/Sources/Reducer/MainTab.swift (1 hunks)
  • Projects/Presentation/RootTab/Sources/Reducer/RootTabReducer.swift (1 hunks)
  • Projects/Presentation/RootTab/Sources/View/RootTabBarView.swift (1 hunks)
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Debug-Info.plist (1 hunks)
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Info.plist (1 hunks)
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Prod-Info.plist (1 hunks)
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Stage-Info.plist (1 hunks)
  • Projects/Presentation/Search/Derived/InfoPlists/SearchTests-Info.plist (1 hunks)
  • Projects/Presentation/Search/Project.swift (1 hunks)
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj (1 hunks)
  • Projects/Presentation/Search/Search.xcodeproj/project.xcworkspace/contents.xcworkspacedata (1 hunks)
  • Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search-Debug.xcscheme (1 hunks)
  • Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search-Prod.xcscheme (1 hunks)
  • Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search-Stage.xcscheme (1 hunks)
  • Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search.xcscheme (1 hunks)
  • Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Coordinator/Reducer/SearchCoordinator.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Coordinator/View/SearchCoordinatorView.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/NoResultsView.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/RecentSearchesSection.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/SearchBackground.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/SearchBar.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/SearchCategoryFilter.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/SearchResultItem.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/SearchResultsList.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/TrendingCard.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/TrendingSection.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/SearchView.swift (1 hunks)
  • README.md (2 hunks)
🧰 Additional context used
🧠 Learnings (10)
📚 Learning: 2025-10-28T02:24:45.154Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/Derived/InfoPlists/API-Stage-Info.plist:17-20
Timestamp: 2025-10-28T02:24:45.154Z
Learning: In Tuist-based projects, files under `Derived/` or `Derived/InfoPlists/` directories are auto-generated by Tuist and should not be manually edited. Any configuration changes should be made in the corresponding Project.swift files instead.

Applied to files:

  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTabTests-Info.plist
  • Projects/Presentation/Search/Derived/InfoPlists/SearchTests-Info.plist
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Stage-Info.plist
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Debug-Info.plist
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Info.plist
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Debug-Info.plist
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Prod-Info.plist
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Prod-Info.plist
  • Projects/Presentation/RootTab/Project.swift
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Info.plist
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Project.swift
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Stage-Info.plist
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.pbxproj
📚 Learning: 2025-10-28T02:24:36.027Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/Derived/InfoPlists/API-Prod-Info.plist:17-18
Timestamp: 2025-10-28T02:24:36.027Z
Learning: In the MusicBandscape project, Info.plist files located in `Derived/InfoPlists/` directories are auto-generated by Tuist and should not be flagged for manual modification, including CFBundlePackageType settings.

Applied to files:

  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTabTests-Info.plist
  • Projects/Presentation/Search/Derived/InfoPlists/SearchTests-Info.plist
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Stage-Info.plist
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Debug-Info.plist
  • Projects/Core/Domain/Entity/Entity.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Info.plist
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Debug-Info.plist
  • MusicBandscape.xcworkspace/xcshareddata/xcschemes/MusicBandscape-Workspace.xcscheme
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Prod-Info.plist
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Prod-Info.plist
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Info.plist
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Core/Data/DataInterface/DataInterface.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/contents.xcworkspacedata
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Stage-Info.plist
  • Projects/App/MusicBandscapeTests/Sources/MusicBandscapeTestPlan.xctestplan
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/project.pbxproj
  • Projects/App/MusicBandscape.xcodeproj/project.pbxproj
  • Projects/Core/Domain/DomainInterface/DomainInterface.xcodeproj/project.pbxproj
📚 Learning: 2025-10-23T01:43:01.591Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 4
File: Projects/Presentation/Presentation/Presentation.xcodeproj/project.pbxproj:85-114
Timestamp: 2025-10-23T01:43:01.591Z
Learning: In Tuist-managed iOS projects (identified by Tuist/ directory, Project.swift manifest files, and Tuist references in build settings), the .xcodeproj/project.pbxproj files are auto-generated and should not be manually edited. Build phases including 'Dependencies' Copy Files phases are generated by Tuist based on the Project.swift manifests, and manual changes will be overwritten on the next `tuist generate` run. Do not flag or suggest manual modifications to pbxproj files in Tuist projects.

Applied to files:

  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Stage-Info.plist
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Debug.xcscheme
  • README.md
  • Projects/Core/Domain/Entity/Entity.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Info.plist
  • Projects/Presentation/Home/Home.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Stage.xcscheme
  • Projects/Presentation/Presentation/Project.swift
  • Projects/Presentation/Presentation/Presentation.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/xcshareddata/xcschemes/MusicBandscape-Workspace.xcscheme
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Prod-Info.plist
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Prod-Info.plist
  • Projects/Presentation/RootTab/Project.swift
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Prod.xcscheme
  • Projects/Presentation/Search/Project.swift
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab.xcscheme
  • Projects/Core/Data/DataInterface/DataInterface.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/contents.xcworkspacedata
  • Projects/Presentation/Search/Search.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  • Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Stage-Info.plist
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.pbxproj
  • Projects/App/MusicBandscape.xcodeproj/project.pbxproj
  • Projects/Core/Domain/DomainInterface/DomainInterface.xcodeproj/project.pbxproj
📚 Learning: 2025-10-30T05:07:37.049Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme:93-96
Timestamp: 2025-10-30T05:07:37.049Z
Learning: In the MusicBandscape project, .xcscheme files under xcshareddata directories are auto-generated by Tuist. Scheme configurations (including buildConfiguration settings for ArchiveAction, ProfileAction, etc.) should be modified in the Tuist manifest files (Project.swift) rather than directly editing the .xcscheme files, as manual changes will be overwritten on the next `tuist generate` run.

Applied to files:

  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService.xcscheme
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService-Stage.xcscheme
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService-Prod.xcscheme
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Debug.xcscheme
  • Projects/Core/Domain/Entity/Entity.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search-Stage.xcscheme
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Stage.xcscheme
  • MusicBandscape.xcworkspace/xcshareddata/xcschemes/MusicBandscape-Workspace.xcscheme
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search-Prod.xcscheme
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Prod.xcscheme
  • Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search.xcscheme
  • Projects/Presentation/Search/Project.swift
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab.xcscheme
  • Projects/Core/Data/DataInterface/DataInterface.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/contents.xcworkspacedata
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService-Debug.xcscheme
  • Projects/App/MusicBandscapeTests/Sources/MusicBandscapeTestPlan.xctestplan
  • Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search-Debug.xcscheme
  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.pbxproj
  • Projects/App/MusicBandscape.xcodeproj/project.pbxproj
📚 Learning: 2025-10-28T02:26:06.959Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/Sources/API/MusicSearchAPI.swift:14-22
Timestamp: 2025-10-28T02:26:06.959Z
Learning: In the MusicBandscape project's API layer (Projects/Core/Data/API/Sources/API/MusicSearchAPI.swift), the MusicSearchAPI.description property intentionally returns empty strings because the main API paths are already defined in MusicScapeDomain.url ("search" and "lookup"). The description property is designed to optionally append additional path segments when needed, following the pattern: finalURL = domain.url + urlPath. Empty strings are valid when no additional path segment is required.

Applied to files:

  • Projects/Core/Data/DataInterface/Sources/MusicSearchRepositoryProtocol.swift
  • Projects/Core/Domain/DomainInterface/Sources/MusicSearchUseCaseProtocol.swift
  • Projects/Core/Domain/UseCase/UseCaseTests/Sources/MusicSearchUseCaseTests.swift
  • Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift
  • Projects/Presentation/Search/Sources/Main /View/Component/SearchResultItem.swift
  • Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift
  • Projects/Core/Data/NetworkService/Sources/MusicSearchService.swift
  • Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift
  • Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift
📚 Learning: 2025-10-28T02:26:13.122Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj:614-624
Timestamp: 2025-10-28T02:26:13.122Z
Learning: project.pbxproj files in the MusicBandscape repository are auto-generated by Tuist and should not be manually edited. Any configuration changes should be made in the Tuist configuration files (e.g., Project.swift) instead.

Applied to files:

  • Projects/Core/Domain/Entity/Entity.xcodeproj/project.pbxproj
  • Projects/Presentation/Home/Home.xcodeproj/project.pbxproj
  • Projects/Presentation/Presentation/Presentation.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/xcshareddata/xcschemes/MusicBandscape-Workspace.xcscheme
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/Project.swift
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Project.swift
  • Projects/Core/Data/DataInterface/DataInterface.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/contents.xcworkspacedata
  • Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj
  • Projects/App/MusicBandscapeTests/Sources/MusicBandscapeTestPlan.xctestplan
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.pbxproj
  • Projects/App/MusicBandscape.xcodeproj/project.pbxproj
  • Projects/Core/Domain/DomainInterface/DomainInterface.xcodeproj/project.pbxproj
📚 Learning: 2025-10-28T02:24:19.454Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/API.xcodeproj/project.pbxproj:612-617
Timestamp: 2025-10-28T02:24:19.454Z
Learning: In the MusicBandscape project, .pbxproj files (Xcode project files) are auto-generated by Tuist. Build configuration settings like OTHER_SWIFT_FLAGS and OTHER_CFLAGS in these files should not be flagged as manual coding issues, as they are managed by Tuist's project generation logic.

Applied to files:

  • Projects/Core/Domain/Entity/Entity.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/xcshareddata/xcschemes/MusicBandscape-Workspace.xcscheme
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Project.swift
  • Projects/Core/Data/DataInterface/DataInterface.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/contents.xcworkspacedata
  • Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.pbxproj
  • Projects/App/MusicBandscape.xcodeproj/project.pbxproj
  • Projects/Core/Domain/DomainInterface/DomainInterface.xcodeproj/project.pbxproj
📚 Learning: 2025-10-28T02:29:01.028Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Network/Foundations/Foundations.xcodeproj/project.pbxproj:586-592
Timestamp: 2025-10-28T02:29:01.028Z
Learning: In the MusicBandscape repository, .xcodeproj/project.pbxproj files are auto-generated by Tuist. Build settings including plugin flags (e.g., LogMacro plugin loading) should not be manually edited in pbxproj files, as they will be overwritten. Any configuration changes must be made in Tuist manifest files (Project.swift) instead.

Applied to files:

  • Projects/Core/Domain/Entity/Entity.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/xcshareddata/xcschemes/MusicBandscape-Workspace.xcscheme
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj
  • Projects/Presentation/Search/Derived/InfoPlists/Search-Prod-Info.plist
  • Projects/Presentation/RootTab/Project.swift
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Prod.xcscheme
  • Projects/Presentation/Search/Project.swift
  • Projects/Core/Data/DataInterface/DataInterface.xcodeproj/project.pbxproj
  • MusicBandscape.xcworkspace/contents.xcworkspacedata
  • Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Stage-Info.plist
  • Projects/App/MusicBandscapeTests/Sources/MusicBandscapeTestPlan.xctestplan
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/RootTab.xcodeproj/project.pbxproj
  • Projects/App/MusicBandscape.xcodeproj/project.pbxproj
  • Projects/Core/Domain/DomainInterface/DomainInterface.xcodeproj/project.pbxproj
📚 Learning: 2025-10-28T02:24:04.787Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/API.xcodeproj/project.pbxproj:518-519
Timestamp: 2025-10-28T02:24:04.787Z
Learning: In this project, Tuist automatically manages dependency resources including framework bundles (e.g., Alamofire_Alamofire.bundle). Resource copying configurations that appear only in test targets in the .pbxproj file are intentionally managed by Tuist's build system and do not require manual configuration in other targets.

Applied to files:

  • Projects/Core/Core/Core.xcodeproj/project.pbxproj
  • Projects/Presentation/Presentation/Presentation.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/Project.swift
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Core/Data/NetworkService/NetworkService.xcodeproj/project.pbxproj
  • Projects/App/MusicBandscape.xcodeproj/project.pbxproj
📚 Learning: 2025-10-23T01:45:36.632Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 4
File: Projects/Shared/DesignSystem/Derived/Sources/TuistAssets+DesignSystemDebug.swift:35-44
Timestamp: 2025-10-23T01:45:36.632Z
Learning: Tuist-generated files (identified by header comment "Generated using tuist — https://github.com/tuist/tuist") should not be flagged for manual modification, as changes will be overwritten on regeneration. These files are located in Derived/ directories and include asset, bundle, and configuration files.

Applied to files:

  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Prod-Info.plist
  • Projects/Core/Domain/UseCase/UseCase.xcodeproj/project.pbxproj
  • Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Stage-Info.plist
🧬 Code graph analysis (24)
Projects/Presentation/Search/Sources/Main /View/Component/TrendingCard.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
Projects/Core/Data/DataInterface/Sources/MusicSearchRepositoryProtocol.swift (3)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)
  • searchMedia (30-37)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (1)
  • searchMedia (31-45)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (1)
  • searchMedia (32-43)
Projects/Core/Domain/DomainInterface/Sources/MusicSearchUseCaseProtocol.swift (3)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)
  • searchMedia (30-37)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (1)
  • searchMedia (31-45)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (2)
  • searchMedia (32-43)
  • getCategoryCount (45-61)
Projects/Core/Domain/UseCase/UseCaseTests/Sources/MusicSearchUseCaseTests.swift (3)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (2)
  • getCategoryCount (45-61)
  • searchMedia (32-43)
Projects/Core/Data/Model/Sources/ITunesSearchResponseDTO.swift (1)
  • mock (75-101)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)
  • searchMedia (30-37)
Projects/Presentation/Search/Sources/Main /View/Component/NoResultsView.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (5)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)
  • searchMedia (30-37)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (1)
  • searchMedia (31-45)
Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (2)
  • searchMedia (63-65)
  • getCategoryCount (67-69)
Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (2)
  • searchMedia (49-51)
  • getCategoryCount (53-55)
Projects/Core/Domain/Entity/Sources/Mapper/Extension+ITunesTrack.swift (2)
  • toDomain (14-52)
  • toDomain (57-59)
Projects/Presentation/Search/Sources/Main /View/Component/TrendingSection.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
Projects/Presentation/Search/Sources/Main /View/Component/SearchBar.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
Projects/Presentation/Detail/Sources/View/Component/NavigationArrowButton.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (1)
  • pretendardFont (43-46)
Projects/Presentation/Search/Sources/Main /View/Component/SearchResultItem.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (4)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (3)
  • searchMusic (27-30)
  • searchMedia (32-43)
  • getCategoryCount (45-61)
Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (4)
  • searchMusic (41-43)
  • searchMedia (49-51)
  • getCategoryCount (53-55)
  • stub (78-98)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)
  • searchMedia (30-37)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (1)
  • searchMedia (31-45)
Projects/Core/Domain/Entity/Sources/MusicItemEntity.swift (1)
Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (1)
  • all (140-149)
Projects/Presentation/Search/Sources/Main /View/Component/SearchCategoryFilter.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
Projects/Presentation/RootTab/Sources/Reducer/RootTabReducer.swift (1)
Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift (1)
  • handleViewAction (105-179)
Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift (3)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (1)
  • searchMedia (31-45)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (2)
  • searchMedia (32-43)
  • getCategoryCount (45-61)
Projects/Core/Domain/Entity/Sources/MusicItemEntity.swift (2)
  • filterByCategory (96-109)
  • sortedByLatest (117-126)
Projects/Presentation/RootTab/Project.swift (1)
Plugins/ProjectTemplatePlugin/ProjectDescriptionHelpers/Project+Templete/Project+Template.swift (1)
  • makeAppModule (11-111)
Projects/Core/Data/Repository/RepositoryTests/Sources/MockMusicSearchRepositoryTests.swift (1)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (2)
  • setResult (21-23)
  • searchMedia (30-37)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (4)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (1)
  • searchMedia (31-45)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (1)
  • searchMedia (32-43)
Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (1)
  • searchMedia (63-65)
Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (1)
  • searchMedia (49-51)
Projects/Presentation/Search/Sources/Coordinator/Reducer/SearchCoordinator.swift (1)
Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift (1)
  • handleViewAction (105-179)
Projects/Presentation/Search/Project.swift (1)
Plugins/ProjectTemplatePlugin/ProjectDescriptionHelpers/Project+Templete/Project+Template.swift (1)
  • makeAppModule (11-111)
Projects/Presentation/Search/Sources/Main /View/Component/RecentSearchesSection.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (4)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (3)
  • searchMusic (27-30)
  • searchMedia (32-43)
  • getCategoryCount (45-61)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)
  • searchMedia (30-37)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (1)
  • searchMedia (31-45)
Projects/Core/Domain/Entity/Sources/MusicItemEntity.swift (1)
  • filterByCategory (96-109)
Projects/Presentation/Search/Sources/Main /View/SearchView.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (4)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (2)
  • searchMusic (27-30)
  • searchMedia (32-43)
Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (2)
  • searchMusic (59-61)
  • searchMedia (63-65)
Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (2)
  • searchMusic (41-43)
  • searchMedia (49-51)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)
  • searchMedia (30-37)
🪛 SwiftLint (0.57.0)
Projects/Core/Domain/Entity/Sources/MediaType.swift

[Warning] 11-11: String enum values can be omitted when they are equal to the enumcase name

(redundant_string_enum_value)


[Warning] 12-12: String enum values can be omitted when they are equal to the enumcase name

(redundant_string_enum_value)


[Warning] 13-13: String enum values can be omitted when they are equal to the enumcase name

(redundant_string_enum_value)


[Warning] 14-14: String enum values can be omitted when they are equal to the enumcase name

(redundant_string_enum_value)

Projects/Presentation/RootTab/Sources/Reducer/RootTabReducer.swift

[Warning] 37-37: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)

Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift

[Warning] 46-46: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 59-59: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 64-64: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 69-69: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 32-32: Initializing an optional variable with nil is redundant

(redundant_optional_initialization)

Projects/Presentation/RootTab/Project.swift

[Warning] 5-5: Imports should be unique

(duplicate_imports)

Projects/Presentation/Search/Project.swift

[Warning] 5-5: Imports should be unique

(duplicate_imports)

🔇 Additional comments (61)
Projects/Presentation/RootTab/RootTab.xcodeproj/project.xcworkspace/contents.xcworkspacedata (1)

1-7: 워크스페이스 파일의 구조가 올바릅니다.

Xcode 워크스페이스 XML 파일이 표준 형식으로 올바르게 작성되었습니다. 그러나 이 파일은 RootTab 모듈을 위한 인프라 구조만 제공할 뿐, 실제 검색 화면 기능 구현은 포함하지 않습니다.

PR 목표에 명시된 다음 항목들의 구현이 필요한데, 현재 제공된 파일에서는 확인할 수 없습니다:

  • 검색 화면 구현
  • 검색 결과 없음 상태 UI 구현
  • 검색 API 연결

Tuist 관리형 프로젝트의 경우 워크스페이스 파일이 일반적으로 자동 생성되므로, 수동으로 XML을 수정할 필요가 없습니다. 대신 Project.swift 매니페스트 파일에서 구조를 정의하는 것이 권장됩니다.

검색 화면의 실제 구현 코드(Swift 소스 파일, UI 컴포넌트, 상태 관리 로직)가 이 PR에 포함되어 있는지 확인해 주시기 바랍니다.

Projects/Presentation/RootTab/RootTabTests/Sources/Test.swift (1)

1-8: 테스트 파일이 비어있습니다

이 파일은 RootTabTests 디렉토리에 위치한 테스트 파일이지만 실제 테스트 코드가 없습니다.

다음 중 하나를 고려하세요:

  • 필요한 테스트 케이스 추가
  • 파일이 필요하지 않다면 제거
  • 향후 작업을 위한 플레이스홀더라면 TODO 주석 추가
Projects/Presentation/Search/Search.xcodeproj/project.xcworkspace/contents.xcworkspacedata (1)

1-7: 표준 Xcode 워크스페이스 파일이 올바르게 생성되었습니다.

이 파일은 Search.xcodeproj를 위한 표준 Xcode 워크스페이스 설정 파일입니다. Tuist 관리 프로젝트에서 자동 생성되는 보일러플레이트 코드이며, 내용이 정확합니다.

Projects/Presentation/Presentation/Sources/Exported/PresentationExported.swift (1)

13-14: 변경 사항이 올바르게 보이며 PR 목표와 일치합니다.

Search 및 RootTab 모듈의 re-export가 검색 화면 구현 및 탭바 연결 목표와 일치합니다. 코드 패턴이 기존 import 구문들과 일관성 있게 유지되고 있습니다.

빌드 시 다음 사항을 확인해 주세요:

  • Search 및 RootTab 모듈이 정상적으로 빌드되는지 확인
  • 순환 의존성이 발생하지 않는지 확인
Projects/Presentation/Detail/Sources/View/DetailView.swift (1)

30-30: Store 기반 네비게이션으로의 전환이 올바르게 적용되었습니다.

ScalingHeaderDetailViewstore 파라미터를 전달하는 것은 Composable Architecture 패턴과 일치하며, 이전 클로저 기반 접근 방식보다 더 나은 아키텍처입니다.

Projects/Presentation/Detail/Sources/View/Component/ScalingHeaderDetailView.swift (2)

10-10: Composable Architecture 통합이 올바르게 구현되었습니다.

ComposableArchitecture import와 store 프로퍼티 추가는 클로저 기반에서 Store 기반 네비게이션으로의 전환을 지원하는 적절한 변경입니다.

Also applies to: 17-17


19-31: 이니셜라이저 시그니처 변경이 아키텍처 리팩토링과 일치합니다.

backAction 클로저를 store 파라미터로 교체한 것은 Composable Architecture 패턴을 올바르게 적용한 것입니다. 이는 보다 예측 가능하고 테스트 가능한 네비게이션 플로우를 제공합니다.

Projects/App/MusicBandscapeTests/Sources/MusicBandscapeTestPlan.xctestplan (2)

52-55: SearchTests 추가가 PR 목표와 일치합니다!

검색 화면 구현을 위한 테스트 타겟이 적절하게 추가되었습니다. 설정이 다른 프레젠테이션 레이어 테스트들과 일관된 패턴을 따르고 있습니다.


17-20: 테스트 타겟 재정렬이 SearchTests 추가와 무관한지 확인이 필요합니다.

xctestplan 파일의 테스트 타겟 순서가 변경되었습니다. SearchTests 추가 외에도 DetailTests, UseCaseTests, RepositoryTests, SplashTests의 순서가 재정렬되었습니다.

재확인 사항:

  • 이 테스트 타겟들의 재정렬이 SearchTests 기능 구현에 필요한 변경인지
  • 단순 정렬 정리인지, 아니면 의도적인 테스트 구조 개선인지

이 파일은 Tuist에 의해 자동 생성되지 않으므로 개발자가 수동으로 유지하고 있습니다. 변경사항이 의도적이라면 커밋 메시지나 설명에 반영하는 것이 좋겠습니다.

README.md (4)

114-121: 구현 미리보기 섹션 추가로 문서 가독성 향상

검색 화면 추가에 맞춰 실제 스크린샷을 포함하여 프로젝트의 구현 진행 상황을 명확히 시각화했습니다. 표 형식이 명확하고 읽기 좋습니다.

스크린샷 파일(Docs/Screenshots/home.png, Docs/Screenshots/search.png)이 실제로 저장소에 커밋되었는지 확인하세요.


168-180: 메모리 관리 분석 섹션이 운영 가이드 역할 수행

Instruments 도구를 활용한 구체적인 검사 절차와 "누수 및 순환 참조 미검출" 결과가 프로젝트의 신뢰성을 높입니다. 특히 라인 179의 "새 피처 추가 시 Instruments 재실행" 권장사항은 향후 메모리 안정성 유지에 실질적인 지침을 제공합니다.


111-111: 모든 이미지 파일이 저장소에 정상 포함되어 있습니다.

검증 결과, README.md에서 참조하는 모든 이미지 파일이 존재합니다:

  • graph.png (저장소 루트)
  • Docs/Screenshots/home.png
  • Docs/Screenshots/search.png

절대 경로(/graph.png)는 GitHub README에서 저장소 루트 기준으로 정상 작동하므로, 코드 변경사항에 문제가 없습니다.


138-167: 설계 기록의 모든 기능이 실제 코드에 구현되어 있습니다

검증 결과, README의 5가지 주요 설계 사항이 모두 구현되었습니다:

  • 계절별 자동 로딩: HomeReducer에서 handleAsyncAction.merge(MusicSeason.allCases.map { .send(.async(.fetchMusic($0))) })로 5개 계절을 병렬 요청하며, handleInnerAction에서 sorted { releaseDateValue 비교 }로 최신순 정렬 후 Set<MusicItem.ID> 기반 중복 제거를 구현했습니다.

  • 검색 카테고리 통계: SearchCategoryFilter에서 countForCategory 메서드로 각 카테고리별 결과 수를 실시간 계산하고 CategoryTab에 배지로 표시합니다.

  • 최근/추천 검색: RecentSearchesSection.swift로 최근 검색 UI를 구현했으며, SearchReducer에서 selectTrendingItem 액션을 정의했습니다.

  • 상세 공유 상태: HomeReducer와 SearchReducer에서 @Shared(.inMemory("MusicItem"))로 동일한 저장소 사용.

  • 테스트 강화: SearchReducerTests.swift와 HomeReducerTests.swift가 존재하며, getCategoryCount 로직 검증이 구현되어 있습니다.

Projects/Core/Data/NetworkService/Project.swift (1)

8-9: 모듈 이름 변경이 적절합니다.

Service에서 NetworkService로의 명확한 이름 변경이 코드의 가독성을 향상시킵니다.

Projects/Core/Data/Repository/Project.swift (1)

15-15: 의존성 업데이트가 올바릅니다.

NetworkService 모듈로의 의존성 변경이 모듈 리팩토링과 일관성을 유지합니다.

Projects/App/Sources/View/ContentView.swift (1)

57-68: 프리뷰 추가가 개발 생산성을 향상시킵니다.

SearchView와 RootTabBarView에 대한 프리뷰 블록이 올바르게 구현되었으며, 기존 프리뷰 패턴과 일관성을 유지합니다.

Projects/Presentation/RootTab/Derived/InfoPlists/RootTabTests-Info.plist (1)

1-22: 자동 생성된 파일입니다.

이 파일은 Tuist에 의해 자동 생성되므로 수동으로 수정할 필요가 없습니다. Based on learnings.

Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Debug-Info.plist (1)

1-22: 자동 생성된 파일입니다.

이 파일은 Tuist에 의해 자동 생성되므로 수동으로 수정할 필요가 없습니다. Based on learnings.

Projects/Core/Domain/Entity/Sources/TrendingItem.swift (1)

10-17: 구현이 올바릅니다.

TrendingItem 구조체가 Identifiable 및 Hashable 프로토콜을 적절히 준수하며, UUID는 각 인스턴스 생성 시 고유하게 할당됩니다.

Projects/Presentation/Search/Derived/InfoPlists/Search-Debug-Info.plist (1)

1-22: 자동 생성된 파일입니다.

이 파일은 Tuist에 의해 자동 생성되므로 수동으로 수정할 필요가 없습니다. Based on learnings.

Projects/Presentation/RootTab/Derived/InfoPlists/RootTab-Info.plist (1)

1-22: 자동 생성된 파일입니다.

이 파일은 Tuist에 의해 자동 생성됩니다. 설정 변경이 필요한 경우 해당 Project.swift 파일을 수정해야 합니다.

Based on learnings

Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab-Prod.xcscheme (1)

1-77: 자동 생성된 스킴 파일입니다.

이 파일은 Tuist에 의해 자동 생성됩니다. 스킴 설정 변경이 필요한 경우 Tuist manifest 파일(Project.swift)에서 수정해야 합니다.

Based on learnings

Projects/Presentation/Search/Sources/Main /View/Component/SearchBackground.swift (1)

11-52: 잘 구현되었습니다.

다층 그라디언트 배경 컴포넌트가 적절하게 구현되었습니다. blend mode와 blur 효과를 활용한 시각적 깊이감이 좋습니다.

Projects/Presentation/RootTab/RootTab.xcodeproj/xcshareddata/xcschemes/RootTab.xcscheme (1)

1-87: 자동 생성된 스킴 파일입니다.

이 파일은 Tuist에 의해 자동 생성됩니다. 스킴 설정 변경이 필요한 경우 Tuist manifest 파일(Project.swift)에서 수정해야 합니다.

Based on learnings

Projects/Core/Data/Repository/RepositoryTests/Sources/MockMusicSearchRepositoryTests.swift (1)

78-168: 테스트 커버리지가 우수합니다.

searchMedia 메서드에 대한 포괄적인 테스트 케이스가 추가되었습니다. 성공/실패 시나리오, 파라미터 검증, 다양한 media/entity 조합을 모두 테스트하고 있어 좋습니다.

Projects/Core/Domain/Entity/Sources/SearchCategory.swift (1)

10-16: 잘 정의된 도메인 엔티티입니다.

검색 카테고리를 명확하게 정의한 enum입니다. CaseIterable 프로토콜 채택으로 UI에서 활용하기 좋습니다.

Projects/Core/Data/Repository/Sources/Detail/MusicDetailRepository.swift (1)

10-10: LGTM! 모듈 리팩토링이 올바르게 적용되었습니다.

Service에서 NetworkService로의 import 변경이 PR 전반의 모듈 재구성과 일치합니다.

Projects/Presentation/Home/Sources/Main /View/HomeView.swift (1)

61-63: LGTM! 검색 화면으로의 네비게이션이 올바르게 연결되었습니다.

SearchBarView에 tapSearch 액션을 처리하는 trailing closure가 추가되어 검색 화면으로의 이동이 구현되었습니다.

Projects/Presentation/Home/Sources/Main /Reducer/HomeReducer.swift (2)

56-56: LGTM! 검색 네비게이션 액션이 추가되었습니다.

tapSearch 액션이 NavigationAction에 추가되어 검색 화면으로의 이동을 지원합니다.


148-149: LGTM! 네비게이션 핸들링이 적절합니다.

tapSearch 액션이 .none을 반환하는 것이 올바릅니다. 실제 네비게이션 로직은 HomeCoordinator에서 처리되는 패턴입니다.

Projects/Core/Data/DataInterface/Sources/MusicSearchRepositoryProtocol.swift (1)

13-13: LGTM! 미디어 검색을 위한 프로토콜 메서드가 추가되었습니다.

searchMedia 메서드가 추가되어 미디어 타입과 엔티티별 검색을 지원합니다. 관련된 구현체(MusicSearchRepository, MockMusicSearchRepository)와 use case에서도 일관되게 구현되었습니다.

Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)

25-28: 변경사항 승인

fetchMusic 메서드가 쿼리를 기록하고 결과를 반환하도록 올바르게 업데이트되었습니다.

Projects/Core/Domain/Entity/Sources/Mapper/Extension+ITunesTrack.swift (2)

15-22: 필수 필드 검증 승인

필수 필드(trackId, trackName, artistName, artworkUrl100)에 대한 guard 문이 올바르게 추가되어 불완전한 데이터가 도메인으로 전파되는 것을 방지합니다.


47-50: 기본값 설정 확인

aboutAlbumInfo의 폴백 체인(collectionCensoredName ?? collectionName ?? "")이 의도한 우선순위인지 확인이 필요합니다. 일반적으로 censored 버전이 우선시되어야 하므로 현재 순서가 적절해 보입니다.

Projects/Presentation/Home/Sources/Coordinator/Reducer/HomeCoordinator.swift (3)

37-37: 탭바 전환 케이스 추가 승인

switchTapBar View 케이스가 추가되어 검색 탭으로의 네비게이션을 지원합니다. 상위 수준의 RootTabReducer에서 처리될 것으로 보입니다.


73-74: 라우팅 로직 승인

.tapSearch 액션이 .switchTapBar 뷰 액션을 전송하도록 올바르게 연결되었습니다.


95-96: switchTapBar 구현 확인

현재 switchTapBar 케이스가 .none을 반환하는 no-op으로 구현되어 있습니다. 이는 상위 RootTabReducer에서 처리될 것으로 예상되지만, 이 동작이 의도된 것인지 확인해주세요.

Projects/Presentation/Presentation/Project.swift (1)

12-15: 모듈 의존성 업데이트 승인

Presentation 모듈이 새로운 RootTab 모듈을 참조하도록 올바르게 업데이트되었습니다. 이는 PR의 전체적인 모듈 재구성과 일치합니다.

Projects/Presentation/Home/Home.xcodeproj/project.pbxproj (1)

98-98: Tuist 관리 파일 - 검토 생략

이 파일은 Tuist에 의해 자동 생성되므로 수동 검토가 필요하지 않습니다. Service.framework에서 NetworkService.framework로의 변경사항은 Project.swift 매니페스트 파일의 의존성 변경에 따라 자동으로 생성되었습니다.

Based on learnings

Also applies to: 263-263, 383-383, 452-452

Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (2)

9-9: Import 업데이트 승인

Service에서 NetworkService로의 import 변경이 올바르게 반영되었습니다.


31-45: searchMedia 메서드 구현 승인

새로운 searchMedia 메서드가 잘 구현되어 유연한 미디어 타입 검색을 지원합니다. fetchMusic과 일관된 패턴을 따르고 있습니다.

Projects/Presentation/Search/Sources/Main /View/Component/TrendingCard.swift (1)

15-42: 카드 UI 구현 승인

깔끔한 SwiftUI 구현으로 다음 요소들이 잘 적용되었습니다:

  • 적절한 그림자와 라운드 코너
  • Design System 폰트 사용
  • 일관된 스타일링
Projects/Presentation/Search/Derived/InfoPlists/Search-Stage-Info.plist (1)

1-22: Tuist 관리 파일 - 검토 생략

이 파일은 Derived/InfoPlists/ 디렉토리에 위치하며 Tuist에 의해 자동 생성됩니다. 설정 변경이 필요한 경우 해당하는 Project.swift 파일을 수정해야 합니다.

Based on learnings

Projects/Core/Domain/UseCase/UseCaseTests/Sources/MusicSearchUseCaseTests.swift (2)

58-104: 카테고리 카운트 테스트 커버리지가 훌륭합니다!

각 카테고리별 정확한 개수 검증과 빈 배열 엣지 케이스까지 커버하고 있어 테스트 품질이 우수합니다.


106-157: searchMedia 테스트 커버리지가 잘 구성되어 있습니다!

성공/실패 경로와 다양한 미디어 타입에 대한 파라미터 검증이 포함되어 있어, 새로운 searchMedia API에 대한 신뢰성 있는 테스트를 제공합니다.

Plugins/DependencyPlugin/ProjectDescriptionHelpers/TargetDependency+Module/Modules.swift (2)

27-28: 새로운 프레젠테이션 모듈 추가가 적절합니다!

Search와 RootTab 케이스가 Presentations enum에 정확히 추가되었습니다. 이는 검색 화면 구현과 탭바 네비게이션을 위한 모듈 구조를 잘 반영하고 있습니다.


63-63: 서비스 모듈명 변경이 명확합니다!

Service에서 NetworkService로의 이름 변경은 모듈의 역할을 더 명확하게 표현합니다.

Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService.xcscheme (1)

1-87: Tuist에 의해 자동 생성된 파일입니다.

이 .xcscheme 파일은 Tuist에 의해 자동 생성되므로 수동으로 편집하지 않아야 합니다. 스킴 설정을 변경하려면 Project.swift 매니페스트 파일을 수정해야 합니다.

Based on learnings

Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (2)

32-43: 미디어 검색 메서드 구현이 우수합니다!

searchMedia 메서드가 깔끔하게 구현되었습니다:

  • 리포지토리 레이어로 검색 요청을 위임
  • DTO를 도메인 엔티티로 매핑
  • async/await를 사용한 적절한 비동기 처리

45-61: 카테고리별 카운팅 로직이 명확합니다!

getCategoryCount 메서드의 switch 문이 모든 SearchCategory 케이스를 명확하게 처리하고 있습니다. [MusicItem]의 computed properties(.musicCount, .movieCount 등)를 활용한 구현이 간결합니다.

Projects/App/Sources/View/AppView.swift (1)

25-28: 탭바 기반 네비게이션으로의 전환이 적절합니다!

Home 기반에서 TabBar 기반 네비게이션으로의 리팩토링이 깔끔하게 완료되었습니다:

  • 상태 케이스를 .home에서 .tabBar로 변경
  • scope 경로를 일관되게 업데이트
  • RootTabBarView로 올바르게 교체

이는 PR 목표인 "탭바 연결"을 잘 반영하고 있습니다.

Projects/Presentation/Home/Sources/Main /View/Component/SearchBarView.swift (2)

7-11: 액션 클로저 파라미터 추가가 훌륭합니다!

SearchBarView에 액션 클로저를 추가하여 검색 화면으로의 네비게이션을 가능하게 한 것은 좋은 설계입니다.


36-37: 탭 제스처 연동이 적절합니다!

contentShape(Rectangle())onTapGesture를 사용하여 전체 검색바 영역에서 탭을 인식하도록 구현한 것이 좋습니다.

Projects/Presentation/Search/Search.xcodeproj/xcshareddata/xcschemes/Search-Debug.xcscheme (1)

1-77: Tuist에 의해 자동 생성된 파일입니다.

이 .xcscheme 파일은 Tuist에 의해 자동 생성되므로 수동으로 편집하지 않아야 합니다. 스킴 설정 변경은 Project.swift에서 수행해야 합니다.

Based on learnings

Projects/Presentation/Search/Derived/InfoPlists/Search-Info.plist (1)

1-22: Tuist에 의해 자동 생성된 파일입니다.

Derived/InfoPlists/ 디렉토리의 Info.plist 파일은 Tuist에 의해 자동 생성됩니다. 설정 변경이 필요한 경우 Project.swift 매니페스트 파일을 수정해야 합니다.

Based on learnings

Projects/Core/Domain/DomainInterface/Sources/MusicSearchUseCaseProtocol.swift (1)

12-13: 프로토콜 확장이 일관되게 구현되었습니다!

새로운 searchMediagetCategoryCount 메서드 요구사항이 프로토콜에 추가되었고, MusicSearchUseCase.swift의 구현과 정확히 일치합니다. API 설계가 깔끔하고 명확합니다.

Projects/Presentation/Search/Sources/Main /View/Component/RecentSearchesSection.swift (1)

11-79: 구현이 깔끔합니다!

최근 검색어 섹션의 구현이 잘 되어 있습니다:

  • 빈 상태 처리가 적절함
  • 디자인 시스템 활용
  • Preview를 통한 개발 편의성 제공
Projects/App/Sources/Reducer/AppReducer.swift (1)

18-18: 아키텍처 리팩토링이 일관되게 적용되었습니다

Home 기반 구조에서 RootTab 기반 탭바 구조로의 전환이 올바르게 구현되었습니다:

  • State와 Action enum 케이스 업데이트
  • Reducer 조합 업데이트
  • 초기화 로직 업데이트

모든 변경사항이 일관성 있게 적용되었습니다.

Also applies to: 38-38, 57-59, 70-70

Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (2)

31-69: 테스트 스텁 확장이 적절합니다

새로운 searchMediagetCategoryCount API를 지원하도록 스텁이 확장되었으며, 기존 테스트와의 호환성을 위해 기본 구현이 제공되었습니다.


237-328: 새로운 기능에 대한 테스트 커버리지가 우수합니다

두 가지 새로운 테스트가 추가되었습니다:

  1. searchMedia_usesInjectedHandler: 핸들러 호출 및 파라미터 검증
  2. getCategoryCount_returnsCategorySpecificCounts: 모든 카테고리(.all, .music, .movies, .podcast, .etc)에 대한 카운팅 로직 검증

테스트가 포괄적이고 명확합니다.

Projects/Presentation/Search/Sources/Coordinator/View/SearchCoordinatorView.swift (1)

14-34: TCA 코디네이터 패턴이 올바르게 구현되었습니다

SearchCoordinatorView가 TCARouter를 사용하여 적절하게 구현되었습니다:

  • 라우팅 상태를 올바르게 스코프화
  • 검색 및 상세 화면으로의 네비게이션 처리
  • TCA 컨벤션을 따름

@ViewAction(for: DetailReducer.self)
public struct DetailView: View {
@Perception.Bindable public var store: StoreOf<DetailReducer>
@Environment(\.dismiss) var dismiss
Copy link

@coderabbitai coderabbitai bot Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

dismiss 프로퍼티 사용 여부를 확인하세요.

@Environment(\.dismiss) 프로퍼티가 선언되었지만 제공된 코드에서 사용되지 않는 것으로 보입니다. 이 프로퍼티가 실제로 필요한지 확인하거나, 사용하지 않는다면 제거를 고려하세요.

다음 스크립트를 실행하여 dismiss 사용 여부를 확인하세요:


🏁 Script executed:

#!/bin/bash
# Description: DetailView에서 dismiss 프로퍼티의 사용 여부 확인

rg -n "dismiss" --type=swift Projects/Presentation/Detail/Sources/View/DetailView.swift -C 3

Length of output: 263



---

🏁 Script executed:

```shell
#!/bin/bash
# Description: DetailView 전체 파일에서 dismiss의 모든 사용 위치 확인

rg -n "dismiss" --type=swift Projects/Presentation/Detail/Sources/View/DetailView.swift

Length of output: 40


dismiss 프로퍼티 제거하세요.

검증 결과, @Environment(\.dismiss) var dismiss는 선언되었지만 DetailView.swift 파일 내 어디에서도 사용되지 않습니다. 이 사용되지 않는 프로퍼티를 제거하세요.

🤖 Prompt for AI Agents
In Projects/Presentation/Detail/Sources/View/DetailView.swift around line 18,
remove the unused property declaration "@Environment(\\.dismiss) var dismiss"
since it is declared but never referenced; delete that line, verify there are no
remaining references to dismiss in this file, and run a build or SwiftLint check
to ensure no unused-symbol warnings remain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정 했어

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the current state of dismiss property in DetailView.swift
echo "=== Checking for dismiss property declaration ==="
rg -n "@Environment.*dismiss" Projects/Presentation/Detail/Sources/View/DetailView.swift

echo -e "\n=== Checking for any usage of dismiss ==="
rg -n "\bdismiss\b" Projects/Presentation/Detail/Sources/View/DetailView.swift

echo -e "\n=== Full context around line 18 ==="
cat Projects/Presentation/Detail/Sources/View/DetailView.swift | head -n 25 | tail -n 15

Length of output: 547


@Roy-wonji, 확인해보니 dismiss 프로퍼티가 아직 코드에 남아있습니다.

현재 Line 18에 다음과 같이 선언되어 있으며, 파일 내에서 사용되지 않고 있습니다:

@Environment(\.dismiss) var dismiss

수정하신 내용을 커밋하고 푸시하셨는지 확인해주세요. 만약 로컬에서만 수정하셨다면, 변경사항을 푸시해주시기 바랍니다. 🙏


🧬 Code Graph Analysis Results

<filename: Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift, lines 22-24>

public func body(content: Content) -> some View {
    return content.font(.custom("PretendardVariable-\(family)", fixedSize: size))
}

<filename: Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift, lines 43-46>

public static func pretendardFont(family: PretendardFontFamily, size: CGFloat) -> Font{
    let font = Font.custom("PretendardVariable-\(family)", size: size)
    return font
  }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정 했어

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check current state of dismiss property in DetailView.swift

echo "=== Checking for @Environment dismiss declaration ==="
rg -n "@Environment.*dismiss" Projects/Presentation/Detail/Sources/View/DetailView.swift || echo "No @Environment dismiss found"

echo -e "\n=== Checking for any usage of 'dismiss' keyword ==="
rg -n "\bdismiss\b" Projects/Presentation/Detail/Sources/View/DetailView.swift || echo "No dismiss usage found"

echo -e "\n=== Showing lines 15-20 for context ==="
sed -n '15,20p' Projects/Presentation/Detail/Sources/View/DetailView.swift

Length of output: 405


@Roy-wonji, 확인 완료했습니다! 👍

사용되지 않던 @Environment(\.dismiss) var dismiss 프로퍼티가 성공적으로 제거되었습니다. 코드가 깔끔하게 정리되었네요. 수고하셨습니다! 🎉


🧬 Code Graph Analysis Results
  • Filename: Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift
    Lines: 22-24
    Content:

    public func body(content: Content) -> some View {
      return content.font(.custom("PretendardVariable-\(family)", fixedSize: size))
    }
    
  • Filename: Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift
    Lines: 43-46
    Content:

    public static func pretendardFont(family: PretendardFontFamily, size: CGFloat) -> Font{
      let font = Font.custom("PretendardVariable-\(family)", size: size)
      return font
    }
    

import ProjectDescription
import DependencyPlugin
import ProjectTemplatePlugin
import ProjectTemplatePlugin
Copy link

@coderabbitai coderabbitai bot Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

중복된 import 제거 필요

ProjectTemplatePlugin이 두 번 import되고 있습니다. 중복된 import를 제거해주세요.

다음과 같이 수정하세요:

 import Foundation
 import ProjectDescription
 import DependencyPlugin
 import ProjectTemplatePlugin
-import ProjectTemplatePlugin
 import DependencyPackagePlugin
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import ProjectTemplatePlugin
import Foundation
import ProjectDescription
import DependencyPlugin
import ProjectTemplatePlugin
import DependencyPackagePlugin
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 5-5: Imports should be unique

(duplicate_imports)

🤖 Prompt for AI Agents
In Projects/Presentation/RootTab/Project.swift around line 5, the import of
ProjectTemplatePlugin is duplicated; remove the redundant import so only a
single import ProjectTemplatePlugin statement remains.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정 했어

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Roy-wonji 수정 감사합니다! 중복된 import가 제거되어 코드가 깔끔해졌네요. 👍


🧠 Learnings used
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Network/Foundations/Foundations.xcodeproj/project.pbxproj:586-592
Timestamp: 2025-10-28T02:29:01.028Z
Learning: In the MusicBandscape repository, .xcodeproj/project.pbxproj files are auto-generated by Tuist. Build settings including plugin flags (e.g., LogMacro plugin loading) should not be manually edited in pbxproj files, as they will be overwritten. Any configuration changes must be made in Tuist manifest files (Project.swift) instead.

Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 4
File: Projects/Presentation/Presentation/Presentation.xcodeproj/project.pbxproj:85-114
Timestamp: 2025-10-23T01:43:01.591Z
Learning: In Tuist-managed iOS projects (identified by Tuist/ directory, Project.swift manifest files, and Tuist references in build settings), the .xcodeproj/project.pbxproj files are auto-generated and should not be manually edited. Build phases including 'Dependencies' Copy Files phases are generated by Tuist based on the Project.swift manifests, and manual changes will be overwritten on the next `tuist generate` run. Do not flag or suggest manual modifications to pbxproj files in Tuist projects.

Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj:614-624
Timestamp: 2025-10-28T02:26:13.122Z
Learning: project.pbxproj files in the MusicBandscape repository are auto-generated by Tuist and should not be manually edited. Any configuration changes should be made in the Tuist configuration files (e.g., Project.swift) instead.

Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/Derived/InfoPlists/API-Stage-Info.plist:17-20
Timestamp: 2025-10-28T02:24:45.154Z
Learning: In Tuist-based projects, files under `Derived/` or `Derived/InfoPlists/` directories are auto-generated by Tuist and should not be manually edited. Any configuration changes should be made in the corresponding Project.swift files instead.

Comment on lines +12 to +13
struct TrendingCard: View {
let item: TrendingItem
Copy link

@coderabbitai coderabbitai bot Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

접근 제어 수정 필요

TrendingCard 구조체와 item 프로퍼티에 public 접근 제어자가 누락되어 있습니다. 다른 모듈에서 이 컴포넌트를 사용하려면 public으로 선언되어야 합니다.

-struct TrendingCard: View {
-  let item: TrendingItem
+public struct TrendingCard: View {
+  public let item: TrendingItem
+
+  public init(item: TrendingItem) {
+    self.item = item
+  }
🤖 Prompt for AI Agents
In Projects/Presentation/Search/Sources/Main /View/Component/TrendingCard.swift
around lines 12–13, the TrendingCard struct and its item property are missing
public access control which prevents usage from other modules; mark the struct
as public and the item property as public, and add a public initializer (public
init(item: TrendingItem)) so the component and its memberwise initializer are
accessible from other modules.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정 했어

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Roy-wonji, 수정해 주셔서 감사합니다! 👍

이제 TrendingCard가 다른 모듈에서 정상적으로 사용될 수 있습니다.

  (\___/)
  (='.'=)  Good work!
  (")_(")

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift (1)

168-179: 검색 취소 누락으로 인한 레이스 조건

사용자가 Cancel/지우기 버튼을 눌러 .clearSearch가 호출되더라도 .cancel(id: CancelID.searchMedia)가 실행되지 않고 state.isSearching도 그대로라서, 진행 중이던 검색 결과가 도착하면 비워둔 화면이 다시 채워집니다. 동시에 로딩 플래그도 계속 true라 UI가 불안정해집니다. .searchTextChanged에서 비슷한 정리를 이미 해주셨듯이, .clearSearch에서도 동일하게 취소와 상태 초기화를 해 주세요.

     case .clearSearch:
       state.searchText = ""
       state.allSearchResults = []
       state.filteredSearchResults = []
       state.currentSearchQuery = ""
       state.selectedCategory = .all
       state.musicCount = 0
       state.movieCount = 0
       state.podcastCount = 0
       state.etcCount = 0
-      return .none
+      state.isSearching = false
+      return .cancel(id: CancelID.searchMedia)
🧹 Nitpick comments (1)
Projects/Presentation/RootTab/RootTabTests/Sources/Test.swift (1)

1-8: 테스트 파일에 실제 테스트 코드가 없습니다.

현재 이 파일은 헤더 주석만 포함하고 있으며, 실제 테스트 케이스나 실행 가능한 코드가 전혀 없습니다. RootTab 모듈의 테스트 커버리지를 제공하지 못하고 있으며, 빈 파일은 코드베이스를 어지럽힐 수 있습니다.

다음 중 하나를 권장합니다:

  • RootTab 기능에 대한 실제 테스트 케이스를 구현하거나
  • 현재 테스트가 필요하지 않다면 파일을 제거하세요

RootTab 모듈에 대한 테스트 케이스 구현을 도와드릴까요? 테스트해야 할 특정 기능이나 시나리오가 있다면 알려주세요.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 698c6ba and 17a0acf.

📒 Files selected for processing (14)
  • Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme (2 hunks)
  • Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (2 hunks)
  • Projects/Presentation/Detail/Sources/View/Component/ScalingHeaderDetailView.swift (2 hunks)
  • Projects/Presentation/Detail/Sources/View/DetailView.swift (1 hunks)
  • Projects/Presentation/RootTab/RootTabTests/Sources/Test.swift (1 hunks)
  • Projects/Presentation/RootTab/Sources/Reducer/MainTab.swift (1 hunks)
  • Projects/Presentation/RootTab/Sources/View/RootTabBarView.swift (1 hunks)
  • Projects/Presentation/Search/Project.swift (1 hunks)
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj (1 hunks)
  • Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/SearchResultsList.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/Component/TrendingCard.swift (1 hunks)
  • Projects/Presentation/Search/Sources/Main /View/SearchView.swift (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • Projects/Presentation/Search/Sources/Main /View/Component/SearchResultsList.swift
  • Projects/Presentation/RootTab/Sources/View/RootTabBarView.swift
  • Projects/Presentation/Search/Sources/Main /View/Component/TrendingCard.swift
  • Projects/Presentation/Search/Project.swift
  • Projects/Presentation/RootTab/Sources/Reducer/MainTab.swift
  • Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-10-30T05:07:37.049Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme:93-96
Timestamp: 2025-10-30T05:07:37.049Z
Learning: In the MusicBandscape project, .xcscheme files under xcshareddata directories are auto-generated by Tuist. Scheme configurations (including buildConfiguration settings for ArchiveAction, ProfileAction, etc.) should be modified in the Tuist manifest files (Project.swift) rather than directly editing the .xcscheme files, as manual changes will be overwritten on the next `tuist generate` run.

Applied to files:

  • Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme
📚 Learning: 2025-10-28T02:26:13.122Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj:614-624
Timestamp: 2025-10-28T02:26:13.122Z
Learning: project.pbxproj files in the MusicBandscape repository are auto-generated by Tuist and should not be manually edited. Any configuration changes should be made in the Tuist configuration files (e.g., Project.swift) instead.

Applied to files:

  • Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme
  • Projects/Presentation/RootTab/RootTabTests/Sources/Test.swift
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj
📚 Learning: 2025-10-28T02:29:01.028Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Network/Foundations/Foundations.xcodeproj/project.pbxproj:586-592
Timestamp: 2025-10-28T02:29:01.028Z
Learning: In the MusicBandscape repository, .xcodeproj/project.pbxproj files are auto-generated by Tuist. Build settings including plugin flags (e.g., LogMacro plugin loading) should not be manually edited in pbxproj files, as they will be overwritten. Any configuration changes must be made in Tuist manifest files (Project.swift) instead.

Applied to files:

  • Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj
📚 Learning: 2025-10-28T02:24:36.027Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/Derived/InfoPlists/API-Prod-Info.plist:17-18
Timestamp: 2025-10-28T02:24:36.027Z
Learning: In the MusicBandscape project, Info.plist files located in `Derived/InfoPlists/` directories are auto-generated by Tuist and should not be flagged for manual modification, including CFBundlePackageType settings.

Applied to files:

  • Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme
📚 Learning: 2025-10-28T02:24:19.454Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/API.xcodeproj/project.pbxproj:612-617
Timestamp: 2025-10-28T02:24:19.454Z
Learning: In the MusicBandscape project, .pbxproj files (Xcode project files) are auto-generated by Tuist. Build configuration settings like OTHER_SWIFT_FLAGS and OTHER_CFLAGS in these files should not be flagged as manual coding issues, as they are managed by Tuist's project generation logic.

Applied to files:

  • Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme
  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj
📚 Learning: 2025-10-23T01:43:01.591Z
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 4
File: Projects/Presentation/Presentation/Presentation.xcodeproj/project.pbxproj:85-114
Timestamp: 2025-10-23T01:43:01.591Z
Learning: In Tuist-managed iOS projects (identified by Tuist/ directory, Project.swift manifest files, and Tuist references in build settings), the .xcodeproj/project.pbxproj files are auto-generated and should not be manually edited. Build phases including 'Dependencies' Copy Files phases are generated by Tuist based on the Project.swift manifests, and manual changes will be overwritten on the next `tuist generate` run. Do not flag or suggest manual modifications to pbxproj files in Tuist projects.

Applied to files:

  • Projects/Presentation/Search/Search.xcodeproj/project.pbxproj
🧬 Code graph analysis (3)
Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (5)
Projects/Presentation/Home/HomeTests/Sources/HomeReducerTests.swift (6)
  • stub (77-96)
  • stub (100-118)
  • all (140-149)
  • searchMusic (59-61)
  • searchMedia (63-65)
  • getCategoryCount (67-69)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (3)
  • searchMusic (27-30)
  • searchMedia (32-43)
  • getCategoryCount (45-61)
Projects/Core/Data/Repository/Sources/Search/MusicSearchRepository.swift (1)
  • searchMedia (31-45)
Projects/Core/Data/Repository/Sources/Search/MockMusicSearchRepository.swift (1)
  • searchMedia (30-37)
Projects/Core/Domain/Entity/Sources/MusicItemEntity.swift (1)
  • filterByCategory (96-109)
Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift (2)
Projects/Core/Domain/UseCase/Sources/Search/MusicSearchUseCase.swift (2)
  • searchMedia (32-43)
  • getCategoryCount (45-61)
Projects/Core/Domain/Entity/Sources/MusicItemEntity.swift (2)
  • filterByCategory (96-109)
  • sortedByLatest (117-126)
Projects/Presentation/Search/Sources/Main /View/SearchView.swift (1)
Projects/Shared/DesignSystem/Sources/Font/PretendardFont.swift (2)
  • body (22-24)
  • pretendardFont (43-46)
🪛 SwiftLint (0.57.0)
Projects/Presentation/Search/Sources/Main /Reducer/SearchReducer.swift

[Warning] 46-46: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 59-59: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 64-64: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 69-69: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 32-32: Initializing an optional variable with nil is redundant

(redundant_optional_initialization)

🔇 Additional comments (9)
Projects/Presentation/Search/Search.xcodeproj/project.pbxproj (1)

1-1519: Tuist 자동 생성 파일 - 검토 불필요

이 project.pbxproj 파일은 Tuist에 의해 자동 생성된 파일입니다. 프로젝트 구조, 빌드 설정, 타겟 구성 등이 올바르게 생성되었으며, Search 모듈과 관련 타겟들(Search-Debug, Search-Prod, Search-Stage, SearchTests)이 적절히 정의되어 있습니다.

빌드 구성이나 설정 변경이 필요한 경우, 이 파일을 직접 수정하지 마시고 Tuist 매니페스트 파일(Project.swift)에서 수정해 주세요.

Based on learnings

Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme (2)

4-4: 스킴 버전 다운그레이드 확인 필요

Xcode 스킴 버전이 "1.7"에서 "1.3"으로 다운그레이드되었습니다. 이 파일은 Tuist에 의해 자동 생성되므로, Project.swift 매니페스트에서 의도적으로 변경된 것인지 확인이 필요합니다.

Based on learnings


46-49: TestPlanReference 속성 순서 변경 확인됨

TestPlanReference의 속성 순서가 변경되었습니다 (default가 reference 앞으로 이동). 이는 Tuist의 자동 생성 포맷 변경으로 보이며, 기능적 영향은 없습니다.

Based on learnings

Projects/Presentation/Detail/Sources/View/Component/ScalingHeaderDetailView.swift (3)

10-10: ComposableArchitecture import가 적절히 추가되었습니다.

Store 기반 아키텍처로 전환하기 위해 필요한 import가 올바르게 추가되었습니다.


17-17: Store 프로퍼티 추가 및 초기화가 올바르게 구현되었습니다.

클로저 기반 네비게이션에서 TCA store 기반 아키텍처로의 전환이 일관되게 구현되었습니다. 프로퍼티 선언, 초기화 파라미터, 그리고 할당이 모두 적절합니다.

Also applies to: 23-23, 29-29


57-59: 디버그 출력문이 완전히 제거되었습니다.

검증 결과, ScalingHeaderDetailView.swift 파일에서 print() 함수 호출과 🔥 이모지가 모두 검출되지 않았습니다. 이전 리뷰에서 지적한 Line 58의 디버그 출력문 print("🔥 ScalingHeaderDetailView: NavigationArrowButton 탭됨")이 성공적으로 제거되었으며, 현재 코드는 깔끔합니다.

Projects/Presentation/Detail/Sources/View/DetailView.swift (2)

29-29: Store 기반 네비게이션으로의 전환이 올바르게 적용되었습니다.

backAction 클로저 대신 store 파라미터를 전달하는 방식으로 변경되어, ScalingHeaderDetailView의 아키텍처 변경과 일관성 있게 통합되었습니다.


18-18: @Environment(\.dismiss) 프로퍼티 제거 확인 완료

검증 결과, @Environment(\.dismiss) var dismiss 프로퍼티가 DetailView에서 완전히 제거되었습니다. 선언 및 사용처 모두 제거되어 이전 리뷰 피드백이 올바르게 반영되었습니다.

Projects/Presentation/Search/SearchTests/Sources/SearchReducerTests.swift (1)

138-187: 종단 검색 플로우 테스트가 충실합니다.
검색 제출부터 로딩 상태, 최근 검색어, 결과 필터 갱신, 의존성 파라미터 검증까지 한 번에 다뤄줘서 회귀 테스트로 든든합니다.

Comment on lines +51 to +52
<Testables>
</Testables>
Copy link

@coderabbitai coderabbitai bot Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

빈 Testables 블록 - 테스트 플랜 구성 확인 필요

Testables 블록이 비어있습니다. TestPlanReference가 구성되어 있으므로 테스트는 MusicBandscapeTestPlan.xctestplan 파일에서 정의될 것으로 예상됩니다. 새로 추가된 Search 및 NetworkService 모듈에 대한 테스트 타겟이 테스트 플랜에 올바르게 포함되어 있는지 확인하세요.


🏁 Script executed:

#!/bin/bash
# 테스트 플랜 파일에서 테스트 타겟 구성 확인
cat Projects/App/MusicBandscapeTests/Sources/MusicBandscapeTestPlan.xctestplan

Length of output: 1491



---

🏁 Script executed:

```shell
#!/bin/bash
# Search for NetworkService test target in the codebase
find . -type f -name "*.xcodeproj" -o -name "*NetworkService*" | grep -i test
# Also check for any references to NetworkServiceTests
rg -i "NetworkServiceTests" --type=json -C2

Length of output: 141



---

🏁 Script executed:

```shell
#!/bin/bash
# Check NetworkService.xcodeproj scheme configuration
cat Projects/Core/Data/NetworkService/NetworkService.xcodeproj/xcshareddata/xcschemes/NetworkService.xcscheme 2>/dev/null || echo "Scheme not found"
# Also check for NetworkServiceTests in BuildActionEntries
rg "NetworkServiceTests" Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/ -A2 -B2

Length of output: 3291


NetworkServiceTests가 테스트 플랜에 누락되었습니다

SearchTests는 테스트 플랜에 포함되어 있지만, NetworkServiceTests는 누락되어 있습니다. NetworkServiceTests 타겟이 존재하고 NetworkService.xcodeproj 스킴에 올바르게 구성되어 있음에도 불구하고, MusicBandscapeTestPlan.xctestplan의 testTargets 배열에 등록되지 않았습니다.

MusicBandscapeTestPlan.xctestplan 파일에 다음 항목을 추가하세요 (SearchTests 항목 다음에):

{
  "target" : {
    "containerPath" : "container:../Core/Data/NetworkService/NetworkService.xcodeproj",
    "identifier" : "E9352438CCA76AF037B25979",
    "name" : "NetworkServiceTests"
  }
}
🤖 Prompt for AI Agents
Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme
around lines 51-52: the test plan is missing the NetworkServiceTests entry in
its testTargets array; open MusicBandscapeTestPlan.xctestplan and insert a new
testTargets entry for NetworkServiceTests (with containerPath
"container:../Core/Data/NetworkService/NetworkService.xcodeproj", identifier
"E9352438CCA76AF037B25979", name "NetworkServiceTests") immediately after the
existing SearchTests entry so the NetworkServiceTests target is registered in
the test plan.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 테스트코드를 작성을 안해서 추가 안했어

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Roy-wonji, 알겠습니다! 테스트 코드가 아직 작성되지 않아서 의도적으로 제외하신 거군요. 이는 합리적인 결정입니다.

나중에 NetworkService 모듈의 테스트 코드를 작성하실 때 테스트 플랜에 추가하시면 됩니다. 👍


🧠 Learnings used
Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/App/MusicBandscape.xcodeproj/xcshareddata/xcschemes/MusicBandscape.xcscheme:93-96
Timestamp: 2025-10-30T05:07:37.049Z
Learning: In the MusicBandscape project, .xcscheme files under xcshareddata directories are auto-generated by Tuist. Scheme configurations (including buildConfiguration settings for ArchiveAction, ProfileAction, etc.) should be modified in the Tuist manifest files (Project.swift) rather than directly editing the .xcscheme files, as manual changes will be overwritten on the next `tuist generate` run.

Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Network/Foundations/Foundations.xcodeproj/project.pbxproj:586-592
Timestamp: 2025-10-28T02:29:01.028Z
Learning: In the MusicBandscape repository, .xcodeproj/project.pbxproj files are auto-generated by Tuist. Build settings including plugin flags (e.g., LogMacro plugin loading) should not be manually edited in pbxproj files, as they will be overwritten. Any configuration changes must be made in Tuist manifest files (Project.swift) instead.

Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/Derived/InfoPlists/API-Prod-Info.plist:17-18
Timestamp: 2025-10-28T02:24:36.027Z
Learning: In the MusicBandscape project, Info.plist files located in `Derived/InfoPlists/` directories are auto-generated by Tuist and should not be flagged for manual modification, including CFBundlePackageType settings.

Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/Repository/Repository.xcodeproj/project.pbxproj:614-624
Timestamp: 2025-10-28T02:26:13.122Z
Learning: project.pbxproj files in the MusicBandscape repository are auto-generated by Tuist and should not be manually edited. Any configuration changes should be made in the Tuist configuration files (e.g., Project.swift) instead.

Learnt from: Roy-wonji
Repo: SpartCodig-iOS/MusicBandscape PR: 6
File: Projects/Core/Data/API/API.xcodeproj/project.pbxproj:612-617
Timestamp: 2025-10-28T02:24:19.454Z
Learning: In the MusicBandscape project, .pbxproj files (Xcode project files) are auto-generated by Tuist. Build configuration settings like OTHER_SWIFT_FLAGS and OTHER_CFLAGS in these files should not be flagged as manual coding issues, as they are managed by Tuist's project generation logic.

Copy link

@minneee minneee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!
이전 PR도 그렇고 지금도 PR크기가 너무 커서 리뷰 하기가 힘든 것 같아요 😭
다음부터는 나눌 수 있으면 나눠서 올려주시면 좋을 것 같아요~

Copy link

@Peter1119 Peter1119 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다 ~!

@Roy-wonji Roy-wonji merged commit c2973e1 into develop Oct 31, 2025
1 check passed
@Roy-wonji Roy-wonji deleted the feature/search branch October 31, 2025 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚒️ 테스트 테스트 코드 작성 ✨ 기능추가 새로운 기능 추가 🎨 디자인 UI 디자인 작업

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨[feat]: 검색 화면 구현

3 participants