Skip to content

refactor: [공방] Bundle 아키텍처 전면 개편 - 폴더 구조, ViewModel 분리, 버그 수정 등#47

Merged
giljihun merged 10 commits intodevelopfrom
style-뭉치-만들기-플로우-기본-ui-변경
Feb 5, 2026

Hidden character warning

The head ref may contain hidden characters: "style-\ubb49\uce58-\ub9cc\ub4e4\uae30-\ud50c\ub85c\uc6b0-\uae30\ubcf8-ui-\ubcc0\uacbd"
Merged

refactor: [공방] Bundle 아키텍처 전면 개편 - 폴더 구조, ViewModel 분리, 버그 수정 등#47
giljihun merged 10 commits intodevelopfrom
style-뭉치-만들기-플로우-기본-ui-변경

Conversation

@giljihun
Copy link
Member

@giljihun giljihun commented Feb 5, 2026

Summary

  • Bundle 폴더 구조 전면 재정리 (Views 계층화, ViewModels 책임 분리)
  • Create/Edit 화면 간 중복 코드 80% 이상 제거
  • BundleViewModel 비즈니스 로직 분리 및 9개 파일로 재구성
  • CollectionViewModel DI 패턴 적용으로 메모리 최적화 (뭔가 좀 전환이나 앱동작이 빨라진거같다)
  • 뭉치 생성/편집 시 발생하던 동기화 버그 수정

🎯 PR 내용

1. 폴더 구조 전면 개편

Before:

Bundle/Views/
├── BundleDetailView.swift
├── BundleEditView.swift
├── BundleCreateView.swift
├── SelectBackgroundSheet.swift
├── ... (모든 파일이 flat하게 존재)

뷰안에 다 때려박혀있어서, 식별이 너무 어려웠다.

After:

Bundle/Views/
├── Detail/          # 뭉치 상세 화면
├── Edit/            # 뭉치 편집 화면
├── Create/          # 뭉치 생성 화면
└── Shared/          # 공통 컴포넌트

편안하다.

2. 중복 코드 제거 및 공통 컴포넌트 추출

Create/Edit 화면에서 동일하게 사용되던 UI 컴포넌트들을 Shared로 추출:

컴포넌트 설명
BundlePurchaseCartItem 구매 장바구니 아이템 셀
BundleSheetToggleButtons 배경/카라비너 시트 토글 버튼
AddKeyringButton 키링 추가 버튼
BackgroundCell 배경 선택 셀
CarabinerCell 카라비너 선택 셀
KeyringCell 키링 선택 셀
SelectBackgroundSheet 배경 선택 시트
SelectCarabinerSheet 카라비너 선택 시트
CarabinerPopup 카라비너 정보 팝업
DraggableSheet 드래그 가능한 시트

생성 / 수정이 매우 비슷해서 겹쳐있는게 많았다. 추상화 진행.

3. BundleViewModel 아키텍처 개선

Before (8개 파일, 책임 혼재):

  • +LoadData, +CRUD, +Edit, +Sort, +Image, +CaptureScene, +ReloadDecision...

After (9개 파일, 명확한 책임 분리):

파일 책임
BundleViewModel.swift 프로퍼티만 (상태 정의)
+Types.swift 데이터 구조체 (BackgroundViewData, CarabinerViewData, KeyringInfo)
+Fetch.swift Firebase 읽기 (bundles, backgrounds, carabiners, keyrings)
+CRUD.swift Firebase 쓰기 (create, update, delete)
+Edit.swift 편집 로직 + 정렬 (기존 +Sort 병합)
+Purchase.swift 구매 로직 (View에서 분리)
+Helpers.swift 유틸리티 (ID 변환, 사용자 아이템 추가)
+Cache.swift 캐시/최적화 (기존 +ReloadDecision + 이미지 캐시 병합)
+Views.swift UI 컴포넌트 (기존 +CaptureScene + 이미지 뷰빌더 병합)

4. 비즈니스 로직 View → ViewModel 이동

구매 로직 분리

기존에 View에 흩어져 있던 구매 관련 로직을 ViewModel로 통합:

  • payableItemsCount - 구매 가능한 아이템 수 계산
  • totalCartPrice - 총 구매 가격 계산
  • hasUnpurchasedItems - 미구매 아이템 존재 여부
  • purchaseSelectedItems() - 실제 구매 처리 (async)
  • isPurchasing - 구매 진행 중 상태

State 상태 변수들 → ViewModel 통일

BundleCreateView에서 로컬로 관리하던 상태들을 ViewModel로 이동하여 화면 간 상태 공유 및 일관성 확보

5. CollectionViewModel DI 적용 (Critical Issue)

기존에는 HomeTab, WorkshopTab, CollectionTab에서
각각 CollectionViewModel()을 생성하여 3개의 인스턴스가 존재했음

MainTabViewModel에서 단일 인스턴스를 생성하고 각 탭에 주입하는 방식으로 변경

효과:

  • 메모리 사용량 감소 (3개 → 1개 인스턴스)
  • 불필요한 Firebase 중복 요청 제거
  • 탭 전환 시 데이터 유지 (이게 큰 버그 유발 가능자였던 것 같다.)

6. 버그 수정

홈에서 번들 변경 구현 후, 새 뭉치 생성 후 홈 화면 미동기화 문제가 있었다.

  • 원인: HomeViewModel이 BundleViewModel 변경을 감지하지 못함
  • 해결: 뭉치 생성 완료 시 refreshBundlesFromBundleVM() 호출 추가

편집 후 키링 데이터 미갱신

  • 원인: 편집 완료 시 키링 fetch 누락
  • 해결: 편집 저장 후 fetchUserKeyring() 호출 추가

좋았어..

🔗 관련 이슈

✅ 체크리스트

  • 빌드 성공
  • 테스트 완료
  • Self-review 완료

- 기존에 하나의 Views -> 역할별 분리
- Views를 플로우 기반으로 분리 (Create, Edit, Detail, Shared)
- Shared 컴포넌트 파일명/Struct명 간소화
- *SelectableCell → *Cell
- KeyringBundleItem → BundleGridItem
- BundleItemCustomSheet → DraggableSheet
- 파일명 ↔ Struct명 불일치 수정
- BundleViewModel을 의존성주입해서 3개 탭에서 단일 인스턴스 공유
- HomeViewModel에 lastLoadedBundleId 추가, 뭉치 변경 감지함
- 새 뭉치 선택 시 키링 데이터 갱신 안되던 버그 해결
- BundleSheetToggleButtons: 배경/카라비너 시트 토글 버튼 추출
- BundlePurchaseCartItem: 구매 장바구니 아이템 행 추출
- BundleCreateView, BundleEditView+Purchase, BundleEditView+SelectSheet에서 중복 제거
- selectedBackground/selectedCarabiner 로컬 @State 제거
- bundleVM.newSelectedBackground/newSelectedCarabiner 직접 사용
- 불필요한 onChange 동기화 코드 제거
- EditView와 동일한 상태 관리 패턴 적용
- BundleViewModel에 구매 관련 computed properties 추가 (payableItemsCount, totalCartPrice, hasUnpurchasedItems)
- BundleViewModel에 isPurchasing 상태 및 purchaseSelectedItems() 메서드 추가

- BundleCreateView에서 로컬 구매 로직 제거, ViewModel 사용으로 변경

- BundleEditView+Purchase에서 중복 구매 로직 제거, ViewModel 사용으로 변경
- BundleEditView에서 로컬 isPurchasing 상태 제거

- Task.sleep을 nanoseconds에서 seconds 스타일로 변경
- MainTabViewModel의 CollectionViewModel을 각 탭에 주입
- HomeTab, WorkshopTab, CollectionTab에서 로컬 인스턴스 생성 제거
- 단일 인스턴스 공유로 메모리 사용 감소 및 데이터 동기화 개선
- +Types: 데이터 구조체 분리 (BackgroundViewData, CarabinerViewData, KeyringInfo)
- +Fetch: +LoadData에서 이름 변경
- +Edit: +Sort 병합
- +Purchase: 구매 로직 분리
- +Helpers: 유틸리티 메서드 분리
- +Cache: +ReloadDecision + 이미지 캐시 로직 병합
- +Views: +CaptureScene + 이미지 뷰빌더 병합
- 각 파일에 역할 설명 주석 추가
- 아 힘들어
@giljihun giljihun self-assigned this Feb 5, 2026
@giljihun giljihun linked an issue Feb 5, 2026 that may be closed by this pull request
@freshfresh22
Copy link
Member

오예~!
빨라진거좋다

@giljihun giljihun merged commit d22e9e6 into develop Feb 5, 2026
@Rama-Moon
Copy link

고봉밥 PR 레전드 열정길

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.

Refactor: [공방] Bundle 아키텍처 전면 개편

3 participants