3. 카카오 챗봇 발화문, 엔티티 적용 - 파라미터 문서

1. 요구사항

카카오톡 채팅창에 명령어를 입력하는 것을 발화문이라고 한다. 발화문을 입력했을 때 HTTP Request로 JSON 형태에서 req.body.userRequest.utterance에 담긴다.

https://chatbot.kakao.com/docs/skill-response-format#userrequest

 

챗봇 관리자센터 개요 · 도움말 - 챗봇 관리자센터

<h2><a class="anchor" aria-hidden="true" id="챗봇-관리자센터-소개"></a><a href="#챗봇-관리자센터-소개" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width

i.kakao.com

EPL 라운드를 입력했을 때 해당 라운드 경기 결과를 보여주는 기능을 구현해야 한다. 서버에서는 입력한 내용을 파라미터로 받아와서 API 요청에 담아서 보내야 한다. 즉, 발화문의 숫자에 해당하는 부분을 챗봇이 읽어서 스킬 서버에 보내야 한다. 발화문에 1부터 38까지 모든 숫자를 입력해서 각각의 발화문 마다 조건문을 만든다면 코드가 굉장히 길어지고 복잡할 것이다. 따라서 발화문의 숫자에 해당하는 부분을 봇이 자동으로 읽어서 판단하게끔 하는 방법이 파라미터 및 엔티티 설정이다.

 

2. 엔티티 / 파라미터

엔티티란 사용자의 발화문을 이해하기 위한 일종의 사전이다. 유동적이고 불규칙적인 사용자의 발화문에서 특정한 데이터를 추출하기 위해서 설정하는 봇을 위한 배경지식이다.

사용자의 발화문 예시를 입력했을 때 숫자에 해당하는 부분이 마킹된다. 이 때 이 부분에 엔티티를 설정할 수 있다.  sys.number 엔티티는 카카오 오픈빌더에서 제공하는 시스템 엔티티이다. sys.number는 기본적인 숫자를 인식한다. 이 때 인식한 숫자 값을 요청의 파라미터로 담아야 한다.

발화문에서 입력받은 부분 중 sys.number 엔티티에 해당하는 값을 파라미터로 담아 보낼 수 있다. 공식 문서에서 파라미터에 대한 설명은 다음과 같다.

파라미터(Parameter)는 봇이 사용자의 의도를 정확히 이해하기 위해 필요로 하는 데이터를 일컫습니다. 봇과의 대화 대부분은 파라미터 데이터를 채우는 작업이라고 할 수 있습니다. 필요한 파라미터가 없으면 다시 되묻기도 합니다. API 형태로 구성된 스킬(Skill)은 데이터가 입력되면, 들어온 데이터에 맞는 다양한 결과값을 보내줍니다. 이때, 스킬에 보내지는 데이터 또한 파라미터입니다. 

출처 : https://chatbot.kakao.com/docs/key-concepts-parameters#%EC%B1%97%EB%B4%87-%EA%B4%80%EB%A6%AC%EC%9E%90%EC%84%BC%ED%84%B0%EC%97%90-%EB%93%A4%EC%96%B4%EA%B0%80%EB%8A%94-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EA%B0%92

 

발화문에서 태깅된 엔티티를 설정한 파라미터에 연결하는 작업이다. 따라서 숫자 입력을 담는 파라미터를 round_num이라 지정하였으며, 엔티티는 숫자를 인식하는 sys.number이다. $round_num은 공식문서에 따라 엔티티의 값을 그대로 사용하는 방법을 준수하였다.

이제 발화문을 입력하였을 때 숫자에 해당하는 부분을 round_num이라는 파라미터를 request 요청에 담아 서버에 보낸다.

req.body

이 때 요청(req), 응답(res)의 내용을 확인하려면 body 부분을 확인해야 한다. 따라서 req.body.~~~ 형식으로 접근해야 한다. body를 빼먹으면 값을 제대로 읽어오지 못한다.

위 사진에서 보듯이 설정한 파라미터 round_num은 action의 params에 있다. 또한 round_num의 값이 JSON 문자열 형태로 담겨 있다. 따라서 round_num의 key에 접근하기 위해선 먼저 파싱을 해야 한다.

apiRouter.post('/sayHello', function(req, res) {
  
  // params에 해당하는 부분만 JSON 형태이므로 일반 객체로 변환
  const request = JSON.parse(req.body.action.params.round_num) // req.action ~ body를 빼먹어서 오류가 생겼음
  // 만약 params를 제외한 나머지는 일반 객체이다.

  console.log(request.amount); // 입력한 숫자 값 출력
});

round_num에 해당하는 부분을 일반 객체로 변환한 뒤 'amount'의 값을 가져올 수 있다.

스킬 탭에서 스킬 테스트를 진행할 수 있는데 여기서 요청하는 파라미터 또한 req.body.action.params에 담긴다. 테스트에서 직접 파라미터를 테스트하는 경우는 발화문의 엔티티를 해석하는 것이 아니기 때문에 결과 값이 JSON 타입이 아닌 일반 객체로 전달된다.

3. 봇 테스트

챗봇을 최종적으로 수정한 뒤 배포 전에 테스트를 진행할 수 있다. 배포는 하면 할 수록 버전 숫자가 증가하는데 테스트 기능을 알기 전에는 선 배포 후 테스트를 진행하느라 쓸데없이 배포 버전이 많아졌다. 실제 개발에서도 배포라는 것은 신중히 진행되는 것으로 테스트는 필수적이라 할 수 있다.

 

해당 봇을 테스트하기 위해서 실제 배포했을 때와 같은 형태의 챗봇으로 결과 값을 확인할 수 있다. 이는 각 블록 별로 설정한 스킬들의 요청-응답 값을 테스트할 수 있다. 필자는 이를 통해 위 과정에서 설정한 라운드 입력 값에 대한 엔티티 값을 추출할 수 있었다.

 

4. JSON과 일반 객체 구분

객체의 key가 따옴표로 감싸있지 않다. 그러나 params.round_num에 해당하는 부분은 ' ' 으로 되어 있으며 key인 amount와 unit이 큰 따옴표로 되어 있다. 즉, 이 부분은 JSON 타입이다. 따라서 해당 값에 접근하기 위해서는 이 부분을 파싱해서 일반 객체로 접근해야 한다. 파싱하지 않고 해당 값에 접근 (req.body.action.params.round_num["amount"])하면 undefined가 출력된다.

 

5. 스킬 Payload

스킬 payload란 스킬서버에게 전달하는 요청 정보를 말한다. 위에서 확인했던 req.body에 해당하는 내용들이다. 즉, Node/Express를 통해 전달받은 payload의 데이터를 확인하는 절차를 거친 것이다. 기술문서를 통해 payload에 담긴 값들이 무엇을 의미하는지 좀 더 자세하기 설명되어 있다.

https://chatbot.kakao.com/docs/skill-response-format#intent

 

챗봇 관리자센터 개요 · 도움말 - 챗봇 관리자센터

<h2><a class="anchor" aria-hidden="true" id="챗봇-관리자센터-소개"></a><a href="#챗봇-관리자센터-소개" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width

i.kakao.com

 

6. 느낀점

일단 요청한 내용이 어떤 것들을 담고 있는지 직접 코드를 작성하고 실행한 결과를 확인하면서 알 수 있었다. 또한 기술문서를 읽을 수 있다면 직접 실행하지 않더라도 어떤 파라미터를 담고 있는지 알 수 있음을 깨달았다. 하지만 이를 알기 위해서는 모르는 상태에서 일단 코드를 먼저 따라 쳐보고 결과를 계속 확인하면서 배우는 방법 밖에 없는 것 같다. 좋은 글을 계속 읽는 것보다 그냥 코드를 먼저 복붙해서 결과를 확인하며 내용을 이해하는 것이 훨씬 효과적임을 깨달았다. 글을 통해 완전히 이해하려고 한다면 너무나도 어렵고 복잡할 뿐더러 재미 또한 떨어지기 마련이다. 일단 그냥 너무 깊게 생각하지 말고, 또 어렵게 생각하지 말고 코드를 쳐서 결과 값을 확인해 보자. 에러가 난다면 내가 원하는 값이 나올 때까지 계속 수정하면 된다. 그 과정에서 원리를 이해하고 지식을 습득할 수 있을 것이다.