본문 바로가기메뉴 바로가기


바로가기 > KCDC 질병관리본부 채널

어떻게 시작했나

안녕하세요. 봇플랫폼파트 Bart (이철민)입니다.
코로나19 로 인한 많은 우려 속에 정부(질병관리본부)에서 카카오쪽에 지원 요청이 들어 왔습니다. 코로나19의 제대로된 정보 제공과 대응책을 안내할 수 있도록 해달라는 요청이었죠. 지금은 접속이 원활하지만 당시에는 홈페이지도 좀 느린 편이었고 질병관리본부 톡채널(구 플러스친구)도 1:1 상담만 포함된 일반 채널이었기 때문에 소통이 쉽지 않은 상태여서 사용자들의 항의가 많이 쌓인 상태였습니다.

작업 시작

카카오에서 제공하는 서비스 중 다음 포털에서는 메인 화면에 안내 페이지를 가이드하도록 했고 카카오톡에서는 질병관리본부 톡채널에 봇 기능을 붙이기로 했습니다.

현재 시점에서 챗봇의 제일 큰 장점은 사용자들이 자주 물어보는 질문에 대한 답변(FAQ)을 제공해주는 것이라고 생각합니다. 실제 상담원에게 질문이 전달되기 전에 상당 질문을 앞에서 걸러주면 부담이 많이 줄거든요. 그리고 봇에게 질문한 내용이 상담원에게 그대로 전달되기 때문에 질문 의도 파악에도 도움이 됩니다.

자율 주행 자동차의 레벨구분과 비교해보면.. 많이 쓰이는 챗봇의 수준은 한 레벨2 정도라고 생각되요. 계속 더 나은 시스템으로 나아가고 있지만요.

과거 카카오 고객센터 챗봇이라던지 카페봇 같은 봇을 제작해본 경험있는 기획자 분들께서 빠르게 봇의 시나리오 동선과 내용을 만들어 주셨고 저는 봇에 필요한 API를 연결해주는 백엔드 서버를 개발하기 시작 했습니다.

작업은..

챗봇 만드는게 저의 주 작업은 아닙니다만 이런 저런 이유로 많이 만들다보니 꽤 노하우가 쌓여 있어서 그렇게 오래 걸리진 않았습니다. 요즘 주력으로 작업하고있는 kotlin + spring boot에 mongodb 로 구성했고 저희 팀에서 사용하고있는 k8s에 올려서 서비스 하기로 했습니다. 배포도 기존의 배포용 git repo와 argo cd를 구축해놓아서 코드 푸시하면 자동으로 배포되도록 세팅해서 빠르게 대응할 수 있도록 했습니다.

이 부분도 나중에 소개하면 좋을텐데 다른 팀원분들이 만져주시는 부분이고 저는 갖다 쓰는 정도라 제가 이야기하는게 좀 부끄럽겠지만 워낙 좋은 시스템이어서 자랑하고 싶네요

기본적인 질의 응답은 오픈 빌더 내에서 정적으로 처리하도록 했고 동적으로 응답이 필요한 부분은 스킬을 붙여서 응답하도록 했습니다.

스킬 응답 만들기

동적 응답이 필요한 기능은 “진료소 찾기”, “현황”, “폴백 응답”, 지식+ 로 정리 되었습니다.

진료소 찾기

현재 위치나 특정 위치에서 가까운 선별 진료소를 찾아주는 기능입니다. 이럴 때 들어올 수 있는 예상 발화는,

"선별 진료소", "병원", "분당 진료소" 

등이 될 것입니다. 결국 "{위치} + 진료소" 류가 될 텐데요, 위치 정보가 같이 들어오지 않는다면 위치 정보를 받을 수 있는 기능을 연결해서 지역을 받은 다음 스킬 서버로 요청 시 함께 들어오도록 구성 했습니다.

위치플러그인

이렇게 어떻게든 지역 명을 받으면 주소 검색 API를 통해서 정제된 주소 데이터로 바꾼 후 다시 키워드로 장소 검색 API를 이용해 선별 진료소의 정보를 구했습니다.

구체적으로는 주소 검색 API에서 나오는 region_2depth_name 를 가지고 키워드 검색 API에 던졌어요. 동일한 이름의 주소가 있을 경우에 처리도 넣고 이것 저것 했습니다.

그렇게 나온 결과로 카드 캐러셀을 구성해서 내보냈습니다.

지도 이미지 만들어내는 것도 좀 골치 아팠는데 지도 이미지 만들어내는 주소가 WCONG 이라는 좌표계를 받고 있어서 WGS84로 받은 정보를 WCONG으로 변환하는 작업을 해줘야 했거든요. 처음에는 API를 콜해야 했는데 카드가 8개이니 8번을 호출해야하는 고통이 있었습니다만 나중에 라이브러리를 찾아서 내부적으로 계산했습니다.

알고보니 WCONG은 WCONGNAMUL.. 과거 콩나물지도의 유산이었습니다.

현황

최근 확진환자 수나 검사 현황을 보여주는 기능입니다. 다행히(?) 질병관리본부쪽에서 톡채널에 포스트를 꾸준히 올려주고 계셔서 최근 포스트 중 특정 패턴을 제목으로 갖고있는 포스트를 가져와 카드로 구성하게 했어요. 채널의 포스트를 조회할 수 있는 내부 API로 데이터를 받아온 뒤 필터링 했습니다.

val filterWords = """현황|역학조사""".toRegex()
val maybeStatus = response.items.filter {
    it.title.contains(filterWords)
}.maxBy { it.published_at }

질병관리본부쪽에 특정 패턴으로 올려주시라고 요청 드렸습니다만 경황이 없으셔서 그런지 다른 제목 패턴으로 올려주시기도 하셔서 그에 맞춰 쭉 대응을 했습니다. 최종적으로는 이미지 + 내용을 담은 카드로 구성을 해서 출력됩니다. 근데 이미지가 안나오네요. 고쳐야할듯 -_-

결과적으론 이 기능이 제일 많이 쓰이고 있습니다.

파란색이 현황 블럭이 호출될 때 작동하는 스킬 API 호출량입니다.

폴백 (+ 지식+)

봇이 처리할 수 없는 질문일 때 나가는 응답을 설정하는 것을 오픈 빌더에서는 폴백 블럭에 설정한다고 표현합니다. 그리고 지식+는 들어온 발화가 미리 입력해둔 QnA 중 유사하다고 판단되는 것이 있으면 그에 해당하는 응답을 내보내 주는 기능인데요.

이게.. 그냥 세팅하면 발화의 의도를 판단하는 순서가 ,

지식+ -> 의도 파악 로직 -> 폴백

입니다만.. 내부적으로는 지식+를 통해 나온 결과에도 score 값이 있고 의도 파악 로직에도 머신 러닝을 태운 결과라면 score 값이 있어서 봇 제작자에게 임계점 판단을 맡기면 좋겠습니다만 외부에 오픈된 기능에서는 이 임계점을 설정할 수가 없습니다.

예를 들어 봇 제작자는 80점 이상일 때 답을 선택되길 바랬지만 내부적으로 임계점이 65점 이상일 때 선택되도록 고정되어있고 기계님이 “제 생각에는 아마도 이 질문 같아요” 라고 말씀해주시며 score 값을 100점 만점에 70점으로 내려준다면 이라면 봇 제작자의 의도와는 다르게 이 답변이 선택되어 응답으로 나가버리는 것이죠.

저희는 좀 더 정확한 답일 경우에만 나가길 바랬고 위와 같은 이유로 저는 봇의 지식+ 답변 선택 세팅을 끄고 내부적으로 호출한 뒤 별도로 판단하여 답변을 선택하게 했습니다.

아마 임계점을 조절하는 것은 외부로 오픈 될 것입니다.(이미 리스트엔 올라와 있긴 합니다만) 이런 식으로 개밥 먹다보면 불편한게 보이고.. 기능으로 개발되고.. 그런거죠.

결과적으로 기계님이 내려주신 응답들의 score가 고만고만 하면 사용자에게 선택을 하게 했고, 한개의 답변이 높은 편이면 그 답이 나가도록 했습니다. 전부다 애매하면 폴백 답변이 나갑니다.

결과

그래서 기본적인 동작은 하루만에 거의 다 만들고 2일 정도 후 오픈 했어요. 완성도는 음.. 한 85% 정도이긴 했습니다만 빠르게 오픈 했어야 했기에 별 수 없었습니다. 그 후에 디테일 끌어올리는 작업은 쭉 틈나는 대로 했습니다. 오픈 후에 1700만명(…)에게 푸시 메시지도 나가고 톡비즈보드에도 배너가 걸리고 다음탑에서 웹 챗봇으로도 유입도 되고 있네요.

트래픽이 많이 들어올 것이라 예상될 때에는 간단하게 replicas 수를 늘려서 적용함으로써 대응 했어요. k8s 만세.

빠르게 사라져야할 봇이고 실제 봇 호출량도 감소 추세여서 다행이다 생각하고 있었는데 요즘 들어 다시 증가세로 돌아 섰습니다.

질본 채널도 요청 받을 당시 30만이던 친구수가 어느새 70만을 돌파 했습니다.

고생하시는 질병관리본부 공무원분들에게 조금이나마 도움이 되었길 바라며 빠르게 코로나19가 진정되길 바랍니다.


질병관리본부 톡채널에 대한 내용은 브런치에서도 확인하실 수 있습니다!

bart.lee
bart.lee 새로운 아이디어를 내고 그것을 빠르게 구현해 내는 것을 좋아하는 개발자입니다

위로