-
Notifications
You must be signed in to change notification settings - Fork 0
컬렉션 API 연동 #272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
컬렉션 API 연동 #272
Conversation
Summary of ChangesHello @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
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
컬렉션 API 연동을 위한 대규모 리팩토링 및 기능 추가 작업이 인상적입니다. 전반적으로 UseCase와 Repository를 분리하고, Reactor 패턴을 적극적으로 활용하여 코드 구조가 명확해지고 유지보수성이 향상되었습니다. 특히 뷰 컨트롤러 간의 데이터 전달 방식을 클로저에서 PublishSubject로 변경하여 반응형 프로그래밍의 이점을 잘 살린 점이 돋보입니다.
다만, 코드베이스 전반에 걸쳐 사용되지 않는 주석 처리된 코드 블록이 다수 발견되었습니다. 이는 코드 가독성을 저해하고 혼란을 야기할 수 있으므로, 사용 계획이 없는 코드라면 정리하는 것이 좋겠습니다. 또한, 일부 파일 이름에 오타가 있고, 잠재적인 버그가 의심되는 부분이 있어 해당 내용에 대한 리뷰 의견을 남겼습니다. 이 부분들을 수정하면 코드의 완성도가 더욱 높아질 것입니다.
| 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)) | ||
| ]) | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
추후 수정 예정
| // 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) | ||
| // } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
추후 수정 예정
MLS/Domain/Domain/UseCaseImpl/Collection/AddBookmarksToCollectionUseCaseImpl.swift
Show resolved
Hide resolved
MLS/Domain/Domain/UseCaseImpl/Collection/AddCollectionsToBookmarkUseCaseImpl.swift
Show resolved
Hide resolved
| import Foundation | ||
|
|
||
| public enum DomainHTTPError: Error, Equatable { | ||
| case httpStatus(code: Int, message: String?) | ||
| case network | ||
| case decode | ||
| case noData | ||
| case unknown | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정완료
MLS/Domain/DomainInterface/UseCase/Collection/AddBookmarksToCollectionUseCase.swift
Show resolved
Hide resolved
MLS/Domain/DomainInterface/UseCase/Collection/AddCollectionsToBookmarkUseCase.swift
Show resolved
Hide resolved
| .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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dataSource가 nil인지 확인한 후, 옵셔널 체이닝(?)이나 guard let 바인딩 없이 강제 언래핑(!)처럼 사용되고 있습니다. dataSource가 UICollectionViewDiffableDataSource의 인스턴스이므로 클래스 타입이라 참조 시점에 nil이 아님이 보장될 수 있지만, guard let dataSource = owner.dataSource else { return }과 같이 안전하게 옵셔널을 해제하는 것이 더 명확하고 안전한 코드 스타일입니다.
| .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) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정완료
📌 이슈
✅ 작업 사항