2025. 2. 25. 16:02ㆍ같이 공부합시다 - Flutter/Dart & Flutter 기초부터 실전까지
📋 개요
🔸 Flutter 앱 개발 시, 색상과 글꼴을 일일이 지정하면 유지보수가 어려움
🔸 ThemeData와 ColorScheme을 활용하면 앱 전체에서 일관된 디자인을 쉽게 적용 가능.
🔸 Flutter 테마 시스템 활용 방법 (ColorScheme, Typography, 다크 모드)
📝 주제
🔸 ColorScheme을 사용한 색상 관리
🔸 Typography를 활용한 텍스트 스타일링
🔸 Material Theme을 이용한 앱 테마 설정
🔸 다크 모드 지원 및 커스텀 테마 적용
1️⃣ Flutter 테마(Theme) 시스템 이해
📌 Flutter의 테마(Theme)는 앱의 일관된 디자인을 유지하는 핵심 요소
📌 Flutter 테마 시스템의 주요 장점
✨ 1. 일관된 디자인 유지
→ 모든 화면에서 동일한 스타일 적용 가능
🎨 2. 색상 및 글꼴 통합 관리
→ ColorScheme, Typography 설정 활용
🌙 3. 다크 모드 지원
→ ThemeMode.system을 사용해 자동 변경 가능
🛠️ 4. UI 유지보수 및 코드 재사용성 증가
→ 변경 사항을 한 곳에서 관리
📌 예제 코드 (기본 테마 설정)
MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
textTheme: TextTheme(bodyLarge: TextStyle(fontSize: 18)),
),
darkTheme: ThemeData.dark(), // 다크 모드 지원
themeMode: ThemeMode.system, // 시스템 설정에 따라 자동 변경
)
✅ 위 코드의 핵심 포인트
1️⃣ ColorScheme.fromSeed(seedColor: Colors.blue) → 앱의 색상을 Blue 계열로 자동 적용
2️⃣ textTheme → 기본 글꼴 스타일 적용 (bodyLarge → 기본 텍스트 크기 18px)
3️⃣ darkTheme: ThemeData.dark() → 다크 모드 자동 지원
4️⃣ themeMode: ThemeMode.system → 시스템 설정에 따라 라이트/다크 모드 자동 변경
💡 테마를 설정하면 앱 전체에 적용 가능하며, 유지보수가 쉬워짐!
2️⃣ ColorScheme (색상 테마) 적용
📌 ColorScheme을 활용하여 앱의 주요 색상을 정의하고, ThemeData에 적용
📌 기본 ColorScheme 설정
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter 테마 설정',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
secondary: Colors.orange,
surface: Colors.white,
onPrimary: Colors.white,
),
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark,
secondary: Colors.deepOrange,
surface: Colors.black,
onPrimary: Colors.white,
),
),
themeMode: ThemeMode.system,
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("ColorScheme 적용"),
),
body: Center(
child: ElevatedButton(
onPressed: () {},
child: const Text("버튼"),
),
),
);
}
}
🔸 Material 3 지원을 위한 ColorScheme.fromSeed() 적용
🔸 라이트 & 다크 모드를 함께 설정하여 다양한 환경에서의 적용 가능성 보강
🔸 themeMode: ThemeMode.system을 설정하여 자동 감지 기능 추가
3️⃣ Typography (글꼴 스타일) 설정
📌 ThemeData.textTheme을 활용하여 앱 전체의 글꼴 스타일을 설정
📌 기본 Typography 설정
ThemeData(
textTheme: const TextTheme(bodyLarge: TextStyle(fontSize: 18)), // 기본 텍스트 스타일
)
📌 글꼴(Font Family) 적용 예제
ThemeData(
fontFamily: 'Roboto',
textTheme: TextTheme(
bodyLarge: TextStyle(fontSize: 18, color: Colors.black),
),
)
🔸 Material 3에서 사용되는 새로운 Typography 스타일(bodyLarge) 적용
🔸 폰트 설정도 추가하여 사용자가 쉽게 적용 가능하도록 개선
4️⃣ Material Theme을 활용한 전체 테마 설정
📌 Material 3 테마 적용 가능 (useMaterial3: true)
📌 버튼, 카드 등 UI 요소의 스타일을 일괄 지정 가능
📌 Material Theme 예제
ThemeData(
useMaterial3: true,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
),
),
)
🔸 버튼 스타일을 일괄적으로 지정 가능
🔸 Material 3 디자인을 지원하여 최신 UI 적용
📌 활용 예제
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Material 3 테마 예제',
theme: ThemeData(
//useMaterial3: true, // ✅ Material 3 디자인 적용
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), // 기본 색상
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue, // 버튼 배경색
foregroundColor: Colors.white, // 버튼 텍스트 색상
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
),
),
floatingActionButtonTheme: const FloatingActionButtonThemeData(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
cardTheme: CardTheme(
color: Colors.white,
shadowColor: Colors.grey.withValues(alpha: 0.5),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
),
),
darkTheme: ThemeData.dark().copyWith(
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.orange,
foregroundColor: Colors.black,
),
),
),
themeMode: ThemeMode.system, // ✅ 시스템 설정에 따라 라이트/다크 모드 자동 변경
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context); // 현재 테마 가져오기
return Scaffold(
appBar: AppBar(
title: const Text('Material 3 테마 적용'),
backgroundColor: theme.colorScheme.primary,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {},
child: const Text('테마 적용 버튼'),
),
const SizedBox(height: 20),
Card(
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'이것은 Material 3 디자인을 적용한 카드입니다.',
style: theme.textTheme.bodyLarge,
),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
);
}
}
📌 Material 3 테스트 결과

5️⃣ 다크 모드 지원
📌 ThemeData.dark()를 활용하여 다크 모드 지원
📌 MediaQuery를 사용하여 시스템 테마 감지 가능
📌 다크 모드 자동 감지 적용
MaterialApp(
themeMode: ThemeMode.system,
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
)
🔸 시스템 설정(다크/라이트)에 따라 자동으로 변경
🔸 사용자가 직접 변경하는 기능도 추가 가능
📌 활용 예제 코드
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
// ✅ MyApp을 StatefulWidget으로 변경하여 themeMode 상태 관리
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
ThemeMode _themeMode = ThemeMode.system; // 기본값: 시스템 설정 따름
void toggleTheme() {
setState(() {
_themeMode =
(_themeMode == ThemeMode.light) ? ThemeMode.dark : ThemeMode.light;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: '다크 모드 지원 앱',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), // 라이트 모드 색상
textTheme:
const TextTheme(bodyLarge: TextStyle(fontSize: 18)), // 기본 텍스트 스타일
),
darkTheme: ThemeData.dark().copyWith(
textTheme: const TextTheme(
bodyLarge: TextStyle(fontSize: 18)), // 다크 모드에서도 동일한 폰트 크기 적용
),
themeMode: _themeMode, // 현재 테마 적용
home: HomeScreen(toggleTheme: toggleTheme),
);
}
}
// ✅ HomeScreen에서 버튼을 눌러 다크 모드 변경
class HomeScreen extends StatelessWidget {
final VoidCallback toggleTheme;
const HomeScreen({super.key, required this.toggleTheme});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final isDarkMode = theme.brightness == Brightness.dark;
return Scaffold(
appBar: AppBar(
title: const Text('다크 모드 테스트'),
backgroundColor: theme.colorScheme.primary,
actions: [
IconButton(
icon: Icon(isDarkMode ? Icons.wb_sunny : Icons.nightlight_round),
onPressed: toggleTheme, // 버튼 클릭 시 테마 변경
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
isDarkMode ? Icons.nightlight_round : Icons.wb_sunny,
size: 80,
color: theme.colorScheme.secondary,
),
const SizedBox(height: 10),
Text(
isDarkMode ? '다크 모드 활성화됨' : '라이트 모드 활성화됨',
style: theme.textTheme.bodyLarge,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: toggleTheme, // 버튼으로 다크 모드 변경
child: const Text('라이트/다크 모드 변경'),
),
],
),
),
);
}
}
📌 다크 모드 테스트 결과

📌 오늘의 요약
✅ ColorScheme을 활용하여 앱의 색상 테마를 설정하는 방법 학습
✅ Typography를 활용하여 텍스트 스타일을 통일하는 방법 이해
✅ Material Theme을 활용하여 버튼, 카드 스타일을 일괄 변경하는 방법 실습
✅ 다크 모드를 감지하여 자동 적용하는 기능 구현
✅ 사용자가 직접 다크 모드를 변경하는 기능 추가
🔥 오늘 배운 핵심 내용 정리
🎨 ColorScheme → 앱의 색상 테마를 한 곳에서 설정하는 방법
🔤 Typography → 텍스트 스타일을 일괄 적용하는 방법
🛠️ Material Theme → 버튼, 카드 등의 스타일을 전체적으로 통일
🌙 다크 모드 적용 → ThemeMode.system을 활용해 자동 변경