Skip to content

Conversation

@doyeonk429
Copy link
Contributor

🚀 PR 개요

💡 PR 유형

  • ✨ Feature (기능 추가)
  • 🐞 Bugfix (버그 수정)
  • 🔥 Hotfix (긴급 수정)
  • 🔧 Refactor (코드 리팩토링)
  • ⚙️ Chore (환경 설정)
  • 📝 Docs (문서 작성 및 수정)

✏️ 변경 사항 요약

  • 빈티지 선택 화면 컴포넌트화
  • 테노 작성 플로우에 추가
  • 보유와인 작성 플로우에 컴포넌트 적용

🔗 관련 이슈

🧪 테스트 내역

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

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

Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-09-12.at.17.05.10.mp4

✅ PR 체크리스트

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

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

리뷰어가 중점적으로 봐야 할 부분이나 설명이 필요한 내용을 자유롭게 작성해주세요.

  • 아직 테노 조회 화면에 데이터 적용 안됨

@doyeonk429 doyeonk429 self-assigned this Sep 12, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 12, 2025

📝 Walkthrough

Summary by CodeRabbit

  • 신규 기능

    • 재사용 가능한 빈티지 선택 화면 도입. 선택 완료 시 콜백으로 다음 단계로 이동.
    • 와인 추가 및 테이스팅 노트 작성 흐름에서 와인 선택 후 빈티지 선택 단계를 거치도록 개선.
    • 화면 상단에 와인 이름과 안내 문구(“빈티지를 선택해 주세요”) 표시.
    • 뒤로가기 시 선택된 빈티지 초기화로 더 명확한 내비게이션 동작 제공.
  • 버그 수정

    • 검색 기반 와인 선택 화면에서 내비게이션 바가 간헐적으로 숨겨지던 문제를 방지하도록 표시 타이밍을 조정.

Walkthrough

빈티지 선택 공용 프로토콜을 추가하고, 보유와인/테이스팅노트 매니저가 이를 채택하도록 확장했다. 빈티지 선택 화면을 MVVM 주입형(ReusableVintageSelectionViewController)으로 교체하고, onComplete 콜백 기반 네비게이션으로 전환했다. 뷰의 상단 섹션 API가 이름+설명 설정 방식으로 변경되었다.

Changes

Cohort / File(s) Summary
공용 프로토콜 추가
DE/DE/Sources/Core/CommonUI/Protocols/VintageSelectionViewModel.swift
새 프로토콜 VintageSelectionViewModel 추가: screenTitle, screenDescription(get-only), save(vintage:), handleBackButton() 정의.
보유와인 매니저 적응
DE/DE/Sources/Features/Setting/Models/MyOwnedWine.swift
MyOwnedWineManager가 VintageSelectionViewModel 채택. 타이틀/설명 제공, save→setVintage 위임, back→resetVintage 위임. CoreModule 임포트.
테이스팅노트 매니저 적응
DE/DE/Sources/Features/TastingNote/Models/TNWineDataManager.swift
TNWineDataManager가 VintageSelectionViewModel 채택. 타이틀/설명 제공, save→updateWineData(vintage:) 위임, back→resetData 위임. CoreModule 임포트.
빈티지 선택 VC 리팩터링/재명명
DE/DE/Sources/Features/Vintage/ReusableVintageSelectionViewController.swift
SelectVintageViewController → ReusableVintageSelectionViewController로 재명명. init(viewModel:) 추가, onComplete 콜백 추가. 화면 상단 텍스트를 viewModel에서 가져오고, back/next 동작을 viewModel.handleBackButton/save로 위임. 내부 네비게이션 제거 후 onComplete로 전달.
상단 섹션 뷰 API 변경
DE/DE/Sources/Features/Vintage/VintageSelectionView.swift
setWineName(_) → setTopSection(name:descText:)로 변경. SnapKit 임포트, Network 제거. desc 텍스트를 인자로 수신하도록 수정.
보유와인 플로우 연결
DE/DE/Sources/Features/Setting/ViewControllers/MyWine/AddNewWineViewController.swift
로컬 wineManager 참조 도입. 와인 선택 시 manager에 id/name 설정 후 ReusableVintageSelectionViewController(viewModel: manager) 표시, onComplete에서 BuyNewWineDateViewController로 진행.
테이스팅노트 플로우 연결
DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/SearchWineViewController.swift
네비게이션바 표시 시점 조정(viewWillAppear). 와인 선택 후 바로 날짜 화면으로 이동하던 흐름을 ReusableVintageSelectionViewController(viewModel: TNWineDataManager.shared) 표시로 변경, onComplete에서 TastedDateViewController로 진행.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant AddNewWineVC
    participant MyOwnedWineManager as ViewModel(MyOwnedWineManager)
    participant VintageVC as ReusableVintageSelectionVC
    participant BuyDateVC

    User->>AddNewWineVC: 와인 선택
    AddNewWineVC->>ViewModel(MyOwnedWineManager): setWineId / setWineName
    AddNewWineVC->>VintageVC: init(viewModel)
    Note over VintageVC: 상단 섹션 = screenTitle/screenDescription
    User->>VintageVC: 연도 선택 후 다음
    VintageVC->>ViewModel(MyOwnedWineManager): save(vintage)
    VintageVC-->>AddNewWineVC: onComplete(selectedYear)
    AddNewWineVC->>BuyDateVC: push
Loading
sequenceDiagram
    autonumber
    actor User
    participant SearchWineVC
    participant TNWineDataManager as ViewModel(TNWineDataManager)
    participant VintageVC as ReusableVintageSelectionVC
    participant TastedDateVC

    User->>SearchWineVC: 와인 선택
    SearchWineVC->>TNWineDataManager: updateWineData(id/name/...)
    SearchWineVC->>VintageVC: init(viewModel)
    User->>VintageVC: 연도 선택 후 다음
    VintageVC->>TNWineDataManager: save(vintage)
    VintageVC-->>SearchWineVC: onComplete(selectedYear)
    SearchWineVC->>TastedDateVC: push
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

Pre-merge checks (4 passed, 1 warning)

❌ 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
Title Check ✅ Passed PR 제목 "[Feature/#184] 테이스팅 노트 작성 플로우 > 빈티지 선택 화면 추가"는 변경사항의 핵심인 '테이스팅 노트 플로우에 빈티지 선택 UI 컴포넌트 추가'를 명확히 요약하고 이슈 번호를 포함해 컨벤션을 따르고 있어 적절합니다.
Linked Issues Check ✅ Passed 변경사항은 재사용 가능한 ReusableVintageSelectionViewController 및 VintageSelectionViewModel 도입, MyOwnedWineManager/TNWineDataManager의 프로토콜 준수, Search/AddNewWine 경로에서 onComplete 기반 연결 등을 통해 이슈 [#184]의 목표(빈티지 선택 화면 추가, 보유와인 뷰 재활용, 검색→빈티지→기존 플로우 연결)를 충족합니다.
Out of Scope Changes Check ✅ Passed 코드 변경은 빈티지 선택 컴포넌트화와 통합에 집중되어 있어 범위 외 변경은 보이지 않습니다; 다만 VintageSelectionView에 남아있는 미사용 despText 상수와 네비게이션 바 표시 위치 변경 같은 사소한 잔재 또는 리팩터링 항목이 존재합니다.
Description Check ✅ Passed PR 설명은 컴포넌트화·테노와 보유와인 플로우 통합 등 변경 내용을 직접적으로 요약하고 관련 이슈(#184)와 테스트 상태를 포함하고 있어 변경셋과 일치합니다.

Poem

새 와인에 해를 묻고, 해에게 맛을 묻네 🍷
화면은 말한다, “빈티지를 골라 주세요”
뷰모델이 고개 끄덕, 저장하고 뒤는 정리
콜백은 길을 열고, 다음 화면이 미소 짓네
해 하나 더해진 플로우, 오늘도 부드럽게 흐른다

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/issue-184

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.

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: 0

🧹 Nitpick comments (10)
DE/DE/Sources/Core/CommonUI/Protocols/VintageSelectionViewModel.swift (1)

5-17: VC에서 약한 참조를 허용하도록 AnyObject 제약 추가 제안

VC가 viewModel을 weak로 잡을 수 있도록 프로토콜에 class(AnyObject) 제약을 거는 것을 권장합니다. 순환 참조 여지를 줄입니다.

-public protocol VintageSelectionViewModel {
+public protocol VintageSelectionViewModel: AnyObject {

추가로, save(vintage:)가 비동기 저장을 포함할 수 있다면 async/throws 시그니처를 고려해 주세요(현재 요구가 동기면 유지 OK).

DE/DE/Sources/Features/TastingNote/Models/TNWineDataManager.swift (1)

75-93: 뒤로가기 시 resetData() 전체 초기화는 UX/데이터 유실 위험 — MyOwnedWineManager와 동작 불일치

MyOwnedWineManager는 handleBackButton에서 vintage만 리셋하는 반면, 여기서는 모든 필드를 초기화합니다. 사용자가 ‘검색 → 빈티지 선택’에서 뒤로가기를 누를 때 와인 선택까지 사라지는 것은 의도와 다를 수 있습니다.

빈티지만 초기화하는 쪽으로 정렬을 제안합니다:

-    func handleBackButton() {
-        resetData()
-    }
+    func handleBackButton() {
+        vintage = 0 // 앱에서 0을 '미선택'으로 취급한다는 전제
+    }

참고: 0을 '미선택'으로 쓰는지 전역 규칙을 확인해 주세요. 만약 Optional이 더 자연스럽다면 모델을 Int?로 리팩터링하는 방안도 있습니다(범위 외 제안).

DE/DE/Sources/Features/Setting/Models/MyOwnedWine.swift (1)

146-162: 타이틀에는 '와인 이름'만 노출 권장 — 선택 화면에서 빈티지 중복 방지

TastingNote 쪽 TNWineDataManager는 screenTitle에 순수 이름을 반환하지만, 여기서는 getWineName()으로 기존 빈티지가 포함될 수 있습니다. 빈티지 선택 화면에서는 이름만 노출하는 편이 일관되고 중복이 없습니다.

-    public var screenTitle: String {
-        return getWineName()
-    }
+    public var screenTitle: String {
+        return getWine().wineName
+    }

또한 "빈티지를 선택해 주세요" 문자열은 공용 상수/로컬라이즈로 통일하면 좋습니다.

DE/DE/Sources/Features/Setting/ViewControllers/MyWine/AddNewWineViewController.swift (1)

193-205: 미사용 클로저 파라미터 경고 제거

SwiftLint 경고(unused_closure_parameter) 해결을 위해 파라미터를 _로 교체하세요.

-        vc.onComplete = { [weak self] selectYear in
+        vc.onComplete = { [weak self] _ in
             let nextVC = BuyNewWineDateViewController()
             self?.navigationController?.pushViewController(nextVC, animated: true)
         }

onComplete가 백그라운드에서 불릴 가능성이 없다면 현재 구현으로 충분합니다. 혹시 VC 내부 구현에 따라 비동기 콜백이 될 수 있다면 main 보장도 고려해 주세요:

vc.onComplete = { [weak self] _ in
    DispatchQueue.main.async {
        let nextVC = BuyNewWineDateViewController()
        self?.navigationController?.pushViewController(nextVC, animated: true)
    }
}
DE/DE/Sources/Features/Vintage/ReusableVintageSelectionViewController.swift (4)

22-24: Storyboard 경로 차단을 명시적으로 표시

Interface Builder 경로를 쓰지 않는다면 unavailable 속성을 붙여 컴파일 타임에 막아 주세요.

-    required init?(coder: NSCoder) {
-            fatalError("init(coder:) has not been implemented")
-        }
+    @available(*, unavailable)
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }

60-66: nextButton 활성화 방식 일관화

isEnabled(isEnabled:) 메서드 호출과 isEnabled 프로퍼티 직접 대입이 혼재합니다. 하나로 통일해 가독성을 높여주세요.

- self?.vintageView.nextButton.isEnabled(isEnabled: true)
+ self?.vintageView.nextButton.isEnabled = true

Also applies to: 75-79


109-122: 다중 탭 방지 및 onComplete 미주입 대비 가드 추가 제안

빠른 연타 시 중복 push 가능성이 있습니다. 탭 시 버튼 비활성화로 방지하고, onComplete 미주입 상황을 로깅/토스트로 방어해 주세요.

 @objc func nextButtonTapped() {
-    //        logButtonClick(screenName: screenName, buttonName: Tracking.ButtonEvent.nextBtnTapped, fileName: #file)
-        
     guard let selectedYear = vintageView.yearPicker.selectedYear else {
         showToastMessage(message: "연도가 선택되지 않았습니다.", yPosition: view.frame.height * 0.5)
         return
     }
-    
-    // 5. ViewModel에 선택된 빈티지 저장
+    // 중복 탭 방지
+    vintageView.nextButton.isEnabled = false
+
+    // 5. ViewModel에 선택된 빈티지 저장
     viewModel.save(vintage: selectedYear)
-    
-    // 6. 외부에서 주입받은 onComplete 클로저 실행
-    onComplete?(selectedYear)
+
+    // 6. 외부에서 주입받은 onComplete 클로저 실행
+    if let onComplete {
+        onComplete(selectedYear)
+    } else {
+        // 미주입 방어: 필요한 경우 토스트/로그
+        showToastMessage(message: "다음 단계로 이동할 수 없습니다.", yPosition: view.frame.height * 0.5)
+        vintageView.nextButton.isEnabled = true
+    }
 }

49-58: 내부 전용 메서드 접근 제어자 명시

외부에서 호출되지 않는 setupUI, setupActions, setupNavigationBarprivate로 좁혀 주세요.

- func setupUI() {
+ private func setupUI() {
 ...
- func setupActions() {
+ private func setupActions() {
 ...
- private func setupNavigationBar() {
+ private func setupNavigationBar() {

Also applies to: 60-94, 96-103

DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/SearchWineViewController.swift (2)

174-181: unused closure parameter 경고 해결

selectedYear를 사용하지 않으므로 언더스코어로 치환해 SwiftLint 경고를 없애세요.

- selectVintageVC.onComplete = { [weak self] selectedYear in
+ selectVintageVC.onComplete = { [weak self] _ in
     let vc = TastedDateViewController()
     self?.navigationController?.pushViewController(vc, animated: true)
 }

181-182: 셀 선택 해제로 UX 개선

푸시 후 선택 상태를 해제해 주세요.

- navigationController?.pushViewController(selectVintageVC, animated: true)
+ navigationController?.pushViewController(selectVintageVC, animated: true)
+ tableView.deselectRow(at: indexPath, animated: true)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e93cdc and d424442.

📒 Files selected for processing (7)
  • DE/DE/Sources/Core/CommonUI/Protocols/VintageSelectionViewModel.swift (1 hunks)
  • DE/DE/Sources/Features/Setting/Models/MyOwnedWine.swift (2 hunks)
  • DE/DE/Sources/Features/Setting/ViewControllers/MyWine/AddNewWineViewController.swift (2 hunks)
  • DE/DE/Sources/Features/TastingNote/Models/TNWineDataManager.swift (2 hunks)
  • DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/SearchWineViewController.swift (2 hunks)
  • DE/DE/Sources/Features/Vintage/ReusableVintageSelectionViewController.swift (4 hunks)
  • DE/DE/Sources/Features/Vintage/VintageSelectionView.swift (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: doyeonk429
PR: Drink-Easy/DE_iOS#180
File: DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/RecordGraphViewController.swift:44-46
Timestamp: 2025-09-02T12:53:54.129Z
Learning: 사용자 doyeonk429는 와인 상세에서 테이스팅노트로 이동하는 플로우에서 빈티지가 무조건 설정되어 넘어간다고 설명했습니다. WineDetailViewController에서 goToTastingNote 메서드에서 vintage 가드 조건이 있어 빈티지 선택이 필수입니다.
Learnt from: doyeonk429
PR: Drink-Easy/DE_iOS#0
File: :0-0
Timestamp: 2025-08-30T13:14:55.618Z
Learning: 사용자 doyeonk429는 한국어로 코드 리뷰를 받기를 선호합니다.
📚 Learning: 2025-09-02T12:53:54.129Z
Learnt from: doyeonk429
PR: Drink-Easy/DE_iOS#180
File: DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/RecordGraphViewController.swift:44-46
Timestamp: 2025-09-02T12:53:54.129Z
Learning: 사용자 doyeonk429는 와인 상세에서 테이스팅노트로 이동하는 플로우에서 빈티지가 무조건 설정되어 넘어간다고 설명했습니다. WineDetailViewController에서 goToTastingNote 메서드에서 vintage 가드 조건이 있어 빈티지 선택이 필수입니다.

Applied to files:

  • DE/DE/Sources/Features/Vintage/VintageSelectionView.swift
  • DE/DE/Sources/Core/CommonUI/Protocols/VintageSelectionViewModel.swift
  • DE/DE/Sources/Features/TastingNote/Models/TNWineDataManager.swift
  • DE/DE/Sources/Features/Setting/Models/MyOwnedWine.swift
  • DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/SearchWineViewController.swift
  • DE/DE/Sources/Features/Vintage/ReusableVintageSelectionViewController.swift
  • DE/DE/Sources/Features/Setting/ViewControllers/MyWine/AddNewWineViewController.swift
🧬 Code graph analysis (4)
DE/DE/Sources/Features/TastingNote/Models/TNWineDataManager.swift (1)
DE/DE/Sources/Features/TastingNote/Models/NewTastingNoteManager.swift (1)
  • resetData (117-130)
DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/SearchWineViewController.swift (1)
DE/DE/Sources/Features/TastingNote/Models/TNWineDataManager.swift (1)
  • updateWineData (41-59)
DE/DE/Sources/Features/Vintage/ReusableVintageSelectionViewController.swift (1)
DE/DE/Sources/Features/Vintage/VintageSelectionView.swift (1)
  • setTopSection (28-35)
DE/DE/Sources/Features/Setting/ViewControllers/MyWine/AddNewWineViewController.swift (3)
DE/DE/Sources/Features/Setting/Models/MyOwnedWine.swift (3)
  • resetWine (137-139)
  • setWineId (77-79)
  • setWineName (82-84)
DE/DE/Sources/Features/Setting/ViewControllers/MyWine/BuyNewWineDateViewController.swift (1)
  • nextVC (88-104)
DE/DE/Sources/Features/Setting/ViewControllers/MyWine/PriceNewWineViewController.swift (1)
  • nextVC (70-98)
🪛 SwiftLint (0.57.0)
DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/SearchWineViewController.swift

[Warning] 176-176: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

DE/DE/Sources/Features/Setting/ViewControllers/MyWine/AddNewWineViewController.swift

[Warning] 202-202: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

🔇 Additional comments (12)
DE/DE/Sources/Features/Vintage/VintageSelectionView.swift (2)

6-6: SnapKit import 적절합니다

이 파일에서 snp 제약을 사용하므로 의존성 추가 OK입니다.


28-35: setTopSection: descText를 Optional로 만들고 기본 문구는 중앙화하세요

DE/DE/Sources/Features/Vintage/VintageSelectionView.swift (약 28–35행) — setTopSection이 매 호출마다 descText를 요구하지 않도록 Optional 기본값을 주고, 기본 설명 문구는 중앙집중화하세요. despText라는 오타 프로퍼티가 보이면 rename 권장.

-    func setTopSection(name: String, descText: String) {
+    func setTopSection(name: String, descText: String? = nil) {
         topView.setTitleLabel(title: name,
                               titleStyle: AppTextStyle.KR.subtitle1,
                               titleColor: AppColor.purple100,
-                              description: descText,
+                              description: descText ?? UIString.vintageSelectPrompt,
                               descriptionStyle: AppTextStyle.KR.head,
                               descriptionColor: AppColor.black)
     }
  • 변경 요점: descText를 Optional로 만들어 호출부를 단순화하고, 기본값은 중앙화된 상수(Localizable.strings 또는 UIString.vintageSelectPrompt)에 두세요.
  • 오타 점검: 코드에 despText가 존재하면 descText로 변경하여 혼동 제거.
  • 중복 문자열 정리: "빈티지를 선택해 주세요"는 Localizable.strings나 공용 상수로 이동.

리포지토리에서 구 API/오타 흔적(예: setWineName, SelectVintageViewController, despText 등)을 직접 확인해 주세요. 다음 명령을 실행한 결과를 붙여주시면 추가로 검증하겠습니다:

rg -nP --hidden -uu '\bsetWineName\s*\(' -S || true
rg -nP --hidden -uu '\bSelectVintageViewController\b' -S || true
rg -nP --hidden -uu '빈티지를 선택해 주세요' -S || true
rg -nP --hidden -uu '\bdespText\b|\bdescText\b' -S || true
DE/DE/Sources/Features/TastingNote/Models/TNWineDataManager.swift (1)

4-4: CoreModule import 적절합니다

DE/DE/Sources/Features/Setting/Models/MyOwnedWine.swift (1)

3-3: CoreModule import 적절합니다

DE/DE/Sources/Features/Setting/ViewControllers/MyWine/AddNewWineViewController.swift (1)

18-18: 싱글톤 뷰모델 주입 OK

해당 VC 수명 동안 동일 인스턴스를 사용하므로 일관성 측면에서 문제없습니다. 필요 시 DI로 대체 가능하지만 현 단계에선 과하지 않습니다.

DE/DE/Sources/Features/Vintage/ReusableVintageSelectionViewController.swift (5)

13-21: MVVM 주입과 onComplete 공개, 방향성 좋습니다

뷰모델 주입과 외부 콜백 기반 흐름으로 분리한 점 아주 👍


26-30: 상단 섹션을 ViewModel로 구성한 점 적절합니다

문자열 하드코딩 제거되고 테스트/재사용 용이해졌습니다.


32-35: nav bar hidden 토글, 후속 화면에 영향 확인 필요

viewWillDisappear에서 네비게이션바를 숨기면 다음 화면(TastedDate 등)이 잠깐 숨김 상태로 표시될 수 있습니다. 다음 화면에서 명시적으로 isNavigationBarHidden = false를 보장하는지 확인 부탁드립니다.


96-101: 백 버튼 처리 OK

네비게이션 매니저를 통한 일관된 백 동작과 ViewModel 훅 호출 모두 적절합니다.


127-131: 모달 dismiss 시 피커 상태 동기화 OK

프레젠테이션 델리게이트 활용 적절합니다.

DE/DE/Sources/Features/TastingNote/ViewControllers/CreateVCs/SearchWineViewController.swift (2)

23-23: 네비게이션바 표시 위치(viewWillAppear)로 이동, 적절합니다

화면 복귀 시점에 맞춘 노출 제어로 일관성 좋아졌습니다.


172-173: 데이터 매니저 업데이트 순서 적절

결과 선택 → 데이터 업데이트 → 빈티지 선택 화면 진입 플로우 타이밍 괜찮습니다.

@doyeonk429 doyeonk429 merged commit 9e0efc7 into develop Sep 12, 2025
@doyeonk429 doyeonk429 deleted the feat/issue-184 branch September 12, 2025 09:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] 테이스팅 노트 작성 플로우 > 빈티지 선택 화면 추가

2 participants