Skip to content

feat: 1차 API 연결#134

Merged
clxxrlove merged 14 commits intodevelopfrom
BOOK-210-feature/#132
Aug 1, 2025
Merged

feat: 1차 API 연결#134
clxxrlove merged 14 commits intodevelopfrom
BOOK-210-feature/#132

Conversation

@clxxrlove
Copy link
Member

@clxxrlove clxxrlove commented Aug 1, 2025

🔗 관련 이슈

📘 작업 유형

  • ✨ Feature (기능 추가)
  • 🐞 Bugfix (버그 수정)
  • 🔧 Refactor (코드 리팩토링)
  • ⚙️ Chore (환경 설정)
  • 📝 Docs (문서 작성 및 수정)
  • ✅ Test (기능 테스트)
  • 🎨 style (코드 스타일 수정)

📙 작업 내역

  • 홈 화면 제외 API, 뷰 연결

🧪 테스트 내역

  • 브라우저/기기에서 동작 확인
  • 엣지 케이스 테스트 완료
  • 기존 기능 영향 없음

Summary by CodeRabbit

  • 신규 기능

    • 독서 노트 작성 플로우에 입력 유효성 검사 및 입력 변경 감지(Combine 기반) 기능이 추가되었습니다.
    • 노트 작성 완료 시 성공 다이얼로그가 표시됩니다.
    • 도서 등록 시 읽기 상태를 선택할 수 있으며, 등록 후 바로 노트 작성 플로우로 진입할 수 있습니다.
    • 텍스트 필드 및 텍스트 뷰에 입력 변경을 감지하는 퍼블리셔가 추가되었습니다.
    • 도서 업서트(등록/수정) 및 노트 생성 유스케이스가 추가되었습니다.
    • 노트 작성 시 OCR 스캔 버튼이 추가되어 스캔 기능을 사용할 수 있습니다.
    • 도서 검색 후 등록 시 자동으로 노트 작성 플로우로 이동하는 기능이 추가되었습니다.
  • 기능 개선

    • 감정 선택 UI 및 입력 방식이 개선되어 선택 시 즉각적으로 반영됩니다.
    • 문장 등록 시 페이지 번호 입력 방식이 숫자형으로 변경되었습니다.
    • 감정 태그 및 정렬 타입 등 여러 enum의 네이밍이 카멜케이스로 일관성 있게 변경되었습니다.
    • 감정 태그, 도서 상태 등 일부 텍스트가 더 명확하게 수정되었습니다.
    • 노트 작성 플로우 내 페이지 전환 시 입력 상태에 따라 다음 버튼 활성화가 동적으로 변경됩니다.
  • 버그 수정

    • 입력값이 비어있을 때 버튼이 비활성화되도록 하여 잘못된 제출을 방지합니다.
  • 리팩터 및 기타

    • 내부 데이터 전달 객체 및 뷰모델 구조가 개선되었습니다.
    • 의존성 주입 및 레이어 간 연결 구조가 정비되었습니다.
    • API 호출 및 DTO 구조가 명확해지고 일관성 있게 변경되었습니다.

@coderabbitai
Copy link

coderabbitai bot commented Aug 1, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

이번 변경은 Record 관련 API 및 도메인 객체의 네이밍, DTO, Repository, UseCase, Presentation 계층의 연동을 포함해, 주요 데이터 흐름과 입력 폼의 구조를 전반적으로 개선하고 1차 API 연동을 완료하는 작업입니다. Combine 기반의 입력 변경 감지, 의존성 주입, 데이터 유효성 검증, 상태 관리 등이 추가 및 개선되었습니다.

Changes

Cohort / File(s) Change Summary
Record API 및 DTO 리팩토링
src/Projects/BKData/Sources/API/RecordAPI.swift, src/Projects/BKData/Sources/DTO/Request/FetchRecordRequestDTO.swift, src/Projects/BKData/Sources/DTO/Request/InsertRecordRequestDTO.swift, src/Projects/BKData/Sources/DTO/Response/FetchRecordResponseDTO.swift, src/Projects/BKData/Sources/DTO/Response/InsertRecordResponseDTO.swift
Record API enum 및 DTO 네이밍, 타입, 접근제어 리팩토링 및 페이징/정렬 대응 신규 DTO 추가
RecordRepository/BookRepository 인터페이스 및 구현
src/Projects/BKData/Sources/Repository/DefaultRecordRepository.swift, src/Projects/BKData/Sources/Repository/DefaultBookRepository.swift, src/Projects/BKDomain/Sources/Interface/Repository/RecordRepository.swift
create 메서드 파라미터명 변경, fetch 메서드 추가, BookRepository 오류 타입 명확화
DI 컨테이너 등록
src/Projects/BKData/Sources/DataAssembly.swift, src/Projects/BKDomain/Sources/DomainAssembly.swift
RecordRepository, BookUpsertUseCase, CreateRecordUseCase 의존성 주입 등록 추가
도메인 엔터티/VO/Enum 리팩토링
src/Projects/BKDomain/Sources/Entity/BookInfo.swift, src/Projects/BKDomain/Sources/Entity/RecordInfo.swift, src/Projects/BKDomain/Sources/VO/BookStatus.swift, src/Projects/BKDomain/Sources/VO/LibraryDetails/LibrarySortType.swift, src/Projects/BKDomain/Sources/VO/RecordDetails/RecordSortType.swift
Equatable/Decodable 준수 추가, Enum 케이스 네이밍 camelCase로 변경
UseCase 신규 도입 및 구현
src/Projects/BKDomain/Sources/Interface/Usecase/BookUpsertUseCase.swift, src/Projects/BKDomain/Sources/Interface/Usecase/CreateRecordUseCase.swift, src/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swift, src/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swift
BookUpsert, CreateRecord 관련 UseCase 프로토콜 및 기본 구현 추가
TextField/TextView 컴포넌트 개선
src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift, src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift
Combine 기반 텍스트 변경 퍼블리셔, 델리게이트/키보드 타입 설정 기능 추가
Note 입력 폼 및 뷰 개선
src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift, src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift, src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift, src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift, src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift
입력값 검증, Combine 기반 입력 변경 알림, 폼 데이터 구조 개선, FormInputNotifiable 프로토콜 도입
Note 뷰모델 및 컨트롤러 연동
src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift, src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift
NoteForm 제출, 상태 플래그, 액션/사이드이펙트/상태/의존성 추가 및 연동
Note/BookDetail/Completion/Coordinator 연동
src/Projects/BKPresentation/Sources/MainFlow/Note/Coordinator/NoteCoordinator.swift, src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swift, src/Projects/BKPresentation/Sources/MainFlow/BookDetail/ViewModel/BookDetailViewModel.swift, src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/AppreciationResultView.swift, src/Projects/BKPresentation/Sources/MainFlow/NoteCompletion/View/NoteCompletionView.swift, src/Projects/BKPresentation/Sources/MainFlow/Home/MainFlowCoordinator.swift
NoteCoordinator bookId 전달, Seed/Emotion rawValue 변경, BookDetail mock 데이터, CompletionView 표시 데이터 수정 등
Search(도서 등록/노트 작성) 흐름 개선
src/Projects/BKPresentation/Sources/MainFlow/Search/ViewModel/SearchViewModel.swift, src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift, src/Projects/BKPresentation/Sources/MainFlow/Search/VO/BookRegistrationStatus.swift, src/Projects/BKPresentation/Sources/MainFlow/Search/Coordinator/SearchCoordinator.swift, src/Projects/BKPresentation/Sources/MainFlow/Search/View/BookRegistrationStatusView.swift
BookRegistrationStatus enum 위치 이동, upsertBook 액션/사이드이펙트/상태 개선, noteReady 플래그 및 연동, Coordinator에서 NoteCoordinator 호출 등
기타 사소한 변경
src/Projects/BKDomain/Sources/Interface/Usecase/CheckTermsStateUseCase.swift, src/Projects/BKDomain/Sources/UseCase/DefaultSearchBookUseCase.swift
불필요한 import 제거, 함수 시그니처 포맷팅 등

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: 등록 성공 다이얼로그 표시
Loading

도서 등록 및 노트 작성 진입

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: 노트 작성 화면 표시
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Assessment against linked issues

Objective Addressed Explanation
필요한 UseCase 구현 (#132)
Presentation 연동 작업 (#132)

Assessment against linked issues: Out-of-scope changes

해당 이슈 목적(UseCase, Presentation 연동)에 부합하지 않는 코드 변경은 발견되지 않았습니다.

Possibly related PRs

Suggested reviewers

  • doyeonk429

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b421c20 and fc873c2.

📒 Files selected for processing (2)
  • src/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swift (1 hunks)
  • src/Projects/BKDomain/Sources/VO/BookStatus.swift (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BOOK-210-feature/#132

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary or @coderabbitai 요약 to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@clxxrlove
Copy link
Member Author

시간대가 시간대다보니 바이패스합니다.

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: 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: 상태 초기화 생명주기를 명확히 해보세요.

bookIdnoteReadied 상태가 언제 초기화되는지 명확하지 않습니다. 적절한 시점에 상태를 리셋하는 액션을 추가하는 것을 고려해보세요.

새로운 액션을 추가해보세요:

 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

📥 Commits

Reviewing files that changed from the base of the PR and between 3a6b0c6 and b421c20.

📒 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.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift
  • src/Projects/BKDomain/Sources/Interface/Usecase/BookUpsertUseCase.swift
  • src/Projects/BKDomain/Sources/Interface/Usecase/CreateRecordUseCase.swift
  • src/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swift
  • src/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift
  • src/Projects/BKData/Sources/Repository/DefaultBookRepository.swift
  • src/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.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift
  • src/Projects/BKData/Sources/Repository/DefaultRecordRepository.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift
  • src/Projects/BKDomain/Sources/Interface/Usecase/BookUpsertUseCase.swift
  • src/Projects/BKDomain/Sources/Interface/Usecase/CreateRecordUseCase.swift
  • src/Projects/BKDomain/Sources/UseCase/DefaultCreateRecordUseCase.swift
  • src/Projects/BKDomain/Sources/UseCase/DefaultBookUpsertUseCase.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift
  • src/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.swift
  • src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swift
  • src/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.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift
  • src/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.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Search/VO/BookRegistrationStatus.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift
  • src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift
  • src/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! 코디네이터 패턴이 올바르게 구현되었습니다.

책 등록 후 노트 작성 플로우로의 전환이 적절하게 구현되었습니다. bookIdNoteCoordinator에 전달하고 부모-자식 관계를 올바르게 설정하여 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: 도메인 객체 변환 로직이 깔끔합니다.

NoteFormRecordVO로 변환하는 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: 메서드 시그니처 개선이 적절합니다.

BookRegistrationStatusisbn을 모두 받아서 upsertBook 액션을 전송하는 것이 더 명확한 인터페이스를 제공합니다.


160-160: 액션 기반 상태 관리 패턴을 잘 활용했습니다.

디버그 로그 대신 loadNoteFlow 액션을 전송하여 상태 관리를 일관성 있게 처리한 것이 좋습니다.

src/Projects/BKData/Sources/API/RecordAPI.swift (4)

7-8: API 케이스명과 파라미터 타입 개선이 적절합니다.

insertfetch로 명명이 더 명확해졌고, RecordVOFetchRecordRequestDTO 사용으로 타입 안전성이 향상되었습니다.


18-22: 일관된 path 포맷팅이 적용되었습니다.

Leading slash를 추가하여 URL 경로 구성이 더 명확해졌습니다.


45-46: 도메인 객체를 DTO로 적절히 래핑했습니다.

RecordVOInsertRecordRequestDTO로 래핑하여 데이터 계층의 책임을 명확히 분리한 것이 좋습니다.


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: 책 등록 및 노트 플로우를 위한 상태 추가가 적절합니다.

bookIdnoteReadied 상태를 통해 책 등록 후 노트 작성 플로우로의 전환을 관리할 수 있습니다.


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: 책 등록 플로우를 위한 적절한 상태 관리입니다.

bookIdnoteReadied 상태가 검색에서 노트 작성으로의 플로우를 명확하게 관리합니다.


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 업데이트를 분리한 점이 좋습니다.

@clxxrlove clxxrlove force-pushed the BOOK-210-feature/#132 branch from a87d78f to fc873c2 Compare August 1, 2025 20:37
@clxxrlove clxxrlove merged commit c0fe4ab into develop Aug 1, 2025
1 check passed
@clxxrlove clxxrlove deleted the BOOK-210-feature/#132 branch August 1, 2025 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BOOK-210/feat] 1차 API 연결

2 participants

Comments