# CodexBar 스토리지 스캔의 중복 갱신 제거

- URL: https://soohan.dev/projects/open-source/codexbar-storage-footprint-performance
- Category: projects/open-source
- Published: 2026-06-11
- Tags: open-source, swift, performance, observation
- Author: Soohan Park

> 스캔 결과가 같아도 Observable 상태가 다시 발행되던 원인을 찾아 메뉴 캐시의 불필요한 무효화를 줄인 기록.

---

CodexBar는 공급자별 로컬 스토리지 사용량을 메뉴를 열 때와 약 5분 간격으로 스캔합니다.
스캔 결과가 이전과 같아도 `providerStorageFootprints`가 매번 다시 할당되고 있었습니다.

이 값은 Observable 상태라서 재할당될 때마다 메뉴 관찰자가 깨어납니다.
결과적으로 화면에 달라진 것이 없어도 메뉴 캐시를 비우고 다시 만들 준비를 했습니다.

```text
storage scan
→ providerStorageFootprints 재할당
→ menuObservationToken 갱신
→ 메뉴 무효화와 캐시 제거
```

## 원인

`ProviderStorageFootprint`는 `Equatable`이었지만 `updatedAt: Date`를 포함했습니다.
스캔할 때마다 현재 시각이 들어가므로 실제 용량과 경로가 모두 같아도
새 결과는 이전 결과와 항상 다르다고 판단됐습니다.

[steipete/CodexBar PR #1416](https://github.com/steipete/CodexBar/pull/1416)에서
시각이 아닌 실제 스캔 내용의 변경 여부를 따로 비교하도록 수정했습니다.

## 변경

- `ProviderStorageFootprint.hasSameContents(as:)` 추가
- `updatedAt`을 제외한 실제 내용을 비교
- 내용이 같으면 기존 footprint를 재사용
- 최종 딕셔너리가 이전 값과 다를 때만 Observable 상태에 할당
- 마지막 스캔 시각과 요청 키 같은 갱신 bookkeeping은 그대로 유지

변경이 없는 스캔은 관찰 이벤트를 발생시키지 않지만,
스캔이 정상적으로 수행됐다는 내부 기록은 계속 전진하도록 경계를 나눴습니다.

## 회귀 테스트

실제 Codex 저장소 구조를 닮은 임시 디렉터리를 만들고 같은 조건으로 두 번 스캔했습니다.
`withObservationTracking`으로 `providerStorageFootprints`를 관찰한 뒤,
두 번째 스캔에서는 값이 다시 발행되지 않는지 확인했습니다.
수정 전에는 실패하고 수정 후에는 통과하는 테스트였습니다.

메인테이너의 최종 검증에서는 다음을 확인했습니다.

- `ProviderStorageFootprintTests` 16개 통과
- 전체 Swift 테스트 412개 스위트, 3,634개 테스트 통과
- SwiftFormat·SwiftLint와 `make check` 통과
- 패키징한 앱에서 스토리지 행 렌더링 확인
- 메뉴를 세 차례 닫고 다시 여는 동안 충돌·멈춤·slow-operation 경고 0건

## 범위와 결과

이 변경은 메뉴 프리징 전체를 해결한 패치가 아닙니다.
메인 브랜치에 이미 들어간 렌더링·캐시 개선과 별개로,
변경 없는 스캔이 캐시 무효화를 유발하던 한 경로를 제거한 작업입니다.

PR은 2026년 6월 11일에 열어 같은 날 병합됐습니다.
최종 변경은 4개 파일, 4개 커밋, `+98 / -2`였으며
메인테이너 리베이스 후에도 기여자 공동 저작과 변경 로그 크레딧이 유지됐습니다.
