원본 소설·정리한 설정·꺼내 쓰는 저장소, 3단계로 나눈다
소설 전체를 AI의 입력창(컨텍스트 창, AI가 한 번에 읽을 수 있는 분량)에 한꺼번에 밀어 넣지 않는다. 그러면 분량이 넘쳐 앞부분부터 잊어버린다. 대신 소설을 분석해 뽑아낸 정리된 핵심 사실만 폴더에 파일로 적어 둔다. 그 폴더를 프로젝트 단위 사실로 memory-bank에 동기화(sync, 폴더 내용과 저장소 내용을 같게 맞추는 일)해 둔다. 나중에 그림·대사를 만드는 순간 search_facts라는 검색 도구로
그때 필요한 사실만 골라 꺼내 온다. 원본 소설은 계속 저장소 밖에 남는다.
원본 소설은 저장소 밖에
가공하지 않은 원본 소설 파일은 --source 옵션(빌더 프로그램에 원본 위치를 알려 주는 실행 인자)으로 파일 위치(전체 경로)만 알려 준다. 파일 자체는 복사하지 않는다. 프로젝트 폴더 안의 source/·uploads/·private/ 폴더는 git(파일 변경 이력을 관리하는 도구) 추적에서 제외한다. memory-bank에도 올리지 않는다.
정리한 설정은 폴더에
소설 한 편마다 폴더 하나(memory-bank/novels/{novel_id}/)를 둔다. 확정된 이야기 사실·인물 설정·세계관·그림체 고정값을 텍스트 파일로 쌓아 둔다. 사람이 직접 읽고 고칠 수 있는 형태다. 무엇이 언제 바뀌었는지는 변경 기록 장부(ledger)에 남긴다.
꺼내 쓰는 저장소는 memory-bank에
동기화 스크립트(폴더 내용을 memory-bank로 옮겨 적는 작은 프로그램)가 이 폴더 내용을 프로젝트 단위 사실로 memory-bank에 올린다. 이미 있으면 갱신하고 없으면 추가한다. memory-bank는 MCP(AI를 외부 도구·저장소에 연결하는 표준 규약)로 붙는다. 그림 콘티(컷 순서와 구도를 미리 그린 설계도)를 짜거나 이미지를 그리는 순간 search_facts / trace_fact 같은 조회 도구로 필요한 사실만 꺼내 온다.
원본 소설 → 빌더 → memory-bank 저장소 → 사용처로 흐른다
novel-builder.py라는 빌더 프로그램이 원본 소설을 잘게 나눠 분석하고,
memory-bank/novels/{novel_id}/설정 폴더를 채운 뒤,
novel-memory-bank-mcp-sync.mjs라는 동기화 프로그램이 그 내용을 memory-bank에 저장한다. 이미 있으면 갱신하고 없으면 추가한다.
저장된 사실을 실제로 쓰는 곳은 네 군데다. 그림 콘티 짜기(storyboard), 말풍선에 글자 얹기(lettering), 그림체 고정값 맞추기(visual seed), 앞뒤 설정이 어긋나지 않는지 검사하기(continuity)다.
빌더 프로그램이 소설을 다섯 단계로 처리한다
extract_title → extract_characters → extract_chapters 순서로 제목·등장인물·챕터를 뽑아 원본 소설을 분해한다. 이 셋은 빌더 프로그램 안의 추출 함수 이름이다. 그다음 미리 정의해 둔 인물·세계관 정보와 합쳐, build_* 단계(설정 파일을 조립하는 함수 묶음)가 설정 데이터를 만든다. 이때 그림체 고정값(seed, 이미지 생성기가 같은 그림을 다시 내도록 고정하는 숫자)은 같은 입력이면 늘 같은 값이 나오도록 계산한다.
마지막으로 run_sync라는 함수가 동기화 프로그램을 불러 memory-bank에 저장한다. 이미 있으면 갱신하고 없으면 추가한다.
설정 영역 10개가 각각 memory-bank 저장 주소 하나에 대응한다
각 영역은 딱 한 가지 역할만 맡는다. 확정된 사실은 canon.md에,
무엇이 언제 바뀌었는지는 continuity-ledger.md에,
아직 확실하지 않은 추측은 research/analysis-log.md에 나눠 적는다. memory-bank 안의 저장 주소(네임스페이스, 사실을 찾아가는 이름표)는 “영역 이름 + 항목 고유 ID”로 자동으로 정해진다. 아래 표의 마지막 열이 그 주소 규칙이고, 중괄호 자리에는 항목마다 다른 값이 들어간다. 인물이면 인물 고유번호(char_id), 세계관 항목이면 항목 고유번호(entity_id)가 그 자리에 들어가고, 그림체 고정값은 한 파일(image-seeds.json)에 모아 둔다.
| Area | Path | Role | MCP namespace |
|---|---|---|---|
| manifest | manifest.json | 소설 ID·버전·소유자·분석 진행 상태·설정 목차 | novel-toon:{id}:manifest:root |
| canon | context/canon.md | 한번 정하면 안 바꾸는 이야기 사실. 분석 근거가 있을 때만 추가. 사실마다 고유번호(fact_id) | novel-toon:{id}:canon:{fact_id} |
| timeline | context/timeline.md | 챕터·회차·시대·실제 날짜 단위로 정리한 사건. 사건마다 고유번호(event_id) | novel-toon:{id}:timeline:{event_id} |
| ledger | context/continuity-ledger.md | 결정 사항·설정 소급 변경(retcon)·모순·수정 이력. 결정마다 고유번호(decision_id) | novel-toon:{id}:ledger:{decision_id} |
| unresolved | context/unresolved-questions.md | 아직 못 푼 조사 질문·애매한 부분. 질문마다 고유번호(q_id) | novel-toon:{id}:unresolved:{q_id} |
| characters | characters/{char_id}.json | 성격·목표·두려움·말투·외모 기준·인물 관계 | novel-toon:{id}:character:{char_id} |
| world | world/{eras,settings,culture} | era · setting · culture · technology · magic · politics | novel-toon:{id}:world:{entity_id} |
| visual | visual/style-bible.md + image-seeds.json | 그림체 기준·이미지 고정값·사진 고정값·제외할 요소 지시(negative prompt). 고정값마다 고유번호(seed_id) | novel-toon:{id}:visual:{seed_id} |
| production | production/episodes/* · panels/* | 회차 기획·그림 콘티(storyboard)·컷(panel) 정보. 회차마다 고유번호(ep_id) | novel-toon:{id}:production:{ep_id} |
| research | research/{analysis-log,source-notes} | 분석 진행 기록·확정 전 추측. 메모마다 고유번호(note_id) | novel-toon:{id}:research:{note_id} |
| source · uploads · private | source/ · uploads/ · private/ | 가공 전 원본 소설·이미지 등 참고 파일·비공개 자료 | — 추적·저장 안 함 — |
저장은 늘 같은 결과로, 조회는 프로젝트 범위 안에서만
동기화는 몇 번을 돌려도 결과가 같다. 이런 성질을 멱등(idempotent, 여러 번 실행해도 결과가 한 번 실행한 것과 같음)이라 부른다. 폴더 상태가 같으면 저장되는 사실도 똑같다. 꺼내 올 때는 memory-bank의 조회 도구 4개(검색·근거 추적·관계 탐색·통계)로 필요한 부분만 조회한다. 저장해 둔 설정 전체를 통째로 가져오지 않는다.
# 1) 원본 소설 → 설정 폴더 생성 + memory-bank 동기화 python3 scripts/novel-builder.py \ --project-root . \ --source /Users/me/blood-inheritance.md \ --novel-id blood-inheritance \ --sync --json # 2) 완료 검사 — 통과 못하면 “완료” 선언 금지 python3 scripts/validate-novel-builder.py \ --project-root . \ --source /Users/me/blood-inheritance.md \ --novel-id blood-inheritance \ --require-mcp-sync --json # 3) 웹툰 만들 때 — search_facts 도구로 필요한 사실만 조회 project=/Users/jung-wankim/Project/novel-toon query="novel_id=blood-inheritance character=han-seoyun visual seed"
설정이 조금씩 어긋나는 것을 막는 운영 규칙
오래 연재할수록 가장 뼈아픈 실패는 설정 표류(drift)다. 인물 설정과 그림체 고정값이 회차를 거치며 조금씩 어긋나는 현상이다. 규칙은 간단하다. 무언가 바뀌면 변경 기록 장부(ledger)에 적고, 가공 전 원본은 이 저장소에 들이지 않는다. 아래 네 묶음 가운데 비공개 경계는 강제 규칙이다. 카드 제목에 붙은 영문 표시가 그 뜻으로, 사람이 기억해서 지키는 권고와 달리 git 설정과 동기화 프로그램이 기계적으로 막는다.
인물·그림체가 어긋나지 않게
- 인물 설정이나 이미지 고정값을 바꾸면 반드시
continuity-ledger.md(변경 기록 장부 파일)에 한 줄 남긴다 - 고정값(seed)은
stable_seed(parts...)함수(입력 조각들로 늘 같은 번호를 만들어 내는 계산식)로 계산해 만든다. 같은 입력이면 다시 돌려도 같은 값이 나온다 - 고정값에
locked=true(잠금 표시)가 걸린 항목은 장부 기록 없이 못 바꾼다 - 그림체 지침(style-bible, 그림체 기준을 적은 문서)을 바꾸면 이후 모든 회차를 다시 검토하게 된다
확실한 것과 추측을 구분
- 근거로 확정된 사실 →
canon.md - 분석 중인 가설 →
research/analysis-log.md - 아직 답 못 낸 질문 →
unresolved-questions.md - 추측을 확정 사실(canon)로 올리려면 근거 인용이 반드시 필요하다
privacy boundary (HARD)
memory-bank/novels/*/source/·uploads/·private/·visual/references/*폴더는 git 추적에서 제외한다- 가공 전 원본 소설은 저장소에 올리지 않는다 (동기화 프로그램의 설정값
sync_raw_manuscripts: false) - 사람이 정리한 요약(확정 사실·인물·세계관·그림체 정보)만 올린다
- 비공개 이미지는 파일이 아니라 ID(식별 번호)로만 가리킨다
작품끼리 섞이지 않게 분리
- 소설 한 편에 폴더 하나를 둔다. 여러 작품이 공유하는 인물·고정값 파일은 쓰지 않는다
- 저장 범위를
project(프로젝트 단위)로 고정한다. 다른 작품으로 설정이 새는 것을 막기 위해서다 - 저장 주소에
novel_id(소설 ID)를 반드시 넣는다 - 꺼내 올 때 검색어(쿼리)에도
novel_id=를 적어 주길 권장한다
그림·영상으로 나가기 전 지켜야 할 두 가지 약속
memory-bank에서 꺼낸 설정은 먼저 그림 콘티 데이터(storyboard, 컷마다 화자·대사·구도를 적은 설계 데이터)로 굳어진다. 그 뒤 아래 두 가지 약속을 지켜야만 이미지와 영상으로 나갈 수 있다.
한국 웹툰식 손글씨 말풍선 규칙
- 일반 문서·자막·UI(화면 버튼용)·세리프(획 끝에 꺾임이 있는) 서체는 금지한다. 한국 웹툰 손글씨 느낌만 쓴다.
- 말풍선 안에는 대사만 넣는다. 화자 이름·콜론·괄호·설명·부가정보는 넣지 않는다.
storyboard JSON(콘티 데이터를 담는 파일 형식으로, 컴퓨터가 읽기 쉬운 텍스트 규격이다)의 항목 가운데speaker는 화자 이름을 담아 두는 참고 항목이고, 말풍선에 실제로 그리는 것은text(대사) 항목의 값뿐이다.- 흰색 둥근 말풍선에 짧은 꼬리를 달고 여백을 넉넉히 둔다.
- 말풍선은 빈 공간에 놓는다. 얼굴·눈·중요한 손·핵심 소품 위에는 겹치지 않게 한다.
- 짧고 자연스러운 한국어 문장을 쓴다. 길면 한 말풍선 안에서 두 줄로 나눈다.
- 최종 한국어 글자는 영상 편집 도구(Remotion, 코드로 영상을 만드는 도구)로 그림 위에 얹는다. AI 이미지 생성에는 맡기지 않는다.
컷마다 화면이 달라야 한다는 규칙
- 컷(panel)을 2개 이상 만들 때는 각 컷마다 서로 다른 화면 특징(
visual_signature, 그 컷의 화면을 한 줄로 요약한 값)을 반드시 준다. - 이웃한 두 컷은 배경·카메라 거리·등장인물 조합·핵심 동작·감정 흐름 중 적어도 1가지는 달라야 한다.
- 연달아 나오는 컷에서 똑같은 “책상에 앉은 사무실” 구도를 반복하지 않는다.
- 한국어 대사는 영상 편집 도구(Remotion)로 말풍선을 얹는다. 이미지 생성 단계에서 글자를 직접 그리지 않는다.
- 영상으로 낼 때는 글자 없는 배경 이미지 위에 말풍선을 얹는 방식을 선호한다.