Conversation
|
Caution Review failedThe pull request is closed. Walkthrough이번 변경은 Record 관련 API 및 도메인 객체의 네이밍, DTO, Repository, UseCase, Presentation 계층의 연동을 포함해, 주요 데이터 흐름과 입력 폼의 구조를 전반적으로 개선하고 1차 API 연동을 완료하는 작업입니다. Combine 기반의 입력 변경 감지, 의존성 주입, 데이터 유효성 검증, 상태 관리 등이 추가 및 개선되었습니다. Changes
Sequence Diagram(s)Note 작성 및 제출 플로우sequenceDiagram
participant User
participant NoteView
participant NoteViewController
participant NoteViewModel
participant CreateRecordUseCase
participant RecordRepository
User ->> NoteView: 입력값 변경
NoteView -->> NoteViewController: .completeForm(form) 이벤트
NoteViewController ->> NoteViewModel: .submitNoteForm(form) 액션
NoteViewModel ->> NoteViewModel: reduce(action:submitNoteForm)
NoteViewModel ->> NoteViewModel: sideEffect(.submit(form))
NoteViewModel ->> CreateRecordUseCase: execute(bookId, recordVO)
CreateRecordUseCase ->> RecordRepository: create(bookId, recordData)
RecordRepository -->> CreateRecordUseCase: RecordInfo 반환
CreateRecordUseCase -->> NoteViewModel: 완료(Void)
NoteViewModel ->> NoteViewModel: .submitNoteFormSuccessed 액션
NoteViewModel ->> NoteViewController: createCompleted = true 상태 변경
NoteViewController ->> User: 등록 성공 다이얼로그 표시
도서 등록 및 노트 작성 진입sequenceDiagram
participant User
participant SearchViewController
participant SearchViewModel
participant BookUpsertUseCase
participant SearchCoordinator
participant NoteCoordinator
User ->> SearchViewController: 도서 상태 선택
SearchViewController ->> SearchViewModel: .upsertBook(isbn, status)
SearchViewModel ->> BookUpsertUseCase: execute(isbn, status)
BookUpsertUseCase -->> SearchViewModel: BookInfo 반환
SearchViewModel ->> SearchViewModel: bookId 상태 저장
SearchViewModel ->> SearchViewController: noteReadied = true
SearchViewController ->> SearchCoordinator: didBookRegistered(bookId)
SearchCoordinator ->> NoteCoordinator: 생성 및 start(bookId)
NoteCoordinator ->> User: 노트 작성 화면 표시
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes해당 이슈 목적(UseCase, Presentation 연동)에 부합하지 않는 코드 변경은 발견되지 않았습니다. Possibly related PRs
Suggested reviewers
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (2)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
|
시간대가 시간대다보니 바이패스합니다. |
There was a problem hiding this comment.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
src/Projects/BKData/Sources/DTO/Response/InsertRecordResponseDTO.swift (1)
6-17: 널 가능 필드가 강제String으로 선언돼 디코딩 실패 위험
quote,review,bookCoverImageUrl는 도메인 모델에서 Optional인데 DTO에서는 Non-Optional로 선언되어 있습니다. 서버에서null또는 빈 값이 오면 전체 디코딩이 throw 됩니다. 안전성을 위해 Optional로 맞추거나decodeIfPresent를 사용해주세요.- let quote: String - let review: String - let bookCoverImageUrl: String + let quote: String? + let review: String? + let bookCoverImageUrl: String?
🧹 Nitpick comments (14)
src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/AppreciationResultView.swift (1)
8-11: EmotionIcon rawValue 한글화에 따른 케이스 정합성 확인
someEmotion1만"#따뜻함"으로 변경되고someEmotion2~4는 여전히 영어 플레이스홀더("#emotion2"등)로 남아 있어 UI-노출 시 라벨이 뒤섞여 보일 수 있습니다. 동일 컨텍스트(SeedReportView 등)에서는 네 가지 모두#+한글로 통일되므로, 이 파일도 맞춰 주는 편이 자연스럽습니다.- case someEmotion2 = "#emotion2" - case someEmotion3 = "#emotion3" - case someEmotion4 = "#emotion4" + case someEmotion2 = "#즐거움" + case someEmotion3 = "#긴장감" + case someEmotion4 = "#슬픔"변경이 의도된 것이 아니라면 전체 케이스를 한글 또는 플레이스홀더 중 하나로 통일해 주세요.
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swift (1)
8-11:#접두어가 사용자 문구에 그대로 노출되는지 확인 필요Raw value를
"#따뜻함"등으로 변경하면서 Line 148-150의 요약 문구에도#따뜻함 감정을 많이 느꼈어요처럼 해시가 그대로 삽입됩니다.
UI/카피라이팅 관점에서 해시가 필요 없다면:- let names = top.map { $0.rawValue }.joined(separator: ", ") + let names = top.map { $0.rawValue.replacingOccurrences(of: "#", with: "") }.joined(separator: ", ")또는 enum rawValue에서
#를 제거하고 UI 표시에만 붙이는 방식을 고려해 주세요.
의도된 노출이라면 이 코멘트는 무시하셔도 됩니다.Also applies to: 148-150
src/Projects/BKDomain/Sources/Entity/RecordInfo.swift (1)
5-5:Decodable추가 후 Date 파싱 전략 확인 필요
RecordInfo가 그대로Decodable을 채택하면JSONDecoder의 기본dateDecodingStrategy(.deferredToDate)가 적용됩니다. 서버가 ISO-8601 문자열을 내려주면 디코딩이 실패할 수 있으니, 레이어 어디선가(예:NetworkService또는Repository) 명시적으로iso8601전략을 설정했는지 점검해주세요.
추가로 테스트 편의를 위해Equatable, 컬렉션 사용을 위해Hashable까지 함께 채택하는 것도 고려해볼 만합니다.src/Projects/BKDomain/Sources/Entity/BookInfo.swift (1)
5-5:Equatable만으로는 부족할 수 있습니다 –Hashable병행 채택 제안동일성 비교가 필요해
Equatable을 붙이신 것은 👍입니다.
컬렉션(Set, Dictionary)에서BookInfo를 키나 요소로 사용하거나, Combine diff-ing 등에 활용하려면Hashable도 함께 채택해 두면 유연성이 높아집니다. 구현 난이도(자동 합성)는 동일하니 검토 부탁드립니다.src/Projects/BKData/Sources/DTO/Response/InsertRecordResponseDTO.swift (1)
34-48:DateParser실패 시distantPast는 의미를 왜곡합니다파싱 실패 시 임의의 과거 날짜를 주입하면 버그 추적이 어려워집니다.
• 실패를 Throw 하거나, Optional Date로 전달해 상위 계층이 처리하도록 하는 편이 명확합니다.
• 최소한.now같은 현재 시각으로 대체하거나 로그 남기기가 좋습니다.- createdAt: DateParser.parse(createdAt) ?? .distantPast, + createdAt: try DateParser.parse(createdAt) ?? { throw DateError.invalidFormat(createdAt) }(),
DateError는 내부에서 정의해주시면 됩니다.src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (1)
185-185: 텍스트 변경 이벤트 발송 로직 개선 제안현재는 텍스트가 비어있지 않을 때만 이벤트를 발송하고 있습니다. 텍스트가 삭제되는 경우에도 이벤트가 필요할 수 있습니다.
더 일관된 이벤트 발송을 위해 다음과 같이 수정하는 것을 고려해보세요:
- if !textView.text.isEmpty { textDidChangeSubject.send(()) } + textDidChangeSubject.send(())src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift (1)
13-13: 미사용 변수를 제거해주세요.
textDidChangeSubject가 선언되었지만 사용되지 않고 있습니다.inputChangedPublisher에서appreciationTextView.textDidChangePublisher를 직접 사용하므로 불필요합니다.다음과 같이 제거해주세요:
- private let textDidChangeSubject = PassthroughSubject<Void, Never>()src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift (1)
149-149: 감정 식별을 위한 더 안정적인 방법을 고려해보세요.
hashValue는 Swift 버전이나 컴파일 환경에 따라 변경될 수 있습니다. 더 안정적인 식별을 위해 다음을 고려해보세요:- view.tag = emotion.hashValue + view.tag = Emotion.allCases.firstIndex(of: emotion) ?? 0- let emotion = Emotion.allCases.first(where: { $0.hashValue == tappedView.tag }) else { + let emotion = Emotion.allCases.indices.contains(tappedView.tag) ? Emotion.allCases[tappedView.tag] : nil, + emotion != nil else {Also applies to: 153-157
src/Projects/BKData/Sources/DTO/Response/FetchRecordResponseDTO.swift (2)
18-22: Sort 구조체의 불린 플래그들을 검토해보세요.
empty,sorted,unsorted플래그들이 서로 상충될 수 있는 상태를 나타낼 수 있습니다. 백엔드 API 응답과 일치하는지 확인하고, 실제 사용 시 혼란을 방지하기 위해 문서화를 고려해보세요.
24-31: Pageable 구조체와 메인 구조체 간 중복 필드를 확인해보세요.
Pageable구조체 내의 일부 필드들(pageSize, pageNumber 등)이 메인 구조체의 필드들과 중복될 수 있습니다. 실제 API 응답 구조와 일치하는지 확인하고, 필요하다면 중복을 제거하는 것을 고려해보세요.src/Projects/BKData/Sources/Repository/DefaultRecordRepository.swift (1)
32-53: 페이지네이션 지원 fetch 메서드가 잘 구현되었습니다.새로운 fetch 메서드가 페이지네이션 매개변수를 적절히 처리하고 응답에서 content를 추출하는 로직이 정확합니다.
다음 매개변수 검증을 고려해보세요:
public func fetch( bookId: String, page: Int, size: Int, sortType: LibrarySortType ) -> AnyPublisher<[RecordInfo], Error> { + guard page >= 0, size > 0 else { + return Fail(error: ValidationError.invalidPagination) + .eraseToAnyPublisher() + } + networkProvider.request(src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift (1)
159-172: 구독 관리 최적화를 고려해보세요.
cancellables.removeAll()을 사용하면 현재 뷰와 관련 없는 다른 구독들도 모두 취소될 수 있습니다. 더 정밀한 구독 관리를 위해 개별 구독을 추적하는 것을 고려해보세요.-private var cancellables = Set<AnyCancellable>() +private var cancellables = Set<AnyCancellable>() +private var currentPageCancellable: AnyCancellable? @objc func pageControlChanged(_ sender: BKPageControl) { let xpos = CGFloat(sender.currentPage) * contentScrollView.bounds.width contentScrollView.setContentOffset(.init(x: xpos, y: 0), animated: true) - cancellables.removeAll() + currentPageCancellable?.cancel() if let notifiable = currentView as? FormInputNotifiable { - notifiable.inputChangedPublisher + currentPageCancellable = notifiable.inputChangedPublisher .sink { [weak self] in self?.updateNextButtonEnabled() } - .store(in: &cancellables) }src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift (1)
35-37: bookId 유효성 검사를 추가해보세요.빈 문자열이나 잘못된 형식의 bookId가 전달될 가능성을 고려하여 초기화 시점에 검증 로직을 추가하는 것을 고려해보세요.
init(bookId: String) { + precondition(!bookId.isEmpty, "BookId must not be empty") self.bookId = bookId bindSideEffects() }src/Projects/BKPresentation/Sources/MainFlow/Search/ViewModel/SearchViewModel.swift (1)
21-22: 상태 초기화 생명주기를 명확히 해보세요.
bookId와noteReadied상태가 언제 초기화되는지 명확하지 않습니다. 적절한 시점에 상태를 리셋하는 액션을 추가하는 것을 고려해보세요.새로운 액션을 추가해보세요:
enum Action { // existing cases... + case resetNoteFlow } +case .resetNoteFlow: + newState.bookId = nil + newState.noteReadied = false
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (41)
src/Projects/BKData/Sources/API/RecordAPI.swift(3 hunks)src/Projects/BKData/Sources/DTO/Request/FetchRecordRequestDTO.swift(1 hunks)src/Projects/BKData/Sources/DTO/Request/InsertRecordRequestDTO.swift(2 hunks)src/Projects/BKData/Sources/DTO/Response/FetchRecordResponseDTO.swift(1 hunks)src/Projects/BKData/Sources/DTO/Response/InsertRecordResponseDTO.swift(2 hunks)src/Projects/BKData/Sources/DataAssembly.swift(1 hunks)src/Projects/BKData/Sources/Repository/DefaultBookRepository.swift(1 hunks)src/Projects/BKData/Sources/Repository/DefaultRecordRepository.swift(1 hunks)src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift(5 hunks)src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift(3 hunks)src/Projects/BKDomain/Sources/DomainAssembly.swift(1 hunks)src/Projects/BKDomain/Sources/Entity/BookInfo.swift(1 hunks)src/Projects/BKDomain/Sources/Entity/RecordInfo.swift(1 hunks)src/Projects/BKDomain/Sources/Interface/Repository/RecordRepository.swift(1 hunks)src/Projects/BKDomain/Sources/Interface/Usecase/BookUpsertUseCase.swift(1 hunks)src/Projects/BKDomain/Sources/Interface/Usecase/CheckTermsStateUseCase.swift(0 hunks)src/Projects/BKDomain/Sources/Interface/Usecase/CreateRecordUseCase.swift(1 hunks)src/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swift(1 hunks)src/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swift(1 hunks)src/Projects/BKDomain/Sources/UseCase/DefaultSearchBookUseCase.swift(1 hunks)src/Projects/BKDomain/Sources/VO/BookStatus.swift(1 hunks)src/Projects/BKDomain/Sources/VO/LibraryDetails/LibrarySortType.swift(1 hunks)src/Projects/BKDomain/Sources/VO/RecordDetails/RecordSortType.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/BookDetail/ViewModel/BookDetailViewModel.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Home/MainFlowCoordinator.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/Coordinator/NoteCoordinator.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift(5 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift(4 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift(4 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift(3 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift(4 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift(2 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift(2 hunks)src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/AppreciationResultView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/NoteCompletionView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/Coordinator/SearchCoordinator.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/VO/BookRegistrationStatus.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/View/BookRegistrationStatusView.swift(0 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift(3 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/ViewModel/SearchViewModel.swift(6 hunks)
💤 Files with no reviewable changes (2)
- src/Projects/BKDomain/Sources/Interface/Usecase/CheckTermsStateUseCase.swift
- src/Projects/BKPresentation/Sources/MainFlow/Search/View/BookRegistrationStatusView.swift
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#56
File: src/Projects/BKPresentation/Sources/Constant/PresentationKeys.swift:3-5
Timestamp: 2025-07-07T13:53:13.006Z
Learning: clxxrlove prefers using enum over struct for constants namespace due to better runtime performance, memory layout, and compiler optimizations. Enum prevents instantiation at compile time without needing private init().
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#94
File: src/Projects/BKData/Sources/Repository/DefaultBookRepository.swift:15-40
Timestamp: 2025-07-21T05:16:18.481Z
Learning: clxxrlove는 Reed-iOS 프로젝트에서 기능 구현 시 우선순위를 명확하게 설정한다. 기본 기능 구현을 먼저 완료하고, 에러 처리나 안정성 개선은 이후 단계에서 진행하는 것을 선호한다.
📚 Learning: clxxrlove prefers separating protocol registrations for refreshhandler and authrepository even when ...
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#66
File: src/Projects/BKData/Sources/DataAssembly.swift:49-60
Timestamp: 2025-07-09T02:32:03.801Z
Learning: clxxrlove prefers separating protocol registrations for RefreshHandler and AuthRepository even when using the same implementation (DefaultAuthRepository) to maintain Interface Segregation Principle, where RefreshHandler focuses on token refresh and AuthRepository handles broader authentication operations.
Applied to files:
src/Projects/BKData/Sources/DataAssembly.swift
📚 Learning: appversionusecase.execute() returns anypublisher where the failure type is never, mak...
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#79
File: src/Projects/BKPresentation/Sources/MainFlow/Setting/ViewModel/SettingViewModel.swift:78-85
Timestamp: 2025-07-11T12:12:48.911Z
Learning: AppVersionUseCase.execute() returns AnyPublisher<String, Never> where the Failure type is Never, making error handling unnecessary. The app version is retrieved from the main bundle which is always available, and the implementation already handles missing version by defaulting to "-".
Applied to files:
src/Projects/BKDomain/Sources/UseCase/DefaultSearchBookUseCase.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swiftsrc/Projects/BKDomain/Sources/Interface/Usecase/BookUpsertUseCase.swiftsrc/Projects/BKDomain/Sources/Interface/Usecase/CreateRecordUseCase.swiftsrc/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swiftsrc/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swiftsrc/Projects/BKData/Sources/Repository/DefaultBookRepository.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Search/ViewModel/SearchViewModel.swift
📚 Learning: reed-ios 프로젝트의 onboardingcheckusecase.execute() 메서드는 anypublisher를 반환하므로 실패할 수 없도록 설계되었...
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#120
File: src/Projects/BKPresentation/Sources/AppCoordinator.swift:31-41
Timestamp: 2025-07-30T11:32:20.533Z
Learning: Reed-iOS 프로젝트의 OnboardingCheckUseCase.execute() 메서드는 AnyPublisher<Bool, Never>를 반환하므로 실패할 수 없도록 설계되었다. Never 타입은 에러가 발생하지 않음을 보장하므로 에러 처리 로직이 불필요하다.
Applied to files:
src/Projects/BKDomain/Sources/UseCase/DefaultSearchBookUseCase.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swiftsrc/Projects/BKData/Sources/Repository/DefaultRecordRepository.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swiftsrc/Projects/BKDomain/Sources/Interface/Usecase/BookUpsertUseCase.swiftsrc/Projects/BKDomain/Sources/Interface/Usecase/CreateRecordUseCase.swiftsrc/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swiftsrc/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Search/ViewModel/SearchViewModel.swift
📚 Learning: the loginviewmodel's authenticatewithtoken case in src/projects/bkpresentation/sources/authflow/view...
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#56
File: src/Projects/BKPresentation/Sources/AuthFlow/ViewModel/LoginViewModel.swift:109-111
Timestamp: 2025-07-07T13:47:32.784Z
Learning: The LoginViewModel's authenticateWithToken case in src/Projects/BKPresentation/Sources/AuthFlow/ViewModel/LoginViewModel.swift is test code and not important for implementation according to the user.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/ViewModel/BookDetailViewModel.swift
📚 Learning: clxxrlove는 emotionregistrationview에서 someemotion1-4 케이스들을 임시로 구현했으며, 해당하는 그래픽 디자인이 나온 후 수정할 예정이라고 명시...
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#112
File: src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift:52-53
Timestamp: 2025-07-28T10:44:32.256Z
Learning: clxxrlove는 EmotionRegistrationView에서 someEmotion1-4 케이스들을 임시로 구현했으며, 해당하는 그래픽 디자인이 나온 후 수정할 예정이라고 명시했다. 감정 선택 UI는 디자인 에셋 완성 후 구현하는 것을 선호한다.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/AppreciationResultView.swiftsrc/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift
📚 Learning: clxxrlove는 reed-ios 프로젝트에서 appicon 에셋 구조를 미리 설정하고, 실제 이미지 파일이 준비되기 전까지는 filename 속성을 의도적으로 생략하는 개발 방...
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#69
File: src/Projects/BKDesign/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json:1-35
Timestamp: 2025-07-10T13:26:07.554Z
Learning: clxxrlove는 Reed-iOS 프로젝트에서 AppIcon 에셋 구조를 미리 설정하고, 실제 이미지 파일이 준비되기 전까지는 filename 속성을 의도적으로 생략하는 개발 방식을 사용한다. 이는 에셋 구조를 먼저 만들고 나중에 이미지를 추가하는 단계적 개발 접근법이다.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/AppreciationResultView.swift
📚 Learning: clxxrlove는 noteview의 nextbuttontapped 메서드에서 폼 검증 실패 시 첫 번째 페이지로 되돌아가는 로직을 임시로 구현했으며, 추후 적절한 에러 처리 로직...
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#112
File: src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift:128-140
Timestamp: 2025-07-28T10:45:09.696Z
Learning: clxxrlove는 NoteView의 nextButtonTapped 메서드에서 폼 검증 실패 시 첫 번째 페이지로 되돌아가는 로직을 임시로 구현했으며, 추후 적절한 에러 처리 로직을 추가할 예정이라고 명시했다. 임시 화면 구현 단계에서는 기본 동작에 집중하고 에러 처리는 후속 작업으로 계획하는 것을 선호한다.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/Home/MainFlowCoordinator.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift
📚 Learning: bkdesign 프로젝트에서 uicolor+ 확장의 시맨틱 컬러 메서드들(.bkcontentcolor, .bkbordercolor, .bkdividercolor, .bkbaseco...
Learnt from: doyeonk429
PR: YAPP-Github/Reed-iOS#63
File: src/Projects/BKDesign/Sources/Extensions/UIColor+.swift:50-92
Timestamp: 2025-07-08T17:17:37.703Z
Learning: BKDesign 프로젝트에서 UIColor+ 확장의 시맨틱 컬러 메서드들(.bkContentColor, .bkBorderColor, .bkDividerColor, .bkBaseColor)이 현재 다크 모드에서도 라이트 모드 색상을 반환하는 것은 의도적인 구현입니다. 아직 다크 모드가 구현되지 않았지만, 미래의 다크 모드 지원을 위한 코드 구조로 준비되어 있습니다.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift
📚 Learning: doyeonk429는 bottomsheetshadow struct에서 apply(to:)와 ascalayershadow() 메서드를 처음에 만들었지만 활용 측면에서 애매할 것 같아...
Learnt from: doyeonk429
PR: YAPP-Github/Reed-iOS#63
File: src/Projects/BKDesign/Sources/Foundation/GraphicSystem/BottomSheetShadow.swift:5-10
Timestamp: 2025-07-08T17:16:15.942Z
Learning: doyeonk429는 BottomSheetShadow struct에서 apply(to:)와 asCALayerShadow() 메서드를 처음에 만들었지만 활용 측면에서 애매할 것 같아서 제외했다고 함. 정적 속성만으로 구현하는 것을 선호함.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift
📚 Learning: reed-ios 프로젝트의 bkbottomsheetviewcontroller에서 버튼 영역 높이(84)는 디자인 시스템에 기반한 의도적인 고정값입니다. clxxrlove에 따르면 ...
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#80
File: src/Projects/BKDesign/Sources/Components/BottomSheet/BKBottomSheetViewController.swift:148-148
Timestamp: 2025-07-14T05:23:04.937Z
Learning: Reed-iOS 프로젝트의 BKBottomSheetViewController에서 버튼 영역 높이(84)는 디자인 시스템에 기반한 의도적인 고정값입니다. clxxrlove에 따르면 작은 기기에서도 동일한 크기가 유지되어야 하며, 동적 계산보다는 상수화만 필요합니다.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift
📚 Learning: in the bkdesign project, all image assets referenced in contents.json files are properly included in...
Learnt from: doyeonk429
PR: YAPP-Github/Reed-iOS#63
File: src/Projects/BKDesign/Resources/Assets.xcassets/chevron-right.imageset/Contents.json:1-26
Timestamp: 2025-07-08T17:15:59.793Z
Learning: In the BKDesign project, all image assets referenced in Contents.json files are properly included in the repository with the correct 1x, 2x, and 3x variants. The chevron-right icon and other design system icons are complete and ready for use.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift
📚 Learning: doyeonk429는 reed-ios 프로젝트에서 ocr 기능 구현 시 sentenceregistrationevent.ocrscantapped enum을 미리 선언해두고, 나중에 ...
Learnt from: doyeonk429
PR: YAPP-Github/Reed-iOS#125
File: src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift:12-14
Timestamp: 2025-07-31T12:41:20.058Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 OCR 기능 구현 시 SentenceRegistrationEvent.ocrScanTapped enum을 미리 선언해두고, 나중에 SentenceRegistrationView에서 버튼으로 진입하는 플로우를 구현할 때 연결할 예정이라고 명시했다. UI와 기능 구현을 먼저 완성하고 화면 간 연결 로직은 후속 작업으로 계획하는 개발 방식을 선호한다.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Search/VO/BookRegistrationStatus.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swiftsrc/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift
🧬 Code Graph Analysis (15)
src/Projects/BKData/Sources/DataAssembly.swift (1)
src/Projects/BKCore/Sources/DiContainer/DIContainer.swift (1)
register(25-46)
src/Projects/BKPresentation/Sources/MainFlow/Search/Coordinator/SearchCoordinator.swift (1)
src/Projects/BKPresentation/Sources/Common/Coordinator/Coordinator.swift (1)
addChildCoordinator(39-44)
src/Projects/BKDomain/Sources/DomainAssembly.swift (1)
src/Projects/BKCore/Sources/DiContainer/DIContainer.swift (1)
register(25-46)
src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/NoteCompletionView.swift (1)
src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/AppreciationResultView.swift (1)
apply(129-138)
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift (2)
src/Projects/BKPresentation/Sources/MainFlow/Search/Coordinator/SearchCoordinator.swift (1)
didBookRegistered(26-34)src/Projects/BKPresentation/Sources/MainFlow/Search/ViewModel/SearchViewModel.swift (1)
send(71-75)
src/Projects/BKData/Sources/API/RecordAPI.swift (1)
src/Projects/BKData/Sources/Repository/DefaultRecordRepository.swift (1)
fetch(32-53)
src/Projects/BKDomain/Sources/Interface/Usecase/BookUpsertUseCase.swift (1)
src/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swift (1)
execute(12-19)
src/Projects/BKDomain/Sources/Interface/Usecase/CreateRecordUseCase.swift (1)
src/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swift (1)
execute(12-19)
src/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swift (1)
src/Projects/BKData/Sources/Repository/DefaultRecordRepository.swift (1)
create(15-30)
src/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swift (1)
src/Projects/BKData/Sources/Repository/DefaultBookRepository.swift (1)
upsert(61-78)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift (4)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift (1)
registrationForm(118-121)src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift (1)
registrationForm(94-103)src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift (1)
registrationForm(102-117)src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift (1)
makeNoteForm(13-44)
src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift (1)
src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift (1)
toRecordVO(46-53)
src/Projects/BKDomain/Sources/Interface/Repository/RecordRepository.swift (1)
src/Projects/BKData/Sources/Repository/DefaultRecordRepository.swift (1)
fetch(32-53)
src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift (1)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift (1)
textField(134-142)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift (1)
src/Projects/BKDesign/Sources/Extensions/UIColor+.swift (1)
bkBorderColor(65-76)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (82)
src/Projects/BKDomain/Sources/UseCase/DefaultSearchBookUseCase.swift (1)
15-24: 형식 변경만 발생 – 문제 없음괄호 위치 조정 외 로직 변화가 없어 기능적으로 영향 없습니다.
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/ViewModel/BookDetailViewModel.swift (1)
84-119: 더 현실적인 목 데이터로 개선되었습니다.기존의 반복적인 시적 텍스트에서 실제 책의 챕터 제목과 섹션으로 변경되어 UI 테스트와 개발에 더 적합한 데이터가 되었습니다. 페이지 번호도 구체적인 값으로 업데이트되어 더 현실적입니다.
src/Projects/BKData/Sources/DTO/Request/InsertRecordRequestDTO.swift (1)
6-32: DTO 네이밍과 구조가 개선되었습니다.
RecordPostDTO에서InsertRecordRequestDTO로 변경하여 용도가 더 명확해졌고, internal 접근 제어자 사용도 적절합니다.RecordVO를 받는 편의 이니셜라이저도 잘 구현되어 있습니다.src/Projects/BKData/Sources/DataAssembly.swift (1)
80-85: RecordRepository 의존성 주입 등록이 올바르게 구현되었습니다.OAuth NetworkProvider를 사용하여 인증이 필요한 Record API 호출에 적합하며, 기존의 다른 레포지토리 등록 패턴과 일관성을 유지하고 있습니다.
src/Projects/BKDomain/Sources/VO/LibraryDetails/LibrarySortType.swift (1)
6-9: Swift 네이밍 컨벤션에 맞게 개선되었습니다.enum case 이름을 snake_case에서 camelCase로 변경하여 Swift 코딩 스타일에 더 적합해졌습니다. raw value는 그대로 유지되어 API 호환성도 보장됩니다.
src/Projects/BKPresentation/Sources/MainFlow/Search/Coordinator/SearchCoordinator.swift (1)
25-35: LGTM! 코디네이터 패턴이 올바르게 구현되었습니다.책 등록 후 노트 작성 플로우로의 전환이 적절하게 구현되었습니다.
bookId를NoteCoordinator에 전달하고 부모-자식 관계를 올바르게 설정하여 1차 API 연동 목표에 부합합니다.src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/NoteCompletionView.swift (3)
31-34: 하드코딩된 테스트 데이터를 동적 데이터로 교체할 계획을 확인해주세요.현재 책 정보가 하드코딩되어 있습니다. 1차 API 연동 과정에서 실제 API 응답 데이터로 대체될 예정인지 확인이 필요합니다.
38-38: 페이지 번호 변경이 의도된 것인지 확인해주세요.페이지 번호가 100에서 99로 변경되었습니다. 이 변경이 특정 테스트 시나리오를 위한 것인지 확인이 필요합니다.
42-42: 생성 날짜 변경의 의도를 확인해주세요.생성 날짜가 "2025.07.28"에서 "2025.06.25"로 변경되었습니다. 이 변경이 특정 테스트 케이스를 위한 것인지 확인이 필요합니다.
src/Projects/BKData/Sources/DTO/Request/FetchRecordRequestDTO.swift (1)
5-9: LGTM! 페이지네이션과 정렬을 위한 DTO가 잘 설계되었습니다.
DictionaryRepresentable프로토콜을 준수하여 API 쿼리 파라미터로 변환 가능하며,LibrarySortType을 사용한 정렬 옵션도 적절합니다. 1차 API 연동 목표에 부합하는 깔끔한 구현입니다.src/Projects/BKDomain/Sources/VO/RecordDetails/RecordSortType.swift (1)
6-9: LGTM! Swift 네이밍 컨벤션에 맞게 개선되었습니다.enum case 이름을 snake_case에서 camelCase로 변경하면서도 서버에서 요구하는 raw value는 유지했습니다. Swift 코드 일관성을 높이는 좋은 개선입니다.
src/Projects/BKDomain/Sources/Interface/Usecase/BookUpsertUseCase.swift (1)
5-10: LGTM! UseCase 프로토콜이 명확하게 정의되었습니다.ISBN과 BookStatus를 받아 BookInfo를 반환하는 upsert 연산이 적절하게 설계되었습니다. Combine의
AnyPublisher<BookInfo, Error>를 사용하여 비동기 처리와 에러 핸들링이 가능하며, 1차 API 연동 목표에 부합합니다.src/Projects/BKDomain/Sources/DomainAssembly.swift (2)
116-121: 올바른 DI 패턴을 따른 BookUpsertUseCase 등록기존 패턴과 일관되게 dependency injection 컨테이너에 BookUpsertUseCase를 등록했습니다. @Autowired를 통한 BookRepository 의존성 주입이 적절히 구현되었습니다.
123-128: 일관된 패턴의 CreateRecordUseCase 등록CreateRecordUseCase 등록이 기존 use case들과 동일한 구조로 구현되어 있어 코드베이스의 일관성을 유지합니다. RecordRepository 의존성 주입도 올바르게 설정되었습니다.
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (2)
6-6: Combine 프레임워크 추가Combine을 import하여 reactive text change 기능을 지원합니다.
60-63: 올바른 reactive publisher 구현PassthroughSubject와 AnyPublisher를 사용한 text change 이벤트 구현이 적절합니다. computed property로 publisher를 노출하는 것도 좋은 패턴입니다.
src/Projects/BKDomain/Sources/Interface/Usecase/CreateRecordUseCase.swift (1)
5-10: 적절한 CreateRecordUseCase 프로토콜 설계Record 생성을 위한 use case 프로토콜이 잘 설계되었습니다. bookId와 record 매개변수를 받아 AnyPublisher<Void, Error>를 반환하는 시그니처가 적절하며, 네트워크 요청이나 유효성 검증 실패 시 에러 처리가 가능하도록 Error 타입을 사용한 것이 좋습니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/Coordinator/NoteCoordinator.swift (3)
11-11: bookId 프로퍼티 추가Note 생성 시 특정 책과 연결하기 위한 bookId 프로퍼티가 적절히 추가되었습니다.
16-24: 초기화 메서드 bookId 매개변수 추가coordinator 초기화 시 bookId를 받아 저장하도록 적절히 수정되었습니다. 의존성 주입 패턴을 올바르게 따르고 있습니다.
27-29: NoteViewModel에 bookId 전달NoteViewController 생성 시 NoteViewModel에 bookId를 전달하는 것이 올바르게 구현되었습니다. Note와 Book 간의 연결을 위한 필수적인 변경사항입니다.
src/Projects/BKData/Sources/Repository/DefaultBookRepository.swift (1)
42-42: Error 타입 일관성 개선
any Error에서Error로 반환 타입을 변경하여 타입 일관성을 개선했습니다. existential 타입을 제거하고 구체적인 Error 프로토콜 타입을 사용하는 것이 더 깔끔하고 다른 메서드들과 일관됩니다.src/Projects/BKPresentation/Sources/MainFlow/Search/VO/BookRegistrationStatus.swift (1)
5-20: LGTM! 깔끔한 enum 구조입니다.도서 등록 상태를 나타내는 enum이 명확하게 정의되어 있고, BKDomain.BookStatus로의 변환 로직도 적절합니다. Raw value로 한국어 문자열을 사용한 것은 UI 표시에 적합한 설계입니다.
src/Projects/BKDomain/Sources/Interface/Repository/RecordRepository.swift (1)
7-18: API 확장이 잘 구현되었습니다.
create메서드의 파라미터명을recordData로 변경한 것과 페이지네이션을 지원하는fetch메서드 추가가 적절합니다. 일관된AnyPublisher<T, Error>패턴을 유지하고 있습니다.src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift (3)
10-10: OCR 기능 추가가 적절합니다.새로운
didTapOCRButton이벤트 케이스가 깔끔하게 추가되었습니다.
55-72: 관심사 분리가 잘 구현되었습니다.폼 제출 로직을 ViewModel로 이동시키고 OCR 버튼 이벤트 처리를 추가한 것이 좋습니다. 각 이벤트가 명확하게 분리되어 있어 유지보수성이 향상되었습니다.
85-92: 상태 기반 UI 업데이트 패턴이 훌륭합니다.
createCompleted상태를 구독하여 성공 다이얼로그를 표시하는 방식이 반응형 프로그래밍 패턴에 잘 맞습니다. 상태 변화에 따른 UI 업데이트가 명확하게 분리되어 있습니다.src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift (2)
6-6: 타입 안전성 개선이 좋습니다.
page프로퍼티를String에서Int로 변경한 것이 타입 안전성 측면에서 더 적절합니다.
46-53: 도메인 객체 변환 로직이 깔끔합니다.
NoteForm을RecordVO로 변환하는toRecordVO()메서드가 명확하게 구현되었습니다. 각 프로퍼티의 매핑이 적절하고,emotionTags를 배열로 래핑하는 것도 적절합니다.src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift (1)
89-103: 반응형 입력 처리와 유효성 검증이 잘 구현되었습니다.
FormInputNotifiable프로토콜 채택으로 반응형 입력 변경 알림을 지원하고,registrationForm()메서드에서 공백 문자 트림 처리와 빈 문자열 검증을 추가한 것이 적절합니다.src/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swift (1)
5-10: UseCase 구현이 올바르게 구조화되어 있습니다.의존성 주입을 통한 Repository 패턴과 public 접근자를 사용한 구조가 적절합니다.
src/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swift (2)
5-10: UseCase 구현이 적절합니다.의존성 주입과 구조체 기반 구현이 올바르게 되어 있습니다.
16-18: 반환 타입 변환이 적절합니다.Repository에서 반환하는
RecordInfo를 UseCase 레벨에서Void로 변환하여 도메인 관심사를 분리한 것이 좋습니다.src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift (3)
21-24: Combine 기반 반응형 패턴이 잘 구현되었습니다.
PassthroughSubject를 사용한 텍스트 변경 이벤트 퍼블리셔가 적절하게 구현되어 있습니다.
79-85: 유용한 설정 메서드들이 추가되었습니다.TextField의 delegate와 keyboard type을 외부에서 설정할 수 있게 하는 메서드들이 적절합니다.
117-119: 텍스트 변경 이벤트 처리가 적절합니다.빈 문자열이 아닐 때만 이벤트를 발행하는 로직이 불필요한 이벤트를 방지합니다.
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift (3)
101-109: 상태 기반 내비게이션 로직이 잘 구현되었습니다.
noteReadied상태 변경을 구독하여 coordinator를 통해 화면 전환하는 반응형 패턴이 적절합니다. 중복 제거와 필터링도 효율적입니다.
135-141: 메서드 시그니처 개선이 적절합니다.
BookRegistrationStatus와isbn을 모두 받아서upsertBook액션을 전송하는 것이 더 명확한 인터페이스를 제공합니다.
160-160: 액션 기반 상태 관리 패턴을 잘 활용했습니다.디버그 로그 대신
loadNoteFlow액션을 전송하여 상태 관리를 일관성 있게 처리한 것이 좋습니다.src/Projects/BKData/Sources/API/RecordAPI.swift (4)
7-8: API 케이스명과 파라미터 타입 개선이 적절합니다.
insert와fetch로 명명이 더 명확해졌고,RecordVO와FetchRecordRequestDTO사용으로 타입 안전성이 향상되었습니다.
18-22: 일관된 path 포맷팅이 적용되었습니다.Leading slash를 추가하여 URL 경로 구성이 더 명확해졌습니다.
45-46: 도메인 객체를 DTO로 적절히 래핑했습니다.
RecordVO를InsertRecordRequestDTO로 래핑하여 데이터 계층의 책임을 명확히 분리한 것이 좋습니다.
56-57: 강타입 query 변환이 개선되었습니다.Raw
Data대신FetchRecordRequestDTO.toDictionary()를 사용하여 타입 안전성과 코드 가독성이 향상되었습니다.src/Projects/BKData/Sources/DTO/Response/FetchRecordResponseDTO.swift (2)
5-32: LGTM! 잘 설계된 제네릭 페이지네이션 DTO입니다.Spring Boot의 표준 페이지네이션 응답 구조와 일치하며, 제네릭 타입 파라미터를 통해 재사용성이 높습니다. 불변성을 위한
let사용과 중첩 구조체 설계가 적절합니다.
5-32: 잘 구조화된 페이지네이션 DTO입니다.Spring Boot의 Page 인터페이스와 일치하는 표준적인 구조로 잘 설계되었습니다. 제네릭 타입 제약조건도 적절합니다.
src/Projects/BKData/Sources/Repository/DefaultRecordRepository.swift (3)
15-30: API 변경사항에 맞춰 잘 업데이트되었습니다.
RecordAPI.insert사용과InsertRecordResponseDTO응답 타입 변경이 적절하며, 매개변수명recordData로의 변경도 의미가 명확합니다.
32-53: 페이지네이션을 지원하는 fetch 메서드가 잘 구현되었습니다.
FetchRecordRequestDTO를 통한 쿼리 파라미터 구성과FetchRecordResponseDTO<RecordInfo>의content배열 추출이 적절합니다. 에러 처리와 디버깅 로그도 일관성 있게 적용되었습니다.
15-30: 레코드 생성 메서드가 새로운 API 구조에 잘 맞춰졌습니다.메서드 시그니처와 API 호출이 새로운 DTO 구조에 맞게 올바르게 업데이트되었습니다. 에러 처리와 로깅도 적절합니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift (10)
18-20: 반응형 입력 변경을 위한 깔끔한 프로토콜 설계입니다.
FormInputNotifiable프로토콜을 통해 각 폼 뷰의 입력 변경을 일관되게 감지할 수 있도록 추상화가 잘 되었습니다.
24-24: Combine 구독 관리를 위한 적절한 추가입니다.반응형 입력 변경 감지를 위한 구독들을 관리하기 위해 필요한 프로퍼티입니다.
67-71: 초기 입력 변경 구독 설정이 적절합니다.현재 뷰가
FormInputNotifiable을 구현하는 경우 입력 변경을 감지하여 다음 버튼 상태를 업데이트하는 로직이 잘 구현되었습니다.
115-117: 현재 뷰 접근을 위한 유용한 computed property입니다.페이지 컨트롤의 현재 페이지를 기반으로 뷰에 접근하는 로직이 깔끔하게 캡슐화되었습니다.
143-147: 폼 데이터 생성 로직이 개선되었습니다.
RegistrationFormProvidable프로토콜을 통해 각 뷰에서 폼 데이터를 수집하고NoteForm.makeNoteForm으로 통합하는 접근법이 깔끔합니다.
153-157: 버튼 상태 관리 로직이 적절합니다.현재 뷰의 폼 유효성을 검사하여 다음 버튼의 활성화 상태를 결정하는 로직이 명확합니다.
163-171: 페이지 변경 시 구독 관리가 올바르게 구현되었습니다.이전 구독을 정리하고 새로운 페이지의 입력 변경을 구독하는 로직이 메모리 누수 없이 적절히 처리되었습니다.
18-21: 반응형 입력 알림을 위한 우수한 프로토콜 설계입니다.
FormInputNotifiable프로토콜이 폼 뷰들 간의 일관된 입력 변경 알림을 제공하는 깔끔한 추상화입니다.
115-117: 코드 가독성을 향상시키는 편의 속성입니다.
currentView계산 속성이 현재 페이지 뷰에 대한 접근을 단순화하여 코드 가독성을 높입니다.
153-157: 반응형 폼 검증이 훌륭하게 구현되었습니다.입력 변경에 따른 버튼 상태 업데이트가 즉각적이고 정확하게 구현되어 사용자 경험을 크게 향상시킵니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift (8)
11-11: 폼 제출 완료 상태 추가가 적절합니다.노트 폼 제출 완료를 추적하기 위한 상태 프로퍼티가 명확하게 정의되었습니다.
16-17: 노트 폼 제출을 위한 액션들이 잘 정의되었습니다.제출 요청과 성공 처리를 위한 액션이 명확하게 분리되어 있습니다.
21-21: 사이드 이펙트 정의가 적절합니다.
NoteForm을 매개변수로 받는 submit 사이드 이펙트가 명확하게 정의되었습니다.
27-27: bookId 의존성 주입이 올바르게 구현되었습니다.생성자를 통해 bookId를 받아 저장하는 방식이 명확하고 적절합니다.
Also applies to: 35-37
29-29: UseCase 의존성 주입이 적절합니다.
@Autowired를 통한CreateRecordUseCase의존성 주입이 프로젝트 패턴과 일치합니다.
54-58: 액션 처리 로직이 올바르게 구현되었습니다.폼 제출 시 사이드 이펙트를 추가하고, 성공 시 상태를 업데이트하는 로직이 명확합니다.
66-73: 사이드 이펙트 처리 로직이 적절합니다.UseCase 실행, 성공 액션 매핑, 에러 무시 처리가 프로젝트의 기본 기능 구현 우선순위에 맞게 잘 구현되었습니다. 에러 처리는 추후 개선할 수 있습니다.
8-38: 아키텍처 패턴을 잘 따른 ViewModel 구조입니다.State-Action-SideEffect 패턴이 일관되게 적용되었고, 의존성 주입과 반응형 바인딩이 적절하게 구현되었습니다.
src/Projects/BKPresentation/Sources/MainFlow/Search/ViewModel/SearchViewModel.swift (9)
21-22: 책 등록 및 노트 플로우를 위한 상태 추가가 적절합니다.
bookId와noteReadied상태를 통해 책 등록 후 노트 작성 플로우로의 전환을 관리할 수 있습니다.
32-32: 노트 플로우 및 책 등록 액션들이 잘 정의되었습니다.
loadNoteFlow,upsertBook(isbn:status:),upsertBookSuccessed액션이 명확하게 분리되어 있어 플로우 관리가 용이합니다.Also applies to: 34-34, 38-38
46-46: 사이드 이펙트 정의가 적절합니다.ISBN과 상태를 매개변수로 받는 upsert 사이드 이펙트가 명확하게 정의되었습니다.
61-61: UseCase 의존성 주입이 적절합니다.
BookUpsertUseCase의존성 주입이 프로젝트 패턴과 일치합니다.
108-111: 노트 플로우 로딩 로직이 적절합니다.
bookId가 존재하는 경우에만noteReadied상태를 true로 설정하는 안전한 로직입니다.
126-130: 책 등록 액션 처리가 올바르게 구현되었습니다.upsert 사이드 이펙트 추가와 성공 시 bookId 상태 업데이트 로직이 명확합니다.
175-182: UseCase 실행 및 에러 처리가 적절합니다.
BookUpsertUseCase실행, 성공 액션 매핑, 에러 무시 처리가 프로젝트의 기본 기능 구현 우선순위에 맞게 잘 구현되었습니다.
19-26: 책 등록 플로우를 위한 적절한 상태 관리입니다.
bookId와noteReadied상태가 검색에서 노트 작성으로의 플로우를 명확하게 관리합니다.
108-112: 노트 플로우 준비 로직이 잘 구현되었습니다.
bookId가 존재할 때만 노트 플로우를 준비하는 조건부 로직이 안전하고 적절합니다.src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift (5)
4-4: Combine 프레임워크 추가가 적절합니다.반응형 입력 처리를 위한 필수 import입니다.
8-11: 페이지 타입 변경이 도메인 모델과 일치합니다.
page속성을String에서Int로 변경한 것은 페이지 번호의 의미를 정확히 반영하며, 타입 안정성을 향상시킵니다.
14-16: Combine 기반 반응형 구조가 잘 구현되었습니다.입력 변경 알림을 위한
PassthroughSubject와 메모리 관리를 위한cancellables설정이 적절합니다. 초기화 시점에bindInputs()를 호출하여 즉시 입력 모니터링을 시작하는 것도 좋은 접근입니다.Also applies to: 41-46
102-117: 폼 검증 로직이 견고하게 구현되었습니다.공백 제거, 빈 문자열 검사, 안전한 정수 변환을 통해 데이터 무결성을 보장합니다. 유효성 검사 실패 시
nil반환으로 오류를 명확히 처리합니다.
133-143: 숫자 입력 제한이 효과적으로 구현되었습니다.
UITextFieldDelegate를 통해 숫자만 입력 가능하도록 제한하여 사용자 경험을 개선하고 유효성 검사 부담을 줄입니다.src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift (3)
12-18: 임시 감정 값 구현이 확인되었습니다.학습 내용에 따르면 디자인 에셋 완성 후 수정 예정인 임시 구현입니다. API 연동을 위한 raw value 추가는 적절합니다.
71-75: 감정 뷰 생성 팩토리 패턴이 잘 적용되었습니다.
makeEmotionView메서드를 통한 뷰 생성으로 코드 중복을 제거하고, lazy 프로퍼티로 성능을 최적화했습니다. 제스처 인식기 설정도 깔끔합니다.Also applies to: 144-151
164-172: 선택 상태 UI 업데이트가 깔끔하게 구현되었습니다.디자인 시스템의 시맨틱 컬러를 활용하고, 선택 로직과 UI 업데이트를 분리한 점이 좋습니다.
src/Projects/BKPresentation/Sources/MainFlow/Home/MainFlowCoordinator.swift
Show resolved
Hide resolved
src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift
Show resolved
Hide resolved
src/Projects/BKPresentation/Sources/MainFlow/Search/ViewModel/SearchViewModel.swift
Show resolved
Hide resolved
a87d78f to
fc873c2
Compare
🔗 관련 이슈
📘 작업 유형
📙 작업 내역
🧪 테스트 내역
Summary by CodeRabbit
신규 기능
기능 개선
버그 수정
리팩터 및 기타