
Claude Code 작업이 중단되어도 재개할 수 있도록 만들기 ── CLAUDE.md와 STATE.md의 역할 분담
요약
Claude Code 작업 중 세션이 끊겨도 맥락을 유지하며 재개할 수 있는 방법론을 소개합니다. 정보를 변하지 않는 전제(CLAUDE.md)와 변하는 상황(STATE.md)으로 분리하고, SessionStart 훅을 통해 자동으로 문맥을 주입하는 기술적 구현 방법을 다룹니다.
핵심 포인트
- 정보를 변하지 않는 전제와 변하는 상황으로 분리하여 관리
- CLAUDE.md는 프로젝트의 목적과 제약 사항을 저장
- STATE.md는 진행 중인 작업과 다음 할 일을 실시간 업데이트
- SessionStart 훅을 사용하여 기동 시 자동으로 문맥 주입
- Windows 환경에서의 UTF-8 인코딩 설정 주의
무엇이 문제였는가
Claude Code에게 긴 작업을 맡기고 있으면, 도중에 세션이 끊깁니다. 컨텍스트 (Context)가 가득 차거나, 날짜가 바뀌거나, 단순히 닫아버리는 경우 등입니다.
재개하면 다음과 같은 상황이 발생합니다.
"이 프로젝트는 무엇을 하고 있나요?"
다시 설명해야 하는 것은 바로 나 자신입니다. 그것도 매번 말이죠. 작업이 커질수록 설명은 길어지고, 결국 설명하는 것이 귀찮아져서 작업 자체가 멈추게 됩니다.
저는 이 문제 때문에 한 번 프로젝트를 중단한 적이 있습니다. 이번에는 그 부분을 해결했기에, 그 구성을 작성해 보겠습니다.
결론: 정보를 "변하지 않는 것"과 "변하는 것"으로 나누기
저장 위치를 두 개로 나눕니다.
| 파일 | 내용 | 업데이트 빈도 |
|---|---|---|
CLAUDE.md | 변하지 않는 전제 (목적・제약・역할 분담・확인된 사실) | 방침이 바뀌었을 때만 |
STATE.md | 변하는 상황 (진행 중인 작업・다음에 할 일・중단 지점) | 작업할 때마다 |
CLAUDE.md는 Claude Code가 기동 시 자동으로 읽는 파일입니다. 여기에 "변하지 않는 것"만 둡니다.
STATE.md는 직접 준비하는 단순한 마크다운 (Markdown) 파일입니다. Claude 스스로가 작업할 때마다 내용을 새로 씁니다.
나누는 이유는 단순합니다. 섞어버리면 업데이트를 하지 않게 되기 때문입니다. 하나의 파일에 전제 조건과 상황을 함께 두면, 상황을 수정할 때마다 전제 조건을 다시 읽어야 하므로 점점 아무도 손대지 않게 됩니다.
STATE.md に 무엇을 적는가
최소한 이것만 있으면 재개할 수 있습니다.
## 진행 중인 작업
- 〇〇 구현. 3단계 중 2단계 완료. 다음은 △△ 검증부터
## 다음에 할 일 (판단 불필요・알아서 진행해도 좋음)
...
"진행 중인 작업"이 가장 중요합니다. 중단될 것 같을 때, 어디까지 끝났고 어디서부터 재개할지를 적습니다. 이곳이 비어 있으면 다음 세션은 결국 짐작만으로 시작하게 됩니다.
기동 시 자동으로 읽게 하기
STATE.md를 두기만 한다고 해서 Claude가 반드시 읽는 것은 아닙니다. 기동 시 강제로 문맥 (Context)에 넣습니다.
.claude/settings.json에 SessionStart 훅 (Hook)을 작성합니다.
{
"hooks": {
"SessionStart": [
...
훅 스크립트는 표준 출력 (Standard Output)으로 JSON을 하나 반환하기만 하면 됩니다.
print(json.dumps({"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": text, # 여기에 넣은 문자열이 문맥에 들어감
...
additionalContext에 넣은 문자열이 그대로 Claude의 문맥에 주입됩니다. STATE.md의 내용을 여기에 흘려보내면, 기동하는 순간 상황을 파악한 상태에서 시작할 수 있습니다.
저의 경우에는 STATE.md에 더해 외부 수치(액세스 수 등)도 API를 통해 가져와서, 이전과의 차이점을 함께 넣고 있습니다. 파일을 열자마자 "이전으로부터 무엇이 변했는지" 알 수 있는 상태가 됩니다.
구현 과정에서 겪은 3가지
1. 표준 출력의 문자 코드
Windows의 콘솔은 기본값이 cp932입니다. 일본어를 포함한 JSON을 그대로 출력하면 훅 측에서 읽을 수 없습니다.
sys.stdout.reconfigure(encoding="utf-8")
이것을 가장 먼저 호출합니다. 이것이 없으면 훅은 조용히 실패합니다 (|| true를 붙여두면 실패했다는 사실조차 알 수 없습니다).
2. 네트워크로 가져올 때의 처리
훅 안에서 외부 API를 호출한다면, 실패하더라도 세션을 망가뜨리지 않도록 합니다.
try:
data = fetch(url)
except Exception as e:
...
조용히 에러를 무시하면, 수치가 0인 것인지 가져오기에 실패한 것인지 구분할 수 없게 됩니다. 가져오지 못했다는 사실을 문맥에 적는 것이 중요합니다.
3. "아직 아무 말도 듣지 못함"이라고 명시하기
훅으로 주입한 문맥은 Claude 입장에서 사용자의 발언과 혼동될 수 있습니다. 주입하는 문자열 끝에 다음과 같이 적어두면 안정적이었습니다.
---
이 총괄은 자동으로 취득한 것. 사용자는 아직 아무 말도 하지 않음.
판단 대기 사항이 있다면 제시할 것. 없다면 다음 작업을 진행해도 좋음.
효과
세션이 끊겨도, 다음에 열자마자
- 이전 작업에서 무엇이 바뀌었는지
- 어디까지 완료되었는지
- 다음에 무엇을 해야 하는지
이 모든 정보가 갖춰진 상태로 시작됩니다. 다시 설명해야 하는 작업이 사라졌습니다.
구조 자체는 "파일 2개와 후크(Hook) 1개"입니다. 복잡한 것이 아닙니다. 핵심은 변하지 않는 것과 변하는 것을 분리한 것과, 업데이트를 인간의 기억에 의존하지 않는 것이라는 두 가지 포인트뿐입니다.
요약
- **
CLAUDE.md**에는 변하지 않는 전제 조건을, **STATE.md**에는 변하는 상황을 기록합니다. 두 가지를 섞으면 업데이트가 되지 않습니다. 중단될 것 같을 때는 "진행 중인 작업"에 재개 지점을 작성하세요. 이 부분이 비어 있으면 다음 작업이 길을 잃게 됩니다. SessionStart후크의 **additionalContext**를 통해 강제로 문맥(Context)에 삽입합니다. 단순히 놓아두기만 해서는 읽히지 않습니다. Windows 환경에서는sys.stdout.reconfigure(encoding="utf-8")설정을 잊지 마세요. 외부 데이터 취득에 실패하더라도 시스템을 망가뜨려서는 안 됩니다. 다만, 데이터를 가져오지 못했다는 사실은 문맥(Context)에 기록해야 합니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기