Agent Skill로 README 자동화하기
저는 요즘 업무에서 AI 에이전트를 적극적으로 활용하여 반복적인 업무를 최대한 AI로 자동화하기 위해 공부 중인데요. 이번에 했던 작업 중 하나가 README 파일 생성 자동화입니다.
AI에게 README를 써달라고 하면 꽤 그럴싸한 결과물이 나옵니다.
하지만 여러 프로젝트에 반복하다 보면 프롬프트가 모호할 때마다 매번 다른 방식으로 문제를 풀기 때문에 들쑥날쑥한 결과가 나오는 문제가 생깁니다. 그래서 Agent Skill을 활용하여 반복 작업을 재사용 가능하고 일관된 결과물로 만들어내기 위해 고군분투했던 과정들을 기록하고, 이번 경험을 토대로 앞으로 다양하게 활용하고자 정리해 보려 합니다.
1. 처음엔 SKILL.md 파일 하나로 시작했습니다
저는 우선 간단하게 시작했어요. 에이전트 워크플로우를 짤 때 처음부터 완벽하게 설계하려다가 아무것도 못 만들 것 같았거든요..ㅎ 일단 실제 프로젝트에 돌려보면서 필요한 부분을 디벨롭하는 방향으로 진행했습니다.
---
name: readme-wizard
description: Generate or improve project READMEs. Use this skill whenever someone mentions README, wants to improve their repo's first impression, asks about shields.io badges, star history charts, contributor avatars, documentation tables, project structure trees, or mermaid architecture diagrams — even if they never say the word "README".
---
# README Wizard
Generate or improve a project's README by scanning the project and producing
a polished, professional result.
## Workflow
1. Detect the project name, description, license, git remote, package manager
(npm, yarn, pnpm, pip, cargo, go, etc.), and CI setup by reading the
project files
2. Improve the README to include:
- A centered hero section with the project name and tagline
- shields.io badges (license, version, CI, stars) using style=for-the-badge
- A "What is this?" section
- A scripts section with real install/dev/build/lintcommands
- A project structure tree
- A documentation table
- A contributing section with contributor avatars from contrib.rocks
- Social link badges (only if social links exist)
- A footer with a star history chart
구조나 문체가 실행할 때마다 달랐습니다. 특히 에이전트가 정보를 찾지 못하면 가짜 소셜 링크나 잘못된 설치 명령어를 지어내는 할루시네이션 현상이 빈번했습니다.
그래서 이번에는 정확한 지침을 추가했어요.
SKILL.md (160줄+)
├── name + description
└── 본문
- 작성 가이드라인 제시
- 배지 형식 지정
- 프로젝트 유형별 적응 규칙
- README 구조 템플릿 제공
- Mermaid 다이어그램 템플릿 제공
- 프로젝트 메타데이터 감지 방법 지침
정확도를 높이기 위해 모든 규칙과 템플릿을 SKILL.md 안에 다 집어넣었습니다. 가이드라인, 배지 형식, Mermaid 다이어그램 템플릿까지 상세히 적었어요.
발생한 문제:
유지보수: 파일이 200줄이 넘어가니 배지 스타일 하나 바꾸려 해도 한참을 스크롤해야 했습니다.
토큰 낭비와 성능 저하: 에이전트가 매번 레포를 직접 스캔(파일 읽기, 파싱)하느라 추론 토큰을 과하게 소모했고, 로직이 복잡해지니 여전히 실수가 잦아졌습니다.
2. 터닝 포인트: 결정론적 스크립트 도입
에이전트가 매번 직접 파일을 뒤지는 수고를 없애기 위해 스캔 스크립트를 만들었습니다. "추론이 필요한 일"과 "정확한 값이 필요한 일" 을 분리해야 한다는 것이었습니다.
스크립트 기반 워크플로우 에이전트가 scripts/scan_project.sh를 실행하면 아래와 같은 정제된 JSON 데이터를 얻습니다.
{
"project_name": "my-app",
"description": "my-app 테스트 프로젝트",
"readme_summary": "my-app 프로젝트",
"license": "",
"owner": "doit",
"repo": "test2",
"package_manager": "pnpm",
"tech_stack": ["react", "typescript", "tailwindcss", "vite", "esbuild", "zustand"],
"engines": {},
"ci": {
"provider": "",
"workflows": []
},
"scripts": ["dev", "build", "lint"],
"social_links": {},
"directory_structure": "node_modules/\npublic/\nsrc/\nsrc/api/\nsrc/components/\nsrc/constants/\nsrc/hooks/\nsrc/pages/\nsrc/store/\nsrc/types/\nsrc/utils/\nCLAUDE.md\nREADME.md\nSOLUTION.md\naassing.md\neslint.config.js\nexample-berry.png\nexample-weary.png\nindex.html\npackage.json\npnpm-lock.yaml\npublic/favicon.svg\npublic/icons.svg\nskills-lock.json\nsrc/App.tsx\nsrc/index.css\nsrc/main.tsx\ntsconfig.app.json\ntsconfig.json\ntsconfig.node.json\nvite.config.ts"
}
스크립트는 값만 반환하고, 명령어 조립은 AI가 합니다. scripts 필드에 "dev", "build" 같은 이름만 담겨있으면, AI가 package_manager: "pnpm"을 보고 pnpm run dev, pnpm run build를 스스로 씁니다. 스크립트로 AI가 모를 수 있는 것만 알려주었습니다.
에이전트가 매번 새로하는 반복 작업을 스크립트로 위임해서, 토큰을 아끼고 결과를 안정적으로 만들 수 있었습니다.
3. 아키텍처 개선: 오케스트레이터 구조
비대했던 SKILL.md를 얇은 지침만 남기고, 관심사를 분리했습니다.
도메인 지식은 참고 자료(references)로, 템플릿과 데이터는 에셋(assets)으로 분리했습니다. 각 파일이 한 가지 역할만 담당하게 됩니다.
SKILL.md (60줄) ← 워크플로우 지침만 남김
references/
└── readme-best-practices.md ← 베스트 프랙티스 분리
assets/
├── badges.json ← 배지 URL 목록 분리
├── readme-template.md ← README 구조 템플릿 분리
└── diagrams.md ← Mermaid 다이어그램 분리
scripts/
└── scan_project.sh ← 스캔 로직 분리
배지 형식을 바꾸고 싶으면 badges.json 만 열면 됩니다. 관심사 분리를 통해 시스템의 유지보수를 훨씬 수월하게 만들었습니다.
4. 명시적 검증
마지막으로 "뭔가 더 나아진 것 같다"는 막연한 느낌 대신, 에이전트가 스스로 검증할 수 있도록 evals/evals.json 에 체크 항목을 추가했습니다.
이 스킬이 좋은 결과물을 냈는지 판단하는 기준"을 정의합니다.
각 테스트 케이스는 3가지로 구성됩니다:
prompt → 실제 사용자가 입력할 법한 요청
expected_output → 결과물에 대한 한 줄 설명
assertions → 결과물이 반드시 만족해야 할 조건들
{
"skill": "readme-generator",
"evals": [
{
"id": "straightforward-request",
"prompt": "Improve the README for this project",
"expected_output": "A polished README.md with all standard sections filled in from actual project data",
"assertions": [
"Has a centered hero section with the project name and a short tagline",
"Includes shields.io badges with style=for-the-badge for status indicators that exist in the project (e.g., license, stars, and optionally version/CI if present)",
"Has a What is this section that describes the project in 2-3 sentences",
"Always includes a Scripts section with the install command as the first row",
"Scripts commands match the detected package manager or ecosystem (e.g. pnpm install, go mod download, pip install -r requirements.txt)",
"For Node projects, dev/build/test/lint rows appear in that order after install — only if those scripts exist in package.json",
"If tech_stack is non-empty, includes a Tech Stack section between Scripts and Project Structure",
"Tech Stack section is a simple table or bullet list — no prose",
"If engines field has a node version, includes it in the Tech Stack section",
"Omits the Tech Stack section entirely if no known frameworks were detected",
"Includes a project structure tree generated from the actual file system, with folders shown before files",
"Has a documentation table linking to real files in the repo",
"Has a contributing section with contributor avatars from contrib.rocks",
"Only includes social badges for links that actually exist in the project",
"Has a star history chart in the footer",
"Does not contain placeholder text like {{PROJECT_NAME}} or TODO"
]
},
{
"id": "casual-request",
"prompt": "My repo needs a better README, can you make it look professional?",
"expected_output": "A professional README.md that transforms a basic or empty README into a polished one",
"assertions": [
"Has a centered hero section with the project name and a short tagline",
"Includes shields.io badges with style=for-the-badge for at least license and stars",
"Has a What is this section that accurately describes what the project does",
"Always includes a Scripts section with commands appropriate for the detected ecosystem",
"Scripts commands match the detected package manager (e.g. pnpm install, not npm install)",
"If tech_stack is non-empty, includes a Tech Stack section between Scripts and Project Structure",
"Omits the Tech Stack section entirely if no known frameworks were detected",
"Includes a project structure tree with folders shown before files",
"Has a contributing section with contributor avatars",
"Does not fabricate social media links that don't exist in the project",
"Does not include badges for CI workflows that don't exist",
"Writing tone is concise and direct, not marketing fluff"
]
},
{
"id": "minimal-project",
"prompt": "Generate a README for this project. It's just a small script, nothing fancy.",
"expected_output": "A concise README that is proportional to the project size — not bloated with unnecessary sections",
"assertions": [
"Has a project title and description",
"Includes a Scripts section with idiomatic commands for the detected ecosystem",
"Does not include empty or stub sections",
"Does not include a Tech Stack section if no major frameworks were detected",
"Does not fabricate metadata that doesn't exist in the project",
"README length is proportional to the project complexity — not excessively long for a simple project",
"Does not contain placeholder text like {{PROJECT_NAME}} or TODO"
]
},
{
"id": "badge-focus",
"prompt": "I want to add some nice badges to my README, the shields.io kind. Can you help?",
"expected_output": "README with properly formatted shields.io badges based on actual project metadata",
"assertions": [
"All badges use style=for-the-badge",
"Badge URLs point to shields.io",
"No badges reference nonexistent CI workflows or packages",
"Status badges are grouped together at the top",
"Badge links point to the correct GitHub pages (stargazers, releases, actions, etc.)",
"Scripts section is present with commands appropriate for the detected ecosystem"
]
}
]
}
4개의 테스트 케이스
| ID | 프롬프트 |
|---|---|
straightforward-request |
일반적인 README 개선 요청 |
casual-request |
"좀 더 전문적으로 보이게 해줘" 같은 캐주얼한 요청 |
minimal-project |
작은 프로젝트에서 불필요하게 비대해지지 않는지 |
badge-focus |
뱃지 요청 시 실제 존재하는 것만 생성하는지 |
에이전트에게 직접 생성된 README를 evals.json의 조건들과 대조해서 검토하도록 요청하도록 했습니다. AI가 직접 채점자 역할을 하는 것입니다.
이제 검증까지하니 훨씬 정확하고 일관적인 결과가 나오게됩니다.
5. 결론
이번 프로젝트를 통해 배운 가장 큰 교훈은 "유용한 스킬은 결국 하나의 작은 시스템이 된다"는 점입니다.
어떤 부분은 유연하고 언어 기반이어야 하고
어떤 부분은 결정론적이어야 하고
어떤 부분은 재사용 가능한 데이터여야 하고
어떤 부분은 테스트 역할을 해야 합니다
README 자동화 뿐만 아니라 . 커밋 메시지 워크플로우, 코드 리뷰 체크리스트, 릴리즈 노트 생성, 팀 내 문서화 등 앞으로 여러 스킬을 만들 때 아래 과정대로 적용해보려 합니다.
SKILL.md하나로 시작합니다실제 프로젝트에 간단하고 빠르게 테스트합니다
반복되는 로직과 일관성 실패를 관찰합니다
기계적인 작업은 스크립트로 분리합니다
도메인 지식은 references로 옮깁니다
템플릿과 데이터는 assets으로 분리합니다
스킬이 유지보수할 만큼 중요해지면 evals를 추가합니다
마치며
처음엔 단순히 'AI가 README 좀 대신 잘 써줬으면 좋겠다'는 마음으로 시작했는데, 만들다 보니 결국 좋은 소프트웨어를 만드는 원칙과 맞닿아 있다는 걸 깨달았습니다. 관심사를 분리하고, 자동화할 수 있는 건 스크립트에 맡기고, 기준을 세워 검증하는 과정 자체가 저에게는 큰 공부가 되었어요. 결국 핵심은 AI에게 모든 걸 맡기는 게 아니라, AI가 가장 잘 할 수 있는 환경을 만들어 주는 설계자의 역할이 중요하다는 것을 깨닫게 되었네요.
아직 배울 게 많지만, 이렇게 하나씩 저만의 스킬을 만들어가는 과정이 즐거워요:)
앞으로도 단순히 도구를 사용하는 데 그치지 않고, 그 도구가 더 잘 작동할 수 있는 '구조'를 고민하는 개발자가 되려합니다. 혹시 더 좋은 자동화 아이디어나 피드백이 있다면 언제든 댓글로 알려주세요! 공유와 피드백은 언제나 환영입니다. 🙌