Conversation
Walkthrough여러 UI 컴포넌트에서 레이블 시스템을 정비(BKLabel 적용 경로 변경·신규 BKLabel2 추가 및 다수 마이그레이션), 텍스트필드 클리어버튼/스타일 확장, 다이얼로그 부제목을 옵셔널로 변경했으며 버튼 생성 API에 사이즈 인자가 도입되고 다수 화면의 레이아웃·카피·스페이싱이 조정되었습니다. 빌드 프로비저닝 프로필도 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User as 사용자
participant SV as SearchView
participant TF as BKSearchTextField(BKBaseTextField)
Note over SV,TF: 상태 적용(.result)
SV->>SV: applySnapshot(state)
alt 결과 책 0개
SV->>TF: setClearButtonMode(.whileEditing)
else 결과 책 존재
SV->>TF: setClearButtonMode(.always)
end
Note over User,SV: 최근 검색어 탭
User->>SV: didTapRecent(keyword)
SV->>SV: setSearchBarText(with: keyword)
SV-->>TF: 내부적으로 text 업데이트
sequenceDiagram
autonumber
participant VC as Caller
participant D as BKDialog
participant TS as titleStack
VC->>D: init(title, subtitle: String?)
D->>D: setup()
D->>TS: addArrangedSubview(titleLabel)
alt subtitle != nil && subtitle != ""
D->>TS: addArrangedSubview(subtitleLabel)
D->>D: subtitleLabel.isHidden = false
else
D->>D: subtitleLabel.isHidden = true
end
sequenceDiagram
autonumber
participant BD as BookDetailView
participant SR as seedReportView
participant DV as divider
BD->>BD: applySnapshot(items)
alt items.isEmpty
BD->>SR: isHidden = true
BD->>BD: seedReportZeroHeight.priority = required
BD->>DV: dividerTopToButtons.priority = high
else
BD->>SR: isHidden = false
BD->>BD: seedReportZeroHeight.priority = low
BD->>DV: dividerTopToSeed.priority = high
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes ✨ 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. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift (1)
15-19: isError 토글 시 helpMessageLabel 색상 미갱신 버그
isError의didSet에서 텍스트필드 타입만 바꾸고,helpMessageLabel색상은 갱신하지 않습니다. 현재handleError()가 해당 색상 반영을 담당하지만 초기setup()에서만 호출되어, 이후setHelpMessage(_, isError:)로 에러 상태를 바꿔도 라벨 색상이 업데이트되지 않을 수 있습니다.다음과 같이
didSet에서handleError()를 호출하도록 수정해 주세요:private var isError: Bool = false { didSet { - isError ? textField.setType(type: .error) : textField.setType(type: .normal) + handleError() } }src/Projects/BKPresentation/Sources/Common/Extension/UINavigationController+.swift (1)
268-275: 강제 언래핑으로 인한 크래시 위험 제거
imageWithOffset의 반환값을 강제 언래핑(!)하고 있어 드물게 nil 발생 시 크래시 위험이 있습니다. 안전한 디폴트(원본 이미지)로 폴백하도록 수정하세요.- let backImage = BKImage.Icon.chevronLeft - .withRenderingMode(.alwaysTemplate) - .imageWithOffset(x: -4, y: 2)! - .withAlignmentRectInsets( - UIEdgeInsets(top: 0, left: -16, bottom: 0, right: 0) - ) + let baseChevron = BKImage.Icon.chevronLeft + .withRenderingMode(.alwaysTemplate) + let offsetChevron = baseChevron.imageWithOffset(x: -4, y: 2) ?? baseChevron + let backImage = offsetChevron.withAlignmentRectInsets( + UIEdgeInsets(top: 0, left: -16, bottom: 0, right: 0) + )src/Projects/BKDesign/Sources/Components/TextField/BKBaseTextField.swift (1)
146-160: clear 버튼 rightView 크기 미설정으로 표시되지 않을 수 있음
rightView는 Auto Layout이 아닌 뷰의 frame에 의존합니다. 현재 컨테이너 뷰 크기를 지정하지 않아 clear 버튼이 보이지 않거나 영역이 0으로 계산될 가능성이 큽니다. 초기 hidden 상태도 설정하는 것이 안전합니다.func applyClearButtonStyle() { - let containerView = UIView() - containerView.addSubview(clearButton) - addTarget(self, action: #selector(updateClearButtonVisibility), for: .editingChanged) - clearButton.addTarget(self, action: #selector(clearButtonTapped), for: .touchUpInside) - rightView = containerView - rightViewMode = .whileEditing + let containerView = UIView() + // UITextField는 rightView의 오토레이아웃을 사용하지 않으므로 명시적 크기가 필요합니다. + containerView.frame = CGRect( + x: 0, y: 0, + width: LayoutConstants.textRightInset, + height: LayoutConstants.height + ) + containerView.addSubview(clearButton) + addTarget(self, action: #selector(updateClearButtonVisibility), for: .editingChanged) + addTarget(self, action: #selector(updateClearButtonVisibility), for: .editingDidBegin) + clearButton.addTarget(self, action: #selector(clearButtonTapped), for: .touchUpInside) + rightView = containerView + rightViewMode = .whileEditing + // 초기 상태 반영 + clearButton.isHidden = (text?.isEmpty ?? true) clearButton.snp.makeConstraints { $0.height.width.equalTo(LayoutConstants.clearButtonSize) $0.top.leading.bottom.equalToSuperview() $0.trailing.equalToSuperview() .inset(LayoutConstants.horizontalInset) } }src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailView.swift (1)
75-80: BKButton(size:) 필수화 사항 반영 필요
addNoteButton에서 기본 생성자(BKButton())를 사용 중입니다. PR 요약대로BKButton생성자가style및size인자를 요구하도록 변경되었으므로, 컴파일 타임 오류는 아니지만 디자인 일관성과 향후 유지보수를 위해 아래와 같이 명시적 인자 전달로 교체해주세요.수정 예시 (디자인 스펙에 맞게
style/size값 조정):- private let addNoteButton: BKButton = { - let button = BKButton() + private let addNoteButton: BKButton = { + let button = BKButton(style: .primary, size: .medium) button.title = "독서 기록 추가" button.setContentHuggingPriority(.defaultLow, for: .horizontal) return button }()검토된 사용처:
- SentenceRegistrationView: 이미
style/size전달 중- LoginView: 이미
style/size(또는custom) 전달 중- SentenceAppreciationView: 이미
style/size전달 중BookDetailView에도 동일한 패턴을 적용해 주세요.
🧹 Nitpick comments (32)
src/Projects/BKPresentation/Sources/MainFlow/Setting/View/SettingCell.swift (1)
41-41: Subviews는 contentView에 추가하는 것이 안전합니다현재 셀(self)에 직접 addSubview 하고 있어 selection/highlight 배경, layoutMargins 처리에서 미묘한 차이가 생길 수 있습니다. 영향이 없으면 유지해도 되지만, 일반적인 UICollectionViewCell 관례와 재사용 안정성을 위해 contentView에 추가하는 것을 권장합니다.
예시:
[titleLabel, iconView, versionLabel].forEach { contentView.addSubview($0) }src/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift (2)
100-104: horizontal 레이아웃 분배 전략 재검토 제안 (.fillProportionally 권장)과거 팀 합의(학습 메모)에 따르면 horizontal에서는 콘텐츠 길이에 비례한 너비(.fillProportionally)를 선호했습니다. 현재는 .fillEqually여서 긴 텍스트 버튼이 잘리는 케이스가 생길 수 있습니다. 스코프 외 변경이지만, 다음과 같이 바꾸는 것을 권장합니다.
원하시면 PR 분리해 반영 패치 제안 드리겠습니다.
예시:
- .horizontal: stackView.distribution = .fillProportionally
- .fullWidth: 현행대로 .fillEqually 유지(두 버튼 균등 너비 의도)
211-214: threeButtonGroup의 secondary/primary에도 사이즈 명시로 일관성 유지 제안twoButtonGroup/singleFullButton는 .large를 명시하지만, threeButtonGroup은 기본값(아마 .medium)에 의존합니다. 동일 화면군에서 버튼 크기가 섞여 보일 수 있으므로, center/right에도 size를 명시하는 것을 권장합니다.
예시(참고용):
let centerButton = BKButton.secondary(title: centerTitle, size: .large) let rightButton = BKButton.primary(title: rightTitle, size: .large)src/Projects/BKPresentation/Sources/MainFlow/Home/View/HomeView.swift (1)
149-151: 매직 넘버(2) 대신 레이아웃 상수 사용으로 일관성 확보 권장컬렉션뷰 상단 오프셋을 하드코딩된
2가 아니라LayoutConstants.collectionTopSpacing을 사용하도록 변경하면, 상수 한 곳으로 디자인 스펙을 관리할 수 있어 유지보수성과 일관성이 좋아집니다. 또한 empty 상태(homeEmptyView)와 non-empty 상태 간 상단 간격이 상수 기반으로 동기화되어 UI 불일치 위험을 줄일 수 있습니다.아래와 같이 수정 제안드립니다:
- $0.top - .equalTo(bookSectionTitleLabel.snp.bottom) - .offset(2) + $0.top + .equalTo(bookSectionTitleLabel.snp.bottom) + .offset(LayoutConstants.collectionTopSpacing)추가 확인 사항:
- 현재
homeEmptyView는bookSectionTitleLabel.snp.bottom에 offset 없이 붙고(라인 156-160), 높이에서만collectionTopSpacing을 더하고 있습니다. 실제 의도가 타이틀과 콘텐츠 사이 간격의 시각적 일치라면, empty 상태에서도 top에 동일한 offset을 주는 것이 자연스럽습니다. 디자이너 스펙에 맞게 아래와 같이 검토해 주세요(예시):homeEmptyView.snp.makeConstraints { $0.top.equalTo(bookSectionTitleLabel.snp.bottom) .offset(LayoutConstants.collectionTopSpacing) // 필요 시 추가 $0.leading.trailing.equalToSuperview() $0.height.equalTo(LayoutConstants.collectionHeight + LayoutConstants.collectionTopSpacing) }검증 제안:
- 책 목록이 비어있는 상태/비어있지 않은 상태 모두에서, 타이틀-콘텐츠 상단 간격이 동일하게 보이는지 스냅샷 혹은 시뮬레이터로 확인 부탁드립니다.
src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift (1)
199-200: spacing 매직 넘버(24) → 디자인 토큰 사용 검토간격을 40→24로 줄인 의도 자체는 이해됩니다. 다만, 다른 곳에서
BKSpacing/BKInset토큰을 쓰는 패턴과 일관되게 24도 토큰으로 표현 가능하면 교체를 권장합니다(예:BKSpacing.spacingX또는BKInset.insetY).추가 확인:
- 디자이너 스펙에서 정확히 24pt가 지정된 값인지, 혹은 가장 가까운 토큰으로 스냅이 의도인지 확인해 주세요. 다양한 화면 크기에서 시각 균형이 유지되는지도 함께 검증 부탁드립니다.
src/Projects/BKDesign/Sources/Foundation/Typography/BKTextStyle.swift (1)
345-365: 중복 제거: mutableAttributedString는 기존 attributedString 결과를 재사용하세요동일한 속성 구성 로직이 중복됩니다. 유지보수성과 일관성을 위해
attributedString을 호출해 생성한 결과를NSMutableAttributedString으로 감싸는 방식으로 단순화하는 것을 권장합니다.- public func mutableAttributedString( - from text: String, - color: UIColor = .label, - extraAttributes: [NSAttributedString.Key: Any] = [:] - ) -> NSMutableAttributedString { - var attributes: [NSAttributedString.Key: Any] = [ - .font: uiFont ?? UIFont.systemFont(ofSize: fontAttributes.fontSize.rawValue), - .foregroundColor: color, - .paragraphStyle: paragraphStyle - ] - - if let letterSpacing = fontAttributes.letterSpacing { - let actualLetterSpacing = letterSpacing.calculateAbsoluteLetterSpacing( - for: fontAttributes.fontSize.rawValue - ) - attributes[.kern] = actualLetterSpacing - } - - attributes.merge(extraAttributes) { $1 } - return NSMutableAttributedString(string: text, attributes: attributes) - } + public func mutableAttributedString( + from text: String, + color: UIColor = .label, + extraAttributes: [NSAttributedString.Key: Any] = [:] + ) -> NSMutableAttributedString { + return NSMutableAttributedString( + attributedString: attributedString(from: text, color: color, extraAttributes: extraAttributes) + ) + }src/Projects/BKPresentation/Sources/Common/Extension/UINavigationController+.swift (1)
342-351: 렌더 실패 시 안전 폴백 반환
UIGraphicsGetImageFromCurrentImageContext()가 nil일 가능성(메모리 부족/컨텍스트 실패 등)을 고려해 자기 자신으로 폴백하세요. 현재 시그니처(UIImage?)를 유지하면서도 사실상 nil을 반환하지 않게 만들 수 있습니다.- func imageWithCustomRect(_ rect: CGRect, canvasSize: CGSize? = nil) -> UIImage? { + func imageWithCustomRect(_ rect: CGRect, canvasSize: CGSize? = nil) -> UIImage? { let finalCanvasSize = canvasSize ?? size UIGraphicsBeginImageContextWithOptions(finalCanvasSize, false, scale) defer { UIGraphicsEndImageContext() } draw(in: rect) - return UIGraphicsGetImageFromCurrentImageContext()?.withRenderingMode(renderingMode) + return UIGraphicsGetImageFromCurrentImageContext()?.withRenderingMode(renderingMode) ?? self }src/Projects/BKDesign/Sources/Components/TextField/BKBaseTextField.swift (2)
129-135: 타입 변경 시 borderWidth도 함께 갱신 필요초기 구성에서는
.normal일 때borderWidth = 0으로 설정하지만, 이후setType으로 타입을 바꿀 때는typeDidChanged()가borderColor만 갱신합니다. 이로 인해.normal로 되돌렸을 때도 border가 남는 불일치가 발생합니다.다음과 같이
typeDidChanged()를 수정하는 것을 제안합니다(선택 적용):// 파일 내 기존 메서드 교체 제안 (참고용) func typeDidChanged() { switch textFieldType { case .normal: layer.borderWidth = 0 layer.borderColor = textFieldType.borderColor.cgColor default: layer.borderWidth = LayoutConstants.borderWidth layer.borderColor = textFieldType.borderColor.cgColor } }
104-106: rightViewMode 중복 설정 가능성초기
configure()→applyClearButtonStyle()에서 항상.whileEditing으로 덮습니다. 외부에서setClearButtonMode(_)를 사용하는 경우, 호출 순서에 따라 설정이 덮일 수 있습니다. 문서화하거나applyClearButtonStyle()에서 기존rightViewMode를 유지하도록 조정하는 것을 고려하세요.src/Projects/BKDesign/Sources/Components/Dialog/BKDialog.swift (2)
108-119: 빈 문자열 subtitle은 스택에 추가하지 않는 편이 일관적입니다
setup()에서는subtitleText != nil만 검사하여 빈 문자열도 스택에 추가될 수 있습니다.configure()에서는 빈 문자열이면 hidden 처리하므로 스택 구조와 표시 로직이 엇갈립니다. 초기부터 비어있는 경우 추가하지 않도록 하는 것이 깔끔합니다.- // subtitle이 있을 때만 추가 - if subtitleText != nil { + // subtitle이 유효할 때만 추가 + if let subtitle = subtitleText?.trimmingCharacters(in: .whitespacesAndNewlines), + !subtitle.isEmpty { titleStack.addArrangedSubview(subtitleLabel) }
145-151: 매직 넘버(4) 대신 상수 사용
LayoutConstants.buttonBottomInset가 선언되어 있으나 사용되지 않았습니다. 일관성을 위해 상수로 교체하세요.buttonGroup.snp.makeConstraints { $0.top.equalTo(rootStack.snp.bottom) .offset(LayoutConstants.buttonTopInset) $0.leading.trailing.equalToSuperview() $0.height.equalTo(84) - $0.bottom.equalToSuperview().inset(4) + $0.bottom.equalToSuperview().inset(LayoutConstants.buttonBottomInset) }src/Projects/BKDesign/Sources/Components/Label/BKLabel2.swift (3)
31-35: 오류 메시지 수정: setFont가 아니라 setFontStyle입니다사용자 가이던스 메시지가 실제 제공 API와 다릅니다. 혼선을 줄이기 위해 메시지를
setFontStyle(_:)로 수정하세요.- @available(*, unavailable, message: "Implement `setFont(_:)` instead.") + @available(*, unavailable, message: "Use `setFontStyle(_:)` instead.") override public var font: UIFont! { get { super.font } set { super.font = newValue } }
133-141: 여러 하이라이트 발생 및 대소문자 옵션 지원 제안현재는 첫 번째 일치만, 대소문자 구분으로 하이라이트합니다. UX 요구에 따라 전체 일치/대소문자 무시 옵션을 지원할 수 있습니다.
예시(전체 일치, 대소문자 무시):
let lcText = labelText.lowercased() let lcWord = word.lowercased() var searchRange = lcText.startIndex..<lcText.endIndex while let foundRange = lcText.range(of: lcWord, options: [], range: searchRange) { let nsRange = NSRange(foundRange, in: lcText) attributedString.addAttribute(.foregroundColor, value: highlightColor, range: nsRange) if let highlightFont = highlightFont { attributedString.addAttribute(.font, value: highlightFont, range: nsRange) } searchRange = foundRange.upperBound..<lcText.endIndex }
76-89: 기본 정렬값 재검토 제안기본 정렬을
.justified로 두면 짧은 텍스트에서도 어색한 간격이 생길 수 있습니다. 일반 라벨의 기본은.natural또는.left가 더 무난합니다.src/Projects/BKPresentation/Sources/MainFlow/Note/View/AppreciationGuideButton.swift (1)
28-32: 하드코딩된 Hex 컬러 사용은 다크 모드/디자인 토큰 일관성에 취약합니다placeholder 하이라이트 컬러를 UIColor(hex: "D6D6D6")로 고정하면 라이트/다크 테마 전환 시 대비 불일치가 발생할 수 있고, 디자인 시스템 토큰 흐름(.bkContentColor 등)에서 이탈합니다. 명시적으로 토큰을 쓰거나(예: .bkContentColor(.disable) 혹은 유사한 토큰), 이번 스펙이 정확한 0xD6D6D6를 요구한다면 BKDesign 내 팔레트/토큰으로 승격해 관리하는 편이 안전합니다.
적용 예(토큰 회귀):
- highlightColor: UIColor(hex: "D6D6D6") + highlightColor: .bkContentColor(.disable)토큰이 정확히 맞지 않는다면 BKDesign 팔레트에 신규 토큰(예: neutral200) 정의 후 사용을 권장합니다.
src/Projects/BKDesign/Sources/Components/Chip/BKChip.swift (1)
6-7: BKLabel2 마이그레이션 LGTM + 라벨 단일 라인 고정 권장BKLabel2로의 전환은 API 호환(setText/setFontStyle/setColor) 측면에서 문제 없어 보입니다. 다만 칩 내부 라벨이 길어지는 경우 줄바꿈으로 칩 높이/레이아웃이 틀어질 수 있으니 단일 라인 고정을 고려해 주세요.
추가 제안:
private func setupViews() { - titleLabel.setText(text: title) - countLabel.setText(text: "\(count)") + titleLabel.setText(text: title) + titleLabel.numberOfLines = 1 + countLabel.setText(text: "\(count)") + countLabel.numberOfLines = 1 countLabel.setFontStyle(style: .label1(weight: .semiBold))src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchSectionHeaderView.swift (1)
67-74: 기본 텍스트 색상을 디자인 토큰으로 교체 권장 (다크 모드/일관성)base 색상을
.black로 고정하면 테마/다크 모드 일관성이 깨질 수 있습니다. 디자인 시스템 토큰 사용을 권장합니다.적용 diff:
- attributes: [ - .font: baseFont, - .foregroundColor: UIColor.black - ] + attributes: [ + .font: baseFont, + .foregroundColor: UIColor.bkContentColor(.primary) + ]추가 제안(참고):
.recent분기(라인 42)의 폰트 스타일도 본 변경 의도에 맞춰.label1(weight: .medium)으로 통일하는 방안 검토 부탁드립니다.src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailViewCell.swift (3)
22-31: 일관성 측면에서 noteLabel도 BKLabel2로 전환 고려동일 셀 내 라벨 타입 혼재는 추후 유지보수/테마 일관성에 불리합니다. 영향 범위가 작으면
noteLabel도 BKLabel2로 이관을 검토해 주세요.
79-83: emotion 아이콘 크롭 가능성 — 의도 확인 및 대안 제시
.scaleAspectFill + cornerRadius + clipsToBounds조합은 비정사각 이미지에서 크롭이 발생합니다. 배경색도 지정되어 있어 아이콘/심볼 형태에 따라 상자처럼 보일 수 있습니다. 크롭이 의도되지 않았다면 아래 대안을 고려해 주세요.대안 예시:
- emotionIcon.contentMode = .scaleAspectFill + emotionIcon.contentMode = .scaleAspectFit emotionIcon.layer.cornerRadius = LayoutConstants.imageCornerRadius emotionIcon.clipsToBounds = true - emotionIcon.backgroundColor = .bkBaseColor(.primary) + // 필요 시 배경 제거 또는 반투명 토큰 사용 + // emotionIcon.backgroundColor = .clear
85-85: 페이지 표기 'P' 대문자 — 용어 표기 일관성 확인다른 화면/리스트에서 소문자
p또는 한글 “쪽”을 사용한다면 통일이 필요할 수 있습니다. 디자인/카피 가이드와 일치하는지 확인해 주세요.src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchView.swift (2)
103-114: 결과 유무에 따른 clear 버튼 모드 전환 OK — ‘최근’ 상태에서의 초기화도 추가 권장.result 상태에서 빈/존재 케이스별로 .whileEditing / .always 전환은 합리적입니다. 다만 .recent 상태로 전환될 때 명시적으로 모드를 초기화하지 않으면 이전 상태의 모드가 잔존할 수 있습니다. .recent 분기에서도 기본값(.whileEditing 등)을 명시해 주는 게 안정적입니다.
아래처럼 .recent 분기에 초기화 한 줄 추가하는 것을 고려해 주세요(선택 사항, 변경 위치는 현 변경 범위 밖이므로 참고용 코드입니다):
case .recent(let state): // ... 스냅샷 구성 로직 searchBar.setClearButtonMode(.whileEditing)
166-168: 최근 검색어 탭 시 이벤트/텍스트 설정 순서 미세 조정 제안UX 관점에서 사용자가 탭하자마자 검색바에 텍스트가 먼저 반영되고, 이어서 검색 이벤트가 전달되는 편이 자연스럽습니다. 기능엔 영향 없으나 순서만 바꿔두면 미세한 깜빡임을 줄일 수 있습니다.
- self?.eventPublisher.send(.search(keyword)) - self?.setSearchBarText(with: keyword) + self?.setSearchBarText(with: keyword) + self?.eventPublisher.send(.search(keyword))src/Projects/BKPresentation/Sources/Common/Extension/BKBottomSheetViewController+.swift (1)
32-35: divider에 음수 inset 사용은 오버플로우/시각적 절단 리스크
equalToSuperview().inset(-BKSpacing.spacing5)는 슈퍼뷰 폭을 넘어 확장합니다. 의도(풀블리드 라인)라면 안전하지만, 컨테이너/시트 가장자리와 겹치거나 클리핑될 수 있습니다. 오버플로우를 피하려면 음수 inset 대신 슈퍼뷰와 동일 폭으로 두는 게 안전합니다.- $0.leading.trailing.equalToSuperview().inset(-BKSpacing.spacing5) + $0.leading.trailing.equalToSuperview()의도가 “좌우 여백 무시하고 풀블리드”라면, 시트 내부 컨텐츠 패딩을 조정하거나 divider 자체의 내부 레이아웃 가이드를 활용하는 대안을 고려해 주세요.
src/Projects/BKDesign/Sources/Components/Label/BKLabel.swift (1)
31-35: 오류 메시지 문구 수정 제안개발자 가이던스 정확성을 위해 ‘Implement
setFont(_:)’ 대신 실제 API 이름을 안내하는 것이 좋습니다.참고(수정 제안 코드 — 변경 범위 밖):
@available(*, unavailable, message: "Use `setFontStyle(style:)` instead.") override public var font: UIFont! { ... }src/Projects/BKDesign/Sources/Components/BottomSheet/BKBottomSheetTitleView.swift (1)
75-96: leading 스타일의 텍스트 정렬을 .left로 고정 권장BKLabel 기본 정렬(.justified)은 다행히 단일 행에서 문제 없지만, 두 줄 이상에서 불필요한 양끝맞춤이 발생할 수 있습니다. leading 레이아웃에서는 .left가 더 예측 가능하고 자연스럽습니다.
참고(변경 범위 밖, 예시 코드):
// configure() 내에서 스타일별 정렬 명시 switch style { case .leadingCloseButton: titleLabel.textAlignment = .left subtitleLabel.textAlignment = .left case .centered: titleLabel.textAlignment = .center subtitleLabel.textAlignment = .center }src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swift (1)
119-125: reportContainer 높이 고정(42) — 텍스트 길이/다국어 대응 시 클리핑 가능성요약 문구가 길어질 경우(탑 감정 복수, 소형 단말, 다국어) 42pt 고정은 줄바꿈/말줄임 처리가 필요합니다. 두 가지 중 하나를 권장합니다.
옵션 A: 한 줄 고정 + 말줄임 처리
- configure() 등에서 설정 추가(참고 코드, 변경 범위 밖):
reportLabel.numberOfLines = 1 reportLabel.lineBreakMode = .byTruncatingTail옵션 B: 동적 높이 허용
- $0.height.equalTo(42) + // 동적 높이: 고정값 제거의도된 고정 높이라면(디자인 고정값), A를 적용해 클리핑만 방지해 주세요.
src/Projects/BKDesign/Sources/Components/Summary/BKBookSummaryView.swift (3)
137-157: big 스타일 추가 전반적으로 👍; 중복 로직 정리 및 재사용성 개선 제안
- 폰트 계층과 descriptionBlock 구성은 의도대로 보입니다. BKLabel.setFontStyle가 내부에서 applyRecommended를 호출하므로 반영도 문제 없습니다.
- 다만 descriptionStack/descriptionBlock 구성(서브뷰 추가, extraLabel 조건부 추가)이 default 분기와 상당히 중복됩니다. 유지보수/QA 대응을 위해 공통 헬퍼로 추출을 권장합니다.
아래와 같이 공통 헬퍼를 도입해 switch 각 분기에서 재사용하면 중복을 줄일 수 있습니다.
@@ - case .big: - titleLabel.setFontStyle(style: .headline1(weight: .semiBold)) - authorLabel.setFontStyle(style: .label2(weight: .regular)) - separatorLabel.setFontStyle(style: .label2(weight: .regular)) - publisherLabel.setFontStyle(style: .label2(weight: .regular)) - extraLabel.setFontStyle(style: .label2(weight: .regular)) - - let descriptionBlock = UIStackView(arrangedSubviews: [descriptionStack]) - descriptionBlock.axis = .vertical - descriptionBlock.alignment = .leading - descriptionBlock.spacing = 0 - - descriptionStack.addArrangedSubview(authorLabel) - descriptionStack.addArrangedSubview(separatorLabel) - descriptionStack.addArrangedSubview(publisherLabel) - labelStack.addArrangedSubview(descriptionBlock) - - if style.showsExtraLabel { - descriptionBlock.addArrangedSubview(extraLabel) - descriptionBlock.setCustomSpacing(style.extraLabelTopOffset, after: descriptionStack) - } + case .big: + applyBigFonts() + buildDescriptionBlock(addExtra: style.showsExtraLabel, extraTop: style.extraLabelTopOffset)그리고 파일 내(선택된 범위 외) 헬퍼를 추가:
private func buildDescriptionBlock(addExtra: Bool, extraTop: CGFloat) { let descriptionBlock = UIStackView(arrangedSubviews: [descriptionStack]) descriptionBlock.axis = .vertical descriptionBlock.alignment = .leading descriptionBlock.spacing = 0 descriptionStack.addArrangedSubview(authorLabel) descriptionStack.addArrangedSubview(separatorLabel) descriptionStack.addArrangedSubview(publisherLabel) labelStack.addArrangedSubview(descriptionBlock) if addExtra { descriptionBlock.addArrangedSubview(extraLabel) descriptionBlock.setCustomSpacing(extraTop, after: descriptionStack) } } private func applyBigFonts() { titleLabel.setFontStyle(style: .headline1(weight: .semiBold)) authorLabel.setFontStyle(style: .label2(weight: .regular)) separatorLabel.setFontStyle(style: .label2(weight: .regular)) publisherLabel.setFontStyle(style: .label2(weight: .regular)) extraLabel.setFontStyle(style: .label2(weight: .regular)) }
269-276: alreadyEnroll 분기의 extraLabel 세팅 분기는 실질적으로 미실행(dead code)alreadyEnroll 스타일에서는 showsExtraLabel이 항상 false라서, 이 분기의 extraLabel 설정은 실행되지 않습니다. 혼동을 줄이기 위해 제거 또는 코멘트 보강을 권장합니다.
아래와 같이 단순 제거 가능합니다:
case .alreadyEnroll: thubmnailCoverView.clipsToBounds = true thubmnailCoverView.layer.cornerRadius = LayoutConstants.imageRadius - - if style.showsExtraLabel, let text = extraText { - extraLabel.setText(text: text) - }
48-48: 오타: thubmnailCoverView → thumbnailCoverView 네이밍 정리 제안속성명이 반복해서 사용되므로 오타를 조기에 정리하는 편이 좋습니다. 리팩터 도중 오표기로 인한 참조 오류를 줄일 수 있습니다.
원하면 이 파일 내 사용처까지 포함한 리네이밍 패치를 제안드릴 수 있습니다.
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailView.swift (3)
168-170: seedReportView의 zero-height 제약만으로 충분합니다현재 height == 0(우선순위 토글)과 height ≥ 0 제약을 동시에 잡고 있는데, 후자는 실질적인 역할이 없습니다. 간소화를 위해 ≥ 0 제약과 그 레퍼런스 속성 제거를 권장합니다.
아래처럼 정리 가능합니다:
- private var seedReportViewHeightConstraint: Constraint? @@ - seedReportZeroHeight = $0.height.equalTo(0).priority(.low).constraint - seedReportViewHeightConstraint = $0.height.greaterThanOrEqualTo(0).constraint + seedReportZeroHeight = $0.height.equalTo(0).priority(.low).constraint
222-228: empty 상태 전환 시 히든/우선순위 동기화 OK; 레이아웃 강제 갱신 고려isHidden과 우선순위 토글이 일관되게 적용되어 있습니다. 전환 애니메이션이나 즉시 반영이 필요하다면 우선순위 업데이트 직후 containerView.layoutIfNeeded()를 호출하는 방식을 고려해 보세요.
384-385: summaryView 높이(98)와 .big 썸네일(높이 100) 불일치.big 스타일에서 BKBookSummaryView의 썸네일 높이가 100인데, 현재 summaryView 고정 높이는 98입니다. superview 바깥으로 2pt가 넘칠 수 있고, 인접 섹션과 겹침 가능성이 있습니다. 최소 100으로 상향하거나 스타일별 높이로 분기하는 것을 권장합니다.
- static let summaryViewHeight: CGFloat = 98 + static let summaryViewHeight: CGFloat = 100대안: 스타일 주입 시 높이를 외부에서 결정하거나(BKBookSummaryViewStyle.thumbnailSize.height 사용), 오토레이아웃으로 내재 콘텐츠에 맞춰 유연하게 잡는 방법도 있습니다.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (32)
src/Projects/BKDesign/Sources/Components/BottomSheet/BKBottomSheetTitleView.swift(5 hunks)src/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift(2 hunks)src/Projects/BKDesign/Sources/Components/Chip/BKChip.swift(1 hunks)src/Projects/BKDesign/Sources/Components/Dialog/BKDialog.swift(4 hunks)src/Projects/BKDesign/Sources/Components/Label/BKLabel.swift(5 hunks)src/Projects/BKDesign/Sources/Components/Label/BKLabel2.swift(1 hunks)src/Projects/BKDesign/Sources/Components/Summary/BKBookSummaryView.swift(2 hunks)src/Projects/BKDesign/Sources/Components/TextField/BKBaseTextField.swift(2 hunks)src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift(3 hunks)src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift(2 hunks)src/Projects/BKDesign/Sources/Foundation/GraphicSystem/BKSpacing.swift(1 hunks)src/Projects/BKDesign/Sources/Foundation/Typography/BKTextStyle.swift(2 hunks)src/Projects/BKPresentation/Sources/ArchiveFlow/View/ArchiveView.swift(1 hunks)src/Projects/BKPresentation/Sources/Common/Extension/BKBottomSheetViewController+.swift(2 hunks)src/Projects/BKPresentation/Sources/Common/Extension/UINavigationController+.swift(2 hunks)src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailView.swift(4 hunks)src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailViewCell.swift(3 hunks)src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailViewHeader.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swift(4 hunks)src/Projects/BKPresentation/Sources/MainFlow/Home/View/HomeEmptyView.swift(2 hunks)src/Projects/BKPresentation/Sources/MainFlow/Home/View/HomeView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Home/View/RecordCountView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/AppreciationGuideButton.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Note/View/EmotionRegistrationView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/View/BookRegistrationStatusView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchSectionHeaderView.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchView.swift(4 hunks)src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Setting/View/SettingCell.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Setting/View/SettingViewController.swift(0 hunks)src/Projects/BKPresentation/Sources/OnboardingFlow/View/OnboardingView.swift(3 hunks)src/Projects/Booket/Project.swift(1 hunks)
💤 Files with no reviewable changes (1)
- src/Projects/BKPresentation/Sources/MainFlow/Setting/View/SettingViewController.swift
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-07-10T08:21:16.126Z
Learnt from: doyeonk429
PR: YAPP-Github/Reed-iOS#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는 버튼들이 콘텐츠 길이에 따라 다른 너비를 가지는 것을 선호합니다.
Applied to files:
src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swiftsrc/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift
📚 Learning: 2025-07-14T05:23:04.937Z
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/BKDesign/Sources/Components/BottomSheet/BKBottomSheetTitleView.swiftsrc/Projects/BKDesign/Sources/Components/Dialog/BKDialog.swift
📚 Learning: 2025-08-11T12:49:16.942Z
Learnt from: doyeonk429
PR: YAPP-Github/Reed-iOS#169
File: src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchResultCell.swift:31-41
Timestamp: 2025-08-11T12:49:16.942Z
Learning: In Reed-iOS project's SearchResultCell, a new BKBookSummaryView instance is created each time configure() is called rather than reusing the existing view. The old view is properly removed and set to nil in prepareForReuse(), allowing deinitialization to handle all cleanup including image downloads. Calling clearView() before removal is unnecessary in this pattern.
Applied to files:
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchView.swiftsrc/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailViewCell.swift
📚 Learning: 2025-07-08T17:15:59.793Z
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/Common/Extension/UINavigationController+.swift
🧬 Code Graph Analysis (13)
src/Projects/BKDesign/Sources/Foundation/Typography/BKTextStyle.swift (1)
src/Projects/BKDesign/Sources/Foundation/Typography/BKFontMetrics.swift (1)
calculateAbsoluteLetterSpacing(51-53)
src/Projects/BKPresentation/Sources/Common/Extension/BKBottomSheetViewController+.swift (1)
src/Projects/BKDesign/Sources/Extensions/UIView+.swift (1)
addSubviews(7-9)
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (1)
src/Projects/BKDesign/Sources/Extensions/UIColor+.swift (2)
bkBaseColor(91-102)bkBorderColor(65-76)
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift (1)
src/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift (1)
twoButtonGroup(165-185)
src/Projects/BKPresentation/Sources/MainFlow/Search/View/BookRegistrationStatusView.swift (1)
src/Projects/BKDesign/Sources/Components/Button/BKButton.swift (1)
secondary(351-358)
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchView.swift (1)
src/Projects/BKDesign/Sources/Components/TextField/BKBaseTextField.swift (1)
setClearButtonMode(104-106)
src/Projects/BKDesign/Sources/Components/Summary/BKBookSummaryView.swift (1)
src/Projects/BKDesign/Sources/Components/Label/BKLabel.swift (1)
setFontStyle(103-107)
src/Projects/BKDesign/Sources/Components/Label/BKLabel.swift (1)
src/Projects/BKDesign/Sources/Foundation/Typography/BKTextStyle.swift (2)
attributedString(323-343)mutableAttributedString(345-365)
src/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift (1)
src/Projects/BKDesign/Sources/Components/Button/BKButton.swift (2)
secondary(351-358)primary(342-349)
src/Projects/BKDesign/Sources/Components/TextField/BKBaseTextField.swift (1)
src/Projects/BKDesign/Sources/Extensions/UIColor+.swift (1)
bkBaseColor(91-102)
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swift (1)
src/Projects/BKDesign/Sources/Extensions/UIColor+.swift (1)
bkBaseColor(91-102)
src/Projects/BKDesign/Sources/Components/Label/BKLabel2.swift (2)
src/Projects/BKDesign/Sources/Extensions/UIColor+.swift (1)
bkContentColor(52-63)src/Projects/BKDesign/Sources/Foundation/Typography/BKTextStyle.swift (1)
attributedString(323-343)
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailViewCell.swift (2)
src/Projects/BKDesign/Sources/Extensions/UIColor+.swift (2)
bkContentColor(52-63)bkBaseColor(91-102)src/Projects/BKPresentation/Sources/Common/Extension/Date+.swift (1)
toKoreanDotDateString(22-24)
⏰ 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 (34)
src/Projects/BKPresentation/Sources/MainFlow/Setting/View/SettingCell.swift (2)
49-53: 아이콘 뷰 trailing 인셋 inset5로 조정 — 정합성 문제 없음좌우 여백이 titleLabel의 leading(inset5)과 일관되게 맞춰졌습니다. 제약 간 충돌 소지도 없고, 디자인 토큰 기준에도 부합해 보입니다.
55-58: 버전 라벨 trailing 인셋 inset5로 조정 — 정합성 문제 없음.chevron/.label 전환 시 isHidden 토글만 이뤄져 런타임 충돌 없이 동작하고, 좌우 여백도 통일되었습니다.
src/Projects/BKPresentation/Sources/MainFlow/Search/View/BookRegistrationStatusView.swift (1)
52-52: .large 사이즈 높이 일치 확인
.large의height가 52로, 기존LayoutConstants.buttonHeight(52)와 완전히 일치합니다. 오토레이아웃 제약 충돌 우려가 없으므로 그대로 머지해 주세요. LGTM.src/Projects/BKDesign/Sources/Components/Button/BKButtonGroup.swift (2)
171-172: twoButtonGroup에 .large 사이즈 명시 — 시각적 일관성 향상left=secondary(.large), right=primary(.large)로 명시해 fullWidth 레이아웃에서 버튼 높이·타이포 크기가 일관되게 맞춰집니다. group.primaryButton = rightButton과도 잘 호환됩니다.
240-240: 사소: 파일 말미 개행/서식 변경기능 영향은 없습니다. 현재 상태 유지에 동의합니다.
src/Projects/BKPresentation/Sources/MainFlow/Home/View/RecordCountView.swift (1)
9-9: BKLabel2로의 전환 LGTM
BKLabel2로의 마이그레이션이 기존 사용 패턴(setText/setFontStyle/setColor + highlight 속성)과 호환되며, 본 뷰의 요구사항에 적절합니다.src/Projects/BKDesign/Sources/Components/TextField/BKTextFieldView.swift (3)
7-7: 제목 레이블의 BKLabel2 전환 LGTM
BKLabel2도입으로 타 컴포넌트와 라벨 시스템이 일관화되었습니다. 외부 API 변화 없이 내부만 갱신된 점도 좋습니다.
42-43: UIStackView 배치 전략 변경(.fill) 적절세로 스택에서
.fill은 일반적인 선택이며, 콘텐츠 크기 우선 배치를 명확히 합니다. 현재 구성(제목-입력-헬프)의 의도에 부합합니다.
116-125: 세로 축 Hugging/Compression 우선순위 명시 좋습니다세로 방향에서 각 구성요소의 레이아웃 안정성 확보에 도움 됩니다. 다만, 길이가 긴 도움말(여러 줄) 시 레이아웃이 충분히 확장되는지 한 번 확인해 주세요.
테스트 제안:
- helpMessage를 2~3줄 이상으로 설정해 다양한 화면 높이(iPhone SE/Pro Max)에서 잘리는 현상이 없는지 점검 바랍니다.
src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift (1)
15-18: 기본 스타일(보더 숨김 + 베이스 배경) 갱신 LGTM에러 시에만 보더를 노출하고 평상시에는 베이스 컬러 배경만 사용하는 방향이 디자인 시스템 변화와 잘 맞습니다.
src/Projects/BKDesign/Sources/Components/Dialog/BKDialog.swift (2)
198-199: 버튼 상단 간격 조정 LGTM
buttonTopInset을inset6에서inset2로 완화하여 제목 영역과 버튼 그룹 간 거리를 줄인 변경은 의도된 디자인 QA 반영으로 보이며 문제 없습니다.
62-71: 이니셜라이저 시그니처 변경 영향 범위 점검 완료–
BKDialog호출부 전수 스캔 결과,
• 모든 호출부에서subtitle인자를 정상적으로 전달하고 있으며
• 빈 문자열""로 넘기는 패턴은 발견되지 않았습니다.따라서 추가 수정 없이 옵셔널 변경을 적용해도 무방합니다.
src/Projects/BKDesign/Sources/Components/Label/BKLabel2.swift (1)
147-156: LabelType.small의 폰트 웨이트 확인 필요
small이.label1(weight: .medium)으로 매핑되어 있습니다. 디자인 가이드(피그마)에서 regular/medium 중 어느 것이 표준인지 한 번 더 확인 부탁드립니다.src/Projects/BKPresentation/Sources/ArchiveFlow/View/ArchiveView.swift (1)
131-135: 여백 증대 변경사항 확인(LGTM)chipScrollView 상단 오프셋을 spacing5로 늘린 변경은 의도된 시각적 간격 조정으로 보입니다. 아래 ArchiveLayoutGuide.chipSectionInset.top(spacing3)과의 균형만 디자인 스펙과 일치하는지 최종 확인해 주세요.
src/Projects/BKPresentation/Sources/MainFlow/Home/View/HomeEmptyView.swift (1)
37-41: 카피 변경 LGTM서브 타이틀 문구 변경은 자연스럽고 톤&매너에 부합합니다. 추가 액션 불필요합니다.
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailViewHeader.swift (1)
23-27: BKLabel2 전환 LGTM공개 API/로직 영향 없이 레이블만 BKLabel2로 교체되어 안전합니다. BKLabel2의 줄간/라인하이트가 BKLabel과 약간 다를 수 있으니 시각적 리그레션만 한번 확인 부탁드립니다.
src/Projects/BKDesign/Sources/Foundation/GraphicSystem/BKSpacing.swift (1)
16-16: spacing9 추가 LGTM토큰 간격(36pt) 보강 좋습니다. 다른 화면(예: 온보딩)에서도 매직 넘버 대신 본 토큰 사용 권장합니다.
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchViewController.swift (1)
248-254: 카피/버튼 레이블 변경 LGTM — 액션 매핑도 일치좌: “나중에 하기”(dismiss), 우: “기록 시작하기”(dismiss 후 흐름 시작)로 primary/secondary 역할과 행동이 자연스럽게 매핑되어 있습니다.
src/Projects/BKPresentation/Sources/OnboardingFlow/View/OnboardingView.swift (2)
116-117: 이미지 좌우 인셋 제거 — 의도 확인 요청
imageView의horizontalEdges를 슈퍼뷰에 맞추며 기존 좌우 인셋을 제거했습니다. 이로 인해 기기별 화면 폭에서 이미지가 가장자리까지 붙을 수 있습니다. 의도된 변경인지 확인 부탁드립니다. 가장자리 여백이 필요하다면 적정BKInset/BKSpacing토큰을 적용하는 편이 안전합니다.
211-213: 간격 미세 조정(spacing8 → spacing7) LGTM타이포그래피 및 상하 레이아웃 균형을 맞추기 위한 조정으로 보이며 문제 없습니다.
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailViewCell.swift (1)
22-31: BKLabel2 마이그레이션 및 스타일 조정 LGTM
- emotionLabel:
.label1(.semiBold)로 상향 — 강조 의도에 부합- creationLabel:
.caption1(.regular)— 날짜 보조 정보 톤에 적절- pageLabel:
.body2(.medium)— 가독성 무난Also applies to: 39-43
src/Projects/BKPresentation/Sources/MainFlow/Search/View/SearchView.swift (2)
22-25: 검색바 타입을 .normal로 변경 — 의도에 부합하는 안전한 수정디자인 톤 앤 매너 정합성을 위해 .brand → .normal 전환한 것으로 보이며, 다른 로직 영향은 없습니다.
81-84: 프로그램matic 텍스트 설정 API 추가 적절외부에서 검색어를 주입해 UI 상태를 동기화하기 좋습니다. 간결하고 부작용 없음.
src/Projects/BKPresentation/Sources/Common/Extension/BKBottomSheetViewController+.swift (1)
108-114: 옵션 항목 좌우 인셋 축소(.inset1) — 밀도 개선 측면에서 타당터치 타깃 높이(56) 유지하면서 좌우 여백만 줄인 변경은 보기 좋고 일관됩니다.
src/Projects/BKDesign/Sources/Components/Label/BKLabel.swift (2)
39-41: 공용 렌더 경로 통일(applyRecommended) — 유지보수성 향상여러 진입점에서
apply()를applyRecommended()로 일원화한 변경은 스타일링 일관성과 변경 용이성 측면에서 좋습니다.Also applies to: 46-48, 53-55, 76-78, 105-107, 111-113, 117-120
154-161: paragraphStyle 인스턴스 생성이 안전함 확인됨
BKTextStyle.paragraphStyle는 computed property로 호출 시마다 새로운NSMutableParagraphStyle인스턴스를 생성해 반환하므로 공유로 인한 부작용은 없습니다.src/Projects/BKDesign/Sources/Components/BottomSheet/BKBottomSheetTitleView.swift (1)
36-52: UILabel → BKLabel 마이그레이션 적절BKLabel API로 일원화하여 스타일 제어가 명확해졌고, 자간/문단 스타일 적용 로직과도 정합적입니다.
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/SeedReportView.swift (3)
8-13: EmotionSeed allCases 순서 변경 영향 확인CaseIterable 순서가 바뀌면:
- 감정 아이콘 나열 순서(라인 150 부근 for-in)가 바뀝니다.
- 동률 시 정렬 결과의 표시 순서(요약 문구 내 나열)도 달라질 수 있습니다(정렬 안정성 보장 없음).
디자인 의도라면 OK, 아니라면 기존 순서를 유지하거나 명시적 정렬 기준을 두세요.
80-85: BKLabel2 도입으로 하이라이트 품질 개선 — 적절한 전환
highlightFont를 통해 강조 가독성이 좋아졌습니다. 타 컴포넌트의 BKLabel2 도입과도 일관됩니다.
127-129: 라벨 중앙 정렬 제약으로 레이아웃 단순화 — OK텍스트가 단문인 현재 요구사항에는 적합합니다. 위 높이 정책만 함께 고려하면 좋겠습니다.
src/Projects/BKDesign/Sources/Components/Summary/BKBookSummaryView.swift (1)
135-136: record 모드 간격 상향(L3→L4) 타이포그래피 가독성 개선에 도움설명 스택 이후 간격을 spacing4로 늘린 변경은 의도대로 레코드 정보 블록의 분리도를 높여줍니다. 다른 스타일에의 영향도 없고 안전합니다.
src/Projects/BKPresentation/Sources/MainFlow/BookDetail/View/BookDetailView.swift (3)
35-35: 복합명사 띄어쓰기 수정 LGTMUI 카피 관점에서 “페이지 순”으로의 변경은 일관성 측면에서 적절합니다. 정렬 로직에는 영향 없습니다.
84-88: 동적 레이아웃 전환용 제약 레퍼런스 보유 방식 적절zero-height, divider 연결 전환을 위해 Constraint 레퍼런스를 보관하는 접근은 유지보수에 유리합니다.
173-179: divider 상단 연결 우선순위 전환 로직 적절; 초기 상태 확인 권장우선순위를 high/low로 교차 설정하는 방식은 의도대로 동작합니다. 다만 최초 화면 구성 시(스냅샷 적용 전) seedReport가 비어있는 경우에도 dividerTopToSeed가 우선되므로, 초기 레이아웃에서 미세한 위치 깜빡임이 있을 수 있습니다. 초기 스냅샷 호출 시점에 맞춰 우선순위를 세팅하거나, setup 단계에서 기본 상태를 ‘빈 상태’ 가정으로 맞출지 확인 부탁드립니다.
원한다면 초기 바인딩 순서를 점검하는 간단한 체크 스크립트를 제공할 수 있습니다.
| func applyRecommended() { | ||
| let customParagraphStyle = fontStyle.paragraphStyle | ||
| customParagraphStyle.alignment = alignment | ||
| customParagraphStyle.lineBreakMode = self.lineBreakMode | ||
|
|
||
| let extraAttributes: [NSAttributedString.Key: Any] = [ | ||
| .paragraphStyle: customParagraphStyle | ||
| ] | ||
|
|
||
| let attributedString = fontStyle.mutableAttributedString( | ||
| from: labelText, | ||
| color: labelColor, | ||
| extraAttributes: extraAttributes | ||
| ) |
There was a problem hiding this comment.
BKTextStyle.paragraphStyle 직접 변형으로 전역 부작용 가능성 높음
fontStyle.paragraphStyle을 그대로 참조해 alignment/lineBreakMode를 변경하면, 해당 paragraphStyle이 공유 인스턴스일 경우 다른 라벨/텍스트에도 파급될 수 있습니다. 이전 apply()는 매번 새로운 NSMutableParagraphStyle을 생성했기에 안전했지만, 현재 구현은 전역 상태 오염 리스크가 있습니다. 반드시 복사본을 만들어 수정하세요.
- let customParagraphStyle = fontStyle.paragraphStyle
- customParagraphStyle.alignment = alignment
- customParagraphStyle.lineBreakMode = self.lineBreakMode
+ let customParagraphStyle: NSMutableParagraphStyle = {
+ if let copy = fontStyle.paragraphStyle.mutableCopy() as? NSMutableParagraphStyle {
+ return copy
+ }
+ let newStyle = NSMutableParagraphStyle()
+ newStyle.setParagraphStyle(fontStyle.paragraphStyle)
+ return newStyle
+ }()
+ customParagraphStyle.alignment = alignment
+ customParagraphStyle.lineBreakMode = self.lineBreakMode🤖 Prompt for AI Agents
In src/Projects/BKDesign/Sources/Components/Label/BKLabel.swift around lines 154
to 167, the code mutates fontStyle.paragraphStyle directly which can cause
global side-effects if that paragraphStyle is a shared instance; instead create
a mutable copy (e.g., let customParagraphStyle =
(fontStyle.paragraphStyle.mutableCopy() as? NSMutableParagraphStyle) ??
NSMutableParagraphStyle()), modify alignment and lineBreakMode on that copy, and
use the copy in extraAttributes so you do not mutate the original shared
paragraphStyle.
| emptyImageView.frame.size = .init(width: 112, height: 112) | ||
|
|
||
| [emptyImageView, labelStack, noteButton].forEach(rootStack.addArrangedSubview) |
There was a problem hiding this comment.
Auto Layout 환경에서 frame 사이즈 지정은 무시될 수 있습니다 — 제약으로 고정하세요
UIStackView + SnapKit 레이아웃에서 arrangedSubview의 frame을 직접 설정하면, Auto Layout 계산 시 덮어써져 의도한 112x112가 반영되지 않을 수 있습니다. 너비/높이 제약으로 고정하는 방식으로 교체해 주세요.
권장 수정:
- emptyImageView.frame.size = .init(width: 112, height: 112)
+ // 사이즈는 오토레이아웃 제약으로 고정setupLayout 내에 다음 제약을 추가:
// setupLayout() 내부 적절한 위치에 추가
emptyImageView.snp.makeConstraints {
$0.width.height.equalTo(112)
}또는 다음과 같이 size 헬퍼 사용:
emptyImageView.snp.makeConstraints { $0.size.equalTo(112) }🤖 Prompt for AI Agents
In src/Projects/BKPresentation/Sources/MainFlow/Home/View/HomeEmptyView.swift
around lines 54 to 56, the code sets emptyImageView.frame.size directly which
can be ignored by Auto Layout in a UIStackView environment; replace the frame
sizing with explicit width/height constraints using SnapKit (e.g., add a
constraint in setupLayout to set both width and height to 112) so the image view
is fixed to 112x112 under Auto Layout.
src/Projects/BKPresentation/Sources/OnboardingFlow/View/OnboardingView.swift
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/Projects/BKPresentation/Sources/AppCoordinator.swift (1)
58-60: 사용자-주도 닫기 시 child 정리 보장 로직 보강 제안LoginViewController 쪽에서 닫기를 VC 자체에서
dismiss하면LoginCoordinator가childCoordinators에 남을 수 있습니다. 닫기(취소) 시에도 child 정리를 보장할 수 있도록 아래 중 하나를 권장합니다.옵션 A(권장): VC → Coordinator로 위임(e.g.,
didTapClose()), Coordinator에서
- parent로부터 자신을 제거(removeChild)하고
navigationController.dismiss(animated:)호출옵션 B: AppCoordinator에서 모달 프레젠테이션 델리게이트로 정리
예시:
// presentAuthFlow 내 authNavigationController.presentationController?.delegate = self // AppCoordinator.swift 하단 등 extension AppCoordinator: UIAdaptivePresentationControllerDelegate { func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { // LoginCoordinator만 찾아서 제거 if let login = childCoordinators.first(where: { $0 is LoginCoordinator }) { removeChildCoordinator(login) } } }실제 구현 시
removeChildCoordinator(_:)유틸이 없다면 추가 필요합니다.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
src/Projects/BKPresentation/Sources/AppCoordinator.swift(1 hunks)src/Projects/BKPresentation/Sources/AuthFlow/View/LoginViewController.swift(2 hunks)src/Projects/BKPresentation/Sources/MainFlow/Setting/View/SettingViewController.swift(1 hunks)src/Projects/BKPresentation/Sources/MainFlow/Setting/ViewModel/SettingViewModel.swift(0 hunks)src/SupportingFiles/Booket/Info.plist(2 hunks)
💤 Files with no reviewable changes (1)
- src/Projects/BKPresentation/Sources/MainFlow/Setting/ViewModel/SettingViewModel.swift
🚧 Files skipped from review as they are similar to previous changes (1)
- src/Projects/BKPresentation/Sources/MainFlow/Setting/View/SettingViewController.swift
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: doyeonk429
PR: YAPP-Github/Reed-iOS#157
File: src/Projects/BKPresentation/Sources/MainFlow/Home/View/HomeViewController.swift:19-24
Timestamp: 2025-08-08T01:38:59.656Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 접근성(accessibility) 관련 개선사항은 현재 작업 중인 PR에서 즉시 처리하지 않고, 접근성 전용 PR이나 이슈를 별도로 만들어 한번에 처리하는 것을 선호한다.
Learnt from: doyeonk429
PR: YAPP-Github/Reed-iOS#157
File: src/Projects/BKPresentation/Sources/AuthFlow/View/LoginView.swift:43-45
Timestamp: 2025-08-08T01:39:15.620Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 접근성 개선 작업을 별도의 전용 PR이나 이슈에서 일괄 처리하는 것을 선호한다. 개별 기능 구현 PR에서는 접근성 관련 제안을 하지 않고, 접근성 전담 작업에서 한번에 처리하는 방식을 원한다.
📚 Learning: 2025-07-07T13:47:32.784Z
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/AuthFlow/View/LoginViewController.swift
⏰ 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 (4)
src/Projects/BKPresentation/Sources/AuthFlow/View/LoginViewController.swift (2)
18-23: X 닫기 버튼 추가 방향 동의 (LGTM)풀스크린 모달 전환(아래 AppCoordinator 변경)과 맞물려 명시적 닫기 진입점을 제공하는 것이 일관적입니다. BKNavigationBarStyle 표준 구성을 그대로 활용한 점도 좋습니다.
90-92: Coordinator에 Close 이벤트 위임하도록 수정 필요직접
self.dismiss(animated:)호출 시 LoginCoordinator가childCoordinators에서 제거되지 않아 메모리 누수와 후속 로직 미실행 위험이 있습니다. Base Coordinator에는removeChildCoordinator(_:)가 구현되어 있지만, LoginCoordinator에는 이를 호출하는 진입점(didTapClose등)이 없어 직접 활용할 수 없습니다.수정 포인트:
- LoginViewController.swift (handleCloseButtonTapped)
- LoginCoordinator.swift (close/cancel 메서드 미구현)
제안하는 변경 예시:
// src/Projects/BKPresentation/Sources/AuthFlow/View/LoginViewController.swift - @objc private func handleCloseButtonTapped() { - self.dismiss(animated: true) - } + @objc private func handleCloseButtonTapped() { + coordinator?.didTapClose() + }// src/Projects/BKPresentation/Sources/AuthFlow/Coordinator/LoginCoordinator.swift extension LoginCoordinator { func didTapClose() { // child 정리 + 모달 해제 parentCoordinator?.removeChildCoordinator(self) navigationController.dismiss(animated: true) } }위와 같이 VC는 Coordinator에 위임만 하고, Coordinator가 child 제거 및 dismiss를 일괄 처리하도록 반드시 리팩터링해야 합니다.
⛔ Skipped due to learnings
Learnt from: clxxrlove PR: YAPP-Github/Reed-iOS#179 File: src/Projects/BKPresentation/Sources/AppCoordinator.swift:53-73 Timestamp: 2025-08-19T17:14:50.088Z Learning: Reed-iOS 프로젝트에서는 Coordinator 패턴에서 자동 cleanup 메커니즘이 구현되어 있다. LoginViewController 등에서 coordinator?.popAndFinish() 호출 시 didFinish()가 자동으로 parentCoordinator?.removeChildCoordinator(self)를 호출하여 child coordinator를 제거한다. 따라서 수동으로 child coordinator 제거를 구현할 필요가 없다.src/Projects/BKPresentation/Sources/AppCoordinator.swift (1)
58-60: 풀스크린 + 인터랙티브 디스미스 차단 적용 LGTM명시적 닫기 버튼을 통한 종료 플로우와 맞물려, 스와이프 등 인터랙티브 디스미스를 비활성화한 선택이 합리적입니다.
src/SupportingFiles/Booket/Info.plist (1)
89-90: EOF 개행 추가는 문제 없습니다.파일 포맷/도구 호환성 측면에서 긍정적입니다.
|
BKLabel2 네이밍 고민을 더 해야하는데,, 일단 approve할게요. 정확히 저걸 지칭할 단어가 안떠오르네요.. 😢 |
|
@doyeonk429 그러게요. 갑자기 BKLabel2가 생겨서 뭔가 꼬였나 했어요. |
🔗 관련 이슈
📘 작업 유형
📙 작업 내역
🧪 테스트 내역
Summary by CodeRabbit
New Features
UI/Style
Chores