Flutter

블로그 프로젝트 - 로그아웃 기능 연결 및 UI 수정

whs5758 2025. 9. 4. 19:25
CustomNavigation
import 'package:flutter/material.dart';
import 'package:flutter_blog/_core/constants/size.dart';
import 'package:flutter_blog/providers/global/session_notifier.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

// 창고에 접근할 수 있는 위젯으로 확장해야 한다.
class CustomNavigation extends ConsumerWidget {
  final scaffoldKey;
  const CustomNavigation(this.scaffoldKey, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    SessionNotifier sessionNotifier = ref.read(sessionProvider.notifier);
    return Container(
      width: getDrawerWidth(context),
      height: double.infinity,
      color: Colors.white,
      child: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              TextButton(
                onPressed: () {
                  scaffoldKey.currentState!.openEndDrawer();
                  Navigator.pushNamed(context, "/post/write");
                },
                child: const Text(
                  "글쓰기",
                  style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.black54,
                  ),
                ),
              ),
              const Divider(),
              TextButton(
                onPressed: () async {
                  // 로그아웃 기능 호출
                  await sessionNotifier.logout();
                  scaffoldKey.currentState!.openEndDrawer();
                  Navigator.popAndPushNamed(context, "/login");
                },
                child: const Text(
                  "로그아웃",
                  style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.black54,
                  ),
                ),
              ),
              const Divider(),
            ],
          ),
        ),
      ),
    );
  }
}

 

ScaffoldKey란 뭘까?

ScaffoldKey는 Flutter의 핵심 개념 중 하나

1. Key의 기본 개념

Widget과 Element의 관계

// Flutter에서 모든 화면 구성 요소는 Widget
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(); // 이것도 Widget
  }
}

Flutter는 Widget을 화면에 그릴 때 Widget Tree와 Element Tree를 만듭니다

  • Widget: 설계도 (불변)
  • Element: 실제 화면에 그려지는 객체 (가변)

Key가 필요한 이유

// 예시: 두 개의 동일한 Container가 있을 때
Column(
  children: [
    Container(color: Colors.red),    // 첫 번째
    Container(color: Colors.blue),   // 두 번째
  ],
)

Flutter가 화면을 다시 그릴 때 "어떤 Container가 어떤 것인지" 구분하기 위해 Key를 사용합니다.

 

2. GlobalKey의 특별한 역할

일반 Key vs GlobalKey

// 일반 Key - 단순 구분용
Container(key: ValueKey("container1"))

// GlobalKey - 위젯에 직접 접근 가능
final GlobalKey<ContainerState> myKey = GlobalKey();
Container(key: myKey)

GlobalKey의 특별함: 위젯의 메서드를 직접 호출할 수 있습니다!

 

3. Scaffold와 ScaffoldKey

Scaffold란?

// Scaffold = 앱 화면의 기본 뼈대
Scaffold(
  appBar: AppBar(),        // 상단 바
  body: Container(),       // 메인 콘텐츠
  drawer: MyDrawer(),      // 왼쪽 사이드 메뉴
  endDrawer: MyDrawer(),   // 오른쪽 사이드 메뉴
  bottomSheet: MySheet(),  // 하단 시트
)

ScaffoldKey = Scaffold 조종기

class MyPage extends StatelessWidget {
  // Scaffold를 조종하기 위한 리모컨
  final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: scaffoldKey,  // 리모컨과 TV 연결
      endDrawer: CustomNavigation(scaffoldKey),  // 리모컨을 드로어에도 전달
      body: Container(),
    );
  }
}