// ─────────────────────────────────────────────
// Word database (built-in for demo)
// ─────────────────────────────────────────────
const WORD_DB = {
get: {
word: "get",
pos: "동사 (verb)",
rootLang: "고대 노르웨이어 (Old Norse)",
rootWord: "geta",
rootMeaning: "손에 넣다, 도달하다",
rootSentence: "🤲 바이킹들이 쓴 geta는 '무언가를 손에 넣다'는 뜻이에요",
definition: "영어에서 가장 많이 쓰이는 동사 중 하나예요. 단순히 가지고 있는 것(have)이 아니라, '없던 상태에서 있는 상태로 바뀌는 과정' 자체를 표현해요. 그래서 '얻다', '되다', '도착하다', '이해하다'까지 모두 하나의 뿌리에서 나왔답니다!",
example: "I finally got a new bike! (마침내 새 자전거를 얻었어요!)",
rootVisual: {
beforeEmoji: "🫙",
beforeLabel: "없는 상태",
afterEmoji: "🤲",
afterLabel: "내 것!",
arrowWord: "get",
arrowKor: "→ 이 움직임!",
headline: "'내 영역 밖'에 있던 것이 '내 영역 안'으로 들어오는 움직임",
sub: "손을 뻗어 바깥의 무언가를 끌어당겨 내 것으로 만드는 애니메이션을 상상해보세요!"
},
branches: [
{
tag: "물건·정보 획득",
cls: "bc-1",
meaning: "얻다 / 받다 / 사다",
ko: '(메일이 내 메일함 안으로 들어옴 → 받았다)',
ex: 'I got an email from her.',
exKo: '그녀에게서 이메일을 받았어요.'
},
{
tag: "상태 변화",
cls: "bc-2",
meaning: "~하게 되다 / ~해지다",
ko: '(밝은 상태 밖 → 어두운 상태 안으로 진입 중)',
ex: 'It is getting dark.',
exKo: '날이 어두워지고 있어요.'
},
{
tag: "이해·깨달음",
cls: "bc-3",
meaning: "이해하다 / 알아듣다",
ko: '(정보가 드디어 내 머릿속 안으로 들어옴!)',
ex: 'I got it! 💡',
exKo: '알겠어요! 이해했어요!'
},
{
tag: "장소 이동",
cls: "bc-4",
meaning: "도착하다 / ~에 가다",
ex: 'How do I get to the station?',
ko: '(역이라는 공간 안으로 들어가는 방법은?)',
exKo: '역에는 어떻게 가나요?'
}
],
images: [
{ emoji: "🤲", cls: "sic-1", word: "get (획득)", desc: "바깥에 있던 것을\n내 손 안으로 끌어당김" },
{ emoji: "🔄", cls: "sic-2", word: "get (변화)", desc: "A 상태에서 B 상태로\n서서히 바뀌어 들어감" },
{ emoji: "📍", cls: "sic-3", word: "get (도착)", desc: "목적지라는 공간 안으로\n쏙 들어가 도달함" }
],
idioms: [
{ icon: "⏰", phrase: "run out of → get out of", meaning: "~에서 벗어나다", example: "I need to get out of this situation." },
{ icon: "🤝", phrase: "get along with", meaning: "~와 잘 지내다", example: "She gets along with everyone." },
{ icon: "🔄", phrase: "get over", meaning: "극복하다, 회복하다", example: "It takes time to get over a cold." }
],
family: [
{ en: "forget", ko: "잊다" },
{ en: "beget", ko: "낳다" },
{ en: "gotten", ko: "얻어진 (과거분사)" },
{ en: "begat", ko: "낳았다 (성경체)" },
{ en: "get-together", ko: "모임" }
]
},
flower: {
word: "flower",
pos: "명사 (noun)",
rootLang: "라틴어 (Latin)",
rootWord: "flos / floris",
rootMeaning: "피어나다, 꽃",
rootSentence: "🌸 flos(피어나다) → 땅 속에 숨어있다 밖으로 터져 나오는 것",
definition: "식물에서 피어나는 꽃. '내부에 있던 아름다움이 밖으로 터져나오는 과정'이 핵심 이미지예요. 꽃처럼 '잠재된 것이 드러나는' 모든 것에 이 뿌리가 쓰여요.",
example: "The cherry flowers are beautiful in spring. (봄에 벚꽃이 아름다워요.)",
rootVisual: {
beforeEmoji: "🌱",
beforeLabel: "땅 속",
afterEmoji: "🌸",
afterLabel: "피어남!",
arrowWord: "flos",
arrowKor: "→ 터져나옴",
headline: "땅 속에 숨어있던 것이 밖으로 활짝 터져나오는 움직임",
sub: "꽃뿐 아니라 재능·번영이 '피어나는' 것도 모두 같은 이미지예요!"
},
branches: [
{
tag: "꽃 자체",
cls: "bc-1",
meaning: "꽃, 화초",
ko: '(씨앗 속에 숨어있던 것이 밖으로 피어난 것 그 자체)',
ex: 'She loves flowers.',
exKo: '그녀는 꽃을 좋아해요.'
},
{
tag: "번성·번영",
cls: "bc-2",
meaning: "flourish: 번성하다",
ko: '(사업이 꽃처럼 활짝 피어나고 있어)',
ex: 'Business is flourishing.',
exKo: '사업이 번성하고 있어요.'
},
{
tag: "밀가루",
cls: "bc-3",
meaning: "flour: 꽃처럼 고운 가루",
ko: '(꽃처럼 가장 고운 부분 → 밀가루)',
ex: 'Add flour to the bowl.',
exKo: '그릇에 밀가루를 넣으세요.'
},
{
tag: "전성기",
cls: "bc-4",
meaning: "in full flower: 한창때",
ko: '(활짝 다 피어난 상태 = 전성기)',
ex: 'She is in full flower.',
exKo: '그녀는 지금 전성기예요.'
}
],
images: [
{ emoji: "🌱", cls: "sic-1", word: "씨앗 속에 숨어", desc: "땅 속 어둠 안에\n잠재된 아름다움" },
{ emoji: "🌸", cls: "sic-2", word: "flower (피어남)", desc: "flos — 내부의 것이\n밖으로 활짝 터져나옴" },
{ emoji: "✨", cls: "sic-3", word: "flourish (번성)", desc: "꽃처럼 재능·번영이\n세상 밖으로 뻗어나감" }
],
idioms: [
{ icon: "🌷", phrase: "flower garden", meaning: "꽃밭, 화원", example: "We planted roses in our flower garden." },
{ icon: "🌺", phrase: "in full flower", meaning: "전성기에, 활짝 피어", example: "She is in full flower as a singer." },
{ icon: "🌼", phrase: "flower girl", meaning: "꽃을 뿌리는 아이", example: "The flower girl walked down the aisle." }
],
family: [
{ en: "flour", ko: "밀가루" },
{ en: "flourish", ko: "번성하다" },
{ en: "floral", ko: "꽃의" },
{ en: "blossom", ko: "꽃피다" },
{ en: "bloom", ko: "개화" }
]
},
run: {
word: "run",
pos: "동사 (verb)",
rootLang: "고대영어 (Old English)",
rootWord: "rinnan / irnan",
rootMeaning: "흐르다, 달리다",
rootSentence: "💧 rinnan(흐르다) → 물이 지형을 따라 쉼없이 앞으로 나아가는 것",
definition: "달리다, 흐르다. '물처럼 멈추지 않고 계속 앞으로 나아가는 것'이 핵심 이미지예요. 사람이 달리는 것, 강이 흐르는 것, 프로그램이 실행되는 것 모두 같은 뿌리에서 나왔어요.",
example: "She runs to school every morning. (그녀는 매일 아침 학교에 달려가요.)",
rootVisual: {
beforeEmoji: "🏔️",
beforeLabel: "높은 곳",
afterEmoji: "🌊",
afterLabel: "아래로!",
arrowWord: "rinnan",
arrowKor: "→ 쉼없이 흐름",
headline: "물처럼 멈추지 않고 계속 앞으로 나아가는 움직임",
sub: "사람이 달리든, 강이 흐르든, 기계가 작동하든 — 모두 같은 '흐름'의 이미지예요!"
},
branches: [
{
tag: "사람·동물",
cls: "bc-1",
meaning: "달리다",
ko: '(두 발이 물처럼 앞으로 흘러감)',
ex: 'She runs fast.',
exKo: '그녀는 빠르게 달려요.'
},
{
tag: "물·액체",
cls: "bc-2",
meaning: "흐르다",
ko: '(강이 바다를 향해 쉬지 않고 흘러감)',
ex: 'The river runs to the sea.',
exKo: '강은 바다로 흘러가요.'
},
{
tag: "기계·프로그램",
cls: "bc-3",
meaning: "작동하다, 실행되다",
ko: '(프로그램이 물 흐르듯 실행됨)',
ex: 'The app runs smoothly.',
exKo: '앱이 부드럽게 실행돼요.'
},
{
tag: "다 소진",
cls: "bc-4",
meaning: "run out: 다 떨어지다",
ko: '(흐르던 것이 다 빠져나감 → 소진)',
ex: 'We ran out of time.',
exKo: '우리는 시간이 다 떨어졌어요.'
}
],
images: [
{ emoji: "💧", cls: "sic-1", word: "rinnan (흐름)", desc: "멈추지 않고 계속\n앞으로 흘러가는 힘" },
{ emoji: "🏃", cls: "sic-2", word: "run (달리다)", desc: "물처럼 쉼없이\n앞으로 나아가는 몸" },
{ emoji: "⚡", cls: "sic-3", word: "run (실행)", desc: "프로그램도 물 흐르듯\n쉬지 않고 작동함" }
],
idioms: [
{ icon: "⏰", phrase: "run out of", meaning: "~이 다 떨어지다", example: "We ran out of time." },
{ icon: "🏥", phrase: "run into", meaning: "우연히 만나다", example: "I ran into my old friend." },
{ icon: "🔄", phrase: "run away", meaning: "도망치다", example: "Don't run away from problems." }
],
family: [
{ en: "runner", ko: "달리는 사람" },
{ en: "runway", ko: "활주로" },
{ en: "runoff", ko: "유출수" },
{ en: "outrun", ko: "앞질러 달리다" },
{ en: "overrun", ko: "넘쳐나다" }
]
},
light: {
word: "light",
pos: "명사/형용사 (noun/adj)",
rootLang: "인도유럽어 (PIE)",
rootWord: "*leuk-",
rootMeaning: "빛나다, 보이다",
rootSentence: "☀️ *leuk(빛나다) → 어둠 속에 가려진 것을 밖으로 드러내는 것",
definition: "빛, 밝음. '어둠에 가려 보이지 않던 것이 드러나는 과정'이 핵심 이미지예요. 물리적인 빛뿐 아니라 '진실이 드러나다', '마음이 밝아지다'도 모두 같은 뿌리에서 나왔어요.",
example: "The light from the sun warms the earth. (햇빛이 지구를 따뜻하게 해요.)",
rootVisual: {
beforeEmoji: "🌑",
beforeLabel: "어둠 속",
afterEmoji: "✨",
afterLabel: "드러남!",
arrowWord: "*leuk",
arrowKor: "→ 밝혀짐",
headline: "어둠 속에 가려져 있던 것이 빛에 의해 환히 드러나는 순간",
sub: "물리적 빛뿐 아니라 '진실이 밝혀지다', '깨달음을 얻다'도 모두 같은 이미지!"
},
branches: [
{
tag: "물리적 빛",
cls: "bc-1",
meaning: "빛, 광원",
ko: '(어둠을 밀어내고 공간을 드러냄)',
ex: 'Turn on the light.',
exKo: '불을 켜세요.'
},
{
tag: "계몽·깨달음",
cls: "bc-2",
meaning: "enlighten: 계몽하다",
ko: '(무지의 어둠에 빛을 넣어줌)',
ex: 'Books enlighten us.',
exKo: '책은 우리를 깨우쳐 줘요.'
},
{
tag: "진실 드러남",
cls: "bc-3",
meaning: "come to light: 밝혀지다",
ko: '(숨겨진 진실이 빛 속으로 나옴)',
ex: 'The truth came to light.',
exKo: '진실이 밝혀졌어요.'
},
{
tag: "가벼움",
cls: "bc-4",
meaning: "light: 가벼운",
ko: '(무겁지 않음 → 빛처럼 가벼운)',
ex: 'This bag is very light.',
exKo: '이 가방은 매우 가벼워요.'
}
],
images: [
{ emoji: "🌑", cls: "sic-1", word: "어둠 속 감춰짐", desc: "*leuk — 빛 없이는\n아무것도 보이지 않음" },
{ emoji: "☀️", cls: "sic-2", word: "light (빛)", desc: "어둠을 밀어내고\n모든 것을 드러냄" },
{ emoji: "💡", cls: "sic-3", word: "enlighten (계몽)", desc: "무지의 어둠 속에\n빛을 넣어 깨우침" }
],
idioms: [
{ icon: "🌅", phrase: "in the light of", meaning: "~에 비추어, 고려하면", example: "In the light of new facts, we changed our plan." },
{ icon: "💡", phrase: "come to light", meaning: "밝혀지다, 드러나다", example: "The truth finally came to light." },
{ icon: "🕯️", phrase: "light up", meaning: "밝아지다, 빛내다", example: "Her face lit up with joy." }
],
family: [
{ en: "lightning", ko: "번개" },
{ en: "enlighten", ko: "계몽하다" },
{ en: "illuminate", ko: "밝히다" },
{ en: "lucid", ko: "명쾌한" },
{ en: "lunar", ko: "달의" }
]
},
heart: {
word: "heart",
pos: "명사 (noun)",
rootLang: "인도유럽어 (PIE)",
rootWord: "*kerd-",
rootMeaning: "심장, 핵심",
rootSentence: "❤️ *kerd(두근두근) → 모든 것의 가장 깊은 중심에서 뛰는 것",
definition: "심장, 마음. '모든 것의 가장 중심·핵심에 있는 것'이 핵심 이미지예요. 몸의 중심에서 뛰는 심장처럼, '용기(courage)'도 마음의 중심에서 나온다는 뜻을 담고 있어요.",
example: "My heart beats fast when I'm excited. (흥분하면 심장이 빨리 뛰어요.)",
rootVisual: {
beforeEmoji: "🫀",
beforeLabel: "몸의 중심",
afterEmoji: "💪",
afterLabel: "힘의 원천!",
arrowWord: "*kerd",
arrowKor: "→ 중심에서 퍼짐",
headline: "모든 것의 가장 깊은 중심에서 에너지가 뿜어져 나오는 것",
sub: "심장이 온몸에 피를 퍼뜨리듯, 이 뿌리도 '핵심', '용기', '감정'으로 퍼져나가요!"
},
branches: [
{
tag: "신체 기관",
cls: "bc-1",
meaning: "심장",
ko: '(몸의 중심에서 뛰는 기관)',
ex: 'My heart is beating fast.',
exKo: '내 심장이 빠르게 뛰고 있어요.'
},
{
tag: "감정·마음",
cls: "bc-2",
meaning: "마음, 감정의 중심",
ko: '(감정이 살아있는 내면의 중심)',
ex: 'She has a kind heart.',
exKo: '그녀는 따뜻한 마음을 가졌어요.'
},
{
tag: "용기",
cls: "bc-3",
meaning: "courage: 심장에서 나오는 힘",
ko: '(마음의 중심에서 나오는 용기)',
ex: 'It takes courage.',
exKo: '그것은 용기가 필요해요.'
},
{
tag: "기억·암기",
cls: "bc-4",
meaning: "by heart: 마음으로 새기다",
ko: '(마음 깊이 새겨두는 것 = 암기)',
ex: 'Learn it by heart.',
exKo: '그것을 외워두세요.'
}
],
images: [
{ emoji: "🫀", cls: "sic-1", word: "*kerd (중심)", desc: "몸의 가장 깊은 곳\n중심에서 뛰는 것" },
{ emoji: "❤️", cls: "sic-2", word: "heart (마음)", desc: "감정과 의지가\n솟아나는 원천" },
{ emoji: "💪", cls: "sic-3", word: "courage (용기)", desc: "마음 중심(cor)에서\n뻗어나오는 힘" }
],
idioms: [
{ icon: "💝", phrase: "by heart", meaning: "암기하여, 외워서", example: "I learned the poem by heart." },
{ icon: "🤗", phrase: "take heart", meaning: "용기를 내다", example: "Take heart! You can do it!" },
{ icon: "💔", phrase: "lose heart", meaning: "낙담하다, 용기를 잃다", example: "Don't lose heart after one failure." }
],
family: [
{ en: "heartbeat", ko: "심장박동" },
{ en: "heartfelt", ko: "진심의" },
{ en: "cardiac", ko: "심장의" },
{ en: "courage", ko: "용기" },
{ en: "core", ko: "핵심" }
]
},
book: {
word: "book",
pos: "명사 (noun)",
rootLang: "고대영어 (Old English)",
rootWord: "bōc / bēce",
rootMeaning: "너도밤나무, 기록",
rootSentence: "🌳 bōc(너도밤나무) → 나무껍질에 칼로 새겨 넣는 것",
definition: "책. '나무에 흔적을 새겨 넣어 영원히 남기는 행위'가 핵심 이미지예요. 너도밤나무(beech) 껍질에 룬 문자를 새겼던 게르만족에서 유래했어요.",
example: "I read three books this summer. (이번 여름에 책 세 권을 읽었어요.)",
rootVisual: {
beforeEmoji: "🌳",
beforeLabel: "나무껍질",
afterEmoji: "📖",
afterLabel: "영원한 기록!",
arrowWord: "bōc",
arrowKor: "→ 새겨 넣음",
headline: "사라지는 말을 나무에 새겨영원히 남기는 행위",
sub: "책(book)과 너도밤나무(beech)가 같은 뿌리! 나무껍질이 최초의 종이였어요."
},
branches: [
{
tag: "물리적 책",
cls: "bc-1",
meaning: "책, 교재",
ko: '(새겨진 기록들의 묶음)',
ex: 'Open your book.',
exKo: '책을 펼쳐요.'
},
{
tag: "예약",
cls: "bc-2",
meaning: "예약하다 (이름을 새기다)",
ko: '(장부에 내 이름을 새겨 넣음 → 예약)',
ex: 'I booked a ticket.',
exKo: '나는 표를 예약했어요.'
},
{
tag: "기록·장부",
cls: "bc-3",
meaning: "the books: 장부, 회계기록",
ko: '(수치를 새겨 넣은 기록 → 장부)',
ex: 'Check the books.',
exKo: '장부를 확인하세요.'
},
{
tag: "처벌",
cls: "bc-4",
meaning: "book sb: 기소하다",
ko: '(경찰 기록에 이름을 새김 → 입건)',
ex: 'He was booked by police.',
exKo: '그는 경찰에 입건됐어요.'
}
],
images: [
{ emoji: "🌳", cls: "sic-1", word: "beech (너도밤나무)", desc: "게르만족이 껍질에\n룬 문자를 새겼던 나무" },
{ emoji: "✍️", cls: "sic-2", word: "bōc (새겨 넣기)", desc: "사라지는 말을\n영원히 남기는 행위" },
{ emoji: "📖", cls: "sic-3", word: "book (책)", desc: "새겨진 기록들을\n엮어 만든 것" }
],
idioms: [
{ icon: "📅", phrase: "book in advance", meaning: "미리 예약하다", example: "Please book your seat in advance." },
{ icon: "📕", phrase: "by the book", meaning: "규칙대로, 원칙대로", example: "He always does things by the book." },
{ icon: "😤", phrase: "in someone's bad books", meaning: "누군가의 미움을 사다", example: "I'm in her bad books after being late." }
],
family: [
{ en: "booklet", ko: "소책자" },
{ en: "notebook", ko: "공책" },
{ en: "bookmark", ko: "책갈피" },
{ en: "bookstore", ko: "서점" },
{ en: "beech", ko: "너도밤나무" }
]
},
water: {
word: "water",
pos: "명사 (noun)",
rootLang: "인도유럽어 (PIE)",
rootWord: "*wed- / *wod-",
rootMeaning: "물, 젖다",
rootSentence: "💧 *wed(젖다) → 건조한 것을 적셔서 생명이 깃들게 하는 것",
definition: "물. '건조하고 딱딱한 것에 스며들어 부드럽고 생기있게 만드는 것'이 핵심 이미지예요. 라틴어 unda(파도), 그리스어 hydor(물)도 모두 같은 뿌리예요.",
example: "We need clean water to live. (우리는 살기 위해 깨끗한 물이 필요해요.)",
rootVisual: {
beforeEmoji: "🏜️",
beforeLabel: "건조한 땅",
afterEmoji: "🌿",
afterLabel: "생명 깃듦!",
arrowWord: "*wed",
arrowKor: "→ 스며듦",
headline: "메마른 것 속으로 물이 스며들어 생명을 불어넣는 과정",
sub: "water, wave, otter, hydro- 모두 이 하나의 뿌리에서 나왔어요!"
},
branches: [
{
tag: "물 자체",
cls: "bc-1",
meaning: "물, 음료",
ko: '(생명을 적시는 물질 그 자체)',
ex: 'Drink some water.',
exKo: '물을 마셔요.'
},
{
tag: "희석",
cls: "bc-2",
meaning: "water down: 물을 타다",
ko: '(강한 것 속에 물이 스며들어 약해짐)',
ex: 'She watered down the juice.',
exKo: '그녀는 주스를 물로 희석했어요.'
},
{
tag: "파도",
cls: "bc-3",
meaning: "wave: 파도 (같은 뿌리!)",
ko: '(unda → wave, 물의 움직임)',
ex: 'The waves are huge today.',
exKo: '오늘 파도가 엄청 높아요.'
},
{
tag: "수소",
cls: "bc-4",
meaning: "hydrogen: 물을 만드는 것",
ko: '(hydro=물 + gen=만들다 → 수소)',
ex: 'H₂O has two hydrogen atoms.',
exKo: '물 분자에는 수소 원자가 두 개 있어요.'
}
],
images: [
{ emoji: "🏜️", cls: "sic-1", word: "*wed (적심)", desc: "메마른 것 속으로\n스며들어 생명을 줌" },
{ emoji: "💧", cls: "sic-2", word: "water (물)", desc: "모든 생명에\n스며드는 물질" },
{ emoji: "🌊", cls: "sic-3", word: "wave / hydro-", desc: "같은 뿌리 — 파도·수소\n모두 물의 이미지" }
],
idioms: [
{ icon: "🌧️", phrase: "water down", meaning: "희석하다, 약하게 만들다", example: "The plan was watered down." },
{ icon: "🐟", phrase: "in deep water", meaning: "곤경에 처하다", example: "He's in deep water with his boss." },
{ icon: "🌉", phrase: "water under the bridge", meaning: "이미 지나간 일", example: "That's all water under the bridge now." }
],
family: [
{ en: "waterfall", ko: "폭포" },
{ en: "underwater", ko: "수중의" },
{ en: "hydrogen", ko: "수소" },
{ en: "hydrant", ko: "소화전" },
{ en: "otter", ko: "수달" }
]
}
};
// ─────────────────────────────────────────────
// Anthropic API search
// ─────────────────────────────────────────────
async function fetchFromClaude(word, retryCount = 0) {
const prompt = `You are an English etymology expert for Korean elementary and middle school students.
CRITICAL LANGUAGE RULES (violations will break the app):
1. Korean text fields (definition, rootSentence, ko, exKo, meaning, rootMeaning, etc.) must be written in COMPLETE, NATURAL Korean sentences only.
2. NEVER embed English word fragments or partial words inside Korean sentences. Wrong: "으로부터THING한 거리" — Right: "~로부터 떨어진 거리"
3. NEVER use Chinese characters (한자). Wrong: "程度가甚다" — Right: "정도가 심하다"
4. When you need to reference the English word being explained inside a Korean sentence, write it SEPARATELY at the end in parentheses, or rephrase in pure Korean. Wrong: "DISTANce한 느낌" — Right: "멀리 떨어진 느낌"
5. The "ex" field is the ONLY field that should contain English text. All other string fields must be pure Korean (hangul + numbers + basic punctuation only).
For the English word "${word}", respond ONLY with a valid JSON object (no markdown, no extra text) in this exact format:
{
"word": "${word}",
"pos": "품사 in Korean (e.g. 동사 (verb))",
"rootLang": "언어 이름 (e.g. 라틴어 (Latin))",
"rootWord": "the root word or PIE root",
"rootMeaning": "2-4 word meaning in Korean",
"rootSentence": "one line with emoji and root word in em tags, Korean description of origin for kids",
"definition": "2-3 sentence Korean explanation for middle schoolers, mentioning the core image/movement",
"example": "one English sentence with word in strong tags, Korean translation in parentheses",
"rootVisual": {
"beforeEmoji": "emoji representing the 'before' state (empty/outside/absent)",
"beforeLabel": "2-4 chars Korean label for before state",
"afterEmoji": "emoji representing the 'after' state (obtained/changed/arrived)",
"afterLabel": "2-4 chars Korean label for after state",
"arrowWord": "the root word shown on the arrow",
"arrowKor": "short Korean phrase describing the movement/transition (e.g. → 이 움직임!)",
"headline": "one sentence Korean description of the core dynamic image, with key phrase wrapped in ...",
"sub": "one sentence Korean tip about how this image connects to multiple meanings"
},
"branches": [
{"tag": "2-4 char Korean category", "cls": "bc-1", "meaning": "Korean meaning", "ko": "(Korean note explaining how the root image connects to this meaning, shown under the meaning)", "ex": "English example with word in strong tags", "exKo": "Korean translation of the example sentence"},
{"tag": "2-4 char Korean category", "cls": "bc-2", "meaning": "Korean meaning", "ko": "(Korean note explaining root image connection)", "ex": "English example with word in strong tags", "exKo": "Korean translation of the example sentence"},
{"tag": "2-4 char Korean category", "cls": "bc-3", "meaning": "Korean meaning", "ko": "(Korean note explaining root image connection)", "ex": "English example with word in strong tags", "exKo": "Korean translation of the example sentence"},
{"tag": "2-4 char Korean category", "cls": "bc-4", "meaning": "Korean meaning", "ko": "(Korean note explaining root image connection)", "ex": "English example with word in strong tags", "exKo": "Korean translation of the example sentence"}
],
"images": [
{"emoji": "emoji showing the origin/root concept", "cls": "sic-1", "word": "Korean label (root 기원)", "desc": "2-line Korean description of the root concept"},
{"emoji": "emoji showing the word itself", "cls": "sic-2", "word": "word (핵심 의미)", "desc": "2-line Korean description of the core meaning"},
{"emoji": "emoji showing a derived/extended meaning", "cls": "sic-3", "word": "derived word (확장 의미)", "desc": "2-line Korean description of how it extends"}
],
"idioms": [
{"icon": "emoji", "phrase": "idiom or phrase", "meaning": "Korean meaning", "example": "English example sentence"},
{"icon": "emoji", "phrase": "idiom or phrase", "meaning": "Korean meaning", "example": "English example sentence"},
{"icon": "emoji", "phrase": "idiom or phrase", "meaning": "Korean meaning", "example": "English example sentence"}
],
"family": [
{"en": "related word", "ko": "Korean meaning"},
{"en": "related word", "ko": "Korean meaning"},
{"en": "related word", "ko": "Korean meaning"},
{"en": "related word", "ko": "Korean meaning"},
{"en": "related word", "ko": "Korean meaning"}
]
}
CRITICAL for rootVisual: The before/after pair should show the DYNAMIC CHANGE that is the word's core image. For example for "get": before=empty hand 🫙, after=full hand 🤲 showing "acquiring". For "grow": before=seed 🌱, after=tree 🌳. Make it intuitive and visual.
For branches: show exactly 4 different semantic extensions from the one core image.
Classes for branches must cycle: bc-1, bc-2, bc-3, bc-4.
Make it fun and educational for Korean kids aged 10-15.`;
// Gemini API 호출
const GEMINI_KEY = 'AIzaSyDWj-wCs68bK1P_09Oz5dgHw83VKScwXBU';
const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key=${GEMINI_KEY}`;
const fetchPromise = fetch(GEMINI_URL, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
contents: [{ parts: [{ text: prompt }] }],
generationConfig: {
temperature: 0.7,
maxOutputTokens: 2500
}
})
});
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => reject(new Error('timeout')), 60000)
);
try {
const response = await Promise.race([fetchPromise, timeoutPromise]);
const data = await response.json();
if (data.error) throw new Error(data.error.message);
const text = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
// JSON 추출 — ```json 블록, 순수 JSON, 부분 매칭 순으로 시도
let clean = text;
const jsonBlock = text.match(/```json\s*([\s\S]*?)```/);
if (jsonBlock) {
clean = jsonBlock[1];
} else {
const start = text.indexOf('{');
const end = text.lastIndexOf('}');
if (start !== -1 && end !== -1) clean = text.slice(start, end + 1);
}
clean = clean.trim();
try {
return sanitizeWordData(JSON.parse(clean));
} catch(parseErr) {
console.error('JSON 파싱 실패:', clean.slice(0, 200));
throw parseErr;
}
} catch (e) {
// 1회 자동 재시도
if (retryCount < 1) {
console.log('재시도 중...');
await new Promise(r => setTimeout(r, 1500));
return fetchFromClaude(word, retryCount + 1);
}
throw e;
}
}
// ─────────────────────────────────────────────
// Render result
// ─────────────────────────────────────────────
function renderResult(d) {
const ra = document.getElementById("resultArea");
const rv = d.rootVisual || {};
const branches = d.branches || [];
ra.innerHTML = `