30줄로 직접 만들기 — 6강의 조립기를 코드로

이 교과서의 결론을 코드로 적으면 이만큼이다. Cloudflare Workers AI는 하루 10,000뉴런을 무료로 주고(Gemma 3 12B 기준 출력 약 20만 토큰 — 5,000자 회차로 60편쯤), 계정에 카드가 없어도 된다. 6강의 다섯 층이 각 줄에 그대로 있다.

// wrangler.jsonc 에 "ai": { "binding": "AI" } 한 줄. 배포는 npx wrangler deploy.
const LORE = [                                            // ③ 로어북
  { keys: ["하은"],   text: "하은 — 27세 기록보관소 직원. 왼눈이 회색. 거짓말을 못 견딘다." },
  { keys: ["인쇄소"], text: "서교동 인쇄소 — 1980년대 활판 인쇄소. 지하에 청사진 금고." },
];
const MEMORY = "3인칭 과거 「~다」 서술. 하은→도윤 반말, 도윤→하은 해요체. 장르: 도시 미스터리."; // ②
const NOTE   = "다음 장면은 200자 안. 대화 한 줄 이상. 결말을 서두르지 않는다.";               // ⑤

export default {
  async fetch(req, env) {
    const { story } = await req.json();                   // 지금까지의 원고
    const tail = story.slice(-8000);                       // ④ 본문 — 창에 맞춰 앞을 자른다
    const lore = LORE
      .filter(e => e.keys.some(k => tail.slice(-1500).includes(k)))  // 끝 1,500자만 훑는다 (7강)
      .map(e => e.text).join("\n");
    const messages = [
      { role: "system", content: `당신은 이 소설의 공동 저자다. 이어서 쓴다.\n${MEMORY}\n${lore}` }, // ①+②+③
      { role: "user",   content: `${tail}\n\n[작가 노트: ${NOTE}]\n\n(이어서)` },                // ④+⑤
    ];
    const out = await env.AI.run("@cf/google/gemma-3-12b-it", { messages, max_tokens: 400, temperature: 1.0 });
    return Response.json({ next: out.response });
  }
};
  • 모델 ID와 뉴런 단가는 Workers AI 문서의 모델 목록에서 다시 확인해야 한다. 목록이 자주 바뀐다. gpt-oss-20b가 뉴런은 더 싸지만 12강에서 본 대로 산문이 약하다.
  • 13강의 어미 검사는 out.response를 받은 다음 정규식 한 줄로 붙인다. 어긋나면 한 번 더 부른다. 그게 14강의 "배수"다.
  • 요약(8강)을 붙이고 싶으면 MEMORY를 상수 대신 KV에 두고, 열 장면마다 모델에게 갱신시킨다. 여기까지 하면 크랙의 스토리 화면과 구조가 같아진다.
서비스가 파는 건 이 30줄에 화면과 결제를 붙인 것이다. 이걸 읽을 수 있으면 어느 서비스의 한계도 읽을 수 있다.

브루니가 적는다

색을 바꾸며 숨는 카멜레온이다. AI 와 같이 만들며 걸린 곳을 한 편씩 적는다. 같은 데서 두 번 걸리지 않으려고 쓰는 기록이다.

AI 소설 표지 · 전체 20강 →