LogoSkills

domain-layer-agent

Clean Architecture 도메인 레이어 전문가입니다. Entity, UseCase, Repository 인터페이스 작업에 사용합니다.

/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 동작 전체 생성)

안에서 무슨 일이 벌어지나요#

정해진 패턴과 금지 규칙을 지켜, 도메인 계층의 각 조각을 일관되게 찍어냅니다.

  1. Entity 만들기 — 핵심 개념의 데이터 모양을 정하고, 필드 순서(ID → 필수 → 선택 → 메타) 규칙을 따릅니다.
  2. Repository Interface 만들기 — 데이터 접근 약속을 정의하고, 이름 앞에 I를 붙입니다.
  3. UseCase 만들기 — 조회·생성 같은 동작을 표준 주입 방식으로 하나씩 만들고 단위 테스트도 함께 작성합니다.
  4. 오류 처리 정의 — Failure / Exception 파일을 만들어 실패 상황을 다룹니다.
  5. 금지 규칙 점검 — 상대 경로 import, UseCase를 건너뛴 직접 호출, getIt/@injectable 사용 등을 막아 일관성을 지킵니다.

⚙️ 상세 옵션·실행 명세 (개발자 / AI 에이전트용)

Role#

Consistently generates Entity, Repository Interface, UseCase, and Failure/Exception.


Activation Conditions#

  • /cc-flutter:feature:domain Activated when command is invoked
  • /cc-flutter:feature:create orchestration Step 3invoked from

Parameters#

ParameterRequiredDescription
feature_nameFeature module name (snake_case)
entity_nameEntity name (PascalCase)
locationapplication, common, console (default: application)
usecasesTo 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.dart

Core Patterns Summary#

Entity#

  • Equatable extends, const Constructor
  • Field 순서: ID → Required → Optional (nullable) → 메타(createdAt etc.)

Repository Interface#

  • I prefix Required (IFeatureRepository)
  • Return Type: Future<Either<Failure, T>> or Stream<Either<Failure, T>> (SWR)

UseCase Patterns#

📚 Details: UseCase Pattern

PatternDescription
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: I prefix + 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