무슨 일이 벌어지나 — 규칙을 적어 뒀는데 AI가 안 읽고 코드를 썼다
나는 AI 코딩 도구 Claude Code에게 자바 코드를 맡긴다. Claude Code는 내 컴퓨터에서 파일을 읽고, 쓰고, 터미널 명령을 실행하는 AI 프로그램이다. 사람이 「주문 목록을 보여 주는 기능을 만들어 줘」라고 하면 Claude가 직접 클래스 파일을 만든다.
우리 팀에는 코드 규칙이 있다. 예를 들어 「데이터를 담아 옮기기만 하는 클래스(DTO)에는 setter를 만들지 않는다」 같은 것이다. 이런 규칙을 주제별로 묶은 것을 「표준」이라고 부른다. 예를 들어 「DTO 생성 표준」은 DTO를 만드는 규칙 묶음이다. 이런 표준 50개를 Claude가 읽을 수 있는 파일로 적어 두었다.
그런데 Claude가 새 클래스(예를 들어 웹 요청을 처음 받는 Controller 클래스)를 만들면서 그 규칙 파일을 한 번도 열지 않고 코드를 쓸 수 있었다. 규칙이 「Claude가 필요하다고 판단하면 여는 파일」에 들어 있었기 때문이다. 판단을 안 하면 규칙은 없는 것과 같다.
이 글은 규칙을 어느 파일에 두어야 Claude가 빠짐없이 읽는가를 설명한다.
먼저 알아야 할 말 — Claude Code가 글을 읽는 통로는 넷이다
Claude는 대화를 시작할 때 모든 파일을 읽지 않는다. AI는 읽은 글의 양만큼 처리 시간과 사용료가 들어서, 다 읽으면 느리고 비싸다. 대신 정해진 통로로 필요한 글만 읽는다. 이 글에 나오는 통로는 넷이다.
CLAUDE.md— 프로젝트 맨 위에 두는 안내문이다. 대화를 시작할 때마다 통째로 읽힌다. 길면 매번 그만큼 비용이 든다- rules (
.claude/rules/*.md) — 파일 맨 위에 「이 규칙은 이런 경로의 파일에 걸린다」를 적어 둔 규칙 파일이다. 예를 들어**/infra/**/*.java라고 적으면, Claude가infra폴더 안의 자바 파일을 읽는 순간 이 규칙이 자동으로 함께 들어온다.**는 「폴더가 몇 겹이든」,*는 「이름이 무엇이든」이라는 뜻이다 - skills (
.claude/skills/*/SKILL.md) — 「이런 일을 할 때 이 순서로 한다」를 적은 설명서다. 평소에는 제목과 한 줄 설명만 보인다. Claude가 「지금 이 일을 하고 있다」고 판단해야 본문을 연다 - 훅(hook) — Claude가 파일을 쓰거나 명령을 실행하기 직전에 자동으로 끼어드는 작은 프로그램이다. 문지기처럼 「이건 안 돼」 하고 막을 수 있다. 막을 때 남긴 안내문은 Claude에게 전달된다
표준 하나에 든 줄들은 두 종류로 나뉜다. 한 표준 안에 두 종류가 같이 들어 있기도 하다.
- 코드 규칙 — 「이 파일의 코드는 이래야 한다」. 예: DTO에 setter를 두지 않는다
- 작업 절차 — 「이 일은 이 순서로 한다」. 예: 커밋(바꾼 코드를 기록으로 남기는 일)하기 직전에 멈추고 사람에게 확인받는다
코드를 한 줄씩 따라가기 — 규칙 파일과 훅의 안내문
먼저 rules 파일 하나의 머리 부분이다.
---
description: Repository 인터페이스와 구현체 설계 규칙.
paths:
- "**/domain/**/*.java"
- "**/infra/**/*.java"
---
# Repository 설계 표준
- 조회 메서드 이름은 기술이 아니라 도메인 언어로 짓는다.
---두 줄 사이 — 규칙의 정보 칸이다. 본문이 아니라 Claude Code가 읽는 설정이다description:— 이 규칙이 무엇인지 한 줄 설명이다. skills의 설명과 달리 Claude가 이 규칙을 부를지 정하는 데 쓰이지 않는다. 사람이 읽고, Copilot·Codex용 파일을 자동으로 만들 때 쓴다paths:— 이 규칙이 걸리는 파일 경로 목록이다.domain폴더나infra폴더 안의.java파일을 Claude가 읽으면 이 규칙이 들어온다# Repository 설계 표준아래 — 규칙 본문이다. 지켜야 할 것을 한 줄씩 적는다. 예시 줄의 내용(Repository, 도메인 언어)은 이 글에서 몰라도 된다. 여기서 볼 것은 「위에는 경로, 아래에는 규칙」이라는 모양이다
다음은 Claude가 infra 폴더에 새 파일을 만들려 할 때 훅이 막으며 남기는 안내문이다.
[규칙 전달 경로 표준] 새 파일 src/main/java/com/x/order/infra/OrderMapper.java 에
걸리는 코딩 표준을 아직 읽지 않았다. 아래 파일을 Read 한 뒤 다시 쓴다:
.claude/rules/repository-design-standard.md
.claude/rules/domain-persistence-standard.md
...
같은 세션에서는 한 번 읽으면 다시 막지 않는다. 대화가 압축되면 다시 읽는다.
- 첫 두 줄 — 어떤 파일을 쓰려다 막혔는지와 이유다. 이 경로에 걸리는 규칙을 이번 대화에서 아직 안 읽었다
.claude/rules/...줄들 — 읽어야 할 규칙 파일이다.Read는 Claude Code가 파일을 여는 동작의 이름이다. Claude가 이 파일들을 Read 하면 규칙 본문이 대화에 들어온다- 마지막 줄 — 같은 대화(세션)에서는 한 번 읽으면 그다음부터 통과시킨다. 대화가 너무 길어지면 Claude Code가 앞부분을 요약해서 줄이는데(압축), 그러면 읽은 규칙도 요약으로 줄어드니 다시 읽게 한다
그래서 이렇게 한다
이 표준에는 규칙 파일이 없다.
이 표준은 자바 코드를 어떻게 쓸지가 아니라 규칙 파일을 어디에 둘지를 정한다. 그래서 Claude가 코드를 쓰면서 읽을 rules 파일이나 skills 파일이 이 표준 몫으로는 없다. 위 한 줄이 「규칙 파일이 없다」고 나오는 이유다. 정한 것은 이렇다.
- 「이 파일의 코드는 이래야 한다」는 rules에 두고, 그 규칙이 걸리는 경로를 파일 맨 위
paths:에 적는다 - 「이 일은 이 순서로 한다」는 skills에 둔다. 둘이 섞인 표준은 같은 표준 이름으로 rules 파일과 skills 파일을 하나씩 둔다. 예를 들어 스키마 마이그레이션 표준은
.claude/rules/schema-migration-standard.md와.claude/skills/schema-migration-standard/SKILL.md두 파일이 된다 - 새 파일을 만들 때, 그리고 터미널 명령으로 코드 파일을 만들거나 고칠 때는 훅이 막고, 그 경로에 걸리는 rules 파일을 Read 한 뒤에만 통과시킨다
- 「Read 했는가」는 이번 대화의 기록 파일로 확인한다. 대화가 압축되면 다시 읽게 한다
왜 이렇게 정했나
코드 규칙은 「파일 경로」가 걸어야 한다. DTO 규칙은 DTO 파일을 쓸 때 필요하다. Claude의 판단에 맡기면 안 여는 날이 생긴다. 그래서 표준 50개를 하나씩 갈랐다. 코드 규칙만 있는 36개는 rules로 옮기고, 작업 절차만 있는 5개는 skills에 남기고, 둘이 섞인 9개는 쪼개서 양쪽에 두었다(36 + 5 + 9 = 50). 이제 그 경로의 파일을 읽으면 규칙이 판단 없이 따라 들어온다.
작업 순서는 「하려는 일」이 걸어야 한다. 「커밋 직전에 멈춘다」는 어느 파일을 쓰느냐와 상관없다. 커밋하려 할 때 필요하다. 그래서 이런 절차는 skills에 남겼다.
rules에는 빈칸이 하나 있다 — 새 파일이다. 실제로 시험해 보니 rules는 Claude가 파일을 읽을 때만 들어왔다. 이미 있는 파일을 고칠 때는 문제가 없다. Claude Code는 파일을 고치기 전에 그 파일을 먼저 Read 하도록 정해져 있어서, 그때 규칙이 들어온다. 그런데 새 파일은 아직 없어서 읽을 것이 없다. 폴더 목록을 훑어보는 것만으로도 안 들어왔다. 그래서 새 파일을 만들 때만 훅이 막고, 걸리는 rules 파일을 읽게 한다.
터미널 명령도 막아야 했다. Claude는 파일을 다룰 때 Claude Code의 도구(Read·Write) 말고 터미널 명령(printf '…' >> 파일 같은 것)을 쓰기도 한다. 실제 프로젝트 사본에서 15번 시켜 보니 6번을 터미널로 했고, 그때는 규칙이 하나도 안 들어왔다. 도구를 거치지 않으니 규칙이 따라 들어올 계기가 없다. 그래서 훅이 터미널 명령을 보고 「어느 파일에 쓰는지」를 뽑아, 그 파일에 걸리는 규칙을 읽기 전에는 막게 했다. 고친 뒤 다시 시켜 보니 규칙을 안 읽고 파일이 바뀐 경우는 한 번도 없었다. 다만 터미널 명령은 쓰는 방법이 끝없이 많아서, 흔한 모양만 잡는다.
훅이 규칙 내용을 직접 건네지 않는 이유는 길이 제한 때문이다. 훅이 막지 않고 Claude에게 글을 덧붙여 건네는 방법도 있는데, 그 글은 1만 자까지다. infra 파일 하나에 걸리는 규칙만 4만 자를 넘는다. 실제로 1만 4천 자짜리 글을 건네 보니 Claude는 앞부분 2KB만 받고 나머지는 못 봤다. 2KB는 글자 수가 아니라 파일 크기 단위라, 한글만으로 채우면 700자 정도다. 1만 자의 10분의 1도 안 된다. 훅이 막으며 남기는 짧은 안내문은 이 제한에 걸리지 않을 만큼 짧다. 그래서 훅은 「이 파일들을 읽어라」만 말하고, 읽는 것은 Claude가 한다.
「읽었는지」는 대화 기록으로 확인한다. 훅은 이번 대화가 적히는 기록 파일을 열어, 그 rules 파일을 실제로 읽은 기록이 있는지 본다. 「한 번 막고 다시 쓰면 통과」로 하면 안내문을 무시하고 바로 다시 써도 통과되기 때문이다.
걸리는 경로도 다시 맞췄다. 예전 Copilot용 파일에 적힌 경로를 그대로 옮기면 어긋나는 곳이 있었다. 화면(프론트엔드) 코드 규칙 9개는 「모든 파일」에 걸려 있어서, 자바 파일을 쓸 때도 화면 규칙을 읽게 되어 있었다. 그래서 .js·.css 같은 화면 파일로 좁혔다. 반대로 규칙이 정하는 파일이 경로에서 빠진 곳 두 군데는 채웠다.
대가도 있다. 자바 코드는 역할별로 폴더를 나눈다 — api(요청을 받는 코드), domain(업무 규칙), infra(DB처럼 바깥과 닿는 코드). 이런 폴더를 계층이라고 부른다. 새 파일을 처음 만들 때마다 아직 안 읽은 규칙이 걸리는 계층에서 한 번씩 멈추고, infra라면 규칙 파일 21개를 읽는다. 시간과 비용이 든다. 그래도 그 내용이 바로 「쓰기 전에 알아야 하는 규칙」이라 줄일 대상이 아니라고 봤다.
다른 AI 도구도 같은 원본을 쓴다. 팀에서는 Claude 말고도 GitHub Copilot과 Codex라는 AI 코딩 도구를 쓴다. Copilot에는 처음부터 「경로에 맞춰 규칙을 싣는」 기능이 있어서 규칙 파일을 따로 두었는데, 사람이 손으로 요약해 오다가 네 곳에서 조건이 빠져 있었다. 이제는 rules에서 자동으로 만든다(작업 절차만 있는 표준 5개는 예외로 손으로 둔다). Codex는 경로로 규칙을 거는 기능이 있는지 아직 확인하지 않아서, 지금은 rules와 skills를 합쳐 자동으로 만든 설명서로 받는다. 세 도구 모두 원본은 .claude/rules와 .claude/skills 하나다.
더 보기
- 규칙 전달 경로 표준 — 검토한 안 전부와 버린 이유, 실측 표
- 표준 동기화 표준 — 규칙이 여러 벌로 퍼질 때 원본 하나에서 생성하는 이유
- 커밋 대기 표준 — 훅이 「막기」와 「묻기」를 어떻게 가르는지
자신만의 철학을 만들어가는 중입니다.
댓글남기기