한글

두벌식 타자

햇빛 드는 책상 위 자판을 누를 때마다 ㅎ→하→한, 받침은 다음 모음을 만나 책상에서 들려 옆 글자로 쓸어 올라간다.

두벌식 타자 실행 화면
새 탭에서 보기

실제 코드로 재생되는 미리보기입니다

프롬프트 설정

Claude 가 읽는 제작 지시문입니다. 직접 읽지 않아도 됩니다.

한글 타자 애니메이션을 HTML 파일 하나로 만들어 줘. 미리보기에서 바로 재생되게. 길게 설명할 테니 숫자는 그대로 지켜 줘.

핵심 아이디어: 햇빛 드는 책상을 위에서 내려다본다. 연한 세이지색 펠트 매트 위에 진회색 몸체의 두벌식 키보드가 놓여 있고, 키캡은 이름 그대로 두 벌이다 — 자음 키는 상아색, 모음 키는 옥색. 키가 하나씩 눌릴 때마다 매트 위쪽에 놓인 아주 큰 글자가 진짜 한글 입력기처럼 조립된다 — ㅎ → 하 → 한 → 한ㄱ → 한그 → 한글. 큰 글자는 매트에 오려 놓은 종이 글자처럼 단단한 그림자를 드리운다. 그리고 받침이 다음 모음을 만나는 순간(망 + ㅡ → 마으) 그 받침이 글자에서 떨어져 책상에서 들린다 — 그림자가 조각에서 벌어지며 옅어지고, 조각은 아래로 살짝 떨어졌다가 옆 칸으로 쓸어 올라가 새 글자의 첫소리 자리에 내려앉는다. 내려앉는 순간 그림자가 다시 붙는다(도깨비불 현상). 입력 과정은 지어내지 말고 유니코드 계산과 두벌식 입력 규칙으로 정확히 만든다.

[바꿀 곳]
- 문장: 마음을 한글로 그리다 (띄어쓰기마다 다음 줄로 내려간다 — 기본은 세 줄)
- 색:
  책상 매트 #CDD9C6 · 햇빛 #F1F5EA · 그림자 #2B3A2F(불투명도는 쓰는 곳마다 정한다) · 큰 글자 #1F2421 · 강조 #A62C16
  자판 몸체 #4A4642 · 몸체 테 #6A655F · 키 접지 그림자 #1E1B19
  자음 키 윗면 #F2EEE5 · 옆면 #CFC6B6 · 글자 #2A2B28
  모음 키 윗면 #7FB2A5 · 옆면 #5E8C80 · 글자 #22302B
  기능 키(시프트·지우기·123·띄어쓰기·엔터) 윗면 #A8A196 · 옆면 #827B70 · 아이콘·글자 #2A2B28
  눌린 키 글자 #F2EEE5
- 글자 대비(합격 기준, 색을 바꿔도 지킨다): 큰 글자와 조립 중 강조 글자는 높이 0.29W 의 아주 큰 굵은 글자라 WCAG 큰 글자 기준 3:1 을 쓴다. 바탕은 둘로 잰다 — 가장 어두운 매트(매트 색에서 결 4단계를 뺀 값)와, 그 글자 자기 그림자가 덮은 매트(매트 위에 그림자색 0.20 을 얹고 결 4단계를 뺀 값). 기본값: 큰 글자 10.2 / 그림자 위 7.4 · 강조 4.6 / 그림자 위 3.3. 키 글자는 작은 글자라 4.5:1 을 쓴다(키 윗면 위, 기본 자음 12.3 · 모음 5.8 · 기능 5.6 · 눌린 키 글자/강조 6.1). 시작할 때 WCAG 상대 휘도 공식으로 이 값들을 계산해 콘솔 대조표에 적고, 기준 미만이면 console.warn('대비 부족: …') 한다. 「지난 문장」 옅은 글자(아래 장면 절)는 배경이라 대비 기준 밖이다.
- 박자: 기본 1.0 (키와 키 사이 간격에만 곱한다. 1.5 면 타자 구간이 1.5배로 느려지고, 시작의 엔터·바램·비키기·눌림·비행·머묾 길이는 그대로다)
- 화면비: 9:16 (캔버스 1080×1920)
- 글꼴: 'Pretendard', 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif (CONFIG 의 글꼴 문자열 한 곳에만 둔다 — 그 한 줄만 바꿔 글꼴별로 시험할 수 있게)

[크기] — W = 화면 폭 1080, H = 화면 높이 1920
- 시점: 책상을 정면 위에서 내려다본다. 원근은 없다. 빛은 왼쪽 위에서 오므로 모든 그림자는 오른쪽 아래로 떨어진다.
- 위쪽 큰 글자: 낱말 하나가 한 줄이다. 칸 크기 em = min(0.88W ÷ 가장 긴 낱말의 음절 수, 0.58H ÷ (1.25·(줄 수 − 1) + 1)). 기본 문장이면 em = 0.2933W(316.8px) — 한 줄 세 칸이 화면 폭의 88% 를 채운다.
- 글자는 굵기 700, 글꼴 크기 em. 칸 너비 = em. 줄마다 최종 음절 수 N 으로 칸을 고정한다: 첫 칸 왼쪽 x0 = (W − N·em) ÷ 2, 칸 i 의 가운데 x = x0 + (i + 0.5)·em, textAlign center. 타자 중에 칸을 다시 가운데 정렬하지 않는다.
- 줄 간격 = 1.25em, 줄 덩어리의 가운데 y = 0.335H. 기본 문장이면 세 줄 가운데가 0.129H · 0.335H · 0.541H, 글자 잉크는 대략 0.055H 부터 0.615H 까지 차서 위쪽 화면의 거의 전부를 쓴다.
- 세로 맞춤: 시작할 때 measureText('한') 의 actualBoundingBoxAscent·Descent 로 잉크 상자를 재고, 그 가운데가 줄 가운데에 오도록 기준선(alphabetic) 위치를 정한다. 모든 글자에 같은 기준선을 쓴다.
- 글자 그림자: 큰 글자·밑줄·커서는 매트에 놓인 물건이다. 각각을 먼저 (0.025em, 0.035em)(= 7.9px, 11.1px) 오른쪽 아래로 옮겨 그림자색 불투명도 0.20 으로 그리고, 그 위에 제 색으로 그린다. 글자 그림자는 글자와 같은 배율 스프링을 따른다.
- 입력 중 표시: 지금 조립 중인 칸은 글자가 강조색이고, 칸 아래 y = 줄 가운데 + 0.56em 에 두께 0.022em 밑줄(칸 양끝에서 0.06em 씩 안쪽, 강조색)이 있다. 그 음절이 확정되는 순간 글자는 큰 글자 색이 되고 밑줄은 사라진다(즉시).
- 커서: 폭 0.025em, 높이 0.95em, 강조색, 마지막으로 차 있는 칸 오른쪽 끝 + 0.05em. 줄이 비어 있으면 x0 + 0.02em. ★커서는 조립 중인 칸이 없을 때만 그린다(줄 첫머리, 띄어쓰기 직후). 조립 중에는 밑줄이 그 자리를 맡는다 — 한글 글자 옆의 세로 막대는 모음 ㅣ 로 읽혀, 혼자 선 ㅁ 옆에서 「미」, 「마」 옆에서 「마ㅣ」가 된다. 커서는 깜빡이지 않는다(보일 때는 늘 켜짐).
- 자판(전부 키 윗면 기준 숫자):
  키 간격 u = 0.0962W, 키 폭 kw = 0.0837W, 키 높이 kh = 0.056H. 한 줄 10키 폭(10u − (u − kw) = 0.9495W)을 화면 가로 가운데에 둔다(왼쪽 끝 x = 0.0253W). 모든 줄이 같은 왼쪽 끝에서 시작한다.
  줄 윗면 y = 0.700H · 0.770H · 0.840H · 0.910H.
  1줄(10키, 들여쓰기 0): ㅂ ㅈ ㄷ ㄱ ㅅ ㅛ ㅕ ㅑ ㅐ ㅔ
  2줄(9키, 들여쓰기 0.5u): ㅁ ㄴ ㅇ ㄹ ㅎ ㅗ ㅓ ㅏ ㅣ
  3줄: 시프트(폭 1.5u − 간격) · ㅋ ㅌ ㅊ ㅍ ㅠ ㅜ ㅡ (1.5u 부터) · 지우기(8.5u 부터 폭 1.5u − 간격)
  4줄: 「123」(폭 1.5u − 간격) · 띄어쓰기(1.5u 부터 폭 7u − 간격, 글자 없음) · 엔터(8.5u 부터 폭 1.5u − 간격)
  여기서 간격 = u − kw. 키 모서리 반지름 0.18·kw. 키 글자는 호환 자모, 크기 0.42·kh, 굵기 700, 키 윗면 가운데. 「123」 글자는 0.30·kh, 굵기 700. 시프트·지우기·엔터는 글자가 아니라 선 아이콘으로 그린다(시프트 = 위쪽 화살표 윤곽, 지우기 = 왼쪽이 뾰족한 오각형 윤곽 안에 ×, 엔터 = 꺾인 화살표 ↵ 모양 선, 선 굵기 0.05·kh).
  키 색은 두 벌이다: 자음 키(ㅂㅈㄷㄱㅅ ㅁㄴㅇㄹㅎ ㅋㅌㅊㅍ) = 자음 키 색, 모음 키(ㅛㅕㅑㅐㅔ ㅗㅓㅏㅣ ㅠㅜㅡ) = 모음 키 색, 나머지 = 기능 키 색. 왼손 자리는 상아, 오른손 자리는 옥색으로 갈린다.
  자판 몸체: 책상 위에 놓인 키보드다. x = 0.012W ~ 0.988W, y = 0.672H 부터 화면 아래 밖까지(아래 모서리는 화면 밖), 모서리 반지름 0.035W, 몸체 색. 윗면 가장자리에서 0.006W 안쪽에 1.5px 몸체 테 색 선(금속 테). 몸체 그림자 = 같은 모양을 (0.008W, 0.010H) 옮겨 그림자색 불투명도 0.28 로 책상에 먼저 그린다.

[책상과 빛] — 배경도 움직이지만 주인공을 가리지 않는다
- 바닥(매트 결 + 햇빛 띠 + 쉬는 자판)은 움직이지 않는다. 시작할 때와 창 크기가 바뀔 때 한 번, ★실제 캔버스 픽셀 크기(canvas.width × canvas.height — 화면 배율·devicePixelRatio 를 곱한 크기) 오프스크린 한 장에 매트 결과 햇빛 띠, 그리고 쉬는 상태(모든 키 p = 0)의 자판 — 몸체 그림자·몸체·테·키 34개 — 를 같이 굽는다. 매 프레임은 변환을 단위 행렬로 두고(setTransform(1,0,0,1,0,0)) 그 한 장을 늘이지 않고 1:1 로 drawImage(bake, 0, 0) 한 번 깐 뒤, 기준 좌표 변환으로 돌아와 나머지를 그린다. 기준 크기(1080×1920)로 구운 판을 화면 배율로 늘여 그리면 매 프레임 전 화면 보간이 돌아 프레임률이 절반(30fps)으로 떨어진다.
- 매트 결: 매트 색을 칠하고 기준 3×3px 칸(실제 픽셀로는 배율만큼 큰 칸)마다 시드 고정 난수로 밝기를 0 ~ −4 단계(0~255 기준) 낮춘다. 펠트 결이다.
- 햇빛 띠: 왼쪽 위 창에서 들어와 매트 위에 비스듬히 누운 빛. 중심 C = (0.42W, 0.30H), 긴 방향은 +30°(캔버스 기준 시계 방향 — 오른쪽으로 갈수록 내려간다), 두께 0.30H, 길이 2.4H(화면 밖까지). 두께 방향 양쪽 0.08H 는 0 → 1 로 부드럽게 차오르고 가운데는 평평하다. 색 = 햇빛 색, 가운데 불투명도 0.50. 바닥 한 장에 매트 결 위로 구워 넣는다. 흔들지 않는다(7초에 0.010H 흔들림은 눈에 안 보이는데, 그걸 위해 매 프레임 화면 크기 그라디언트를 채우면 프레임률이 절반이 된다).
  빛 띠는 매트에만 비친다 — 바닥 한 장 안에 있으니 글자·그림자·자판은 늘 그 위에 그려진다. 그래서 글자 대비는 빛 밖(가장 어두운 매트)이 하한이다.
- 그리는 순서: 바닥 한 장(1:1, 쉬는 자판 포함) → 눌린 키 다시 그리기(아래) → 지난 문장(옅은 글자, 그림자 없음) → 큰 글자 그림자 → 큰 글자·밑줄·커서 → 날아가는 조각의 그림자 → 날아가는 조각.
- 눌린 키 다시 그리기: 매 프레임 p > 0 인 키만, 그 키의 덮개 상자(키 왼쪽·위로 0.002W, 오른쪽으로 0.006W, 아래로 바닥선 + 0.005H 까지)를 몸체 색으로 채워 구워 둔 쉬는 모습을 지우고, 그 자리에 [키 눌림]의 세 겹(접지 그림자 → 옆면 → 윗면·광택·모서리 빛 → 글자)을 그 순간 p 로 다시 그린다. 덮개 상자는 이웃 키·이웃 그림자·몸체 테에 닿지 않는 크기다(키 사이 가로 틈 13.5px · 줄 사이 틈 12.5px, 쉬는 그림자는 오른쪽 4.6px · 아래 7.7px). 시프트의 p 가 0.5 이상인 동안은 1줄 열 키도 같은 방법으로 다시 그린다(글자가 쌍자음·ㅒ·ㅖ 로 바뀌므로).
- 비용 상한(합격 기준): 프레임마다 새 캔버스 0 · 화면 크기 그라디언트 채움 0(키 윗면 광택은 키 크기라 괜찮다) · 늘여 그리는 화면 크기 drawImage 0 · 프레임마다 다시 그리는 키 ≤ 4개(시프트 p ≥ 0.5 동안은 1줄 10개 추가). 키 하나는 그림자·옆면·윗면·광택·모서리 빛·글자로 여섯 번 그려져, 34키를 매 프레임 다 그리면 휴대폰급 CPU(4배 감속 근사)에서 15~30fps 로 떨어진다. 시작 뒤 requestAnimationFrame 타임스탬프 간격 120개의 중앙값을 콘솔에 적고 20ms 를 넘으면 console.warn('프레임 느림: …') 한다(render 앞뒤 performance.now 로는 못 잰다 — 캔버스는 명령을 쌓고 바로 돌아온다).

[키 눌림 — 깊이·그림자·박자]
- 키 하나는 세 겹이다. ① 접지 그림자: 옆면과 같은 모양을 (0.6·sh, sh) 만큼 오른쪽 아래로 옮긴 키 접지 그림자 색, 불투명도 a. ② 옆면: 윗면과 같은 폭, 윗면 위끝부터 바닥선(= 윗면 쉬는 위치 + kh + sd)까지, 그 키 종류의 옆면 색. ③ 윗면: 높이 kh, 그 키 종류의 윗면 색 위에 위끝 흰색 10% → 아래끝 0% 세로 그라디언트(키 종류와 무관하게 0~kh 좌표로 시작할 때 하나 만들어 translate 로 재사용), 윗면 위끝에서 2px 아래에 흰색 18% 1.5px 선 하나(모서리 빛).
- 쉬는 상태: 옆면이 윗면 아래로 sd = 0.0075H(14.4px) 보이고, 그림자 sh = 0.004H, a = 0.45.
- 눌림 정도 p(0~1): 윗면이 p·0.0062H(최대 11.9px) 내려간다. 바닥선은 고정이라 보이는 옆면은 14.4px → 2.5px 로 줄어든다. 그림자 sh = 0.004H·(1 − 0.7p), a = 0.45·(1 − 0.5p). 윗면 색은 그 키의 윗면 색 → 강조색으로 p 만큼 섞고, 키 글자 색은 그 키의 글자 색 → 눌린 키 글자 색으로 p 만큼 섞는다.
- 그림자는 흐리게 하지 않는다(shadowBlur 쓰지 않음). 단단한 그림자다.
- 한 번 누름의 p(τ), τ = t − 그 키의 입력 시각 tk:
  τ ∈ [−0.045, 0): p = easeInQuad((τ + 0.045)/0.045) — 손끝이 내리누르는 0.045초
  τ ∈ [0, 0.06): p = 1 — 바닥. 글자는 정확히 τ = 0 에 바뀐다
  τ ∈ [0.06, 0.20): p = 1 − easeOutCubic((τ − 0.06)/0.14) — 0.14초에 걸쳐 올라온다
  그 밖은 0. 같은 키가 연달아 눌려 구간이 겹치면 큰 쪽 값을 쓴다.
- 쌍자음·ㅒ·ㅖ(문장을 바꿨을 때)는 시프트를 같이 누른다: 시프트는 tk − 0.12 부터 0.045초에 내려가 tk + 0.06 까지 머물고 같은 0.14초로 올라온다. 시프트의 p 가 0.5 이상인 동안 1줄 글자가 ㅃ ㅉ ㄸ ㄲ ㅆ ㅛ ㅕ ㅑ ㅒ ㅖ 로 바뀐다(키 색은 그대로). 눌리는 키는 시프트 쪽이 아니라 원래 키(ㅅ 자리 등)다.

[입력 규칙 — 두벌식 오토마타, 시작할 때 한 번 계산]
1) 문장을 키 순서로 풀기: 완성 음절(0xAC00~0xD7A3)은 c = 코드 − 0xAC00, 초성 = floor(c / 588), 중성 = floor((c % 588) / 28), 종성 = c % 28 (588 = 21×28). 표는
   초성 19: ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ
   중성 21: ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ
   종성 28: (없음)ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ
   겹모음은 두 키로(ㅘ=ㅗㅏ ㅙ=ㅗㅐ ㅚ=ㅗㅣ ㅝ=ㅜㅓ ㅞ=ㅜㅔ ㅟ=ㅜㅣ ㅢ=ㅡㅣ), 겹받침도 두 키로(ㄳ=ㄱㅅ ㄵ=ㄴㅈ ㄶ=ㄴㅎ ㄺ=ㄹㄱ ㄻ=ㄹㅁ ㄼ=ㄹㅂ ㄽ=ㄹㅅ ㄾ=ㄹㅌ ㄿ=ㄹㅍ ㅀ=ㄹㅎ ㅄ=ㅂㅅ) 푼다. 띄어쓰기는 띄어쓰기 키. 호환 자모(ㄱ~ㅣ, 예: ㅋㅋ)는 그 키 하나. 그 밖의 문자는 건너뛰고 console.warn 한다.
2) 그 키들을 입력기 규칙으로 다시 친다. 조립 중 음절 = (초, 중, 종) 중 일부.
   - 자음: 비어 있으면 새 칸(초). 초만 있으면 확정하고 새 칸. 초+중이면 받침이 될 수 있는 자음(ㄸ ㅃ ㅉ 제외)은 종성으로, 아니면 확정하고 새 칸. 종성이 있으면 (종성, 자음)이 겹받침 표에 있을 때만 겹받침으로, 아니면 확정하고 새 칸.
   - 모음: 비어 있으면 모음 혼자 새 칸. 초만 있으면 초+중. 초+중이고 (중, 모음)이 겹모음 표에 있으면 합친다, 아니면 확정하고 모음 혼자 새 칸. 종성이 있으면 ★도깨비불: 종성이 홑받침이면 통째로 떼어 새 칸의 초성으로, 겹받침이면 뒤 자음만 떼어 새 칸의 초성으로(앞 자음은 남는다), 남은 음절은 확정.
   - 띄어쓰기: 확정하고 다음 줄. 엔터: 확정.
   - 칸에 그릴 글자: 초+중(+종)이면 0xAC00 + (초×21 + 중)×28 + 종, 혼자인 자음·모음은 호환 자모 글자.
3) 다 친 결과가 원래 문장과 같은지 console.assert 하고, 키마다 [키, 화면 문자열, 사건] 표를 console.table 로 출력한다.
기본 문장의 정답(키 → 화면): ㅁ ㅁ · ㅏ 마 · ㅇ 망 · ㅡ 마으(도깨비불) · ㅁ 마음 · ㅇ 마음ㅇ · ㅡ 마음으 · ㄹ 마음을 · ␣ · ㅎ ㅎ · ㅏ 하 · ㄴ 한 · ㄱ 한ㄱ · ㅡ 한그 · ㄹ 한글 · ㄹ 한글ㄹ · ㅗ 한글로 · ␣ · ㄱ ㄱ · ㅡ 그 · ㄹ 글 · ㅣ 그리(도깨비불) · ㄷ 그릳 · ㅏ 그리다(도깨비불). 키 24개, 도깨비불 3번.

[받침 조각 — 완성 글자 그림에서 잘라 낸다. 호환 자모 글자(ㅇ, ㄹ)를 따로 그려 날리는 것은 금지]
시작할 때 도깨비불마다 한 번 계산해 캐시한다. 방식은 세 단계이고, 앞 단계가 실패할 때만 다음 단계로 간다.
1) 준비: 오프스크린 캔버스(한 변 1.4em)에 출발 음절(망)을 화면과 같은 글꼴·크기·굵기·기준선 오프셋으로 가운데에 그리고 getImageData 로 알파를 읽는다. 알파 ≥ 100 인 픽셀의 상자 = 잉크 상자(위끝 top, 아래끝 bottom, 높이 h).
2) 1순위 — 연결 성분: 알파 ≥ 60 인 픽셀을 4방향 이웃 연결 성분으로 나누고, 잉크 픽셀의 0.4% 미만인 성분은 버린다. 받침 성분 = 위끝이 top + 0.45h 보다 아래이고 아래끝이 bottom − 0.08h 보다 아래인 성분. 겹받침이면 뒤 자음만 조각이다: 받침 성분이 둘 이상이면 무게중심 x 가 가장 오른쪽인 것. 하나뿐이고 그 폭이 잉크 폭의 0.6 이상이면(두 자음이 붙음) 그 성분 안에서 폭의 0.30~0.70 사이 알파 합이 가장 작은 열의 오른쪽. 하나뿐이고 폭이 0.6 미만이면 무게중심 x 가 잉크 가운데보다 오른쪽일 때만 조각으로 쓰고, 왼쪽이면(앞 자음만 떨어지고 뒤 자음은 모음에 붙은 경우 — Pretendard 「닭」이 그렇다) 1순위 실패로 보고 2순위로 간다.
   조각 마스크 = 고른 성분의 픽셀 + 그 둘레 2px 안의 모든 픽셀(알파와 무관 — 단 다른 성분에 속한 픽셀은 뺀다). 마스크 밖은 투명. 상자로 자르지 않는다. 둘레를 「알파 > 0 인 픽셀」로만 넓히면 마스크 경계가 안티에일리어스 가장자리에 딱 붙어, 지운 그림에 빠진 받침의 윤곽이 머리카락 선으로 남는다.
3) 2순위 — 줄 방식(획이 붙은 글꼴용): top + 0.45h ~ bottom − 0.15h 사이에서 알파 합이 가장 작은 줄을 찾아 그 아래를 조각으로 자른다. 겹받침이면 그 띠를 다시 폭의 0.30~0.70 사이 알파 합이 가장 작은 열에서 갈라 오른쪽만 쓴다. 모음 획 끝이 조금 묻어 가도 괜찮다 — 시그니처가 사라지는 것보다 낫다.
4) 최후 — 조각 없음: 출발 칸은 바뀌고 도착 칸은 tk 에 바로 뜬다. 이때 반드시 console.warn('도깨비불 조각 실패: <음절>, 글꼴 <실제 글꼴>') 을 남긴다. 호환 자모로 대체하지 않는다.
5) 조각에서 만드는 그림 넷(전부 이 단계에서 한 번): 조각(강조색) · 조각 그림자판(같은 마스크를 그림자색으로) · 지운 그림(출발 음절에서 마스크를 destination-out) · 지운 그림의 그림자판. 마스크를 다른 크기로 늘려 쓸 때는(선명도를 위해 크게 그릴 때 등) 보간을 끈다(imageSmoothingEnabled = false) — 보간하면 경계가 반쯤만 지워진다.
6) 도착 첫소리 재기: 도착 음절(으)도 같은 방법으로 그리고 성분으로 나눈다. 첫소리 = 가로 모음(ㅗㅛㅜㅠㅡ)이면 무게중심 y 가 top + 0.40h 보다 위인 성분들, 세로 모음(ㅏㅐㅑㅒㅓㅔㅕㅖㅣ)이면 무게중심 x 가 잉크 왼쪽 + 0.55·잉크 폭보다 왼쪽인 성분들, 겹모음이면 두 조건을 다 만족하는 성분들. 그 성분들의 잉크 상자 가운데가 착지점 D, 폭·높이가 (Dw, Dh). 못 찾으면 칸 가운데 기준 표값을 쓴다: 세로 모음 (−0.12em, −0.06em), 가로 모음 (0, −0.14em), 겹모음 (−0.12em, −0.14em), Dw·Dh 는 조각과 같게.
7) ★자체 대조(합격 기준): 도깨비불마다 [음절, 방식(성분/줄/없음), 조각 폭×높이(em), 도착 첫소리 폭×높이(em), dip(em), 아래 틈(H), 출발 칸 바뀜(tk + 초), P2.x 이동(em), 출발 글자와 최소 거리(em), 지운 그림 잔여 알파] 를 console.table 로 출력한다. 기본 문장의 기대값 — 세 번 모두 방식 = 성분이고(Pretendard·맑은 고딕·Noto Sans KR 모두), 조각은 망 ≈ 0.62×0.37em · 글 ≈ 0.66×0.43em · 릳 ≈ 0.63×0.34em, 도착 첫소리는 으의 ㅇ ≈ 0.68×0.52em · 리의 ㄹ ≈ 0.54×0.64em · 다의 ㄷ ≈ 0.51×0.62em 이다(세 글꼴에서 잰 값, 각 ±0.08em). dip 은 망 0.15~0.25 · 글 0.10~0.15 · 릳 0.15~0.20em(글꼴마다 다르다), 아래 틈은 전부 0.025H 이상, 출발 칸 바뀜은 망 ≈ +0.17 · 글·릳 ≈ +0.17~0.19초, 출발 글자와 최소 거리는 전부 0.04em 이상(이동이 +0.24em 에서도 못 미치면 console.warn). 지운 그림 잔여 알파 = 지운 그림에서 마스크 안 픽셀의 알파 최댓값이고 기대값 0, 8 을 넘으면 console.warn. 기본 문장에서 「없음」이 하나라도 나오면 console.error('합격 기준 미달: …') 를 낸다.

[큰 글자의 움직임]
- 글자가 바뀌면 즉시 바꿔 그린다(입력기처럼). 대신 그 칸에 배율 스프링을 준다. τ = 그 칸의 마지막 사건 뒤 초, 배율의 중심은 칸 가운데(도깨비불 착지만 예외).
  새 칸이 생김: s(τ) = 1 − 0.35·e^(−7τ)·cos(20τ) — 0.65 에서 시작, τ≈0.14초에 1.12 로 튀고, τ≈0.30초에 0.96, 0.49초 뒤 ±1% 안.
  칸 글자가 바뀜(ㅎ→하, 하→한 등): s(τ) = 1 − 0.08·e^(−9τ)·cos(24τ) — 0.92 에서 시작해 τ≈0.12초에 1.026, 0.17초 뒤 ±1% 안. 톡 하는 정도.
  한 칸에는 가장 최근 사건의 스프링 하나만 쓴다(곱하지 않는다).
- ★도깨비불(시그니처): 모음 키의 입력 시각 tk 에
  ① 출발 칸: tk 부터 「지운 그림」(망에서 ㅇ 만 빠진 모양)과 그 그림자판을 그린다. 조각의 가장 왼쪽 점(배율·기울기를 반영한 조각 상자 네 모서리 중 가장 왼쪽 x)이 출발 칸 오른쪽 끝(x0 + (칸 번호 + 1)·em)을 처음 넘는 시각 tc 에 받침 뺀 글자(마)로 바꾸고 「글자가 바뀜」 스프링. tc 는 시작할 때 비행을 200점으로 나눠 구한다. 비행이 끝날 때까지 못 넘으면 tc = tk + 0.26. 기본 문장이면 망 ≈ tk + 0.17, 글·릳 ≈ tk + 0.19~0.20. 확정 색은 tk 부터. 받침 뺀 독립 글자는 모음이 아래로 길어져(그의 ㅡ, 리의 ㅣ) 일찍 바꾸면 아직 칸 위를 지나는 조각에 붙는다 — 그래서 고정 시각이 아니라 조각이 칸을 떠난 순간에 바꾼다.
  ② 조각은 0.26초 동안 난다. u = (t − tk)/0.26, s = easeInOutSine(u). 위치 = 3차 베지어(P0, P1, P2, P3)의 s 지점. P0 = S(조각 상자의 원래 가운데), P1 = (S.x + 0.15·(D.x − S.x), S.y + dip), P2 = (D.x, D.y + 0.55em), P3 = D. 조각은 먼저 오른쪽 아래로 살짝 떨어졌다가, 비어 있는 도착 칸 안을 아래에서 위로 쓸어 올라가 D 에 선다. D 보다 위로 올라가지 않으므로 윗줄과의 틈은 원래 줄 사이 틈(약 0.33em ≈ 0.055H) 그대로다. 아래로 꺼지는 맛은 주로 P2(도착점 0.55em 아래)가 만든다 — dip 이 0.10em 까지 줄어도 쓸어 올라가는 곡선은 남는다.
  ②-b 출발 글자와의 거리(합격 기준): 쓸어 올라가는 조각의 모서리가 출발 칸 글자 끝(그의 ㅡ 오른끝, 리의 ㅣ 아래끝)을 스치지 않게 한다. 시작할 때 출발 칸 글자 그림 둘 — 지운 그림, 받침 뺀 글자 — 의 거리 지도(각 픽셀에서 가장 가까운 잉크(알파 ≥ 60)까지 거리, 1.4em 오프스크린에서 가로세로 1 · 대각 1.414 두 번 훑는 챔퍼 거리)를 한 번 만든다. 조각 잉크(알파 ≥ 60)의 가장자리 픽셀을 비행 변환(위치·배율·기울기)으로 옮겨 그 지도에서 거리를 읽는다(tc 전에는 지운 그림, tc 뒤에는 받침 뺀 글자). u ∈ [0.4, 1] 의 200점 중 최솟값이 0.04em(12.7px) 미만이면 P2.x 를 0.04em 씩 오른쪽으로 옮기고 dip(③)·tc(①)·거리를 다시 계산한다(최대 +0.24em). u < 0.4 는 재지 않는다 — 떨어져 나오는 순간의 조각은 원래 글자 안 틈만큼 가까운 게 정상이다. 기본 문장이면 이 PC 계산으로 P2.x 이동은 글 +0.12~0.16em · 릳 +0.12~0.20em(글꼴마다 다르다), 망은 0 이다. 이동해도 dip·아래 틈은 바뀌지 않고 tc 는 0.01~0.02초 당겨진다.
  ③ dip = 0.25em 이 기본이고 최대다. 시작할 때 비행을 30점으로 나눠 조각의 가장 낮은 점을 구한다. 가장 낮은 점 = 조각 가운데 y + (조각 반높이 × 세로 배율)·cos(각도) + (조각 반폭 × 가로 배율)·|sin(각도)|. 뒤 항은 기울기 몫이다 — 기울어진 조각은 아래 모서리가 내려가므로 빼먹으면 실제 틈이 표보다 0.006H 좁게 나온다. 아랫줄 잉크 위끝(마지막 줄이면 자판 몸체 위끝 0.672H)과의 틈이 0.025H 이상이 될 때까지 dip 을 0.05em 씩 줄인다(최소 0.10em). 그림자는 이 계산에 넣지 않는다.
  ④ 크기 맞추기: u ≤ 0.6 동안 조각은 원래 크기. u 가 0.6 → 1 로 가는 동안 k = smoothstep((u − 0.6)/0.4) 로 가로·세로 배율을 따로 보간해, u = 1 에서 조각 잉크 상자가 (0.92·Dw, 0.92·Dh) 가 되게 한다. 그 위에 범프 1 + 0.10·sin(πu) 를 곱한다. 0.92 는 착지 스프링의 시작 배율이다 — 그래서 착지 프레임에 첫소리 크기가 이어진다.
  ⑤ 기울기: ctx.rotate(+8°·sin(πu)) — 캔버스에서 양수는 시계 방향이다. 조각은 늘 오른쪽으로 날므로 위쪽이 진행 방향으로 숙는다. 비행 중 색은 강조색.
  ⑥ 들림(이 작품의 「우와」): 들린 높이 z = sin(πu). 조각 그림자판을 조각과 같은 회전·배율로, 조각보다 (0.025em, 0.035em)×(1 + 3z) 만큼 오른쪽 아래에, 불투명도 0.20×(1 − 0.45z) 로 조각보다 먼저 그린다. u = 0.5 에서 그림자는 (0.10em, 0.14em) = (32, 44)px 떨어지고 불투명도 0.11 로 옅어진다 — 받침이 책상에서 집혀 올라간다. u = 0 과 1 에서는 글자 그림자와 똑같은 (7.9, 11.1)px · 0.20 이라, 떨어져 나오는 프레임과 내려앉는 프레임에 그림자가 끊기지 않는다. 그림자는 다른 글자·자판 몸체 위에도 그대로 떨어진다(조각이 그 위를 지나므로).
  ⑦ 비행하는 동안 도착 칸(글자·밑줄·글자 그림자)은 비어 있다. 조각이 D 에 닿는 바로 그 프레임(tk + 0.26)에 조각과 조각 그림자를 지우고 도착 칸에 새 음절을 「글자가 바뀜」 스프링(0.92 시작)으로 띄운다. 배율 중심은 D 다 — 첫소리가 조각이 선 자리에서 그대로 이어진다. 0.65 에서 시작하는 「새 칸」 스프링은 여기서 쓰지 않는다(크기가 반으로 꺼졌다가 부풀어 움찔해 보인다). 조각과 새 글자를 한 프레임도 같이 그리지 않는다.
  ⑧ 비행 중에는 커서를 그리지 않는다. 착지한 새 음절은 조립 중이므로 커서 규칙대로 그 뒤에도 커서는 없다(밑줄이 그 칸을 가리킨다).

[장면] — 박자와 시간표 (박자 값이 1.0 일 때의 값)
- 시작은 이전 바퀴의 끝이다. 0초 화면 = 햇빛 드는 매트 위에 세 줄이 다 쳐져 있고 마지막 음절 「다」가 아직 조립 중(강조색 + 밑줄, 조립 중이라 커서는 없다). 첫 프레임부터 위쪽 화면이 그림자를 드리운 큰 글자로 꽉 차 있다.
- 0.15초 엔터: 엔터 키를 같은 p(τ)로 누른다(tk = 0.15). 그 순간 「다」가 확정 색이 되고 밑줄이 사라진다.
- 지난 문장(보내기 대신): 세 줄은 한꺼번에 화면 밖으로 나가지 않는다 — 그러면 첫 줄을 치는 2초 넘게 위쪽 화면의 2/3 가 빈 매트로 남는다. 0.21~0.45초에 세 줄 모두 「지난 문장」으로 바랜다: 글자 색은 큰 글자 색 그대로 불투명도 1 → 0.16(선형), 그림자 불투명도 0.20 → 0, 그림자 오프셋 그대로(매트에 눌려 붙는다). 줄 i 의 지난 글자는 ★그 줄의 첫 키 0.30초 전에 비켜 사라진다: v = 0 → 1(0.30초, 선형) 동안 글자 불투명도 0.16·(1 − v)², 배율 1 → 1.04(easeOutCubic, 줄 가운데 기준), 위로 0.015H·easeOutCubic(v). 그림자는 그리지 않는다 — 옅은 글자는 종이가 아니라 매트에 남은 자국이라, 그림자를 주면 글자(0.16)보다 짙은 그림자가 생겨 같은 글자 두 벌(이중 인쇄)로 보인다. 「들림」(그림자가 벌어짐)은 시그니처의 불투명한 조각에만 쓴다. 기본 문장이면 1줄 0.50~0.80 · 2줄 2.66~2.96 · 3줄 4.49~4.79초. 그래서 지금 치는 줄의 칸만 비고, 아랫줄은 옅은 지난 글자가 그 자리를 늘 채운다. 지난 글자는 지금 치는 줄에 없으므로 「비행 중 도착 칸은 비어 있다」 규칙과 부딪히지 않는다. 아래 틈(③)의 「아랫줄 잉크 위끝」은 지난 글자에도 같다(같은 칸·같은 글자다). 0.50초부터(1줄이 비키기 시작) 1줄 첫 칸 앞(x0 + 0.02em)에 커서가 켜지고, 첫 키 0.80 에 조립 중 칸이 생기며 꺼진다.
- 첫 키 tk = 0.80초. 다음 키까지의 간격(아래 다섯 값과 도깨비불 추가 틈에 박자 값을 곱한다):
  손이 바뀜(자음 → 모음, 모음 → 자음 — 두벌식은 자음이 왼손, 모음이 오른손): 0.17초
  같은 손 연타(자음 → 자음, 모음 → 모음): 0.23초
  이 두 값에 낱말 빠르기를 곱한다: 첫 낱말 ×1.15, 둘째부터 ×1.0.
  띄어쓰기로 들어가는 간격 0.24초, 띄어쓰기에서 나오는 간격 0.28초(낱말 빠르기 곱하지 않음).
  도깨비불을 일으킨 키 다음 간격에는 0.20초를 더한다(다음 키가 띄어쓰기여도 더한다). 박자를 곱한 뒤에도 이 간격은 0.36초(비행 0.26 + 0.10)보다 짧아지지 않게 한다 — 착지 전에 다음 키가 눌리면 안 된다.
- 기본 문장의 결과(검산용, 반올림): ㅁ 0.80 · ㅏ 1.00 · ㅇ 1.19 · ㅡ 1.39(도깨비불 → 착지 1.65) · ㅁ 1.78 · ㅇ 2.05 · ㅡ 2.24 · ㄹ 2.44 · ␣ 2.68 · ㅎ 2.96 · ㅏ 3.13 · ㄴ 3.30 · ㄱ 3.53 · ㅡ 3.70 · ㄹ 3.87 · ㄹ 4.10 · ㅗ 4.27 · ␣ 4.51 · ㄱ 4.79 · ㅡ 4.96 · ㄹ 5.13 · ㅣ 5.30(도깨비불 → 착지 5.56) · ㄷ 5.67 · ㅏ 5.84(도깨비불 → 착지 6.10).
- 시그니처 순간 = 1.39~1.65초: 옥색 ㅡ 키가 눌리는 순간, 맨 윗줄 첫 칸 「망」의 아래쪽 ㅇ 이 빠져나와(S ≈ 0.207W, 0.174H) 그림자를 떼며 들리고, 오른쪽 아래로 살짝 떨어졌다가 가운데 칸으로 쓸어 올라가 「으」의 첫소리 자리(D ≈ 0.500W, 0.106H)에 내려앉으며 그림자가 다시 붙는다. 화면을 연 지 1.4초 만에 온다.
- 머묾: 마지막 키 뒤 1.16초. 「다」는 조립 중 표시 그대로다(그래서 커서는 없다).
- 길이 = 마지막 키 + 1.16초 = 기본 문장 약 7.0초(6.998). 끝 프레임 = 0초 프레임(세 줄 + 조립 중 「다」, 커서 없음, 지난 글자 없음 — 3줄 지난 글자는 4.79초에 이미 사라졌다, 모든 키 p = 0)이라 이음매 없이 반복된다. 검산: 0초~0.15초는 바램이 시작되기 전이라 지난 문장 장치가 이음매에 끼어들지 않는다.

[구현]
- HTML 파일 하나로 만든다. 외부 파일·글꼴·라이브러리·네트워크 요청을 쓰지 않는다(미리보기에서 막히거나 느려진다).
- 첫 <script> 맨 앞에 CONFIG 객체를 두고 [바꿀 곳]의 값과 이 글에 나온 숫자(시간표·크기·색·세기)를 이름 붙여 모은다. 나중에 숫자만 바꿔 다듬을 수 있게.
- 그림은 시간 t(초)만으로 계산하는 함수 render(t) 로 그린다. requestAnimationFrame 의 타임스탬프나 performance.now() 로 t 를 구한다. setTimeout·setInterval·CSS 애니메이션·transition 으로 움직이지 않는다(프레임마다 속도가 달라지고, 다시 재생할 때 어긋난다). 시뮬레이션처럼 상태가 쌓이는 작품은 고정 시간 간격으로 상태를 진행하되 그 진행도 타임스탬프로만 정한다.
- 난수는 시드 고정 난수(mulberry32 등)만 쓴다. Math.random 은 쓰지 않는다(매번 다른 화면이 나온다).
- 캔버스 내부 해상도는 화면비에 맞춘 기준 크기로 고정하고, 창 크기에 맞춰 화면비를 지키며 가운데에 꽉 차게 보이게 한다(남는 곳은 배경색). 스크롤이 생기지 않게 한다. devicePixelRatio 는 그리는 선명도에만 반영한다.
- 글자는 시스템 글꼴만 쓴다: 'Pretendard', 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif. 붓글씨·손글씨 느낌은 글꼴이 아니라 획을 그려서 낸다.
- 길이가 정해진 작품은 끝나면 처음과 같은 화면으로 돌아가 이음매 없이 반복한다.
- 모든 함수·상수·셰이더 문자열을 먼저 정의하고, 시작(초기화와 첫 requestAnimationFrame)은 스크립트 맨 끝에서 한 번만 호출한다. 정의되기 전에 쓰면 첫 화면에서 멈춘다.
- 이 작품의 기준 크기는 1080×1920 이다. 창의 남는 곳(배경색)은 책상 매트 색이다.
- 시작할 때(document.fonts.ready 뒤) 한 번: 바닥 한 장(실제 픽셀 크기, 쉬는 자판 포함 — 창 크기가 바뀌면 다시)과 키 윗면 그라디언트 → 문장 → 키 목록 → 입력 시각 → 키마다 화면 상태(줄별 칸 목록: 글자, 조립 중 여부, 마지막 사건 시각과 종류, 배율 중심) → 도깨비불 목록(시각, 출발·도착 칸, 조각·조각 그림자판·지운 그림·지운 그림 그림자판 캔버스, S·D·Dw·Dh·dip·tc·P2.x 이동)을 만들어 두고, [바꿀 곳]의 대비 표와 [받침 조각] 7) 의 자체 대조 표를 출력한다. render(t) 는 t 이하인 마지막 사건의 상태를 찾아 그리기만 한다. t < 첫 키 에서는 「다 친 상태」 → 엔터 → 바램 → 1줄 비키기를 그리고, 각 줄의 지난 글자는 그 줄이 비킬 때까지 그린다. 프레임 사이에 값을 쌓지 않는다.
- CONFIG 에 박자 배율·키 간격 다섯 값·낱말 빠르기·도깨비불 최소 간격·눌림 구간·깊이·그림자(글자 그림자 오프셋·불투명도, 들림 배수 3·옅어짐 0.45, 키·몸체 그림자)·햇빛 띠(중심·각도·두께·가장자리·불투명도)·매트 결 세기·스프링 두 개·비행 시간·dip·크기 맞추기 시작점 0.6·기울기·머묾·엔터·바램(0.21~0.45, 0.16)·비키기(첫 키 0.30초 전, 1.04)·출발 글자 최소 거리(0.04em, 이동 0.04 씩 최대 0.24)·프레임 경고 20ms 숫자를 모두 넣는다.

[하지 말 것]
- 날아가는 받침을 호환 자모 글자(ㅇ, ㄹ 등)로 따로 그리지 않는다 — 받침 자리의 자모는 납작하고 작은데 획 굵기는 글자 전체와 같아서, 따로 그린 호환 자모와 모양·굵기가 다르다. 떨어져 나오는 첫 프레임에 조각이 갑자기 커지고 굵어지며 튄다.
- 받침을 「줄 전체가 비는 빈 줄」로만 찾지 않는다 — 많은 고딕 글꼴(이 글꼴 목록의 첫째 Pretendard 포함)에서 모음 세로획 끝과 받침 위끝이 같은 높이에 있어 빈 줄이 없다. 그러면 조각이 조용히 사라지고 시그니처가 통째로 없어진다. 성분 → 줄 → 경고 순서를 지킨다.
- 조각 계산이 실패했는데 아무 말 없이 넘어가지 않는다 — 콘솔 경고와 자체 대조 표가 없으면 시그니처가 빠진 영상을 정상으로 믿게 된다.
- 마스크를 늘릴 때 보간하지 않고, 마스크 둘레를 알파로 고르지 않는다 — 지운 그림에 빠진 받침의 윤곽이 1px 선으로 남아 「유령」처럼 보인다.
- 착지에 0.65 에서 시작하는 스프링을 쓰지 않는다 — 크기를 맞춰 내려앉은 첫소리가 한 프레임에 반으로 꺼졌다가 다시 부풀어 움찔해 보인다.
- 조각을 윗줄 쪽으로 높이 띄우는 포물선으로 날리지 않는다 — 윗줄 글자에 닿을 듯이 붙고, 출발 글자의 모음 위를 덮고 지나간다. 아래로 떨어졌다 빈 칸 안에서 올라오는 길이 두 문제를 다 피한다. 「들림」은 위치가 아니라 그림자 거리로 보여 준다.
- 「들림」을 조각 크기로 크게 키우지 않는다(범프 0.10 그대로) — 커진 조각이 아랫줄·자판 쪽 틈을 먹어 dip 이 바닥(0.10em)에 붙고, 출발 글자 모음에 닿는다.
- 글자가 바뀔 때 모핑·크로스페이드를 넣지 않는다 — 실제 입력기는 한 프레임에 바뀌고, 모양이 다른 두 글자(ㅎ 과 하)가 겹쳐 보이면 유령 같은 덧그림이 남는다. 바뀜의 맛은 배율 스프링이 맡는다.
- 완성 음절을 한 번에 띄우는 타자기 효과로 만들지 않는다 — ㅎ → 하 → 한, 한ㄱ, 마으 같은 중간 상태가 이 작품의 볼거리 전부다. 중간 상태를 손으로 적은 목록으로 만들지 말고 반드시 오토마타로 계산한다(문장을 바꾸면 손 목록은 틀린다).
- 타자 중에 칸을 다시 가운데 정렬하지 않는다 — 글자가 생길 때마다 줄 전체가 좌우로 밀리면 조립이 안 읽힌다. 칸은 최종 문장으로 처음부터 고정한다.
- 큰 글자를 화면 가운데 작게 두지 않는다 — 세로 화면의 위쪽이 비면 자판 시연 화면처럼 보인다. 칸 크기 공식(폭 88%)을 지킨다.
- 빈 화면으로 시작하지 않는다 — 세로 영상은 첫 1초에 넘겨진다. 0초는 다 쳐진 문장이고, 엔터로 문장이 바래고 첫 줄이 책상에서 들려 비키는 움직임이 첫 1초를 맡는다.
- 「도깨비불」이라는 이름 때문에 불꽃·발광·글로우·잔상 꼬리를 붙이지 않는다 — 이름은 입력기 현상의 별명일 뿐이다. 빛 효과는 받침의 실제 모양을 가리고 흔한 모션 템플릿처럼 보이게 한다.
- 햇빛을 빛줄기·렌즈 플레어·먼지 입자로 꾸미지 않고, 글자나 자판 위에 덮지 않는다 — 빛은 매트에 비친 띠 하나다. 글자 위를 덮으면 대비가 자리마다 달라지고, 꾸밈은 주인공(글자 조립)과 눈길을 다툰다.
- 바닥(매트 결·햇빛 띠)을 매 프레임 새로 만들거나, 흔들거나, 기준 크기로 구워 늘여 그리지 않는다 — 결이 움직이면 화면 전체가 지글거리고, 화면 크기 그라디언트 채움이나 늘여 그리기 한 번이 프레임률을 절반으로 만든다. 바닥은 실제 픽셀 크기 한 장으로 굽고 1:1 로 깐다.
- 자판을 원근으로 기울이지 않는다 — 키 좌표와 틈 계산이 전부 어긋나고, 멀어진 윗줄 키 글자가 작아져 안 읽힌다. 책상 위 물건 느낌은 한 방향 빛의 단단한 그림자로 낸다.
- 파티클·장식 입자를 쓰지 않는다 — 움직이는 것은 키와 글자와 받침 조각뿐이어야 「눌렀더니 이렇게 됐다」가 읽힌다.
- 손이나 손가락을 그리지 않는다 — 키를 가리고, 그려 넣은 손은 어색하다. 눌림은 키의 깊이와 그림자로만 보인다.
- 키 위에 눌린 글자를 크게 띄우는 말풍선(휴대폰 자판 미리보기)을 넣지 않는다 — 눈이 아래로 끌려 위쪽의 조립 순간을 놓치고, 같은 정보가 두 번 나온다.
- 흐린 그림자(shadowBlur·filter)를 쓰지 않는다 — shadowBlur 는 캔버스 변환을 따르지 않아 화면 크기마다 그림자가 달라지고, 키 33개에 매 프레임 쓰면 휴대폰에서 끊긴다. 단단한 그림자가 눌림 깊이와 들린 높이도 더 또렷이 보여 준다.
- 바탕을 검정·남색으로 바꾸지 않는다 — 단단한 그림자가 보이지 않아 책상 위 물건이라는 물성이 통째로 사라진다.
- 키에 영문을 같이 찍지 않는다 — 글자가 작아지고 어수선해진다. 키 글자는 한글 자모 하나다.
- 조립 중인 글자 옆에 커서를 그리지 않는다 — 같은 색 세로 막대가 모음 ㅣ 로 읽혀 ㅁ 이 「미」가 된다.
- 비키는 지난 글자에 그림자를 주지 않는다 — 불투명도 0.16 짜리 옅은 글자에 그림자를 주면 그림자가 글자보다 짙어져, 들림이 아니라 초점이 나간 이중 인쇄로 보인다. 첫 1초 안(0.50~0.80초)에 일어나 첫인상을 깎는다.
- 쉬는 자판 34키를 매 프레임 다시 그리지 않는다 — 키 하나가 여섯 번 그려져 200번이 넘고, 휴대폰급 CPU 에서 프레임률이 절반 아래로 떨어져 0.26초 비행이 끊긴다. 쉬는 자판은 바닥에 굽고 눌린 키만 다시 그린다.
- 지난 문장을 화면 밖으로 날려 보내 비우지 않는다 — 첫 줄을 치는 동안 위쪽 화면 2/3 가 빈 매트가 되고, 시그니처가 빈 화면 구석에서 일어난다.
- 커서를 깜빡이지 않는다 — 깜빡임이 조립 순간과 눈길을 다투고, 반복 이음매에서 켜짐·꺼짐이 어긋나 한 프레임 튄다.
- 박자에 무작위 흔들림을 넣지 않는다 — 박자는 손 바뀜 규칙이 만든다. 무작위 간격은 도깨비불 착지 전에 다음 키가 눌리는 겹침을 만든다.
- 실제 키보드·휴대폰 상표나 로고를 넣지 않는다 — 이 작품은 특정 제품이 아니라 두벌식 배열 자체를 보여 준다.

사용 방법

필요한 것: claude.ai 계정 — 무료 계정에서도 Claude Opus 5.5 를 고를 수 있습니다

  1. claude.ai 에서 새 대화를 엽니다.
  2. 모델 메뉴에서 Claude Opus 5.5 를 고르고, 같은 메뉴의 Effort(답변 깊이)를 High 로 둡니다.
  3. 복사한 프롬프트를 붙여 넣고 전송합니다. 결과로 나온 HTML 파일을 브라우저로 열면 재생됩니다.
권장 모델
Claude Opus 5.5 · Effort High
화면비
9:16 (세로)
재생 길이
7초
결과물
HTML 파일 하나 · 따로 설치할 것 없음
영상 파일
위 「MP4 저장 기능 포함」을 켜면 결과 화면에 녹화 단추가 생깁니다 1080 기준 · 12 Mbps · 브라우저에 따라 MP4 또는 WebM

추가 요청 예시

결과가 나온 뒤 같은 대화에서 이어서 요청하면 해당 부분만 수정됩니다.

  • 문장을 「닭갈비 먹고 싶다」로 바꿔 줘. 닭갈 다음에 ㅂ 을 치면 「닭갋」이 됐다가 ㅣ 를 치는 순간 ㅂ 만 들려 넘어가 「닭갈비」가 되는 걸 보고 싶어.
  • 밤 책상으로 바꿔 줘. 매트를 먹갈색 호두나무(#2A211B)로, 햇빛 띠 대신 오른쪽 위 스탠드의 따뜻한 불빛(#F1C27D, 같은 띠 모양에 불투명도 0.18)으로, 큰 글자를 #F3EBDD, 강조색을 #FF7A45 로 하고 그림자 불투명도는 0.35 로 올려 줘.
  • 타자를 1.5배 천천히 치게 하고, 문장이 다 쳐진 뒤 머무는 시간도 2초로 늘려 줘.

한글

같은 카테고리의 다른 프롬프트

한글 전체 보기

모든 모션 보기 블로그 글 목록 RSS 로 새 글 받기