"디자인 파일 5장으로 완성된 앱을 만들 수 있을까?"
시작: 무모한 도전
첫 스터디의 미션은 가계부 앱 만들기다. 디자인앱에서 프롬프트로 만든 화면(PNG)을 Claude Code에게 던졌다.
@stitch 폴더 내의 디자인을 사용해서 @source_code 폴더 내에 Flutter 프로젝트를 만들어줘Claude는 4장의 스크린샷을 분석하더니 순식간에 프로젝트 구조를 잡기 시작했다:
홈 화면 (월별 지출 요약)
거래내역 화면
데이터 분석 화면 (파이 차트!)
프로필/설정 화면
"오, 이거 금방 되겠는데?"
첫 번째 에러: SDK 버전 충돌
flutter pub get
실행하자마자 빨간 에러가 터졌다.
The current Dart SDK version is 3.10.7.
Because smart_expense requires SDK version >=2.18.0 <3.0.0, version solving failed.
문제: 내 Flutter는 3.38.7 버전인데, pubspec.yaml이 구버전 SDK를 요구하고 있었다.
해결: pubspec.yaml의 SDK 제약 조건을 수정했다.
# Before
environment:
sdk: '>=2.18.0 <3.0.0'
# After
environment:
sdk: '>=3.0.0 <4.0.0'
두 번째 에러: fl_chart의 반란
파이 차트를 그리기 위해 fl_chart 패키지를 사용했는데...
Error: The getter 'boldTextOverride' isn't defined for the class 'MediaQueryData'.
문제: fl_chart 0.55.2 버전이 최신 Flutter와 호환되지 않았다.
해결: 최신 버전으로 업그레이드!
# Before
fl_chart: ^0.55.2
# After
fl_chart: ^0.70.2
세 번째 에러: 화면이 넘쳐흘러요! (Overflow)
드디어 앱이 실행됐다! 그런데...
A RenderFlex overflowed by 42 pixels on the right.
하단 네비게이션 바가 삐져나오고, 텍스트들이 화면을 뚫고 나가려 했다.
문제: 고정 크기 위젯들이 다양한 화면 크기에 대응하지 못함.
해결: 반응형 디자인으로 전면 수정!
// Before: 고정 크기
Text('데이터 분석', style: TextStyle(fontSize: 11))
// After: LayoutBuilder + Flexible + FittedBox
LayoutBuilder(
builder: (context, constraints) {
final isCompact = constraints.maxWidth < 400;
return Row(
children: [
Expanded( // 자동으로 공간 분배
child: FittedBox( // 텍스트 크기 자동 조절
fit: BoxFit.scaleDown,
child: Text(
isCompact ? '분석' : '데이터 분석', // 공간에 따라 텍스트 변경
style: TextStyle(fontSize: isCompact ? 10 : 11),
),
),
),
],
);
},
)
핵심 포인트:
LayoutBuilder: 부모 위젯의 크기 제약 조건을 알 수 있음Flexible/Expanded: 남은 공간을 자동으로 채움FittedBox: 자식 위젯을 사용 가능한 공간에 맞게 조절
네 번째 에러: 다크모드가 안 먹혀!
프로필 화면에 다크모드 스위치를 넣었다. 토글하면... 아무 변화 없음.
// 문제의 코드
return Scaffold(
backgroundColor: AppColors.background, // 하드코딩된 색상!
appBar: AppBar(
backgroundColor: Colors.white, // 이것도!
),
)
문제: 모든 색상이 하드코딩되어 있어서 테마가 변경되어도 UI가 반응하지 않음.
해결: Theme.of(context)를 사용한 테마 인식 방식으로 변경!
// 수정된 코드
Widget build(BuildContext context) {
final theme = Theme.of(context); // 현재 테마 가져오기
return Scaffold(
// 테마에서 자동으로 배경색 가져옴
appBar: AppBar(
title: const Text('내 정보'),
// backgroundColor 지정 안 함 -> 테마 설정 사용
),
body: Container(
color: theme.cardTheme.color, // 테마 색상 사용
child: Text(
'안녕하세요',
style: TextStyle(
color: theme.textTheme.bodyLarge?.color, // 테마 텍스트 색상
),
),
),
);
}
수정해야 했던 파일 수: 20개 이상!
모든 화면과 위젯을 돌아다니며 Colors.white → theme.cardTheme.color, AppColors.textPrimary → theme.textTheme.bodyLarge?.color로 바꿨다.
최종 결과
투입 시간: 약 2시간 (대부분 에러 해결...)
완성된 기능:
4개 화면 (홈, 분석, 거래내역, 프로필)
반응형 디자인
다크모드 (진한 청색 테마)
파이 차트 데이터 시각화
카테고리별 지출 분석
배운 것들:
Flutter 버전 호환성은 항상 확인하자
반응형 디자인은 처음부터 고려하자
테마 시스템을 활용하면 다크모드는 쉽다
Claude Code는 에러 메시지만 던져주면 알아서 고친다
핵심 코드 스니펫
ThemeProvider 설정
// lib/core/providers/theme_provider.dart
class ThemeProvider extends ChangeNotifier {
ThemeMode _themeMode = ThemeMode.light;
bool get isDarkMode => _themeMode == ThemeMode.dark;
void setDarkMode(bool isDark) {
_themeMode = isDark ? ThemeMode.dark : ThemeMode.light;
notifyListeners(); // UI 갱신 트리거
}
}
MaterialApp에 테마 연결
// lib/app/app.dart
return ChangeNotifierProvider(
create: (_) => ThemeProvider(),
child: Consumer<ThemeProvider>(
builder: (context, themeProvider, child) {
return MaterialApp(
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: themeProvider.themeMode, // 여기서 전환!
home: const MainScreen(),
);
},
),
);
다크모드 스위치 연결
// lib/features/profile/profile_screen.dart
Switch(
value: themeProvider.isDarkMode,
onChanged: (value) {
themeProvider.setDarkMode(value); // 토글하면 전체 앱 테마 변경
},
)
마치며
처음엔 "PNG 4장으로 앱 만들기"가 가능할까 의심했지만, 결과적으로 가능했다. 그 과정이 순탄하진 않았다. 하지만 그게 개발 아닌가? 에러를 만나고, 구글링하고, 해결하고... 그 과정에서 배우는 것들이 진짜 실력이 된다.
Claude Code가 좋았던 점은, 에러 메시지를 던지면 "아, 이건 이런 문제네요"하고 바로 해결책을 제시한다는 것. 마치 옆에 시니어 개발자가 앉아있는 느낌이었다.
다음엔 실제 데이터베이스와 연동시켜볼 예정이다.
"삽질은 성장의 어머니다."