감정일기 앱을 설계하면서 가장 먼저 고민했던 부분은
“어떤 데이터를 어떻게 구조화할 것인가?”였습니다.
앱의 핵심은 감정을 기록하고,
그날의 상태를 시각적으로 표현하는 것에 있습니다.
따라서 데이터 모델을 먼저 명확히 정의하는 것이 앱의 전체 설계 방향을 결정짓는 핵심이었어요.
🏗️ 1. EmotionDiary 구조 설계
감정일기는 사용자가 직접 입력하는 가장 기본 단위의 데이터입니다.
하루 동안 느낀 감정, 그에 대한 짧은 기록, 그리고 선택적으로 이미지를 포함할 수 있죠.
이를 표현하기 위해 다음과 같은 구조체를 설계했습니다.
import Foundation
struct EmotionDiary: Identifiable, Codable {
var id: UUID = UUID() // 일기 고유 식별자
var createdAt: Date = Date() // 작성 일시
var emotion: EmotionType // 감정 타입 (열거형)
var content: String // 일기 내용 (사용자 입력)
var imageURL: String? // 선택 이미지 (Firebase Storage 업로드 URL)
}
📍 설계 포인트
UUID 기반 식별자
감정일기 작성 시점에서 UUID()로 생성합니다.
Core Data나 Firebase Firestore에 저장 시에는 String으로 변환해 사용합니다.
예: let idString = diary.id.uuidString
createdAt (작성일시)
사용자가 언제 기록했는지 명확히 알 수 있도록 Date 타입으로 저장.
정렬 및 “1년 전 오늘” 기능 구현 시에도 유용합니다.
emotion
EmotionType 열거형으로 감정의 종류를 정의.
감정별 이미지, 색상, 라벨 등을 함께 관리할 수 있어 유지보수에 유리합니다.
imageURL
Firebase Storage에 업로드된 이미지의 다운로드 URL을 문자열로 저장합니다.
사용자가 이미지를 선택하지 않으면 nil로 처리합니다.
🎨 2. EmotionType 열거형 설계
감정은 단순한 문자열보다는 앱 내에서 이미지, 색상, 텍스트를 통합 관리할 수 있는 구조가 좋습니다.
그래서 EmotionType을 아래처럼 구성했습니다 👇
(예를 들어 간략하게 구성했습니다.)
enum EmotionType: String, Codable, CaseIterable {
case happy, sad, angry, tired, calm, anxious, neutral
// 감정별 이미지 (Asset 이름과 동일)
var imageName: String {
switch self {
case .happy: return "emotion_happy"
case .sad: return "emotion_sad"
case .angry: return "emotion_angry"
case .tired: return "emotion_tired"
case .calm: return "emotion_calm"
case .anxious: return "emotion_anxious"
case .neutral: return "emotion_neutral"
}
}
// 감정별 컬러 HEX 코드
var color: String {
switch self {
case .happy: return "#FFD66B"
case .sad: return "#9DB4F5"
case .angry: return "#F57C73"
case .tired: return "#B7AFA3"
case .calm: return "#A2D5C6"
case .anxious: return "#E2B4BD"
case .neutral: return "#DADADA"
}
}
// 감정명 (한글 라벨)
var displayName: String {
switch self {
case .happy: return "행복"
case .sad: return "슬픔"
case .angry: return "화남"
case .tired: return "피곤"
case .calm: return "평온"
case .anxious: return "불안"
case .neutral: return "무감정"
}
}
}
🧩 Asset 연결 방식
Assets.xcassets 내에 아래처럼 이미지 이름을 동일하게 맞추어 저장합니다.
emotion_happy
emotion_sad
emotion_angry
emotion_tired
emotion_calm
emotion_anxious
emotion_neutral
그리고 아래처럼 바로 사용이 가능해요 👇
let image = UIImage(named: diary.emotion.imageName)
이 방식은 로컬 Asset 관리 + MVVM 데이터 바인딩 모두에 적합한 설계입니다.
🤔 Firebase(Cloud Firestore) 구조 예시
/users (collection)
└── {uid} (document)
├── nickname: "jung"
├── email: "user@example.com"
├── profileImageURL: "https://firebasestorage.googleapis.com/..."
├── joinDate: Timestamp
└── /diaries (subcollection)
└── {diaryId} (document)
├── id: "UUID-string" // id.uuidString
├── createdAt: Timestamp
├── emotion: "happy" // EmotionType.rawValue
├── content: "오늘은 기분이 좋아요."
└── imageURLs: ["https://...","https://..."] // optional
Firestore 문서(예시 JSON)
{
"id": "D1E2F3A4-....",
"createdAt": "2025-10-12T08:30:00Z", // Firestore Timestamp
"emotion": "happy",
"content": "오늘은 정말 좋은 하루였다 ☀️",
"imageURLs": [
"https://firebasestorage.googleapis.com/....jpg"
]
}
id는 앱에서 만든 UUID().uuidString로 저장 — 클라이언트에서 생성된 고유 ID 유지.
createdAt은 클라이언트 시각(Date)를 쓰거나(권장: 서버 시각 필요 시 FieldValue.serverTimestamp() 사용).
emotion은 EmotionType.rawValue(String)으로 저장 → 읽을 때 EmotionType(rawValue:)로 복원.
😀 Firebase Storage 구조
권장 폴더 구조 (관리·삭제·보안 편의성 때문에 사용자/일기 기준으로 분리):
/emotion_diary_images
└── /{userId}
└── /{diaryId}
├── img1.jpg
├── img2.jpg
사용자가 이미지 선택 → 이미지 파일을 Storage /emotion_diary_images/{uid}/{diaryId}/...에 업로드
업로드 완료 후 downloadURL을 받아 Firestore imageURLs 배열에 저장
Firestore 문서는 이미지 URL을 포함하여 생성(또는 업로드 완료 후 문서 update)
🔹 Firestore / Storage 보안 규칙 샘플
Firestore rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// 사용자 문서
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
// diaries 서브컬렉션
match /diaries/{diaryId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
}
Storage rules
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /emotion_diary_images/{userId}/{diaryId}/{fileName} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
'감정일기(가칭)' 카테고리의 다른 글
| 🌿 감정일기 앱의 진화: Core Data에서 Firebase, 그리고 AI (0) | 2025.10.12 |
|---|---|
| ☁️ Core Data, iCloud, Firebase — 감정일기 앱에서 어떤 걸 써야 할까? (0) | 2025.10.12 |
| 🔄 Core Data + Firebase(Firestore) 동기화 구조 설계 (0) | 2025.10.12 |
| 😊 감정일기의 제품 철학 (0) | 2025.10.11 |
| Firebase로 시작하는 실전 앱 3선 📱 (0) | 2025.10.11 |