Skip to content

차곡 v1.0.0을 배포합니다.#270

Merged
Tom-BumSuChoi merged 1492 commits into
mainfrom
dev
Jun 3, 2026
Merged

차곡 v1.0.0을 배포합니다.#270
Tom-BumSuChoi merged 1492 commits into
mainfrom
dev

Conversation

@Kimyonhae

Copy link
Copy Markdown
Collaborator

📦 차곡 (ChaGok) Release Notes


🚀 최신 업데이트 요약

이번 업데이트에서는 WhisperKit/MLX 엔진의 안정성 및 영속성 문제를 해결하고, 사용자 경험을 개선하기 위한 UI/UX 폴리싱내부 리팩토링 작업을 대폭 진행했습니다. 또한, SPM-Tuist 테스트 빌드 이슈를 수정하여 개발 생산성을 개선했습니다.


✨ 신규 기능 및 사용자 경험 (UI/UX) 개선

🏷️ 카테고리 직관화 및 네이밍 변경

사용자가 화면의 역할을 보다 쉽게 파악할 수 있도록 홈 화면의 주요 카테고리 네이밍을 직관적으로 변경했습니다.

  • 기본 폴더 ➔ 📁 모든 기록
  • 개인 폴더 ➔ 📂 폴더 목록

🎨 앱 로고 최적화 (Icon Composer 및 리소스 이관)

  • Icon Composer를 연동하여 완성도 높은 앱 로고를 공식적으로 설정했습니다.
  • Tuist 환경에서 tuist generate를 실행할 때 로고 파일이 사라지는 문제를 해결하기 위해, 루트 디렉토리가 아닌 Resource 폴더 내부로 아이콘 에셋을 안전하게 이관했습니다.

🔄 다운로드 UX 개선 (에러 핸들링 및 재시도)

  • 다운로드 요청 전 errorMessage를 초기화하여 이전의 에러 상태가 UI에 잔존하지 않도록 개선했습니다.
  • 레이아웃이 깨지지 않도록 불필요한 AutoLayout 제약 조건 워닝을 말끔히 정리했습니다.
  • LocalizedError의 기본 구현 타입 이슈로 인해 특정 에러 상황에서 메시지가 정상 표출되지 않던 문제를 수정하여, 네트워크 유실이나 다운로드 실패 시 사용자에게 정확한 실패 원인을 안내하도록 개편했습니다.

🗑️ 휴지통 음성 노트 진입 시 보안 및 기능 제한 (isTrashMode)

  • 휴지통에 보관된 음성 노트를 클릭하여 진입할 시 isTrashMode를 활성화하여 실수로 편집되거나 유실되는 것을 방지합니다.
  • 휴지통 모드에서는 뒤로 가기, 음성 재생/일시 정지, 검색 기능을 제외한 모든 부가 기능(스크립트 수정, 다운로드 재시도 등)이 안전하게 제한됩니다.

⚡ Whisper 모델 로딩 타이밍 변경을 통한 성능 최적화

  • 녹음 화면을 닫을 때(dismiss) 수행되던 Whisper 모델 로딩 과정을 녹음 화면에 최초 진입하는 시점으로 앞당겨 로딩 딜레이를 해소하고 최적의 앱 반응 속도를 확보했습니다.

🐛 버그 수정 및 안정성 향상

🔒 WhisperKit 영속성 버그 & 무결성 검증 추가

  • 존재하지 않는 Whisper 모델 파일을 탐색함으로써 발생하던 Source of Truth 검증 실패(영속성 오류) 현상을 해결했습니다.
  • 단순히 모델의 경로 존재 여부뿐만 아니라 모델 내부 파일의 완결성(Integrity) 검증 로직을 더해 에러를 사전에 방지하도록 견고화했습니다.
  • 에러 발생 상황을 구체적으로 세분화하여, 사용자 화면에 상황별(요약 실패, 기기 사용 제한 등) 알림창(WarningConstration)이 정확히 다르게 표출되도록 분기 처리했습니다.

🧪 MLX / Whisper 에러 스트림 고도화 (디버깅 지원)

  • 온디바이스 AI 파이프라인에서 예외 상황이 발생할 경우, 구체적인 원인 추적이 가능하도록 각 URLErrorNSError의 세부 에러 메시지를 스트림을 통해 외부로 던지도록 설계했습니다.

📥 모델 다운로드 중복 요청 방지

  • 이미 다운로드가 진행 중인 경우, 내부적으로 고유 UUID를 발급하여 해당 프로세스를 식별 및 추적합니다.
  • 동일 모델에 대한 중복 다운로드 요청 발생 시, 진행 중이던 기존 작업을 cancel하고 조기 반환(return) 처리하여 시스템 리소스 낭비를 막았습니다.

🛠️ 개발 생산성 및 코드 품질 향상 (Refactoring)

⚙️ Tuist / SPM 테스트 빌드 실패 해결

  • Swift Package Manager(SPM) 환경에서 Tuist 단위 테스트(tuist test)를 빌드할 때, 매크로 자동 생성 코드의 호환성 문제로 빌드가 지속 실패하는 문제를 확인했습니다.
  • 이를 해결하기 위해 매크로 코드를 의존하는 대신 **내부 수동 코드를 대상 파일에 직접 추가(리팩토링)**하여 테스트 빌드가 무리 없이 성공하도록 수정했습니다.

🧹 SwiftFormat 스타일 적용 및 코드 정리

  • Domain 모듈의 일관성을 높이기 위해 swiftformat 컨벤션을 일괄 적용했습니다.
  • OnDeviceStatus 엔티티 내에서 실제로 사용되지 않고 방치되어 있던 runTime 프로퍼티 필드를 과감히 제거하여 데이터 모델을 단순화했습니다.

🧪 단위 테스트 Mock 데이터 동기화

  • 최근 비즈니스 로직 및 인터페이스 변경점에 맞춰 MockOnDeviceStatusUseCase 및 테스트 시그니처를 최신 사양으로 업데이트했습니다.
  • FolderDetailViewModel, MainViewModel, TrashViewModelSettingViewModel 프리뷰 파일 등 영향이 미치는 모든 테스트 코드 내 파라미터 매칭을 완벽히 완료했습니다.

TomBumSuChoi added 30 commits April 23, 2026 22:13
- VoiceNoteViewModel.moveVoiceNote에 완료 콜백 파라미터 추가
- VoiceNoteViewController에서 이동 완료 시 폴더명을 담은 토스트 표시
- MoveFolderCoordinator에 TopDetentStyle enum(belowNavigationBar/belowSegmentControl)을 도입하고, 경로별로 다른 상단 inset을 적용
- MainCoordinator: VoiceNote/FolderDetail 델리게이트 구현을 분리하고 공통 시트 제시 로직을 private helper로 통합
- VoiceNoteCoordinatorDelegate.presentFolderList를 presentMoveFolder(for:onComplete:)로 rename하여 FolderDetail 경로와 시그니처 분리
- UnderlineSegmentedControl 상수(underlineSegmentedControlHeight, underlineSegmentedControlTopMargin)를 Constant에 추가해 VoiceNoteViewController와 detent 계산에서 공유
- 검색 모드 종료 시 이전 재생 상태와 무관하게 play를 호출하지 않도록 검증
- wasPlaying 플래그 제거에 맞춰 테스트 명명도 재정리
폴더 이동 시트 구조와 detent를 정리합니다.
- 좌측 고정 scaleX 애니메이션이 적용되는 가로 그라디언트 막대
- 핵심 포인트 / 키워드 스켈레톤 셀에서 사용 예정
- 관련 상수는 Constant.skeleton* 로 분리
- 핵심 포인트 영역의 로딩 스켈레톤 셀
- SkeletonLineView를 래핑하고 보라 원 번호 뱃지를 동일 컨테이너로 결합
- beginOffset으로 셀별 애니메이션 위상 차등
- 키워드 영역의 로딩 스켈레톤 셀
- 셀 1개당 라인 1개 — 행 개수는 데이터소스에서 결정
- 캡슐 형태 cornerRadius는 layoutSubviews에서 bounds.height / 2로 계산
- analysisState가 pending/transcribing/transcribed/summarizing/regenerating일 때
  핵심 포인트 3개, 키워드 2개의 스켈레톤 셀 노출
- VoiceNoteSummaryViewController.Item에 keyPointSkeleton/keywordsSkeleton 케이스 추가
- 키워드 섹션 셀 간격을 keywordChipLineSpacing(10)으로 분리
- 키워드 스켈레톤 셀 높이를 KeywordChipLabel.standardHeight로 강제하여
  스켈레톤 ↔ 실제 chip 전환 시 셀 높이 점프 제거
- analysisState가 pending/transcribing일 때 스크립트 페이지에 본문 라인
  스켈레톤 30개 노출
- VoiceNoteScriptViewController.Item에 scriptSkeleton 케이스 추가
- 스켈레톤 표시 중에는 셀 간격 8, 실제 표시 중에는 16으로 분기
- analysisState 변경 시 invalidateLayout으로 spacing 즉시 갱신
- ScriptCell의 timeLabel-textView 간격 중복 제거
  (textContainerInset.top 8 한 군데에서만 결정)
- CoreDataLocalDataBase에 NSFetchedResultsController 기반 observeAll 추가
- VoiceNoteRepository/UseCase에 observe(folderID:), observeAllFromDefaultFolder,
  observeRecent(limit:) 추가
- WasteBasketRepository에 observe() 추가 (VoiceNote/Folder 두 stream을 합쳐 emit)
- FolderRepository에 observeAll, FolderUseCase에 observeDeletableFolders 추가
- 각 Mock(VoiceNote/Folder/WasteBasket)에 신규 stream 메서드용 result/expect/verify 추가
- 기존 fetch 계열 API는 호환을 위해 유지
- FolderDetailViewModel: fetchItems 제거 → observe(folderID:) 구독으로 전환,
  onAppear/onDisappear 도입
- MainViewModel: 4개 카테고리(최근/기본 폴더/개인 폴더/휴지통) 각각 stream 구독으로 전환,
  cancelObservations 추가하여 viewWillDisappear 시 정리
- TrashViewModel: fetchItems 제거 → repository.observe() 구독으로 전환,
  onAppear/onDisappear 도입
- VoiceNoteViewModel.observeVoiceNote의 dropFirst 제거 — 부모가 stream으로
  latest를 보장하므로 첫 emit 스킵 의식 불필요
- 각 ViewController의 viewWillAppear/viewWillDisappear에서 lifecycle 메서드 호출
- Preview/Fake 구현체 및 ViewModel 테스트(FolderDetail/Main/Trash)를 stream 기반으로
  업데이트

Closes #243
- ManagedObjectMapping 프로토콜 + 6개 Entity의 toModel/insert/update/find/
  identityPredicate/entityName/sortDescriptors 모두 제거
- CoreDataLocalDataBase를 NSPersistentContainer 노출만 하는 wrapper로 축소
  (CRUD/observe 메서드 모두 제거)
- DataTests target/scheme + Tests 디렉토리 통째 제거

WIP: 매핑/Repository 재작성 전까지 빌드 깨짐 (#243)
- DefaultVoiceNoteRepository, DefaultFolderRepository, DefaultWasteBasketRepository의
  init이 CoreDataLocalDataBase 대신 NSManagedObjectContext를 직접 받도록 변경
- AppDIContainer에서 localDataBase.container.viewContext를 주입하도록 수정

WIP: 메서드 본문 + Entity 매핑 재작성 전까지 빌드 깨짐 (#243)
- Folder 모델: isDeletable: Bool 제거 → kind: FolderKind 추가
- FolderKind enum 신설 (.default, .custom, .trash) — .trash는 휴지통 통합 추후
- FolderEntity (xcdatamodel + Swift): isDeletable → kindRaw: String
- FolderUseCase / VoiceNoteUseCase의 isDeletable 사용처를 kind 기반으로 변경
- DefaultVoiceNoteUseCase.create는 default folder를 fetch한 뒤 VoiceNote를
  구성해 repository에 넘김 (title 같은 비즈니스 결정도 UseCase로 이동)
- VoiceNoteRepository.create 시그니처 변경: VoiceRecord -> VoiceNote
  (Repository는 단순 영속화)
- AppDIContainer에서 voiceNoteUseCase에 folderRepository 주입
- 기존 isDeletable을 사용하던 모든 호출처(Stub/Mock/Preview/Test) 업데이트

WIP: Repository 메서드 본문 + Entity 매핑 재작성 전까지 빌드 깨짐 (#243)
마이그레이션은 의도적으로 무시 (개발 단계, 데이터 손실 허용)
- xcdatamodel의 6개 entity에 codeGenerationType="manualNone" 명시 (수동 정의 명확화)
- 각 entity에 @nonobjc class func fetchRequest() static 메서드 추가
- DefaultVoiceNoteRepository.create가 FolderEntity.fetchRequest() 사용
- CoreDataEntityName enum 삭제 (entity name 문자열은 fetchRequest() 안으로 격리)
- Folder.kind에 .trash 케이스 추가 (앱 첫 실행 시 자동 생성)
- VoiceNote에 originalFolderID/deletedWithFolder 필드 추가
  - 휴지통 진입 시 원본 폴더 위치 + cascade 여부 기록
- FolderRepository: fetch(by kind:), observe(by kind:) 추가, observeAll 제거
- VoiceNoteRepository: observe(folderID:)/observeRecent에 trash 필터 추가
- 휴지통 연산을 각 도메인 Repository로 이동
  - Folder/VoiceNote.moveToTrash, restore, hardDelete
  - 폴더 삭제 시 안의 노트 cascade로 휴지통 폴더로 이동
  - 폴더 복원 시 cascade 노트만 함께 복원 (단독 삭제 노트는 휴지통 유지)
- TrashUseCase 신설 — 두 stream merge하여 [WasteBasketItem] 조립
- WasteBasketRepository(프로토콜·구현체·에러) 전부 제거
- xcdatamodel codeGenerationType="manualNone" 제거 (Xcode 빌드 크래시 원인)
- FRCStreamDelegate 헬퍼 추가
- AppDIContainer: WasteBasketRepository 제거, TrashUseCase 등록
- ViewModel 마이그레이션
  - TrashViewModel: TrashUseCase 사용, restore/cancel 분기 처리
  - MainViewModel: trash 카테고리 stream을 TrashUseCase로 변경
  - FolderViewModel: 폴더 휴지통 이동을 trashUseCase.moveToTrash(folderID:)로
  - FolderDetailViewModel: 노트 이동/복원을 trashUseCase 사용
  - VoiceNoteViewModel: 노트 휴지통 이동을 trashUseCase.moveToTrash(noteID:)로
  - OnBoardingViewModel: 첫 실행 시 createTrash() 호출 추가
  - 모든 Preview에 PreviewTrashUseCase 추가
- DebugSeeder: VoiceNoteRepository.create 시그니처 변경에 맞춰 VoiceNote 직접 구성
- DomainTesting: MockTrashUseCase 추가, MockFolderRepository/MockVoiceNoteRepository에 trash API 추가
- 모든 ViewModel Tests SUT 업데이트 + WasteBasketRepository 의존 제거
…트 수정

- Folder.content([VoiceNote]) → voiceNoteIDs([UUID])
  - FolderEntity.toModel()에서 살아있는 노트 ID만 추출 (휴지통 노트 제외)
  - FolderCardView/FolderViewCell/MoveFolderListView가 voiceNoteIDs.count 표시
    → 개인폴더 카운트가 0으로만 보이던 버그 해결
- 휴지통 시스템을 "nested folder" 모델로 재정의
  - Folder.parentID: UUID? 추가 (휴지통 안의 폴더는 parentID == trash.id)
  - VoiceNote.deletedWithFolder 제거 — cascade는 부모 폴더 위치로 자연 표현
  - VoiceNoteRepository.observeCascadeDeleted 제거 (불필요)
  - TrashUseCase.observeCascadeNotes 제거 (불필요)
- FolderRepository.moveToTrash 단순화
  - 이전: 폴더 안 모든 노트를 일일이 휴지통 폴더로 이동 + 플래그 set
  - 이후: F.parentID = trash.id, F.deletedAt = .now (안의 노트 안 건드림)
- FolderRepository.restore 단순화
  - 이전: cascade 노트 fetch 후 일괄 update
  - 이후: F.parentID = nil, F.deletedAt = nil (안의 노트 자동 부활)
- 휴지통 폴더 상세 진입 시 빈 화면 버그 해결
  - 이제 일반 observe(folderID:)로 cascade 노트 표시 가능
- Predicate 변경
  - 일반 폴더: kindRaw == .custom AND parentID == nil
  - 휴지통 폴더: parentID != nil AND kindRaw == .custom
  - 최근 노트: deletedAt == nil AND folder.parentID == nil
- CoreDataStorageError: 사용되지 않던 6개 케이스 제거
  - createFailed/fetchFailed/fetchAllFailed/updateFailed/deleteFailed/relationNotFound
  - Repository가 직접 NSManagedObjectContext 다루며 자체 에러 throw하므로 불필요
  - resourceNotFound, initializeFailed 2개만 유지 (init 단계 에러)
- CoreDataLocalDataBase.sharedModel 정적 캐시 제거
  - 단일 인스턴스 사용 환경이라 멀티 인스턴스 방지용 캐시가 over-engineering
  - init에서 직접 mergedModel 로드
- BundleInfo private 클래스 제거, CoreDataLocalDataBase로 통합
  - Bundle(for:) 참조 + modelName 상수 둘 다 본 클래스에 인라인
- name, deletedAt, parentID를 var로 변경하여 직접 mutation 지원
- FolderUseCase.update에서 Folder(...) 재생성 대신 값 복사 후 수정 방식으로 전환
- 위 변경 과정에서 기존 update의 parentID 누락 버그 해소
- VoiceNote(...) 전체 재생성 대신 copyWith 사용으로 전환
- 기존 재생성 로직에서 originalFolderID 필드가 누락되어 update를 거치면
  원본 폴더 정보가 소실되던 버그 해소
- 유일성 보장은 도메인 책임이므로 Repository는 배열을 반환하고
  호출 UseCase가 .first 추출 + notFound 검증을 담당하도록 변경
- DefaultFolderRepository의 fetchLimit=1 제거, createdAt 내림차순 정렬 추가
- MockFolderRepository와 관련 테스트 호출부도 배열 반환에 맞춰 갱신
- FolderRepository, VoiceNoteRepository 프로토콜의 hardDelete(id:)를 delete(id:)로 변경
- "영구 삭제"라는 구분은 UseCase 레벨의 의미이고, Repository 입장에서는
  단일 영속화 API "delete"로 표현되는 것이 자연스러움
- 구현체, Mock, TrashUseCase 내부 호출부 일괄 갱신
- 폴더의 휴지통 이동/복원/영구 삭제를 FolderUseCase가 도메인 로직으로 담당
- moveToTrash: trash 폴더 resolve 후 parentID/deletedAt 세팅, repository.update 호출
- restore: parentID/deletedAt을 nil로 되돌린 뒤 repository.update 호출
- delete: repository.delete(id:) 위임
- 관련 Preview/Fake FolderUseCase 구현체에도 빈 구현 추가
- 노트의 휴지통 이동/복원/영구 삭제를 VoiceNoteUseCase가 도메인 로직으로 담당
- moveToTrash: trash 폴더 resolve 후 originalFolderID 스냅샷 + folderID/deletedAt 세팅, repository.update 호출
- restore: "원본 폴더가 살아있으면 원본, 아니면 기본 폴더" 분기 로직을 UseCase로 이관
  (기존에는 DefaultVoiceNoteRepository.restore 내부에 있던 도메인 규칙)
- delete: repository.delete(id:) 위임
- 관련 Preview/Fake VoiceNoteUseCase 구현체에도 빈 구현 추가
- FolderViewModel.move: trashUseCase.moveToTrash → folderUseCase.moveToTrash
- FolderDetailViewModel.move/restore: trashUseCase → voiceNoteUseCase로 이관
- VoiceNoteViewModel.moveToWasteBasket: trashUseCase → voiceNoteUseCase
- 해당 테스트들은 MockTrashUseCase 검증 대신 실제 UseCase + Mock Repository로
  내려가 repository.update 호출 여부를 검증하도록 조정
… 각 UseCase로 전환

- TrashViewModel에 folderUseCase, voiceNoteUseCase 의존성 추가
- delete/restore/cancelRestore 계열은 WasteBasketItem 분기 후 각 도메인 UseCase의
  delete/restore/moveToTrash 호출하도록 변경
- observe와 allClear는 추후 TrashUseCase 제거 단계에서 함께 정리 예정
- AppDIContainer, Preview, TrashViewModelTests SUT 조립부도 갱신
- 테스트 검증은 MockTrashUseCase 기대값 대신 Mock Repository의 update/delete
  호출 횟수로 내려감. 이를 위해 MockFolderRepository에 expectDelete 추가
Kimyonhae and others added 24 commits May 30, 2026 18:32
- MockDeleteOnDeviceRepository.swift 레거시 모의 객체 삭제 및 중복 심볼 충돌 해결
- OnBoardingViewModelTests에서 불필요한 레거시 DownloadStatus/getMaxIndex/isFinalStep 검증 제거
- OnBoardingViewModelTests의 Gemma 지원 판단 흐름을 checkModelSupport() 기반으로 변경하고, MockOnDeviceRepository 개별 주입 적용
- DownloadOnDeviceViewModelTests의 Flaky 비동기 emit/스트림 로직을 지우고, 유즈케이스 메소드 파라미터 호출 및 값 상태 검사 중심의 동기식 구조로 전면 리팩토링
- MLX/Whisper 온디바이스 Mock 파일들을 Domain/Testing 모듈로 정상 분리 배포하여 프레젠테이션 테스트 모듈 가독성 극대화
- focusHighlighted: systemRed -> warning2
- 전체 Cell에 적용 했습니다.
- 기본 폴더 -> 모든 기록
- 개인 폴더 -> 폴더 목록
(온보딩, 설정, 음성 노트, OnDevice) 전체적으로 리펙토링 합니다
- whisper 모델 경로 확인 뿐만 아니라 내부 파일의 완결성 검사를 진행합니다.
- failure 상황을 2개로 정의합니다 각 요약 실패, 기기 사용 제한 의 WarningConstration을 분리하여 정확히 전달
- 제대로 에러 catch가 되었음에도 불구 하고 errorMessage가 들어오지 않는 이유는 LocalizedError의 기본 구현이 String? 이었기 때문이었습니다.
- 각 failed: 재시도 이름 변경
- 에러 스트림: 네트워크 유실 및 다운로드 에러 모두 errorMessage로 잘 들어오도록 수정하였습니다.
- 휴지통을 통해 음성노트를 진입 시 대부분의 기능을 isTrashMode를 통해 통제합니다.
- 뒤로가기 , 음성 play,pause, 검색 을 제외하고는 전체 기능을 막아둡니다.
- 각 URLError와 NSError를 던짐으로서 errorMessage를 확인 할 수 있도록 설계
- errorMessage를 다운로드 전 초기화합니다.
- autoLayout 제약 워닝을 제거 합니다.
- `MockOnDeviceStatusUseCase` 및 테스트 시그니처 최신화
- `FolderDetail`, `Main`, `Trash` 뷰 모델 테스트 코드 내 파라미터 매치
- `SettingViewModel` 프리뷰 및 테스트 케이스 동기화
다운로도 동기화 버그 및 휴지통 진입 시 음성 노트 기능 차단힙니다.
- 실제 문서는 docs/README.md로 일원화
- 루트 README 삭제 시 GitHub 홈은 docs/README.md로 폴백 표시
- tuist: app icon Nmae 설정
- 전체 루트에 넣으면 tuist generate와 함께 로고가 사라지므로 ReSource 내부에 저장합니다.
Icon Composer로 앱 로고를 넣습니다.
- dismisss 아닌 녹음 화면 진입 시
- 존재하지 않는 파일을 찾고 있었기 때문에 source of Trueth 실패
- 추천 모델 까지만 확인하고 삭제도 동일
- 사용하지 않는 핑드 값을 제거합니다.
- 진행중인 다운로드는 UUID 를 통해 식별하여 cancel
- 마지막으로 downloading상태면 return 적용
- 매크로 자동 코드가 SPM에서 tuist test에 계속 빌드 실패로 나와 내부 수동 코드를 직접 파일에 추가했습니다.
@Kimyonhae Kimyonhae self-assigned this Jun 3, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request establishes the core architecture of the ChaGok iOS application, introducing the App target, Core utilities, Domain use cases, and Data repositories for CoreData, file management, and on-device AI models (Whisper and MLX). The code review is highly constructive, pointing out several critical issues: a Swift 6 actor isolation violation in OnDeviceStatusUseCase, potential noise in silent audio generation due to uninitialized AVAudioPCMBuffer memory, a directory leak in FileManagerStorageService, a negative duration formatting bug in TimeInterval, SwiftUI rendering overhead in FolderCardView, and unnecessary error logging in AppDIContainer for expected flows. Addressing these issues will significantly improve the app's concurrency safety, performance, and stability.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread Domain/Sources/UseCases/OnDevice/OnDeviceStatusUseCase.swift
Comment thread Domain/Sources/UseCases/OnDevice/OnDeviceStatusUseCase.swift
Comment thread App/Sources/Debug/DebugSeeder.swift
Comment thread Core/Sources/Extensions/TimeInterval+Formatting.swift
Comment thread Presentation/Sources/Component/Folder/FolderCardView.swift
Comment thread App/Sources/AppDIContainer.swift
@Tom-BumSuChoi Tom-BumSuChoi self-requested a review June 3, 2026 13:36
@Tom-BumSuChoi Tom-BumSuChoi merged commit 5dc8b64 into main Jun 3, 2026
6 of 7 checks passed
@Kimyonhae

Copy link
Copy Markdown
Collaborator Author

저희 차곡의 1차 MVP가 드디어 끝났네요!!
정말 고생 많으셨습니다 범수님 👍 💯 🥇

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