Keural Kit
내 웹 서비스 안에 Keural 채팅·드라이브·프롬프트 화면을 넣는 임베드 스크립트입니다.
Keural Kit은 스크립트 하나로 Keural 화면을 내 페이지에 넣습니다. 화면은 Shadow DOM 안에 그려지므로 내 페이지의 CSS와 섞이지 않습니다. Kit은 Keural 웹 배포 때 함께 갱신됩니다. 배포 후에도 이전 화면이 보이면 브라우저·CDN 캐시를 비우고 window.KeuralKit.__build로 빌드 시각을 확인합니다.
Kit은 Keural 로그인 세션(Keural API 도메인의 쿠키)으로 동작합니다. userInfo는 화면 표시용이며, 사용자 확인은 쿠키 세션으로 합니다. 내 서비스 도메인에서 쓰려면 도입 전에 도메인 등록과 로그인 연동(SSO 등)을 Keural 담당자와 협의합니다.
불러오기
Kit은 사용하는 Keural 환경의 웹 주소에서 불러옵니다. keural.ai는 https://keural.ai, 온프레미스·전용 환경은 그 환경의 Keural 웹 주소입니다. 스크립트보다 먼저 Kit이 호출할 서버 주소를 window.__KEURAL_ENV__에 설정합니다. 세 주소는 같은 환경의 주소여야 하며, 도입 시 담당자에게 받습니다.
<script>
window.__KEURAL_ENV__ = {
NEXT_PUBLIC_API_BASE_URL: '<KEURAL_API_URL>',
NEXT_PUBLIC_FAST_API_BASE_URL: '<KEURAL_AGENT_URL>',
NEXT_PUBLIC_MODE: 'prd',
};
</script>
<script src="<KEURAL_WEB_URL>/plugin/kit/keural.js" async></script>| 값 | 내용 |
|---|---|
<KEURAL_WEB_URL> | Keural 웹 주소. 예: https://keural.ai |
<KEURAL_API_URL> | Keural API 서버 주소. 예: https://api.keural.ai |
<KEURAL_AGENT_URL> | Keural 에이전트 서버 주소 |
NEXT_PUBLIC_MODE | 운영 환경은 prd, 개발 환경은 dev |
같은 Kit을 두 번째 도메인에서도 쓰려면 NEXT_PUBLIC_ADDITIONAL_FRONTEND_URL, NEXT_PUBLIC_ADDITIONAL_API_BASE_URL, NEXT_PUBLIC_ADDITIONAL_FAST_API_BASE_URL 세 값을 모두 설정합니다. 하나라도 빠지면 오류가 납니다. 값은 경로 없는 https:// 주소입니다.
스크립트가 로드되면 window.KeuralKit이 생성됩니다. React 같은 SPA에서는 스크립트가 한 번만 로드되도록 로더를 씁니다.
export function loadKeuralKit(src = '<KEURAL_WEB_URL>/plugin/kit/keural.js') {
if (window.KeuralKit) return Promise.resolve(window.KeuralKit);
return new Promise((resolve, reject) => {
const s = document.createElement('script');
s.src = src;
s.async = true;
s.onload = () => resolve(window.KeuralKit);
s.onerror = () => {
s.remove();
reject(new Error('Keural Kit failed to load'));
};
document.head.appendChild(s);
});
}채팅 넣기
const el = document.getElementById('keural-chat')!;
window.KeuralKit.mountChat(el, {
userInfo: { userId: user.id, name: user.name },
colorMode: 'light',
initialData: { message: '이번 분기 매출 요약해 줘', room_name: '분기 보고' },
onSessionCreated: (roomId) => router.push(`/c/${roomId}`),
onError: () => router.push('/'),
});
// 화면을 떠날 때
window.KeuralKit.unmount(el);- 기존 대화를 열려면
sessionId에 대화 ID를 넣습니다. initialData는 새 대화를 열 때만 넣습니다. 기존 대화를 열 때 넣으면 같은 메시지가 다시 전송됩니다.userInfo.userId가 없으면 비로그인으로 처리됩니다. 로그인 정보가 준비된 뒤 마운트합니다.
메서드
| 메서드 | 설명 |
|---|---|
mountChat(el, options) | 채팅 화면 |
mountDrivePage(el, options) | 드라이브 화면. onAsk(files)로 질문할 파일을 받습니다 |
mountPromptPage(el, options) | 프롬프트 화면. onAsk(prompts)로 고른 프롬프트를 받습니다 |
mountDriveDialog(el, options) / updateDriveDialog | 드라이브 파일 선택 창(open 필수, onClose, onSelect(files), initialSelected) |
mountPromptDialog(el, options) / updatePromptDialog | 프롬프트 선택 창(open 필수, onClose, onSelect, onDefaultSelect, selectDefaultPrompt, defaultPromptDismissed) |
unmount(el) | 마운트한 화면 제거 |
mount*·update* 메서드는 colorMode와 userInfo를 함께 받고, unmount(el)은 요소만 받습니다. update*는 같은 요소를 새 옵션으로 다시 그립니다. 창을 열고 닫을 때는 open 값을 바꿔 update*를 호출합니다. 같은 요소에 mount*를 다시 호출하면 기존 화면을 재사용합니다.
mountChat 옵션
| 옵션 | 타입 | 설명 |
|---|---|---|
sessionId | string | 열 대화 ID. 없으면 새 대화 |
userInfo | { userId, name?, orgId?, orgName? } | 사용자 정보. userId 필수 |
initialData | object | 새 대화 첫 메시지. 아래 initialData 참고 |
colorMode | 'light' | 'dark' | 테마. 기본 light |
initialEffort | 'fast' | 'balanced' | 'high' | 'xhigh' | 'max' | 처음 레벨. 기본 fast |
initialWebSearch | boolean | 웹 검색을 켠 채로 시작. 기본 true |
initialDeepResearch | boolean | Deep Research를 켠 채로 시작 |
hideHomeButton / hideNewChatButton | boolean | 헤더 버튼 숨김 |
hideModePopup | boolean | 모드 선택 팝업 숨김 |
messageActions | { id, label, onClick(messageId) }[] | 답변 메뉴에 내 동작 추가 |
headerLeftActions / headerRightActions | HeaderLeftAction[] | 헤더에 내 버튼 추가 |
onHeaderLeftMount | (el: HTMLElement) => void | 헤더 왼쪽 영역이 그려지면 그 요소를 받습니다 |
mobileMenuItems / mobileBottomActions | array | 모바일 폭에서 메뉴·하단 버튼 추가 |
onMobileHomeButton | () => void | 모바일 폭의 홈 버튼을 눌렀을 때 |
chatInputFooter | string | 입력창 아래 안내 문구 |
shareTooltip | string | 공유 버튼 툴팁 문구 |
onSessionCreated | (roomId) => void | 새 대화가 만들어졌을 때 |
onStreamDone | (roomId) => void | 답변이 끝났을 때 |
onSummaryDone | (roomId) => void | 대화 제목·요약이 만들어졌을 때 |
onRoomInfo | (info) => void | 대화 정보가 바뀌었을 때 |
onShare / onExport | (roomId) => void | 공유·내보내기 버튼을 눌렀을 때 |
onError | (error: Error) => void | 오류가 났을 때 |
initialData
| 필드 | 타입 | 설명 |
|---|---|---|
message | string | 필수. 첫 메시지 |
files | FileType[] | 함께 보낼 드라이브 파일(mountDriveDialog의 onSelect로 받은 값) |
prompts | object[] | 함께 쓸 프롬프트 |
webSearch | boolean | 웹 검색 |
deepResearch | boolean | Deep Research |
effort | 'fast' | 'balanced' | 'high' | 'xhigh' | 'max' | 레벨 |
model | { label, value } | 답할 모델 |
room_name | string | 대화 이름. roomName·title·name도 받습니다. |
folder_id | string | null | 저장할 폴더 |
hideModePopup | boolean | 모드 선택 팝업 숨김 |
화면 언어
Kit 화면은 한국어로 표시됩니다.
설정과 로그인
- 사용자 설정은 Keural 웹이나 앱에서 바꾸며, Kit 화면은 그 설정을 따릅니다.
- 로그인은 내 서비스가 처리하고, Kit에는 로그인된 사용자 정보만 넘깁니다.