Skip to content

Conversation

@doyeonk429
Copy link
Member

@doyeonk429 doyeonk429 commented Nov 6, 2025

🔗 관련 이슈

📘 작업 유형

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

📙 작업 내역

  • NoteEditView/VC/VM 로직 수정
  • EmotionEditView/VC 로직 수정

🧪 테스트 내역

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

🎨 스크린샷 또는 시연 영상 (선택)

Simulator.Screen.Recording.-.ReedDefaultSize.-.2025-11-07.at.08.24.27.mp4

✅ PR 체크리스트

  • 커밋 메시지가 명확합니다
  • PR 제목이 컨벤션에 맞습니다
  • 관련 이슈 번호를 작성했습니다
  • 기능이 정상적으로 작동합니다
  • 불필요한 코드를 제거했습니다

💬 추가 설명 or 리뷰 포인트 (선택)

  • EmotionEditView에 VM가 없지만, 또 VM으로 처리할만큼 로직이 많은 것도 아닌 것 같아 일단 completion 으로 data 전달하는 방식을 유지하되, 새로 select된 emotion 추적을 쉽게 하기 위해 @Published를 사용하였습니다. 그리고 ViewEvent 구조로 개편하였습니다.

Summary by CodeRabbit

출시 노트

  • 새 기능

    • 감정 편집 및 노트 저장 버튼의 상태 관리 개선
    • 폼 필드 변경 사항 실시간 추적 기능 추가
  • 버그 수정

    • 감정 선택 및 폼 저장 흐름 안정성 개선
  • 리팩터

    • 이벤트 기반 아키텍처로 내부 통신 패턴 통합
    • 폼 상태 관리 및 변경 감지 로직 최적화

@doyeonk429 doyeonk429 self-assigned this Nov 6, 2025
@github-actions github-actions bot requested a review from clxxrlove November 6, 2025 23:32
@doyeonk429 doyeonk429 added the 🐞 fix Something isn't working label Nov 6, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 6, 2025

Walkthrough

NoteEdit 플로우의 감정 및 텍스트 필드 변경사항을 실시간 추적하도록 리팩토링하고, 초기값 대비 차이 감지 시에만 저장/편집 버튼을 활성화하는 기능을 구현했습니다. 이벤트 기반 아키텍처로 통합하여 상태 변화를 ViewModel에 전달합니다.

Changes

Cohort / File(s) 변경 요약
감정 입력 View 및 Controller
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditView.swift, src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditViewController.swift
EmotionEditView: 이벤트 기반 인터페이스 도입 (EmotionEditViewEvent enum), editButtonTappedSubject/getCurrentEmotionSubject를 단일 eventPublisher로 통합, currentSelectedEmotion 상태 추가. EmotionEditViewController: initialEmotion으로 초기값 비교 로직 추가, emotionDidChange 이벤트 처리 시 초기값과 비교하여 편집 버튼 활성화/비활성화 제어.
노트 편집 View
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditView.swift
NoteEditViewEvent에 pageDidChange(String), sentenceDidChange(String), appreciationDidChange(String) 케이스 추가, 각 필드의 텍스트 변경 시 해당 이벤트 발행, setSaveButtonEnabled(_:) 공개 메서드 추가.
노트 편집 Controller
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditViewController.swift
viewModel의 isDiff 상태 바인딩으로 저장 버튼 활성화/비활성화 제어, bindAction에서 pageDidChange/sentenceDidChange/appreciationDidChange 이벤트 처리 추가 및 ViewModel으로 전달, saveButtonTapped 액션을 formData 파라미터 없이 전송.
노트 편집 ViewModel
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/ViewModel/NoteEditViewModel.swift
State에 currentFormData (page/sentence/appreciation), initialRecordInfo, initialSelectedEmotion, isDiff 추가. Action에 saveButtonTapped(formData:)를 파라미터 없는 saveButtonTapped로 변경, pageDidChange/sentenceDidChange/appreciationDidChange 액션 신규 추가. checkForDiff(state:) 메서드로 필드 변경사항 감지, 관련 액션 후 diff 상태 업데이트.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant NoteEditView
    participant NoteEditViewController
    participant NoteEditViewModel
    participant EmotionEditViewController

    User->>NoteEditView: 텍스트 입력 (page/sentence/appreciation)
    NoteEditView->>NoteEditViewController: pageDidChange/sentenceDidChange/appreciationDidChange 이벤트 발행
    NoteEditViewController->>NoteEditViewModel: 해당 액션 전달
    NoteEditViewModel->>NoteEditViewModel: currentFormData 업데이트<br/>checkForDiff() 호출<br/>isDiff 계산
    NoteEditViewModel-->>NoteEditViewController: statePublisher.isDiff 업데이트
    NoteEditViewController->>NoteEditView: setSaveButtonEnabled(isDiff)
    NoteEditView->>User: 저장 버튼 활성화/비활성화

    User->>NoteEditView: 감정 편집 버튼 터치
    NoteEditView->>NoteEditViewController: emotionEditViewEvent (.editButtonTapped)
    NoteEditViewController->>EmotionEditViewController: 감정 선택 화면 표시
    User->>EmotionEditViewController: 감정 선택 변경
    EmotionEditViewController->>NoteEditViewController: emotionDidChange 이벤트 (선택된 감정)
    NoteEditViewController->>NoteEditViewModel: emotionSelected 액션
    NoteEditViewModel->>NoteEditViewModel: initialSelectedEmotion과 비교<br/>checkForDiff() 호출<br/>isDiff 계산
    NoteEditViewModel-->>NoteEditViewController: statePublisher.isDiff 업데이트
    NoteEditViewController->>NoteEditView: setSaveButtonEnabled(isDiff)
    NoteEditView->>User: 저장 버튼 활성화/비활성화
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 분

주의가 필요한 부분:

  • NoteEditViewModel의 diff 로직: checkForDiff(state:) 메서드가 currentFormData, initialRecordInfo, initialSelectedEmotion을 정확히 비교하는지 검증 필요. nil/empty string 처리가 일관성 있게 되는지 확인.
  • 상태 동기화: initialRecordInfo와 initialSelectedEmotion이 recordDetailFetch/patchSuccess 시점에 올바르게 초기화되는지, 그리고 이후 수정 플로우에서 유지되는지 검증.
  • 이벤트 흐름의 연결성: EmotionEditView → EmotionEditViewController → NoteEditViewController → NoteEditViewModel 각 계층 간 이벤트 전달이 누락되지 않았는지 확인.
  • 버튼 활성화/비활성화 타이밍: 초기 로드 시 버튼이 disabled 상태로 설정되고, 필드 변경 시에만 활성화되는 시퀀스가 보장되는지 검증.
  • saveButtonTapped 액션의 formData 제거: 이전에 formData 파라미터를 통해 전달되던 데이터가 currentFormData로 대체되었으므로, ViewModel 내 저장 처리 로직에서 currentFormData를 올바르게 사용하는지 확인.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 변경사항의 주요 내용을 명확하게 설명하고 있으며, 기록 수정 화면의 로직 개선이라는 핵심 변경사항을 반영하고 있습니다.
Linked Issues check ✅ Passed 모든 코드 변경사항이 #251 이슈의 요구사항을 충족하고 있습니다: 초기값으로 버튼을 disabled 상태로 설정하고, 초기값과 수정된 값을 비교하여 변경이 있을 때만 버튼을 활성화합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #251 이슈의 범위 내에 있으며, 변경사항 없을 때 버튼 활성화 버그를 수정하기 위한 일관성 있는 구현입니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BOOK-421-fix/#251

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de0cff9 and 5dc1cc0.

📒 Files selected for processing (5)
  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditView.swift (3 hunks)
  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditViewController.swift (1 hunks)
  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditView.swift (4 hunks)
  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditViewController.swift (2 hunks)
  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/ViewModel/NoteEditViewModel.swift (6 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 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
Repo: YAPP-Github/Reed-iOS PR: 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에서는 접근성 관련 제안을 하지 않고, 접근성 전담 작업에서 한번에 처리하는 방식을 원한다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 163
File: src/Projects/BKData/Sources/DTO/Request/UserBookRegisterRequestDTO.swift:7-9
Timestamp: 2025-08-08T16:13:31.712Z
Learning: Reed-iOS에서 서버 스펙 변경으로 DTO 필드명이 바뀔 때, doyeonk429는 코드 전반의 파라미터/시그니처 리네이밍까지 확장하지 않고, 실제 요청 직렬화 키가 맞는지(예: isbn13)만 보장하면 충분하다는 범위 최소화 방식을 선호한다. (PR: YAPP-Github/Reed-iOS#163, 파일: BKData/Sources/DTO/Request/UserBookRegisterRequestDTO.swift)
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 112
File: src/Projects/BKPresentation/Sources/MainFlow/Note/View/NoteView.swift:128-140
Timestamp: 2025-07-28T10:45:09.696Z
Learning: clxxrlove는 NoteView의 nextButtonTapped 메서드에서 폼 검증 실패 시 첫 번째 페이지로 되돌아가는 로직을 임시로 구현했으며, 추후 적절한 에러 처리 로직을 추가할 예정이라고 명시했다. 임시 화면 구현 단계에서는 기본 동작에 집중하고 에러 처리는 후속 작업으로 계획하는 것을 선호한다.
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 134
File: src/Projects/BKPresentation/Sources/MainFlow/Note/ViewModel/NoteViewModel.swift:66-74
Timestamp: 2025-08-01T20:35:39.806Z
Learning: clxxrlove는 NoteViewModel에서 UI 에러 처리를 추후 작업으로 계획하며, 현재 단계에서는 기본 기능 구현에 집중하는 것을 선호한다고 명시했다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 68
File: src/Projects/BKDesign/PreviewApp/Sources/View/BKButtonTestViewController.swift:124-133
Timestamp: 2025-07-10T08:21:49.399Z
Learning: doyeonk429는 테스트 전용으로만 사용되는 extension이나 코드는 해당 테스트 파일에 그대로 두는 것을 선호합니다. 실제 프로덕션 코드에서 사용되지 않는 테스트 전용 코드는 별도 파일로 분리하지 않고 테스트 파일 내에 유지하는 것이 그들의 코드 구성 방식입니다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 138
File: src/Projects/BKDesign/Resources/Assets.xcassets/icons/home.imageset/Contents.json:4-14
Timestamp: 2025-08-04T15:20:43.982Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 에셋 파일명이 영어가 아닌 경우(한글, 일본어 등)에는 경고를 받고 싶어하지만, 영어 파일명의 네이밍 컨벤션(예: home.png vs home1.png)은 기능적으로 문제없다면 신경쓰지 않는 것을 선호한다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 98
File: src/Projects/BKPresentation/Sources/AuthFlow/View/TermsView.swift:78-85
Timestamp: 2025-07-22T05:37:28.756Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 더미 데이터나 테스트 데이터의 구체적인 내용(예: URL 주소)에 대해서는 리뷰 시 지적하지 않기를 선호한다. 더미 데이터는 임시적이며 실제 기능 구현 시 교체될 예정이므로 URL의 구체적인 주소는 중요하지 않다고 본다.
📚 Learning: 2025-08-26T07:08:40.739Z
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 203
File: src/Projects/BKDesign/Sources/Components/TextField/BKTextView.swift:102-110
Timestamp: 2025-08-26T07:08:40.739Z
Learning: In the Reed-iOS codebase, BKTextView's startEditing functionality is automatically triggered through ViewModel reactive bindings (likely via Combine), so manual focus calls after appendText are not needed as the focus is handled by the viewmodel layer.

Applied to files:

  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditViewController.swift
  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditView.swift
📚 Learning: 2025-07-28T10:44:32.256Z
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 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/NoteEdit/View/EmotionEditViewController.swift
  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditView.swift
  • src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/ViewModel/NoteEditViewModel.swift
🧬 Code graph analysis (5)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditViewController.swift (2)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditView.swift (3)
  • setSaveButtonEnabled (297-299)
  • emotionStatusTapped (152-154)
  • saveButtonTapped (156-158)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/ViewModel/NoteEditViewModel.swift (1)
  • send (70-74)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditView.swift (1)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/ViewModel/NoteEditViewModel.swift (1)
  • send (70-74)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditViewController.swift (1)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditView.swift (3)
  • setSelectedEmotion (75-77)
  • setEditButtonEnabled (83-85)
  • editButtonTapped (79-81)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditView.swift (1)
src/Projects/BKDesign/Sources/Components/Button/BKButton.swift (1)
  • primary (342-349)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/ViewModel/NoteEditViewModel.swift (1)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditView.swift (1)
  • saveButtonTapped (156-158)
⏰ 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 (17)
src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditViewController.swift (2)

124-131: LGTM!

초기값과 현재값의 차이를 추적하여 저장 버튼의 활성화 상태를 제어하는 로직이 올바르게 구현되었습니다. removeDuplicates()를 통해 불필요한 UI 업데이트를 방지하고, 메인 스레드에서 UI를 업데이트하는 패턴도 적절합니다.


137-148: LGTM!

텍스트 필드 변경 이벤트를 ViewModel로 전달하는 로직이 올바르게 구현되었습니다. 각 필드의 변경사항이 실시간으로 추적되어 diff 계산에 반영됩니다.

src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditViewController.swift (3)

19-26: LGTM!

초기 감정 상태(initialEmotion)와 현재 선택된 감정(selectedEmotion)을 명확하게 분리하여 관리하는 것이 좋습니다. 이를 통해 변경사항 추적이 용이합니다.


33-36: LGTM!

초기 로드 시 편집 버튼을 비활성화 상태로 설정하는 것이 PR의 목표와 일치합니다. 사용자가 실제로 감정을 변경했을 때만 버튼이 활성화됩니다.


40-54: LGTM!

이벤트 기반 아키텍처로 리팩토링하면서 변경사항 추적 로직이 올바르게 구현되었습니다. 새로 선택된 감정과 초기 감정을 비교하여 버튼 활성화 상태를 제어하는 로직이 정확합니다.

src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/NoteEditView.swift (3)

12-14: LGTM!

각 텍스트 필드의 변경사항을 개별적으로 추적하기 위한 이벤트 케이스들이 명확하게 정의되었습니다. 이를 통해 필드별로 초기값과 비교가 가능합니다.


116-135: LGTM!

각 텍스트 필드의 변경사항을 실시간으로 감지하여 이벤트를 발행하는 로직이 올바르게 구현되었습니다. 메모리 관리도 적절하게 처리되었습니다.


297-299: LGTM!

저장 버튼의 활성화 상태를 제어하는 공개 API가 명확하고 간결하게 구현되었습니다.

src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/ViewModel/NoteEditViewModel.swift (6)

18-22: LGTM!

변경사항 추적에 필요한 상태 필드들이 적절하게 추가되었습니다. 초기값(initialRecordInfo, initialSelectedEmotion)과 현재값(currentFormData)을 분리하여 관리하는 구조가 명확합니다.


82-106: LGTM!

데이터 로드 시 초기값 설정 및 현재 폼 데이터 초기화가 올바르게 구현되었습니다. isDiff를 false로 초기화하여 변경사항이 없는 상태로 시작하는 것이 정확합니다.


118-120: LGTM!

감정 선택 시 변경사항 추적이 올바르게 동작합니다.


122-142: LGTM!

저장 버튼 액션이 파라미터 없이 ViewModel의 currentFormData를 사용하도록 리팩토링되었습니다. 감상평이 비어있을 때 nil로 처리하는 로직도 적절합니다.


144-174: LGTM!

저장 성공 후 상태를 재초기화하여 새로운 기준값으로 설정하는 로직이 올바릅니다. 각 필드 변경 액션도 일관되게 구현되어 있으며, 변경 후 즉시 diff를 재계산하는 것이 정확합니다.


214-226: LGTM!

각 필드별로 초기값과 현재값을 비교하는 핵심 로직이 올바르게 구현되었습니다. 문자열 비교, optional 처리, 그리고 OR 조건을 통한 변경사항 감지가 모두 정확합니다. 이 로직이 PR의 주요 목표인 "변경사항이 있을 때만 버튼 활성화"를 구현합니다.

src/Projects/BKPresentation/Sources/MainFlow/NoteEdit/View/EmotionEditView.swift (3)

9-27: LGTM!

이벤트 기반 인터페이스 구조가 명확하게 정의되었습니다. currentSelectedEmotion을 computed property로 구현하여 내부 상태 추출 로직을 캡슐화한 것이 좋습니다.


39-46: LGTM!

감정 선택 변경을 이벤트로 발행하는 로직이 올바르게 구현되었습니다. reactive 패턴을 적절하게 활용하고 있습니다.


79-85: LGTM!

이벤트 발행 및 버튼 제어 API가 명확하고 간결하게 구현되었습니다. NoteEditView와 일관된 패턴을 따릅니다.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

@doyeonk429 doyeonk429 merged commit e46cf91 into develop Nov 7, 2025
5 checks passed
@doyeonk429 doyeonk429 deleted the BOOK-421-fix/#251 branch November 7, 2025 23:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐞 fix Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BOOK-421/qa] 기록 수정 시, 변경사항 있을 때만 버튼 활성화

3 participants