๋ธ๋ก๊ทธ ๋ด์ ๊ฒ์๋ฌผ์ PC ๋ฒ์ ์ ์ต์ ํ ๋์ด ์์ต๋๋ค.
์ค๋์ ํ๋ฌํฐ์์ ์๋ ๋ก๊ทธ์ธ์ Splash Screen์ ๊ตฌํํด๋ณด๋ ค๊ณ ํฉ๋๋ค. ์๋ ๋ก๊ทธ์ธ์ ์ฑ ๊ฐ๋ฐ์ ์ ํด๋ดค๋ค๋ฉด ํ ๋ฒ์ฏค์ ๊ตฌํํด๋ดค์ ๊ธฐ๋ฅ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. SharedPreference๋ฅผ ํ์ฉํด์ ๊ตฌํํ๋๋ฐ ์ค๋์ ์กฐ๊ธ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์ ๊ทผํ์ต๋๋ค. ๋ฐ๋ก BLoC๋ฅผ ํตํด์ ๊ตฌํํ๋๋ฐ์, BLoC๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ ๋ก๊ทธ์ธ๊ณผ Splash Screen์ ํ๋์ ๋ก์ง์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ํ๋ฒ ์์ํด๋ณด์ฃ .
๋ฐ๋ก BLoC๋ก ๊ตฌํํ์ง ์๊ณ ๊ธฐ์กด์ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๊ณ BLoC๋ก ๋ฆฌํํ ๋งํ๋ ๋ฐฉ์์ผ๋ก ์ ๊ทผํฉ๋๋ค. ๊ธฐ์กด ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ฉด์ ๋ฐ์ํ๋ ๋ฌธ์ ์ ์ด ๋ฌธ์ ๋ฅผ ์ด๋ค ์์ผ๋ก ํด๊ฒฐํ๋์ง๊ฐ ์ค์ํ๋๊น์.
์๋ ๋ก๊ทธ์ธ
์์ ๋ง์๋๋ฆฐ ๊ฒ์ฒ๋ผ SharedPreference๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
shared_preferences | Flutter Package
Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on Android.
pub.dev
ํน์ ๋ณด์์ ์ข ๋ ์ ๊ฒฝ ์ฐ๊ณ ์ถ๋ค๋ฉด SecureSharedPreference๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
secure_shared_preferences | Flutter Package
Simple to use yet powerful package to encypt shared preferences in android and UserDefaults in iOS.
pub.dev
๊ตฌํ์ ๊ฐ๋จํฉ๋๋ค. ์ฌ์ฉ์ ์ธ์ฆ(๋ก๊ทธ์ธ)์ ์ฑ๊ณตํ๋ฉด SharedPreference์ ํน์ ๊ฐ(ํ ํฐ)์ ์ ์ฅํ๊ณ ์ฑ์ ์คํํ์ ๋ ์ฒ์ ๋ก๋๋๋ ํด๋์ค(ํ์ด์ง)์์ didChangeDependencies๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํด์ SharedPreference์ ์ ์ฅ๋ ๊ฐ์ ๋ถ๋ฌ์ต๋๋ค. ์กด์ฌํ์ง ์์ผ๋ฉด ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋ํ๊ณ ์กด์ฌํ๋ ๊ฒฝ์ฐ ๋ฉ์ธ ํ์ด์ง๋ก ์ด๋ํฉ๋๋ค.
๋ง๋ก ๋ณด๋๊น ๋ณต์กํด ๋ณด์ด๋ค์. ์ฝ๋๋ก ๊ฐ๋จํ๊ฒ ๊ตฌํํด๋ณด๋๋ก ํ์ฃ . ์ค์ ๋ก๊ทธ์ธ ํ์ด์ง์ฒ๋ผ TextField๋ ์ฐ์ง ์์ ๊ฒ์ ๋๋ค. FloatingActionButton์ผ๋ก ๋ก๊ทธ์ธ์ ๋์ ํฉ๋๋ค.
Main ํด๋์ค์ ๋๋ค.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isAuth = false;
@override
void didChangeDependencies() async {
// SharedPreference์ ์ ์ฅ๋ ํ ํฐ์ด ์๋์ง๋ฅผ ํ์ธ
final token = await SharedPreferManager().getSharedPreference();
if (token != "Not Auth") {
_isAuth = true;
}
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: _isAuth ? const HomeScreen() : const LoginScreen(),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await SharedPreferManager()
.setSharedPreference("codokodo is authenticate");
},
child: const Icon(Icons.login),
),
);
}
}
ํ๋ฌํฐ๊ฐ ๊ธฐ๋ณธ ์ ๊ณตํด์ฃผ๋ ์ค์ผ๋ ํค ์ฝ๋ ์์์ ์์ ํ์ต๋๋ค. ์์ ๋ง์๋๋ฆฐ ๊ฒ์ฒ๋ผ SharedPreference์ ์ ์ฅ๋ ํ ํฐ์ด ์๋์ง๋ฅผ ํ์ธํฉ๋๋ค. ํ ํฐ์ด ์ ์ฅ๋์ด ์์ผ๋ฉด _isAuth๋ฅผ true๋ก ๋ณ๊ฒฝํฉ๋๋ค. ์ดํ ์์ ฏ์ ๋ ๋๋งํ ๋ _isAuth์ ๊ฐ์ ๋ฐ๋ผ ๋ค๋ฅธ ํ์ด์ง๋ฅผ ๋ณด์ฌ์ค๋๋ค. ๋ํ TextField๋ก ๊ตฌํํ์ง ์๊ณ FloatingActionButton์ ํด๋ฆญํ๋ฉด SharedPreference์ ํน์ ํ ๋ฌธ์์ด(ํ ํฐ์ด๋ผ๊ณ ๊ฐ์ )์ ์ ์ฅํ๋๋ก ๊ตฌํํ์ต๋๋ค.
Home Screen๊ณผ Login Screen๋ ๊ฐ๊ฐ ์ฌ์ฉ์ ์ธ์ฆ ์ดํ์ ๋ณด์ฌ์ง๋ ํ๋ฉด๊ณผ ์ด์ ์ ๋ณด์ฌ์ง๋ ํ๋ฉด์ ๋๋ค. ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
"์ฌ์ฉ์ ์ธ์ฆ์ ์ฑ๊ณตํ์ต๋๋ค.",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
);
}
}
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
"๋ก๊ทธ์ธ์ ์งํํด์ฃผ์ธ์.",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
);
}
}
๋ณ๋๋ก ์ ์ํ SharedPreferManager์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. Singleton์ผ๋ก ์ ์ํ์๊ณ getter, setter์ ๋ํ ๋ก์ง๋ง ๊ฐ์ง๊ณ ์์ต๋๋ค. getter๋ฅผ ๋ณด๋ฉด key๋ก ์ ๋ฌํ auth์ value๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด Not Auth๋ฅผ ๋ฆฌํดํฉ๋๋ค.
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferManager {
static final SharedPreferManager _instance = SharedPreferManager._internal();
final Future<SharedPreferences> _manager = SharedPreferences.getInstance();
SharedPreferManager._internal() {}
factory SharedPreferManager() {
return _instance;
}
Future<void> setSharedPreference(String token) async {
final manager = await _manager;
manager.setString("auth", token);
}
Future<String> getSharedPreference() async {
final manager = await _manager;
return manager.getString("auth") ?? "Not Auth";
}
}
๊ตฌํ์ด ๋๋ฌ์ต๋๋ค. ์ค์ ๋ก ๋น๋๋ฅผ ํด๋ณด๋ฉด ์๋์ ๊ฐ์ด ์ฑ์ ์ฒ์ ์คํํ์ ๋์๋ ๋ก๊ทธ์ธ ํ์ด์ง(LoginScreen)๋ก ์ด๋ํ์ง๋ง FloatingActionButton์ ํด๋ฆญํ๊ณ ์ฑ์ ์ฌ์คํํ๋ฉด ์ฌ์ฉ์ ์ธ์ฆ์ ์ฑ๊ณตํ๋ค๋ ๋ฉ์ธ ํ์ด์ง(HomeScreen)์ผ๋ก ์ด๋ํฉ๋๋ค.
๋ฌธ์ ์
๊ฐ๋จํ๊ฒ ๊ตฌํ์ ๋ง์ณค์ต๋๋ค. ํ์ง๋ง ๋ญ๊ฐ ์ด์ํฉ๋๋ค. ์ฌ์ฉ์ ์ธ์ฆ์ ์ฑ๊ณตํ๋ฉด ์ฑ์ ์ฌ์คํํ์ง ์์๋ ๋ฉ์ธ ํ์ด์ง๋ก ์ด๋ํด์ผ ํฉ๋๋ค. ํ์ง๋ง ์ง๊ธ์ ์ฑ์ ์ฌ์คํํด์ผ์ง๋ง ๋ฉ์ธ ํ์ด์ง๋ก ์ด๋์ด ๊ฐ๋ฅํฉ๋๋ค. ๋ฌผ๋ก ๊ฐ๋จํ๊ฒ ํด๊ฒฐํ ์ ์์ต๋๋ค. didChangeDependencies์ Navigator ์ฝ๋๋ฅผ ์ถ๊ฐํ์ฌ Home Screen์ผ๋ก ์ด๋ํ๋๋ก ๊ตฌํํ๋ฉด ๋ฉ๋๋ค. ๋ก๊ทธ์์ ์ญ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก Home Screen์์ Login Screen์ผ๋ก ์ด๋ํ๋ Navigator ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ฉด ์ ์์ ์ผ๋ก ๋ก๊ทธ์ธ, ๋ก๊ทธ์์ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ต๋๋ค. ํ์ง๋ง ์ด๋ ๊ฒ Navigator๋ก ๊ตฌํํ๊ฒ ๋๋ฉด ํ์ฅ์ฑ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. (์ฃผ๊ด์ ์ธ ์๊ฒฌ์ ๋๋ค.)
๊ฐ๋ น Splash Screen์ ์ถ๊ฐํ๋ค๊ณ ๊ฐ์ ํด๋ณผ๊น์? ์ฑ์ ์คํํ๋ฉด ๋จผ์ Splash Screen๋ถํฐ ๋ณด์ฌ์ง๋๋ฐ
[Splash Screen] SharedPreference ํ์ธ & ํ ํฐ์ด ์ ์ฅ๋์ด ์์ง ์์ -> Navigator๋ก Push -> [Login Screen] ์ฌ์ฉ์ ์ธ์ฆ ์ฑ๊ณต -> Navigator๋ก Push -> [Home Screen]
๋ฒ์จ ๋ ๋ฒ์ Push๊ฐ ๋ฐ์ํฉ๋๋ค. ์ฝ๊ณ ๋น ๋ฅด๊ฒ ๊ตฌํํ ์ ์์ง๋ง ๊ฐ ํ์ด์ง๊ฐ ์ข
์์ ์ผ๋ก ๊ตฌํ๋๋ค๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด๋ฅผ BLoC์ผ๋ก ํด๊ฒฐํ๋ ค๊ณ ํฉ๋๋ค. (์ง๊ธ๊น์ง ์๋ก ์ธ๊ฐ์?) BLoC๋ฅผ ์ ์ฉํ๋ฉด ํ๋์ ๋ก์ง์ผ๋ก ๋ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ด ํ๋์ ํด๋์ค์์ ๋ชจ๋ ๊ด๋ฆฌํ๋๊ฒ ๊ฐ๋ฅํด์ง๋๋ค.
์ฐ์ BLoC์ ๋ํ ์ดํด๊ฐ ํ์ํฉ๋๋ค. ์ ๋ ์ธํด์ ์งํํ๋ฉด์ BLoC์ ๋ํด ๋ฐฐ์ฐ๊ณ ์๋ ๋จ๊ณ๋ผ ์์ง ๋ง์ด ๋ถ์กฑํฉ๋๋ค. ๋์์ธ ํจํด์ด๋ ์ํ ๊ด๋ฆฌ์ ๋ํ ์ง์์ด ์์ผ์๋ฉด ์ดํด๊ฐ ๋น ๋ฅด์ค ๊ฒ๋๋ค. ๊ฐ๋จํ๊ฒ ์ค๋ช ํ์๋ฉด UI์ Data๋ฅผ ๋ณด์ฌ์ฃผ๋ Presention Layer์ Data๋ฅผ ๊ฐ๊ณตํ๋ Business Logic์ ๋ณ๋๋ก ๋ถ๋ฆฌํ๋ ๋์์ธ ํจํด์ผ๋ก MVVM๊ณผ ์๋นํ ์ ์ฌํฉ๋๋ค.
BLoC๋ Event, State, BLoC๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. 3๊ฐ์ ํด๋์ค๋ก ๊ตฌ๋ถ๋๋ค๊ณ ์ดํดํ์๋๊ฒ ์ข๊ฒ ๋ค์. ๊ฐ๊ฐ์ ๋ํด์๋ ๋ค์ ๊ฒ์๊ธ๋ก ์ฐพ์์ค๊ฒ ์ต๋๋ค. ํ๋จ์ ๊ด๋ จ ์๋ฃ๋ฅผ ์ฒจ๋ถํ์ต๋๋ค.
flutter_bloc | Flutter Package
Flutter Widgets that make it easy to implement the BLoC (Business Logic Component) design pattern. Built to be used with the bloc state management package.
pub.dev
Flutter bloc for beginners
What is flutter bloc?
medium.com
Flutter: BlocBuilder vs BlocConsumer vs BlocListener
You can find the Spanish version here ๐
ppantaleon.medium.com
https://booiljung.github.io/technical_articles/flutter/state_management/architecture_your_flutter_project_using_bloc_pattern.html
Top BLOC ํจํด์ ์ฌ์ฉํ Flutter ํ๋ก์ ํธ ์ํคํ ์ณ ์ค๊ณ ์๋ฌธ: Architect your Flutter project using BLOC pattern ์ฌ๋ฌ๋ถ ์๋ ํ์ธ์! ์ ๋ Flutter์ ๊ดํ ์๋ก์ด ๊ธ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด๋ฒ์๋ “Flutter ํ๋ก์
booiljung.github.io
'๐ป ๊ฐ๋ฐ > Flutter' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Flutter] ModalBottomSheet๊ฐ ํค๋ณด๋์ ์ํด ๊ฐ๋ ค์ง๋ ํ์ (0) | 2022.08.09 |
---|---|
[Flutter / Dart] What is Equatable? (0) | 2022.08.06 |
[Flutter / Dart] What is Singleton? (0) | 2022.07.21 |
[Flutter] SingleChildScrollView, ListView, ListView.bulider (1) | 2021.08.18 |
4. Column, Row, Expanded (0) | 2021.08.18 |