/cc-flutter:feature:data — 앱의 "데이터 창고" 담당 일꾼#
| 항목 | 내용 |
|---|---|
| 실행 명령 | /cc-flutter:feature:data |
| 별칭 | /data:create, /layer:data |
| 모델 | sonnet |
| 사용 도구 | Read, Edit, Write, Glob, Grep |
| 연계 스킬 | feature |
한마디로#
앱이 화면에 보여줄 정보를 서버에서 가져오고, 잠깐 보관(캐시)하고, 기기 안에 저장하는 "데이터 창고 담당자"를 자동으로 만들어 주는 도구입니다. 마치 매장 뒤편의 창고 직원처럼 — 본사(서버)에서 물건을 받아오고, 자주 쓰는 건 가까이 쌓아두고(캐시), 필요하면 매장 내 보관함(로컬 DB)에 넣어 둡니다.
누가·언제 쓰나요#
- Flutter 앱에 새 기능을 만드는 개발자가, 그 기능의 "데이터 처리 부분"을 만들 때 사용합니다.
-
/cc-flutter:feature:data명령을 직접 실행하거나, 전체 기능을 한 번에 만드는/cc-flutter:feature:create작업의 4번째 단계에서 자동으로 호출됩니다.
무엇을 해주나요#
데이터를 다루는 데 필요한 파일들을 정해진 구조로 한꺼번에 만들어 줍니다. 만들어지는 것들:
- Repository (
{feature}_repository.dart) — 데이터를 가져오고 저장하는 핵심 창구 - API Mixin (
{feature}_api_mixin.dart) — 서버와 통신하는 부분 - Cache (
{entity}_cache_repository.dart) — 자주 쓰는 데이터를 잠깐 보관하는 곳 -
Local DB (
{entity}_table.dart,{entity}_dao.dart,{feature}_database.dart) — 기기 안에 데이터를 저장하는 부분
캐시 방식은 두 가지 중에서 고릅니다: SWR(자주 바뀌거나 실시간 데이터에 적합) 또는 Cache-First(거의 안 바뀌는 데이터에 적합).
어떻게 쓰나요#
# 기본 사용 — 기능 이름과 핵심 데이터(엔티티) 이름을 지정
/cc-flutter:feature:data feature_name=post entity_name=Post
feature_name(필수) — 기능 모듈 이름 (snake_case, 예:post)entity_name(필수) — 핵심 데이터 이름 (PascalCase, 예:Post)-
location(선택) — 어디에 만들지:application(기본),common,console caching(선택) — 캐시 방식:swr(기본),cache-first,none
안에서 무슨 일이 벌어지나요#
- 서버에서 데이터를 받아오는 창구(Repository)와 통신 부분(API Mixin)을 만듭니다.
- 서버 데이터와 앱 내부 데이터 형식을 서로 변환하는 연결 작업을 넣습니다.
- 선택한 캐시 방식(SWR / Cache-First)에 맞게 데이터를 잠깐 보관하는 부분을 구성합니다.
- 기기 안에 데이터를 저장하는 표(Table)와 저장 담당(DAO)을 만듭니다.
- 마지막으로, 결과가 항상 일정한 형식으로 나오는지 등 체크리스트를 점검합니다.
⚙️ 상세 옵션·실행 명세 (개발자 / AI 에이전트용)
Role#
Consistently generates Repository implementation, API Mixin (namespace import), Cache strategy, and Local DB.
Activation Conditions#
/cc-flutter:feature:dataActivated when command is invoked- Invoked from
/cc-flutter:feature:createorchestration Step 4
Parameters#
| Parameter | Required | Description |
|---|---|---|
feature_name | ✅ | Feature module name (snake_case) |
entity_name | ✅ | Entity name (PascalCase) |
location | ❌ | application, common, console (default: application) |
caching | ❌ | swr, cache-first, none (default: swr) |
Generated Files#
feature/{location}/{feature_name}/lib/src/data/
├── repository/
│ ├── {feature}_repository.dart
│ ├── mixins/
│ │ └── {feature}_api_mixin.dart
│ └── repository.dart
├── cache/
│ └── {entity}_cache_repository.dart
└── local/
├── tables/
│ └── {entity}_table.dart
├── dao/
│ └── {entity}_dao.dart
└── {feature}_database.dartCore Patterns Summary#
Repository Implementation#
📚 Details: Repository Pattern
@LazySingleton(as: IFeatureRepository)Annotation- Mixin separation pattern recommended (network logic reuse)
API Mixin (Namespace required!)#
import 'package:serverpod_service/serverpod_service.dart' as serverpod;
mixin FeatureApiMixin implements IFeatureRepository {
serverpod.ServerpodClient get client; // ✅ 네임스페이스로 충돌 방지
}
Caching Strategy Selection#
📚 Details: Caching Pattern
| Pattern | Selection Criteria |
|---|---|
| SWR | Frequent updates, Real-time |
| Cache-First | Minimize network, Static data |
Critical Import Pattern#
// Repository: dependencies만 사용
import 'package:dependencies/dependencies.dart';
// Mixin: 네임스페이스 필수!
import 'package:serverpod_service/serverpod_service.dart' as serverpod;
// Domain Entity (네임스페이스 없음)
PostCategory category = PostCategory.qna;
// API DTO (네임스페이스로 충돌 방지)
serverpod.PostCategory apiCategory = serverpod.PostCategory.qna;
Checklist#
- Repository:
@LazySingleton(as: Interface)Annotation - API Mixin:
as serverpodNamespace import - 양방향 DTO 변환:
_mapFromDto,_categoryToDto - Caching strategy: SWR or Cache-First
- Drift: Table + DAO Generation
- Return Type:
Either<Failure, T>consistency