SharedPreferences
는 Flutter 및 다른 많은 모바일 플랫폼에서 사용되는 경량의 데이터 저장 솔루션입니다. 이를 사용하여 간단한 데이터(예: 사용자 설정, 애플리케이션의 상태 등)를 키-값 쌍으로 로컬 디바이스에 저장할 수 있습니다. SharedPreferences
는 주로 간단한 정보를 영구적으로 저장하고, 앱이 재시작되더라도 그 정보를 유지할 필요가 있을 때 유용합니다.
SharedPreferences
의 기본 사용 방법:의존성 추가: pubspec.yaml
파일에 shared_preferences
패키지를 추가합니다.
dependencies:
flutter:
sdk: flutter
shared_preferences: ^latest_version
인스턴스 가져오기: SharedPreferences
의 인스턴스를 비동기적으로 가져옵니다.
SharedPreferences prefs = await SharedPreferences.getInstance();
데이터 읽기 및 쓰기:
setInt
, setString
, setBool
, setDouble
, setStringList
등의 메소드를 사용하여 데이터를 저장합니다.await prefs.setString('myKey', 'myValue');
getInt
, getString
, getBool
, getDouble
, getStringList
등을 사용하여 데이터를 읽어옵니다.String? value = prefs.getString('myKey');
데이터 제거: remove
메소드를 사용하여 특정 키의 데이터를 제거합니다.
await prefs.remove('myKey');
SharedPreferences
사용 시 고려할 점:SharedPreferences
는 간단한 데이터 저장에 적합합니다. 복잡한 데이터 구조나 큰 데이터 세트를 저장하기에는 적합하지 않습니다.await
키워드를 사용하여 비동기 처리를 해야 합니다.SharedPreferences
는 사용자의 선호 언어 설정, 테마 모드, 로그인 상태 유지와 같은 간단한 사용자 설정을 유지하는 데 매우 유용합니다.
import 'package:shared_preferences/shared_preferences.dart';
class PlaybackConfigRepository {
static const String _autoplay = "autoplay";
static const String _muted = "muted";
final SharedPreferences _preferences;
PlaybackConfigRepository(this._preferences);
Future<void> setMuted(bool value) async {
_preferences.setBool(_muted, value);
}
Future<void> setAutoplay(bool value) async {
_preferences.setBool(_autoplay, value);
}
bool isMuted() {
return _preferences.getBool(_muted) ?? false;
}
bool isAutoplay() {
return _preferences.getBool(_autoplay) ?? false;
}
}
SharedPreferences
는 Flutter에서 제공하는 플러그인으로, 키-값 쌍으로 데이터를 저장하고 읽어오는 간단한 영구 저장 메커니즘이며, 이는 Android의 SharedPreferences
및 iOS의 NSUserDefaults
에 대한 래퍼입니다.
주어진 PlaybackConfigRepository
클래스에서, setMuted
와 setAutoplay
메서드가 async
키워드를 사용하여 비동기로 선언되어 있습니다. 그 이유는 다음과 같습니다:
I/O Operations: SharedPreferences
에서 값을 저장하거나 불러오는 것은 I/O 작업입니다. 이러한 작업들은 시간이 걸릴 수 있으므로, 메인 스레드에서 동기적으로 실행되면 사용자 인터페이스가 멈출 수 있습니다.
Non-blocking: 비동기적으로 처리하면, 작업이 완료될 때까지 기다리지 않고 다른 작업을 계속 수행할 수 있습니다. Future
를 반환함으로써, 작업의 완료를 기다리거나 다른 작업과 조합하여 실행할 수 있습니다.
SharedPreferences API Design: SharedPreferences
의 setBool
메서드 자체가 비동기적으로 설계되어 있습니다. 따라서 해당 메서드를 호출할 때 await
키워드를 사용해야 합니다. 그러기 위해서는 함수를 async
으로 선언해야 합니다.
그러나, isMuted
와 isAutoplay
메서드에서는 비동기적인 코드가 없는데, 이는 SharedPreferences
에서 값을 바로 읽어오기 때문입니다. 이러한 값을 읽어오는 메서드는 동기적으로 동작하므로 Future
를 반환하지 않습니다.
요약하면, setMuted
와 setAutoplay
메서드는 SharedPreferences
에 값을 저장하는 I/O 작업을 수행하기 때문에, 이를 비동기적으로 처리하여 UI 스레드가 차단되지 않도록 합니다.
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:toonflix2/models/webtoon_detail_model.dart';
import 'package:toonflix2/models/webtoon_episode_model.dart';
import 'package:toonflix2/services/api_service.dart';
import 'package:toonflix2/widgets/episode_widget.dart';
class DetailScreen extends StatefulWidget {
final String title, thumb, id;
const DetailScreen({
super.key,
required this.title,
required this.thumb,
required this.id,
});
State<DetailScreen> createState() => _DetailScreenState();
}
class _DetailScreenState extends State<DetailScreen> {
late Future<WebtoonDetailModel> webtoon;
late Future<List<WebtoonEpisodeModel>> episodes;
late SharedPreferences prefs;
bool isLiked = false;
Future initPrefs() async {
prefs = await SharedPreferences.getInstance();
final likedToons = prefs.getStringList('likedToons');
if (likedToons != null) {
if (likedToons.contains(widget.id) == true) {
setState(() {
isLiked = true;
});
}
} else {
await prefs.setStringList('likedToons', []);
}
}
void initState() {
super.initState();
webtoon = ApiService.getToonById(widget.id);
episodes = ApiService.getLatestEpisodesById(widget.id);
initPrefs();
}
onHeartTap() async {
final likedToons = prefs.getStringList('likedToons');
if (likedToons != null) {
if (isLiked) {
likedToons.remove(widget.id);
} else {
likedToons.add(widget.id);
}
await prefs.setStringList('likedToons', likedToons);
setState(() {
isLiked = !isLiked;
});
}
}
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 2,
backgroundColor: Colors.white,
foregroundColor: Colors.green,
actions: [
IconButton(
onPressed: onHeartTap,
icon: Icon(
isLiked ? Icons.favorite : Icons.favorite_outline,
),
),
],
title: Text(
widget.title,
style: const TextStyle(
fontSize: 24,
),
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(50),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Hero(
tag: widget.id,
child: Container(
width: 250,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
blurRadius: 15,
offset: const Offset(10, 10),
color: Colors.black.withOpacity(0.3),
)
],
),
child: Image.network(widget.thumb),
),
),
],
),
const SizedBox(
height: 25,
),
FutureBuilder(
future: webtoon,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
snapshot.data!.about,
style: const TextStyle(fontSize: 16),
),
const SizedBox(
height: 15,
),
Text(
'${snapshot.data!.genre} / ${snapshot.data!.age}',
style: const TextStyle(fontSize: 16),
),
],
);
}
return const Text("...");
},
),
const SizedBox(
height: 25,
),
FutureBuilder(
future: episodes,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: [
for (var episode in snapshot.data!)
Episode(
episode: episode,
webtoonId: widget.id,
)
],
);
}
return Container();
},
),
],
),
),
),
);
}
}
이 코드에서 SharedPreferences
는 사용자의 '좋아요' 상태를 로컬 저장소에 저장하고 불러오는 데 사용됩니다. DetailScreen
은 웹툰의 상세 정보와 에피소드를 표시하는 StatefulWidget
이며, 사용자가 특정 웹툰을 '좋아요' 했는지의 여부를 SharedPreferences
를 통해 관리합니다.
SharedPreferences
의 활용 방법인스턴스 초기화:
initPrefs
함수에서 SharedPreferences.getInstance()
를 호출하여 SharedPreferences
의 인스턴스를 초기화합니다. 이는 비동기적으로 수행되므로 await
키워드가 필요합니다.데이터 저장 및 불러오기:
likedToons
는 사용자가 '좋아요'한 웹툰의 ID 목록을 저장하는 키입니다.likedToons
목록에 추가되고, '좋아요'를 취소하면 해당 ID가 목록에서 제거됩니다.prefs.getStringList('likedToons')
를 호출하여 현재 '좋아요'한 웹툰의 목록을 불러옵니다.prefs.setStringList('likedToons', likedToons)
를 사용하여 수정된 목록을 다시 저장합니다.상태 업데이트:
onHeartTap
함수에서는 사용자가 하트 아이콘을 탭할 때마다 '좋아요' 상태를 토글하고, 이 변경 사항을 SharedPreferences
에 저장합니다.setState
를 호출하여 UI를 최신 상태로 업데이트합니다.SharedPreferences
의 역할SharedPreferences
는 사용자가 특정 웹툰을 '좋아요' 했는지 여부를 저장하고 추적하는 데 사용됩니다. 이를 통해 앱을 종료하고 다시 시작해도 사용자의 '좋아요' 상태가 유지됩니다.SharedPreferences
를 사용함으로써 사용자 경험을 개선하고, 앱의 사용성을 높일 수 있습니다.이 예제는 SharedPreferences
를 사용하여 간단한 사용자 설정이나 상태를 유지하고 관리하는 방법을 잘 보여줍니다. Flutter 앱 개발에서 SharedPreferences
는 이와 같이 간단한 데이터를 영구적으로 저장하고 불러오는 데 유용하게 사용됩니다.