✅ Firebase 의 Storage 에 저장하는 메서드
- images/{userID}/profileImage/profileImage_{userID}.jpg 경로를 사용해서 사용자별로 폴더를 구분
- 나중에 리뷰 이미지 등 다른 카테고리를 추가할 확장성도 고려
- 이 메서드는 Firebase Storage에 사용자의 프로필 이미지를 업로드하는 기능을 수행
import Foundation
import FirebaseAuth
import FirebaseStorage
import FirebaseStorageCombineSwift
import Combine
final class StorageManager {
// MARK: - Variable
static let shared = StorageManager() // ✅ 싱글턴 인스턴스 생성
let storage = Storage.storage() // ✅ Firebase Storage 인스턴스
func uploadProfilePhotp(with userID: String, image: Data, metaData: StorageMetadata) -> AnyPublisher<StorageMetadata, Error> {
return storage
.reference()
.child("images/\(userID)/profileImage/profileImage_\(userID).jpg") // ✅ 저장 경로 설정
.putData(image, metadata: metaData) // ✅ 데이터를 업로드하고 메타데이터 포함
.print() // ✅ 디버깅 용
.eraseToAnyPublisher() // ✅ Combine을 사용해 AnyPublisher로 변환
}
}
🔷 메서드 설명
매개변수
- userID: String → 사용자의 고유한 ID (폴더 구분용)
- image: Data → 업로드할 이미지 데이터 (JPEG, PNG 등)
- metaData: StorageMetadata → 업로드할 파일에 대한 메타데이터
🔷 메타데이터(StorageMetadata)란?
StorageMetadata는 Firebase Storage에 업로드할 파일의 추가 정보(메타데이터)를 설정하는 역할을 해.
📌 사용 목적
- MIME 타입 지정 (ex: image/jpeg, image/png)
- 커스텀 메타데이터 추가 (ex: ["uploader": "user123"])
- 캐싱 설정 (ex: 만료 날짜 지정)
let metaData = StorageMetadata()
metaData.contentType = "image/jpeg" // 파일 타입 설정
metaData.customMetadata = ["uploadedBy": "user123", "type": "profile"]
🔨 개선할 수 있는 점
1️⃣ profileImage 폴더의 중복된 의미
- 현재 profileImage 폴더 안에 profileImage_{userID}.jpg라는 파일명을 사용
- profileImage/profileImage_{userID}.jpg보다는 profile/profile.jpg 같은 형식이 더 직관적일 수도 있음
- 만약 같은 폴더에 여러 개의 프로필 사진을 저장하고 관리할 예정이라면, 현재 방식도 괜찮음.
2️⃣ 프로필 사진을 덮어쓰기할 경우 고려
- 현재 방식은 같은 profileImage_{userID}.jpg를 계속 덮어쓰는 구조
- 혹시 유저가 이전 사진을 유지하고 싶다면, timestamp를 붙여서 버전 관리를 할 수도 있음
images/{userID}/profile/profile_{timestamp}.jpg
🤔 타임스탬프를 사용한 파일명
let timestamp = Int(Date().timeIntervalSince1970) // 현재 시간을 초 단위로 변환
📌 타임스탬프를 적용한 파일명 예제
func uploadProfilePhotp(with userID: String, image: Data, metaData: StorageMetadata) -> AnyPublisher<StorageMetadata, Error> {
let timestamp = Int(Date().timeIntervalSince1970) // 현재 시간을 초 단위로 변환
return storage
.reference()
.child("images/\(userID)/profileImage/profileImage_\(timestamp).jpg") // ✅ 저장 경로 설정
.putData(image, metadata: metaData) // ✅ 데이터를 업로드하고 메타데이터 포함
.print() // ✅ 디버깅 용
.eraseToAnyPublisher() // ✅ Combine을 사용해 AnyPublisher로 변환
}
📌 저장 경로 예시
- 1709110200은 2025년 2월 28일의 특정 시점을 나타내는 타임스탬프 값
images/user123/reviews/review_abc123_1709110200.jpg
3️⃣ 리뷰 이미지 저장 경로 미리 정의
- 리뷰 이미지 저장도 고려하고 할 경우, 미리 폴더 구조를 정의해 두면 좋음.
func uploadReviewImage(userID: String, reviewID: String, image: Data, metaData: StorageMetadata) -> AnyPublisher<StorageMetadata, Error> {
return storage
.reference()
.child("images/\(userID)/reviews/review_\(reviewID).jpg") // 리뷰 이미지 저장 경로
.putData(image, metadata: metaData)
.print()
.eraseToAnyPublisher()
}
✅ 최종 추천 구조
images/
├── {userID}/
│ ├── profile/profile.jpg
│ ├── reviews/{reviewID}.jpg
│ ├── posts/{postID}.jpg (필요하면)
│ ├── etc/ (기타 필요한 이미지)
'UIKIT > Firebase' 카테고리의 다른 글
🔥 Firebase의 Storage 내에 저장된 여러 이미지 삭제하기! (0) | 2025.03.12 |
---|---|
🔥 Firebase Storage에 이미지 업로드, 이미지 주소 URL 가져오기 (0) | 2025.02.28 |
❓ FireStore 내에 회원정보를 불러오는 데 왜 tryMap? (0) | 2025.02.27 |
❓ Firebase 로그인 메서드 내 map의 역할 (0) | 2025.02.27 |
🚀 Future를 사용한 방식 vs map(\.user)을 사용한 방식의 차이점 (Future 는 필수인가?) (0) | 2025.02.26 |