Skip to content

refactor: Reducer 리팩토링#212

Draft
clxxrlove wants to merge 1 commit intodevelopfrom
refactor/#211
Draft

refactor: Reducer 리팩토링#212
clxxrlove wants to merge 1 commit intodevelopfrom
refactor/#211

Conversation

@clxxrlove
Copy link
Member

🔗 관련 이슈

📙 작업 내역

  • 임시 PR입니다

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

  • HomeReducer만 간단하게 수정해봤는데 이 방향이 맞는지 체크하고 넘어가야 할 거 같아서 미리 Draft로 올려뒀어
  • 한번 체크 부탁함 !! @jihun32

@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a7192277-a185-47f5-aa5f-feca453e8215

📥 Commits

Reviewing files that changed from the base of the PR and between f9fc036 and 16b9109.

📒 Files selected for processing (4)
  • Projects/Feature/Home/Interface/Sources/Home/HomeReducer.swift
  • Projects/Feature/Home/Interface/Sources/Root/HomeCoordinator.swift
  • Projects/Feature/Home/Sources/Home/HomeReducer+Impl.swift
  • Projects/Feature/Home/Sources/Home/HomeView.swift

📝 Walkthrough

HomeReducer 리팩토링

개요

복잡도가 증가하는 Home Reducer를 아키텍처적으로 개선하기 위한 리팩토링입니다. 상태와 액션의 도메인 기반 분할을 통해 코드 구조를 정리합니다. (#211 이슈와 연계)

주요 아키텍처 변경

상태(State) 구조 재편성

  • 평탄 구조 → 중첩 구조로 전환하여 관심사 분리:
    • State.Data: 도메인 데이터 관리 (cards, goalsCache, calendarDate, calendarSheetDate, calendarWeeks, 보류 중인 삭제 작업)
    • State.UIState: UI 상태 (isLoading, mainTitle, calendarMonthTitle, isRefreshHidden, hasUnreadNotification, nowDate)
    • State.Presentation: 프레젠테이션 레이어 (toast, modal, sheet/alert 플래그)
    • proofPhotohasCards 계산 속성은 최상위 수준 유지

액션(Action) 세분화

  • 도메인 기반 sub-enum 도입으로 액션 분류:
    • Action.View: 사용자 이벤트 (onAppear, 카드 탭, 버튼 클릭 등)
    • Action.Internal: 내부 트리거 (목표 조회 같은 부수 효과 시작)
    • Action.Response: 비동기 완료/API 응답 처리 (deletePhotoLogResult, pokePartnerResult, fetchGoalsResult 등)
    • Action.Presentation: 토스트 메시지 표시용 (.showToast(...))
    • 최상위 보존: proofPhoto, binding, delegate

상태 변경 및 흐름 개선

Reducer 구현 재조직

  • 단일 monolithic switch → 구조화된 감소 함수:
    • reduceView, reduceInternal, reduceResponse, reducePresentation 함수로 로직 분해
    • 각 액션 카테고리별 명확한 처리 경로 형성

비동기 작업 및 사이드 이펙트 명시화

  • 목표 조회, 권한 확인, 포토로그 삭제, 파트너 포킹 등의 비동기 작업이 명시적인 response 액션으로 라우팅
  • 포토 업로드 완료 처리: state.data.cards/state.data.goalsCache 업데이트 후 response 액션 디스패치
  • 실패 처리: presentation 토스트로 통합 (.presentation(.showToast(...)))

뷰 계층 업데이트

HomeView 액션 라우팅 변경

  • store.send(.onAppear)store.send(.view(.onAppear))
  • 대부분의 사용자 상호작용을 .view(...) 래퍼로 감싸기
  • 목표 새로고침: .fetchGoals.internal(.fetchGoals)

상태 접근 패턴 변경

  • 최상위 속성 접근 → 중첩된 스토어 네임스페이스 사용
    • store.ui.*: UI 상태 읽기
    • store.data.*: 도메인 데이터 읽기
    • store.presentation.*: 프레젠테이션 바인딩
  • 예: store.isLoadingstore.ui.isLoading, store.cardsstore.data.cards

변경 영역

  • Projects/Feature/Home/Interface/Sources/Home/HomeReducer.swift (+116/-67)
  • Projects/Feature/Home/Sources/Home/HomeReducer+Impl.swift (+380/-313)
  • Projects/Feature/Home/Sources/Home/HomeView.swift (+43/-43)
  • Projects/Feature/Home/Interface/Sources/Root/HomeCoordinator.swift (+1/-1, 문서만 업데이트)

검토 포인트

  • 중첩 상태 구조의 스냅샷 테스트 관리 (테스트 변경사항 미기록)
  • 다른 Reducer 리팩토링 시 일관성 유지 여부
  • 자식 Reducer 통합(composition) 방식이 유지되는지 확인

Walkthrough

HomeReducer의 상태와 액션 구조를 평탄화에서 중첩 분할 구조로 리팩토링했습니다. 상태를 Data, UIState, Presentation으로 분리하고, 액션을 View, Internal, Response, Presentation 하위 열거형으로 재구성했으며, 이에 따라 구현과 뷰를 업데이트했습니다.

Changes

Cohort / File(s) Summary
State 구조 리팩토링
Projects/Feature/Home/Interface/Sources/Home/HomeReducer.swift
StateData, UIState, Presentation 중첩 타입으로 분할하고, HomeError 열거형 추가. 액션을 View, Internal, Response, Presentation 하위 열거형으로 재구성.
Reducer 구현 업데이트
Projects/Feature/Home/Sources/Home/HomeReducer+Impl.swift
단일 Reduce 스위치를 reduceView, reduceInternal, reduceResponse, reducePresentation으로 분해. 상태 접근을 중첩 경로(예: state.ui.isLoading, state.data.cards)로 변경. 비동기 효과와 응답 처리를 새로운 액션 라우팅으로 재구성.
뷰 업데이트
Projects/Feature/Home/Sources/Home/HomeView.swift
상태 읽기를 중첩 스토어 네임스페이스(store.ui.*, store.data.*, store.presentation.*)로 변경. 디스패치 호출을 .view(...)로 래핑하여 새로운 액션 라우팅 패턴 적용.
문서 예제 업데이트
Projects/Feature/Home/Interface/Sources/Root/HomeCoordinator.swift
액션 경로 예제를 .home(.onAppear)에서 .home(.view(.onAppear))로 업데이트.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/#211
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

CodeRabbit can generate a title for your PR based on the changes with custom instructions.

Set the reviews.auto_title_instructions setting to generate a title for your PR based on the changes in the PR with custom instructions.

@clxxrlove
Copy link
Member Author

@coderabbitai summary

@clxxrlove clxxrlove marked this pull request as draft March 19, 2026 09:35
@github-actions github-actions bot requested a review from jihun32 March 19, 2026 09:35
@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

✅ Actions performed

Summary regeneration triggered.

Copy link
Contributor

@jihun32 jihun32 left a comment

Choose a reason for hiding this comment

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

맞아! 근데 지금보니까 State랑 Action에 하위 리듀서 state랑 action이 덩그러니 있는데 이것도 Child로 묶으면 어떨까?

as-is

public var proofPhoto: ProofPhotoReducer.State?

to-be

public struct ChildState: Equatable {
    public var proofPhoto: ProofPhotoReducer.State?
}

action도 비슷하게 하면 될 거 같은데 어때?

Comment on lines +94 to 106
public var hasCards: Bool { !data.cards.isEmpty }

public var goalSectionTitle: String {
let now = CalendarNow()
let today = TXCalendarDate(year: now.year, month: now.month, day: now.day)
if calendarDate < today {
if data.calendarDate < today {
return "지난 우리 목표"
}
if today < calendarDate {
if today < data.calendarDate {
return "다음 우리 목표"
}
return "오늘 우리 목표"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

이것들도 UI 안에 넣는게 좋을듯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants