Skip to content

[Refactor-T3-187] 감정 구슬 등록 화면 · 추천 루틴 결과 화면 연결 - #64

Merged
choijungp merged 3 commits into
developfrom
refactor/emotion-routine
Oct 2, 2025
Merged

[Refactor-T3-187] 감정 구슬 등록 화면 · 추천 루틴 결과 화면 연결 #64
choijungp merged 3 commits into
developfrom
refactor/emotion-routine

Conversation

@choijungp

@choijungp choijungp commented Oct 1, 2025

Copy link
Copy Markdown
Contributor

🌁 Background

감정 구슬 등록 화면과 추천 루틴 결과 화면을 이어주고 감정 구슬 등록 api를 연동해주었어요 ~~
또한 추천 루틴 결과 화면이 v1과 다르게 변경되어서 그것두 수정해주었답니다 ~


📱 Screenshot

1. 온보딩

Simulator.Screen.Recording.-.iPhone.13.mini.-.2025-10-01.at.13.55.29.mp4

2. 목표 재설정

Simulator.Screen.Recording.-.iPhone.13.mini.-.2025-10-01.at.13.54.10.mp4

3. 감정 구슬 등록

Simulator.Screen.Recording.-.iPhone.13.mini.-.2025-10-01.at.13.54.43.mp4

👩‍💻 Contents

  • 감정 구슬 등록 화면 -> 추천 루틴 결과 화면 연결
  • 감정 구슬 api 연동
  • 추천 루틴 결과 화면 동작 요구사항에 맞게 수정

📝 Review Note

추천 루틴 결과 화면 동작 설명

스크린샷 2025-09-30 23 28 18 스크린샷 2025-09-30 23 28 24

온보딩은 v1과 동일하지만 목표 재설정감정 구슬 등록이 서로 바뀌듯이 수정되었습니다 !!

기존에는 목표 재설정에서는 루틴 선택이 불가능하고 확인 버튼을 통해 추천 루틴 화면으로 이동하는 것이었지만,
수정된 v2에서는 1개의 루틴을 선택하고 루틴 등록 화면으로 이동해달라는 요구사항이 있었습니다.

또한 감정 구슬 등록은 v1에서는 루틴 1개 선택 후 루틴 등록 화면으로 이동했었지만,
수정된 v2에서는 루틴 선택 불가능하고 추천 루틴 결과 목록만 확인할 수 있도록 바뀌었습니다. 😭

감정 구슬 등록 후 추천 루틴 결과 화면에서는 "맞춤 추천 보러가기" 버튼과 "건너뛰기" 버튼이 있습니다.
각 버튼의 용도는 다음과 같습니다.

  • 맞춤 추천 보러가기: 추천 루틴 탭으로 이동
  • 건너뛰기: 홈 탭으로 이동

다만 감정 구슬 등록은 2개의 경로로 진입할 수 있는데요 !! (홈, 추천 루틴 상단)
어떠한 경로로 진입하든 버튼의 동작은 위에 기재한 것과 동일하게 해달라는 디자이너의 요청이 있었습니다 !!!

혹시 흐름이 이해가 안되는 부분이 있다면 말씀해주세용 ~~


📣 Related Issue

  • close #T3-187

Summary by CodeRabbit

  • New Features
    • 감정 등록 완료 후 1초 뒤 추천 루틴 화면으로 자동 이동.
    • 추천 루틴 화면에 감정 등록 진입 버튼 추가.
    • 루틴 생성 완료 시(마이페이지 경로) 루트로 복귀, 2번 탭 전환 및 토스트 노출.
  • Refactor
    • 진입 경로별(온보딩/마이페이지/감정) 확인·건너뛰기 동작을 일관되게 정비: 탭 전환, 루트 이동, 토스트 표시.
    • 추천 루틴 화면의 버튼 라벨 및 초기 활성화 상태 조정.
    • 마이페이지 진입 시 내비게이션 바 항상 표시.
    • 추천 루틴 선택 규칙을 마이페이지 맥락에 맞게 조정.

@choijungp
choijungp requested a review from taipaise October 1, 2025 05:12
@choijungp choijungp self-assigned this Oct 1, 2025
@coderabbitai

coderabbitai Bot commented Oct 1, 2025

Copy link
Copy Markdown

Walkthrough

감정 등록 완료 화면에서 1초 지연 후 추천 루틴 결과 화면으로 내비게이션하도록 변경. 추천 루틴/루틴 생성 흐름에 마이페이지 컨텍스트 분기 추가. 결과 화면의 엔트리 포인트별 버튼/내비 동작 조정. 마이페이지 진입 시 네비게이션 바 강제 표시. 델리게이트를 통해 감정 등록 화면으로 진입 추가.

Changes

Cohort / File(s) Summary of changes
감정 등록 완료 → 추천 루틴 결과 전환
Projects/Presentation/Sources/EmotionRegister/View/EmotionRegisterCompletionViewController.swift
Shared 임포트, emotion 프로퍼티 및 init 추가. viewDidAppear에서 1초 지연 후 DI로 ResultRecommendedRoutineViewModel 생성, 해당 VC로 푸시. 하단 탭 숨김 설정. 의존성 누락 시 fatalError.
마이페이지 내비게이션 바 표시
Projects/Presentation/Sources/MyPage/View/MypageView.swift
viewWillAppear에서 네비게이션 바 숨김 해제 호출 추가.
추천 루틴 화면에서 감정 등록 진입
Projects/Presentation/Sources/RecommendedRoutine/View/RecommendedRoutineViewController.swift
RegisterEmotionButtonViewDelegate 채택. 델리게이트 메서드에서 DI로 EmotionRegisterViewModel 생성 후 EmotionRegistrationViewController 푸시, 탭 바 숨김.
추천 루틴 결과: 엔트리 포인트별 동작 정비
Projects/Presentation/Sources/ResultRecommendedRoutine/View/ResultRecommendedRoutineViewController.swift
버튼 라벨/활성화 로직 재분류(.onboarding/.mypage 묶음, .emotion 분리). .emotion에서 네비 바 타이틀 방식 변경. configureEntryPoint 초기 버튼 상태 조정. Skip/확정 동작을 엔트리 포인트별로 분기: 루트 복귀/탭 전환/토스트 표출/다음 화면 이동 등. 루틴 생성 진입 시 isFromMypage: true 전달.
추천 루틴 결과 ViewModel 선택 로직 수정
Projects/Presentation/Sources/ResultRecommendedRoutine/ViewModel/ResultRecommendedRoutineViewModel.swift
selectRecommendedRoutine에서 선택 초기화 조건을 .emotion.mypage로 변경.
루틴 생성: 마이페이지 분기 추가
Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift
isFromMypage: Bool 프로퍼티/파라미터 추가(기본 false). 등록 버튼 동작 분기: 마이페이지일 때 루트 팝, 탭 2 전환, ViewModel에 토스트 표출 트리거; 그 외 기존 애니메이션 팝.
루틴 생성 ViewModel: 토스트 트리거
Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift
InputshowRecommendedRoutineToastMessageView 추가. action 라우팅 및 지연 후 NotificationCentershowRecommendedRoutineToast 포스트 메서드 추가.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant ERC as EmotionRegisterCompletionVC
  participant DI as DIContainer
  participant RRMVM as ResultRecommendedRoutineViewModel
  participant RRMVC as ResultRecommendedRoutineViewController

  User->>ERC: 화면 표시
  ERC-->>ERC: viewDidAppear (1초 지연)
  ERC->>DI: resolve(ResultRecommendedRoutineViewModel)
  DI-->>ERC: RRMVM
  ERC->>RRMVC: init(viewModel: RRMVM, entry: .emotion)
  ERC->>RRMVC: push(hidesBottomBarWhenPushed = true)
Loading
sequenceDiagram
  autonumber
  actor User
  participant RR as RecommendedRoutineViewController
  participant DI as DIContainer
  participant ERVM as EmotionRegisterViewModel
  participant ERVC as EmotionRegistrationViewController

  User->>RR: RegisterEmotionButton 탭
  RR->>DI: resolve(EmotionRegisterViewModel)
  DI-->>RR: ERVM
  RR->>ERVC: init(viewModel: ERVM)
  RR->>ERVC: push(hidesBottomBarWhenPushed = true)
Loading
sequenceDiagram
  autonumber
  actor User
  participant RRMVC as ResultRecommendedRoutineVC
  participant Nav as UINavigationController
  participant Tab as TabBarView

  rect rgb(235, 245, 255)
  note right of RRMVC: EntryPoint 분기 처리
  alt .emotion - Skip
    User->>RRMVC: Skip 탭
    RRMVC->>Nav: popToRoot(animated: false)
    RRMVC->>Tab: select(tabIndex: 0)
  else .onboarding - Skip
    User->>RRMVC: Skip 탭
    RRMVC->>RRMVC: goToNextView()
    RRMVC->>Tab: setAsRoot()
  else .mypage - Skip
    User->>RRMVC: Skip 탭
    RRMVC-->>User: no-op
  end
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant RC as RoutineCreationViewController
  participant Nav as UINavigationController
  participant Tab as TabBarView
  participant VM as RoutineCreationViewModel
  participant NC as NotificationCenter

  User->>RC: 등록 버튼 탭
  alt isFromMypage == true
    RC->>Nav: popToRoot(animated: false)
    RC->>Tab: select(tabIndex: 1)
    RC->>VM: action(.showRecommendedRoutineToastMessageView)
    VM-->>NC: post(showRecommendedRoutineToast) (지연)
  else isFromMypage == false
    RC->>Nav: popViewController(animated: true)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

당근 들고 탭을 톡, 토끼는 길을 연다
감정에서 추천으로, 1초 숨 고르고 건너
마이페이지 별길 따라 탭 두 칸 점프!
토스트는 포근포근, 알림은 살포시 번져
오늘도 흐름 정돈, 점프와 팝의 춤 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 이 PR 제목은 감정 구슬 등록 화면과 추천 루틴 결과 화면 간의 연결이라는 주요 변경사항을 간결하고 구체적으로 요약하고 있어 스캔하는 동료가 한눈에 의도를 파악할 수 있습니다.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/emotion-routine

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
Projects/Presentation/Sources/MyPage/View/MypageView.swift (1)

44-46: 네비게이션 바 표시 로직이 올바르게 추가되었습니다.

setNavigationBarHidden(false, animated:) 호출은 마이페이지 진입 시 네비게이션 바가 확실히 표시되도록 보장하며, 애니메이션 파라미터를 존중합니다. 이는 PR의 네비게이션 플로우 조정과 잘 부합합니다.

다만, 55번 라인에서 navigationController?.navigationBar.isHidden = false로 동일한 작업을 수행하고 있어 약간의 중복이 있습니다. setNavigationBarHidden(_:animated:) 메서드가 선호되는 API이므로, 필요하다면 55번 라인을 제거하는 것을 고려해볼 수 있습니다.

선택적으로 중복을 제거하려면 다음 diff를 적용할 수 있습니다:

         navigationController?.navigationBar.standardAppearance = appearance
         navigationController?.navigationBar.scrollEdgeAppearance = appearance
         navigationController?.navigationBar.compactAppearance = appearance
-        navigationController?.navigationBar.isHidden = false
     }
📜 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 5ad2984 and d569012.

📒 Files selected for processing (7)
  • Projects/Presentation/Sources/EmotionRegister/View/EmotionRegisterCompletionViewController.swift (5 hunks)
  • Projects/Presentation/Sources/MyPage/View/MypageView.swift (1 hunks)
  • Projects/Presentation/Sources/RecommendedRoutine/View/RecommendedRoutineViewController.swift (2 hunks)
  • Projects/Presentation/Sources/ResultRecommendedRoutine/View/ResultRecommendedRoutineViewController.swift (7 hunks)
  • Projects/Presentation/Sources/ResultRecommendedRoutine/ViewModel/ResultRecommendedRoutineViewModel.swift (1 hunks)
  • Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift (4 hunks)
  • Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-16T09:21:15.038Z
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Onboarding/View/OnboardingRecommendedRoutineView.swift:57-59
Timestamp: 2025-07-16T09:21:15.038Z
Learning: OnboardingRecommendedRoutineView에서 viewWillAppear에 registerOnboarding 호출하는 것이 적절한 이유: 사용자가 이전 페이지에서 온보딩 선택지를 변경한 후 돌아올 때 새로운 선택지로 다시 등록해야 하기 때문. 홈 뷰에서는 이 뷰로 돌아올 수 없어서 중복 호출 문제가 발생하지 않음.

Applied to files:

  • Projects/Presentation/Sources/ResultRecommendedRoutine/View/ResultRecommendedRoutineViewController.swift
🧬 Code graph analysis (5)
Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift (2)
Projects/Presentation/Sources/ResultRecommendedRoutine/ViewModel/ResultRecommendedRoutineViewModel.swift (2)
  • action (56-74)
  • showRecommendedRoutineToastMessageView (161-168)
Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift (3)
  • action (83-117)
  • registerRoutine (244-284)
  • showRecommendedRoutineToastMessageView (286-293)
Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift (1)
Projects/Presentation/Sources/ResultRecommendedRoutine/ViewModel/ResultRecommendedRoutineViewModel.swift (1)
  • showRecommendedRoutineToastMessageView (161-168)
Projects/Presentation/Sources/ResultRecommendedRoutine/View/ResultRecommendedRoutineViewController.swift (2)
Projects/Presentation/Sources/Common/Extension/UIViewController+.swift (1)
  • configureCustomNavigationBar (19-29)
Projects/Presentation/Sources/ResultRecommendedRoutine/ViewModel/ResultRecommendedRoutineViewModel.swift (1)
  • action (56-74)
Projects/Presentation/Sources/RecommendedRoutine/View/RecommendedRoutineViewController.swift (2)
Projects/Shared/Sources/DIContainer/DIContainer.swift (1)
  • resolve (18-25)
Projects/Presentation/Sources/RecommendedRoutine/View/Component/RegisterEmotionButtonView.swift (1)
  • registerEmotionButtonViewDidTapRegisterButton (11-13)
Projects/Presentation/Sources/EmotionRegister/View/EmotionRegisterCompletionViewController.swift (1)
Projects/Shared/Sources/DIContainer/DIContainer.swift (1)
  • resolve (18-25)
⏰ 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 (6)
Projects/Presentation/Sources/ResultRecommendedRoutine/View/ResultRecommendedRoutineViewController.swift (6)

38-61: EntryPoint enum 속성 리팩토링이 적절합니다.

온보딩과 마이페이지가 동일한 동작을 하므로 케이스를 통합한 것이 깔끔합니다. 감정 등록 진입점의 경우 루틴 선택이 불가능하고(isRoutineButtonEnabled = false), 버튼 레이블도 "맞춤 추천 루틴 보러 가기"로 차별화되어 PR 목표와 일치합니다.


130-135: 감정 진입점의 뒤로가기 버튼 제거 동작을 확인해주세요.

.withBackButton(title: "")에서 .withTitle(title: "")로 변경하면서 감정 진입점에서 뒤로가기 버튼이 제거되었습니다. goToNextView()의 감정 케이스가 popToRootViewController를 사용하는 것으로 보아 의도된 동작으로 보이지만, 사용자가 이전 화면(감정 등록 화면)으로 돌아갈 수 없게 됩니다. 이것이 의도된 UX인지 확인이 필요합니다.


213-222: 감정 진입점의 확인 버튼 초기 상태가 적절합니다.

감정 등록 흐름에서는 루틴 선택이 불필요하므로(isRoutineButtonEnabled = false) 확인 버튼을 처음부터 활성화(buttonState: .default)하는 것이 올바른 구현입니다.


313-335: 건너뛰기 버튼의 진입점별 동작이 정확합니다.

각 진입점별 동작이 명확하게 구분되어 있습니다:

  • 감정 진입점: 홈 탭(index 0)으로 이동 (PR 목표와 일치)
  • 온보딩: goToNextView() 호출
  • 마이페이지: 동작 없음 (버튼이 숨겨져 있음)

337-358: goToNextView()의 진입점별 흐름이 PR 목표와 일치합니다.

각 케이스의 동작:

  • 온보딩: TabBarView로 루트 전환
  • 마이페이지: fetchSelectedRoutineId 호출하여 루틴 생성 화면으로 이동
  • 감정: 추천 루틴 탭(index 1)으로 이동 후 토스트 표시

감정 케이스의 "맞춤 추천 보러가기" 버튼 동작이 정확하게 구현되었습니다.


360-369: RoutineCreationViewController 초기화 시그니처 확인 완료. isFromMypage가 기본값 false로 정의되어 기존 호출에 영향 없으며, 마이페이지 진입점에서 true로 전달하는 것도 적절합니다.

Comment on lines 145 to +156
UIAction { [weak self] _ in
self?.viewModel.action(input: .registerRoutine)
self?.navigationController?.popViewController(animated: true)
guard let self else { return }
self.viewModel.action(input: .registerRoutine)
if self.isFromMypage {
if
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first(where: { $0.isKeyWindow }),
let tabBarView = window.rootViewController as? TabBarView {
self.navigationController?.popToRootViewController(animated: false)
tabBarView.selectedIndex = 1
viewModel.action(input: .showRecommendedRoutineToastMessageView)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

self 누락으로 인한 컴파일 오류

UIAction 클로저 내부에서는 self를 명시해야 합니다. 현재 viewModel.action(input: .showRecommendedRoutineToastMessageView) 호출은 컴파일되지 않습니다. 아래와 같이 self.viewModel로 수정해 주세요.

-                        viewModel.action(input: .showRecommendedRoutineToastMessageView)
+                        self.viewModel.action(input: .showRecommendedRoutineToastMessageView)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
UIAction { [weak self] _ in
self?.viewModel.action(input: .registerRoutine)
self?.navigationController?.popViewController(animated: true)
guard let self else { return }
self.viewModel.action(input: .registerRoutine)
if self.isFromMypage {
if
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first(where: { $0.isKeyWindow }),
let tabBarView = window.rootViewController as? TabBarView {
self.navigationController?.popToRootViewController(animated: false)
tabBarView.selectedIndex = 1
viewModel.action(input: .showRecommendedRoutineToastMessageView)
}
UIAction { [weak self] _ in
guard let self else { return }
self.viewModel.action(input: .registerRoutine)
if self.isFromMypage {
if
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first(where: { $0.isKeyWindow }),
let tabBarView = window.rootViewController as? TabBarView {
self.navigationController?.popToRootViewController(animated: false)
tabBarView.selectedIndex = 1
self.viewModel.action(input: .showRecommendedRoutineToastMessageView)
}
}
}
🤖 Prompt for AI Agents
Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift
lines 145-156: inside the UIAction closure the call viewModel.action(input:
.showRecommendedRoutineToastMessageView) is missing the explicit self reference
causing a compile error; change that call to self.viewModel.action(input:
.showRecommendedRoutineToastMessageView) (keeping the existing [weak self]
capture and the guard let self else { return } intact).

@taipaise taipaise left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오늘도 고생하셨습니다!! 그리고 변경된 사항을 사진과 표로 정리해주셔서 정말로 쉽게 이해할 수 있었습니다 (아리가토~~)

@choijungp
choijungp merged commit f5c3593 into develop Oct 2, 2025
2 checks passed
@choijungp
choijungp deleted the refactor/emotion-routine branch October 2, 2025 06:28
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.

2 participants