feat: 독서 기록 화면 구현#112
Conversation
|
""" Walkthrough이 변경 사항은 독서 기록(노트) 플로우를 신규 구현합니다. 노트 작성 기능에 필요한 뷰, 뷰모델, 코디네이터, 폼 데이터 구조체, 그리고 UI 컴포넌트들이 추가되었으며, 기존 컴포넌트(BKTextView 등)의 리팩토링 및 개선도 포함되어 있습니다. 관련 자산 이미지와 디자인 시스템 요소도 함께 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant HomeViewController
participant MainFlowCoordinator
participant NoteCoordinator
participant NoteViewController
participant NoteView
User->>HomeViewController: Note 버튼 탭
HomeViewController->>MainFlowCoordinator: didTapNoteButton()
MainFlowCoordinator->>NoteCoordinator: 생성 및 start()
NoteCoordinator->>NoteViewController: push NoteViewController
NoteViewController->>NoteView: 노트 작성 진행
NoteView->>NoteViewController: completeForm 이벤트 전달
NoteViewController->>NoteCoordinator: (향후) 폼 제출 처리
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Assessment against linked issues
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 (1)
🧰 Additional context used🧠 Learnings (2)📓 Common learningssrc/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (1)Learnt from: doyeonk429 🧬 Code Graph Analysis (1)src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (3)
🔇 Additional comments (12)
✨ 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
|
…tionFormProvidable
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (9)
src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift (2)
14-18: 오류 상태 처리 로직 중복을 개선하세요.
isError프로퍼티의didSet과handleError()메서드에서 동일한 로직이 중복되고 있습니다. 한 곳에서 처리하도록 통합하는 것이 좋겠습니다.다음과 같이 개선할 수 있습니다:
private var isError: Bool = false { didSet { - isError ? textField.setType(type: .error) : textField.setType(type: .normal) + updateErrorState() } }그리고
handleError()메서드를updateErrorState()로 이름을 변경하여 일관성을 유지하세요.
59-63: 레이아웃 설정을 setup으로 이동하는 것을 고려하세요.Content hugging과 compression resistance 우선순위 설정을
layoutSubviews보다는setup()메서드에서 하는 것이 더 적절할 수 있습니다.func setup() { titleLabel.setText(text: labelText) textField.placeholder = placeholder helpMessageLabel.setText(text: helpMessage) handleError() + setContentHuggingPriority(.defaultLow, for: .horizontal) + setContentCompressionResistancePriority(.required, for: .horizontal) + [titleLabel, textField, helpMessageLabel] .forEach(stackView.addArrangedSubview(_:)) addSubview(stackView) }src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift (1)
37-58: 감상평 가이드 버튼의 동작을 확인해주세요버튼은 잘 스타일링되어 있지만 실제 동작이 구현되어 있는지 확인이 필요합니다. 사용자가 버튼을 탭했을 때 어떤 가이드를 제공할 계획인가요?
감상평 작성 가이드를 표시하는 기능을 구현해드릴까요?
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (2)
134-146: 플레이스홀더 로직이 중복되어 있습니다세 개의 delegate 메서드에서 동일한 로직이 반복됩니다.
+private func updatePlaceholderVisibility() { + placeholderLabel.isHidden = !textView.text.isEmpty +} + extension BKTextView: UITextViewDelegate { public func textViewDidChange(_ textView: UITextView) { - placeholderLabel.isHidden = !textView.text.isEmpty + updatePlaceholderVisibility() } public func textViewDidBeginEditing(_ textView: UITextView) { - placeholderLabel.isHidden = !textView.text.isEmpty + updatePlaceholderVisibility() } public func textViewDidEndEditing(_ textView: UITextView) { - placeholderLabel.isHidden = !textView.text.isEmpty + updatePlaceholderVisibility() } }
128-131: 애니메이션 최적화를 고려해보세요
superview?.layoutIfNeeded()는 형제 뷰들까지 불필요하게 레이아웃을 다시 계산할 수 있습니다.UIView.animate(withDuration: 0.25) { - self.superview?.layoutIfNeeded() + self.stackView.layoutIfNeeded() }src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift (1)
12-12: 구체적인 타입 대신 프로토콜 사용을 고려해보세요델리게이트를 구체적인
NoteCoordinator타입으로 선언하면 테스트와 재사용성이 제한됩니다.-weak var delegate: NoteCoordinator? +weak var delegate: NoteViewControllerDelegate?그리고 다음과 같은 프로토콜을 정의하세요:
protocol NoteViewControllerDelegate: AnyObject { // 필요한 메서드 정의 }src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift (3)
18-26: 페이지 뷰 배열 초기화 방식을 개선해 보세요.현재
pageViews배열이 각 뷰의 인스턴스를 직접 생성하고 있는데, 이는 메모리 효율성 관점에서 개선 여지가 있습니다.-private lazy var pageViews: [UIView] = [ - SentenceRegistrationView(), - EmotionRegistrationView(), - SentenceAppreciationView() -] +private lazy var pageViews: [UIView] = makePageViews() + +private func makePageViews() -> [UIView] { + return [ + SentenceRegistrationView(), + EmotionRegistrationView(), + SentenceAppreciationView() + ] +}
80-85: Auto Layout 제약 조건 설정에 주의가 필요합니다.
contentStackView의 너비를pageViews.count로 곱하여 설정하는 부분이 정확하지만, 페이지 수가 변경될 가능성을 고려해야 합니다.contentStackView.snp.makeConstraints { $0.edges.equalTo(contentScrollView.contentLayoutGuide) - $0.width.equalTo(contentScrollView.frameLayoutGuide) - .multipliedBy(pageViews.count) + $0.width.equalTo(contentScrollView.frameLayoutGuide) + .multipliedBy(pageControl.numberOfPages) $0.height.equalTo(contentScrollView.frameLayoutGuide) }
90-114: 중첩된 스크롤뷰 구조가 복잡합니다.각 페이지를 개별
UIScrollView로 감싸는 구조가 필요한지 검토해 보세요. 현재 구현에서는 수직 스크롤을 위한 것으로 보이지만, 단순한 뷰 구조로도 충분할 수 있습니다.중첩 스크롤뷰가 정말 필요한지 확인하고, 필요하다면 다음과 같이 명확한 주석을 추가하는 것을 고려해 보세요:
func makeInnerViews() { pageViews.forEach { pageView in + // 각 페이지의 내용이 화면을 초과할 경우 수직 스크롤을 위한 래퍼 let scrollView = UIScrollView() scrollView.alwaysBounceVertical = false
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
src/Projects/BKDesign/Resources/Assets.xcassets/graphics/mascot.imageset/mascot.pngis excluded by!**/*.pngsrc/Projects/BKDesign/Resources/Assets.xcassets/graphics/mascot.imageset/mascot@2x.pngis excluded by!**/*.pngsrc/Projects/BKDesign/Resources/Assets.xcassets/graphics/mascot.imageset/mascot@3x.pngis excluded by!**/*.png
📒 Files selected for processing (21)
src/Projects/BKDesign/PreviewApp/Sources/View/BKInputCatalogView.swift(2 hunks)src/Projects/BKDesign/Resources/Assets.xcassets/graphics/Contents.json(1 hunks)src/Projects/BKDesign/Resources/Assets.xcassets/graphics/mascot.imageset/Contents.json(1 hunks)src/Projects/BKDesign/Sources/Components/BKCheckBox.swift(1 hunks)src/Projects/BKDesign/Sources/Components/BKPageControl.swift(1 hunks)src/Projects/BKDesign/Sources/Components/Button/BKButtonStyle.swift(1 hunks)src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift(1 hunks)src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift(1 hunks)src/Projects/BKDesign/Sources/Foundation/GraphicSystem/BKImage.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Home/HomeViewController.swift(4 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(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchResultCell.swift(3 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift(1 hunks)
🧰 Additional context used
🧠 Learnings (12)
📓 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 프로젝트에서 기능 구현 시 우선순위를 명확하게 설정한다. 기본 기능 구현을 먼저 완료하고, 에러 처리나 안정성 개선은 이후 단계에서 진행하는 것을 선호한다.
src/Projects/BKDesign/Resources/Assets.xcassets/graphics/Contents.json (1)
Learnt from: doyeonk429
PR: #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.
src/Projects/BKDesign/Sources/Components/Button/BKButtonStyle.swift (1)
Learnt from: doyeonk429
PR: #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)이 현재 다크 모드에서도 라이트 모드 색상을 반환하는 것은 의도적인 구현입니다. 아직 다크 모드가 구현되지 않았지만, 미래의 다크 모드 지원을 위한 코드 구조로 준비되어 있습니다.
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift (3)
Learnt from: doyeonk429
PR: #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.
Learnt from: doyeonk429
PR: #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() 메서드를 처음에 만들었지만 활용 측면에서 애매할 것 같아서 제외했다고 함. 정적 속성만으로 구현하는 것을 선호함.
Learnt from: clxxrlove
PR: #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에 따르면 작은 기기에서도 동일한 크기가 유지되어야 하며, 동적 계산보다는 상수화만 필요합니다.
src/Projects/BKDesign/Sources/Foundation/GraphicSystem/BKImage.swift (1)
Learnt from: doyeonk429
PR: #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.
src/Projects/BKDesign/Sources/Components/BKCheckBox.swift (3)
Learnt from: doyeonk429
PR: #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.
Learnt from: clxxrlove
PR: #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에 따르면 작은 기기에서도 동일한 크기가 유지되어야 하며, 동적 계산보다는 상수화만 필요합니다.
Learnt from: doyeonk429
PR: #68
File: src/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift:86-92
Timestamp: 2025-07-10T08:21:16.126Z
Learning: BKButtonGroup의 horizontal 레이아웃에서 stackView.distribution을 .fillProportionally로 설정한 것은 의도된 디자인입니다. doyeonk429는 버튼들이 콘텐츠 길이에 따라 다른 너비를 가지는 것을 선호합니다.
src/Projects/BKDesign/Resources/Assets.xcassets/graphics/mascot.imageset/Contents.json (1)
Learnt from: doyeonk429
PR: #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.
src/Projects/BKPresentation/Sources/MainFlow/Home/HomeViewController.swift (1)
Learnt from: doyeonk429
PR: #68
File: src/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift:86-92
Timestamp: 2025-07-10T08:21:16.126Z
Learning: BKButtonGroup의 horizontal 레이아웃에서 stackView.distribution을 .fillProportionally로 설정한 것은 의도된 디자인입니다. doyeonk429는 버튼들이 콘텐츠 길이에 따라 다른 너비를 가지는 것을 선호합니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift (1)
Learnt from: clxxrlove
PR: #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에 따르면 작은 기기에서도 동일한 크기가 유지되어야 하며, 동적 계산보다는 상수화만 필요합니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift (1)
Learnt from: clxxrlove
PR: #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.
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (1)
Learnt from: doyeonk429
PR: #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)이 현재 다크 모드에서도 라이트 모드 색상을 반환하는 것은 의도적인 구현입니다. 아직 다크 모드가 구현되지 않았지만, 미래의 다크 모드 지원을 위한 코드 구조로 준비되어 있습니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift (1)
Learnt from: clxxrlove
PR: #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에 따르면 작은 기기에서도 동일한 크기가 유지되어야 하며, 동적 계산보다는 상수화만 필요합니다.
🧬 Code Graph Analysis (6)
src/Projects/BKDesign/PreviewApp/Sources/View/BKInputCatalogView.swift (1)
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (1)
setErrorMessage(78-80)
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchResultCell.swift (1)
src/Projects/BKDesign/Sources/Extensions/UIView+.swift (1)
addSubviews(7-9)
src/Projects/BKPresentation/Sources/MainFlow/Home/HomeViewController.swift (1)
src/Projects/BKPresentation/Sources/MainFlow/Home/MainFlowCoordinator.swift (1)
didTapNoteButton(53-60)
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (3)
src/Projects/BKDesign/Sources/Extensions/UIColor+.swift (3)
bkBorderColor(65-76)bkBackgroundColor(38-50)bkContentColor(52-63)src/Projects/BKDesign/Sources/Components/Label/BKLabel.swift (1)
setText(80-83)src/Projects/BKDesign/Sources/Extensions/UIView+.swift (1)
addSubviews(7-9)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift (3)
src/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift (1)
singleFullButton(162-175)src/Projects/BKDesign/Sources/Extensions/UIView+.swift (1)
addSubviews(7-9)src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift (1)
makeNoteForm(13-44)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift (3)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift (3)
setupView(60-64)setupLayout(70-96)registrationForm(100-104)src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift (3)
setupView(55-63)setupLayout(69-102)registrationForm(106-111)src/Projects/BKDesign/Sources/Extensions/UIView+.swift (1)
addSubviews(7-9)
🪛 SwiftLint (0.57.0)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift
[Warning] 54-54: TODOs should be resolved (- ViewModel 구현 이후 추가)
(todo)
[Warning] 53-53: Unused parameter in a closure should be replaced with _
(unused_closure_parameter)
🔇 Additional comments (44)
src/Projects/BKDesign/Resources/Assets.xcassets/graphics/mascot.imageset/Contents.json (1)
1-23: 에셋 카탈로그 구성이 올바릅니다.표준 iOS 에셋 카탈로그 형식을 따르고 있으며, 1x, 2x, 3x 해상도 변형을 모두 포함하고 있습니다. 구조가 정확합니다.
src/Projects/BKDesign/Sources/Foundation/GraphicSystem/BKImage.swift (1)
55-58: 디자인 시스템 구조가 일관성 있게 확장되었습니다.기존 Icon, Checkbox enum과 동일한 패턴으로 Graphics enum을 추가하여 일관성을 유지하고 있습니다. 네임스페이스 구성이 적절합니다.
src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift (1)
5-105: 전반적으로 잘 구현된 컴포넌트입니다.텍스트 필드 컴포넌트가 적절한 캡슐화와 공개 API를 제공하며, 오류 상태 관리 기능도 포함하고 있습니다. 레이아웃과 초기화 패턴도 프로젝트 규칙을 잘 따르고 있습니다.
src/Projects/BKDesign/Resources/Assets.xcassets/graphics/Contents.json (1)
1-6: 에셋 카탈로그 메타데이터가 올바릅니다.graphics 폴더에 대한 표준 에셋 카탈로그 메타데이터 구성입니다.
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift (1)
134-134: 마스코트 이미지 적용이 올바릅니다.새로 추가된
BKImage.Graphics.mascot에셋을 올바르게 사용하고 있습니다. TODO 주석도 적절하며, 향후 그래픽 디자인 작업 후 변경될 예정임을 명시하고 있습니다.src/Projects/BKDesign/Sources/Components/Button/BKButtonStyle.swift (1)
96-100: 공개 이니셜라이저 추가로 API 유연성 향상
BKButtonColorSet에 명시적인 공개 이니셜라이저를 추가하여 커스텀 버튼 스타일링의 유연성을 제공합니다. 기존solid(_)팩토리 메서드와 함께 다양한 버튼 상태 색상 조합을 쉽게 만들 수 있게 되었습니다.src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchResultCell.swift (3)
42-42: UI 일관성을 위한 구분선 컴포넌트 추가
BKDivider를 사용하여 검색 결과 셀 간의 시각적 구분을 명확히 했습니다. 디자인 시스템의 표준 구분선 컴포넌트를 활용한 좋은 선택입니다.
54-54: 서브뷰 추가 방식 개선
UIView+확장의addSubviews메서드를 활용하여 여러 서브뷰를 한 번에 추가하는 깔끔한 방식입니다.
78-80: 구분선 레이아웃 제약 조건 적절히 설정구분선을 셀 하단에 고정하는 제약 조건이 올바르게 설정되어 있어 셀 간 구분이 명확해집니다.
src/Projects/BKPresentation/Sources/MainFlow/Home/MainFlowCoordinator.swift (1)
53-60: 노트 플로우 코디네이터 추가로 네비게이션 확장기존 설정 및 검색 플로우와 동일한 패턴을 따라 노트 플로우 코디네이터를 구현했습니다. 자식 코디네이터 배열에 추가하여 메모리 관리도 적절히 처리되었습니다.
src/Projects/BKDesign/Sources/Components/BKCheckBox.swift (2)
43-45: 고유 콘텐츠 크기 명시로 레이아웃 개선
intrinsicContentSize를 오버라이드하여 체크박스의 고정 크기를 명시했습니다. 이는 Auto Layout 계산을 더 정확하게 만들고 일관된 크기를 보장합니다.
50-57: 이미지 뷰 중앙 정렬로 시각적 일관성 향상이미지 뷰를 가장자리에 고정하는 대신 중앙에 배치하고 고정 크기를 설정하여, 컨테이너 크기에 관계없이 체크박스 아이콘이 항상 중앙에 정렬되도록 개선했습니다.
src/Projects/BKPresentation/Sources/MainFlow/Home/HomeViewController.swift (4)
30-34: 노트 버튼 추가로 홈 화면 기능 확장기존 설정 및 검색 버튼과 동일한 구조로 노트 버튼을 구현하여 일관성을 유지했습니다.
52-52: 스택 뷰에 노트 버튼 추가새로운 노트 버튼이 수직 스택 뷰에 적절히 추가되어 홈 화면의 버튼 레이아웃이 확장되었습니다.
69-69: 타겟-액션 바인딩 일관성 유지노트 버튼의 타겟-액션 바인딩이 기존 버튼들과 동일한 패턴으로 구현되어 일관성을 유지합니다.
84-86: 코디네이터 패턴 준수
openNote메서드가 기존 네비게이션 메서드와 동일한 구조로 구현되어 코디네이터 패턴을 일관되게 따릅니다.src/Projects/BKPresentation/Sources/MainFlow/Note/Coordinator/NoteCoordinator.swift (3)
6-6: LGTM! 표준 코디네이터 패턴을 잘 따르고 있습니다.
SessionExpirationNotifying프로토콜 준수로 인증 시스템과의 통합도 적절하게 처리되어 있습니다.
11-17: 의존성 주입이 적절하게 구현되었습니다.부모 코디네이터와 네비게이션 컨트롤러를 주입받는 구조가 깔끔하고, weak reference 사용으로 메모리 리크도 방지하고 있습니다.
19-23: 뷰 컨트롤러 생성과 네비게이션 처리가 적절합니다.델리게이트 설정과 애니메이션이 포함된 push 동작이 표준 패턴을 잘 따르고 있습니다.
src/Projects/BKDesign/Sources/Components/BKPageControl.swift (4)
6-18: 공개 인터페이스가 잘 설계되었습니다.
numberOfPages와currentPage프로퍼티의didSet옵저버를 통한 UI 업데이트와.valueChanged이벤트 전송이 적절하게 구현되어 있습니다.
35-37: init(coder:) 비활성화가 적절합니다.프로그래밍 방식으로만 생성되는 컴포넌트의 의도가 명확하게 표현되어 있습니다.
50-63: 인디케이터 설정 로직이 효율적입니다.기존 뷰들을 정리하고 새로운 인디케이터를 생성하는 로직이 깔끔하며,
updateIndicators()호출로 초기 상태 설정도 적절합니다.
74-78: 레이아웃 상수가 적절하게 캡슐화되었습니다.기존 학습에 따르면 clxxrlove님이 상수 네임스페이스로 enum을 선호하시는데, 이 구현이 그 선호도와 일치합니다.
src/Projects/BKDesign/PreviewApp/Sources/View/BKInputCatalogView.swift (3)
75-87: 텍스트 입력 컴포넌트 타입 변경이 적절합니다.
BKTextView에서BKTextFieldView로의 변경이 단일 라인 입력의 의도를 명확하게 표현하고 있습니다.
91-99: 새로운 멀티라인 텍스트 뷰 추가가 적절합니다.리팩토링된
BKTextView컴포넌트를 보여주는 예시가 잘 구성되어 있습니다.
130-133: 카탈로그 뷰 설정이 완전합니다.새로운 컴포넌트들이 스택 뷰에 적절하게 추가되었고,
setErrorMessage호출로 에러 상태 시연도 포함되어 있습니다.src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteForm.swift (2)
5-10: 데이터 모델이 간결하고 명확합니다.노트 폼의 필수 속성들이 불변 프로퍼티로 적절하게 정의되어 있습니다.
13-44: 팩토리 메서드가 잘 구현되었습니다.다양한
RegistrationForm타입에서 데이터를 추출하고, guard 문으로 필수 값들의 존재를 검증하는 로직이 안전하고 명확합니다.src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceRegistrationView.swift (6)
7-10: 데이터 구조체가 명확하게 정의되었습니다.페이지와 문장 정보를 담는 간단한 구조가 적절합니다.
22-30: 입력 컴포넌트 설정이 적절합니다.
BKTextFieldView와BKTextView를 사용한 페이지와 문장 입력 필드 구성이 UI 요구사항에 맞습니다.
32-53: 커스텀 버튼 스타일링이 세심하게 구현되었습니다.브랜드 컬러와 테두리, 아이콘을 활용한 스캔 버튼의 시각적 디자인이 잘 적용되어 있습니다.
69-102: 레이아웃 제약 조건이 체계적으로 구성되었습니다.SnapKit을 사용한 제약 조건 설정이 깔끔하고, 각 컴포넌트 간의 간격과 정렬이 적절합니다.
105-112: 프로토콜 구현이 정확합니다.
RegistrationFormProvidable프로토콜을 통해 폼 데이터를 적절하게 제공하고 있습니다.
115-122: 레이아웃 상수 캡슐화가 우수합니다.기존 학습에 따르면 clxxrlove님이 선호하는 enum을 사용한 상수 네임스페이스 패턴이 적절하게 적용되었습니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift (1)
6-26: 구조가 잘 설계되었습니다!단방향 데이터 플로우 패턴을 위한 기본 구조가 적절하게 구성되어 있습니다. 향후 구현 시 State, Action, SideEffect를 채워나가기 좋은 구조입니다.
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (1)
3-5: 리팩토링 설명이 명확합니다!기존 컴포넌트와의 차이점을 잘 설명해주셔서 다른 개발자들이 이해하기 쉽습니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift (1)
63-70: 멀티 페이지 네비게이션 처리가 잘 구현되었습니다!현재 페이지에 따라 뒤로가기 동작을 다르게 처리하는 로직이 명확하고 직관적입니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift (7)
8-16: 타입 정의가 잘 구성되어 있습니다.
RegistrationFormenum과RegistrationFormProvidableprotocol이 각 페이지의 폼 데이터를 일관된 방식으로 관리할 수 있도록 잘 설계되어 있습니다. 프로토콜 기반 접근 방식으로 각 페이지 뷰가 독립적으로 폼 데이터를 제공할 수 있어 모듈성이 좋습니다.
30-35: 스택뷰 설정이 적절합니다.
horizontalaxis와fillEquallydistribution으로 각 페이지가 동일한 너비를 갖도록 설정한 것이 멀티페이지 레이아웃에 적합합니다.
47-48: 스크롤 설정이 의도와 일치합니다.
isPagingEnabled = true와isScrollEnabled = false조합으로 페이지 컨트롤과 버튼을 통해서만 페이지 전환이 가능하도록 제한한 것이 UX 측면에서 적절합니다.
51-52: 타겟-액션 패턴 사용이 적절합니다.페이지 컨트롤과 버튼의 이벤트 처리를 타겟-액션 패턴으로 구현한 것이 UIKit의 관례에 맞습니다.
116-121: 폼 데이터 생성 로직이 견고합니다.
compactMap을 사용하여 nil 값을 제거하고, 정적 메서드를 통해 폼 데이터를 생성하는 방식이 안전하고 명확합니다.
123-126: 페이지 전환 애니메이션 구현이 적절합니다.페이지 컨트롤 변경 시 스크롤뷰의 contentOffset을 애니메이션과 함께 업데이트하는 방식이 부드러운 사용자 경험을 제공합니다.
143-149: 레이아웃 상수 정의가 체계적입니다.
LayoutConstantsenum을 사용하여 매직 넘버를 피하고 레이아웃 값을 중앙집중식으로 관리하는 방식이 좋습니다. 학습된 내용에 따르면 clxxrlove님이 선호하는 enum 사용 패턴과도 일치합니다.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift (1)
53-53: 사용하지 않는 클로저 파라미터를 수정해주세요SwiftLint가 사용하지 않는 파라미터를 감지했습니다.
- .sink { [weak self] _ in + .sink { [weak self] _ in
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/Projects/BKPresentation/Sources/MainFlow/Note/View/SentenceAppreciationView.swift
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
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.652Z
Learning: clxxrlove는 NoteView의 nextButtonTapped 메서드에서 폼 검증 실패 시 첫 번째 페이지로 되돌아가는 로직을 임시로 구현했으며, 추후 적절한 에러 처리 로직을 추가할 예정이라고 명시했다. 임시 화면 구현 단계에서는 기본 동작에 집중하고 에러 처리는 후속 작업으로 계획하는 것을 선호한다.
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 프로젝트에서 기능 구현 시 우선순위를 명확하게 설정한다. 기본 기능 구현을 먼저 완료하고, 에러 처리나 안정성 개선은 이후 단계에서 진행하는 것을 선호한다.
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (1)
Learnt from: doyeonk429
PR: #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)이 현재 다크 모드에서도 라이트 모드 색상을 반환하는 것은 의도적인 구현입니다. 아직 다크 모드가 구현되지 않았지만, 미래의 다크 모드 지원을 위한 코드 구조로 준비되어 있습니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift (2)
Learnt from: clxxrlove
PR: #112
File: src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift:128-140
Timestamp: 2025-07-28T10:45:09.652Z
Learning: clxxrlove는 NoteView의 nextButtonTapped 메서드에서 폼 검증 실패 시 첫 번째 페이지로 되돌아가는 로직을 임시로 구현했으며, 추후 적절한 에러 처리 로직을 추가할 예정이라고 명시했다. 임시 화면 구현 단계에서는 기본 동작에 집중하고 에러 처리는 후속 작업으로 계획하는 것을 선호한다.
Learnt from: clxxrlove
PR: #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.
🧬 Code Graph Analysis (1)
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (3)
src/Projects/BKDesign/Sources/Extensions/UIColor+.swift (3)
bkBorderColor(65-76)bkBackgroundColor(38-50)bkContentColor(52-63)src/Projects/BKDesign/Sources/Components/Label/BKLabel.swift (1)
setText(80-83)src/Projects/BKDesign/Sources/Extensions/UIView+.swift (1)
addSubviews(7-9)
🪛 SwiftLint (0.57.0)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift
[Warning] 54-54: TODOs should be resolved (- ViewModel 구현 이후 추가)
(todo)
🔇 Additional comments (13)
src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteViewController.swift (5)
7-9: 이벤트 정의가 명확합니다.NoteViewEvent 열거형이 깔끔하게 정의되어 있으며, 폼 완료 이벤트를 적절히 표현하고 있습니다.
11-26: 클래스 구조와 초기화가 잘 설계되었습니다.MVVM + Coordinator 패턴을 적절히 활용하고 있으며, weak delegate로 메모리 누수를 방지하고 있습니다. AnyViewBindableViewModel 래퍼 사용도 적절합니다.
28-40: 뷰 라이프사이클 관리가 적절합니다.탭바 숨김, 커스텀 백 버튼 설정, 인터랙티브 팝 제스처 비활성화가 노트 플로우에 맞게 잘 구현되어 있습니다.
42-45: UI 상태 복원이 적절합니다.뷰가 사라질 때 탭바를 다시 표시하여 UI 상태를 올바르게 복원하고 있습니다.
63-70: 커스텀 백 버튼 로직이 올바르게 구현되었습니다.페이지 상태에 따른 분기 처리가 적절하며, 다중 페이지 네비게이션을 잘 지원하고 있습니다.
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (8)
3-5: 주석 내용이 명확하고 변경 사항을 잘 설명합니다.네이밍 변경과 새로운 컴포넌트 추가에 대한 목적이 명확하게 설명되어 있습니다.
11-27: UITextView 설정이 잘 구현되어 있습니다.텍스트뷰의 기본 스타일링과 속성들이 적절하게 설정되어 있습니다. 특히
textContainer.lineFragmentPadding = .zero설정으로 불필요한 패딩을 제거한 것이 좋습니다.
58-60: computed property로 텍스트 접근 제공이 적절합니다.읽기 전용
text프로퍼티로 현재 텍스트 값에 안전하게 접근할 수 있도록 구현되어 있습니다.
107-130: 레이아웃 로직이 복잡하지만 기능적으로 올바릅니다.타이틀 레이블의 존재 여부에 따라 다른 제약 조건을 적용하는 로직이 적절합니다. 플레이스홀더 레이블의 위치도 텍스트뷰 내부의 적절한 위치에 배치되어 있습니다.
132-147: 동적 타이틀 레이블 관리가 잘 구현되어 있습니다.타이틀 텍스트의 유무에 따라 레이블을 동적으로 추가/제거하고, 애니메이션도 포함되어 있어 사용자 경험이 향상됩니다.
149-169: 에러 상태 관리가 체계적으로 구현되어 있습니다.에러 메시지 표시/숨김과 함께 테두리 색상 변경이 동기화되어 있으며, 애니메이션도 적절하게 적용되어 있습니다.
171-183: UITextViewDelegate 구현이 플레이스홀더 동작에 완벽합니다.텍스트 변경, 편집 시작/종료 시점에서 플레이스홀더의 표시/숨김이 일관되게 처리되어 있습니다.
185-191: 레이아웃 상수들이 디자인 시스템을 잘 활용하고 있습니다.BK 디자인 시스템의 상수들을 사용하여 일관된 스타일링을 유지하고 있습니다.
| public func setLabelText(_ text: String?) { | ||
| self.labelText = text | ||
| } | ||
|
|
||
| public func setErrorMessage(_ errorMessage: String) { | ||
| self.errorMessage = errorMessage | ||
| } |
| registerButton.snp.makeConstraints { | ||
| $0.top.equalTo(sentenceTextView.snp.bottom) | ||
| .offset(LayoutConstants.buttonOffset) | ||
| $0.trailing.equalToSuperview() | ||
| .inset(LayoutConstants.horizontalInset) | ||
| $0.height.equalTo(LayoutConstants.buttonHeight) | ||
| $0.bottom.equalToSuperview() |
There was a problem hiding this comment.
Q) 이부분 Snapkit 제약 조건 충돌 경고 날 것 같은데 발생 안하나용?
There was a problem hiding this comment.
의외로 여기서는 안잡히긴 하는데 ... scrollView에서 충돌나서 이거는 천천히 수정해볼게요. 수정 후 머지하겠습니다.
There was a problem hiding this comment.
으아아 아니다 이거 말고 다음 작업도 이거에서 연계되는거라 거기에서 작업할게요
🔗 관련 이슈
📘 작업 유형
📙 작업 내역
🧪 테스트 내역
🎨 스크린샷 또는 시연 영상 (선택)
백버튼 동작
ScreenRecording_07-28-2025.19-20-25_1.MP4
Form 완성에 성공한 경우 (하드코딩으로 UI 테스트)
ScreenRecording_07-28-2025.19-30-23_1.MP4
Form 완성에 실패한 경우
ScreenRecording_07-28-2025.19-33-20_1.mov
✅ PR 체크리스트
💬 추가 설명 or 리뷰 포인트 (선택)
Summary by CodeRabbit
신규 기능
UI 개선
버그 수정