[GCP]Dialogflow 를 이용한 간단 챗봇 만들기 6탄 — Proxy server 패턴

안녕하세요 이정운 입니다.

지난번에 Dialogflow 에 대한 이야기의 대장정 사이에서 Google 의 대표적인 PaaS 서비스인 GAE flex 를 소개하고 container 기반으로 서비스를 배포하고 짧게 A/B 테스트까지 해봤습니다.(링크) Dialogflow 이야기 시리즈 중간에 굳이 GAE flex 이야기를 했던 이유중의 하나는 이번에 GAE flex 를 이용해서 Dialogflow 의 proxy server 아키텍처 패턴를 구성해 보려고 했기 때문입니다. (이름은 거창하지만 그냥 중간에 proxy server 를 두는 구성 입니다.)

Dialogflow 의 proxy server 아키텍처 패턴이란 상단의 구조처럼 Dialogflow 가 Chat platform(또는 Chat interface) 에서 바로 요청을 받는 것이 아니라 중간에 proxy server 를 두어서 해당 단계에서 모든 쿼리를 처리하여 사용자 제어력을 높일 수 있는 아키텍처 구조입니다. 이 아키텍처의 가장 큰 장점은 모든 요청과 응답이 proxy server 를 거치는 구조이므로 사용자가 필요한 경우에 전처리나 후처리를 쉽게 추가할 수 있다는 점 입니다.

예를 들어 입력값의 보정이나 수정이 필요할때, dialogflow 가 처리하지 않고 사람이 처리하도록 하는 Human handoff 가 필요할 때 proxy server 패턴인 경우 해당 구현이 용이합니다. 또 하나의 예를 더 들자면 이와 같은 구성을 통해서 민감정보를 가리고 실제 사용자와 채팅을 하는 형태도 쉽게 구현할 수 있습니다. 챗봇과 대화중에 cloud 에 올라가기에는 민감한 데이터가 있다면 proxy server 를 on-prem 데이터센터에 두고 해당 데이터는 필터를 이용해서 가린후에 dialogflow 와 연동을 할 수가 있습니다. 또는, Dialogflow 에서 직접 연동 기눙을 제공하지 않는 카카오톡과 같은 다른 챗봇과의 연동이 필요할 때도 유용하게 잘 쓰일수 있습니다.

다만, 모든것을 만족하고 장점만 있는 아키텍처는 있을 수 없는 것처럼 proxy server 패턴도 결국 네트워크 입장의 홉이 하나 증가되어 성능 감소가 있을 수 있고 관리 포인트도 증가되는 단점을 가지고 있습니다.결국, 전체적인 아키텍처를 구성하는 모든 방법론이 동일하겠지만 구현시 각 환경과 요건에 따라서 실제 챗봇 구현 목적에 더 적합한 패턴이나 아키텍처를 선택해서 사용하면 되지 않을까 합니다.

그럼 지금부터 실제 구현을 해보면서 이를 좀 더 살펴보는 시간을 가져보도록 하겠습니다. 늘 이야기 하지만 본 이야기는 하단의 링크들을 참고하여 작성하였습니다.

Quickstart for Node.js in the App Engine Flexible Environment
https://cloud.google.com/appengine/docs/flexible/nodejs/quickstart

Extending the Node.js Runtime of the Google App Engine Flexible Environment
https://cloud.google.com/community/tutorials/extending-google-appengine-flexible-nodejs-runtime

app.yaml Configuration File
https://cloud.google.com/appengine/docs/flexible/nodejs/reference/app-yaml

dialogflow-nodejs-client-v2
https://github.com/dialogflow/dialogflow-nodejs-client-v2#quickstart

dialogflow-nodejs-client-v2/samples/detect.js
https://github.com/dialogflow/dialogflow-nodejs-client-v2/blob/master/samples/detect.js


#1) Dialogflow client library 테스트

Proxy server 패턴을 구현하기 위해서는 가장 기본적으로 Dialogflow client library 를 이용해서 proxy server 를 만들어야 하며 이를 통해서 Dialogflow 와 통신해야 합니다. (다 직접 짤수도 있겠지만 만들어져 있는 모듈을 가지고 사용하는 것이 훨 수월하겠죠.) 본격적으로 Proxy server 를 작성하기 전에 간단하게 Dialogflow client library 에 대한 sample code 를 이용해서 간단히 테스트해보고 그 구조를 살펴보는 시간을 가져보도록 하겠습니다.

다양한 환경에서 테스트 가능하겠지만 보다 더 쉽게 테스트 해보기 위하여 지난 이야기에서 언급했던 Google Cloud Platform(GCP) 관리 콘솔로 먼저 접속합니다. (Dialogflow 와 연동된 GCP 프로젝트를 의미하며 에이전트 설정 메뉴에서 확인 가능합니다.)

https://console.cloud.google.com

GCP 메뉴에서 우측 상단에 있는 사각형 아이콘을 클릭하여 Cloud shell 을 실행합니다. 참고로 Cloud Shell 은 브라우저에서 바로 사용할 수 있는 콘솔을 제공해주는 컴포넌트로 쉽게 생각해서 개발자를 위한 개발 서버를 바로 제공해준다고 보면 됩니다. (더군다나 무료 입니다. — https://cloud.google.com/shell/docs/)

Cloud shell 에서 npm 을 이용해 dialogflow 모듈과 google cloud 를 위한 common 모듈을 설치합니다. (Cloud shell 의 또다른 장점은 개발자를 위해서 필요한 많은 모듈들이 사전에 설치되어 있다는 것입니다. )

npm install — save dialogflow
npm install @google-cloud/common — save

혹시, 위의 명령을 수행하는데 문제가 있다면 npm update 를 해보시고 진행해보시기를 바라겠습니다.

그리고 테스트를 위해서 github 에 공개되어 있는 dialogflow-nodejs-client-v2 소스를 로컬로 복제 합니다. (참고로 proxy server 의 특성상 효율이 좋은 node.js 가 그나마 편해서 node.js 기준으로 테스트 하지만 다른 프로그래밍 언어를 원하시면 github 에 다른 코드들을 참고하시기 바라겠습니다)

git clone https://github.com/dialogflow/dialogflow-nodejs-client-v2.git
cd dialogflow-nodejs-client-v2/samples

해당 디렉토리에서 다양한 Sample 소스를 확인해봅니다. 참고적으로 Cloud shell 의 또 하나의 장점은 code editor 도 지원이 된다는 것입니다. Cloud shell 의 우측 상단의 연필모양을 클릭하게 되면 Code editor 로 마치 eclipse 처럼 소스를 보면서 편하게 편집할 수 있습니다.

Sample 폴더에는 다양한 샘플들이 있는데 여기서는 가장 간단하게 Dialogflow 와 통신이 되는 지만 확인하기 위해서 detect.js 를 테스트 해보도록 하겠습니다. 해당 소스를 보시면 크게 text 로 쿼리를 수행하는 detectTextIntent(), event 로 쿼리하는 detectEventIntent(), 음성파일로 쿼리하는 detectAudioIntent(), 스트리밍으로 쿼리하는 streamingDetectIntent() 함수로 이루어져 있으며 잘 만들어진 샘플이기 때문에 지금 여기서는 detectTextIntent() 만 보지만 실제 개발시에는 다른 소스들도 참고하시면 좋을듯 합니다. (실제로 본 이야기에서는 간단한 테스트가 목적이고 Dialogflow 에 대한 이야기다 보니 실제 프로그래밍을 깊게 다루지는 않도록 하겠습니다. 하고 싶어도 제가 잘 몰라서…@.,@)

해당 소스에 대한 좀더 상세 설명과 사용 방법은 github 에 자세히 정리되어 있으니 이를 참고하시기 바라겠습니다.

https://github.com/dialogflow/dialogflow-nodejs-client-v2/tree/master/samples

추가적으로 테스트를 시작하기 전에 Dialogflow 접속 권한을 획득하기 위한 인증키가 필요합니다. 이를 위해서 GCP 관리콘솔에 IAM & admin > Service accounts 메뉴로 가면 하단과 같이 dialogflow 관련 service account 를 찾을 수 있습니다. 해당 service account 의 우측 끝에 햄버거 메뉴를 클릭하여 key 를 생성하고 json 형태로 key를 다운로드가 가능합니다.

다음으로 다운로드한 json 형태의 key 파일을 Cloud shell 로 업데이트 합니다. 참고로 Cloud shell 의 우측 상당 햄버거 메뉴에는 하단과 같이 ‘Upload file’ 메뉴가 있어서 아주 쉽게 작업하고 있는 로컬의 파일을 Cloud shell 로 업로드 가능합니다.

마지막으로 Cloud shell 에서 수행되는 프로그램이 credential key 정보를 인식하기 위하여 하단과 같이 환경변수를 추가 합니다. 이때 해당 환경변수의 값은 지금막 업로드한 json 형태의 key 파일의 위치를 입력하시면 됩니다.

export GOOGLE_APPLICATION_CREDENTIALS=”/home/jwlee98/jwlee-dialogflow-test01–9d7aa7b58efb.json”

여기까지 잘 완료했으면 Dialogflow 통신을 위한 권한처리에 대한 준비가 완료된 것이니 이제 실제 테스트를 해보도록 하겠습니다. 기 언급한 것처럼 다양한 Sample 소스 중에 detect.js 를 사용해서 정상적으로 Dialogflow 와 통신이 가능한지 간단하게만 테스트해보도록 하겠습니다. 이때 projectId(Dialogflow 의 프로젝트 ID 를 의미하며 Dialogflow 설정 화면에서 확인 가능) 와 languageCode(언어 코드를 넣어주면 됩니다. 한글은 ‘ko’), sessionId(session 에 대한 ID 값으로 사용자를 구분하며 같은 사용자의 경우 동일 sessionId 를 넣어주면 됩니다.) 경우에는 테스트 목적에 맞게 각각 임의로 넣으시면 됩니다. 이와 같은 기준으로 기존에 만들어둔 Dialogflow 의 Intent 를 호출하도록 하단과 같이 테스트 해봅니다.

node detect.js text — projectId jwlee-dialogflow-test01 — languageCode ko — sessionId “detect-session-id” -q “자전거에 문제가 생겼어요”

node detect.js text — projectId jwlee-dialogflow-test01 — languageCode ko — sessionId “detect-session-id” -q “내일 오후 2시에 하고 싶어요”

상단과 같이 이전 이야기의 Dialogflow 테스트와 동일하게 텍스트로 결과가 나오면 Dialogflow client library 를 가지고 정상적으로 Dialogflow 와 테스트 통신을 수행하신 것입니다. 짝짝짝!


#2) Dialogflow 를 위한 Proxy server 생성 — GAE flex

이전 파트에서 Dialogflow client library 를 살펴보고 사용하는 방법을 테스트 해봤으며 어떻게 동작하는지 테스트 해봤습니다. 그럼 이제 본격적으로 Proxy server 를 작성해보도록 할까요? (본격적이라고 하지만 개발 이야기가 아니므로 간단한 데모 정도만 만들 예정입니다.)

detect.js 를 참고해서 간단한 sample code 를 server.js 로 작성해서 살펴보도록 하겠습니다. 하단의 소스는 이전 파트에서 언급한 detect.js 를 기반으로 간단하게 proxy server 구현을 해보도록 수정을 하였습니다. 예를들어 요청/응답 기반으로 동작하기 위하여 query 를 배열로 받는 부분을 수정하였고 서버로 동작하기 위해서 express 모듈을 추가했습니다. 마지막으로, 좀 더 테스트 목적에 깔끔하도록 불 필요한 것들은 싹 날렸습니다.

참고로 Cloud shell 에는 node.js 용 express 모듈이 없으므로 사전에 npm 을 이용해서 설치해야 합니다. (예: npm install express — save)

참고로 해당 소스는 하단의 github 에 올려두었으니 좀 더 자세한 소스가 궁금하신 분들은 참고하시기 바라겠습니다.
https://github.com/jwlee98/GCP/tree/master/dialogflow/lecture06

이렇게 소스 작성이 완료되었으면 이제 정상적으로 돌아가는지 Cloud Shell 에서 로컬 테스트를 한번 해보겠습니다. (로컬에서 직접 테스트 해보고 문제가 없으면 GAE flex 로 배포하려는 목적입니다.)

node ./server.js&

curl — header “Content-Type: application/json” \
— request POST \
— data ‘{“query”:”자전거에 문제가 있습니다”}’ \
http://localhost:8080/queryDialogflow

상단의 결과처럼 테스트가 문제없이 되었다면 GAE flex 에 배포하는 단계를 수행하도록 하겠습니다.

그런데 우선, GAE flex 배포 전에 IAM 에서 dialogflow 호출을 위한 권한에 문제가 없도록 첫번째 파트에서 언급한 것과 유사하게 GAE 의 default service account 에 dialogflow client 권한을 하단과 같이 할당해 두셔야 합니다.

그리고 실제 GAE flex 배포에서 사용될 설정파일인 app.yaml 을 하단과 같이 만들어 둡니다.

이제 준비가 되었으면 GAE flex 배포를 수행합니다. 이번 이야기에서는 지난 이야기와 좀 다르게 바로 명령어를 수행하는 형태로 진행합니다.(다양한 배포 방법을 보여주기 위해서이지 다른 의미는 없습니다.)

gcloud app deploy

‘gcloud app deploy’ 로 GAE flex 를 배포하게 되면 지난 이야기에서 봤던 것과 동일하게 배포되긴 하지만 사전에 Cloud shell 에 있는 내용을 container image 로 만드는 단계가 자동으로 추가되어서 진행됩니다. GAE flex 가 정상 배포되었다면 GCP 관리콘솔의 App Engine 메뉴에서 다음과 같이 확인가능합니다.

추신 #1 : 추가적으로 app.yaml 의 runtime 을 “runtime: custom” 으로 하게 되면 하단의 명령을 통해서 Dockerfile 을 자동 생성할 수 있습니다.

gcloud beta app gen-config — custom

이렇게 Dockerfile 이 생성되면 원하는 형태대로 추가 커스터마이징이 가능해지며(좀 더 세밀하게 container image 생성 가능) 이전 이야기에서 언급했던 것처럼 Container registry 에 container image 만들고 생성된 container image 를 GAE flex 로 배포도 가능합니다.

gcloud builds submit — tag gcr.io/jwlee-dialogflow-test01/gaetest ./

gcloud app deploy — image-url=gcr.io/jwlee-dialogflow-test01/gaetest ./app.yaml

추신 #2 : 개발/테스트 환경인 경우 GAE flex 버전을 새롭게 만들지 말고 기존 버전을 업데이트 하도록 작업하면 (deploy 명령 뒤에 version 만 동일하게 넣어주면 됩니다.) 배포시간을 많이 줄일 수 있습니다. (테스트의 경우 약 2분만에 배포 완료)

gcloud app deploy — image-url=gcr.io/jwlee-dialogflow-test01/gaetest ./app.yaml — version=20180824t194433

이렇게 GAE flex 의 배포가 정상적으로 완료 되었다면 GAE flex 의 서비스 주소를 (https://프로젝트명.appspot.com) 통해서 이전과 동일하게 테스트 요청을 수행해보면 하단과 같이 dialogflow 를 통해서 정상적으로 응답이 나오는 것을 확인 가능합니다.

curl — header “Content-Type: application/json” \
— request POST \
— data ‘{“query”:”자전거에 문제가 있습니다”}’ \
https://jwlee-dialogflow-test01.appspot.com/queryDialogflow

curl — header “Content-Type: application/json” \
— request POST \
— data ‘{“query”:”내일 오후 2시에 하고 싶어요”}’ \
https://jwlee-dialogflow-test01.appspot.com/queryDialogflow


여기까지 잘 확인이 되었다면 오늘 이야기에서 하려고 했던 GAE flex 를 이용해서 proxy server 를 구현해보고 그 테스트까지 무사히 잘 마무리 하신것 입니다. 이제 해당 구조라면 Chat interface 가 무엇이든 간에 request/response 형태만 proxy server 에서 변경해주면 dialogflow 와 소통이 가능합니다. 처음에 이야기 했듯이 다양한 아키텍처 형태가 있으며 그 중에 proxy server 패턴을 사용하면 다양한 장점을 추가할 수 있습니다. 이를 통해서 사전에 다양한 제어도 가능하며 직접 integration 기능을 제공하지 않는 카카오톡과 같은 챗봇 플랫폼과 원하는 형태대로 연동도 가능하다는 점 참고 바라겠습니다.

오늘 준비한 이야기는 여기까지이며 다음에 다른 이야기로 다시 돌아 오도록 하겠습니다. 그럼 이만 휘리릭~~~

추신 #3: 당연한 이야기겠지만 proxy server 에 이전 강좌(링크) 에서 사용된 Webhook 용 서버 소스를 올리고 필요한 URL 만 다르게 설정한다면 proxy server 에서 Dialogflow 의 Fulfillment 처리도 가능합니다.

추신 #4 : 이번 이야기를 위해서 사용한 소스는 공유를 위해서 github 에 올려두었으니 참고하시기 바라겠습니다.

* Disclaimer: 본 글의 작성자는 Google 직원이지만 Google cloud 를 공부하는 한 개인으로서 작성된 글입니다. 본 글의 내용, 입장은 Google 을 대변하지 않으며 Google 이 해당 콘텐츠를 보장하지 않습니다.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade