Flutter MaterialApp theme의 primaryColor가 push된 라우트에도 적용되는지 코드로 확인하는 방법

2026. 10. 25. 11:00·Flutter
728x90

왜 이 내용을 정리하나

Flutter 앱을 만들다 보면 MaterialApp에 theme을 한 번 지정해 두고, 그 뒤로 여러 화면을 Navigator로 쌓아 가는 구조가 흔하다. 이때 첫 화면에서는 색이 잘 보이는데 push한 새 화면의 AppBar나 버튼 색이 기대와 다르게 나오면 원인을 찾기 어렵다. 특히 화면마다 Theme 위젯을 따로 감싸 둔 경우에는 어느 쪽 설정이 이기는지 헷갈린다. 그래서 theme의 primaryColor가 새 라우트까지 실제로 내려가는지 눈으로 보는 대신 코드로 확인하는 방법을 정리해 본다.

개념 설명

MaterialApp의 theme 값은 앱 전체의 기본 ThemeData로 쓰인다. Navigator가 push하는 라우트는 같은 MaterialApp 아래에 있으므로 별다른 지정이 없으면 같은 ThemeData를 상속받는다. 즉 primaryColor도 기본적으로 그대로 전달된다.

다만 Theme 위젯을 중간에 한 번 더 감싸면 그 하위 트리에서는 바깥 값을 덮어쓴 ThemeData가 쓰인다. 라우트는 Navigator 아래의 별도 Overlay 항목으로 올라가지만, Theme 조회는 위젯 트리의 BuildContext를 따라 올라가며 이뤄진다. 따라서 push된 라우트의 context에서 Theme.of(context)를 호출하면 그 시점에 유효한 primaryColor를 얻을 수 있다.

핵심은 화면에 그려진 색을 추측하지 않고, 라우트의 build 안에서 Theme.of(context).primaryColor 값을 읽어 확인하는 것이다. 값을 직접 출력하거나 테스트에서 expect로 비교하면 된다.

코드 예제

아래 예제는 첫 화면에서 두 번째 화면으로 push한 뒤, 두 번째 화면이 읽은 primaryColor를 화면에 텍스트로 보여준다. 기대값은 MaterialApp에 지정한 색이며, 일치 여부도 함께 표시한다.

import 'package:flutter/material.dart';

const Color kExpectedPrimary = Color(0xFF1565C0);

void main() {
  runApp(const ThemeCheckApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'theme check',
      theme: ThemeData(
        primaryColor: kExpectedPrimary,
      ),
      home: const FirstPage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('첫 화면')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.of(context).push(
              MaterialPageRoute(builder: (_) => const SecondPage()),
            );
          },
          child: const Text('두 번째 화면으로 이동'),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final Color actual = Theme.of(context).primaryColor;
    final bool matched = actual.value == kExpectedPrimary.value;

    return Scaffold(
      appBar: AppBar(title: const Text('두 번째 화면')),
      body: Center(
        child: Text(
          matched ? 'primaryColor 일치' : 'primaryColor 불일치',
          style: TextStyle(color: actual, fontSize: 20),
        ),
      ),
    );
  }
}

이 코드를 실행해 첫 화면의 버튼을 누르면 두 번째 화면이 열리고, 그 화면의 AppBar와 가운데 텍스트가 MaterialApp에서 지정한 색으로 표시된다. 텍스트 내용은 기대한 색과 실제 색이 같으면 'primaryColor 일치'가 나오고 다르면 '불일치'가 나온다. 색상 값은 TextStyle의 color로도 그대로 적용되어 시각적으로도 확인할 수 있다.

헷갈리는 점

가장 흔한 혼동은 AppBar 색과 primaryColor를 같은 것으로 보는 것이다. Material 3에서는 ColorScheme 기반으로 색이 계산되므로 primaryColor만 바꿔도 AppBar 배경이 그대로 바뀌지 않을 수 있다. 그래서 색을 확인할 때는 AppBar 모양보다 Theme.of(context)에서 읽은 값을 기준으로 보는 편이 정확하다.

두 번째로, Navigator.push 전에 감싼 Theme 위젯이 라우트 바깥에 있는지 안에 있는지에 따라 결과가 달라진다. push 호출 위치의 context가 아니라 라우트 builder 안의 context를 기준으로 읽어야 한다는 점도 자주 놓친다. 이 노트의 예제는 builder 안에서 Theme.of를 호출하므로 그 차이를 피한다.

세 번째로, 다이얼로그나 BottomSheet처럼 Navigator 라우트가 아닌 Overlay 기반 위젯은 같은 방식으로 확인하더라도 context 위치가 다를 수 있다. 그런 경우에도 해당 위젯의 build 안에서 Theme.of를 호출해 값을 직접 읽는 방식이 같게 적용된다.

정리

push된 새 라우트에서 primaryColor가 적용되는지는 라우트 build 안에서 Theme.of(context).primaryColor를 읽어 기대값과 비교하면 코드로 확인할 수 있다. MaterialApp의 theme은 Navigator 라우트에 기본으로 상속되며, 중간에 Theme 위젯이 끼어 있으면 그 하위 값이 우선한다. AppBar의 실제 색은 Material 3의 ColorScheme 계산에 따라 달라질 수 있으므로 화면보다 읽은 값을 기준으로 판단하는 것이 안전하다. 이 노트에서는 theme 값을 라우트 안에서 직접 읽어 비교하는 방법을 정리해 본다.

#Flutter #MaterialApp #theme #primaryColor #Navigator #라우팅 #Dart

728x90
LIST

'Flutter' 카테고리의 다른 글

Flutter async*와 yield로 만든 Stream을 StreamBuilder에 연결했을 때 ConnectionState 변화 순서 확인하기  (0) 2026.10.26
Dart 명명된 매개변수에서 required와 기본값을 함께 쓸 때의 동작 확인  (0) 2026.10.24
Dart 레코드를 함수 반환값으로 쓰고 구조 분해로 받아 확인하는 방법  (0) 2026.10.24
Flutter Column과 Row로 화면을 배치하는 방법  (0) 2026.10.23
Flutter에서 StatelessWidget과 StatefulWidget을 나누는 기준  (0) 2026.10.23
'Flutter' 카테고리의 다른 글
  • Flutter async*와 yield로 만든 Stream을 StreamBuilder에 연결했을 때 ConnectionState 변화 순서 확인하기
  • Dart 명명된 매개변수에서 required와 기본값을 함께 쓸 때의 동작 확인
  • Dart 레코드를 함수 반환값으로 쓰고 구조 분해로 받아 확인하는 방법
  • Flutter Column과 Row로 화면을 배치하는 방법
Mr. Joo
Mr. Joo
  • Mr. Joo
    삽질의 시작
    Mr. Joo
  • 전체
    오늘
    어제
    • 분류 전체보기 (256) N
      • Python (7) N
      • 개발 요약 (10)
      • Flutter (77) N
      • Android (9)
      • Swift (9) N
      • React (16) N
      • 인공지능 (4)
      • 대학원 (3)
      • CS (10)
      • 개발 뉴스 (108)
      • IT 기기 (1)
      • 알면 유용한 정보 (2)
  • 인기 글

  • 태그

    DART
    오늘의 개발 뉴스
    뉴스
    Swift
    앱 개발
    이슈
    기술
    오늘의 기술 뉴스
    android
    개발 뉴스
    Dart 기초
    react
    기술 뉴스
    오늘의 뉴스
    개발
    앱
    개발 이슈
    Flutter
    오늘의 이슈
    플러터
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
Mr. Joo
Flutter MaterialApp theme의 primaryColor가 push된 라우트에도 적용되는지 코드로 확인하는 방법
상단으로

티스토리툴바