/cc-flutter:feature:domain — 앱의 "핵심 규칙" 설계 담당#
| 항목 | 내용 |
|---|---|
| 실행 명령 | /cc-flutter:feature:domain |
| 별칭 | /domain:create, /layer:domain |
| 모델 | sonnet |
| 사용 도구 | Read, Edit, Write, Glob, Grep |
| 연계 스킬 | feature |
한마디로#
앱이 다루는 핵심 개념(예: 사용자, 주문)과 그것으로 할 수 있는 일(조회·생성 등)을 일관된 형태로 만들어 주는 전담 일꾼입니다. 건물로 치면 화면 디자인이나 데이터 저장 방식과 무관하게 변하지 않는 "설계 원칙"을 정리해 두는 단계예요.
누가·언제 쓰나요#
-
새 기능의 데이터 모양과 규칙을 처음 잡을 때 —
/cc-flutter:feature:domain명령을 직접 실행하면 동작합니다. - 백엔드부터 앱까지 한 번에 만드는 전체 기능 생성(
/cc-flutter:feature:create)이 진행될 때, 그 안의 3번째 단계로 자동 호출됩니다.
무엇을 해주나요#
기능 하나에 필요한 도메인 뼈대 파일들을 일정한 규칙에 맞춰 한 번에 만들어 줍니다. 실제로 생기는 것:
- Entity — 핵심 개념의 데이터 모양 (
{entity}.dart등) -
Repository Interface — 데이터를 가져오고 저장하는 "약속" 정의 (
i_{feature}_repository.dart) -
UseCase — 조회·생성 같은 개별 동작 (
get_{entity}s_usecase.dart,create_{entity}_usecase.dart등) -
Failure / Exception — 오류 상황을 다루는 파일 (
{feature}_failure_messages.dart,{feature}_exception.dart)
이 파일들은 모두 feature/{location}/{feature_name}/lib/src/domain/ 폴더 아래에 정리되어 만들어집니다.
어떻게 쓰나요#
# 기능 이름과 핵심 개념(Entity) 이름을 지정해 도메인 계층 생성
/cc-flutter:feature:domain
# 같은 일을 하는 다른 이름(별칭)으로도 호출 가능
/domain:create
/layer:domain
전달할 수 있는 값:
feature_name(필수) — 기능 모듈 이름 (snake_case, 예:user_profile)entity_name(필수) — 핵심 개념 이름 (PascalCase, 예:UserProfile)-
location(선택) — 어디에 둘지:application(기본값) /common/console usecases(선택) — 만들 동작 목록 (지정 안 하면 기본 CRUD 동작 전체 생성)
안에서 무슨 일이 벌어지나요#
정해진 패턴과 금지 규칙을 지켜, 도메인 계층의 각 조각을 일관되게 찍어냅니다.
- Entity 만들기 — 핵심 개념의 데이터 모양을 정하고, 필드 순서(ID → 필수 → 선택 → 메타) 규칙을 따릅니다.
- Repository Interface 만들기 — 데이터 접근 약속을 정의하고, 이름 앞에
I를 붙입니다. - UseCase 만들기 — 조회·생성 같은 동작을 표준 주입 방식으로 하나씩 만들고 단위 테스트도 함께 작성합니다.
- 오류 처리 정의 — Failure / Exception 파일을 만들어 실패 상황을 다룹니다.
-
금지 규칙 점검 — 상대 경로 import, UseCase를 건너뛴 직접 호출,
getIt/@injectable사용 등을 막아 일관성을 지킵니다.
⚙️ 상세 옵션·실행 명세 (개발자 / AI 에이전트용)
Role#
Consistently generates Entity, Repository Interface, UseCase, and Failure/Exception.
Activation Conditions#
/cc-flutter:feature:domainActivated when command is invoked/cc-flutter:feature:createorchestration Step 3invoked from
Parameters#
| Parameter | Required | Description |
|---|---|---|
feature_name | ✅ | Feature module name (snake_case) |
entity_name | ✅ | Entity name (PascalCase) |
location | ❌ | application, common, console (default: application) |
usecases | ❌ | To generate UseCase List (default: CRUD Before체) |
Generated Files#
feature/{location}/{feature_name}/lib/src/domain/
├── entity/
│ ├── {entity}.dart
│ ├── {entity}_list_result.dart
│ └── entity.dart # export
├── repository/
│ ├── i_{feature}_repository.dart
│ └── repository.dart # export
├── usecase/
│ ├── get_{entity}s_usecase.dart
│ ├── create_{entity}_usecase.dart
│ └── usecase.dart # export
├── failure/
│ └── {feature}_failure_messages.dart
└── exception/
└── {feature}_exception.dartCore Patterns Summary#
Entity#
Equatableextends,constConstructor- Field 순서: ID → Required → Optional (nullable) → 메타(createdAt etc.)
Repository Interface#
Iprefix Required (IFeatureRepository)- Return Type:
Future<Either<Failure, T>>orStream<Either<Failure, T>>(SWR)
UseCase Patterns#
📚 Details: UseCase Pattern
| Pattern | Description |
|---|---|
| Optional Constructor Injection | ✅ Standard - UseCase([IRepo? repo]) : _repo = repo ?? ConcreteRepo() |
Prohibited Patterns#
// ❌ Relative path import prohibited
import '../domain/entity/user.dart';
// ❌ Repository 직접 호출 (UseCase 우회) 금지
final result = await repository.getUser();
// ❌ getIt usage prohibited
IRepo get repo => getIt<IRepo>();
// ❌ @injectable 어노테이션 금지
Checklist#
Common (Required)#
- Entity: Equatable extends + const constructor
- Repository:
Iprefix +Either<Failure, T>Return - Write UseCase unit tests
- Use package imports only
UseCase Patterns#
- ✅ Optional Constructor Injection:
const UseCase([IRepo? repo]) : _repo = repo ?? ConcreteRepo() - ✅ Test:
UseCase(mockRepo)Direct injection