콘텐츠로 이동

users 스키마

사용자 문서의 전체 스키마. 회원가입, 로그인, 소셜 연동, 본인인증, 내 정보 조회 등 공통 파트의 핵심 컬렉션입니다.

저장 위치

users/{uid}

uid는 Firebase Authentication의 UID를 그대로 사용합니다.

상태 흐름

(미등록) → authentication=False → authentication=True (이니시스 본인인증 완료)
                               withdrawn=True (회원 탈퇴)
  • 회원가입 완료 시 authentication=True로 기본 저장됩니다(이니시스 본인인증 별도).
  • 이니시스 본인인증(inicis_success)이 완료되어야 CI_hash가 채워져 완전한 본인인증 상태가 됩니다.
  • 탈퇴 시 개인정보 필드는 None으로 마스킹되고 withdrawn=True, withdrawn_at이 기록됩니다. 문서는 삭제하지 않고 유지됩니다.

문서 필드

프로필 / 개인정보 (암호화 3종 패턴)

필드 타입 설명
name_enc string AES 암호화된 이름
name_hash string 이름 SHA256 해시 (SALT 기반, 비교/검색용)
phone_enc string AES 암호화된 전화번호 (010-XXXX-XXXX)
phone_hash string 전화번호 SHA256 해시
email_enc string AES 암호화된 이메일
email_hash string 이메일 SHA256 해시
sub_address_enc string AES 암호화된 상세주소

프로필 / 평문 필드

필드 타입 설명
sex string "male" | "female"
birth timestamp 생년월일 (datetime 객체로 저장)
telecom string 통신사 (KT | SKT | LGT | KT(알뜰) | SKT(알뜰) | LGT(알뜰))
postalcode string? 우편번호 (v1 registration에서는 없음, v2 이상)
main_address string 메인 주소 (도로명 주소 등)

인증/상태

필드 타입 설명
authentication bool 기본 본인인증 플래그 (가입 시 True, my_info에서는 CI_hash 존재 여부와 AND)
CI_hash string? 이니시스 본인인증 성공 시 저장되는 CI 값의 SHA256 해시
withdrawn bool? 탈퇴 여부 (탈퇴 시 True)
withdrawn_at timestamp? 탈퇴 시각
created_at timestamp 가입 시각 (SERVER_TIMESTAMP)
updated_at timestamp? 주소 변경 등 업데이트 시각

소셜 로그인 연동

필드 타입 설명
login_providers string[] 연동된 로그인 수단 목록 (email, google, apple, kakao)
google_sub string? Google 계정의 sub (고유 ID)
apple_sub string? Apple 계정의 sub (고유 ID)
kakao_id string? 카카오 계정의 고유 ID (문자열)

login_providers 배열과 각 {provider}_sub/{provider}_id 필드는 함께 관리됩니다. 해제 시 해당 필드는 firestore.DELETE_FIELD로 제거되고 배열에서도 빠집니다.

로그인 시도 (중첩 오브젝트)

필드 타입 설명
login_attempts object? 로그인 실패 횟수/잠금 상태 — 아래 LoginAttempts 참조

본인인증 임시 상태 (이니시스 거래 진행 중)

필드 타입 설명
mTxId string? 이니시스 거래번호 (본인인증/이메일찾기/전화번호변경 진행 중에만)
pending_phone string? 전화번호 변경 진행 중인 새 번호 (change_phone_num에서 임시 저장)

이메일 변경 임시 상태 (5분 만료)

필드 타입 설명
email_change_code string? 6자리 이메일 변경 인증 코드
email_change_target string? 변경 대상 새 이메일 (평문)
email_change_expires timestamp? 인증 코드 만료시각 (KST 기준, 발급 후 5분)

푸시 알림

필드 타입 설명
fcm_token string? Firebase Cloud Messaging 푸시 토큰. update_fcm_token으로 갱신

LoginAttempts

로그인 실패 횟수와 계정 잠금 상태를 관리하는 중첩 오브젝트입니다. login/login_guard.py에서 관리합니다.

{
  "failed_count": 3,
  "locked": false,
  "locked_at": null,
  "last_attempt_at": "timestamp"
}
필드 타입 설명
failed_count int 누적 로그인 실패 횟수 (성공 시 0으로 초기화)
locked bool 계정 잠금 여부. MAX_FAILED_ATTEMPTS=15 도달 시 자동 True
locked_at timestamp? 잠금 시각. 잠금 해제 시 DELETE_FIELD
last_attempt_at timestamp 마지막 시도 시각

잠금 해제는 비밀번호 재설정 메일 발송(send_password_reset_email) 또는 로그인 성공 시 자동으로 이루어집니다.

서브컬렉션

users/{uid}/ 하위 서브컬렉션 목록.

서브컬렉션 설명 별도 스키마 문서
membership 사용자가 속한 회사/현장 목록 membership.md
equipments 개인 소유 장비 목록 equipments.md
notifications 푸시/인앱 알림 리스트 notifications.md
requests 가입/출근 승인 요청 상태 requests.md
login_logs 로그인 성공 기록 login_logs.md
inquiries 사용자 문의사항 inquiries.md
certificates (워크마루) 자격증 정보 — (워크마루 영역)
resumes (워크마루) 이력서 — (워크마루 영역)

탈퇴(withdraw) 시 equipments, certificates, resumes, requests, inquiries 서브컬렉션이 모두 삭제됩니다. membership이 있으면 탈퇴 자체가 거부됩니다.

예시 문서

{
  "name_enc": "AES(홍길동)",
  "name_hash": "sha256(홍길동 + SALT)",
  "phone_enc": "AES(010-1234-5678)",
  "phone_hash": "sha256(010-1234-5678 + SALT)",
  "email_enc": "AES(user@example.com)",
  "email_hash": "sha256(user@example.com + SALT)",
  "sub_address_enc": "AES(101동 202호)",
  "sex": "male",
  "birth": "1998-02-02T00:00:00Z",
  "telecom": "SKT",
  "postalcode": "12345",
  "main_address": "서울시 강남구 테헤란로 1",
  "authentication": true,
  "CI_hash": "sha256(userCi + SALT)",
  "login_providers": ["email", "google"],
  "google_sub": "1234567890",
  "login_attempts": {
    "failed_count": 0,
    "locked": false,
    "last_attempt_at": "2026-04-20T10:00:00Z"
  },
  "fcm_token": "fcm_xxx",
  "created_at": "2026-04-01T00:00:00Z"
}