Coding Rules Agents Can Follow
팀 컨벤션 문서를 그대로 IDE 에이전트의 규칙 파일로 건넸더니 문서는 열두 절로 늘었는데 어느 규칙이 지켜졌는지 확인할 방법은 문서에 없었습니다. 2025년 모바일 웹 서비스 구축에서 쓴 프로젝트 가이드라인과 그 뒤 개인 저장소와 업무 저장소에 둔 에이전트 지침 파일을 다시 읽으며 규칙을 검사 가능한 규칙, 판단이 필요한 규칙, 도구가 대신하는 규칙으로 나눴습니다. 기억할 한 가지는 셋 중 마지막을 규칙 파일에서 빼서 린트 설정으로 옮기는 일입니다.
사람용 컨벤션을 그대로 건네면 확인할 수 없는 규칙이 쌓입니다
가이드라인은 첫머리에 “권장 사항이 아닌 필수 규칙”이라고 선언하고 Biome 검사를 통과해야 하며 어떤 경고도 허용하지 않는다고 적었습니다. 그 아래 내보내기, 파일명, 식별자, 함수 선언, 매개변수 구조 분해, 상수, 열거형, 주석, 이벤트 핸들러, useEffect, 코드 영역 주석, 상태 관리, 인터페이스의 열두 절이 이어집니다. 사람에게 주는 온보딩 문서로는 충분했지만 에이전트 규칙으로는 세 가지가 문제였습니다.
종류가 섞여 있었습니다. 파일명과 식별자 케이스는 린트가 이미 잡는 규칙이고 훅 반환값을 어디까지 구조 분해할지는 코드를 쓰면서 판단할 규칙이며 “간결하고 목적 중심적으로” 쓰라는 주석 규칙은 사람이 리뷰해야 알 수 있는 규칙입니다. 셋을 같은 목록에 두면 에이전트는 모두 같은 무게로 읽습니다.
우선순위도 없었습니다. 모든 절이 필수라 두 규칙이 부딪힐 때 무엇을 버릴지 문서가 말해 주지 않습니다. Claude Code 문서는 두 지시가 서로 모순되면 모델이 임의로 하나를 고를 수 있다고 경고하고 파일 하나를 200줄 아래로 두라고 권합니다. Cursor 문서도 규칙을 500줄 아래로 유지하고 큰 규칙은 여러 개로 나누라고 안내합니다. Claude Code: memory, Cursor: Rules
확인 방법은 더 없었습니다. “AI 어시스턴트는 항상 이 규칙에 부합하는 코드만 생성해야 합니다”라는 문장은 바람이지 검사가 아닙니다. Claude Code 문서는 규칙 파일을 강제되는 설정이 아니라 맥락으로 다룬다고 밝히고 어떤 행동을 막으려면 훅을 쓰라고 안내합니다. SpecKit 적용에서도 constitution에 적은 규칙을 지키지 않은 구현이 꽤 나왔습니다. 규칙을 적었다고 지켜지지는 않습니다.
규칙을 세 종류로 나눕니다
규칙마다 같은 질문을 던졌습니다. 도구가 같은 입력에 늘 같은 답을 내는가, 아니라면 올바른 예와 잘못된 예를 쓸 수 있는가, 그것도 아니라면 리뷰에서 사람이 볼 가치가 있는가입니다.
flowchart TD
Q1{"도구가 같은 입력에<br>같은 답을 내는가?"} -- 예 --> Tool["린트, 타입 검사, 커밋 훅 설정"]
Q1 -- 아니요 --> Q2{"올바른 예와 잘못된 예를<br>쓸 수 있는가?"}
Q2 -- 예 --> Rule["규칙 파일: 적용 조건, 기준, 예시"]
Q2 -- 아니요 --> Q3{"리뷰에서 사람이<br>볼 가치가 있는가?"}
Q3 -- 예 --> Review["리뷰 체크리스트"]
Q3 -- 아니요 --> Drop["삭제"]열두 절을 이 질문으로 나누면 절반 넘게 규칙 파일 밖으로 나갑니다.
| 가이드라인의 규칙 | 종류 | 가는 곳 |
|---|---|---|
index.ts로 다시 내보내기 금지 | 도구 | Biome performance/noBarrelFile |
| 파일명은 kebab-case | 도구 | Biome style/useFilenamingConvention |
| 식별자는 camelCase, 타입은 PascalCase | 도구 | Biome style/useNamingConvention 또는 typescript-eslint naming-convention |
React.MouseEvent 같은 UMD 전역 참조 금지, import type 사용 | 도구 | TypeScript 컴파일러와 Biome style/useImportType |
enum 대신 as const 객체 | 도구 | Biome style/noEnum |
쓰지 않는 매개변수는 _ 접두사로 남김 | 도구 | Biome correctness/noUnusedFunctionParameters |
useEffect 의존성 | 도구 | Biome correctness/useExhaustiveDependencies 또는 react-hooks/exhaustive-deps |
| props에서 파생한 값을 effect 안에서 state로 복사 금지 | 도구 | react-hooks/set-state-in-effect |
| 상수는 CONSTANT_CASE | 검사 가능한 문장 | 린트 기본값은 허용만 하고 요구하지 않음. 규칙 파일에 예시와 함께 둠 |
핸들러 이름은 handle + 대상 + 이벤트, 타입은 props 계약 재사용 | 검사 가능한 문장 | 규칙 파일. 계약 재사용은 컴포넌트 경계 글의 핸들러 절 |
| JSX 인라인 함수 금지, 추가 인자는 커링 | 검사 가능한 문장 | 규칙 파일. ESLint를 쓰면 react/jsx-no-bind |
| 훅 반환 객체는 변수로 받고 속성으로 접근 | 판단 | 규칙 파일. 조건과 예시를 붙여 다시 씀 |
| 로컬, 전역, 서버 상태의 저장 위치 | 판단 | 규칙 파일. 서버 응답을 전역 스토어에 넣지 않는다는 금지형으로 다시 씀 |
| 주석은 한글, props와 인터페이스 필드 위에 한 줄 | 판단 | 규칙 파일. 위치는 검사할 수 있고 내용은 리뷰 |
| 코드 영역 구분 주석 | 리뷰 | 사람 독자를 위한 규칙이라 에이전트 규칙에서는 뺌 |
도구가 허용하는 것과 요구하는 것은 다릅니다. Biome의 useNamingConvention은 전역 const에 camelCase와 CONSTANT_CASE를 모두 허용하므로 상수를 반드시 CONSTANT_CASE로 쓰라는 규칙은 기본값으로 강제되지 않습니다. 이런 규칙은 도구로 옮겼다고 믿지 말고 검사 가능한 문장으로 규칙 파일에 남깁니다.
판단이 필요한 규칙은 조건과 예시를 붙여야 검사할 수 있는 문장이 됩니다. 훅 반환값 규칙을 다시 쓴 예입니다.
<!-- 전: 기준이 "과도하게"라서 에이전트도 리뷰어도 선을 모릅니다 -->
- 훅, 라이브러리 함수 호출 결과를 한 번에 과도하게 구조 분해하지 않고
객체 체이닝 방식으로 필요한 메서드나 속성을 호출합니다.
<!-- 후: 적용 조건, 기준, 예외, 예시 -->
## 훅 반환값은 객체로 받습니다
적용: 메서드가 셋 이상인 객체를 돌려주는 훅(`useForm`, `useQuery`)을 호출할 때
기준: 반환값을 변수 하나로 받고 `form.register(...)`처럼 속성으로 접근합니다.
예외: 값 하나만 쓰는 호출(`const { data } = useQuery(...)`)은 구조 분해합니다.
잘못된 예: `const { register, handleSubmit, watch, formState: { errors } } = useForm()`
올바른 예: `const form = useForm()` 뒤 `form.register('username')`규칙 하나를 적용 조건, 핵심 기준, 잘못된 예와 올바른 예, 함께 볼 규칙으로 펼치는 형식은 agent conventions에서 정했습니다. 그 저장소는 같은 원본에서 에이전트용 contract와 사람이 읽는 문서를 생성하고 올바른 예에 린트와 타입 검사를 겁니다. 규칙 파일의 예시가 실제로 컴파일되는지는 그렇게 확인합니다.
도구가 대신하는 규칙은 설정 파일로 옮깁니다
가이드라인이 쓴 린트는 Biome입니다. 표에서 도구로 보낸 규칙은 설정 몇 줄이 됩니다.
{
"linter": {
"rules": {
"performance": { "noBarrelFile": "error" },
"style": {
"noEnum": "error",
"useImportType": "error",
"useFilenamingConvention": {
"level": "error",
"options": { "filenameCases": ["kebab-case"] }
},
"useNamingConvention": {
"level": "error",
"options": { "strictCase": false }
}
},
"correctness": {
"noUnusedFunctionParameters": "error",
"useExhaustiveDependencies": "error"
}
}
}
}noBarrelFile, noEnum, useFilenamingConvention, useNamingConvention은 Biome 문서 기준으로 추천 규칙이 아니라서 직접 켜야 합니다. useImportType, noUnusedFunctionParameters, useExhaustiveDependencies는 추천 규칙이라 기본으로 켜져 있고 noUnusedFunctionParameters는 밑줄로 시작하는 매개변수를 의도된 미사용으로 보고 건너뜁니다. 가이드라인이 두 절에 걸쳐 설명한 “쓰지 않는 인자는 _e로 적는다”는 이 규칙 하나로 끝납니다. Biome: noBarrelFile, noEnum, useFilenamingConvention, useNamingConvention, useImportType, noUnusedFunctionParameters, useExhaustiveDependencies
UMD 전역 참조 금지는 린트보다 앞에서 걸립니다. tsconfig의 allowUmdGlobalAccess를 켜지 않으면 모듈 파일에서 React.MouseEvent처럼 UMD 전역을 참조할 때 TypeScript가 import를 추가하라는 오류(TS2686)를 냅니다. 규칙 파일에 적을 것이 아니라 컴파일러 옵션을 바꾸지 않으면 됩니다. TSConfig: allowUmdGlobalAccess
ESLint를 쓰는 프로젝트라면 같은 규칙이 다른 이름으로 있습니다.
import reactHooks from 'eslint-plugin-react-hooks'
import importPlugin from 'eslint-plugin-import'
import tseslint from 'typescript-eslint'
export default [
// 7.0.0부터 React Compiler 규칙이 recommended에 들어 있습니다
reactHooks.configs.flat.recommended,
{
plugins: { import: importPlugin, '@typescript-eslint': tseslint.plugin },
rules: {
'func-style': ['error', 'expression'],
'import/prefer-default-export': 'error',
'@typescript-eslint/naming-convention': [
'error',
{ selector: 'variable', format: ['camelCase', 'PascalCase', 'UPPER_CASE'] },
{ selector: 'typeLike', format: ['PascalCase'] },
{ selector: 'parameter', format: ['camelCase'], leadingUnderscore: 'allow' },
],
},
},
]eslint-plugin-react-hooks 7.0.0 변경 기록은 프리셋을 recommended와 recommended-latest 둘로 줄이고 컴파일러 규칙을 기본으로 켰다고 적습니다. 그중 set-state-in-effect는 effect 안에서 동기적으로 state를 바꾸는 코드를 잡고 props에서 계산할 수 있는 값은 렌더링 중에 계산하라고 안내합니다. 가이드라인이 useEffect 절에 문장으로 적던 규칙의 상당 부분이 이 플러그인으로 갑니다. 함수 선언 방식은 ESLint 핵심 규칙 func-style이, 하나뿐인 내보내기를 default로 두는 규칙은 import/prefer-default-export가 맡습니다. eslint-plugin-react-hooks, set-state-in-effect, typescript-eslint: naming-convention, ESLint: func-style, eslint-plugin-import
도구로 옮기고 나면 규칙 파일에는 한 줄만 남습니다. “pnpm biome check를 통과하지 못한 코드는 완료로 보고하지 않는다”입니다. 규칙의 내용은 설정 파일이 들고 있고 규칙 파일은 그 검사를 언제 돌리고 결과를 어떻게 보고할지만 말합니다.
규칙 파일의 형식과 위치는 도구마다 다릅니다
남은 규칙을 어디에 둘지는 도구가 정합니다. 2026년 10월 문서 기준으로 정리했습니다.
| 도구 | 파일 | 범위 지정 | 길이 안내 |
|---|---|---|---|
| AGENTS.md 규격 | 루트와 하위 폴더의 AGENTS.md | 수정 중인 파일에서 가장 가까운 파일이 우선 | 없음. 필수 필드도 없음 |
| Claude Code | CLAUDE.md, .claude/CLAUDE.md, CLAUDE.local.md, .claude/rules/*.md | 규칙 파일 frontmatter의 paths 글롭, @경로로 다른 파일 포함 | 파일당 200줄 아래 |
| Cursor | .cursor/rules/*.mdc | alwaysApply, globs, description으로 항상, 파일별, 에이전트 판단, 수동 | 500줄 아래 |
| JetBrains Junie | .junie/AGENTS.md, 루트 AGENTS.md와 .junie/rules/*.md, 이전 형식 .junie/guidelines.md | 프로젝트 규칙이 전역 ~/.junie/AGENTS.md보다 우선 | 없음 |
| GitHub Copilot | .github/copilot-instructions.md, .github/instructions/*.instructions.md | frontmatter applyTo 글롭, 가장 가까운 AGENTS.md | 없음 |
공통점은 둘입니다. 가까운 파일이 이기고 경로 글롭으로 범위를 좁힐 수 있습니다. Claude Code는 CLAUDE.md가 없을 때 AGENTS.md를 대신 읽고 Cursor, Junie, Copilot도 AGENTS.md를 읽으므로 도구 공통 규칙은 AGENTS.md에 두고 도구별 파일에는 그 도구만의 설정을 남길 수 있습니다. 규칙을 한 원본에서 생성해 도구별 파일로 내보내는 접근은 agent conventions 페이지에 있습니다. AGENTS.md, Junie: Guidelines and memory, Copilot: repository custom instructions
길이 예산은 읽기 순서로 지킵니다. 항상 읽는 파일에는 검사 명령, 금지 사항, 보고 형식처럼 매번 필요한 것만 두고 React, CSS, 테스트 규칙은 경로별 규칙으로 나눠 그 파일을 만질 때만 읽히게 합니다. Cursor 문서는 긴 내용을 복사하는 대신 파일을 참조하라고 권하고 Claude Code 문서는 @경로 포함이 정리에는 도움이 되지만 맥락 비용은 줄이지 않는다고 밝힙니다. 항상 맥락에 있어야 하는 문장만 본문에 남기는 이유입니다.
절차와 보고 형식은 규칙과 다른 층에 둡니다
업무 저장소의 AGENTS.md는 코드 규칙을 거의 담지 않았습니다. 대신 요청을 기능 변경, 버그, 리뷰 반영, 지침 수정, 승인된 계획의 실행으로 나누는 라우팅, skill 확인부터 완료까지 아홉 단계, 단계 사이의 게이트, 보고 형식을 적었습니다. 코드 규칙은 프로젝트 규칙이나 별도 skill 팩을 따른다고 한 줄로 넘깁니다.
## Gates
- 요청 정리 없이 구현하지 않는다.
- plan이 필요한 작업은 실행 방식을 정하기 전에 구현하지 않는다.
- review를 통과하지 못한 채 다음 task나 완료 단계로 넘어가지 않는다.
- 새로 실행한 검증 없이 완료 처리하지 않는다.
## Final Report
- 무엇을 바꿨는지
- 실행한 검증 명령과 결과
- 자동 검사와 수동 확인의 구분
- 남은 리스크와 미실행 항목게이트를 ”…하지 않는다”로 쓴 이유는 어겼는지 보고에서 바로 보이기 때문입니다. 보고에 실행한 검증 명령이 없으면 마지막 게이트를 어긴 것입니다. 다만 SpecKit과 LangGraph 글의 결론대로 문서는 순서를 설명할 뿐 강제하지 못합니다. 문서에 둔 절차가 주는 것은 순서 보장이 아니라 어겼을 때 드러나는 보고 형식입니다.
IDE 어시스턴트에 둔 규칙 파일은 응답 형식을 고정했습니다. 계획, 최소 패치, 선택 이유, 다음 확인 목록의 네 부분으로 답하고 버그는 분류, 최소 재현, 가설 셋 이하, 패치, 회귀 테스트 순서로 다루라고 적었습니다. 리팩터링은 중복 3회 이상, 순환 복잡도 10 초과, 측정된 병목처럼 숫자가 있는 조건에서만 시작하고 PR은 300줄 아래로 둡니다. 숫자는 임의로 정한 값이지만 “필요할 때 리팩터링한다”보다는 어겼는지 셀 수 있습니다.
프롬프트와 규칙은 구분합니다. “시작 전에 질문부터 하라”는 큰 작업에는 맞지만 규칙 파일에 넣으면 한 줄 수정에도 질문이 돌아옵니다. 다섯 단어 이하의 초안으로 생각하고 구분선 뒤에 답하라는 식의 출력 기법은 모델에 따라 효과가 달라 규칙으로 고정할 근거가 없습니다. 둘 다 요청할 때 붙이는 프롬프트로 남겼고 규칙 파일에는 “답은 한국어로 쓴다”처럼 매번 같은 요구만 두었습니다.
지켜졌는지 확인하는 방법을 규칙에 함께 적습니다
규칙을 셋으로 나눈 뒤에는 종류마다 확인 주체가 정해집니다. 도구 규칙은 검사 명령이, 검사 가능한 문장은 에이전트의 자기 확인과 리뷰가, 판단 규칙은 리뷰가 봅니다. 규칙 파일에 적을 것은 규칙 자체보다 이 확인 절차입니다.
- 보고에 실행한 검증 명령과 결과를 적고 자동 검사와 수동 확인을 나눕니다. 개인 문서 저장소의 규칙은 커밋 전에 테스트, 문장 검사, 빌드,
git diff --check를 돌리고 요청 범위의 파일만 담으라고 적었습니다. 명령 목록이 있으면 “검증했다”가 아니라 “무엇을 돌렸다”로 보고가 바뀝니다. - 규칙을 고치면 같은 입력으로 결과를 비교합니다. agent conventions는 규칙 하나를 적용 조건과 두 예시까지 펼친 읽기 견본을 두고 시나리오별로 어떤 규칙이 선택되는지 평가하는 코드를 둡니다. 모델의 준수율을 재지는 않지만 규칙을 바꿨을 때 선택과 예시가 깨졌는지는 잡습니다.
- 리뷰 체크리스트에는 판단 규칙만 남깁니다. 도구가 잡는 항목을 체크리스트에 다시 적으면 리뷰어가 린트를 손으로 되풀이하게 됩니다.
확인 주체가 없는 규칙은 지워도 결과가 달라지지 않습니다. 코드 영역 구분 주석을 에이전트 규칙에서 뺀 기준도 같습니다. 사람 독자에게는 도움이 되지만 에이전트가 그 주석을 썼는지로 코드의 동작이나 검사 결과가 바뀌지 않습니다.
확인 방법과 한계
근거는 2025년 프로젝트 가이드라인의 개인 노트 사본, IDE 어시스턴트 규칙 파일, 업무 저장소와 개인 문서 저장소의 AGENTS.md, 프롬프트 메모와 agent conventions 저장소입니다. 가이드라인이 실제 저장소에서 어떤 범위로 적용됐는지와 에이전트가 각 규칙을 어긴 빈도는 다시 확인하지 않았습니다. 규칙을 세 종류로 나눈 뒤의 준수율, 토큰 사용량, 리뷰 시간도 재지 않았으므로 나눈 쪽이 낫다는 수치는 없습니다.
도구별 파일 경로, 길이 안내와 린트 규칙 이름은 2026년 10월 문서 기준입니다. Biome 설정은 규칙 이름과 옵션을 문서에서 확인해 다시 쓴 예시이고 프로젝트 설정을 그대로 옮기지 않았습니다. noBarrelFile은 Biome 1.6.0, noUnusedFunctionParameters는 1.8.0부터 있습니다.
참고 자료
- AGENTS.md
- Claude Code: How Claude remembers your project
- Cursor: Rules
- JetBrains Junie: Guidelines and memory
- GitHub Copilot: Adding repository custom instructions
- Biome: noBarrelFile, noEnum, useFilenamingConvention, useNamingConvention, useImportType, noUnusedFunctionParameters, useExhaustiveDependencies
- TSConfig: allowUmdGlobalAccess
- typescript-eslint: naming-convention
- ESLint: func-style
- eslint-plugin-import
- React: eslint-plugin-react-hooks, set-state-in-effect, CHANGELOG
- nomeehej/agent-conventions