본문 바로가기

iOS (스파르타)

UserDefaults ,,,

 

UserDefaults

앱을 시작할 때마다 키-값 쌍을 영구적으로 저장하는 사용자 기본 데이터베이스에 대한 인터페이스

 

 

UserDefaults는 iOS 앱에서 사용자 기본 설정 및 앱 설정을 저장하고 관리하기 위한 클래스이다.

주로 사용자의 환경 설정, 앱 상태, 간단한 데이터 등을 저장하는데 사용된다.

 

UserDefaults는 런타임(runtime) 환경에서 동작하는 객체이다. 앱이 실행되는 동안 기본 저장소에 접근하여 데이터를 가져오고 기록하는 역할을 한다. 이 말은 앱이 실행되지 않는 환경, 예를 들어 플레이그라운드에서는 UserDefaults 객체를 사용하여 데이터를 읽거나 쓸 수 없다는 의미가 된다. 

 

UserDefaults는 싱글톤 패턴으로 설계되어 있기 때문에 앱 전체에서 딱 하나의 인스턴스만 생성되며, 이 인스턴스를 앱 전체가 공유해서 사용하는 형태를 띤다. 다시 말해 필요한 곳마다 UserDefaults 객체를 호출하면 각각의 호출에 응답하기 위한 인스턴스가 생성되는 것이 아니라 하나의 UserDefaults 객체가 모든 요청을 응답 받아 처리한다는 것이다. 따라서 UserDefauls 를 사용할 때에는 직접 초기화 메소드를 호출하여 인스턴스를 생성하지 않고 이미 생성되어 있는 인스턴스를 참조해서 사용해야 한다. 이를 위해 UserDefaults 객체의 메소드나 프로퍼티 대부분은 클래스 메소드나 클래스 프로퍼티로 정의되어 있다. 

 

UserDefaults 객체의 API

UserDefaults 객체는 데이터를 읽고 쓰기 위해 여러 개의 메소드를 제공한다. 각 메소드들은 데이터의 타입별로 다양하게 정의되어 있으므로 우리는 데이터에 가장 적합한 메소드를 선택하여 사용할 수 있다. 타입을 모르거나 타입에 맞는 메소드가 정의되어 있지 않을 경우를 대비하여 범용 타입의 메소드도 제고오디고 있다.

 

데이터 타입 저장된 값을 읽어올 때 값을 저장할 때
문자열 타입 string(forKey:) set(_:forKey:)또는
setValue(_:forKey:)
정수 타입 integer(forKey:)
실수 타임 float(forKey:) 또는 
double(forKey:)
참/거짓 논리 타임 bool(forKey:)
Base64 타입 data(forKey:)
배열 타입 array(forKey:)
딕셔너리 타입 dictionary(forKey:)
범용 타입 object(forKey:) 또는
value(forKey)
Nil 타입 - setNilValueForKey(_:)

 

표를보면 저장된 값을 읽어오는 메소드는 데이터 타입별로 정확하게 나누어져있지만, 값을 저장하는 메소드는 모두 범용 메소드를 사용하는 것처럼 착각하기 쉽다. 하지만 사실 setValue(_:forKey:)만 범용 메서드이며, set(_:forKey:)는 전용 메서드이다. 메서드 오버로딩(Overloading)되어 있기 때문에 동일한 이름을 가지고 있을 뿐이다.

 

set(_:forKey:)라는 메서드 시그니처를 가지는 모든 메서드의 목록을 보면 이 점을 쉽게 이해할 수 있다.

set(_ value:Any?, forKey:String)
set(_ value:Bool, forKey:String)
set(_ value:Double, forKey:String)
set(_ value:Float, forKey:String)
set(_ value:Int, forKey:String)

 

나열된 메서드들은 서로 다르지만 모두 set(_:forKey:)라는 동일한 이름을 사용한다.

또한 매개변수도 value, forKey로 동일하다. 이는 메서드 오버로딩 문법을 적용했기 때문이다.

메서드 오버로딩을 사용하면 하나의 이름과 형식으로 여러 타입의 매개변수에 대응하는 합수를 작성할 수 있어서 사용자의 혼란을 줄이고 일관성을 유지할 수 있다. 우리는 그저 타입에 맞는 메서드를 찾을 필요 없이 set(_:forKey:) 메서드만 사용하면 된다.

메소드 오버로딩이란?
메소드 오버로딩(Method Overloading)이란, 메소드의 이름과 매개변수명은 모두 동일하되 매개변수의 타입만 다른 메소드를 여러 개 정의할 수 있는 문법을 이야기한다. 객체 지향 프로그래밍의 주요 특성 중 하나이다.

 

UserDefaults 객체로부터 반환되는 값은 옵셔널 타입이다.

 

 

 

UserDefaults 사용 방법

 

1. 데이터 저장하기

let defaults = UserDefaults.standard

// 문자열 저장
defaults.set("John Doe", forKey: "username")

// 숫자 저장
defaults.set(25, forKey: "age")

 

2. 데이터 불러오기

저장된 데이터를 불러올 때는 저장할 때 사용한 키를 사용한다.

let defaults = UserDefaults.standard

// 문자열 불러오기
if let username = defaults.string(forKey: "username") {
    print("Username: \(username)")
}

// 숫자 불러오기
let age = defaults.integer(forKey: "age")
print("Age: \(age)")

 

3. 데이터 삭제하기

UserDefaults에서 특정 키에 대한 데이터를 삭제할 수 있다.

let defaults = UserDefaults.standard

// 데이터 삭제
defaults.removeObject(forKey: "username")

 

4. 복잡한 데이터 타입 저장하기

배열과 딕셔너리와 같은 복잡한 데이터 타입도 저장할 수 있다.

 

배열저장

let defaults = UserDefaults.standard

let array = ["Apple", "Banana", "Cherry"]
defaults.set(array, forKey: "fruits")

 

딕셔너리저장

let defaults = UserDefaults.standard

let dict = ["name": "John", "age": 25] as [String : Any]
defaults.set(dict, forKey: "user")

 

데이터 저장

let defaults = UserDefaults.standard

if let data = "Hello, World!".data(using: .utf8) {
    defaults.set(data, forKey: "greeting")
}

 

날짜 저장

let defaults = UserDefaults.standard

let date = Date()
defaults.set(date, forKey: "currentDate")

 

불러올 때도 같은 방식으로 불러올 수 있다.

let defaults = UserDefaults.standard

// 배열 불러오기
if let fruits = defaults.array(forKey: "fruits") as? [String] {
    print("Fruits: \(fruits)")
}

// 딕셔너리 불러오기
if let userProfile = defaults.dictionary(forKey: "userProfile") {
    print("User Profile: \(userProfile)")
}

 

5. 커스텀 데이터 타입 저장하기

커스텀 데이터 타입을 저장하려면 해당 데이터를 'Data' 타입으로 인코딩한 수 저장해야 한다.

struct CustomObject: Codable {
    var name: String
    var age: Int
}

// 객체 저장
let object = CustomObject(name: "John Doe", age: 30)
if let encoded = try? JSONEncoder().encode(object) {
    defaults.set(encoded, forKey: "customObject")
}

// 객체 불러오기
if let savedData = defaults.data(forKey: "customObject"),
   let savedObject = try? JSONDecoder().decode(CustomObject.self, from: savedData) {
    print("Name: \(savedObject.name), Age: \(savedObject.age)")
}

 

UserDefaults 사용 시 주의사항

UserDefaults는 큰 데이터를 저장하는데 적합하지 않다. 이미지, 동영상 등의 큰 파일은 다른 방법을 사용하여 저장하는 것이 좋다.

synchronize 메서드는 데이터를 즉시 저장하지만, 이는 필요하지 않은 경우 사용하지 않는 것이 좋다.

키를 잘못 사용하거나 중복된 키를 사용하면 데이터가 덮여쓰여질 수 있다. 고유한 키를 사요하는 것이 좋다.

 

 

 

 

참고-꼼꼼한재은씨의 Swift: 실전편, 챗GTP 질답

 

책이 좀 오래된 내용이라 달라진 부분이 많을 수도 있지만...

UserDefaults 완벽이해 하고싶다.. 뿌시고싶다...