CLAUDE.md 잘 쓰는 방법 | 규칙을 적어도 안 지켜지는 이유

핵심 요약

CLAUDE.md 는 클로드 코드가 새 대화마다 자동으로 읽는 지시문 파일입니다. 짧게 두는 것이 맞지만 그것만으로는 부족했어요. 제 CLAUDE.md 는 141줄인데, 거기서 가리키는 인계 문서가 11만 자로 불어나자 앞부분만 읽고 멈추는 일이 생겼고 같은 측정을 두 번 연달아 놓쳤습니다. 실수 여섯 건을 되짚어 보니 고쳐진 셋은 전부 코드였고 안 고쳐진 셋은 전부 문서였습니다. 그래서 놓치면 못 되돌리는 것만 골라 코드로 옮겼고, 지난 실패를 넣어 보니 실제로 잡아냈습니다.

CLAUDE.md 가 하는 일 — 새 대화마다 자동으로 읽히는 파일

클로드 코드를 쓰다 보면 대화가 길어집니다. 그러다 새 창을 열면, 어제까지 쌓아 둔 이야기가 통째로 사라져요. 어디까지 했는지 처음부터 다시 설명해야 합니다.

그걸 막으라고 있는 것이 CLAUDE.md 입니다. 작업 폴더에 이 이름으로 파일을 두면, 클로드 코드가 새 대화를 열 때마다 알아서 읽습니다. 말하자면 매번 되풀이하기 싫은 것을 적어 두는 자리예요.

그래서 다들 여기에 규칙을 적습니다. 저도 그랬고요. 그런데 적는다고 지켜지지는 않았습니다. 그 이야기를 하려고 합니다.

먼저 하나 구분해 두겠습니다. 이 글에는 파일이 둘 나옵니다. 매번 읽히는 CLAUDE.md 가 하나이고, 거기서 「자세한 것은 여기를 보라」고 가리키는 인계 문서가 다른 하나예요. 인계 문서는 보통 핸드오프라고 부릅니다. 일을 넘겨받는 사람에게 건네는 문서라는 뜻이고, 영어 handoff 를 그대로 읽은 말이에요. 제 CLAUDE.md 는 지금 141줄입니다. 짧게 두려고 일부러 그랬고요. 문제는 그 짧은 파일이 가리키는 쪽에서 터졌습니다.

제가 막힌 자리 — 대화가 끊기면 사라지는 맥락

저는 워드프레스 사이트 하나를 고쳐 나가는 일에 클로드 코드를 쓰고 있습니다. 매일 아침 점검을 돌리고, 글을 올리고, 검색 반영을 확인하는 일이에요.

문제는 이런 일이 며칠에 걸쳐 이어진다는 데 있습니다. 예를 들어 오늘 방문자가 161명이라고 해도, 그 숫자 하나만 봐서는 는 건지 준 건지 알 수가 없어요. 어제가 153명이었다는 것을 같이 알아야 뜻이 생깁니다.

그런데 대화는 하루를 못 넘깁니다. 길어지면 요약되고, 요약되면 숫자가 흐려져요.

새 대화를 열 때마다 「어제 뭐 했더라」가 반복됐습니다.

첫 처방과 그 끝 — 인계 문서 11만 자

처음 떠올린 답은 누구나 떠올리는 그것이었어요. 문서를 쓰자.

CLAUDE.md 자체는 짧게 뒀습니다. 매번 읽히는 파일이라 길면 그만큼 매번 값을 치르니까요. 대신 자세한 것을 인계 문서로 빼고, CLAUDE.md 에는 「그것부터 읽어라」 한 줄만 남겼습니다.

그 인계 문서가 지금 11만 자입니다. 원고지로 550장쯤 돼요.

여기서 이상한 일이 벌어졌습니다. 문서가 길어질수록 안 읽히기 시작한 겁니다. 정확히는 앞부분만 읽고 멈추는 일이 생겼어요. 한 번은 문서 앞쪽의 옛날 절만 읽고 일을 시작해서, 그 뒤 사흘쯤 되는 작업을 통째로 놓친 적도 있습니다.

⛔ 여기서 알게 된 것이 하나 있어요. CLAUDE.md 를 짧게 두는 것만으로는 부족합니다. 그 파일이 가리키는 곳이 길면, 짧게 둔 보람도 같이 없어집니다. 가리키기만 하고 안 읽히면 안 적은 것과 같으니까요.

안 읽힌 증거 — 날짜가 남은 실패 둘

막연한 느낌이 아닙니다. 날짜가 남아 있습니다.

저는 검색 반영이 얼마나 빨리 되는지 재고 있었어요. 글을 올린 날부터 며칠 만에 검색에 들어오는지 세는 일이라, 중간에 하루라도 거르면 판정이 안 됩니다.

9월 12일에 그 점검을 걸렀습니다. 문서에는 「거르지 마라」가 분명히 적혀 있었어요. 적혀 있었는데도 걸렀습니다. 이틀인지 사흘인지 가리는 자리였는데 그걸 놓쳤습니다.

두 번째는 9월 14일입니다. 이번엔 거르지 않았어요. 대신 하지 말았어야 할 일을 했습니다. 자동 통보를 이미 넣어 둔 글에 손으로 한 번 더 요청을 넣은 거예요. 둘이 섞이는 바람에 어느 쪽 덕인지 알 수 없게 됐습니다.

이번엔 문서 탓도 아니었습니다. 「하지 마라」를 적을 자리가 아예 없었거든요. 문서에는 할 일만 적게 돼 있었습니다.

같은 측정을 두 번 연달아 놓쳤고, 원인은 서로 달랐습니다.

실수 여섯 건의 갈래 — 코드가 고친 셋, 문서가 못 고친 셋

여기서 기분으로 판단하지 않으려고, 그동안 남긴 기록을 열어서 실수를 하나씩 헤아려 봤습니다. 여섯 건이 나왔어요.

고쳐진 것 셋은 이랬습니다.

글을 올린 뒤 검색 요청을 빠뜨리던 실수에는 요청을 대신 넣어 주는 명령을 만들었습니다. 그 뒤로 나간 글 두 편은 기록을 되짚어 보니 빠짐없이 들어가 있었어요. 확인한 것은 거기까지입니다.

확인하지 않은 것을 확인한 것처럼 쓰던 버릇에는 검수를 글마다 자동으로 돌리게 했습니다. 첫 실전에서 세 군데를 잡았고 셋 다 진짜였어요. 그중 하나가 「서버 응답 속도도 그대로고요」였는데, 확인해 본 적이 없는 문장이었습니다.

서버 반영을 빠뜨려도 「맞다」고 나오던 것은 서버 쪽을 같이 확인하게 고쳤습니다. 고친 뒤 한 번 돌려서 서버와 이 컴퓨터가 맞는 것을 봤어요.

안 고쳐진 것 셋은 위에서 말한 두 건과, 문서가 낡아서 틀린 순서를 시킨 한 건입니다. 세 번째는 글을 올린 뒤 손볼 곳이 네 군데인데 문서에는 세 곳으로 적혀 있던 일이었어요. 그대로 따르면 한 곳을 통째로 빠뜨립니다.

여기서 갈래가 뚜렷해졌어요.

고쳐진 것은 전부 코드였고, 안 고쳐진 것은 전부 문서였습니다.

옮긴 것 — 문서가 아니라 코드

그래서 문서를 더 쓰지 않기로 했습니다. 대신 놓치면 못 되돌리는 것만 골라서 코드로 옮겼어요.

원래 저에게는 상태를 확인해서 보여 주는 명령이 하나 있었습니다. 오늘 날짜, 지금까지 올린 글, 아침 점검을 했는지 같은 것을 한 화면에 뿌려 주는 도구예요.

그 도구는 지금 어떤지 보여 주기만 했습니다. 오늘 꼭 해야 하는 일이 있어도 말해 주지 않았고, 하면 안 되는 일을 하려고 해도 말리지 않았어요. 말하자면 온도계였지 알람이 아니었습니다.

여기에 관문을 얹었습니다. 날짜가 박힌 약속을 문장이 아니라 항목으로 적게 하고, 그 명령이 다른 무엇보다 먼저 찍게 했어요.

{"when": "2026-09-16", "what": "예약 글 발행 처리",
 "why": "반영 속도를 확인할 마지막 기회",
 "must": ["자동 통보 넣기", "검색 요청 — 사람이 할 것"],
 "never": ["손으로 중복 요청"]}

중요한 것이 never 입니다. 「하지 마라」를 적을 자리를 만든 거예요.

⛔ 다만 여기는 정직하게 적어야겠습니다. never 는 코드가 막아 주는 것이 아닙니다. 맨 위에 먼저 띄워 줄 뿐이에요. 지키는 것은 여전히 읽는 쪽의 몫입니다. 달라진 것은 그 한 줄이 11만 자 속에 묻혀 있다가 첫 화면 맨 위로 나왔다는 것뿐이고요.

어두운 터미널 화면. 오늘 할 일 아래에 해야 할 것 두 줄과 하지 말 것 한 줄이 나오고, 그 아래 놓쳤다는 표시와 사흘 지났다는 안내문
왼쪽 위가 오늘 걸린 약속이고, 맨 아래가 사흘 전에 놓친 것입니다.

그리고 하나 더 얹었습니다. 날짜가 지났는데 안 했으면 「놓쳤다」고 말하게 했어요. 지금까지는 놓쳐도 아무도 알려주지 않았거든요.

여기서 한 가지를 조심했습니다. 했는지 안 했는지를 코드가 직접 재게 했어요. 그날 점검 기록이 실제로 남아 있는지, 그 글이 실제로 공개됐는지를 자기가 봅니다. 왜 그래야 하는지는 뒤에서 다시 말씀드릴게요.

시험 — 갈래 아홉 개

고쳤으면 그 자리에서 돌려 봐야 합니다. 잘 되는 경우만 보고 넘어가면 다음 날 아침에 죽어 있는 일이 생기거든요. 그래서 안 되는 경우까지 흉내 내서 아홉 가지를 시험했습니다.

기록이 없는 날, 기록이 있는 날, 아직 안 나간 글, 이미 나간 글, 확인할 방법이 없는 경우, 사람이 「했음」을 적어 둔 경우, 날짜가 깨진 경우, 설정 파일이 깨진 경우, 약속이 아예 없는 경우입니다.

아홉 가지 모두 뜻대로 움직였어요. 이 일의 값은 첫 번째에 있었습니다. 9월 12일을 넣어 보니 실제로 「놓쳤다」고 찍었거든요. 그때 이것이 있었으면 그 판정을 안 놓쳤습니다.

⛔ 그런데 이 아홉 가지는 전부 「빠뜨린 것을 알아채는가」를 본 것입니다. 「하지 말라는 것을 실제로 막는가」는 시험하지 않았어요. 앞에서 적었듯 그건 코드가 막는 자리가 아니니까요. 그러니까 9월 12일 쪽은 시험을 통과했고, 9월 14일 쪽은 아직입니다.

여기까지가 제 윈도우 환경에서 직접 돌려 본 것입니다.

그대로 쓰실 분을 위해 — 파일 둘과 명령 한 줄

제가 쓰는 것은 사이트 사정이 섞여 있어서 그대로 드리기 어렵습니다. 대신 뼈대만 남긴 것을 아래에 두겠습니다. 이 자리에서 직접 돌려 본 것이고, 잘 안 되는 경우까지 넣어서 시험했어요.

파일은 둘입니다. 약속을 적어 두는 promises.json 과, 그것을 읽어서 보여 주는 gate.py 예요.

둘 다 CLAUDE.md 와 같은 폴더에 둡니다. 클로드 코드를 열 때 들어가는 그 작업 폴더 맨 위예요. 파이썬만 있으면 되고 따로 깔 것은 없습니다. 파이썬이 있는지는 이렇게 확인하시면 됩니다.

python --version

3.9 이상이면 그대로 됩니다. 폴더는 이런 모양이 됩니다.

내-작업-폴더/
  CLAUDE.md          ← 원래 있던 것
  gate.py            ← 새로 만든다
  promises.json      ← 새로 만든다
  logs/              ← 뒤에서 설명합니다

약속을 적는 파일 — promises.json

[
 {"when": "2026-09-16",
  "what": "예약 글 발행 처리",
  "why": "반영 속도를 확인할 마지막 기회",
  "must": ["자동 통보 넣기", "검색 요청 넣기"],
  "never": ["손으로 중복 요청"],
  "check_file": "logs/{when}.json"}
]
약속을 적어 둔 JSON 파일 화면. when, what, why, must, never, check_file 여섯 칸
약속 하나를 적은 모습입니다. never 칸이 이 글의 핵심입니다.

칸이 여섯입니다. when 은 날짜, what 은 할 일, why 는 왜 중요한지, must 는 해야 하는 것들이에요. 나머지 둘이 핵심입니다.

처음이시라면 칸 셋만 적고 시작하셔도 됩니다. 나머지는 나중에 채우면 돼요.

[
 {"when": "2026-09-20", "what": "도메인 만료일 연장", "why": "넘기면 사이트가 멈춘다"}
]

이 셋만 있어도 그날이 오면 알려 주고, 지나면 「놓쳤다」고 말합니다. 저도 처음엔 이 모양으로 시작했어요.

never 는 하면 안 되는 일을 적는 자리입니다. 제가 9월 14일에 놓친 것이 이 자리가 없어서였어요. 할 일만 적게 해 두면, 하지 말아야 할 일은 아무 데도 안 남습니다.

check_file 은 했는지 코드가 스스로 확인하는 방법이에요. 저 자리에 적힌 파일이 실제로 생겨 있으면 「했다」로 봅니다. {when} 은 그 약속의 날짜로 바뀝니다. 위 보기에서는 logs/2026-09-16.json 이 있으면 한 것으로 봐요.

여기서 막히실 겁니다. 「나는 기록 파일 같은 걸 안 남기는데」 하고요. 저도 처음엔 그랬습니다.

답은 간단합니다. 일을 할 때 흔적이 남게 만드시면 됩니다. 그 일이 끝나는 자리에 이 한 줄을 더하세요.

mkdir -p logs && echo "{}" > logs/$(date +%F).json

윈도우 파워셸이면 이렇게 하시고요.

mkdir logs -Force; "{}" | Out-File "logs/$(Get-Date -f yyyy-MM-dd).json"

내용은 아무것도 아니어도 됩니다. 파일이 생겼는지만 봅니다. 손으로 「했음」을 적는 것과 뭐가 다르냐 하시면, 이건 일을 하면 저절로 남는다는 점이 다릅니다. 따로 기억할 것이 없어요.

⛔ 여기가 제일 중요한 대목입니다. 애초에 까먹어서 생긴 문제를, 까먹지 말라는 방법으로 풀 수는 없습니다. 그래서 되도록 check_file 을 적으시기를 권합니다.

코드에는 done 이라고 손으로 적는 길도 남겨 뒀어요. 확인할 방법이 마땅치 않은 일도 있으니까요. 다만 그건 마지막 수단입니다. 그 길로 가면 제가 원래 겪던 자리로 돌아갑니다.

보여 주는 파일 — gate.py

# -*- coding: utf-8 -*-
"""날짜가 박힌 약속을 다른 무엇보다 먼저 보여 준다."""
import json
import sys
from datetime import date
from pathlib import Path

sys.stdout.reconfigure(encoding='utf-8')
HERE = Path(__file__).resolve().parent
TODAY = date.today()


def load():
    """(약속들, 오류) 를 준다. 못 읽은 것과 비어 있는 것은 다르다."""
    f = HERE / 'promises.json'
    if not f.exists():
        return None, f'약속 파일이 없다 — {f.name} 을 만들어라'
    try:
        return json.loads(f.read_text(encoding='utf-8')), ''
    except (ValueError, OSError) as e:
        return None, f'약속 파일을 못 읽었다 — {e}'


def done(p):
    """했는지 코드가 직접 확인한다. 확인할 방법이 없으면 사람이 적은 것을 본다."""
    mark = p.get('check_file')
    if mark:
        return (HERE / mark.replace('{when}', p['when'])).exists()
    return True if p.get('done') else None


def main():
    rows, err = load()
    if err:
        print(err)
        print('«약속 없음»이라는 뜻이 아니다. 파일부터 고쳐라')
        return 1

    hit = False
    for p in rows:
        try:
            gap = (date.fromisoformat(p['when']) - TODAY).days
        except (ValueError, KeyError, TypeError):
            print(f'날짜를 못 읽어 건너뛴다 — {p.get("what", "(이름 없음)")}')
            continue
        if gap == 0:
            head = '[오늘]'
        elif 1 <= gap <= 2:
            head = f'[{gap}일 뒤]'
        elif gap < 0 and done(p) is not True:
            head = f'[놓쳤다 — {-gap}일 지남]'
        else:
            continue
        hit = True
        print(f'{head} {p.get("what", "")}')
        if p.get('why'):
            print(f'    왜: {p["why"]}')
        for x in p.get('must') or []:
            print(f'    해야 할 것 — {x}')
        for x in p.get('never') or []:
            print(f'    하지 말 것 — {x}')
    if not hit:
        print('오늘 걸린 약속 없음')
    return 0


raise SystemExit(main())

CLAUDE.md 에 적을 한 줄

마지막으로 CLAUDE.md 맨 위에 이 한 줄을 둡니다.

## 시작할 때
1. 다른 것을 읽기 전에 이것부터 돌린다:  python gate.py

돌리면 위에서 보신 그 화면이 나옵니다.

그런데 클로드가 이 한 줄을 진짜 지키느냐가 궁금하실 거예요. 제 경우는 지킵니다. 새 대화를 열면 다른 것을 읽기 전에 이 명령부터 돌리고, 화면에 뜬 것을 읽고 시작해요.

다만 이 글 앞부분에서 말씀드린 그 일이 여기서도 똑같이 적용됩니다. CLAUDE.md 가 짧아야 지켜집니다. 이 한 줄이 스무 번째 줄쯤에 묻혀 있으면 그냥 지나갑니다. 맨 위 첫 항목에 두세요.

제대로 됐는지 확인하는 법

만들고 나면 한 번 시험해 보시는 편이 좋습니다. 일부러 놓친 척 해 보는 거예요. 지난 날짜로 약속을 하나 적고 돌려 봅니다.

[
 {"when": "2026-01-01", "what": "시험용", "why": "놓침이 잡히나 보려고"}
]

[놓쳤다 — ○○일 지남] 시험용 이 나오면 제대로 된 것입니다. 확인하셨으면 그 줄은 지우세요.

날짜가 지났는데 기록이 없으면 「놓쳤다」와 며칠 지났는지를 같이 찍습니다. 지금까지는 놓쳐도 아무도 알려주지 않았는데, 그 자리가 메워졌어요.

어두운 터미널 화면. 약속 파일을 못 읽었다는 안내와, 약속 없음이라는 뜻이 아니니 파일부터 고치라는 안내문 두 줄
못 읽은 것과 없는 것은 다릅니다. 그 둘을 구분해서 말하게 고쳤습니다.

⛔ 하나 덧대면, 약속 파일이 깨졌을 때 「약속 없음」이라고 말하지 않게 해 두시는 편이 좋습니다. 처음 만들 때 제가 그렇게 해 뒀다가 고쳤어요. 못 읽은 것과 없는 것은 다른데, 그걸 같게 말하면 조용히 틀린 답이 됩니다. 관문을 만든 이유가 무색해지고요.

CLAUDE.md 에 남길 것과 뺄 것 — 기준 한 줄

그래서 CLAUDE.md 를 어떻게 쓰냐고 물으신다면, 제 기준은 이렇게 정리됐습니다.

코드가 대신 잴 수 있는 것은 적지 않습니다. 지금 글이 몇 편인지, 오늘 점검을 했는지 같은 것은 명령 한 줄이 그 자리에서 재 줍니다. 손으로 적어 둔 숫자는 반드시 낡아요. 낡은 숫자는 없느니만 못하고요.

놓치면 못 되돌리는 것은 문서에 적지 않습니다. 문서에 적으면 읽히기를 기다려야 하는데, 그 기다림에서 두 번 졌습니다. 이런 것은 코드가 맨 먼저 들이밀게 두는 편이 낫습니다.

그러면 CLAUDE.md 에는 뭐가 남느냐. 어디부터 봐야 하는지와, 무엇을 하면 안 되는지가 남습니다. 짧을수록 좋고요. 제 것은 지금 141줄입니다.

한 가지 덧대자면, CLAUDE.md 가 가리키는 곳도 같이 짧아야 합니다. 여기만 줄이고 옆 문서를 불려 놓으면 제가 겪은 자리로 돌아옵니다.

혹시 클로드 코드를 이제 시작하시는 분이라면 설치와 첫 설정부터 보시고, 요금이 걱정되시면 사용량 한도가 어떻게 도는지를 먼저 확인해 두시면 편합니다.

아직 모르는 것 — 첫 시험대는 9월 16일

솔직하게 적겠습니다. 이게 효과가 있는지는 아직 모릅니다.

9월 14일에 만들었습니다. 그날 낮에 같은 실수를 한 번 더 하고 나서요. 지난 실패를 넣어 보니 잡아내더라, 여기까지가 지금 말할 수 있는 전부입니다. 앞으로도 안 놓치는지는 아직 확인하지 못했습니다.

첫 시험대는 9월 16일입니다. 같은 종류의 측정이 그날 한 번 더 있거든요. 그때 관문이 제 몫을 하는지 보고, 결과가 어떻든 그대로 적어 두려고 합니다.

혹시 같은 문제로 답답하셨다면, 문서를 더 쓰기 전에 한 번 헤아려 보시길 권합니다. 지금까지 놓친 것들이 문서가 없어서 놓친 것인지, 있는데도 놓친 것인지요. 저는 후자였습니다.

자주 묻는 질문

CLAUDE.md 는 어디에 두나요?

클로드 코드를 실행하는 작업 폴더 맨 위에 CLAUDE.md 라는 이름으로 두면 됩니다. 새 대화를 열 때마다 알아서 읽습니다. 따로 켜 주는 설정은 없어요.

CLAUDE.md 는 길게 쓸수록 좋나요?

아닙니다. 짧을수록 낫습니다. 제 것은 141줄이에요. 다만 짧게 두는 것만으로는 부족했습니다. CLAUDE.md 가 「자세한 것은 여기를 보라」고 가리키던 인계 문서가 11만 자까지 늘어나자 앞부분만 읽고 멈추는 일이 생겼거든요. 가리키는 곳도 같이 짧아야 합니다.

그럼 CLAUDE.md 에는 무엇을 적나요?

어디부터 봐야 하는지와 무엇을 하면 안 되는지를 적습니다. 반대로 지금 글이 몇 편인지처럼 코드가 그 자리에서 잴 수 있는 것은 적지 않습니다. 손으로 적은 숫자는 반드시 낡기 때문입니다.

규칙을 적었는데도 안 지켜지면 어떻게 하나요?

놓치면 못 되돌리는 것만 골라서 코드가 맨 먼저 들이밀게 두는 쪽을 권합니다. 다만 코드가 행동을 막아 주지는 않습니다. 저는 날짜가 박힌 약속을 항목으로 적게 하고, 그 날짜가 지났는데 안 했으면 스스로 알려 주게 했습니다. 지키는 것은 여전히 읽는 쪽의 몫이고, 달라진 것은 그 한 줄이 첫 화면 맨 위로 나왔다는 점입니다.

효과가 검증됐나요?

아직 아닙니다. 만든 지 하루밖에 안 됐습니다. 지난 실패를 넣어 보니 잡아냈다는 것까지가 지금 확인된 전부이고, 앞으로도 안 놓치는지는 아직 확인하지 못했습니다.

관문 코드를 그대로 쓸 수 있나요?

본문에 뼈대만 남긴 것을 넣어 뒀습니다. promises.json 과 gate.py 두 파일을 같은 폴더에 두고 python gate.py 로 돌리면 됩니다. CLAUDE.md 맨 위에 그 명령을 먼저 돌리라는 한 줄을 넣어 두시면 새 대화마다 걸립니다.

기록 파일을 안 남기는데 check_file 을 어떻게 쓰나요?

일을 할 때 흔적이 남게 만드시면 됩니다. 그 일이 끝나는 자리에 mkdir -p logs && echo "{}" > logs/$(date +%F).json 한 줄을 더하시면 그날 날짜로 빈 파일이 생깁니다. 내용은 아무것도 아니어도 되고 파일이 생겼는지만 봅니다. 손으로 「했음」을 적는 것과 다른 점은 일을 하면 저절로 남아서 따로 기억할 것이 없다는 것입니다.

위로 스크롤