본문 바로가기
PulseBoard/Profile

Firebase 기반 사용자 프로필 관리 전략 — 서버 단일 소스 + 세션 캐시

by 밤새는 탐험가89 2026. 1. 3.
728x90
SMALL

소셜 로그인(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가 캐시 전략을 책임진다

이 구조는:

  • 과하지 않고
  • 확장 가능하며
  • 실무에서도 가장 많이 쓰이는 패턴이다.

“항상 최신 데이터”와
“불필요한 네트워크 호출 최소화”
이 둘의 균형을 맞춘 설계

728x90
LIST