🤖 Claude 실행 지시서 — 영화 영어학습 자동화

← 내셔널 트레저 학습 페이지 예시 보러가기

이 문서를 Claude에게 주세요.
Claude가 알아서 다 합니다.

당신이 할 일은 딱 3가지.
나머지는 Claude가 Notion과 카카오톡까지 직접 연결해 자동화를 완성합니다.

👤 당신이 할 3가지

  • 영화 스크립트 PDF 준비
  • 계정 연결 (Notion + 카카오)
  • 터미널 명령어 2줄 실행

🤖 Claude가 하는 나머지

  • Notion DB 직접 생성
  • 큐 페이지 30일치 자동 생성
  • 매일 자동화 스케줄 등록
  • 카카오톡 연동·테스트
👤

친구(사용자)에게 — 먼저 읽으세요

이 문서를 어떻게 사용하는지

이 문서의 사용 방법 (30초)

  1. 아래 "사전 준비 3가지"를 완료합니다
  2. Claude.ai 채팅창을 열고, 이 HTML 파일을 첨부하거나 내용 전체를 붙여넣기합니다
  3. "이 가이드대로 처음부터 끝까지 실행해줘" 라고만 입력합니다
  4. Claude가 중간에 물어보는 것들에만 답변해 주면 됩니다
💡
Claude가 직접 Notion에 DB를 만들고, 카드를 생성하고, 자동화 스케줄까지 등록합니다. 당신은 파일을 제공하고 계정을 연결해 주기만 하면 됩니다. 코드를 이해하거나 직접 편집할 필요가 없습니다.

사전 준비 3가지 (Claude 실행 전에 완료)

🤖

Claude에게 — 실행 지침 (이 섹션부터가 Claude용입니다)

Claude는 아래 지침대로 순서대로 실행하세요
📌
Claude에게: 이 문서를 받았다면 다음 원칙을 따르세요 1. 아래 PHASE 순서대로 실행합니다.
2. 각 PHASE에서 사용자가 직접 해야 하는 것이 있으면 그것만 명확히 알려주고 기다립니다.
3. 나머지는 말하지 말고 직접 실행합니다.
4. 각 PHASE 완료 후 결과를 한 줄로 보고하고 다음 PHASE로 넘어갑니다.

PHASE 0 — 준비 상태 확인

🤖 Claude 실행

시작 전에 사용자에게 다음을 확인합니다:

Claude가 사용자에게 묻는 내용 ① Notion MCP가 Claude.ai Settings에 연결되어 있나요? ② PlayMCP(카카오톡)가 연결되어 있나요? ③ 영화 스크립트 PDF 파일이 준비되어 있나요? 파일 이름을 알려주세요. ④ Notion에서 DB를 만들 부모 페이지 이름을 알려주세요. (예: "홈", "MY WIKI" 등) → 모두 확인되면 PHASE 1로 진행합니다.

PHASE 1 — PDF에서 문장 추출

👤 사용자 1회 실행 필요

Claude가 추출 스크립트를 생성하고, 사용자는 딱 2줄만 터미널에서 실행합니다.

Claude 실행 절차 1. 사용자의 작업 폴더에 scripts/ 와 data/ 폴더 구조를 안내한다 2. 아래 추출 스크립트를 scripts/extract_dialogues.py 로 저장하도록 내용을 제공한다 3. 사용자에게 이렇게 안내한다:
  "터미널(또는 명령 프롬프트)에서 아래 2줄을 실행해 주세요:"
  pip install pdfplumber
  python scripts/extract_dialogues.py
4. 실행 결과(몇 개 문장 추출됐는지)를 붙여넣어 달라고 요청한다 5. data/script_clean.json 파일을 Claude에게 업로드해 달라고 요청한다 → JSON 파일을 받으면 PHASE 2로 진행
📎
추출 스크립트 (Claude가 이 내용을 사용자에게 제공) 아래 스크립트를 scripts/extract_dialogues.py로 저장합니다. PDF 경로만 실제 파일명으로 바꾸면 됩니다.
scripts/extract_dialogues.py — 이 내용을 그대로 파일로 저장
import pdfplumber, re, json
from pathlib import Path
from collections import Counter

ROOT = Path(__file__).resolve().parent.parent
PDF  = ROOT / "your-movie-script.pdf"   # ← 실제 PDF 파일명으로 변경
OUT  = ROOT / "data" / "script_clean.json"
OUT.parent.mkdir(exist_ok=True)

PAGE_HDR   = re.compile(r"[A-Z][a-z].*,\s*\d+/\d+/\d+")
CONTINUED  = re.compile(r"^\s*\d*\s*CONTINUED:?", re.I)
SCENE_RE   = re.compile(r"^\d+\s+(INT\.|EXT\.|INT/EXT|FADE)", re.I)
PAREN_RE   = re.compile(r"\([^)]*\)")
CONTD_RE   = re.compile(r"\(CONT'?D\)|\(O\.?S\.?\)|\(V\.?O\.?\)|\(MORE\)", re.I)
CHAR_MIN, DLG_MIN, DLG_MAX = 30, 20, 35
ABBREVS = ["Mr.","Mrs.","Ms.","Dr.","Sr.","Jr.","St.","Mt.","Co.","Inc.",
           "Ltd.","Prof.","Gen.","Lt.","Sgt.","U.S.","etc.","vs.","e.g.","i.e."]

def split_sents(text):
    p = text
    for a in ABBREVS: p = p.replace(a, a.replace(".",""))
    p = p.replace("--"," ").replace("...","")
    parts = re.split(r"(?<=[.!?])\s+(?=[A-Z\"'])", p)
    out=[]
    for s in parts:
        s=s.strip().replace("","...").replace("",".")
        s=re.sub(r"\s+"," ",s)
        if s and len(s)>=2: out.append(s)
    return out

def is_char(c):
    b=CONTD_RE.sub("",c); b=PAREN_RE.sub("",b).strip()
    if not b or len(b)>35 or not any(x.isalpha() for x in b): return False
    return not any(x.islower() for x in b) and not b.endswith(":")

raw=[]; cur_char=cur_scene=None; buf=[]
def flush():
    global buf
    if cur_char and buf:
        blk=re.sub(r"\s+"," "," ".join(buf).strip())
        if blk: raw.append((cur_char,cur_scene,blk))
    buf=[]

with pdfplumber.open(PDF) as pdf:
    for pg in pdf.pages:
        for line in (pg.extract_text(layout=True) or "").split("\n"):
            rs=line.rstrip(); c=rs.lstrip()
            if not c: flush(); cur_char=None; continue
            if PAGE_HDR.search(c) or CONTINUED.match(c): flush(); cur_char=None; continue
            ind=len(rs)-len(c)
            if SCENE_RE.match(c):
                flush(); cur_char=None
                cur_scene=re.sub(r"\s{2,}"," ",c); cur_scene=re.sub(r"\s+\d+\s*$","",cur_scene)
                continue
            if ind>=CHAR_MIN and is_char(c):
                flush(); n=CONTD_RE.sub("",c); cur_char=PAREN_RE.sub("",n).strip(); continue
            if cur_char and DLG_MIN<=ind<=DLG_MAX+5:
                cl=PAREN_RE.sub("",c).strip()
                if cl: buf.append(cl)
                continue
            flush(); cur_char=None
    flush()

sents=[]; sid=0
for ch,sc,blk in raw:
    for s in split_sents(blk):
        sid+=1
        sents.append({"id":sid,"char":ch,"scene":sc or "","text":s,"word_count":len(s.split())})

OUT.write_text(json.dumps(sents,ensure_ascii=False,indent=2),encoding="utf-8")
chars=Counter(s["char"] for s in sents)
print(f"✅ {len(sents)}개 문장 추출 완료 ({len(chars)}명 캐릭터)")
print(f"   약 {len(sents)//5}일치 학습 분량 (하루 5문장)")
print(f"   상위 캐릭터: {', '.join(f'{c}({n})' for c,n in chars.most_common(5))}")
print(f"   저장 위치: {OUT}")

PHASE 2 — Notion 학습 DB 생성

🤖 Claude가 직접 실행

사용자에게 묻지 않고 Claude가 Notion MCP를 사용해 직접 DB를 생성합니다.

Claude 실행 절차 1. Notion MCP로 사용자가 알려준 부모 페이지 아래에 DB를 생성한다   DB 이름: "🎬 [영화제목] Daily English"
DB 스키마 (반드시 이 구조로 생성): • 학습일 — Title (제목) • 날짜 — Date • Day # — Number • 문장 범위 — Text ("1-5" 형식) • 주요 인물 — Text • 장면 — Text • 상태 — Select (학습 전/gray, 학습 중/yellow, 완료/green, 복습 필요/red)
2. 생성된 DB ID를 메모해 PHASE 3, 4에서 사용한다 3. "Notion DB 생성 완료 (ID: xxx)" 한 줄 보고 후 PHASE 3 진행

PHASE 3 — 큐 페이지 30일치 생성

🤖 Claude가 직접 실행

업로드받은 script_clean.json을 파싱해 Notion에 30개 큐 페이지를 일괄 생성합니다.

Claude 실행 절차 1. script_clean.json에서 Day 1~30 (문장 id 1~150) 데이터를 파싱한다 2. 각 Day 그룹(5문장)에 대해 Notion 페이지를 생성한다
각 페이지의 구조: 제목: "Day 001 — Scene X (INT. LOCATION)" 속성: 학습일(제목), Day#(숫자), 문장 범위, 주요 인물, 장면, 상태="학습 전" 본문: 아래 형식의 코드블록 포함
본문 포맷: ## 📦 Raw Sentences (routine input) ```json {"day": N, "id_range": "X-Y", "sentences": [...5개 문장 객체...]} ``` --- ## 📋 학습 정보 - Day: N / 문장 범위: X-Y / 장면: ... / 주요 인물: ... _(분석 내용은 매일 08:00 KST에 자동 생성됩니다.)_ 3. 30개 페이지 생성 완료 후 "큐 페이지 Day 1~30 생성 완료" 보고 ※ 페이지가 너무 많으면 10개씩 나눠서 생성해도 됨

PHASE 4 — 매일 자동화 Routine 등록

🤖 Claude가 직접 실행

Claude.ai 클라우드 Routine을 생성해 매일 08:00 KST에 자동 실행되도록 설정합니다.

Routine 설정값 크론 스케줄: "0 23 * * *" (매일 23:00 UTC = 08:00 KST) 모델: claude-sonnet-4-6 (또는 현재 최신 Sonnet) MCP: Notion MCP + PlayMCP (카카오톡)
Routine 프롬프트 (아래 내용 그대로 사용): 매일 아침 영어 학습 카드를 만들고 카카오톡으로 발송한다. 절차: 1. Notion DB [PHASE 2에서 얻은 DB ID]에서 "상태" = "학습 전"이고 "Day #"이 가장 작은 페이지를 가져온다. 2. 페이지 본문의 ```json ... ``` 코드블록을 파싱해 sentences 배열(5개 문장)을 추출한다. 3. 각 문장(text)에 대해 아래 학습 카드를 작성한다: 🇰🇷 한국어 번역 (자연스럽게) 💬 회화 표현 — 이 패턴을 실제 대화에서 활용하는 예문 1개 📖 어휘 — 핵심 단어 2~3개 (품사 · 뜻 · 예문) 🔖 문법 포인트 — 이 문장의 핵심 문법 1개, 간결하게 4. 마지막에 추가: ✅ 오늘의 학습 체크리스트 (5문장 각각 체크박스) ✍️ 응용 예문 만들기 (오늘 배운 표현 중 하나로 본인 예문 작성) 5. 페이지 본문을 위 카드 내용으로 replace_content로 교체한다. "상태"를 "완료"로, "날짜"를 오늘 KST 날짜로 업데이트한다. 6. KakaoTalk MemoChat으로 발송한다: 제목: 🎬 오늘의 영어 학습 — Day N / 293 내용: [동기부여 한 줄] 오늘 5문장이 준비됐습니다! 👉 [페이지 링크] "학습 전" 페이지가 없으면: 카카오톡으로 "📭 영어 학습 큐가 비었습니다. 새 배치를 추가해 주세요!" 발송.
Routine 생성 완료 후 ID를 사용자에게 알려준다

PHASE 5 — 동작 검증 (수동 트리거)

🤝 Claude 실행 + 사용자 확인
Claude 실행 절차 1. 방금 만든 Routine을 수동으로 1회 즉시 실행한다 2. 실행이 완료되면 사용자에게 다음을 확인해 달라고 요청한다:   "카카오톡에 알림이 왔나요? (링크도 열려나요?)"   "Notion Day 1 페이지의 상태가 '완료'로 바뀌었나요?" 3. 두 가지 모두 확인되면 셋업 완료를 알린다:   "✅ 셋업 완료! 내일부터 매일 08:00 KST에 자동으로 카카오톡이 옵니다.    30일 후(Day 30 소진 시점)에 큐를 보충해야 합니다.    큐가 소진되면 카카오톡으로 '큐가 비었습니다' 알림이 자동으로 옵니다."
🔄

30일마다 — 큐 보충 방법

큐가 소진되면 Claude에게 이렇게 요청하세요

"큐가 비었습니다" 카카오톡 알림을 받으면, Claude.ai 채팅창에 아래 메시지를 보내세요.

사용자가 Claude에게 보내는 메시지 (30일마다) 영어 학습 자동화 큐가 소진됐어.
Notion DB ID는 [DB_ID]야.
script_clean.json을 첨부할게.
Day [N+1]부터 Day [N+30]까지 큐 페이지 30개를 Notion에 추가해줘.
💡
script_clean.json 파일은 처음 추출한 것을 보관해 두세요. 큐 보충 때마다 이 파일을 Claude에게 첨부하면 Claude가 알아서 다음 배치를 생성합니다.

전체 배치 계획 (영화 1편 기준, 약 300일)

배치Day 범위보충 시점
1차 (최초 셋업)Day 1 ~ 30지금
2차Day 31 ~ 6030일 후
3차Day 61 ~ 9060일 후
4차 ~ 9차Day 91 ~ 27090 ~ 270일 후
마지막Day 271 ~ 끝270일 후
🔧

문제가 생겼을 때

Claude에게 상황을 설명하면 대부분 해결됩니다
증상Claude에게 이렇게 말하세요
카카오톡이 안 와요 "Routine [ID] 실행은 됐는데 카카오톡이 안 왔어. PlayMCP 연결 확인하고 재실행해줘"
Notion이 업데이트가 안 됨 "Routine 실행 후 Notion 페이지가 안 바뀌었어. Notion MCP 상태 확인해줘"
큐가 비었다는 알림 위 "큐 보충 방법" 메시지를 Claude에게 보내세요
PDF 추출 결과가 이상함 "추출된 JSON 파일 앞부분을 보니 char가 이상해. 스크립트 CHAR_INDENT_MIN 값 조정 방법 알려줘"
Routine 시간을 바꾸고 싶음 "Routine [ID] 스케줄을 07:00 KST로 변경해줘"
카드 내용 형식을 바꾸고 싶음 "Routine [ID] 프롬프트에서 어휘 설명을 3개로 늘리고 예문도 추가해줘"
💬
핵심은 Routine ID와 DB ID를 메모해 두는 것입니다. 셋업 완료 후 Claude가 알려주는 두 ID를 어딘가에 저장해 두세요. 나중에 수정·재실행 요청 시 이 ID가 필요합니다.