en un clic
api-contract
Cross-stack API 계약 동기화. NestJS DTO ↔ Flutter DTO 일치성 관리.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Menu
Cross-stack API 계약 동기화. NestJS DTO ↔ Flutter DTO 일치성 관리.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Basé sur la classification professionnelle SOC
Figma MCP 로 디자인을 픽셀 퍼펙트로 구현. 토큰 추출 → 테마 매핑 → 정확한 레이아웃 → 스크린샷 diff 검증 루프. Flutter/React 공용.
Flutter 외부/BaaS API 연동 풀 파이프라인. 계약 → retrofit 코드젠 → dio 인터셉터(auth/retry) → Result 매핑 → repository → 오프라인 캐시. dio-retrofit 스킬 심화.
TanStack Query v5 패턴 (React). 서버 상태 패칭/캐시/뮤테이션/낙관적 업데이트.
Supabase BaaS 연동 패턴 (Flutter). 인증/DB/리얼타임/스토리지/RLS.
Auth.js v5 (NextAuth) 패턴. 세션/미들웨어/Server Action 가드.
Dio+Retrofit API 통신 패턴. API 클라이언트, 인터셉터 작성 시 자동 참조.
| name | api-contract |
| description | Cross-stack API 계약 동기화. NestJS DTO ↔ Flutter DTO 일치성 관리. |
| globs | contracts/**, server/src/**/dto/**, client/data/remote/**, client/data/dto/**, client/domain/entity/**, docs/api/** |
크로스-스택 피처는 contracts/<domain>.contract.md 가 계약의 원본이다.
서버 DTO 작성 전에 반드시 확인:
contracts/<domain>.contract.md 가 있으면 → 그 필드/타입/enum 그대로 구현.
계약에 없는 필드 추가 금지 — 필요하면 메인 세션에 inbox 로 계약 수정 요청.contracts/README.md 형식).
팀 멤버라면 메인에게 계약 작성 요청이 원칙 (멤버는 contracts/ read-only)./api-sync 의 기준.contracts/ 가 없는 레거시 프로젝트는 아래 기존 흐름 (NestJS DTO = 원본) 사용.
contracts/*.contract.md → Prisma Schema → NestJS DTO → Flutter DTO → Flutter Entity
↑ ↑ ↑ ↑ ↑
계약 원본 DB 테이블 API 응답 형태 JSON 역직렬화 앱 도메인 모델
// server/src/game/dto/roll-dice-response.dto.ts
import { ApiProperty } from '@nestjs/swagger';
export class TileEventDto {
@ApiProperty({ enum: ['BUY_OPTION', 'PAY_TOLL', 'GOLDEN_KEY', 'WARP', 'ISLAND'] })
type: string;
@ApiProperty({ required: false })
data?: Record<string, unknown>;
}
export class RollDiceResponseDto {
@ApiProperty({ minimum: 1, maximum: 6 })
dice: number;
@ApiProperty()
newPosition: number;
@ApiProperty()
passedStart: boolean;
@ApiProperty({ required: false })
startBonus?: number;
@ApiProperty({ required: false })
event?: TileEventDto;
@ApiProperty()
diceBalance: number;
}
// client/data/remote/dto/roll_dice_response_dto.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'roll_dice_response_dto.freezed.dart';
part 'roll_dice_response_dto.g.dart';
@freezed
class RollDiceResponseDto with _$RollDiceResponseDto {
const factory RollDiceResponseDto({
required int dice,
required int newPosition,
required bool passedStart,
int? startBonus,
TileEventDto? event,
required int diceBalance,
}) = _RollDiceResponseDto;
factory RollDiceResponseDto.fromJson(Map<String, dynamic> json) =>
_$RollDiceResponseDtoFromJson(json);
}
@freezed
class TileEventDto with _$TileEventDto {
const factory TileEventDto({
required String type,
Map<String, dynamic>? data,
}) = _TileEventDto;
factory TileEventDto.fromJson(Map<String, dynamic> json) =>
_$TileEventDtoFromJson(json);
}
// client/domain/entity/roll_result.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'roll_result.freezed.dart';
@freezed
class RollResult with _$RollResult {
const factory RollResult({
required int dice,
required int newPosition,
required bool passedStart,
int? startBonus,
TileEvent? event,
required int diceBalance,
}) = _RollResult;
}
// client/data/remote/dto/roll_dice_response_dto.dart (extension)
extension RollDiceResponseDtoX on RollDiceResponseDto {
RollResult toEntity() => RollResult(
dice: dice,
newPosition: newPosition,
passedStart: passedStart,
startBonus: startBonus,
event: event?.toEntity(),
diceBalance: diceBalance,
);
}
| NestJS (서버) | Flutter DTO | Flutter Entity | 비고 |
|---|---|---|---|
| camelCase | camelCase | camelCase | JSON key 동일 |
| snake_case DB | @ApiProperty | @JsonKey(name:) | DB↔API 변환은 서버 |
string | String | String | |
number | int / double | int / double | 정수/실수 구분 |
boolean | bool | bool | |
Date (ISO) | DateTime | DateTime | JSON: ISO 8601 문자열 |
enum | String + enum | domain enum | DTO는 String, Entity에서 enum 변환 |
T? optional | T? nullable | T? nullable | |
T[] array | List<T> | List<T> |
docs/api/
├── auth.md # POST /auth/login, /auth/refresh, /auth/logout
├── board.md # GET /boards, POST /board/roll, /board/buy, etc.
├── game.md # 게임 이벤트 상세
└── _template.md # API 문서 템플릿
각 API 문서에 포함할 항목:
# NestJS Swagger에서 자동 생성된 OpenAPI JSON과 Flutter DTO 대조
# 1. NestJS에서 swagger.json 추출
curl http://localhost:3000/api-json > docs/api/swagger.json
# 2. Flutter DTO 파일 목록과 대조
# → 누락된 DTO, 필드 불일치 확인
GOLDEN_KEY, PAY_TOLL)docs/api/ 문서는 API 변경 시 즉시 갱신