본문 바로가기
PulseBoard/Auth

소셜 로그인 이후 프로필 작성 온보딩 설계 (Firebase Auth + Firestore + Storage)

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

소셜 로그인(Google / Apple / Kakao / Naver)을 모두 구현한 뒤,
다음으로 고민해야 할 것은 **“로그인 이후 사용자를 어떻게 서비스에 진입시킬 것인가”**이다.

 

단순히 로그인에 성공했다고 해서 바로 서비스를 사용하게 만드는 것이 항상 최선은 아니다.
대부분의 서비스는 로그인 이후 최소한의 사용자 프로필 정보를 요구한다.

 

이 글에서는 Firebase Auth 기반 소셜 로그인 이후, 최초 1회만 프로필 작성 화면을 노출하는 온보딩 로직을 어떻게 설계했는지 정리한다.

 

1. 문제 정의

현재 앱의 상태는 다음과 같다.

  • Firebase Auth로 소셜 로그인 완료 가능
  • uid 발급 및 인증 상태 관리 가능
  • 아직 서비스 레벨의 “회원 프로필”은 존재하지 않음

이 상태에서 발생하는 질문은 하나다.

“로그인이 끝난 사용자를 바로 Home으로 보내도 되는가?”

 

대부분의 경우 답은 NO다.

  • 사용자 이름이 없다
  • 프로필 이미지가 없다
  • 서비스 내부에서 사용자를 표현할 수 있는 정보가 없다

그래서 로그인(Auth)프로필(Profile) 을 분리한 설계가 필요하다.

 

2. 설계 목표

이번 온보딩 로직의 목표는 다음과 같다.

  1. 소셜 로그인 성공 = 인증 완료
  2. 인증 완료 후, 최초 1회만 프로필 작성 요구
  3. 이미 프로필이 존재하면 다시 묻지 않음
  4. 프로필 정보는 Auth가 아닌 서비스 레벨 데이터로 관리

즉,

Auth는 “누구인지 증명”만 책임지고,
Profile은 “서비스에서 누구로 보일지”를 책임진다

 

3. 전체 흐름 요약

전체 앱 진입 흐름은 아래와 같다.

앱 실행
↓
Firebase Auth 상태 확인
↓
로그인 안 됨 → Login 화면
↓
로그인 성공
↓
HomeViewController 진입
↓
프로필 존재 여부 확인
  ├─ 없음 → 프로필 작성 화면 표시
  └─ 있음 → Home 정상 사용

 

중요한 점은 **“프로필 작성 화면이 별도의 진입 화면이 아니라, Home 위에서 조건부로 노출된다”**는 것이다.

 

이 방식은 UX 측면에서도 자연스럽고, 구조적으로도 단순하다.

 

4. AuthViewModel의 책임

이 구조에서 가장 중요한 설계 포인트는 다음 질문이다.

“프로필 작성 여부를 누가 판단해야 하는가?”

 

정답은 ViewController가 아니라 AuthViewModel이다.

이유

  • Auth 상태는 전역 상태다
  • 프로필 유무는 “앱 진입 조건”이다
  • Home뿐 아니라, 다른 화면에서도 동일한 판단이 필요해질 수 있다

따라서 AuthViewModel은 다음과 같은 상태를 관리한다.

enum AppEntryState {
    case unauthenticated
    case needsProfileSetup
    case authenticated
}

 

AuthViewModel은:

  1. Firebase Auth 상태 변경을 감지하고
  2. currentUser가 존재하면
  3. Firestore에 프로필 문서가 존재하는지 확인하여
  4. 앱의 진입 상태를 결정한다

5. 프로필 존재 여부 판단 기준

프로필 작성 여부를 판단하는 기준은 명확하다.

❌ 사용하지 않는 기준 

  • Firebase Auth의 displayName
  • Firebase Auth의 photoURL

이 값들은 인증 계층의 정보이며,
서비스 로직의 프로필로 사용하기에는 부적절하다.

 

✅ 사용 기준 (권장)

Firestore
/users/{uid} 문서 존재 여부
  • 문서 없음 → 프로필 미작성
  • 문서 있음 → 프로필 작성 완료

이 방식은:

  • 단순하고
  • 명확하며
  • 확장성이 좋다

6. Firebase 데이터 구조 설계

6-1. Firebase Storage (프로필 이미지)

이미지 원본은 Storage에 저장한다.

profile-images/
 └─ {uid}/
     └─ profile.jpg (또는 uuid 기반 파일명)

 

Storage의 역할은 오직 하나다.

  • 바이너리 이미지 저장

6-2. Firestore (프로필 메타데이터)

서비스 로직에서 사용하는 프로필 정보는 Firestore에 저장한다.

users/
 └─ {uid}
      - username: String
      - profileImagePath: String
      - createdAt: Timestamp

 

Firestore의 역할은:

  • 빠른 조회
  • 서비스 로직에서 필요한 데이터 제공
  • Auth와 분리된 회원 정보 관리

👉 Storage에는 절대 닉네임 같은 데이터를 저장하지 않는다.

 

7. 프로필 작성 UX 설계

프로필 작성 화면은 다음 조건을 만족한다.

  • HomeViewController 위에 표시
  • Sheet 또는 FullScreenCover 형태
  • 입력 항목은 최소화
    • 프로필 이미지 (선택)
    • Username (필수)

중요한 UX 원칙은 이거다.

“첫 진입에서 사용자를 귀찮게 하지 말 것”

 

이미지는 선택 사항으로 두고,
닉네임만으로도 프로필 생성을 허용하는 것이 초기 온보딩에 유리하다.

 

8. 회원 탈퇴와의 연결성

이 설계는 이후 회원 탈퇴 로직과 자연스럽게 연결된다.

  • Auth 삭제 → 인증 계정 제거
  • Firestore users/{uid} 삭제 → 프로필 정보 제거
  • Storage 이미지 삭제 → 리소스 정리

즉, 프로필을 별도 데이터로 관리하기 때문에
탈퇴 로직 역시 명확한 단계로 확장 가능하다.

 

9. 이 구조의 장점 정리

  • Auth / Profile 책임 분리
  • 로그인과 서비스 준비 상태를 명확히 구분
  • 최초 1회 온보딩 UX 구현 가능
  • 이후 기능 확장(설정 변경, 프로필 수정)에 유리
  • 실무에서 사용하는 패턴과 동일

10. 마무리

소셜 로그인 구현은 끝이 아니라 시작이다.
진짜 중요한 것은 **“로그인한 사용자를 서비스에 어떻게 안착시키느냐”**다.

이번 설계의 핵심은 단순하다.

로그인은 인증이고,
프로필은 서비스다.

 

이 둘을 분리해서 설계하면,
온보딩·탈퇴·권한·확장 모든 부분이 자연스럽게 연결된다.

728x90
LIST