Menu
CoddyTech

상태를 어디에 둘지 선택하기

Coddy Flutter 여정의 상태 관리 섹션에 포함된 레슨. 27개 중 21번째.

Settings 화면의 다크 모드 스위치는 움직이지만, 아무것도 어두워지지 않습니다. setState로 값을 유지하지만, 스위치만 그 값을 볼 수 있습니다. 테마는 멀리 떨어진 MyApp에서 설정됩니다. 이 값은 앱 전체에 속합니다.

앱의 모든 값에는 자리가 필요합니다. 누가 그 값을 사용하는지 생각해 보세요.

  • 하나의 위젯(필드의 텍스트, 열린 패널, 탭 인덱스): 해당 위젯에서 setState를 사용합니다.
  • 가까이 있는 몇 개의 위젯(버튼과 그 옆의 레이블): 부모 위젯으로 올리고 아래로 전달합니다.
  • 여러 위젯 또는 여러 화면(사용자, 장바구니, 설정): Provider 또는 Riverpod를 사용하는 공유 모델입니다.

Provider와 Riverpod 중 무엇을 선택할까요? 둘 다 제 역할을 합니다. Provider는 조금 더 간단하고 위젯 트리에 모델을 넣어 context를 통해 찾습니다. Riverpod는 트리 바깥에 프로바이더를 두므로 값에 context가 필요 없고, 프로바이더끼리 서로 감시할 수 있습니다. 앱 하나를 선택해 어디서나 동일하게 사용하세요.

여기에는 StateProvider가 적합합니다. 하나의 bool 값을 MyApp에서 읽어 테마를 선택하고, 스위치에서 값을 변경합니다.

final darkModeProvider = StateProvider((ref) => false);

// MyApp에서, 이제 ConsumerWidget:
themeMode: ref.watch(darkModeProvider) ? ThemeMode.dark : ThemeMode.light,
challenge icon

챌린지

어려움

다크 모드 스위치가 앱 전체에 적용되도록 하세요.

  • 맨 위에 final darkModeProvider = StateProvider((ref) => false);를 추가하세요.
  • MyApp을 ConsumerWidget으로 바꾸고, themeMode가 프로바이더를 따르도록 하세요.
  • SettingsScreen을 ConsumerWidget으로 바꾸세요. 스위치에는 프로바이더의 값이 표시되고, 값이 변경되면 해당 값이 설정됩니다.

직접 해보기

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: ThemeMode.light,
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Notes'),
        actions: [
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const SettingsScreen()),
              );
            },
          ),
        ],
      ),
      body: const Center(child: Text('No notes yet')),
    );
  }
}

class SettingsScreen extends StatefulWidget {
  const SettingsScreen({super.key});

  @override
  State<SettingsScreen> createState() => _SettingsScreenState();
}

class _SettingsScreenState extends State<SettingsScreen> {
  bool dark = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Settings')),
      body: ListView(
        children: [
          SwitchListTile(
            title: const Text('Dark mode'),
            value: dark,
            onChanged: (value) {
              setState(() {
                dark = value;
              });
            },
          ),
        ],
      ),
    );
  }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

상태 관리의 모든 레슨

직접 연습해 보세요: 온라인 Flutter 컴파일러