🗺️ 전체 지도: 무엇으로 무엇을 만들었나
💡 핵심 아이디어는 하나입니다. 대본(문장 목록) 하나에서 자막, 장면 길이, 애니메이션 타이밍, 음성 위치가 모두 계산돼서 나옵니다. 그래서 문장 하나를 고치면 나머지가 같이 따라 바뀌어요. 프로그래머들은 이걸 "단일 원본(single source of truth)"이라고 부릅니다.
① 웹 노트: HTML · CSS · JavaScript
웹 페이지는 세 가지 언어가 역할을 나눠 맡습니다. 집에 비유하면 이렇습니다.
학습 노트의 "키워드 가리고 외우기" 버튼을 기억하나요? 비밀은 문장 속 [[ ]] 표시입니다. 문장을 이렇게 적어 두면,
e:'엘니뇨 시기에는 무역풍이 평소보다 [[약해진다]].'
JavaScript 한 줄이 [[ ]] 안의 글자를 찾아서 "키워드"로 바꿔 줍니다. 찾는 규칙을 정규 표현식이라고 해요.
// [[글자]] 를 찾아서 <b class="k">글자</b> 로 바꾸기
const mk = t => t.replace(/\[\[(.+?)\]\]/g, '<b class="k">$1</b>');
그리고 CSS가 "가리기 모드일 때 .k 글자는 투명하게"라고 정해 둡니다. 버튼은 모드만 켜고 끕니다.
body.hide .k:not(.show){ color: transparent; background: #d9efec; }
🧪 실험실: 내 문장에 [[키워드]] 넣어 보기
👀 지금 바로 해 볼 것: 학습 노트를 열고 Ctrl + U(페이지 소스 보기)를 누르면 노트의 모든 코드가 보입니다. 숨긴 것이 없어요. 위 코드도 그 안에 그대로 있습니다.
② 영상: 1초에 그림 30장
영상은 사실 빠르게 넘기는 그림책입니다. 이 영상은 1초에 30장, 308.9초 동안 모두 9,267장이에요. 사람이 9,267장을 그릴 수는 없으니까, "시각 t를 주면 그 순간의 그림을 그리는 함수"를 하나 만들었습니다.
function renderFrame(t){ // t = 영상 시작 후 몇 초인가
// t에 따라 바닷물 색, 화살표 길이, 글자 위치를 계산해서 그린다
}
예를 들어 "무역풍 화살표가 2초 동안 자라난다"는 이렇게 계산합니다. p는 0(시작)에서 1(끝)까지 변하는 진행률이에요.
const p = clamp((t - 시작시각) / 2); // 0 ~ 1 사이로 자르기
화살표길이 = 최대길이 * p;
🧪 실험실: 시간 슬라이더를 움직여 보세요
0~4초 평상시 → 4~8초 엘니뇨(무역풍 약화, 따뜻한 물이 동쪽으로) → 8~12초 라니냐(무역풍 강화). 이 그림도 같은 방식, 즉 t를 받아서 그리는 함수 하나로 그렸습니다.
그림을 어떻게 mp4로 바꿨을까
Playwright는 화면 없이 브라우저를 자동으로 조종하는 도구입니다. Python에서 "t=0초 그려 → 찍어 → t=0.033초 그려 → 찍어…"를 9,267번 반복시켰어요. 컴퓨터 두 코어로 나눠 돌려 약 25분 걸렸습니다.
자막과 장면 길이는 대본에서 자동으로
대본 파일 script.js에는 문장이 순서대로 적혀 있고, 프로그램은 한글 음절 수로 읽는 데 걸릴 시간을 어림합니다.
const RATE = 4.4, GAP = 0.55; // 1초에 4.4음절, 문장 사이 0.55초 쉼
읽는시간 = 음절수 / RATE;
🧪 실험실: 내 문장은 몇 초짜리일까?
음절 수 ≈ 0 → 읽는 시간 ≈ 0초 (숫자는 1.5음절, 쉼표·마침표는 0.6음절로 계산)
③ 배경음: 소리도 숫자다
소리는 공기의 떨림이고, 떨림은 사인파라는 그래프로 쓸 수 있습니다. 1초에 440번 떨리면(440Hz) '라' 음이에요. 건반 하나 올라갈 때마다 진동수가 2의 12제곱근 배가 됩니다.
hz = 440 * 2 ** ((건반번호 - 69) / 12) # 69번 건반 = 라(A4)
Python의 numpy로 1초에 48,000개의 숫자를 계산해서 파형을 만들고, 음 여러 개를 더해 화음(Cmaj7, Am7, Fmaj7, G6…)을 만들었습니다. 템포는 84 BPM, 장면마다 악기 층의 음량을 다르게 해서 분위기를 바꿨어요. 외부 음원은 하나도 쓰지 않았습니다.
🧪 실험실: 영상에 나온 화음 들어 보기
소리가 납니다. 이어폰 음량을 확인하세요. 브라우저가 사인파를 직접 계산해서 내는 소리예요.
④ 내레이션: AI 음성을 시간표에 맞춰 붙이기
처음 영상에는 자막과 배경음만 있었습니다. 나중에 목소리를 입히면서 이런 순서로 작업했어요.
- 음성: Microsoft의 신경망 음성
ko-KR-SunHiNeural(여성). Python 도구edge-tts로 만들었습니다. - 안 넘치게: 문장마다 쓸 수 있는 시간(다음 문장 전까지)이 정해져 있어요. 음성이 더 길면 그 문장만 말 속도를 올려 다시 만듭니다. 이번에는 첫 문장만 6% 빨라졌어요.
- 덕킹(ducking): 말할 때만 배경음을 살짝 낮추는 기술입니다. 라디오 DJ가 말할 때 음악이 작아지는 것과 같아요.
- 음량 맞추기: 유튜브 같은 곳이 쓰는 기준인 LUFS로 -16 정도에 맞췄습니다. 그래서 영상마다 소리 크기가 들쭉날쭉하지 않아요.
- 읽는 법 교정: 화면에는 "30도"라고 쓰고, 음성만 "삼십 도"로 읽게 바꿨습니다.
🤖 이 과정은 AI 코딩 도우미(Claude)에게 "1. 설치 확인 → 2. 음성 생성 → 3. 검증 → 4. 사이트 교체" 같은 순서 있는 지시서를 주고 같이 진행했습니다. AI를 잘 쓰는 요령도 결국 무엇을, 어떤 순서로, 어떻게 확인할지 분명하게 쓰는 거예요. 좋은 실험 보고서를 쓰는 능력과 똑같습니다.
✏️ 직접 고쳐 보기: 난이도별 안내
레벨 1노트의 글자 바꾸기 (준비물: 메모장)
- 학습 노트 페이지에서 Ctrl + S를 눌러 내 컴퓨터에 저장합니다.
- 저장한
.html파일을 오른쪽 클릭해서 연결 프로그램 → 메모장(또는 VS Code)으로 엽니다. - Ctrl + F로 바꾸고 싶은 문장을 찾아 고칩니다. 외우고 싶은 단어는
[[ ]]로 감싸 보세요. - 저장할 때 인코딩은 UTF-8로 합니다. 그다음 파일을 더블클릭해 브라우저로 열면 바뀐 노트가 보입니다.
레벨 2색깔 바꾸기 (CSS 변수)
파일 맨 위 <style> 안의 첫 줄에서 색이 정해집니다. --warm(엘니뇨 빨강), --cold(라니냐 파랑), --acc(키워드 초록)의 값을 바꿔 보세요. 한 곳만 고쳐도 페이지 전체 색이 바뀝니다.
:root{ --warm:#e5484d; --cold:#2b6cb0; --acc:#0f766e; }
/* 예: --acc:#7c3aed → 키워드가 보라색으로 */
레벨 3내레이션 목소리 바꾸기 (Python + ffmpeg)
내레이션 키트 폴더에서 명령 한 줄로 목소리·속도·배경음을 바꿔 다시 만들 수 있습니다.
python narrate.py --voice ko-KR-InJoonNeural --force # 남성 음성으로 전부 다시
python narrate.py --rate 5 # 전체 5% 빠르게
python narrate.py --bgm -12 # 배경음 더 작게
레벨 4대본을 고쳐 영상 전체 다시 만들기
src/script.js의 문장을 고치고 ./build.sh를 실행하면, 장면 길이와 자막과 애니메이션 시점이 새로 계산되어 영상이 처음부터 다시 렌더링됩니다. 필요한 것은 Node.js, Python(playwright, numpy, scipy, pillow), ffmpeg, 한글 글꼴입니다. 렌더링에 25분쯤 걸리니 대신 미리보기 도구로 한 장면만 찍어 볼 수도 있어요.
python3 tools/snap.py pacific:e4+6 # 태평양 장면 e4 문장 6초 뒤를 PNG로
※ 영상 제작 코드는 이 사이트에 올라가 있지 않습니다. 레벨 4에 도전하고 싶다면 선생님께 요청하세요.
| 이걸 바꾸고 싶다면 | 여기를 고친다 |
|---|---|
| 노트 문장·키워드 | 학습 노트 HTML의 ITEMS 목록 |
| 노트 색 | :root{ --warm … } |
| 영상 챕터 버튼 | 영상 페이지 HTML의 CH 목록 (초, 제목) |
| 목소리·말 속도·배경음 크기 | narrate.py 옵션 |
| 음성만 다르게 읽기 | narrate.py의 READ 목록, 예: ("CO₂","이산화 탄소") |
| 대본·자막·장면 길이 | src/script.js → build.sh |
🏆 도전 과제
체크한 내용은 이 브라우저에만 저장됩니다.
🆘 막혔을 때
한글이 '???'나 이상한 글자로 깨져요
파일을 UTF-8로 저장하지 않았을 때 생깁니다. 메모장 다른 이름으로 저장 창 아래의 인코딩을 UTF-8로 바꾸세요.
'python'은(는) 내부 또는 외부 명령… 이 아닙니다
Python이 설치되지 않았거나 경로(PATH)가 아직 반영되지 않았습니다. winget install Python.Python.3.12로 설치한 뒤 명령 창을 새로 열면 됩니다. ffmpeg도 마찬가지(winget install Gyan.FFmpeg).
고쳤는데 브라우저에서 그대로예요
저장을 했는지 확인하고 Ctrl + F5(강력 새로고침)를 누르세요. 브라우저가 예전 파일을 기억(캐시)하고 있을 수 있습니다.
화면이 하얗게 나오거나 버튼이 안 눌려요
JavaScript 어딘가에 따옴표나 괄호가 빠졌을 가능성이 큽니다. F12를 눌러 Console 탭을 보면 빨간 글씨로 몇 번째 줄이 잘못됐는지 알려 줍니다. 오류 메시지는 컴퓨터가 주는 힌트예요.
망가뜨릴까 봐 무서워요
고치기 전에 파일을 복사해 두세요(노트_원본.html). 내 컴퓨터에 저장한 파일은 아무리 고쳐도 이 사이트에는 영향이 없습니다. 마음껏 망가뜨려 보는 게 제일 빨리 배우는 방법입니다.