Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
Tags
- 배포
- nodejs
- ListView
- 자바 출력 방식
- react
- 자바스크립트
- firebase
- java 출력
- lifecycle
- 단축키
- java
- unity
- println
- java 콘솔 출력 차이
- UI/UX
- riverpod
- JS
- scss
- abap
- JQ
- 앱심사
- Flutter
- develop
- printf
- LLM
- 엡
- DART
- Clean Architecture
- 자바 포맷 출력
- npm
Archives
- Today
- Total
guricode
[Flutter] 상수 클래스 본문
상수 클래스는 앱 전체에서 사용되는 고정된 값들을 한 곳에 모아놓은 클래스다. 색상, 폰트 크기, API URL, 문자열 등 변하지 않는 값들을 관리한다.
주요 장점은:
1. 유지보수성 - 한 곳만 수정하면 전체 적용
2. 일관성 - 동일한 값 보장
3. 타입 안전성 - 컴파일 타임 오류 감지
4. 가독성 - 의미있는 이름 사용
실무에서는 AppColors, AppSizes, ApiConstants 등으로
분류하여 관리하고, private 생성자로 인스턴스
생성을 방지한다.
주요상수클래스
- AppColors - 색상
- AppTextStyles - 텍스트 스타일
- AppSizes - 크기(padding, radius 등)
- ApiConstants - API 관련
- AppStrings - 문자열
색상 상수 AppColors
import 'package:flutter/material.dart';
class AppColors {
// private 생성자 - 인스턴스 생성 방지
AppColors._();
// Primary Colors
static const Color primary = Color(0xFF2196F3);
static const Color primaryLight = Color(0xFF64B5F6);
static const Color primaryDark = Color(0xFF1976D2);
// Secondary Colors
static const Color secondary = Color(0xFFFF9800);
static const Color secondaryLight = Color(0xFFFFB74D);
static const Color secondaryDark = Color(0xFFF57C00);
// Neutral Colors
static const Color black = Color(0xFF000000);
static const Color white = Color(0xFFFFFFFF);
static const Color grey = Color(0xFF9E9E9E);
static const Color greyLight = Color(0xFFE0E0E0);
static const Color greyDark = Color(0xFF616161);
// Semantic Colors
static const Color success = Color(0xFF4CAF50);
static const Color warning = Color(0xFFFFC107);
static const Color error = Color(0xFFF44336);
static const Color info = Color(0xFF2196F3);
// Background Colors
static const Color background = Color(0xFFF5F5F5);
static const Color surface = Color(0xFFFFFFFF);
static const Color scaffoldBackground = Color(0xFFFAFAFA);
// Text Colors
static const Color textPrimary = Color(0xFF212121);
static const Color textSecondary = Color(0xFF757575);
static const Color textDisabled = Color(0xFFBDBDBD);
}
텍스트 스타일 상수 AppTextStyles
import 'package:flutter/material.dart';
class AppTextStyles {
AppTextStyles._();
// Headings
static const TextStyle h1 = TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: AppColors.textPrimary,
);
static const TextStyle h2 = TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: AppColors.textPrimary,
);
static const TextStyle h3 = TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
);
// Body Text
static const TextStyle bodyLarge = TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: AppColors.textPrimary,
);
static const TextStyle bodyMedium = TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: AppColors.textPrimary,
);
static const TextStyle bodySmall = TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
color: AppColors.textSecondary,
);
// Button Text
static const TextStyle button = TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.white,
);
// Caption
static const TextStyle caption = TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
color: AppColors.textSecondary,
);
}
크기 상수 AppSizes
class AppSizes {
AppSizes._();
// Padding & Margin
static const double paddingXS = 4.0;
static const double paddingS = 8.0;
static const double paddingM = 16.0;
static const double paddingL = 24.0;
static const double paddingXL = 32.0;
// Border Radius
static const double radiusS = 4.0;
static const double radiusM = 8.0;
static const double radiusL = 16.0;
static const double radiusXL = 24.0;
static const double radiusRound = 999.0;
// Icon Sizes
static const double iconXS = 16.0;
static const double iconS = 20.0;
static const double iconM = 24.0;
static const double iconL = 32.0;
static const double iconXL = 48.0;
// Button Heights
static const double buttonHeightS = 36.0;
static const double buttonHeightM = 48.0;
static const double buttonHeightL = 56.0;
// AppBar
static const double appBarHeight = 56.0;
// Bottom Navigation Bar
static const double bottomNavBarHeight = 60.0;
}
API 상수 ApiConstants
class ApiConstants {
ApiConstants._();
// Base URLs
static const String baseUrl = 'https://api.example.com';
static const String baseUrlDev = 'https://dev-api.example.com';
static const String baseUrlStaging = 'https://staging-api.example.com';
// API Version
static const String apiVersion = 'v1';
// Endpoints
static const String login = '/auth/login';
static const String register = '/auth/register';
static const String logout = '/auth/logout';
static const String users = '/users';
static const String posts = '/posts';
static const String comments = '/comments';
// Timeout
static const int connectTimeout = 30000; // 30초
static const int receiveTimeout = 30000; // 30초
// Headers
static const String headerContentType = 'Content-Type';
static const String headerAuthorization = 'Authorization';
static const String headerAccept = 'Accept';
// Content Types
static const String contentTypeJson = 'application/json';
static const String contentTypeFormData = 'multipart/form-data';
}
문자열 상수 AppStrings
class AppStrings {
AppStrings._();
// App
static const String appName = 'My Flutter App';
static const String appVersion = '1.0.0';
// Common
static const String ok = '확인';
static const String cancel = '취소';
static const String save = '저장';
static const String delete = '삭제';
static const String edit = '수정';
static const String loading = '로딩 중...';
static const String error = '오류가 발생했습니다';
static const String retry = '다시 시도';
// Auth
static const String login = '로그인';
static const String logout = '로그아웃';
static const String register = '회원가입';
static const String email = '이메일';
static const String password = '비밀번호';
static const String forgotPassword = '비밀번호 찾기';
// Validation
static const String fieldRequired = '필수 입력 항목입니다';
static const String invalidEmail = '올바른 이메일을 입력하세요';
static const String passwordTooShort = '비밀번호는 8자 이상이어야 합니다';
// Messages
static const String loginSuccess = '로그인에 성공했습니다';
static const String loginFailed = '로그인에 실패했습니다';
static const String networkError = '네트워크 연결을 확인하세요';
}
이미지 경로 상수 AppImages
class AppImages {
AppImages._();
// Base Path
static const String _basePath = 'assets/images';
// Logo
static const String logo = '$_basePath/logo.png';
static const String logoWhite = '$_basePath/logo_white.png';
// Icons
static const String iconHome = '$_basePath/icons/home.png';
static const String iconProfile = '$_basePath/icons/profile.png';
static const String iconSettings = '$_basePath/icons/settings.png';
// Illustrations
static const String emptyState = '$_basePath/empty_state.png';
static const String errorState = '$_basePath/error_state.png';
static const String successState = '$_basePath/success_state.png';
// Placeholder
static const String userPlaceholder = '$_basePath/user_placeholder.png';
static const String imagePlaceholder = '$_basePath/image_placeholder.png';
}
애니메이션 상수 AppAnimations
class AppAnimations {
AppAnimations._();
// Duration
static const Duration fast = Duration(milliseconds: 150);
static const Duration normal = Duration(milliseconds: 300);
static const Duration slow = Duration(milliseconds: 500);
// Curves
static const Curve defaultCurve = Curves.easeInOut;
static const Curve bounceCurve = Curves.bounceOut;
static const Curve elasticCurve = Curves.elasticOut;
}
보통이런식으로 사용
lib/
├── constants/
│ ├── app_colors.dart
│ ├── app_text_styles.dart
│ ├── app_sizes.dart
│ ├── api_constants.dart
│ ├── app_strings.dart
│ ├── app_images.dart
│ └── app_animations.dart
├── screens/
├── widgets/
└── main.dart
const vs static const 차이
static const (권장)
class AppColors {
static const Color primary = Color(0xFF2196F3);
// 클래스 이름으로 접근: AppColors.primary
// 인스턴스 생성 불필요
}
const (위젯에서)
const Text('Hello') // 컴파일 타임 상수
Text('Hello') // 런타임 생성
// const 사용 시 성능 향상
// Flutter가 위젯을 재사용함
1. Private 생성자 사용
class AppColors {
// 인스턴스 생성 방지
AppColors._();
static const Color primary = Color(0xFF2196F3);
}
// 불가능
// var colors = AppColors();
// 가능
Color color = AppColors.primary;
2. 의미있는 네이밍
// 나쁜 예
static const Color c1 = Color(0xFF2196F3);
static const double s1 = 16.0;
// 좋은 예
static const Color primary = Color(0xFF2196F3);
static const double paddingMedium = 16.0;
3. 그룹화
class AppColors {
AppColors._();
// Primary 그룹
static const Color primary = Color(0xFF2196F3);
static const Color primaryLight = Color(0xFF64B5F6);
static const Color primaryDark = Color(0xFF1976D2);
// Secondary 그룹
static const Color secondary = Color(0xFFFF9800);
static const Color secondaryLight = Color(0xFFFFB74D);
static const Color secondaryDark = Color(0xFFF57C00);
}
4. 환경별 분리
// config/environment.dart
enum Environment { dev, staging, production }
class ApiConfig {
static Environment currentEnv = Environment.dev;
static String get baseUrl {
switch (currentEnv) {
case Environment.dev:
return 'https://dev-api.example.com';
case Environment.staging:
return 'https://staging-api.example.com';
case Environment.production:
return 'https://api.example.com';
}
}
}
프로젝트를 진행하기전에 상수클래스를 정의하고 진행하는게 좋다.
| 유지보수성 | 한 곳에서 수정하면 전체 앱에 적용 |
| 일관성 | 동일한 값을 보장 |
| 가독성 | 의미있는 이름으로 코드 이해 쉬움 |
| 타입 안전성 | 컴파일 타임에 오류 감지 |
| 재사용성 | 여러 곳에서 동일한 값 사용 |
| 협업 | 팀원 간 통일된 규칙 |
주의사항
1. 너무 많은 상수 클래스 금지
// 과도한 분리
class ButtonColors { }
class TextColors { }
class BackgroundColors { }
// ... 너무 많음!
// 적절한 그룹화
class AppColors {
// Button Colors
static const Color buttonPrimary = ...;
// Text Colors
static const Color textPrimary = ...;
// Background Colors
static const Color background = ...;
}
2. 하드코딩과의 균형
// 한두 번만 쓰는 값은 상수로 만들 필요 없음
// 3번 이상 사용되면 상수로 추출 (Rule of Three)
3. 동적 값은 상수 불가
// 불가능
static const String currentTime = DateTime.now().toString();
// 가능
static String getCurrentTime() => DateTime.now().toString();
Const와 final의 차이점
- const = 컴파일 타임 상수. 값이 빌드 시점에 확정. 객체도 불변이며 캐싱(동일 리터럴은 동일 인스턴스).
- final = 런타임 1회 할당. 최초 한 번 할당 후 변경 불가. 값은 실행 중 계산 가능.
| 항목 | const | final |
| 결정 시점 | 컴파일 타임 | 런타임(첫 할당 시) |
| 재할당 | 불가 | 불가 |
| 값 제약 | 반드시 상수식 | 아무 값이나 가능(단, 1회만) |
| 객체 특성 | 깊은 불변 + canonicalization | 참조 불변(내부는 가변 가능) |
| 위젯 최적화 | const 위젯 재사용 | 해당 없음 |
| late 사용 | 불가 | 가능(late final) |
예시:
const a = 3 * 7; // OK, 컴파일 타임 상수
final b = DateTime.now(); // OK, 런타임에 결정
final list1 = [1,2]; // 리스트 재할당 불가, 내부 수정은 가능
list1.add(3); // OK
const list2 = [1,2]; // 리스트와 요소 모두 불변
// list2.add(3); // 컴파일 에러
class P { final int x; const P(this.x); }
const p1 = P(1), p2 = P(1);
identical(p1, p2); // true (동일 인스턴스)
요약:
- const ⊃ final. const는 항상 final이지만, final은 상수일 필요 없음.
- 변하지 않는 “값 자체”가 컴파일 시 확정이면 const. 실행 중 한 번 정해질 값이면 final.
- 위젯 트리에서는 가능하면 const로 지정해 리빌드 비용을 줄인다.
'앱 > Flutter&Dart' 카테고리의 다른 글
| [Flutter] MVVM패턴 (0) | 2025.10.20 |
|---|---|
| [Flutter] Riverpod 상태관리 와 Provider상태관리 (0) | 2025.10.20 |
| [Flutter]ListView, ListView.builder, SingleChildScrollView + Column 차이점 (0) | 2025.10.19 |
| [Flutter] StatefulWidget의 생명주기(Lifecycle) (0) | 2025.10.19 |
| [Flutter] Flutter 앱에서 상태(state)란 무엇인가 (0) | 2025.10.19 |