프로젝트 맥락
본 글은 SwiftUI로 Apple Developer Academy_Challenge 2에서 개발 중인 ‘Re:ToU(오늘의 너)’ 앱을 기반으로 작성되었습니다.
‘오늘의 너’는 사용자가 하루 동안 자신의 감정을 선택하고, 회고를 작성하는 기능을 제공합니다.
모든 데이터는 기기에 안전하게 저장되어야 했기 때문에, 서버 연동 없이 로컬 데이터 저장 방식을 설계했습니다.
그 중에서도 간단하고 빠르게 구현할 수 있는 UserDefaults를 사용하여 초기 버전을 완성했습니다.
기능 설명
UserDefaults는 iOS에서 소규모 데이터를 쉽게 저장하고 불러올 수 있는 기본 저장소입니다.
Key-Value 형태로 데이터를 저장하며, 앱을 재시작해도 데이터가 유지됩니다.
이번 프로젝트에서는
- 사용자가 선택한 감정(Emoji)
- 작성한 회고 텍스트
- 작성 날짜(Date)
- 를 UserDefaults에 저장하고, 앱 실행 시 불러오는 기능을 구현했습니다.
시도 동기
처음에는 별다른 저장 방식을 사용하지 않고, 메모리 내(@State)에서만 데이터를 관리했습니다.
하지만 앱을 종료하고 다시 실행했을 때 데이터가 모두 사라지는 문제를 겪었습니다.
이 프로젝트는 클라우드 저장이나 서버 연동이 아닌 로컬 저장만을 목표로 했기 때문에,
가장 간단한 방법인 UserDefaults를 사용하는 것으로 방향을 정했습니다.
문제 발견
UserDefaults를 사용하면서 다음과 같은 문제를 겪었습니다.
흔히 발생하는 에러/이슈
- 앱을 새로 실행했을 때 데이터가 Optional(nil)로 나오는 문제타입 변환이 실패해서 값이 nil이 되는 상황이 발생했습니다.
- 저장은 잘 되었지만, 읽어올 때 Key를 잘못 입력하거나
- UserDefaults에 직접 Codable 객체를 저장할 수 없는 문제직접 만든 구조체나 클래스를 저장하려면 Codable을 이용해 Data 타입으로 변환해야 합니다.
- UserDefaults는 기본적으로 String, Int, Bool, Array, Dictionary 같은 기본 타입만 지원합니다.
문제 해결
1. UserDefaults 기본 사용
간단한 값(String, Int 등)을 저장하는 경우는 매우 쉽습니다.
// 저장
UserDefaults.standard.set("😊", forKey: "selectedEmotion")
// 불러오기
let emotion = UserDefaults.standard.string(forKey: "selectedEmotion") ?? ""
하지만, 감정과 텍스트, 날짜를 하나의 데이터로 묶어 저장하려면 커스텀 구조체를 사용해야 했습니다.
2. Codable을 이용한 구조체 저장
회고 데이터를 관리하기 위해 다음과 같은 구조체를 만들었습니다.
struct Reflection: Codable, Identifiable {
var id: UUID
var date: Date
var emotion: String
var text: String
}
구조체를 저장할 때는 JSONEncoder를 이용해 Data로 변환한 후 저장합니다.
func saveReflection(_ reflection: Reflection) {
if let encoded = try? JSONEncoder().encode(reflection) {
UserDefaults.standard.set(encoded, forKey: "currentReflection")
}
}
func loadReflection() -> Reflection? {
if let savedData = UserDefaults.standard.data(forKey: "currentReflection"),
let decoded = try? JSONDecoder().decode(Reflection.self, from: savedData) {
return decoded
}
return nil
}
이렇게 하면 복잡한 객체도 안전하게 저장하고 복구할 수 있습니다.
비슷한 접근 방법 비교
방법설명장점단점
UserDefaults | Key-Value 기반 간단 저장 | 구현 빠름, 가벼움 | 데이터 양 많아지면 비효율적 |
FileManager 저장 | 파일로 직접 저장 | 자유로운 구조 가능 | 직접 파일 관리 필요 |
CoreData 사용 | 관계형 데이터베이스 저장 | 대규모 데이터 처리 가능 | 초기 설정과 학습 비용 큼 |
느낀 점
UserDefaults는 단순한 Key-Value 저장소지만,
Codable을 잘 활용하면 꽤 복잡한 데이터도 쉽게 저장하고 복구할 수 있다는 걸 알게 됐다.
이번 프로젝트에서는 데이터 양이 많지 않고 구조도 단순했기 때문에 UserDefaults가 최적의 선택이었지만,
만약 사용자 데이터가 많아지거나 복잡한 관계형 데이터가 필요해진다면 CoreData나 다른 저장 방식을 검토해야겠다는 생각이 들었다.
또한, UserDefaults에 저장할 때는 항상 Key를 상수로 관리하고, 타입 변환 실패에 대비하는 코드를 작성하는 습관이 중요하다고 느꼈다.
정리
- 간단한 데이터 저장에는 UserDefaults가 매우 유용하다.
- Codable을 이용하면 구조체(커스텀 객체)도 저장할 수 있다.
- Key 관리와 타입 변환에 주의해야 한다.
- 대규모 데이터가 필요할 경우 CoreData를 고려해야 한다.
'iOS & SwiftUI' 카테고리의 다른 글
SwiftUI에서 감정 이모지 선택 UI 구현하기: HStack 기반 구조 (2) | 2025.05.05 |
---|---|
SwiftUI에서 입력 완료 여부에 따라 버튼 활성화 상태 제어하기 (1) | 2025.05.03 |
SwiftUI에서 NavigationLink를 안전하게 사용하는 방법: 상태 기반 전환 설계하기 (0) | 2025.05.01 |
SwiftUI 앱에서 ViewModel 분리와 State 관리 방법 (1) | 2025.04.29 |