데이터 스토리지는 모바일 애플리케이션의 핵심 작업 중 하나로, 성능, 보안 및 사용자 경험에 영향을 미칩니다. 이 글에서는 SQLite, Room, Core Data, Realm, Firebase Firestore, SharedPreferences, DataStore, Keystore, Keychain과 직렬화 형식(JSON, Protobuf) 및 라이브러리(Gson, Moshi, kotlinx.serialization)를 다룹니다. 이 가이드는 초보 개발자가 올바른 데이터 스토리지 솔루션을 선택하는 데 도움을 줍니다. 자세한 내용은 공식 Android 데이터 스토리지 가이드를 참조하세요.
주요 포인트
엔터티 간의 관계가 있는 구조화된 데이터를 저장하기 위해 관계형 데이터베이스가 사용됩니다.
SQLite는 모든 모바일 플랫폼에서 작동하는 임베디드 관계형 데이터베이스입니다. 별도의 서버가 필요하지 않으며 데이터는 단일 파일에 저장됩니다. SQLite는 Room(Android)의 기반이며 선택적으로 Core Data(iOS)의 기반입니다. 라이브러리: android.database.sqlite(Android), FMDB/Core Data(iOS), sqflite(Flutter).
Room은 SQLite를 다루기 위한 공식 Android Architecture Components 라이브러리입니다. ORM 계층을 제공합니다: Entity(테이블), DAO(쿼리), Database(진입점). Room은 컴파일 타임에 SQL 쿼리를 검사하고, 코루틴과 Flow를 지원하며, 스키마를 자동으로 마이그레이션합니다.
@Entity data class User( @PrimaryKey val id: Int, val name: String, val email: String ) @Dao interface UserDao { @Query("SELECT * FROM user WHERE id = :id") suspend fun getUser(id: Int): User? }
Core Data는 객체 그래프를 관리하는 Apple의 프레임워크입니다. 순수 데이터베이스가 아니라 SQLite, XML 또는 바이너리 스토리지 위의 지속성 계층입니다. Core Data는 객체(NSManagedObject), 관계, 스키마 버전 관리, 실행 취소/다시 실행 및 NSManagedObjectContext를 통한 멀티스레딩을 관리합니다.
Realm은 SQLite의 대안으로 설계된 고성능 모바일 데이터베이스입니다. Realm은 읽기 및 쓰기에서 SQLite보다 빠르며, 반응형 알림(Live Objects), 실시간 암호화 및 크로스 플랫폼(Android, iOS, Flutter, React Native)을 지원합니다. 단점: APK/IPA 크기 증가 및 더 많은 메모리 사용.
소량의 데이터(설정, 토큰, 캐시)를 저장하기 위해 간단한 키-값 저장소가 사용됩니다.
SharedPreferences는 Android의 레거시 키-값 저장소입니다. 단점: 동기 액세스(읽기 시 UI 차단), 타입 지정 부족, 대용량 파일 로드 시 ANR 위험. 새 프로젝트에는 권장되지 않습니다.
DataStore는 Google의 SharedPreferences를 대체하는 최신 도구입니다. Kotlin Coroutines와 Flow를 통해 비동기로 작동하며, Preferences DataStore(키-값) 및 Proto DataStore(Protobuf를 통한 타입 지정 데이터)를 지원합니다. DataStore는 UI 스레드에 안전하며 트랜잭션을 지원합니다.
UserDefaults는 iOS에서 작은 설정을 위한 표준 저장소입니다. 기본 타입, 문자열, 날짜, Data를 지원합니다. UserDefaults는 동기식이므로 대용량 데이터에는 적합하지 않습니다. register(defaults:)를 통한 값 등록으로 기본값을 설정합니다.
장치 간 동기화가 필요한 애플리케이션의 데이터 저장을 위해 Firebase 클라우드 데이터베이스가 사용됩니다.
Firebase Firestore는 실시간 구독, 자동 확장, 강력한 쿼리 및 내장 오프라인 모드를 갖춘 NoSQL 문서 데이터베이스입니다. 데이터는 컬렉션과 문서(JSON 유사 구조)로 구성됩니다. Firestore는 트랜잭션 및 배치 작업을 지원합니다. 채팅, 피드 및 소셜 앱에 이상적입니다.
Firebase Realtime Database는 데이터를 단일 JSON 트리로 저장하는 이전 Firebase NoSQL 데이터베이스입니다. Firestore보다 단순하지만 쿼리 및 확장에서 유연성이 떨어집니다. 간단한 실시간 애플리케이션(온라인 상태, 간단한 채팅)에 권장됩니다.
| 특징 | Cloud Firestore | Firebase Realtime DB |
|---|---|---|
| 데이터 모델 | 컬렉션 → 문서 | JSON 트리 |
| 쿼리 | 복잡(필터링, 정렬, 제한) | 단순(키 기준) |
| 확장 | 자동 | 수동 샤딩 |
| 오프라인 모드 | 예(영구 캐시) | 예 |
| 가격 | 읽기/쓰기 작업당 | 트래픽 + 스토리지당 |
토큰, 비밀번호 및 암호화 키 저장을 위해서는 특별한 보호 저장소가 필요합니다.
Android Keystore는 암호화 키를 위한 시스템 저장소입니다. 키는 하드웨어 환경(TEE — Trusted Execution Environment)에 저장되어 앱과 OS에서 접근할 수 없습니다. 키 생성, 암호화 및 서명을 지원합니다. Android 9+에는 StrongBox Keymaster(전용 칩)가 포함됩니다.
Keychain Services는 비밀번호, 키 및 인증서를 위한 안전한 iOS 저장소입니다. 데이터는 하드웨어 Secure Enclave를 사용하여 암호화됩니다. Keychain은 접근성 수준을 지원합니다: Always, WhenUnlocked, WhenUnlockedThisDeviceOnly, AfterFirstUnlock.
EncryptedSharedPreferences는 AES256-GCM 및 HKDF를 통한 키-값 암호화가 포함된 SharedPreferences 래퍼입니다. AndroidX Security 라이브러리에 구현되어 있습니다. 토큰 및 민감한 설정 저장에 권장됩니다.
IT Sectr에서는 리프레시 토큰과 생체 인식 기반 키 저장을 위해 Android Keystore + EncryptedSharedPreferences를 사용합니다. iOS에서는 최대 보안을 위해 kSecAttrAccessibleWhenUnlockedThisDeviceOnly 수준의 Keychain을 사용합니다.
파일 저장(이미지, 비디오, 문서)을 위해 모바일 플랫폼은 여러 유형의 스토리지를 제공합니다.
Android는 Internal Storage(/data/data/패키지/ — 비공개 저장소)와 External Storage(SD 카드 또는 에뮬레이션된 파티션)를 구분합니다. Cache Directory는 시스템이 지울 수 있는 임시 저장소입니다. Scoped Storage(Android 10+)는 External Storage에 대한 접근을 제한합니다 — 앱은 자신의 파일 또는 MediaStore/SAF를 통한 파일만 볼 수 있습니다.
iOS는 Documents Directory(iCloud 백업, 영구 데이터), Library/Caches(임시 파일, 백업 안 됨) 및 Tmp Directory(임시, 지울 수 있음)를 제공합니다. 파일 시스템 작업에는 NSFileManager를 사용합니다. iOS 11+는 클라우드 파일을 위한 File Provider를 지원합니다.
직렬화는 객체를 전송 또는 저장을 위한 형식으로 변환합니다. 역직렬화는 반대 과정입니다.
JSON(JavaScript Object Notation)은 가장 인기 있는 형식입니다: 읽기 쉽고, 유연하며, 모든 플랫폼에서 지원됩니다. XML은 더 엄격하며 레거시 시스템에서 사용됩니다. Protobuf(Protocol Buffers)는 Google의 바이너리 형식입니다: JSON보다 3-10배 더 작고, 구문 분석이 빠르며, 엄격한 스키마가 있습니다. 고부하 시스템 및 마이크로서비스에 사용됩니다.
JSONSerialization은 JSON 작업을 위한 내장 API입니다. Codable(Encodable/Decodable)은 JSON, Property List 및 기타 형식으로 자동 직렬화를 위한 현대적인 Swift 프로토콜입니다.
struct User: Codable { let id: Int let name: String let email: String } let user = User(id: 1, name: "Alice", email: "alice@example.com") let encoder = JSONEncoder() let jsonData = try encoder.encode(user)
Flutter 및 React Native에는 자체 효율적인 스토리지 라이브러리가 있습니다.
Hive는 Flutter용 경량 고속 키-값 저장소입니다. 네이티브 코드가 필요 없으며(순수 Dart), TypeAdapter를 통한 타입 지정을 지원하고, 격리 상태에서 작동합니다. 캐시, 설정 및 소량의 데이터에 이상적입니다.
ObjectBox는 Flutter, Android 및 iOS용 고성능 임베디드 데이터베이스입니다. SQLite보다 10배 이상 빠르며, 최소 오버헤드를 위해 플랫 파일 구조를 사용합니다. 관계, 쿼리 및 반응형 구독(ObjectBox Dart)을 지원합니다.
Drift는 Flutter 및 Dart용 반응형 SQLite 라이브러리입니다. 타입 안전 쿼리, 마이그레이션, DAO 함수 및 Stream 지원(반응형 업데이트)을 제공합니다. Drift는 SQLite가 필요한 Flutter 프로젝트의 주요 선택입니다.
자주 묻는 질문
플랫폼에 따라 다릅니다: Room(Android)은 컴파일 타임 쿼리 검사가 있는 SQLite 기반 공식 라이브러리입니다. Core Data(iOS)는 객체 그래프가 있는 Apple의 프레임워크입니다. 크로스 플랫폼 프로젝트에는 Realm 또는 ORM을 통한 SQLite가 적합합니다.
SharedPreferences는 동기 액세스 및 ANR 위험이 있는 오래된 구현입니다. DataStore(Jetpack)는 Kotlin Coroutines 및 Flow 기반의 현대적인 대체품으로, 비동기, 타입 지정 및 오류 보호를 지원합니다.
Android: EncryptedSharedPreferences 또는 Android Keystore. iOS: WhenUnlockedThisDeviceOnly 접근성의 Keychain Services. 중요 데이터의 경우 생체 인증과 함께 Secure Enclave(iOS) 및 하드웨어 Keystore(Android)를 사용하세요.
Cloud Firestore는 실시간 동기화, 오프라인 모드 및 자동 확장을 갖춘 Firebase의 NoSQL 데이터베이스입니다. 채팅, 뉴스 피드 및 장치 간 동기화가 필요한 프로젝트에 적합합니다.
Flutter: Hive(빠른 키-값), Floor(SQLite ORM), Drift(Moor, 반응형 SQLite), ObjectBox(고성능 임베디드 DB). React Native: Realm, WatermelonDB(지연 로딩) 및 AsyncStorage(SharedPreferences 유사).
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.