Flutter

블로그 프로젝트 - main.dart 코드 리뷰

whs5758 2025. 8. 22. 19:04
import 'package:flutter/material.dart';
import 'package:flutter_blog/_core/constants/theme.dart';
import 'package:flutter_blog/ui/pages/auth/join_page/join_page.dart';
import 'package:flutter_blog/ui/pages/auth/login_page/login_page.dart';
import 'package:flutter_blog/ui/pages/post/list_page/post_list_page.dart';
import 'package:flutter_blog/ui/pages/post/write_page/post_write_page.dart';
import 'package:flutter_blog/ui/pages/splash/splash_page.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

// TODO: 1. Stack의 가장 위 context를 알고 있다.
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,
      // context가 없는 곳에서 context를 사용할 수 있는 방법
      debugShowCheckedModeBanner: false,
      home: SplashPage(),
      routes: {
        "/login": (context) => const LoginPage(),
        "/join": (context) => const JoinPage(),
        "/post/list": (context) => PostListPage(),
        "/post/write": (context) => const PostWritePage(),
      },
      theme: theme(),
    );
  }
}

 

Context가 없는 상황에서의 문제 발생

class ApiService {
  static Future<void> login() async {
    try {
      // 로그인 API 호출
      final response = await dio.post('/login');
      
      // 성공했으니 메인 화면으로 이동하고 싶은데...
      // Navigator.pushNamed(context, '/post/list');  ← context가 없어요!
      
    } catch (e) {
      // 에러 발생시 사용자에게 알리고 싶은데...
      // ScaffoldMessenger.of(context).showSnackBar(...);  ← context가 없어요!
    }
  }
}
// 전역에서 접근 가능한 네비게이터 키
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

// MaterialApp에 연결
MaterialApp(
  navigatorKey: navigatorKey,  // ← 여기서 연결!
  // ...

 

navigatorKey 활용 코드로 편리해졌음
class ApiService {
  static Future<void> login() async {
    try {
      final response = await dio.post('/login');
      
      // 이제 context 없이도 네비게이션 가능!
      navigatorKey.currentState!.pushNamed('/post/list');
      
    } catch (e) {
      // context 없이도 스낵바 표시 가능!
      final context = navigatorKey.currentContext!;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('로그인 실패: $e'))
      );
    }
  }
}

 

Stack의 의미:

  • Flutter는 화면을 Stack 구조로 관리합니다
  • 새로운 화면을 열면 위에 쌓이고 (push)
  • 뒤로 가면 위에서 제거됩니다 (pop)

"가장 위 context"의 의미:

// 화면 스택 예시
[SplashPage] ← 가장 아래 (첫 화면)
[LoginPage]  ← 로그인 화면 추가
[PostListPage] ← 메인 화면 추가 (가장 위)
// navigatorKey.currentContext는 현재 보이는 화면의 context
final currentContext = navigatorKey.currentContext!;

// 이것은 현재 사용자가 보고 있는 화면의 context와 동일
// 따라서 어디서든 현재 화면에 대한 작업 가능!