소셜 로그인(Google, Apple, Kakao, Naver)을 Firebase Authentication으로 구현한 뒤,
다음으로 반드시 고민하게 되는 주제가 있다.
“사용자 프로필 정보는 어디에, 어떻게 저장하고 관리해야 할까?”
이 글에서는 Firebase Firestore를 단일 소스(Single Source of Truth)로 두고,
앱에서는 세션 단위 메모리 캐시만 사용하는 프로필 관리 전략을 정리한다.
1. 문제 상황 정리
현재 앱의 구조는 다음과 같다.
- 인증(Auth): Firebase Authentication
- 사용자 프로필: Firestore에 저장
- 프로필 이미지: Firebase Storage
사용자는 로그인 후 프로필을 작성하고,
그 정보는 Firestore에 저장된다.
여기서 자연스럽게 떠오르는 질문은 이것이다.
“앱을 재실행하면,
매번 Firestore에서 프로필을 다시 받아와야 할까?”
또는 반대로,
“한 번 받아온 프로필을 앱에 저장해두고 계속 써도 되지 않을까?”
2. 선택지 검토
프로필 관리 전략은 크게 세 가지로 나뉜다.
① 매번 Firestore에서 다시 로드
화면 진입 → Firestore fetch → UI 표시
장점
- 항상 최신 데이터
- 구조 단순
단점
- 불필요한 네트워크 호출
- Home 진입 시마다 지연
- 여러 ViewModel에서 중복 요청 발생
② 로컬 영구 저장 (UserDefaults / CoreData)
Firestore 저장 + 로컬 DB 저장
단점이 더 큼
- 데이터 동기화 복잡
- 변경 시 일관성 깨지기 쉬움
- UserDefaults는 프로필 저장 용도로 부적합
- CoreData는 과설계
👉 이 단계에서는 적절하지 않다.
③ Firestore + 앱 메모리 캐시 (선택한 방식)
Firestore = 진짜 데이터
앱 메모리 = 현재 세션 캐시
이 방식이 가장 균형 잡힌 선택이다.
3. 설계 원칙: Single Source of Truth
이 구조의 핵심 원칙은 하나다.
“프로필 데이터의 진실은 Firestore에만 있다.”
- Firestore: 항상 신뢰 가능한 데이터
- 앱 메모리: 빠른 접근을 위한 임시 복사본
앱이 종료되면:
- 메모리 캐시는 자연스럽게 사라진다
- 다음 실행 시 Firestore에서 다시 로드
👉 상태 꼬임이 발생하지 않는다.
4. 세션 캐시가 필요한 이유
사용자 프로필은 다음과 같은 특성이 있다.
- 로그인 이후 거의 모든 화면에서 사용
- 자주 변경되지 않음
- 변경 시 즉시 UI에 반영되어야 함
이런 데이터를 매번 네트워크로 가져오는 건 비효율적이다.
그래서 “현재 로그인 세션 동안만 유지되는 캐시”가 가장 적합하다.
5. UserRepository 내부 캐시 전략
이 구조에서는 별도의 UserStore를 만들지 않는다.
대신 UserRepository 내부에 얕은 캐시를 둔다.
UserRepository
├─ Firestore 접근
├─ PulseUser 변환
└─ 메모리 캐시 관리
Repository의 책임
- Firestore에서 사용자 프로필 로드
- 최초 로드 후 메모리에 캐시
- 프로필 수정 시
- Firestore 업데이트
- 캐시 갱신
- 로그아웃 / 탈퇴 시 캐시 제거
ViewModel은:
- “캐시인지 네트워크인지”를 전혀 알 필요가 없다.
6. 실제 동작 흐름
앱 첫 실행
Auth 확인
↓
UserRepository.fetchCurrentUser()
↓
캐시 없음 → Firestore fetch
↓
캐시에 저장
↓
UI 표시
앱 사용 중
다른 화면 진입
↓
fetchCurrentUser()
↓
캐시 반환
↓
즉시 UI 표시
프로필 수정
사용자 입력
↓
Firestore update
↓
캐시 갱신
↓
UI 즉시 반영
앱 종료
메모리 캐시 자동 소멸
7. 왜 영구 로컬 저장을 하지 않았나?
- UserDefaults
- 문자열/플래그용
- 사용자 프로필 저장에 부적합
- CoreData
- 오프라인 우선 앱이 아님
- 동기화 비용 대비 이득 적음
- Keychain
- 인증 정보용
- 프로필 데이터 저장 목적 아님
👉 지금 단계에서는 메모리 캐시가 최적
8. Combine / Rx 기반 Store는 언제 필요할까?
실무에서는 다음 상황에서 UserStore 같은 상태 저장 계층이 필요해진다.
- 사용자 정보가 실시간으로 자주 변경됨
- 여러 화면에서 동시에 반응해야 함
- 상태 스트림이 핵심인 앱(SNS, 협업툴)
PulseBoard의 현재 구조에서는:
- 프로필 변경 빈도 낮음
- 실시간 동기화 요구 없음
👉 그래서 Repository + 캐시만으로 충분하다.
9. 회원 탈퇴 / 로그아웃과의 연결
이 구조는 탈퇴 로직과도 자연스럽게 연결된다.
- Firestore 사용자 문서 삭제
- Storage 이미지 삭제
- Firebase Auth 계정 삭제
- Repository 캐시 초기화
👉 데이터 잔존 문제 없음.
10. 정리
이번 설계의 핵심은 단순하다.
- Firestore는 단일 진실 소스
- 앱은 세션 동안만 데이터를 들고 있다
- Repository가 캐시 전략을 책임진다
이 구조는:
- 과하지 않고
- 확장 가능하며
- 실무에서도 가장 많이 쓰이는 패턴이다.
“항상 최신 데이터”와
“불필요한 네트워크 호출 최소화”
이 둘의 균형을 맞춘 설계
'PulseBoard > Profile' 카테고리의 다른 글
| FirebaseProfileImageUploader 설계 — 프로필 이미지를 왜 분리해야 하는가 (0) | 2026.01.05 |
|---|---|
| FirestoreUserRepository 설계 — 사용자 프로필을 안전하게 관리하는 방법 (0) | 2026.01.04 |
| UserRepository 설계 — Firebase 프로필 데이터를 어떻게 다룰 것인가 (1) | 2026.01.03 |
| PulseUser 모델 설계 — Firebase Auth 이후 사용자 프로필을 어떻게 정의할 것인가 (0) | 2026.01.03 |
| 소셜 로그인 이후 프로필 작성 온보딩 설계 (Firebase Auth + Firestore + Storage) (1) | 2026.01.01 |