Skip to content

Conversation

@pinocchio22
Copy link
Contributor

@pinocchio22 pinocchio22 commented Nov 27, 2025

📌 이슈

  • #이슈번호

✅ 작업 사항

  • 컬렉션 생성 / 조회
  • 컬렉션 상세 조회
  • 컬렉션 수정 / 삭제
  • 컬렉션 필터

@pinocchio22 pinocchio22 self-assigned this Nov 27, 2025
@pinocchio22 pinocchio22 added the feat 새로운 기능을 추가 label Nov 27, 2025
@pinocchio22 pinocchio22 linked an issue Nov 27, 2025 that may be closed by this pull request
@gemini-code-assist
Copy link

Summary of Changes

Hello @pinocchio22, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 애플리케이션의 컬렉션 관리 기능을 대폭 확장하기 위해 컬렉션 API를 포괄적으로 통합합니다. 사용자 정의 컬렉션을 생성, 조회, 수정 및 삭제하는 기능과 함께, 북마크를 이러한 컬렉션과 연결하는 개선된 메커니즘을 도입합니다. 데이터, 도메인, 프레젠테이션 계층 전반에 걸쳐 광범위한 리팩토링이 이루어졌으며, 네트워크 엔드포인트, 리포지토리 구현, 유스케이스 및 UI 구성 요소가 업데이트되어 더욱 강력하고 기능이 풍부한 컬렉션 경험을 제공합니다.

Highlights

  • 컬렉션 API 연동: 컬렉션 생성, 조회, 상세 조회, 수정, 삭제 등 컬렉션 관리의 모든 기능을 지원하는 API가 연동되었습니다.
  • 북마크 관리 기능 강화: 사용자가 여러 북마크를 컬렉션에 추가하고, 컬렉션 내에서 북마크를 효율적으로 관리할 수 있도록 기능이 개선되었습니다.
  • 컬렉션 뷰 및 필터링 개선: 컬렉션 목록 및 상세 뷰의 UI가 업데이트되었으며, 정렬 및 아이템 필터링 기능이 통합되어 사용자 경험이 향상되었습니다.
  • 코드 스타일 및 에러 처리 강화: SwiftLint 규칙이 추가되어 코드 스타일이 더욱 엄격해졌고, DomainHTTPError 열거형 도입으로 일관된 에러 처리가 가능해졌습니다.
  • 의존성 주입 업데이트: 새로운 컬렉션 기능과 리팩토링을 지원하기 위해 앱 전반의 의존성 주입 설정이 광범위하게 업데이트되었습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

컬렉션 API 연동을 위한 대규모 리팩토링 및 기능 추가 작업이 인상적입니다. 전반적으로 UseCase와 Repository를 분리하고, Reactor 패턴을 적극적으로 활용하여 코드 구조가 명확해지고 유지보수성이 향상되었습니다. 특히 뷰 컨트롤러 간의 데이터 전달 방식을 클로저에서 PublishSubject로 변경하여 반응형 프로그래밍의 이점을 잘 살린 점이 돋보입니다.

다만, 코드베이스 전반에 걸쳐 사용되지 않는 주석 처리된 코드 블록이 다수 발견되었습니다. 이는 코드 가독성을 저해하고 혼란을 야기할 수 있으므로, 사용 계획이 없는 코드라면 정리하는 것이 좋겠습니다. 또한, 일부 파일 이름에 오타가 있고, 잠재적인 버그가 의심되는 부분이 있어 해당 내용에 대한 리뷰 의견을 남겼습니다. 이 부분들을 수정하면 코드의 완성도가 더욱 높아질 것입니다.

Comment on lines 98 to 113
case .undoLastDeletedBookmark:
guard let lastDeleted = currentState.lastDeletedBookmark else { return .empty() }
guard let lastDeleted = currentState.lastDeletedBookmark,
let lastDeletedBookmarkId = currentState.lastDeletedBookmark?.bookmarkId else { return .empty() }
return setBookmarkUseCase.execute(
bookmarkId: lastDeleted.originalId,
isBookmark: .set(lastDeleted.type)
)
// 북마크 다시 설정시 이전 collection을 전부 추적해야하고 새로 바뀐 북마크ID가 필요하여 현재는 원할하게 동작하지 않음
.andThen(addCollectionAndBookmarkUseCase.execute(collectionIds: [currentState.collection.collectionId], bookmarkIds: [lastDeletedBookmarkId]))
.andThen(
Observable.concat([
// 불러오기
fetchCollectionUseCase.execute(id: currentState.collection.collectionId)
.map { .setItems($0) },
.just(.setLastDeletedBookmark(nil))
])
)

Choose a reason for hiding this comment

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

high

undoLastDeletedBookmark 액션 처리 로직에 "현재는 원할하게 동작하지 않음"이라는 주석이 있습니다. 버그가 있는 기능이 포함된 것으로 보입니다. 이 기능이 의도대로 동작하지 않는다면, 문제를 해결하거나 혹은 해결 전까지 해당 기능을 비활성화하여 사용자에게 잘못된 경험을 주지 않도록 하는 것이 중요합니다. 특히 addCollectionAndBookmarkUseCase를 호출하는 부분이 문제의 원인일 수 있으니 검토가 필요해 보입니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

추후 수정 예정

Comment on lines +34 to +54
// public func addBookmarksToCollection(collectionId: Int, bookmarkIds: [Int]) -> Completable {
// let endPoint = CollectionEndPoint.addBookmarksToCollection(id: collectionId, body: AddBookmarkRequestBody(bookmarkIds: bookmarkIds))
// return provider.requestData(endPoint: endPoint, interceptor: tokenInterceptor)
// .catch { error in
// if let netErr = error as? NetworkError {
// switch netErr {
// case let .statusError(code, body):
// return .error(DomainHTTPError.httpStatus(code: code, message: body))
// default:
// return .error(DomainHTTPError.unknown)
// }
// } else {
// return .error(DomainHTTPError.unknown)
// }
// }
// }
//
// public func addCollectionsToBookmark(bookmarkId: Int, collectionIds: [Int]) -> Completable {
// let endPoint = CollectionEndPoint.addCollectionsToBookmark(id: bookmarkId, body: AddCollectionRequestBody(collectionIds: collectionIds))
// return provider.requestData(endPoint: endPoint, interceptor: tokenInterceptor)
// }

Choose a reason for hiding this comment

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

medium

주석 처리된 addBookmarksToCollectionaddCollectionsToBookmark 함수가 있습니다. 현재 사용되지 않는 코드라면 가독성과 유지보수성 향상을 위해 삭제하는 것을 고려해 보세요.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

추후 수정 예정

Comment on lines 1 to 9
import Foundation

public enum DomainHTTPError: Error, Equatable {
case httpStatus(code: Int, message: String?)
case network
case decode
case noData
case unknown
}

Choose a reason for hiding this comment

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

medium

파일 이름에 오타가 있습니다. DomainHTTPError.swift.swift가 아닌 DomainHTTPError.swift로 수정해야 합니다. 파일 확장자가 중복되었습니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

수정완료

Comment on lines 469 to 473
.subscribe { owner, scrolls in
guard let dataSource = owner.dataSource else { return }
guard owner.dataSource != nil else { return }
var snapshot = owner.dataSource.snapshot()
snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .scrollCategories))
snapshot.appendItems(scrolls.scrollTypes.map { .scrollCategories($0) }, toSection: .scrollCategories)

Choose a reason for hiding this comment

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

medium

dataSourcenil인지 확인한 후, 옵셔널 체이닝(?)이나 guard let 바인딩 없이 강제 언래핑(!)처럼 사용되고 있습니다. dataSourceUICollectionViewDiffableDataSource의 인스턴스이므로 클래스 타입이라 참조 시점에 nil이 아님이 보장될 수 있지만, guard let dataSource = owner.dataSource else { return }과 같이 안전하게 옵셔널을 해제하는 것이 더 명확하고 안전한 코드 스타일입니다.

Suggested change
.subscribe { owner, scrolls in
guard let dataSource = owner.dataSource else { return }
guard owner.dataSource != nil else { return }
var snapshot = owner.dataSource.snapshot()
snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .scrollCategories))
snapshot.appendItems(scrolls.scrollTypes.map { .scrollCategories($0) }, toSection: .scrollCategories)
.subscribe { owner, scrolls in
guard let dataSource = owner.dataSource else { return }
var snapshot = dataSource.snapshot()
snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .scrollCategories))
snapshot.appendItems(scrolls.scrollTypes.map { .scrollCategories($0) }, toSection: .scrollCategories)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

수정완료

@pinocchio22 pinocchio22 merged commit 84b4234 into dev Nov 27, 2025
2 checks passed
@pinocchio22 pinocchio22 deleted the feat/#269-CollectionAPI branch November 27, 2025 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 새로운 기능을 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

컬렉션 API 연동

2 participants