Userdefaults와 @AppStorage의 차이
Intro
App내에서 특정 값들을 앱이 꺼진상태에서도 저장하려면 어떻게 해야될까요?
Userdefaults와 @AppStorage를 사용해서 저장하면 됩니다.
Userdefaults는 기존 UIkit에서 많이 사용했던 방식이고 AppStorage는 SwiftUI에서 iOS 14부터 새로생긴 내용 입니다.
이번에는 두개의 개념에 대해 설명하고 두개의 차이에 대해 알아보겠습니다.
What is UserDefaults
Apple에서는 "App을 실행하는 동안 지속적으로 key-value로 저장하는 사용자의 기본 Database에 대한 Interface"라고 해요.
쉽게 말해 별도의 DB 없이 App에 내가 원하는 값을 어떤 Key와 함께 저장하고, 언제든 그 Key를 통해 값을 불러낼 수 있는 것이죠.
단, 512KB 이하의 간단한 String, Bool, Int, Array 등 단일 Data를 저장하는 데에 적합하기 때문에 대량의 Data를 저장하고 싶다면 따로 Database를 만드는 것을 추천합니다!
간단 카운터 예시
다음과 같이 버튼을 통해 카운터를 증가하는 앱이 있다고 가정해 볼게요
struct ContentView: View {
@State private var count: Int = 0
var body: some View {
VStack {
Text("clicked count: \(count)")
Button("click") {
count += 1
}
}
}
}
위의 코드를 실행하면 클릭 횟수가 화면에 표시되게 됩니다.
근데 위 코드상에서는 앱을 종료핬다가 다시 키면 카운트가 0이 되어버리겠죠?
그것을 UserDefaults를 이용해서 방지할 수 있습니다.
struct ContentView: View {
@State private var count = UserDefaults.standard.integer(forKey: "Clicked")
var body: some View {
VStack {
Text("총 카운트 : \(count)")
Button("카운트 증가") {
count += 1
UserDefaults.standard.set(count, forKey: "Clicked")
}
}
}
}
다음과 같이 코드를 수정하면 앱을 종료했다가 다시 실행을 시켜도 count라는 변수가 UserDefaults의 키 값을 통해 값을 받아오기 때문에 저장될 수 있습니다.
데이터를 저장하려면?
데이터를 저장하기 위해서는 UserDefaults.standerd.set(값, forkey: "키값")
을 넣어주면 됩니다.
UserDefault.standard.set(0, forkey: "number") //Integer 타입 데이터 저장
UserDefault.standard.set(false, forkey: "boolean") //Boolean 타입 데이터 저장
UserDefault.standard.set("Hi", forkey: "string") //String 타입 데이터 저장
데이터를 불러오려면?
데이터를 불러오기 위해서는 UserDefaults.standerd.자료형(key: "키값")
을 넣어주면 됩니다.
let string = UserDefault.standard.string(key: "string") ?? ""
let number = UserDefault.standard.integer(key: "number")
let boolean = UserDefault.standard.bool(key: "boolean")
데이터를 불러올때 처음 값이 저장되어 있지 않으면 Int와 Float, Double 타입은 0을, Bool 타입은 false를 반환한다.
String 타입의 데이터를 불러올때 주의할 점은 처음 값이 저장되어 있지 않으면 nil을 반환하기 때문에 optional binding으로 처리해야 한다.
데이터를 삭제 하려면?
데이터를 저장하기 위해서는 UserDefaults 인스턴스의 removeObject 메서드를 사용 삭제한다.
UserDefault.standard.removeObject(forKey:"numebr")
UserDefaults를 좀더 쉽게 관리할수 없을까?
저는 UserDefaults를 좀더 쉽게 관리하기 위해서 Extension을 통해 관리 합니다.
미리 set, get에 대해 정의를 해놓고 바로 호출해서 사용할 수 있게 만들어 놓습니다.
extension UserDefaults {
private static let isNoti = "notiKey"
func setUserNoti(_ noti: String) {
set(noti, forKey: UserDefaults.isNoti)
}
func getUserNoti() -> String? {
return string(forKey: UserDefaults.isNoti)
}
}
위의 코드는 제가 실재로 사용했던 예시 입니다.
set과 get에 대해서 미리 정의 되어 있죠?
이렇게 자주 사용될 값들을 미리 정의해놓고 사용하면 가독성도 올라가고 좋은것 같습니다.
What is @AppStorage
Userdefaults와 기본적으로 역할은 동일합니다.
사용성에서 크게 차이가 있고, 하위뷰로 데이터를 넘겨줄 수 있습니다.
위의 프로젝트 예시에서 데이터를 가져오는 코드를 살펴보면
@State private var count = UserDefaults.standard.integer(forKey: "cliked")
뭔가 코드가 길어 보이지 않나요?
이것에 대해 해결하기 위해 iOS 14버전 이상 부터 @State 속성을 포함하여 데이터 저장까지 한번에 할 수 있는 property wrapper 가 나왔습니다.
그게 바로 @AppStorage 입니다.
import SwiftUI
struct ContentView: View {
@AppStorage("cliked") private var count = 0
var body: some View {
VStack {
Text("clicked count: \(count)")
Button("click") {
count += 1
}
}
}
}
그래서 어떤상황에 어떤걸 사용할까?
UserDefaults의 주요 사용 예시
- 사용자 설정 저장: 예를 들어 앱의 테마 색상이나 소리 설정.
- 로그인 상태 유지: 사용자가 앱을 다시 시작해도 로그인 상태를 유지해야 할 때.
- 작은 데이터 조각 저장: 사용자의 최근 검색어나 마지막으로 열람한 페이지 번호 등.
@AppStorage의 주요 사용 예시
- 데이터 바인딩: 사용자 인터페이스 요소와 직접적으로 바인딩하여 UI 업데이트가 자동으로 데이터 저장소에 반영될 수 있도록 합니다.
- 간편한 데이터 전달: 상위 뷰에서 하위 뷰로 데이터를 전달할 때 복잡한 상태 관리 없이 사용할 수 있습니다.
그래서 결론적으로는
- UserDefaults: 기존의 UIKit과 호환되는 부분에서 주로 사용되며, 데이터를 프로그래밍적으로 조절해야 할 때 유리합니다. 예를 들어, 백그라운드에서 실행되는 작업이나 복잡한 조건 로직을 수반하는 데이터 저장 및 검색에 적합합니다.
- @AppStorage: SwiftUI에서 사용자 인터페이스의 상태와 직접적으로 연결된 데이터를 저장할 필요가 있을 때 유용합니다. 코드가 간결해지고 SwiftUI의 선언적 프로그래밍 패러다임에 잘 맞습니다.
UIKit에선 @AppStorage를 못쓸까?
"네"
@AppStorage는 SwiftUI의 일부로서 설계되었기 때문에 UIKit에서는 사용할 수 없습니다. @AppStorage는 SwiftUI의 뷰 모델과 데이터 바인딩 시스템에 통합되어 있어, SwiftUI 내에서 데이터의 저장 및 업데이트가 뷰와 직접적으로 연결될 수 있게 돕습니다.