Files
game-fe-agent/docs/fe-ai-rules.html

613 lines
19 KiB
HTML

<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>프론트엔드 AI 활용 지침 체계</title>
<style>
:root {
--navy: #18172b;
--blue: #0b5ed7;
--blue-dark: #0756c9;
--purple: #46369a;
--green: #15803d;
--orange: #d97706;
--bg: #f5f7fb;
--card: #ffffff;
--line: #dce4f0;
--text: #1f2937;
--muted: #667085;
--soft-blue: #eef5ff;
--soft-yellow: #fff9e8;
--soft-green: #eefaf2;
--soft-purple: #f3f0ff;
--soft-gray: #f8fafc;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family:
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
"Noto Sans KR",
sans-serif;
color: var(--text);
background: var(--bg);
line-height: 1.55;
}
.hero {
display: flex;
align-items: center;
justify-content: space-between;
padding: 28px 44px;
color: #fff;
background: var(--navy);
border-bottom: 3px solid #1677ff;
}
.hero h1 {
margin: 0;
font-size: 25px;
font-weight: 800;
letter-spacing: -0.04em;
}
.hero p {
margin: 0;
color: #9da8ca;
font-size: 12px;
}
.container {
width: min(1050px, calc(100% - 48px));
margin: 32px auto 48px;
}
.card {
margin-bottom: 20px;
padding: 24px;
background: var(--card);
border: 1px solid var(--line);
border-radius: 8px;
}
.section-title {
margin: 0 0 18px;
color: #8a9cbc;
font-size: 12px;
font-weight: 800;
letter-spacing: 0.02em;
}
.purpose-title {
margin: 0 0 10px;
color: var(--blue);
font-size: 17px;
font-weight: 800;
line-height: 1.45;
}
.purpose-desc {
margin: 0;
font-size: 14px;
}
/* rules 4개 카드 */
.rules-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
}
.rule-box {
padding: 18px;
border-radius: 6px;
border: 1px solid;
}
.rule-box.blue { background: var(--soft-blue); border-color: #9ec3ff; }
.rule-box.yellow { background: var(--soft-yellow); border-color: #ecc65d; }
.rule-box.green { background: var(--soft-green); border-color: #8fd1a4; }
.rule-box.purple { background: var(--soft-purple); border-color: #c4b5fd; }
.box-title {
margin: 0 0 8px;
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 12px;
font-weight: 800;
}
.blue .box-title { color: #003d91; }
.yellow .box-title { color: #8a5a00; }
.green .box-title { color: #065f2b; }
.purple .box-title { color: #3b2780; }
.box-label {
display: inline-block;
margin-bottom: 10px;
padding: 3px 8px;
font-size: 11px;
font-weight: 800;
border-radius: 4px;
}
.blue .box-label { color: #004da8; background: #bdd7ff; }
.yellow .box-label { color: #8a5a00; background: #ffe49c; }
.green .box-label { color: #065f2b; background: #bce9cd; }
.purple .box-label { color: #3b2780; background: #ddd6fe; }
.box-subject {
margin: 0 0 10px;
font-size: 13px;
font-weight: 700;
}
.dash-list {
margin: 0;
padding: 0;
list-style: none;
color: #4b5563;
font-size: 12px;
line-height: 1.8;
}
.dash-list li::before {
content: "· ";
}
/* 파일별 상세 내용 */
.detail-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
.detail-box {
padding: 18px 20px;
background: var(--soft-gray);
border: 1px solid var(--line);
border-radius: 6px;
}
.detail-title {
display: flex;
align-items: center;
gap: 10px;
margin: 0 0 14px;
font-size: 14px;
font-weight: 800;
}
.detail-title code {
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 12px;
color: var(--blue-dark);
background: var(--soft-blue);
padding: 2px 7px;
border-radius: 4px;
}
.kv-list {
margin: 0;
padding: 0;
list-style: none;
font-size: 13px;
}
.kv-list li {
display: flex;
gap: 8px;
padding: 5px 0;
border-bottom: 1px solid var(--line);
}
.kv-list li:last-child {
border-bottom: 0;
}
.kv-key {
flex-shrink: 0;
width: 90px;
color: #6b7280;
font-size: 12px;
}
.kv-val {
color: var(--text);
}
/* 커밋 타입 뱃지 */
.commit-types {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-top: 10px;
}
.ct {
padding: 3px 9px;
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 11px;
font-weight: 800;
border-radius: 4px;
background: #1e293b;
color: #e2e8f0;
}
/* 작업 흐름 */
.flow {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
align-items: stretch;
}
.flow-item {
position: relative;
padding: 18px 16px;
background: var(--soft-gray);
border: 1px solid var(--line);
border-radius: 6px;
}
.flow-item:not(:last-child)::after {
content: "→";
position: absolute;
top: 50%;
right: -14px;
color: #98a2b3;
font-size: 18px;
transform: translateY(-50%);
}
.flow-num {
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
margin-bottom: 10px;
color: #fff;
font-size: 12px;
font-weight: 800;
border-radius: 50%;
background: var(--blue-dark);
}
.flow-num.green { background: var(--green); }
.flow-num.orange { background: var(--orange); }
.flow-num.purple { background: var(--purple); }
.flow-title {
margin: 0 0 4px;
font-size: 14px;
font-weight: 800;
}
.flow-desc {
margin: 0 0 10px;
color: #4b5563;
font-size: 12px;
}
.tag-list {
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.tag {
display: inline-block;
padding: 2px 7px;
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 11px;
border-radius: 4px;
border: 1px solid;
background: #fff;
}
.tag.blue { color: #064aa2; border-color: #9ec3ff; background: #eef5ff; }
.tag.yellow { color: #8a5a00; border-color: #ecc65d; background: #fff9e8; }
.tag.green { color: #166534; border-color: #8fd1a4; background: #eefaf2; }
.tag.purple { color: #3b2780; border-color: #c4b5fd; background: #f5f3ff; }
/* 금지 규칙 */
.no-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.no-item {
padding: 12px 14px;
background: #fff5f5;
border: 1px solid #fca5a5;
border-radius: 6px;
font-size: 13px;
color: #991b1b;
}
.no-item strong {
display: block;
margin-bottom: 4px;
font-size: 12px;
color: #7f1d1d;
}
@media (max-width: 900px) {
.hero {
display: block;
padding: 24px;
}
.hero p {
margin-top: 8px;
}
.container {
width: calc(100% - 28px);
margin-top: 20px;
}
.rules-grid,
.detail-grid,
.flow,
.no-list {
grid-template-columns: 1fr;
}
.flow-item:not(:last-child)::after {
top: auto;
right: 50%;
bottom: -18px;
transform: translateX(50%) rotate(90deg);
}
}
</style>
</head>
<body>
<header class="hero">
<div>
<h1>프론트엔드 AI 활용 지침 체계</h1>
<p>gameservice-fe-agent — rules/ 4개 파일 요약</p>
</div>
</header>
<main class="container">
<!-- 목적 -->
<section class="card">
<h2 class="section-title">문서 목적</h2>
<p class="purpose-title">
Claude AI가 프론트엔드 개발 업무를 지원할 때,<br />
어떤 지침을 언제 자동으로 참조하는지 정의합니다.
</p>
<p class="purpose-desc">
<code>rules/</code> 폴더의 4개 파일은 <code>CLAUDE.md</code>에서 <code>@import</code>로 불러오며,
모든 작업에 자동으로 적용됩니다. Vue 3 / Nuxt / TypeScript / Tailwind CSS 기반 프로젝트에서
일관성 있는 코드 작성과 협업을 지원합니다.
</p>
</section>
<!-- rules 4개 개요 -->
<section class="card">
<h2 class="section-title">rules/ 4개 파일 개요</h2>
<div class="rules-grid">
<article class="rule-box blue">
<h3 class="box-title">coding-conventions.md</h3>
<span class="box-label">코딩 컨벤션</span>
<p class="box-subject">포맷팅 · 네이밍 · 타입</p>
<ul class="dash-list">
<li>스페이스 2칸, 싱글 쿼터, 세미콜론 필수</li>
<li>camelCase / PascalCase / UPPER_SNAKE</li>
<li>any 사용 금지, 함수 반환 타입 명시</li>
<li>import 순서 (외부→절대→상대)</li>
</ul>
</article>
<article class="rule-box yellow">
<h3 class="box-title">framework-rules.md</h3>
<span class="box-label">프레임워크 규칙</span>
<p class="box-subject">Vue 3 / Nuxt / Tailwind</p>
<ul class="dash-list">
<li>&lt;script setup lang="ts"&gt; 기본</li>
<li>Pinia (공유 상태), useFetch (서버 상태)</li>
<li>Tailwind 유틸리티 우선, clsx 조건부 클래스</li>
<li>라이브러리 도입 시 PR에 이유 기록</li>
</ul>
</article>
<article class="rule-box green">
<h3 class="box-title">commit-pr.md</h3>
<span class="box-label">커밋 / PR 규칙</span>
<p class="box-subject">Conventional Commits + PR 템플릿</p>
<ul class="dash-list">
<li>type(scope): subject 형식</li>
<li>subject 50자 이내, 명령형 현재 시제</li>
<li>Squash and merge 기본 전략</li>
<li>CI(Lint/Test/Build) + 1인 이상 승인</li>
</ul>
</article>
<article class="rule-box purple">
<h3 class="box-title">claude-workflow.md</h3>
<span class="box-label">Claude 작업 방식</span>
<p class="box-subject">탐색 → 계획 → 구현 → 검증</p>
<ul class="dash-list">
<li>기존 코드 존중, 최소 변경 원칙</li>
<li>모호한 요구사항은 추측 말고 질문</li>
<li>임의 기능 추가·대량 리팩토링 금지</li>
<li>결론 먼저, 변경 파일 요약</li>
</ul>
</article>
</div>
</section>
<!-- 파일별 상세 -->
<section class="card">
<h2 class="section-title">파일별 핵심 규칙 상세</h2>
<div class="detail-grid">
<div class="detail-box">
<h3 class="detail-title"><code>coding-conventions.md</code> 포맷팅 &amp; 네이밍</h3>
<ul class="kv-list">
<li><span class="kv-key">들여쓰기</span><span class="kv-val">스페이스 2칸 (탭 금지)</span></li>
<li><span class="kv-key">문자열</span><span class="kv-val">싱글 쿼터 <code>'</code>, JSX 속성은 더블 쿼터 <code>"</code></span></li>
<li><span class="kv-key">세미콜론</span><span class="kv-val">항상 작성 (생략 금지)</span></li>
<li><span class="kv-key">최대 길이</span><span class="kv-val">한 줄 100자, 초과 시 줄바꿈</span></li>
<li><span class="kv-key">변수/함수</span><span class="kv-val">camelCase — userProfile, fetchUserData</span></li>
<li><span class="kv-key">상수</span><span class="kv-val">UPPER_SNAKE_CASE — MAX_RETRY_COUNT</span></li>
<li><span class="kv-key">컴포넌트</span><span class="kv-val">PascalCase.vue — UserCard.vue</span></li>
<li><span class="kv-key">Composable</span><span class="kv-val">use 접두사 camelCase — useAuth.ts</span></li>
<li><span class="kv-key">불리언</span><span class="kv-val">is / has / can / should 접두사</span></li>
<li><span class="kv-key">any 사용</span><span class="kv-val">금지 — 불가피 시 주석 + unknown 우선 검토</span></li>
</ul>
</div>
<div class="detail-box">
<h3 class="detail-title"><code>framework-rules.md</code> Vue 3 / Nuxt / Tailwind</h3>
<ul class="kv-list">
<li><span class="kv-key">컴포넌트</span><span class="kv-val">&lt;script setup lang="ts"&gt; 필수, Options API 금지</span></li>
<li><span class="kv-key">컴포넌트 크기</span><span class="kv-val">200줄 초과 시 분리 검토</span></li>
<li><span class="kv-key">Props</span><span class="kv-val">defineProps&lt;T&gt;() 제네릭으로 타입 명시</span></li>
<li><span class="kv-key">Emits</span><span class="kv-val">defineEmits&lt;{ ... }&gt;() 제네릭으로 선언</span></li>
<li><span class="kv-key">ref vs reactive</span><span class="kv-val">원시값 · 단일 객체는 ref 우선</span></li>
<li><span class="kv-key">공유 상태</span><span class="kv-val">Pinia 사용</span></li>
<li><span class="kv-key">서버 상태</span><span class="kv-val">useFetch / useAsyncData (직접 fetch 지양)</span></li>
<li><span class="kv-key">라우팅</span><span class="kv-val">Nuxt 파일 기반 라우팅, [param].vue 동적 라우트</span></li>
<li><span class="kv-key">Tailwind</span><span class="kv-val">유틸리티 우선, 조건부는 clsx / cn</span></li>
<li><span class="kv-key">라이브러리</span><span class="kv-val">도입 시 PR에 이유·번들 영향·대안 기록</span></li>
</ul>
</div>
<div class="detail-box">
<h3 class="detail-title"><code>commit-pr.md</code> Conventional Commits</h3>
<ul class="kv-list">
<li><span class="kv-key">형식</span><span class="kv-val">type(scope): subject</span></li>
<li><span class="kv-key">subject</span><span class="kv-val">50자 이내, 명령형 현재 시제, 마침표 없음</span></li>
<li><span class="kv-key">body</span><span class="kv-val">"왜"를 설명, 72자 줄바꿈</span></li>
<li><span class="kv-key">머지 전략</span><span class="kv-val">Squash and merge 기본</span></li>
<li><span class="kv-key">승인</span><span class="kv-val">최소 1인 이상 + CI 전부 통과</span></li>
<li><span class="kv-key">Draft PR</span><span class="kv-val">중간 피드백 필요 시 Draft 먼저 오픈</span></li>
</ul>
<div class="commit-types">
<span class="ct">feat</span>
<span class="ct">fix</span>
<span class="ct">refactor</span>
<span class="ct">style</span>
<span class="ct">docs</span>
<span class="ct">test</span>
<span class="ct">chore</span>
<span class="ct">perf</span>
<span class="ct">ci</span>
</div>
</div>
<div class="detail-box">
<h3 class="detail-title"><code>claude-workflow.md</code> 작업 원칙</h3>
<ul class="kv-list">
<li><span class="kv-key">작업 순서</span><span class="kv-val">탐색 → 계획 → 구현 → 검증</span></li>
<li><span class="kv-key">기본 원칙</span><span class="kv-val">기존 코드 존중 · 최소 변경 · 근거 있는 수정</span></li>
<li><span class="kv-key">모호한 요구</span><span class="kv-val">추측 금지 → 사용자에게 확인</span></li>
<li><span class="kv-key">커뮤니케이션</span><span class="kv-val">결론 먼저, 변경 파일 요약</span></li>
<li><span class="kv-key">검증</span><span class="kv-val">린트 / 타입체크 / 빌드 통과 확인</span></li>
</ul>
</div>
</div>
</section>
<!-- 금지 규칙 -->
<section class="card">
<h2 class="section-title">claude-workflow.md — 해서는 안 되는 것</h2>
<div class="no-list">
<div class="no-item">
<strong>임의 기능 추가 금지</strong>
사용자가 요청하지 않은 기능을 추가하지 않습니다.
</div>
<div class="no-item">
<strong>대량 리팩토링 금지</strong>
요청 범위를 벗어나는 코드 변경은 하지 않습니다.
</div>
<div class="no-item">
<strong>주석·문서 임의 삭제 금지</strong>
불필요해 보여도 삭제 전 사용자에게 확인합니다.
</div>
<div class="no-item">
<strong>비밀정보 하드코딩 금지</strong>
환경변수, 키, 토큰을 코드에 직접 작성하지 않습니다.
</div>
<div class="no-item">
<strong>의존성 버전 임의 변경 금지</strong>
요청 없이 package.json 버전을 수정하지 않습니다.
</div>
<div class="no-item">
<strong>강제 푸시·히스토리 재작성 금지</strong>
push --force, reset --hard는 명시적 요청 없이 실행하지 않습니다.
</div>
</div>
</section>
<!-- 작업 흐름 -->
<section class="card">
<h2 class="section-title">Claude 작업 단계별 참조 흐름</h2>
<div class="flow">
<article class="flow-item">
<div class="flow-num">1</div>
<h3 class="flow-title">탐색 (Explore)</h3>
<p class="flow-desc">관련 파일 파악, 유사 패턴 확인</p>
<div class="tag-list">
<span class="tag blue">CLAUDE.md</span>
<span class="tag yellow">coding-conventions</span>
</div>
</article>
<article class="flow-item">
<div class="flow-num purple">2</div>
<h3 class="flow-title">계획 (Plan)</h3>
<p class="flow-desc">할 일 목록 공유, 아키텍처 변경 시 승인</p>
<div class="tag-list">
<span class="tag yellow">coding-conventions</span>
<span class="tag yellow">framework-rules</span>
<span class="tag purple">claude-workflow</span>
</div>
</article>
<article class="flow-item">
<div class="flow-num orange">3</div>
<h3 class="flow-title">구현 (Implement)</h3>
<p class="flow-desc">코드 작성, 공통·프로젝트 지침 준수</p>
<div class="tag-list">
<span class="tag yellow">coding-conventions</span>
<span class="tag yellow">framework-rules</span>
</div>
</article>
<article class="flow-item">
<div class="flow-num green">4</div>
<h3 class="flow-title">검증 (Verify)</h3>
<p class="flow-desc">린트·타입체크·빌드, 커밋·PR 작성</p>
<div class="tag-list">
<span class="tag yellow">coding-conventions</span>
<span class="tag green">commit-pr</span>
<span class="tag purple">claude-workflow</span>
</div>
</article>
</div>
</section>
</main>
</body>
</html>