본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 15. 15:23

실제로 작동하는 Flutter 에이전트 스킬을 작성하는 방법: 2026년 레시피

요약

AI 에이전트가 최신 Flutter 코드를 정확히 작성할 수 있도록 돕는 'SKILL.md' 작성법을 다룹니다. Anthropic, Google, OpenAI의 가이드를 통합하여 실질적으로 작동하는 에이전트 스킬 설계 레시피를 제공합니다.

핵심 포인트

  • 에이전트 스킬은 단순 문서가 아닌 엄격하게 설계된 SKILL.md 형식이어야 함
  • 잘못 작성된 스킬은 컨텍스트 예산을 낭비하고 잘못된 코드를 유도함
  • Anthropic, Google, OpenAI의 모범 사례를 결합한 통합 레시피 제안
  • 프레임워크 업데이트 속도와 LLM 학습 데이터 간의 지식 격차 해소 방법 제시

요약 (TL;DR) 훌륭한 에이전트 스킬은 단순한 문서 더미가 아닙니다. 발견을 위해 설계된 설명, 무자비할 정도의 간결함, 사전에 명시된 안티 패턴 (anti-patterns), 체크리스트 워크플로, 그리고 피드백 루프를 갖춘 엄격하게 범위가 지정된 SKILL.md입니다. 이 형식은 Claude Code, OpenAI Codex, Google Antigravity, Gemini CLI, 그리고 Cursor 전반에서 작동하는 개방형 표준입니다. 이 포스트는 Flutter, Anthropic, Google, OpenAI의 공식 작성 가이드를 하나의 레시피로 합성하여, 바로 복사해서 사용할 수 있는 완전한 Flutter 스킬을 제공하며, 추측하는 대신 실제로 이를 평가하는 방법을 보여줍니다.

지난 기사에서 저는 공식 Dart 및 Flutter 에이전트 스킬 (Agent Skills)에 대해, 그리고 왜 그것들이 당신의 AI가 2022년 스타일의 Flutter 코드를 작성하는 것을 방지하는지에 대해 썼습니다. 제가 받은 가장 흔한 답변은 모두 비슷한 질문이었습니다:

"멋지네요. 그럼 제 자신만의 스킬은 어떻게 작성하나요?"

그래서 저는 실제 플레이북 (playbooks)을 읽으러 갔습니다. 개인적인 의견이 아닌 1차 자료들 말입니다: Flutter의 스킬 문서와 평가 프레임워크 (eval framework), Anthropic의 스킬 작성 모범 사례 (best practices), Google의 Antigravity 스킬 문서, 그리고 OpenAI의 Codex 스킬 가이드입니다. 좋은 소식은 그들이 거의 모든 것에 동의한다는 점입니다. 더 좋은 소식은 실제로 작동하는 스킬과 조용히 무시되는 스킬 사이의 격차는 몇 가지 결정에 달려 있으며, 대부분의 사람들이 이를 잘못 결정한다는 것입니다.

여기에 Flutter 스타일의 레시피가 있습니다.

목차

  • 나쁜 스킬이 스킬이 없는 것보다 더 나쁜 이유
  • 레시피를 만들기 전에 필요한 해부학적 구조
  • 하나의 형식, 모든 에이전트
  • 레시피: 작동하는 스킬의 9가지 재료
  • 그대로 가져다 쓸 수 있는 완전한 Flutter 스킬
  • 스킬을 실제로 평가하는 방법
  • 아무도 언급하지 않는 보안 주의사항
  • 커뮤니티의 솔직한 의견
  • 배포 체크리스트 (ship-it checklist)
  • 자주 묻는 질문 (FAQ)
  • 마치며

나쁜 스킬이 스킬이 없는 것보다 더 나쁜 이유

AI 에이전트(AI agents)는 제너럴리스트(generalists)입니다. 이들은 수년간의 Flutter 코드(그중 상당수는 더 이상 사용되지 않는 deprecated 코드임)를 평균 내어, 현재 시점에서 정확한 답변 대신 통계적으로 가장 흔한 답변을 제공합니다. Flutter 팀은 이를 **지식 격차 (knowledge gap)**라고 명명했습니다. 즉, 프레임워크가 제공하는 기능의 속도가 언어 모델(language models)이 학습 데이터(training data)를 업데이트하는 속도보다 더 빠르다는 것입니다. 스킬(Skills)은 에이전트에게 작업 특화된 전문가 워크플로우(expert workflow)를 제공함으로써 그 격차를 메우기 위해 존재합니다.

하지만 아무도 말해주지 않는 사실이 있습니다. 잘못 작성된 스킬은 단순히 도움이 되지 않는 것에 그치지 않습니다. 그것은 실질적인 비용을 발생시킵니다. 모든 스킬의 메타데이터(metadata)는 항상 에이전트의 컨텍스트 예산(context budget)을 차지하고 있습니다. 전혀 트리거(trigger)되지 않는 모호한 스킬은 무거운 짐일 뿐입니다. 설명이 불분명하여 잘못된 작업에 트리거되는 스킬은 더 나쁩니다. 왜냐하면 이제 당신의 에이전트가 잘못된 플레이북(playbook)을 확신을 가지고 따르게 되기 때문입니다.

기준은 "마크다운 (Markdown)을 좀 작성했는가"가 아닙니다. 기준은 "에이전트가 이를 신뢰할 수 있게 찾아내고, 신뢰하며, 따르는가"입니다. 아래의 모든 내용은 이 기준을 충족하기 위한 것입니다.

레시피를 만들기 전에 필요한 해부학적 구조

스킬은 가능한 가장 단순한 형태입니다. 하나의 필수 파일이 포함된 폴더입니다.

building-riverpod-async-screens/
├── SKILL.md          # 필수: 메타데이터 (metadata) + 지침 (instructions)
├── references/       # 선택 사항: 필요 시 로드되는 심층 문서 (deep-dive docs)
...

SKILL.md 자체는 YAML 프론트매터 (YAML frontmatter)와 마크다운 (Markdown) 본문으로 구성됩니다.

---
name: building-riverpod-async-screens
description: "Riverpod을 사용하여 비동기 데이터를 로드하는 Flutter 화면 구축..."
...

이 구조를 확장 가능하게 만드는 마법은 **점진적 공개 (progressive disclosure)**입니다. 시작 시 에이전트는 모든 스킬의 가벼운 메타데이터(이름, 설명, 경로)만 로드합니다. 작업이 일치할 때만 전체 SKILL.md를 읽으며, 본문에서 지시할 때만 references/ 또는 examples/에 있는 내용을 읽습니다. 만약 당신이 Flutter를 작성한다면 이미 이 패턴을 알고 있을 것입니다. 이것은 컨텍스트 윈도우 (context window)를 위한 지연 로딩 (deferred loading)입니다. OpenAI, Anthropic, 그리고 Google 모두 정확히 동일한 메커니즘을 설명하고 있습니다.

하나의 형식, 모든 에이전트

이 부분이 바로 스킬을 작성할 가치가 있게 만드는 지점입니다. SKILL.md는 개방형 표준(agentskills.io에서 발행되었으며, Anthropic에서 시작되어 현재는 생태계 전반에 채택됨)입니다. 하나의 스킬가 거의 모든 곳에서 작동합니다:

도구 (Tool)벤더 (Vendor)스킬 저장 위치
Claude CodeAnthropic.claude/skills/ (프로젝트), ~/.claude/skills/ (개인)
...

Flutter 팀의 설치 프로그램은 도구 간 공통 위치를 직접 타겟팅합니다:

npx skills add flutter/skills --skill '*' --agent universal

--agent universal 플래그를 사용하면 모든 내용이 .agents/skills 폴더에 저장되며, 이 폴더는 에이전트들이 자동으로 탐색(auto-discover)할 수 있는 호환 가능한 폴더입니다. 스킬을 한 번만 작성하면, 팀원들이 어떤 에이전트를 선호하든 상관없이 모두가 동일한 전문 지식을 갖게 됩니다. Codex는 그 위에 배포 계층을 추가하지만(저작 형식을 "스킬 (skill)", 설치 가능한 패키지를 "플러그인 (plugin)"이라고 부름), 핵심 파일은 동일합니다.

레시피: 제대로 작동하는 스킬을 위한 9가지 요소

모든 공식 소스들이 이 요소들로 수렴합니다. 저는 실제 중요도에 따라 순서를 배치했습니다.

1. 설명 (Description)이 승부의 80%를 결정한다

만약 당신의 스킬이 트리거(trigger)되지 않는다면, 그것은 거의 대부분 지시사항(instructions) 때문이 아닙니다. 바로 설명 때문입니다. 이것은 파일 전체에서 가장 중요한 단 한 줄입니다. 왜냐하면 에이전트가 100개 이상의 후보 중에서 당신의 스킬을 로드할지 말지 결정할 때 읽는 유일한 부분이기 때문입니다.

공식 가이드에서 제시하는 세 가지 규칙:

  • 3인칭으로 작성하세요. 설명은 시스템 프롬프트(system prompt)에 주입됩니다. "저는 화면 구축을 도와드릴 수 있습니다" 또는 "이것을 사용하여..."와 같은 표현은 모두 탐색(discovery) 문제를 일으킵니다. "...하는 Flutter 화면을 구축함 (Builds Flutter screens that...)"과 같이 작성하세요.
  • 무엇을 하는지, 그리고 언제 사용하는지를 명시하세요. 개발자가 실제로 입력할 법한 구체적인 트리거 단어(trigger words)를 포함하세요.
  • 핵심 사용 사례를 앞부분에 배치하세요. Codex의 가이드는 명시적입니다. 설명이 잘리더라도 매칭이 작동할 수 있도록 트리거 용어를 가장 먼저 배치하십시오. Antigravity는 과도한 활성화를 방지하기 위해 "사용하지 마시오 (Do not use)" 조항을 추가할 것을 권장합니다.

비교해 봅시다:

# 약함: 모호함, 트리거 없음, 올바르게 실행될 가능성이 매우 낮음
description: Flutter 화면 작성을 도와줍니다.

...

2. 무자비할 정도로 간결하게 작성하세요 (Be ruthlessly concise)

Anthropic은 이를 완벽하게 표현했습니다: 컨텍스트 윈도우 (context window)는 공공재입니다. 당신의 스킬은 시스템 프롬프트 (system prompt), 대화 내용, 다른 모든 스킬의 메타데이터, 그리고 사용자의 실제 요청과 이 공간을 공유합니다. 기본 전제는 에이전트가 이미 매우 똑똑하다는 것이어야 합니다.

Flutter가 무엇인지 설명하지 마세요. 위젯 (widget)이 무엇인지 설명하지 마세요. JSON을 정의하지 마세요. 모든 문장에 대해 질문하십시오: "에이전트가 정말 이것을 모를까?" SKILL.md 본문은 500행 미만으로 유지하세요. 만약 그 이상으로 늘어난다면, references/ 파일들로 분리하세요.

<!-- 나쁨: 모델이 이미 알고 있는 것에 토큰을 낭비함 -->
Flutter는 Google의 UI 툴킷입니다. 위젯은 UI의 구성 요소입니다.
네트워크 호출을 하려면 먼저 HTTP 클라이언트가 필요하며, 이는...

3. 작업에 맞춰 자유도 (degrees of freedom)를 조절하세요

Anthropic이 제시한 이 프레임워크는 대부분의 사람들이 놓치는 부분입니다. 에이전트를 경로를 따라 걷는 로봇이라고 생각해보세요:

  • 절벽이 있는 좁은 다리 (낮은 자유도): 단 하나의 올바른 순서가 있으며, 실패 시 비용이 높습니다. 정확하고 엄격한 지침을 제공하세요. 예시: "정확히 dart run build_runner build --delete-conflicting-outputs를 실행하세요. 플래그 (flags)를 수정하지 마세요."
  • 탁 트인 들판 (높은 자유도): 유효한 경로가 많으며, 컨텍스트 (context)가 결정합니다. 방향을 제시하고 에이전트를 신뢰하세요. 예시: "계층화된 접근 방식 (layered approach)을 사용하여 기능을 구조화하세요. 기존 프로젝트에 적합한 폴더 이름을 선택하세요."

취약하고 결정론적인 (deterministic) Flutter 작업들 (코드 생성, 마이그레이션, 플랫폼 설정)은 낮은 자유도를 필요로 합니다. 아키텍처 및 디자인 결정은 높은 자유도를 필요로 합니다. 대부분의 스킬은 이 둘의 혼합이 필요합니다.

4. 패턴뿐만 아니라 안티 패턴 (anti-patterns)을 먼저 제시하세요

이것이 공식 Flutter 스킬들을 매우 효과적으로 만드는 요소이며, 시니어급 스킬과 주니어급 스킬을 구분 짓는 핵심 재료입니다. 무엇을 해야 하는지만 말하지 마세요. 잘못된 본능을 명시적으로 금지하세요.

공식 flutter-build-responsive-layout 스킬이 정확히 이 작업을 수행합니다. 이 스킬은 단순히 "반응형으로 만드세요"라고 말하지 않습니다. 대신 다음과 같이 말합니다: MediaQuery.orientationOf를 사용하여 레이아웃을 전환하지 마세요, "폰"인지 "태블릿"인지 확인하지 마세요, 화면 방향을 고정하지 마세요. 이러한 부정적인 규칙(negative rules)들이 모델이 수천 개의 오래된 튜토리얼에서 학습한, 그럴듯해 보이지만 틀린 패턴(plausible-but-wrong pattern)을 따르는 것을 방지합니다.

## Rules (규칙)

- 데이터/로딩/에러를 렌더링할 때 `AsyncValue.when`을 사용하세요. 데이터가 존재한다고 가정하지 마세요.
...

5. 작업을 체크리스트 워크플로우(checklist workflow)로 전환하기

여러 단계로 이루어진 모든 작업에 대해, 에이전트가 자신의 응답에 복사하여 하나씩 체크할 수 있는 체크리스트를 제공하세요. 이는 복잡한 작업에서 가장 흔한 실패 모드인 '단계 누락'을 방지합니다. Anthropic과 Flutter 자체 스킬 모두 이 패턴을 사용합니다.

## Workflow (워크플로우)

이 체크리스트를 복사하여 진행 상황을 추적하세요:
...

6. 피드백 루프(feedback loop) 추가하기

전체 플레이북에서 가장 영향력이 큰 패턴은 바로 이것입니다: 검증기(validator) 실행, 오류 수정, 반복. 에이전트에게 스스로 실행할 수 있는 객관적인 점검 항목과, 이를 통과할 때까지 계속 진행하라는 규칙을 부여하세요. Flutter에서는 세계적인 수준의 검증기들을 무료로 사용할 수 있습니다.

코드를 생성한 후, `dart analyze`를 실행하세요. 문제가 보고되면 이를 수정하고 다시 실행하세요. 분석 결과가 깨끗하고 `flutter test`를 통과했을 때만 결과를 제시하세요.

이 단 하나의 습관은 다른 거의 모든 것보다 출력 품질을 더 효과적으로 향상시킵니다. 왜냐하면 "맞아 보이는 것"을 "증명 가능한 컴파일 및 린트(lint) 통과" 상태로 전환해주기 때문입니다.

7. 점진적 공개(progressive disclosure)를 의도적으로 사용하기

메인 SKILL.md 파일은 간결한 개요로 유지하고, 상세한 내용은 연결된 파일로 넘기세요. Antigravity 문서에서 명명한 세 가지 패턴은 다음과 같습니다:

  • 라우터 패턴 (Router pattern): SKILL.md만 포함. 집중도가 높고 단일 목적을 가진 스킬에 적합합니다.
  • 레퍼런스 패턴 (Reference pattern): SKILL.md + references/. 깊이 있는 API 상세 정보가 필요한 스킬에 적합합니다.
  • 퓨샷 패턴 (Few-shot pattern): SKILL.md + examples/. 출력 품질이 실제 작업 예시를 보는 것에 의존하는 스킬에 적합합니다.

분할할 때의 두 가지 규칙: SKILL.md로부터 참조를 **한 단계 깊이 (one level deep)**로 유지해야 합니다 (에이전트는 중첩된 파일을 부분적으로만 읽을 수 있기 때문). 또한, 100줄이 넘는 참조 파일에는 **목차 (table of contents)**를 추가하여 에이전트가 부분적으로 읽더라도 전체 범위를 파악할 수 있도록 하세요.

8. 시간 민감 정보 제거하기

"2025년 8월 이전에는 이전 API를 사용하세요"와 같은 문구는 절대 쓰지 마세요. 이는 정보가 부패하게 만듭니다. 대신, 지원 중단 (deprecated) 가이드는 접이식 "이전 패턴 (old patterns)" 섹션에 넣어, 역사는 유지하면서도 현재의 경로를 깔끔하게 유지하세요.

## Old patterns

<details>
...

9. 열 개의 형용사보다 하나의 정석적인 예시가 낫다

출력 품질이 스타일에 의존한다면, 스타일을 설명하기보다 완전한 입출력 예시를 보여주세요. 모델은 산문 (prose)을 따르는 것보다 패턴을 매칭하는 능력이 훨씬 뛰어납니다. 실행 가능한 단 하나의 정확한 Dart 코드 스니펫 (snippet)이 스킬 전체를 고정해 줍니다.

바로 가져다 쓸 수 있는 완전한 Flutter 스킬

위의 모든 재료를 결합한, 실제로 작동하는 전체 스킬을 소개합니다. 이 스킬은 AI 에이전트가 구식 Flutter 코드를 작성하기 쉬운 지점인 '비동기 데이터 로딩 (loading async data)'을 타겟팅합니다. 이를 .agents/skills/building-riverpod-async-screens/SKILL.md에 넣으면 Claude Code, Codex, Antigravity에서 바로 작동합니다.

---
name: building-riverpod-async-screens
description: Build a Flutter screen that loads async data with Riverpod,
...
// product_providers.dart
final productProvider = FutureProvider.autoDispose<List<Product>>((ref) async {
  final repo = ref.watch(productRepositoryProvider);
...

Old patterns

Why not FutureBuilder? (legacy)

FutureBuilder는 캐싱되지 않으면 재빌드될 때마다 future를 다시 실행하여 중복 네트워크 호출을 발생시킵니다. Provider는 기본적으로 캐싱 및 중복 제거 (dedupe)를 수행합니다. 서버 상태 (server state)에는 Provider를 선호하세요.


설명이 얼마나 많은 역할을 하는지, 규칙이 올바른 방법을 나열하기 전에 잘못된 본능을 어떻게 차단하는지, 워크플로우가 어떻게 검증 루프 (validator loop)로 끝나는지, 그리고 예시가 복사하기에 충분할 만큼 얼마나 완전한지 주목하세요. 그것이 파일 하나에 담긴 전체 레시피입니다.

...

{
"skills": ["building-riverpod-async-screens"],
"query": "OrderRepository에서 사용자의 주문 내역을 불러와 리스트로 보여주는 화면을 구축하세요"
...


### Flutter 방식대로 평가하기

Dart 및 Flutter 팀은 **핵심 사용자 여정 (critical user journeys)**, 즉 단순한 연습용 프롬프트가 아닌 현실적인 개발자 작업(tasks)을 중심으로 구축된 실험적인 평가 프레임워크(flutter/evals 리포지토리에 오픈 소스로 공개됨)를 운영합니다. 이들은 두 가지 축을 기준으로 점수를 매기며, 이는 여러분의 스킬(skill)에도 적용할 수 있는 훌륭한 평가 기준(rubric)입니다:

-   **결정론적 정확성 (Deterministic correctness)**: 컴파일이 되는가, `dart analyze`를 통과하는가, 그리고 테스트를 통과하는가? 객관적이며 기계로 확인 가능합니다.
-   **질적 성능 (Qualitative performance)**: 추론이 타당한가, 출력이 간결한가, 접근 방식이 안전한가? 자동화된 모델 판사(model judge)와 전문가 인간에 의해 등급이 매겨집니다.

여러분의 스킬에 이를 적용하면 매우 단순한 루프(loop)로 요약됩니다: 스킬을 사용했을 때와 사용하지 않았을 때 작업을 실행한 다음, "결정론적 체크를 통과했는가, 그리고 코드가 의미 있게 개선되었는가?"라고 질문하십시오. 만약 스킬이 두 축 중 어느 것도 변화시키지 못한다면, 그것은 컨텍스트 예산(context budget)을 사용할 가치가 없는 것입니다.

### 두 개의 에이전트 사용하기: 하나는 작성용, 다른 하나는 테스트용

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0