Big Project · AI's EYE 26

모르는 질문에 억지로 답하지 않는 Agent 설계

챗봇은 어떤 질문에도 가장 가까운 도구를 골라 답해야 유용해 보인다. 답하지 않는 선택이 왜 더 안전할 수 있는지 이해하기 어렵다.

근거 · 프로젝트 문서 · 코드 · 테스트

1장: 모르는 답을 만들었을 때의 위험성

솔라는 새로 오픈한 카페의 키오스크 앞에서 잠시 망설였다. 화면 속 챗봇에게 “여기 화장실은 어디에 있어요?”라고 물어볼까 하다가 그만두었다. 얼마 전, 비슷한 상황에서 엉뚱한 대답을 들었던 기억이 떠올랐기 때문이다. 그 챗봇은 “죄송합니다. 현재 매장 내 이용 가능한 좌석은 3개입니다.”라고 답했었다. 아마도 ‘어디에 있나요’라는 질문을 가장 비슷한 ‘매장 상태 확인’ 기능에 억지로 연결한 결과일 것이다.

‘챗봇은 어떤 질문이든 최대한 답을 찾아내려고 노력해야 유용한 거 아닌가?’

집으로 돌아온 솔라는 거실 소파에 앉아 있는 언니 루나에게 방금 겪은 일을 털어놓았다.

“언니, 오늘 카페 챗봇한테 또 이상한 대답을 들을 뻔했어. 화장실 위치를 물어보면 좌석 수를 알려줄 것 같아서 아예 물어보지도 않았지. 왜 저런 챗봇들은 모르면 모른다고 안 하고, 굳이 엉뚱한 대답이라도 내놓으려고 할까? 그게 더 불편한데.”

솔라의 말에 루나는 잠시 생각하더니, 태블릿을 가져와 메모 앱을 켰다.

“만약 그 챗봇이 화장실 위치를 모르는 대신, 어떻게든 ‘가장 가까운’ 답을 찾아야만 한다면 어떤 일이 벌어질지 한번 상상해 볼까?”

루나는 솔라의 질문 “화장실은 어디에 있어요?”를 화면 위에 적었다. 그리고 그 아래에 챗봇이 가진 몇 가지 도구를 나열했다.

  1. 매장 상태 조회: 현재 좌석 수, 대기 인원 정보 제공
  2. 메뉴 정보: 커피, 디저트 메뉴와 가격 안내
  3. 주문 조회: 주문 번호로 주문 상태 확인

“자, 솔라 네가 챗봇이라고 생각해 봐. ‘화장실’에 대한 정보는 없어. 하지만 무조건 이 세 가지 도구 중 하나를 써서 답을 해야만 해. 어떤 걸 고를 거야?”

“음… 역시 ‘매장 상태 조회’가 제일 비슷해 보이지. ‘매장’이라는 단어가 들어있으니까.”

솔라는 마지못해 대답했다. 자기가 겪었던 상황과 똑같았다.

“그래. 그럼 ‘매장 상태 조회’ 도구를 호출해서 ‘현재 매장 내 이용 가능한 좌석은 3개입니다’라는 답을 받았어. 이걸 사용자에게 그대로 전달하는 게 최선일까?”

“아니, 그건 그냥 엉뚱한 소리잖아. 사용자는 화장실을 물었는데 좌석 얘기를 하면 황당해하지.”

“그렇지. 그럼 챗봇이 조금 더 똑똑해서, 그 정보를 바탕으로 문장을 만들어낸다고 해보자.” 루나는 키보드를 두드려 새로운 문장을 만들었다. “예를 들면, ‘고객님, 문의하신 매장 내 공간은 현재 여유롭습니다. 편하게 이용 가능한 좌석이 3개 준비되어 있습니다’ 같은 식으로. 어때? 좀 더 그럴듯하지 않아?”

솔라는 미간을 찌푸렸다. “그럴듯하지만… 더 나쁜 것 같은데? 화장실이 어디 있냐는 질문에 ‘공간이 여유롭다’고 답하면, ‘아, 화장실이 저쪽 어딘가에 있나 보다’ 하고 사용자가 오해해서 두리번거리게 만들잖아. 없는 정보를 있는 것처럼 꾸며내서 사람을 더 헷갈리게 하는 거니까.”

“맞아. 바로 그 지점이야.”

루나는 말을 이었다.

“만약 질문이 ‘가장 가까운 주차장 할인 정책 알려줘’였는데, 챗봇이 가진 도구 중에 ‘메뉴 정보’밖에 없다고 가정해 봐. 챗봇이 억지로 ‘아메리카노 할인 행사 중입니다!’라고 답한다면 어떨까? 그냥 귀찮은 수준이지. 하지만 만약 ‘개인정보 변경해 줘’라는 민감한 요청에 챗봇이 ‘가장 가까운’ 도구인 ‘주문 조회’를 실행시켜서 다른 사람의 주문 정보를 보여준다면?”

솔라는 자기도 모르게 “아…” 하고 낮은 탄성을 내뱉었다. 생각지도 못한 시나리오였다. 단순한 오답이 아니라, 심각한 개인정보 유출 사고로 이어질 수 있었다.

“잘못된 정보는 그냥 불편한 게 아니야. 때로는 위험할 수도 있어. 사용자의 신뢰를 완전히 잃게 만들고, 보안 문제를 일으키고, 결국 아무도 그 서비스를 쓰지 않게 만들지.”

루나는 태블릿 화면을 솔라에게 보여주었다. 솔라가 처음 했던 질문 옆에, 루나가 방금 말한 위험 시나리오들이 나란히 적혀 있었다.

질문: “화장실은 어디에 있어요?”

  1. 억지로 ‘매장 상태 조회’ 도구 호출
    • 결과: “이용 가능한 좌석 3개” → 오정보 제공 (사용자 혼란)
  2. 억지로 ‘주문 조회’ 도구 호출 (민감한 질문의 경우)
    • 결과: 다른 사람의 주문 정보 노출 → 보안 사고, 신뢰 붕괴
  3. 답변 거절
    • 결과: “죄송합니다, 해당 정보는 안내해 드릴 수 없습니다.” → 가장 안전한 선택

표를 보고 나니 명확해졌다. ‘어떤 질문에도 답해야 유용하다’는 생각은 순진한 착각이었다. 챗봇이 모르는 질문에 억지로 답을 만들어내는 것은 유용한 게 아니라 무책임한 행동이었다. 차라리 정직하게 모른다고 말하는 것이 훨씬 더 안전하고 신뢰를 주는 방식이었다.

“이제 알겠다.” 솔라가 고개를 끄덕였다. “챗봇이 ‘가까운 기능을 호출하지 않고’ 그냥 모른다고 답하는 게 왜 중요한지. 그게 챗봇을 지키고, 사용자를 지키는 최소한의 안전장치였구나.”

솔라는 아까 키오스크 앞에서 망설였던 자신을 떠올렸다. 만약 그 챗봇이 “화장실 정보는 제공하지 않습니다.”라고 명확히 답해줬다면, 잠시 아쉬웠을지는 몰라도 불쾌하거나 혼란스럽지는 않았을 것이다.

그런데 한 가지 궁금증이 새로 생겼다. 그렇다면 애초에 챗봇은 어디까지 답하고, 어디부터는 모른다고 해야 할까? 그 기준은 누가, 어떻게 정하는 걸까? 챗봇이 마음대로 대답하지 않도록 하려면, 명확한 ‘근거 범위’ 같은 것이 필요하지 않을까?

2장: Agent의 근거 범위와 ‘계약’ 설정

솔라는 거실 테이블에 앉아 어제 루나와 나눴던 대화를 곱씹고 있었다. 모르는 질문에 억지로 답하는 챗봇이 얼마나 위험할 수 있는지 깨닫고 나니, 새로운 질문이 머릿속을 맴돌았다. ‘그렇다면 챗봇은 어디까지 답해야 하는가?’

솔라는 노트 한 페이지를 펼쳐 맨 위에 ‘챗봇이 꼭 대답해야 하는 것’이라고 적었다. 그리고 잠시 고민하더니 사용자가 궁금해할 만한 것들을 쭉 나열하기 시작했다.

  • 화장실 위치
  • 주차장 정보
  • 메뉴 추천
  • 가까운 버스 정류장
  • 오늘의 날씨

‘이 정도는 답해줘야 쓸모 있다고 느끼지 않을까? 유용하려면 당연히 최대한 많은 걸 알려줘야지.’ 솔라는 자신의 목록이 꽤 합리적이라고 생각했다.

그때, 솔라의 노트 위로 루나의 태블릿 화면이 비쳤다. 화면에는 간결한 목록이 하나 떠 있었다.

고객 Agent의 현재 도구 범위

  1. 매장 상태 확인 (좌석, 대기)
  2. 배달 예상 시간(ETA) 조회
  3. 메뉴 정보 안내
  4. 매장 운영 정책 안내
  5. 주문 내역 조회

솔라는 두 목록을 번갈아 보았다. 자신이 만든 ‘이상적인’ 목록과 루나가 보여준 ‘현실의’ 목록은 너무나도 달랐다.

“언니, 이건 너무 기능이 적은 거 아냐?” 솔라가 먼저 입을 열었다. “내가 적은 것들이 사용자 입장에서는 훨씬 더 필요할 것 같은데. 주차 정보나 화장실 위치 같은 거 말이야.”

루나는 솔라의 말에 고개를 끄덕이는 대신, 질문을 던졌다.

“네 목록과 내 목록에 있는 항목들의 가장 큰 차이점이 뭘까? 특히, 그 정보를 우리가 어디서, 얼마나 확실하게 가져올 수 있는지 생각해 봐.”

‘정보의 출처?’

솔라는 루나의 목록을 다시 한번 꼼꼼히 들여다보았다.

첫 번째, ‘매장 상태 확인’. 이건 매장 관리 시스템에 직접 연결하면 정확한 데이터를 가져올 수 있다. 두 번째, ‘ETA 조회’. 배달 대행사의 API를 연동하면 실시간으로 확인 가능하다. 세 번째, ‘메뉴 정보’. 당연히 우리 가게의 POS 시스템에 있는 정보다. 네 번째, ‘운영 정책’. 환불 규정이나 영업시간처럼 우리가 명확하게 정해놓은 규칙이다. 마지막, ‘주문 내역 조회’. 고객의 주문 번호를 받아서 우리 데이터베이스를 보면 된다.

하나씩 따져보던 솔라는 무릎을 탁 쳤다.

“아! 알겠다! 언니가 보여준 목록은 전부 우리가 직접 통제하고 검증할 수 있는 데이터 소스를 가진 것들이네! 내부 시스템이나 API처럼, ‘확실한 근거’가 있는 정보들 말이야.”

솔라는 흥분하며 말을 이었다. “반면에 내가 적은 건… ‘화장실 위치’는 보통 직원이 구두로 알려주지 데이터로 관리하지는 않잖아. ‘주변 맛집 추천’은 너무 주관적이고, ‘오늘의 날씨’는 외부 날씨 API를 또 끌어와야 하니까 우리가 직접 책임질 수 있는 정보가 아니고. 정보의 ‘근거’가 명확하고 통제 가능한가, 아닌가의 차이였구나!”

“바로 그거야.”

루나가 처음으로 긍정의 말을 건넸다.

“Agent를 만든다는 건, 세상의 모든 질문에 답하는 만능 비서를 만드는 게 아니야. 사용자와 ‘우리는 이 범위 안에서, 이 근거를 바탕으로 당신의 질문에 책임지고 답하겠습니다’라는 약속, 즉 일종의 ‘계약(contract)’을 맺는 과정에 가까워.”

루나는 태블릿 화면을 살짝 바꿔, 다섯 가지 도구 목록 옆에 ‘Agent의 계약서’라는 제목을 붙였다.

Agent의 계약서 (Contract)
약속하는 것 (In-Scope)매장 상태, ETA, 메뉴, 정책, 주문 조회
(내부 시스템, DB 등 명확한 근거 보유)
약속하지 않는 것 (Out-of-Scope)그 외 모든 질문
(화장실 위치, 맛집 추천, 날씨 등)

“도구의 범위를 다섯 가지로 한정한 건, 우리가 사용자에게 딱 이 다섯 가지 행동과 정보에 대해서만 품질을 보증하겠다는 명시적인 약속인 셈이지. 범위를 넓히는 게 무조건 좋은 게 아니야. 지킬 수 없는 약속을 남발하는 것과 같으니까.”

솔라는 ‘계약’이라는 단어를 보며 고개를 끄덕였다. 챗봇의 기능 목록이 완전히 다르게 보이기 시작했다. 단순히 기술적인 기능의 나열이 아니라, 사용자와의 신뢰를 지키기 위한 약속의 조항들이었다. 제한된 범위는 챗봇의 무능함이 아니라, 오히려 책임감의 표현이었던 것이다.

“이제 알겠어. Agent가 답할 수 있는 질문의 범위를 정하는 건, 결국 우리가 어디까지 책임질 것인지를 명확히 하는 거구나.”

솔라는 자신의 노트에 적었던 목록을 가만히 내려다보았다. ‘유용함’에 대한 생각이 짧았다는 것을 깨달았다. 진짜 유용함은 아무 말이나 해주는 것이 아니라, 약속된 범위 안에서 절대적으로 신뢰할 수 있는 답변을 주는 데 있었다.

그러자 새로운 궁금증이 생겼다.

“좋아, 계약 범위를 정하는 건 이해했어. 그럼 사용자가 계약서에 없는, 즉 범위를 벗어난 질문을 던지면 어떻게 해야 해? 예를 들어 ‘여기 와이파이 비밀번호 뭐예요?’ 같은 질문 말이야. 이럴 때 Agent는 뭐라고 답해야 이 계약을 잘 지키는 게 될까?”

3장: 명시적 거절이 왜 더 안전한가

솔라는 전날 루나와 함께 만들었던 ‘Agent의 계약서’를 자신의 노트에 다시 옮겨 적고 있었다. 매장 상태, ETA, 메뉴, 정책, 주문 조회. 명확한 근거를 가진 다섯 가지 약속. 이제 이 범위를 벗어난 질문에 억지로 답해서는 안 된다는 사실은 분명히 이해했다.

문제는 그 다음이었다. 계약을 잘 지키려면, 범위를 벗어난 질문을 어떻게 ‘거절’해야 할까?

솔라는 노트의 빈 공간에 사용자의 질문 하나를 적었다. “여기 와이파이 비밀번호 뭐예요?” 그리고 그 아래에 Agent가 할 수 있는 대답의 후보들을 나열하기 시작했다.

  1. “죄송하지만, 와이파이 비밀번호는 안내해 드릴 수 없습니다.” (가장 예의 바른 거절)
  2. “저는 매장 운영과 관련된 정보만 드릴 수 있어요.” (조금 더 정보를 주는 거절)
  3. “답변할 수 없는 질문입니다.” (가장 단호한 거절)

‘어떤 게 제일 낫지? 사용자 입장에서는 1번처럼 부드럽게 말해주는 게 덜 불쾌할 것 같은데… 너무 기계적으로 ‘불가능’이라고만 하면 정이 없어 보이잖아.’

솔라가 한창 고민에 빠져 있을 때, 루나가 다가와 솔라의 노트를 들여다보았다. 솔라가 적어놓은 세 가지 거절 문장을 잠시 보던 루나는, 말없이 자신의 태블릿을 가져와 화면을 켰다.

“좋은 고민이야. ‘어떻게 거절할 것인가’는 Agent의 신뢰성을 결정하는 중요한 문제거든. 솔라 네가 생각한 답변들, 그리고 우리가 피하기로 했던 최악의 답변을 한번 비교해 볼까?”

루나는 태블릿에 표를 하나 그리기 시작했다. 질문은 똑같이 “여기 와이파이 비밀번호 뭐예요?”였다. 그리고 세로축에는 세 가지 대응 시나리오를 적었다.

“첫 번째는 우리가 지난번에 얘기했던 ‘억지로 답하기’야. 와이파이와 가장 비슷해 보이는 ‘매장 운영 정책 안내’ 도구를 호출해서, 엉뚱한 답을 내놓는 경우지.”

시나리오 1: 잘못된 도구 호출

Agent가 ‘정책’ 도구를 호출하여 “저희 매장 환불 정책은 구매 후 7일 이내입니다.” 라고 답한다.

“이건 그냥 최악이지.” 솔라가 고개를 저었다. “사용자는 혼란스럽고, Agent에 대한 신뢰는 바로 깨질 거야.”

“맞아. 그럼 네가 생각했던 ‘예의 바른 거절’을 두 번째 시나리오로 넣어보자.”

시나리오 2: 일반적인 문장으로 거절

Agent가 스스로 문장을 생성하여 “죄송하지만, 와이파이 정보는 제가 안내해 드리기 어렵습니다.” 라고 답한다.

“이게 훨씬 낫지 않아? 사용자의 기분도 상하지 않게 하고, 정직하게 모른다고 말하니까. 신뢰도 지킬 수 있고.” 솔라가 자신 있게 말했다.

“정말 그럴까?” 루나가 반문했다. “Agent가 스스로 거절 ‘문장’을 만들어내는 방식의 허점을 생각해 봐. 만약 Agent가 조금 더 ‘도움이 되고 싶은’ 나머지, ‘죄송하지만 와이파이 정보는 제가… 잘 모르지만, 보통 ‘guest1234’ 같은 걸 많이 쓰지 않나요?’ 라고 덧붙인다면?”

“아…” 솔라의 입에서 짧은 탄식이 나왔다. 그럴듯한 추측을 덧붙이는 순간, 그 답변은 또 다른 형태의 위험한 오답이 되어버린다. 거절하겠다는 의도는 좋았지만, 문장을 자유롭게 생성하는 과정에서 새로운 위험이 생긴 것이다.

“그럼 마지막 세 번째. Agent가 스스로 답을 만들지 않는 방식이야.”

루나는 표의 마지막 칸을 채워 넣었다.

시나리오 3: 명시적인 신호(Signal)로 거절

Agent는 질문이 계약 범위 밖임을 판단하고, ‘답변 불가’를 의미하는 시스템 신호, 예를 들어 unsupported_question을 반환한다. 그러면 시스템은 이 신호를 받아 미리 정해진 안전한 문장 “요청하신 정보는 제가 안내해 드릴 수 있는 범위가 아닙니다.”를 사용자에게 보여준다.

솔라는 세 번째 시나리오를 뚫어지라 쳐다보았다. 처음에는 ‘답변할 수 없는 질문입니다’ 같은 딱딱한 문장과 다를 바 없다고 생각했다. 하지만 루나의 설명을 듣고 나니 핵심적인 차이가 보였다.

“잠깐, 그럼 세 번째 방식에서 Agent는 ‘말’을 하는 게 아니네?”

“정확해. Agent의 역할은 ‘거절 문장 생성’이 아니야. 그저 ‘이 질문은 내 계약 범위 밖이다’라는 판단을 내리고, 그 판단을 unsupported_question이라는 명확한 깃발을 들어 시스템에 알리는 것까지야. 사용자에게 보여질 최종 메시지는 Agent의 손을 떠나, 이미 검증된 안전한 문장으로 고정되어 있는 거지.”

루나는 표를 완성해서 솔라에게 보여주었다.

질문: “여기 와이파이 비밀번호 뭐예요?”사용자 경험신뢰도시스템 안정성/안전
1. 잘못된 도구 호출최악 (혼란)붕괴위험 (오정보)
2. 일반 문장으로 거절불안정저하 가능성위험 (환각/추측)
3. 명시적 신호(unsupported_question)로 거절예측 가능상승매우 안전

표를 본 솔라는 무릎을 쳤다. unsupported_question은 사용자에게 보여주는 불친절한 메시지가 아니었다. Agent가 자유롭게 말을 만들다 길을 잃지 않도록 막는, 시스템 내부의 안전장치이자 약속이었다. 억지로 답을 만들지도 않고, 어설프게 거절하다 실수를 만들지도 않는 가장 확실한 방법.

사용자 입장에서도 매번 다른 방식으로 거절하는 Agent보다, ‘이건 제 일이 아닙니다’라고 명확하고 일관되게 말해주는 Agent를 더 신뢰할 수 있을 터였다. 무엇을 할 수 있고, 무엇을 할 수 없는지 명확히 아니깐.

“이제야 ‘가까운 기능을 호출하지 않고 unsupported_question을 반환한다’는 문장이 완벽하게 이해됐어.”

솔라는 흥분한 목소리로 말했다.

“이건 단순히 기능을 호출하지 않는다는 뜻이 아니었어. ‘추측해서 말하지 않겠다’는 약속을 시스템 수준에서 지키는 가장 확실한 방법이었구나.”

솔라는 다시 자신의 노트로 돌아갔다. 그리고 어제 그렸던 ‘Agent의 계약서’ 표를 수정하기 시작했다. ‘약속하지 않는 것(Out-of-Scope)’ 항목 아래에 새로운 원칙을 굵은 글씨로 추가했다.

※ 거절 원칙: 계약 범위 밖의 질문을 받으면, 자유로운 문장 생성을 시도하지 않는다. 대신, 시스템에 unsupported_question 신호를 보내 정해진 응답을 반환하도록 한다. 이것이 Agent의 신뢰와 안전을 지키는 계약의 마지막 조항이다.

노트에 마지막 문장을 적어 넣는 순간, 솔라는 자신이 만든 Agent가 어떤 질문에 답해야 하고, 어떤 질문을 거절해야 하는지, 그리고 그 거절을 어떻게 가장 안전하게 수행해야 하는지에 대한 명확한 청사진을 갖게 되었음을 깨달았다. 진짜 유용하고 신뢰할 수 있는 Agent를 만드는 첫걸음이었다.