saveUserToFirestore 메서드
private func saveUserToFirestore(userUID: String, username: String, email: String, profileImageURL: String, completion: @escaping (Bool, Error?) -> Void) {
let db = Firestore.firestore()
let userData: [String: Any] = [
"username": username,
"email": email,
"profileImageURL": profileImageURL,
"createdAt": Timestamp()
]
db.collection("users").document(userUID).setData(userData) { error in
if let error = error {
print("Firestore 저장 실패: \(error.localizedDescription)")
completion(false, error)
} else {
print("Firestore 저장 성공")
completion(true, nil)
}
}
}
이 메서드는 Firestore의 users 컬렉션에 사용자 정보를 저장하는 역할을 합니다. 이 정보는 사용자 UID를 문서 ID로 사용하여 Firestore 데이터베이스에 저장됩니다.
Firestore 인스턴스 가져오기:
let db = Firestore.firestore()
- Firestore 데이터베이스에 접근하기 위해 Firestore.firestore()를 호출하여 데이터베이스 인스턴스를 가져옵니다.
저장할 데이터 생성:
let userData: [String: Any] = [
"username": username,
"email": email,
"profileImageURL": profileImageURL,
"createdAt": Timestamp()
]
- 저장할 데이터를 딕셔너리 형태로 정의합니다:
- "username": 사용자 이름.
- "email": 사용자 이메일.
- "profileImageURL": 프로필 이미지의 Firebase Storage 다운로드 URL.
- "createdAt": Firestore의 Timestamp를 사용하여 데이터 생성 시간을 저장.
Firestore에 데이터 저장:
db.collection("users").document(userUID).setData(userData) { error in
- Firestore의 users 컬렉션에 접근합니다.
- userUID를 문서 ID로 설정하여 데이터를 저장합니다.
- setData를 호출하여 userData를 Firestore에 저장합니다.
에러 처리 및 성공 여부 반환:
- 저장 과정에서 발생한 에러를 처리합니다:
if let error = error {
print("Firestore 저장 실패: \(error.localizedDescription)")
completion(false, error)
} else {
print("Firestore 저장 성공")
completion(true, nil)
}
- 저장 실패:
- 에러 메시지를 출력하고, completion(false, error)를 호출하여 실패를 알립니다.
- 저장 성공:
- 성공 메시지를 출력하고, completion(true, nil)를 호출하여 성공을 알립니다.
사용 예제
saveUserToFirestore(userUID: "12345", username: "JohnDoe", email: "johndoe@example.com", profileImageURL: "https://firebase.storage.url") { success, error in
if success {
print("사용자 정보가 Firestore에 저장되었습니다.")
} else if let error = error {
print("Firestore 저장 실패: \(error.localizedDescription)")
}
}
Firestore 구조 예시
저장 후 Firestore 데이터는 다음과 같은 구조를 갖습니다:
users (컬렉션)
└── 12345 (문서, userUID)
├── username: "JohnDoe"
├── email: "johndoe@example.com"
├── profileImageURL: "https://firebase.storage.url"
└── createdAt: {타임스탬프}
uploadProfileAndSaveUserToFirestore 메서드
private func uploadProfileAndSaveUserToFirestore(userUID: String, request: RegisterUserRequest, completion: @escaping (Bool, Error?) -> Void) {
// 1. 이미지를 Firebase Storage에 업로드
guard let imageData = request.userImage.jpegData(compressionQuality: 0.5) else {
completion(false, NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "이미지 데이터를 변환할 수 없습니다."]))
return
}
let storageRef =
Storage.storage().reference().child("profile_images/\(userUID).jpg")
storageRef.putData(imageData, metadata: nil) { metadata, error in
if let error = error {
print("Firebase Storage 업로드 실패: \(error.localizedDescription)")
completion(false, error)
return
}
// 2. 다운로드 URL 가져오기
storageRef.downloadURL { url, error in
if let error = error {
print("Firebase Storage 다운로드 URL 가져오기 실패: \(error.localizedDescription)")
completion(false, error)
return
}
guard let profileImageURL = url?.absoluteString else {
completion(false, NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "이미지 URL을 가져올 수 없습니다."]))
return
}
// 3. Firestore에 사용자 정보 저장
self.saveUserToFirestore(userUID: userUID, username: request.username, email: request.email, profileImageURL: profileImageURL) { success, error in
completion(success, error)
}
}
}
}
이 메서드는 Firebase Storage에 이미지를 업로드한 뒤, 업로드된 이미지의 다운로드 URL을 가져와 Firestore에 사용자 데이터를 저장하는 역할을 합니다.
이미지 데이터 변환 및 업로드 준비
guard let imageData = request.userImage.jpegData(compressionQuality: 0.5) else {
completion(false, NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "이미지 데이터를 변환할 수 없습니다."]))
return
}
- request.userImage:
- UIImage 타입으로 전달된 프로필 이미지를 가져옵니다.
- jpegData(compressionQuality:):
- 이미지를 JPEG 포맷으로 변환하며, 압축 품질은 0.5로 설정(50% 품질). 이는 이미지 크기를 줄여 업로드 속도를 높이고 저장 공간을 절약하기 위함입니다.
Firebase Storage 경로 설정
let storageRef = Storage.storage().reference().child("profile_images/\(userUID).jpg")
- Storage.storage():
- Firebase Storage 인스턴스를 가져옵니다.
- .reference():
- Storage의 루트 경로를 참조합니다.
- .child("profile_images/\(userUID).jpg"):
- 업로드 경로를 설정:
- profile_images: Firebase Storage 내 폴더 이름.
- \(userUID).jpg: 파일 이름으로 사용자 고유 UID를 사용하여 충돌 방지.
- 전체 경로는 다음과 같습니다:
- 업로드 경로를 설정:
profile_images/{userUID}.jpg
Firebase Storage에 이미지 업로드
storageRef.putData(imageData, metadata: nil) { metadata, error in
if let error = error {
print("Firebase Storage 업로드 실패: \(error.localizedDescription)")
completion(false, error)
return
}
}
- putData(_:metadata:):
- Firebase Storage에 이미지 데이터를 업로드.
- metadata는 생략되어 기본 메타데이터로 저장됩니다.
- 에러 처리:
- 업로드가 실패하면 에러 메시지를 출력하고 completion(false, error)를 호출하여 실패를 알립니다.
다운로드 URL 가져오기
storageRef.downloadURL { url, error in
if let error = error {
print("Firebase Storage 다운로드 URL 가져오기 실패: \(error.localizedDescription)")
completion(false, error)
return
}
guard let profileImageURL = url?.absoluteString else {
completion(false, NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "이미지 URL을 가져올 수 없습니다."]))
return
}
}
- downloadURL:
- 업로드된 이미지의 공개 URL을 반환.
- URL 검증:
- URL이 없거나 변환에 실패하면 에러를 반환.
Firestore에 사용자 정보 저장
self.saveUserToFirestore(userUID: userUID, username: request.username, email: request.email, profileImageURL: profileImageURL) { success, error in
completion(success, error)
}
- saveUserToFirestore:
- userUID를 문서 ID로 사용하여 Firestore의 users 컬렉션에 사용자 데이터를 저장.
- 전달되는 데이터:
- username: 사용자 이름.
- email: 사용자 이메일.
- profileImageURL: Firebase Storage에서 가져온 이미지 다운로드 URL.
로직 순서
- 이미지 데이터를 준비:
- UIImage를 JPEG 포맷으로 변환.
- 압축 품질을 설정하여 이미지 크기를 줄임.
- Firebase Storage 경로 설정:
- profile_images/{userUID}.jpg 경로에 이미지를 저장할 준비.
- Firebase Storage에 이미지 업로드:
- putData를 사용하여 이미지 데이터를 업로드.
- 다운로드 URL 가져오기:
- 업로드가 완료된 후, 다운로드 가능한 URL을 가져옴.
- Firestore에 사용자 정보 저장:
- 다운로드 URL과 함께 사용자 정보를 users 컬렉션에 저장.
Firestore와 연동 후 저장 결과
Firestore 구조:
users (컬렉션)
└── {userUID} (문서)
├── username: "JohnDoe"
├── email: "johndoe@example.com"
├── profileImageURL: "https://firebasestorage.googleapis.com/v0/b/{bucket}/o/profile_images%2F{userUID}.jpg"
└── createdAt: {Timestamp}
Firebase Storage 구조:
profile_images (폴더)
└── {userUID}.jpg (파일)
registerUser 메서드
func registerUser(request: RegisterUserRequest, completion: @escaping (Bool, Error?) -> Void) {
// 1. Firebase Auth로 사용자 생성
Auth.auth().createUser(withEmail: request.email, password: request.password) { authResult, error in
if let error = error {
print("Firebase Auth 사용자 생성 실패: \(error.localizedDescription)")
completion(false, error)
return
}
guard let userUID = authResult?.user.uid else {
let uidError = NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "사용자 UID를 가져올 수 없습니다."])
completion(false, uidError)
return
}
// 2. 이미지 업로드와 Firestore 데이터 저장 통합
self.uploadProfileAndSaveUserToFirestore(userUID: userUID, request: request) { success, error in
if success {
print("회원가입 성공")
completion(true, nil)
} else {
print("회원가입 실패: \(error?.localizedDescription ?? "알 수 없는 에러")")
completion(false, error)
}
}
}
}
이 메서드는 Firebase Auth를 통해 사용자 계정을 생성하고, 계정 생성 후 프로필 이미지 업로드 및 Firestore에 사용자 데이터 저장을 처리하는 역할을 합니다.
Firebase Auth로 사용자 생성
Auth.auth().createUser(withEmail: request.email, password: request.password) { authResult, error in
if let error = error {
print("Firebase Auth 사용자 생성 실패: \(error.localizedDescription)")
completion(false, error)
return
}
- Auth.auth().createUser:
- Firebase Authentication을 통해 사용자를 생성합니다.
- 이메일(request.email)과 비밀번호(request.password)를 사용하여 계정을 만듭니다.
- 계정 생성 성공 시 authResult를 반환, 실패 시 error를 반환.
- 에러 처리:
- 사용자 생성 실패 시 에러 메시지를 출력하고, completion(false, error)를 호출하여 호출자에게 실패를 알립니다.
UID 확인
guard let userUID = authResult?.user.uid else {
let uidError = NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "사용자 UID를 가져올 수 없습니다."])
completion(false, uidError)
return
}
- authResult?.user.uid:
- Firebase가 생성한 고유 사용자 ID(UID)를 가져옵니다.
- UID는 Firebase Storage 및 Firestore에 데이터를 저장할 때 경로로 사용됩니다.
- 에러 처리:
- UID를 가져올 수 없는 경우, 커스텀 에러(uidError)를 생성하여 반환합니다.
이미지 업로드 및 Firestore 데이터 저장
self.uploadProfileAndSaveUserToFirestore(userUID: userUID, request: request) { success, error in
if success {
print("회원가입 성공")
completion(true, nil)
} else {
print("회원가입 실패: \(error?.localizedDescription ?? "알 수 없는 에러")")
completion(false, error)
}
}
- uploadProfileAndSaveUserToFirestore:
- 프로필 이미지를 Firebase Storage에 업로드하고, Firestore에 사용자 정보를 저장합니다.
- UID, 이메일, 비밀번호, 프로필 이미지를 전달합니다.
- 에러 처리:
- 이미지 업로드 및 데이터 저장 성공 여부를 success 플래그와 error 객체로 판단.
- 성공 시 completion(true, nil) 호출, 실패 시 에러 메시지를 출력하고 completion(false, error) 호출.
로직 순서
- Firebase Auth로 사용자 계정 생성:
- 이메일과 비밀번호로 계정을 생성.
- 계정 생성 성공 시 사용자 UID를 가져옴.
- UID 확인:
- UID는 Firebase Storage 및 Firestore에서 사용자 데이터를 고유하게 식별하기 위한 값입니다.
- UID를 가져오지 못하면 실패로 처리.
- 이미지 업로드 및 데이터 저장:
- UID를 기반으로 Firebase Storage에 이미지를 업로드.
- 다운로드 URL을 Firestore에 저장하여 프로필 이미지와 사용자 정보를 통합.
이 메서드의 역할
이 메서드는 회원가입 과정을 하나의 흐름으로 묶어 처리합니다:
- Firebase Auth를 통해 사용자 계정을 생성.
- 계정 생성 후 UID 기반으로 프로필 이미지를 저장.
- Firestore에 사용자의 정보를 저장하며 회원가입을 완료.
이를 통해 회원가입 과정에서 필요한 인증, 데이터 저장, 이미지 업로드를 통합적으로 관리합니다.
🔥 user.uid 란? 🔥
user.uid는 Firebase Authentication에서 사용자 계정을 생성하거나 로그인했을 때 Firebase가 자동으로 생성해 제공하는 고유 사용자 ID입니다.
이 UID는 AuthDataResult 객체의 user 속성을 통해 접근할 수 있으며, Firebase의 다양한 서비스에서 사용자를 식별하는 핵심 역할을 합니다.
예시: AuthDataResult의 구조
Auth.auth().createUser 호출 시 반환되는 데이터 구조는 다음과 같습니다:
Auth.auth().createUser(withEmail: "test@example.com", password: "password123") { authResult, error in
if let authResult = authResult {
let user = authResult.user
print("사용자 UID: \(user.uid)") // Firebase가 생성한 고유 사용자 ID
print("사용자 이메일: \(user.email ?? "없음")")
} else if let error = error {
print("사용자 생성 실패: \(error.localizedDescription)")
}
}
- authResult.user.uid:
- Firebase가 생성한 고유한 사용자 ID.
- authResult.user.email:
- 사용자 계정에 등록된 이메일.
UID의 용도
- 사용자 고유 식별:
- Firebase Authentication에서 사용자 계정을 고유하게 식별하기 위해 UID를 사용합니다.
- UID는 중복되지 않으며, Firebase의 각 서비스(예: Firestore, Storage)에서 사용자별 데이터를 관리하는 데 사용됩니다.
- Firebase Storage 경로:
- UID를 기준으로 프로필 이미지 경로나 사용자 파일을 저장합니다.
let storageRef = Storage.storage().reference().child("profile_images/\(userUID).jpg")
- 3. Firestore 문서 ID:
- UID를 Firestore의 문서 ID로 사용하여 사용자 데이터를 저장합니다.
db.collection("users").document(userUID).setData(userData)
'Project > FirebaseTest' 카테고리의 다른 글
FireBase - 회원 정보 불러오기_프로필 이미지 사용방식 (다운로드 vs URL 기반 로딩) (0) | 2024.12.05 |
---|---|
FireBase - 회원 정보 불러오기 (0) | 2024.12.05 |
FireBase - 사용자 정보 불러오기 및 사용자 삭제 (0) | 2024.12.04 |
FireBase - 유효성 검사 + 사용자 등록 (0) | 2024.12.03 |
FireBase - 로그인과 로그아웃 처리하는 메서드 정의 (1) | 2024.12.03 |