ABOUT ME

작은 디테일에 집착하는 개발자

Today
-
Yesterday
-
Total
-
  • [iOS] 디바이스에 데이터 저장하기 1탄 (Feat. UserDefaults)
    IT Study/iOS 2024. 10. 19. 22:15
    728x90

    출처 : https://developer.apple.com/documentation/foundation/userdefaults

     

    안녕하세요, Three입니다.

    이번 글에서는 iOS 앱에서 데이터를 저장하는 다양한 방식과 함께, UserDefaults를 사용해 사용자의 테마 설정을 저장하고 관리하는 방법에 대해 소개하고자 합니다.

    그 전에 iOS의 데이터 저장 방식을 확인하고, 시작하도록 하겠습니다 😀

     

     

    1. iOS 데이터 저장 방식

    앱 데이터와 사용자 데이터를 기기에 저장하는 방법은 여러 가지가 있습니다. 아래의 표로 간단히 특징들에 대해 알아보시죠.

    방법 사용 장점 단점
    UserDefaults 앱 설정 (테마, 음량, 언어) 빠름, 간단 보안 X, 오직 소규모 데이터
    File System 이미지, 문서, 음악, 비디오 파일 구조 관리 가능 파일 관리 필요
    Core Data 복잡한(관계형) 데이터 모델 관계형 데이터 관리 용이 학습 시간 소요
    Keychain 비번, 토큰, 신용카드, 구매정보 높은 보안성 (암호화) 큰 데이터 저장 X
    CloudKit 기기 간 동기화가 필요한 데이터 여러 기기의 동기화 가능 인터넷 필수, 서버 비용 발생
    SwiftData 복잡한 데이터 모델 SwiftUI 연동, 선언 API 초기 단계, 오직 iOS 17 이상

     

     

    2. UserDefaults

    UserDefaults는 간단한 설정 값들을 저장할 때 적합한 방법입니다.

    실제 제가 만들고 있는 앱(Alone Chat)에서 이를 사용하고 있는데요, 사용자 테마(light/dark)를 저장하고 UI의 여러 요소에 반영하는 예제를 살펴보겠습니다.

     

    2-1. 기본 메서드

    저장
    set(_:forKey:) // 값, 키(String)로 저장
    
    읽기
    object(forKey:), bool(forKey:), string(forKey:)
    
    제거
    removeObject(forKey:) // 키(String)로 제거

     

    2-2. 사용하기

    아래 코드에서 ThemeManager 클래스를 사용하여 사용자 테마 설정을 저장하고, 선택한 테마에 따라 앱의 UI를 동적으로 변경합니다.

    여기서 UserDefaults를 통해 테마 정보를 저장하고 불러오며, `@Published` 속성을 사용해 SwiftUI 뷰에서 테마가 변경될 때마다 자동으로 UI가 업데이트되도록 하고 있습니다.

    import Foundation
    import SwiftUI
    
    class ThemeManager: ObservableObject {
    	// 1. get default object: UserDefaults.standard (인스턴스 생성하기)
        private let defaults = UserDefaults.standard
        
        // 2. define key (and theme) (사용 편의성을 위해 enum 정의하기)
        private enum UserDefaultsKeys: String {
            case selectedTheme = "SelectedTheme"
        }
        
        enum Theme: String {
            case light
            case dark
        }
        
        // 3. set or get SelectedTheme (선택한 테마를 저장 혹은 불러오는 프로퍼티 설정하기)
        @Published var selectedTheme: Theme {
            didSet {
                defaults.set(selectedTheme.rawValue, forKey: UserDefaultsKeys.selectedTheme.rawValue)
            }
        }
        
        init() {
            if let themeString = defaults.string(forKey: UserDefaultsKeys.selectedTheme.rawValue),
               let theme = Theme(rawValue: themeString)
            {
                self.selectedTheme = theme
            } else {
                self.selectedTheme = .light
            }
        }
        
        var backgroundColor: Color {
            switch selectedTheme {
            case .light:
                return Color(hex: "E9E9E9")
            case .dark:
                return Color(hex: "384136")
            }
        }
        
        var titleColor: Color {
            switch selectedTheme {
            case .light:
                return Color(hex: "313131")
            case .dark:
                return Color(hex: "F69937")
            }
        }
        
        var logoImage: String {
            switch selectedTheme {
            case .light:
                return "logo_light"
            case .dark:
                return "logo_dark"
            }
        }
    }

     

    2-3. 테마 관리 예시

    앱의 뷰에서 ThemeManager를 사용하여 배경색이나 텍스트 색상을 동적으로 설정할 수 있습니다.

    ThemeManager의 selectedTheme 속성을 사용해 버튼을 클릭할 때마다 테마가 바뀌고, 이에 따라 앱의 UI 색상과 이미지가 즉시 변경됩니다. 이를 통해 유저는 어두운 테마와 밝은 테마 간에 쉽게 전환할 수 있습니다.

    import SwiftUI
    
    struct MainView: View {
        @EnvironmentObject var themeManager: ThemeManager
        
        var body: some View {
            GeometryReader { geometry in
                NavigationStack {
                    ZStack {
                        themeManager.backgroundColor
                            .edgesIgnoringSafeArea(.all)
                        
                        Image(themeManager.logoImage) // 테마 전환
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: geometry.size.width, height: geometry.size.height)
                            .position(CGPoint(x: 132.0, y: 64.0))
                        
                        VStack(spacing: 10) {
                            HStack(spacing: 10) {
                                Text(viewModel.model.title)
                                    .foregroundColor(themeManager.titleColor) // 테마 전환
                                    .font(.system(size: 40, weight: .ultraLight))
                            }
                        }
                        .padding(.top, 10)
                        
                        VStack {
                            Spacer()
                            
                            HStack(spacing: 10) {
                                // 테마 전환 버튼
                                Button(action: {
                                    themeManager.selectedTheme = themeManager.selectedTheme == .light ? .dark : .light
                                }, label: {
                                    Image(systemName: themeManager.emoji)
                                        .font(.system(size: 20))
                                        .frame(width: 66, height: 66)
                                        .background(Color.black.opacity(0.6))
                                        .foregroundColor(.white)
                                        .clipShape(Circle())
                                })
                                
                                // ...

     

     

    3. 정리

    이렇게 UserDefaults와 ThemeManager를 활용한 예제는 간단한 설정을 앱에 적용할 때 매우 유용합니다.

    다음 포스트에서는 SwiftData 저장 방식을 살펴보도록 하겠습니다.

Designed by Tistory.