키오스크에 AI를 붙이자는 얘기가 늘었습니다. 음성으로 주문받기, 얼굴로 회원 알아보기, 재고 보고 추천하기.
웹에서 되던 게 매장 단말에서 그대로 되지는 않습니다. 조건이 다릅니다.
회선은 끊긴다고 보고 짜야 합니다
사무실 회선과 매장 회선은 다릅니다. 무인 매장은 대개 인터넷 하나에 공유기 하나입니다. 그게 끊기면 키오스크도 멈춥니다.
웹이라면 사용자가 새로고침하고 말지만, 매장에서는 결제 직전에 멈춘 화면 앞에 손님이 서 있습니다.
그래서 키오스크는 기능을 두 층으로 나눕니다.
| 층 | 뭐가 들어가나 | 끊기면 |
|---|---|---|
| 핵심 | 주문·결제·입실 | 로컬에서 계속 돌고, 나중에 맞춘다 |
| 부가 | AI 추천, 음성 안내 | 조용히 사라진다 |
// AI가 실패해도 화면은 멈추면 안 된다
async function getRecommendation(cart: Item[]): Promise<Item[] | null> {
try {
return await withTimeout(callModel(cart), 1500); // 1.5초 넘으면 포기
} catch {
return null; // 추천 영역을 그냥 안 그린다
}
}
추천이 안 뜨는 건 손님이 눈치 못 챕니다. 결제가 안 되는 건 바로 전화가 옵니다. 이 우선순위를 코드 구조에 박아두세요.
서 있는 사람의 2초는 깁니다
웹에서 2초는 참을 만합니다. 뒤에 줄이 있는 매장에서 2초는 다릅니다.
LLM 호출은 보통 그보다 오래 걸립니다. 그래서 응답을 기다려야 하는 자리에 넣으면 안 됩니다.
✗ [메뉴 선택] → (모델 호출·대기) → [추천 화면] → [결제]
✓ [메뉴 선택] → [결제 화면 바로 표시]
└ 뒤에서 모델 부르고, 오면 추천 영역만 채움
"화면 띄우기 전에 모델을 부른다"가 아니라 "이미 띄운 화면을 나중에 채운다" 로 뒤집으면 대부분 풀립니다.
미리 계산해두는 방법도 있습니다. 손님이 메뉴 고르는 동안 호출을 시작해두면 결제 화면에 왔을 때는 결과가 와 있습니다.
매장 단말은 성능이 낮습니다
키오스크는 대체로 오래된 저사양 PC나 안드로이드 태블릿입니다. 웹 만들던 감각으로 짜면 현장에서 버벅입니다.
- 무거운 애니메이션은 프레임이 떨어집니다
- 메모리 누수가 있으면 며칠 켜둔 사이에 터집니다
- 브라우저가 낡아 최신 문법이 안 돌 수 있습니다
특히 두 번째가 무섭습니다. 웹은 사용자가 탭을 닫지만 키오스크는 한 달 내내 같은 페이지가 떠 있습니다. 개발할 때 안 보이던 누수가 현장에서 3일 만에 드러납니다. 오래 켜두는 테스트를 일정에 넣으세요.
카메라를 다는 순간 얘기가 달라집니다
얼굴로 회원을 알아보는 기능은 요청이 자주 옵니다. 기술은 어렵지 않은데 법이 무겁습니다.
얼굴은 생체정보입니다. 수집하려면 따로 동의를 받아야 하고, 뭘 어떻게 보관하는지 알려야 하고, 매장에 안내도 붙여야 합니다. 무인 매장에서 그 동의를 어떻게 받을 거냐가 실무에서 제일 먼저 막히는 지점입니다.
대안이 있으면 대안이 낫습니다.
| 하고 싶은 것 | 얼굴 말고 |
|---|---|
| 회원 알아보기 | QR·회원번호·휴대폰 뒷자리 |
| 연령 확인 | 신분증 스캔, 성인인증 연동 |
| 재방문 파악 | 결제 수단 토큰 |
얼굴이 아니면 안 되는 이유가 분명할 때만 가세요.
음성 주문은 매장 소음을 못 이깁니다
음성 인식도 자주 요청받습니다. 조용한 사무실에서는 잘 됩니다. 매장은 다릅니다.
- 배경 음악, 다른 손님 대화, 주방 소리
- 사투리와 빠른 말
- 뒤에 줄이 있으면 사람들은 음성을 안 씁니다
마지막이 결정적입니다. 남들 앞에서 소리 내어 주문하는 걸 불편해하는 사람이 많습니다. 음성은 보조로만 두고, 화면 터치만으로 모든 흐름이 끝나야 합니다.
현장은 원격으로 고칠 수 있어야 합니다
AI와는 상관없지만 키오스크에서 제일 자주 후회하는 부분이라 같이 적습니다.
매장이 열 곳이면 문제도 열 곳에서 생깁니다. 매번 사람이 나가면 유지비가 개발비를 넘습니다. 그래서 처음부터 이 셋은 넣어둡니다.
- 원격으로 화면 보고 재시작하기
- 업데이트를 한 번에 배포하기
- 오류 나면 서버로 자동 보고하기
마지막이 없으면 "가끔 멈춘대요"라는 말만 듣고 원인을 못 찾습니다. 잡히지 않은 예외를 매장 ID와 함께 보내는 것만으로도 대응이 완전히 달라집니다.
window.addEventListener("error", (e) => {
void report({
storeId: STORE_ID,
kiosk: KIOSK_ID,
message: e.message,
stack: e.error?.stack?.slice(0, 2000),
at: new Date().toISOString(),
});
});
여기에 하트비트까지 더하면 더 좋습니다. 1분마다 살아 있다는 신호를 보내고 5분간 없으면 알림이 갑니다. 손님이 헛걸음하기 전에 압니다.
정리
키오스크의 AI는 없어도 장사가 되는 자리에 넣어야 합니다.
- 핵심 흐름은 회선이 끊겨도 로컬에서 돌게
- AI 호출은 타임아웃을 짧게, 실패하면 조용히 사라지게
- 대기 화면 앞이 아니라 이미 뜬 화면을 채우는 자리에
- 카메라와 음성은 대안이 없을 때만
- 원격 확인·배포·오류 보고는 첫날에
회선이 끊기고 손님이 서 있고 카메라에 법이 걸리는 환경입니다. 핵심은 단순하게 두고 AI는 그 위에 얹는 순서가 안전합니다.
