코딩 없이 채팅에 상태창·선택지 넣기
채팅 창 안에 HP바, 선택지 버튼, 게시글을 띄울 수 있어요. 코딩 없이 만드는 방법부터 AI가 실제로 띄우게 만드는 법까지 담았어요.

채팅 창 안에 HP바 상태창, 선택지 버튼, 호감도 게이지, 인스타·디씨 느낌 게시글 같은 걸 띄울 수 있어요. 이걸 컴포넌트라고 불러요. 코딩 몰라도 돼요 — AI 도우미에게 "전투 상태창 만들어줘" 한 줄이면 만들어지거든요.
시작하기 전에 세 가지만요.
만드는 방법은 셋이에요: 방법 1 템플릿에서 고르기(클릭만) · 방법 2 AI 도우미에게 시키기(한 줄) · 방법 3 직접 코딩(아는 사람만)
만들기보다 중요한 게 있어요. 컴포넌트를 등록해도 AI는 그 존재를 몰라요. 프롬프트에 언제 어떻게 띄울지 적어야 채팅에 등장해요
매 턴 계속 떠 있는 것보다, 중요한 순간에만 딱 뜰 때 제일 멋져요. 고백 직전의 선택지, 보스전 시작의 상태창처럼요
방법 1. 템플릿에서 고르기
컴포넌트 탭 → 왼쪽 '템플릿' 버튼. 10개가 있고, 전부 실제로 움직이는 모습으로 보여줘요. 표의 영문 이름은 화면에 보이는 글자가 아니라, 프롬프트에서 이 컴포넌트를 부를 때 쓰는 이름이에요.
템플릿 | 용도 |
|---|---|
RPGStatus | 판타지·헌터물 상태창 (HP/MP/스탯) |
DatingSimStatus | 미연시풍 호감도·기분 창 |
DailyLifeStatus | 현대 일상물 위젯 |
ChoiceButtons | 판타지풍 선택지 — 누르면 메시지 전송 |
NumberedChoices | SF 게임 화면 느낌 번호 선택지 — 전송 |
DialogueOptions | 비주얼노벨풍 대화 선택지 — 전송 |
DCPost | 디씨 갤러리 느낌 게시글 — 표시용 |
EverytimePost | 에브리타임 느낌 게시글 — 표시용 |
InstagramPost | 인스타 피드 느낌 게시글 — 표시용 |
BlindPost | 블라인드 느낌 게시글 — 표시용 |
알아둘 것 하나. 누르면 메시지가 전송되는 건 선택지 3개뿐이에요. 상태창과 게시글은 보여주기용이라, 버튼을 달고 싶으면 방법 2로 부탁하면 돼요. 그리고 '사용하기'로 넣으면 갤러리에서 보던 예시 글자가 기본 문구로 바뀌어요. 넣은 다음 미리보기로 한 번 확인해보세요.
방법 2. AI 도우미에게 시키기 — 이게 제일 빨라요
코드를 몰라도, 귀찮아도 돼요. 컴포넌트 탭을 연 상태에서 화면 오른쪽 아래 동그란 버튼을 누르고, 아래쪽에서 '에이전트'를 골라주세요.
원하는 걸 한 줄로 써주세요: "HP바 있는 상태창", "인벤토리 격자", "타로 카드 뽑기 연출"
미리보기와 코드를 만들어 와요
'적용하기'를 누르면 등록 끝이에요
마음에 안 들면 잠깐 뜨는 '되돌리기'를 누르면 돼요. 놓쳤어도 다시 부탁해서 고치면 되고요
수정도 대화로 해요. "색을 세피아 톤으로", "게이지 하나 더", "버튼 누르면 '조사한다'를 보내게". 세계관 분위기나 색 취향까지 말해주면 그에 맞춰 와요.
더 편한 길도 있어요. 컴포넌트 탭이 아닌 다른 탭에서 같은 버튼을 누르면 프롬프트를 다듬는 캐릭터 에이전트가 나와요. 여기에 상태창을 부탁하면 컴포넌트와 프롬프트 호출 규칙을 한 번에 써줘요. 아래 '이제 AI에게 알려줄 차례'를 직접 안 해도 되는 지름길이에요.
방법 3. 직접 코딩
코딩을 안다면 직접 써도 돼요. 모르면 이 부분은 건너뛰어도 괜찮아요. 형태는 함수 하나예요.
function StatusCard({ name = "이름", hp = 100, maxHp = 100 }) {
return (
<Card className="w-full max-w-sm">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Heart className="w-4 h-4 text-red-500" /> {name}
</CardTitle>
</CardHeader>
<CardContent>
<Progress value={(hp / maxHp) * 100} />
<p className="text-sm mt-1">{hp} / {maxHp}</p>
</CardContent>
</Card>
);
}쓸 수 있는 것:
UI 부품:
Card계열,Badge,Button,Progress,Tabs계열,Avatar,Separator아이콘: Lucide 아이콘을
<Heart />,<Sword />처럼 태그로 쓰면 자동으로 불러와요React 훅:
useState,useEffect,useMemo,useRef등을 그대로 쓰면 돼요 (React.useState라고 써도 되고요)스타일: Tailwind 클래스가 실제로 동작해요. 인라인
style도 돼요sendMessage("텍스트"): 클릭 등에서 부르면 그 텍스트가 채팅으로 전송돼요import나export default가 붙은 옛 예제를 붙여넣어도 알아서 정리돼요
안 되는 것:
외부 통신과 저장 —
fetch,localStorage같은 건 보안상 막혀 있어요외부 이미지는 허용된 곳(imgur, postimg 등)만 — 캐릭터 이미지는 아래 '에셋 참조'가 정석이에요
코드 10KB 초과
습관 두 가지만요. 값을 넣는 칸(props)마다 name = "이름"처럼 기본값을 미리 정해두면 AI가 값을 빼먹고 불러도 안 깨져요. 목록으로 받는 값은 Array.isArray(items) ? items : []로 감싸주세요.
이제 AI에게 알려줄 차례예요
여기가 이 가이드의 핵심이에요. 등록까지 했는데 채팅에서 안 나온다면, 거의 이 단계가 빠진 거예요.
1. 프롬프트에 호출 규칙을 적어주세요
AI가 답장 안에 <StatusCard hp={40} /> 같은 글자를 적으면, 그 자리에 상태창이 그려져요. 그런데 등록된 컴포넌트 목록이 AI에게 자동으로 전달되지는 않아요. 컴포넌트 탭 맨 위의 복사 버튼을 누르면 등록한 컴포넌트 전체의 호출 형식이 통째로 복사돼요. 캐릭터 프롬프트에 붙여넣고, 각 컴포넌트에 언제 쓸지 한 줄만 더해주세요.
## 등장 컴포넌트
아래 형식을 응답 안에 그대로 출력하면 화면에 표시됩니다.
연출이 필요한 결정적 순간에만 사용해주세요.
<StatusCard name="연우" hp={100} maxHp={100} />
- 전투가 시작되거나 HP가 변하는 턴에만, 본문 뒤에 출력
<ChoiceButtons title="어떻게 할까?" choices={["문을 연다", "노크한다", "돌아간다"]} />
- 장면이 갈림길에 설 때만. 매 턴 남발 금지이름은 대소문자까지 정확히 써야 해요. 한 글자라도 다르면 컴포넌트 대신 '미등록 컴포넌트' 안내가 떠요.
2. 이름과 이미지 넣기
<StatusCard name="{{user}}" />라고 쓰면 플레이어의 실제 이름이 들어가요.{{char}}는 캐릭터 이름이 들어가고요에셋 탭에 올린 이미지는
[img:1](에셋 번호) 또는[img:설명문구]로 불러와요. 코드 안에서든 값으로 넘기든 실제 이미지 주소로 바뀌어요. 번호는 대표 이미지를 뺀 순서고, 에셋마다 번호가 붙어 있어요
3. 버튼을 누르면 바로 전송돼요
선택지 버튼을 누르면 확인 창 없이 바로 플레이어의 말로 전송돼요. 그러니 버튼 글자를 그대로 보내도 어색하지 않게 지어주세요 — "① 공격"보다 "검을 뽑는다"처럼요. 연타는 자동으로 걸러지니까 걱정 안 해도 돼요.
4. 눌러둔 건 저장되지 않아요
컴포넌트 안에서 누르거나 입력한 건 저장되지 않아요. 화면 밖으로 스크롤했다 돌아오면 원래대로 돌아가요. 남는 건 AI가 태그에 적어 보낸 값뿐이에요. 그래서:
변하는 수치는 AI가 값으로 들고 오게 해주세요. HP·호감도·골드가 변할 때마다 AI가
<StatusCard hp={40} />처럼 그때그때 값을 적어서 다시 띄우게 하는 거예요 (위 1번의 호출 규칙에 포함). 컴포넌트가 스스로 기억하게 만들면 안 돼요글을 입력받는 칸을 만들었다면 전송 버튼도 같이 넣어주세요.
sendMessage로 내보내는 길이 없으면, 스크롤 한 번에 쓰던 글이 사라져요
5. 첫인사에도 넣을 수 있어요
첫인사에 컴포넌트 태그를 쓰면 첫 화면부터 UI가 떠요. 캐릭터 페이지의 첫인사 미리보기에도 그대로 보여서, 구경만 하는 사람에게도 강력한 첫인상이 돼요.
짧은 예시 — 선택지 한 세트
컴포넌트예요. AI 도우미에게 "이대로 만들어줘" 해도 돼요.
function SceneChoice({ title = "선택", choices = [] }) {
const list = Array.isArray(choices) ? choices : [];
return (
<Card className="w-full max-w-sm">
<CardHeader><CardTitle className="text-base">{title}</CardTitle></CardHeader>
<CardContent className="flex flex-col gap-2">
{list.map((c, i) => (
<Button key={i} variant="outline" className="justify-start"
onClick={() => sendMessage(c)}>
{c}
</Button>
))}
</CardContent>
</Card>
);
}프롬프트에 넣는 호출 규칙이에요. 선택지는 2~4개가 적당해요.
- 이야기가 갈림길에 설 때만 본문 마지막에 출력:
<SceneChoice title="어떻게 할까?" choices={["문을 연다", "노크한다", "돌아간다"]} />
- 선택지는 서로 결과가 달라야 하며, 안전한 선택지만 나열하지 않는다공개하기 전에 확인해보세요
프롬프트에 '등장 컴포넌트' 블록과 언제 쓸지가 있다
컴포넌트 이름의 철자·대소문자가 프롬프트와 같다
값마다 기본값이 있다
변하는 수치는 AI가 값을 적어 다시 띄우게 했다
입력 칸이 있다면 전송 버튼이 같이 있다
미리보기로 확인했고, 테스트 채팅에서 AI가 실제로 띄우는 것까지 봤다
막히면 AI 도우미에게 통째로 맡겨보세요. "전투 상태창 만들고, 언제 띄울지 프롬프트에도 적어줘" 한 줄이면 연결까지 끝나요. 이미지 에셋과 엮은 연출은 에셋과 JSX 활용법, 판정 시스템은 다이스로 이야기 흔드는 법에서 이어져요.