AI 코딩 에이전트가 내뱉는 쓰레기 코드의 공통점이 있다. 컴파일은 된다. 테스트도 통과한다. 그런데 시니어 엔지니어가 보면 빨간 펜을 꺼낸다. any로 퉁친 타입, 구현 세부사항을 검증하는 의미 없는 테스트, catch (e) {}로 조용히 삼켜버린 프로덕션 에러. 이게 악의는 아니다. 아무도 '완료'가 어떻게 생겼는지 알려주지 않았을 때, 에이전트가 선택하는 가장 그럴듯한 경로가 그것이다.
그렇다고 프롬프트를 더 잘 쓴다고 해결되지 않는다. 채팅창에 매번 'any 쓰지 마세요, 테스트는 행동을 검증하세요'를 타이핑하는 건 에이전트를 쓰는 의미가 없다. dev.to에 올라온 AGENTS.md 실전 사례와 Cursor Rules 가이드가 공통으로 가리키는 답은 하나다—규칙을 파일에 박아두면, 에이전트가 알아서 읽는다.
파일 기반 규칙의 생태계: 어떤 도구가 뭘 읽나
먼저 도구별로 읽는 파일이 다르다는 걸 정리해둬야 한다. Cursor는 .cursor/rules/ 폴더의 .mdc 파일을 읽는다. Claude Code는 CLAUDE.md와 AGENTS.md를 세션 시작 시 로드한다. Windsurf는 자체 rules 디렉터리가 있고, GitHub Copilot은 .github/copilot-instructions.md를 읽는다. 이름이 제각각이라 헷갈리지만, 작동 원리는 같다. 에이전트가 작업을 시작하기 전에 읽는 파일에 규칙을 넣는 것.
이 중에서 AGENTS.md는 크로스툴 표준에 가장 가깝다. 레포 루트에 두면 해당 스펙을 따르는 모든 에이전트가 읽어간다. 반면 .cursor/rules/ 파일은 글로브 패턴으로 조건부 로딩이 가능하다는 게 강점이다. TypeScript 파일을 건드릴 때만, 테스트 파일을 편집할 때만 특정 규칙이 컨텍스트에 들어온다. 레포 전체 규칙은 AGENTS.md에, 파일 타입별 세부 규칙은 Cursor Rules로 레이어링하는 게 실용적인 조합이다.
소원 목록 vs. 계약서
규칙 파일을 만들어봤는데 에이전트가 무시한 경험이 있다면, 십중팔구 소원 목록을 썼기 때문이다. "좋은 코드를 작성하세요