Google 어시스턴트용 작업으로 사용자 참여 유도하기

1. 개요

Actions on Google 개발자 플랫폼을 사용하면 스마트 스피커, 스마트폰, 자동차, TV, 헤드폰 등 10억 대 이상의 기기에서 Google의 가상 개인 비서인 Google 어시스턴트의 기능을 확장하는 소프트웨어를 만들 수 있습니다. 사용자는 어시스턴트와의 대화를 통해 식료품 구매나 차량 예약 등의 작업을 처리합니다. 가능한 작업 전체 목록은 작업 디렉터리를 참고하세요. 개발자는 Actions on Google을 사용하여 사용자와 서드 파티 서비스 간의 즐겁고 효과적인 대화형 환경을 쉽게 만들고 관리할 수 있습니다.

이 모듈은 Google 어시스턴트용 작업을 빌드해 본 경험이 있는 독자를 위한 고급 Codelab 모듈입니다. 이전에 Actions on Google을 사용해 본 경험이 없다면 입문 Codelab ( 레벨 1, 레벨 2, 레벨 3)에 따라 플랫폼에 익숙해지시는 것이 좋습니다. 이 고급 모듈에서는 작업의 기능을 확장하고 잠재고객을 늘리는 데 도움이 되는 일련의 기능을 안내합니다.

작업의 성공을 측정하는 한 가지 중요한 방법은 사용자 참여 또는 작업이 첫 상호작용 후 사용자를 다시 돌아오게 하는 데 얼마나 효과적인지를 측정하는 것입니다. 이를 더 쉽게 하기 위해 사용자에게 대화로 돌아가는 경로를 제공하는 여러 기능을 작업에 구현할 수 있습니다.

이 Codelab에서는 Actions on Google의 사용자 참여 기능과 권장사항을 다룹니다.

a3fc0061bd01a75.png 961ef6e27dc73da2.png

빌드할 항목

다음을 사용 설정하여 이미 빌드된 기능을 개선합니다.

  • 사용자에게 탭하여 작업과 대화할 수 있는 일일 업데이트를 전송합니다.
  • 사용자에게 작업으로 돌아가는 푸시 알림을 보냅니다.
  • 사용자를 모바일 웹브라우저에서 작업으로 연결하는 링크를 만듭니다.

학습할 내용

  • 사용자 참여란 무엇이며 액션의 성공에 사용자 참여가 중요한 이유
  • 사용자 참여도를 높이기 위해 작업을 수정하는 방법
  • 다양한 종류의 작업에서 사용할 수 있는 사용자 참여 기능
  • Actions API를 사용하여 어시스턴트를 통해 알림을 전송하는 방법

필요한 항목

다음과 같은 도구가 있어야 합니다.

  • 원하는 IDE/텍스트 편집기(예: WebStorm, Atom, Sublime)
  • Node.js, npm, git이 설치된 셸 명령어를 실행하는 터미널
  • 웹브라우저(예: Chrome)
  • Firebase 명령줄 인터페이스가 있는 로컬 개발 환경
  • 어시스턴트가 지원되는 휴대기기 (Android 또는 iOS)(이 프로젝트를 빌드하는 데 사용할 Google 계정과 동일한 Google 계정으로 어시스턴트에 로그인해야 합니다.)

웹훅 코드를 이해하려면 JavaScript (ES6)를 능숙하게 다루는 것이 좋지만, 필수사항은 아닙니다.

2. 프로젝트 설정

이 섹션에서는 이전에 빌드한 완전한 작업에 사용자 참여 기능을 추가하는 방법을 설명합니다.

샘플 이해하기

이 Codelab의 샘플은 'Action Gym'이라는 가상의 헬스장을 위한 간단한 작업입니다. 작업은 매일 순환하는 수업 목록을 포함하여 체육관에 관한 정보를 제공합니다. 순환 클래스 목록은 매일 다른 유용한 정보를 제공하므로 이와 같은 정보를 제공하는 작업은 모든 사용자 참여 기능에 적합합니다.

다음 다이어그램은 Action Gym 샘플의 대화 흐름을 보여줍니다.

e2d6e4ad98948cf3.png

추가하는 참여 기능에 더 적합하도록 대화상자를 약간 수정합니다. 하지만 대화의 일반적인 디자인은 많이 변경되지 않습니다.

기본 파일 다운로드

다음 명령어를 실행하여 Codelab용 GitHub 저장소를 클론합니다.

git clone https://github.com/actions-on-google/user-engagement-codelab-nodejs

프로젝트 및 에이전트 설정

작업 프로젝트 및 Dialogflow 에이전트를 설정하려면 다음 단계를 완료하세요.

  1. Actions 콘솔을 엽니다.
  2. 새 프로젝트를 클릭합니다.
  3. 프로젝트 이름(예: engagement-codelab)을 입력합니다.
  4. 프로젝트 만들기를 클릭합니다.
  5. 카테고리를 선택하는 대신 옵션 더보기 섹션까지 아래로 스크롤한 다음 대화형 카드를 클릭합니다.
  6. Build your Action을 클릭하여 옵션을 펼치고 Add Action(s)을 선택합니다.
  7. Add Your First Action(첫 번째 작업 추가)을 클릭합니다.
  8. Create Action 대화상자에서 Custom Intent를 선택한 다음 Build를 클릭하여 Dialogflow 콘솔을 시작합니다.
  9. Dialogflow 콘솔의 에이전트 만들기 페이지에서 만들기를 클릭합니다.
  10. 왼쪽 탐색 메뉴에서 6bf56243a8a11a3b.png (톱니바퀴 아이콘)을 클릭합니다.
  11. 내보내기 및 가져오기를 클릭한 다음 Zip 파일에서 복원을 클릭합니다.
  12. 앞서 다운로드한 /user-engagement-codelab-nodejs/start/ 디렉터리에서 agent.zip 파일을 업로드합니다.
  13. RESTORE를 입력하고 복원을 클릭합니다.
  14. 완료를 클릭합니다.

처리 배포

이제 작업 프로젝트와 Dialogflow 에이전트가 준비되었으므로 Firebase Functions CLI를 사용하여 로컬 index.js 파일을 배포합니다.

기본 파일 클론의 /user-engagement-codelab-nodejs/start/functions/ 디렉터리에서 다음 명령어를 실행합니다.

firebase use <PROJECT_ID>
npm install
firebase deploy

몇 분 후에 웹훅이 Firebase에 성공적으로 배포되었음을 나타내는 'Deploy complete!'가 표시됩니다.

배포 URL 가져오기

Dialogflow에 Cloud 함수의 URL을 제공해야 합니다. 이 URL을 검색하려면 다음 단계를 따르세요.

  1. Firebase Console을 엽니다.
  2. 옵션 목록에서 작업 프로젝트를 선택합니다.
  3. 개발 > 함수를 클릭합니다. '데이터 공유 설정을 선택'하라는 메시지가 표시되는 경우 나중에 하기를 클릭하여 이 옵션을 무시할 수 있습니다.
  4. 대시보드 탭에 'fulfillment' 항목이 표시됩니다. 트리거 아래에 URL을 입력합니다. 이 URL을 저장합니다. 다음 섹션에서 Dialogflow에 복사해야 합니다.

1741a329947975db.png

Dialogflow에서 웹훅 URL 설정

이제 처리에 웹훅을 사용하도록 Dialogflow 에이전트를 업데이트해야 합니다. 힙 덤프를 분석하려면 다음 단계를 따르세요.

  1. Dialogflow 콘솔을 엽니다. 원하는 경우 Firebase 콘솔을 닫아도 됩니다.
  2. 왼쪽 탐색 메뉴에서 fulfillment를 클릭합니다.
  3. 웹훅을 사용 설정합니다.
  4. Firebase 대시보드에서 복사한 URL이 아직 표시되지 않으면 붙여넣습니다.
  5. 저장을 클릭합니다.

프로젝트가 올바르게 설정되었는지 확인

사용자는 작업 시간이 포함된 하드 코딩된 텍스트 응답, 각 요일의 수업 일정을 나열하는 텍스트 응답을 비롯하여 Action Gym에 관한 정보를 얻기 위해 작업을 호출할 수 있어야 합니다.

작업 시뮬레이터에서 작업을 테스트하려면 다음 단계를 따르세요.

  1. Dialogflow 콘솔 왼쪽 탐색 메뉴에서 통합 >을 클릭합니다. Google 어시스턴트
  2. 자동 미리보기 변경사항이 사용 설정되어 있는지 확인하고 테스트를 클릭하여 작업 프로젝트를 업데이트합니다.
  3. 작업 시뮬레이터가 작업 프로젝트를 로드합니다. 작업을 테스트하려면 Input 필드에 Talk to my test app를 입력하고 Enter 키를 누릅니다.
  4. Action Gym에 오신 것을 환영한다는 답변이 표시됩니다. 메시지에 따라 대화를 계속 진행하면서 처리에서 각 입력에 대한 응답을 제공하는지 확인합니다.

60acf1ff87b1a87f.png

3. 일일 업데이트 구독 추가

사용자의 참여를 유도하는 일반적인 방법은 가장 유용한 때에 정보를 제공하는 것입니다. 이는 사용자에게 인텐트의 일일 업데이트를 구독하는 옵션을 제공하여 해당 인텐트의 처리로 직접 연결되는 어시스턴트 알림을 전송함으로써 이루어집니다.

이 단계에서는 일일 업데이트 구독에 관해 알아보고 작업의 Class List 인텐트에 구독을 추가합니다. 이 안내를 따르면 작업의 대화가 다음 다이어그램과 같이 표시됩니다.

f48891c8118f7436.png

어떻게 사용자의 참여를 유도할까요?

스마트폰 사용자는 앱별 정보와 업데이트를 제공하는 푸시 알림에 익숙할 것입니다. 업데이트를 전송하는 의도가 사용자에게 매일 가치를 제공한다면 일일 업데이트 구독을 통해 어시스턴트 외부의 휴대기기 사용자에게 간편하게 액세스할 수 있습니다.

일일 업데이트는 유용한 참여 도구일 수 있지만 모든 작업에 반드시 통합되어야 하는 것은 아닙니다. 작업에 일일 업데이트 구독을 추가할지 결정할 때 다음 팁을 고려하세요.

  • 매일 업데이트하면서 사용자에게 매일 다르고 유용한 정보가 표시되는지 확인합니다. 일일 업데이트를 탭할 때마다 매번 같은 메시지가 표시된다면 사용자가 며칠 후 구독을 취소할 가능성이 높습니다.
  • 사용자가 일일 업데이트의 의도로 곧바로 이동하는 경우 대화 내용이 사용자에게 의미가 있는지 확인하세요. 사용자가 대화를 처음부터 시작하지 않을 수도 있으므로 많은 맥락이 있다고 기대해서는 안 됩니다.
  • 일일 업데이트를 구독하라는 메시지를 표시하기 전에 사용자에게 작업의 이점을 보여주세요. 사용자는 '매일 이 콘텐츠를 원합니다'라고 생각해야 합니다. 구독 옵션이 표시될 때
  • 구독을 반복적으로 제안하여 사용자를 부담스럽게 하지 마세요. 사용자에게 구독하고자 하는 콘텐츠를 보여준 직후 일일 업데이트 구독을 제공하고 다른 곳에서 성가시게 하지 않습니다.
  • 업데이트 인텐트가 트리거된 후에는 대화를 짧게 유지하세요. 대부분의 일일 업데이트는 단일 응답으로만 구성되고 사용자 입력 없이 종료됩니다.

일일 업데이트 사용 설정

일일 업데이트 구독은 사용자를 대화를 시작하게 하는 시작 인텐트에 추가되거나 대화 내의 어딘가로 딥 링크하기 위해 더 구체적인 인텐트에 추가될 수 있습니다. 이 Codelab에서는 대화상자가 매일 변경되고 사용자는 사용 가능한 클래스를 알려주는 것이 유용할 수 있으므로 Class List 인텐트가 가장 적합합니다.

Class List 인텐트의 일일 업데이트를 사용 설정하려면 다음 단계를 따르세요.

  1. Actions 콘솔에서 개발 탭을 클릭하고 왼쪽 탐색 메뉴에서 작업을 선택합니다.
  2. 작업 목록에서 Class List를 클릭합니다.
  3. 사용자 참여 발생 시간 섹션에서 사용자에게 일일 업데이트를 제공하시겠습니까 옵션을 전환합니다.
  4. 일일 업데이트를 설명하는 구체적인 콘텐츠 제목을 설정합니다. 컨텍스트는 '매일 <콘텐츠 제목>을(를) 몇 시에 보내 드릴까요?'이므로 소리 내어 말할 때 제목이 구체적이고 소리가 정확해야 합니다. 이 예에서는 콘텐츠 제목list of upcoming Action Gym classes로 설정합니다.
  5. 페이지 상단의 저장을 클릭합니다.

c00885cc30e14d68.png

Dialogflow 설정

Dialogflow 콘솔에서 다음 단계에 따라 일일 업데이트 구독 흐름의 인텐트를 만듭니다.

사용자에게 구독하라는 메시지 표시

  1. 일일 업데이트 구독을 요청하는 사용자를 처리할 새 인텐트를 설정합니다. Dialogflow 콘솔에서 왼쪽 탐색 메뉴의 인텐트 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
  2. 이 새 인텐트의 이름을 Setup Updates로 지정합니다.
  3. 학습 문구 섹션에서 다음 사용자 표현을 추가합니다.
  • Send daily reminders
  • Reminder
  • Remind me
  • Updates
  • Upcoming classes
  1. fulfillment 섹션에서 이 인텐트에 웹훅 호출 사용 설정 옵션을 전환합니다.
  2. 페이지 상단의 저장을 클릭합니다.

5c70faa02151da0.png

사용자 결정 처리

  1. 일일 업데이트 구독 메시지에 대한 사용자의 응답을 처리할 새 인텐트를 설정합니다. 왼쪽 탐색 메뉴에서 Intents 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
  2. 이 새 인텐트의 이름을 Confirm Updates로 지정합니다.
  3. 이벤트 섹션 아래에 actions_intent_REGISTER_UPDATE를 추가합니다. 이 Dialogflow 이벤트는 구독 여부에 관계없이 사용자가 일일 업데이트 구독 흐름을 완료하면 트리거됩니다.
  4. fulfillment 섹션에서 이 인텐트에 웹훅 호출 사용 설정 옵션을 전환합니다.
  5. 페이지 상단의 저장을 클릭합니다.

b871c2bdadac8abc.png

처리 구현

웹훅에서 처리를 구현하려면 다음 단계를 완료하세요.

종속 항목 로드

b2f84ff91b0e1396.png index.js 파일에서 require() 함수를 업데이트하여 actions-on-google 패키지의 RegisterUpdate 패키지를 추가합니다. 그러면 가져오기가 다음과 같이 표시됩니다.

index.js

const {
  dialogflow,
  Suggestions,
  RegisterUpdate,
} = require('actions-on-google');

추천 칩 업데이트

b2f84ff91b0e1396.png index.js 파일에서 DAILY 항목을 추천 검색어 칩 제목 목록에 추가합니다. 그러면 Suggestion 정의가 다음과 같이 표시됩니다.

index.js

// Suggestion chip titles
const Suggestion = {
  HOURS: 'Ask about hours',
  CLASSES: 'Learn about classes',
  DAILY: 'Send daily reminders',
};

새 인텐트의 fulfillment 추가

사용자가 구독하겠다고 말하면 업데이트의 타겟 인텐트 (클래스 목록) 및 유형 (DAILY)으로 RegisterUpdate 도우미를 호출하여 일일 업데이트 구독 흐름을 시작합니다. 정기 결제 흐름이 완료되면 어시스턴트는 정기 결제 성공 여부를 설명하는 status 인수를 사용하여 actions_intent_REGISTER_UPDATE 이벤트를 트리거합니다. 사용자에게 정기 결제 상태에 따라 변경되는 후속 메시지를 제공합니다.

b2f84ff91b0e1396.png index.js 파일에 다음 코드를 추가합니다.

index.js

// Start opt-in flow for daily updates
app.intent('Setup Updates', (conv) => {
  conv.ask(new RegisterUpdate({
    intent: 'Class List',
    frequency: 'DAILY',
  }));
});

// Confirm outcome of opt-in for daily updates
app.intent('Confirm Updates', (conv, params, registered) => {
  if (registered && registered.status === 'OK') {
     conv.ask(`Gotcha, I'll send you an update everyday with the ` +
     'list of classes. Can I help you with anything else?');
  } else {
    conv.ask(` I won't send you daily reminders. Can I help you with anything else?`);
  }
  if (conv.screen) {
    conv.ask(new Suggestions([Suggestion.HOURS, Suggestion.CLASSES]));
  }
});

사용자에게 대체 메시지 제공

수업 목록 응답에서 마지막에 일일 업데이트 구독을 제공하지만 문제가 발생합니다. 사용자가 일일 업데이트 알림을 탭하면 이와 동일한 응답이 트리거되므로 일일 업데이트 알림일지라도 여전히 일일 업데이트를 구독하라는 메시지가 표시됩니다. 사용자가 다시 구독해야 한다고 생각하지 않도록 하려면 어떻게 해야 할까요?

conv 객체의 인수에는 사용자가 대화를 시작한 위치에 관한 정보가 포함되어 있습니다. conv 인수에 UPDATES 섹션이 포함되어 있는지 확인합니다. 이 섹션은 사용자가 일일 업데이트 알림에서 대화를 시작했음을 나타내고 적절하게 응답을 변경할 수 있습니다. 이 대화 브랜치를 사용하여 클래스 목록을 제공한 직후 대화상자를 닫을 수 있습니다. 이는 일일 업데이트를 짧게 유지하는 권장사항을 따릅니다.

b2f84ff91b0e1396.png index.js 파일에서 다음 코드를 바꿉니다.

index.js

// Class list intent handler
app.intent('Class List', (conv, {day}) => {
  if (!day) {
    day = DAYS[new Date().getDay()];
  }
  const classes =
  [...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
  .join(', ');
  const classesMessage =
  `On ${day} we offer the following classes: ${classes}. ` +
  `Can I help you with anything else?`;
  conv.ask(classesMessage);
  if (conv.screen) {
    conv.ask(new Suggestions([Suggestion.HOURS]));
  }
});

다음과 같이 바꿉니다.

index.js

// Class list intent handler
app.intent('Class List', (conv, {day}) => {
  if (!day) {
    day = DAYS[new Date().getDay()];
  }
  const classes =
  [...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
  .join(', ');
  let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
  // If the user started the conversation from the context of a daily update,
  // the conv's arguments will contain an 'UPDATES' section.
  let engagement = conv.arguments.get('UPDATES');
  // Check the conv arguments to tailor the conversation based on the context.
  if (engagement) {
    classesMessage += `Hope to see you soon at Action Gym!`;
    conv.close(classesMessage);
  } else {
    classesMessage += `Would you like me to send you daily reminders of upcoming classes, or can I help you with anything else?`;
    conv.ask(classesMessage);
    if (conv.screen) {
      conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.HOURS]));
    };
  };
});

일일 업데이트 테스트하기

터미널에서 다음 명령어를 실행하여 업데이트된 웹훅 코드를 Firebase에 배포합니다.

firebase deploy

작업 시뮬레이터에서 맞춤 재프롬프트를 테스트하려면 다음 단계를 따르세요.

  1. Actions 콘솔에서 Test로 이동합니다.
  2. 입력 필드에 Talk to my test app를 입력하고 Enter 키를 누릅니다.
  3. Learn about classes을 입력하고 Enter 키를 누릅니다. 이제 작업의 응답에서 일일 알림을 보내도록 제안할 것입니다.
  4. Send daily reminders을 입력하고 Enter 키를 누릅니다.
  5. 업데이트를 확인할 시간을 입력하고 Enter 키를 누릅니다. 테스트를 위해 현재 시간보다 3~5분 늦게 응답해 보세요.

83a15ecac8c71787.png

지정한 시간 즈음에 휴대기기에서 어시스턴트의 알림을 받게 됩니다. 이 알림이 표시되는 데 몇 분 정도 걸릴 수 있습니다. 알림을 탭하면 어시스턴트의 Class List 인텐트로 직접 딥 링크되어 예정된 수업 목록을 확인할 수 있습니다.

8582482eafc67d5b.png

4. 푸시 알림 추가

작업 외부에서 사용자의 참여를 유도하는 또 다른 옵션으로 Actions API를 호출하여 사용자에게 푸시 알림을 보낼 수 있습니다. 일일 업데이트와 달리 이러한 알림은 어시스턴트가 자동으로 예약하지 않으므로 원할 때 보낼 수 있습니다.

이 단계에서는 새 Class Canceled 인텐트를 추가하고 사용자에게 클래스 취소를 알리는 알림을 전송하여 작업에서 푸시 알림을 구현하는 방법을 알아봅니다. 또한 알림을 보내는 데 필요한 다음 세 가지 구성요소를 설정합니다.

  • Actions API 계정 - API에 POST 요청을 전송하여 사용자에게 알림을 전송하므로 이 API와 상호작용하려면 서비스 계정과 사용자 인증 정보를 설정해야 합니다.
  • 권한 도우미 - 사용자에게 푸시 알림을 보내는 데 필요한 사용자 ID에 액세스하려면 사용자의 권한이 필요합니다. 이 예에서는 클라이언트 라이브러리 함수를 사용하여 권한 도우미를 호출하고 이 ID를 요청합니다.
  • 저장공간 - 대화와 관계없이 사용자에게 푸시 알림을 보내려면 언제든지 리콜할 수 있는 위치에 사용자 ID를 저장해야 합니다. 이 예시에서는 각 사용자의 정보를 저장하도록 Firestore 데이터베이스를 설정합니다.

이 안내를 따른 후 작업의 대화에 다음 대화상자를 추가합니다.

7c9d4b633c547823.png

어떻게 사용자의 참여를 유도할까요?

스마트폰 사용자는 앱별 정보와 업데이트를 제공하는 푸시 알림에 익숙할 것입니다. 푸시 알림은 사용자에게 알림을 사용 설정할 적절한 이유가 있는 경우 어시스턴트 외부의 휴대기기 사용자에게 유연하게 액세스할 수 있는 방법입니다. 일일 업데이트를 통해 사용자는 매일 알림이 전송된다는 사실을 이미 알고 있습니다. 하지만 푸시 알림에서는 사용자가 간헐적인 알림을 받도록 선택했는지 또는 하루에 여러 개의 알림을 받도록 선택했는지 알 수 없습니다.

푸시 알림은 유용한 참여 도구이지만 모든 작업에 반드시 통합되어야 하는 것은 아닙니다. 작업에 푸시 알림을 추가할지 결정할 때 다음 팁을 고려하세요.

  • 푸시 알림의 예시 일정을 계획하세요. 푸시 알림을 하루에 한 번만 전송할 계획이라면 일일 업데이트를 사용하는 것이 좋습니다.
  • 푸시 알림을 받을 때마다 유용한 정보를 제공해야 합니다. 알림은 작업의 인텐트 중 하나에 딥 링크될 수도 있으므로 인텐트가 유용하고 관련성이 있어야 합니다.
  • 사용자에게 푸시 알림 구독을 요청할 때는 이 사실을 명확히 밝혀야 합니다. 각 푸시 알림의 내용을 이해하고 알림 전송 빈도도 어느 정도 알고 있어야 합니다.

Actions API 사용 설정

  1. Google Cloud 콘솔을 열고 드롭다운에서 작업 프로젝트 이름을 선택합니다.

d015c1515b99e3db.png

  1. 탐색 메뉴 (☰)에서 API 및 서비스 > 라이브러리.
  2. Actions API를 검색하고 사용 설정을 클릭합니다.

6d464f49c88e70b4.png

서비스 계정 만들기

Actions API에는 인증이 필요하므로 요청을 보내려면 서비스 계정을 만들어야 합니다. Actions API용 서비스 계정 키를 만들고 설치하려면 다음 단계를 따르세요.

  1. Google Cloud 콘솔의 탐색 메뉴(☰)에서 API 및 서비스 > 사용자 인증 정보.
  2. 사용자 인증 정보 만들기 > 서비스 계정 키를 입력합니다.
  3. 서비스 계정 드롭다운 메뉴에서 새 서비스 계정을 선택합니다.
  4. 다음 정보를 입력합니다.
  • 서비스 계정 이름: service-account
  • 역할: 프로젝트 > 담당자
  • 서비스 계정 ID: service-account (항상 뒤에 @<project_id>.iam.gserviceaccount.com이 표시됨)
  • 키 유형: JSON
  1. 만들기를 클릭합니다.
  2. 다운로드한 JSON 파일을 프로젝트의 /user-engagement-codelab/start/functions/ 디렉터리로 이동합니다.
  3. JSON 파일 이름을 service-account.json로 바꿉니다.

d9bd79d35691de3a.png

Firestore 사용 설정

대화 외부에서 알림을 보내려면 알림 코드에서 참조할 수 있는 사용자 ID를 저장할 방법이 필요합니다. 이 예시에서는 Firestore 데이터베이스를 사용하여 구독한 사용자의 사용자 ID를 저장합니다.

다음 단계에 따라 작업의 Firestore 데이터베이스를 만듭니다.

  1. Firebase Console에서 작업 프로젝트 이름을 선택합니다.
  2. 왼쪽 탐색 메뉴에서 개발 > 데이터베이스를 선택하고 데이터베이스 만들기를 클릭합니다.
  3. 테스트 모드에서 시작을 선택합니다.
  4. 사용 설정을 클릭합니다.

6dfc386413954caa.png

Dialogflow 설정

Dialogflow 콘솔에서 다음 단계에 따라 푸시 알림 수신 동의 흐름을 만듭니다.

사용자에게 구독하라는 메시지 표시

  1. 취소된 클래스의 푸시 알림 구독을 요청하는 사용자를 처리할 새 인텐트를 설정합니다. Dialogflow 콘솔에서 왼쪽 탐색 메뉴의 인텐트 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
  2. 이 새 인텐트의 이름을 Setup Push Notifications로 지정합니다.
  3. 학습 문구 섹션에서 다음 사용자 표현을 추가합니다.
  • Subscribe to notifications
  • Send notification
  • Notify me
  • Send class notifications
  • Cancelled notifications
  1. fulfillment 섹션에서 이 인텐트에 웹훅 호출 사용 설정 옵션을 전환합니다.
  2. 페이지 상단의 저장을 클릭합니다.

3d99bc41d0492552.png

사용자 결정 처리

  1. 푸시 알림 구독 메시지에 대한 사용자의 응답을 처리할 새 인텐트를 설정합니다. 왼쪽 탐색 메뉴에서 Intents 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
  2. 이 새 인텐트의 이름을 Confirm Push Notifications로 지정합니다.
  3. 이벤트 섹션 아래에 actions_intent_PERMISSION를 추가합니다. 이 Dialogflow 이벤트는 구독 여부에 관계없이 사용자가 푸시 알림 구독 흐름을 완료하면 트리거됩니다.
  4. fulfillment 섹션에서 이 인텐트에 웹훅 호출 사용 설정 옵션을 전환합니다.
  5. 페이지 상단의 저장을 클릭합니다.

d37f550c5e07cb73.png

푸시 알림 처리

푸시 알림을 특정 인텐트에 연결할 수 있으므로 푸시 알림을 탭하는 사용자가 작업의 해당 인텐트로 직접 딥 링크됩니다. 이 예시에서는 취소된 클래스에 대한 세부정보를 제공하는 푸시 알림용 새 인텐트를 추가합니다.

다음 단계를 따라 사용자가 푸시 알림을 탭할 때 트리거할 인텐트를 추가하세요.

  1. Dialogflow 콘솔에서 왼쪽 탐색 메뉴의 인텐트 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
  2. 이 새 인텐트의 이름을 Class Canceled로 지정합니다.
  3. 학습 문구 섹션에서 Cancelations사용자 표현으로 추가합니다.
  4. fulfillment 섹션에서 이 인텐트에 웹훅 호출 사용 설정 옵션을 전환합니다.
  5. 페이지 상단의 저장을 클릭합니다.

940379556f559631.png

대화 중에 테스트 알림 보내기

프로덕션에는 푸시 알림을 보내는 작업 처리 코드와 별도의 스크립트가 있어야 합니다. 이 예에서는 작업과 대화하는 동안 푸시 알림을 보내도록 호출할 수 있는 인텐트를 만듭니다. 이 인텐트는 디버그 목적으로만 사용됩니다. 실제로 푸시 알림은 처리에 의해 처리되거나 작업의 대화의 일부로 트리거되어서는 안 됩니다.

푸시 알림을 테스트하기 위한 인텐트를 만들려면 다음 단계를 따르세요.

  1. 테스트 및 디버깅을 위해 구독 중인 사용자에게 푸시 알림을 보낼 수 있는 새 인텐트를 설정합니다. Dialogflow 콘솔에서 왼쪽 탐색 메뉴의 인텐트 옆에 있는 + 버튼을 클릭하여 새 인텐트를 만듭니다.
  2. 이 새 인텐트의 이름을 Test Notification로 지정합니다.
  3. 학습 문구 섹션에서 Test notification사용자 표현으로 추가합니다.
  4. fulfillment 섹션에서 이 인텐트에 웹훅 호출 사용 설정 옵션을 전환합니다.
  5. 페이지 상단의 저장을 클릭합니다.

6967f5a997643eb8.png

푸시 알림 사용

Class Canceled 인텐트에 대한 푸시 알림을 사용 설정하려면 다음 단계를 따르세요.

  1. Dialogflow 콘솔에서 탐색 메뉴의 통합으로 이동합니다.
  2. Google 어시스턴트 카드에서 통합 설정을 클릭합니다.
  3. Class Canceled암시적 호출 인텐트로 추가합니다. 이 단계는 Dialogflow에서 사용자가 푸시 알림을 탭하여 Class Canceled 인텐트와 대화를 시작할 수 있음을 인식하는 데 필요합니다.
  4. 닫기를 클릭합니다.

1ac725231ed279a1.png

  1. Actions 콘솔에서 개발 탭을 클릭하고 왼쪽 탐색 메뉴에서 작업을 선택합니다.
  2. 작업 목록에서 수업 취소됨을 클릭합니다.
  3. 사용자 참여 발생 시간 섹션에서 푸시 알림을 보내시겠습니까? 옵션을 전환합니다.
  4. 푸시 알림을 설명하는 구체적인 콘텐츠 제목을 설정합니다. '<콘텐츠 제목>에 관한 푸시 알림을 보내도 괜찮을까요?'가 컨텍스트이므로 제목을 소리내어 말할 때 구체적이고 소리가 정확해야 합니다. 이 예에서는 콘텐츠 제목class cancelations로 설정합니다.
  5. 페이지 상단의 저장을 클릭합니다.

4304c7cd575f6de3.png

처리 구현

웹훅에서 처리를 구현하려면 다음 단계를 완료하세요.

종속 항목 로드

b2f84ff91b0e1396.png index.js 파일에서 require() 함수를 업데이트하여 actions-on-google 패키지의 UpdatePermission 패키지를 추가합니다. 그러면 가져오기가 다음과 같이 표시됩니다.

index.js

const {
  dialogflow,
  Suggestions,
  RegisterUpdate,
  UpdatePermission,
} = require('actions-on-google');

추천 칩 업데이트

b2f84ff91b0e1396.png index.js 파일에서 NOTIFICATIONS 항목을 추천 검색어 칩 제목 목록에 추가합니다. 그러면 Suggestion 정의가 다음과 같이 표시됩니다.

index.js

// Suggestion chip titles
const Suggestion = {
  HOURS: 'Ask about hours',
  CLASSES: 'Learn about classes',
  DAILY: 'Send daily reminders',
  NOTIFICATIONS: 'Get notifications',
};

새 가져오기 설정하기

Firestore 데이터베이스에 연결하려면 firebase-admin 패키지를 추가하고 데이터베이스에 저장된 필드의 상수를 추가합니다. 또한 google-auth-libraryrequest 패키지를 가져와 Actions API에 대한 인증과 요청을 처리합니다.

b2f84ff91b0e1396.png index.js 파일에서 가져오기에 다음 코드를 추가합니다.

index.js

// Firebase admin import
const admin = require('firebase-admin');

// Initialize Firestore
admin.initializeApp();
const db = admin.firestore();

// Firestore constants
const FirestoreNames = {
 INTENT: 'intent',
 USER_ID: 'userId',
 USERS: 'users',
};

// Actions API authentication imports
const {auth} = require('google-auth-library');
const request = require('request');

수업 취소 알림 설정 제안

b2f84ff91b0e1396.png index.js 파일에서 다음 코드를 바꿉니다.

index.js

// Class list intent handler
app.intent('Class List', (conv, {day}) => {
  if (!day) {
    day = DAYS[new Date().getDay()];
  }
  const classes =
  [...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
  .join(', ');
  let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
  // If the user started the conversation from the context of a daily update,
  // the conv's arguments will contain an 'UPDATES' section.
  let engagement = conv.arguments.get('UPDATES');
  // Check the conv arguments to tailor the conversation based on the context.
  if (engagement) {
    classesMessage += `Hope to see you soon at Action Gym!`;
    conv.close(classesMessage);
  } else {
    classesMessage += `Would you like me to send you daily reminders of upcoming classes, or can I help you with anything else?`;
    conv.ask(classesMessage);
    if (conv.screen) {
      conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.HOURS]));
    };
  };
});

다음과 같이 바꿉니다.

index.js

// Class list intent handler
app.intent('Class List', (conv, {day}) => {
  if (!day) {
    day = DAYS[new Date().getDay()];
  }
  const classes =
  [...new Set(schedule.days[day].map((d) => `${d.name} at ${d.startTime}`))]
  .join(', ');
  let classesMessage = `On ${day} we offer the following classes: ${classes}. `;
  // If the user started the conversation from the context of a daily update,
  // the conv's arguments will contain an 'UPDATES' section.
  let engagement = conv.arguments.get('UPDATES');
  // Check the conv arguments to tailor the conversation based on the context.
  if (engagement) {
    classesMessage += `Hope to see you soon at Action Gym!`;
    conv.close(classesMessage);
  } else {
    classesMessage += `Would you like to receive daily reminders of upcoming classes, subscribe to notifications about cancelations, or can I help you with anything else?`;
    conv.ask(classesMessage);
    if (conv.screen) {
      conv.ask(new Suggestions([Suggestion.DAILY, Suggestion.NOTIFICATIONS,
Suggestion.HOURS]));
    };
  };
});

새 인텐트의 fulfillment 추가

사용자가 푸시 알림을 구독하고 싶다고 하면 UpdatePermission 도우미를 호출하여 사용자에게 권한을 요청합니다. 성공하면 PERMISSION 인수가 conv 객체의 인수에 추가되고, 이를 통해 대화를 피봇팅할 수 있습니다.

사용자의 권한을 확보하면 conv 객체의 인수에서 사용자 ID를 가져와 데이터베이스에 저장합니다. 나중에 이 사용자 ID를 Actions API로 전송합니다. 이를 통해 어시스턴트가 알림을 수신할 사람을 결정합니다.

마지막으로 푸시 알림을 탭하여 트리거되는 Class Canceled 인텐트에 fulfillment를 추가합니다. 이 예에서 응답은 자리표시자 문자열이지만 이 Action의 프로덕션 지원 버전에서는 알림 스크립트가 어떤 클래스가 취소되었는지에 관한 보다 동적인 정보를 제공합니다.

b2f84ff91b0e1396.png index.js 파일에 다음 코드를 추가합니다.

index.js

// Call the User Information helper for permission to send push notifications
app.intent('Setup Push Notifications', (conv) => {
 conv.ask('Update permission for setting up push notifications');
 conv.ask(new UpdatePermission({intent: 'Class Canceled'}));
});

// Handle opt-in or rejection of push notifications
app.intent('Confirm Push Notifications', (conv) => {
 if (conv.arguments.get('PERMISSION')) {
   let userId = conv.arguments.get('UPDATES_USER_ID');
   if (!userId) {
     userId = conv.request.conversation.conversationId;
   }
   // Add the current conversation ID and the notification's
   // target intent to the Firestore database.
   return db.collection(FirestoreNames.USERS)
   .add({
     [FirestoreNames.INTENT]: 'Class Canceled',
     [FirestoreNames.USER_ID]: userId,
   })
   .then(() => {
     conv.ask(`Great, I'll notify you whenever there's a class cancelation. ` +
     'Can I help you with anything else?');
   });
 } else {
   conv.ask(`Okay, I won't send you notifications about class cancelations. ` +
     'Can I help you with anything else?');
 }
 if (conv.screen) {
    conv.ask(new Suggestions([Suggestion.CLASSES, Suggestion.HOURS]));
  }
});

// Intent triggered by tapping the push notification
app.intent('Class Canceled', (conv) => {
 conv.ask('Classname at classtime has been canceled.');
});

테스트 알림 추가

사용자에게 푸시 알림을 보내려면 사용자 ID, 알림의 제목, 타겟 인텐트와 함께 POST 요청을 Actions API에 전송합니다. 이 예시에서 테스트 알림 인텐트를 트리거하면 Firestore 데이터베이스를 반복하여 알림을 구독하는 모든 사용자에게 푸시 알림이 전송됩니다.

이 예시에서는 웹훅 처리에 푸시 알림을 전송하는 코드를 포함하고 대화에서 테스트 인텐트를 호출하여 이 코드를 트리거합니다. 게시하려는 작업의 경우 푸시 알림 코드가 처리와 별도의 스크립트에 있어야 합니다.

b2f84ff91b0e1396.png index.js 파일에 다음 코드를 추가합니다.

index.js

// Debug intent to trigger a test push notification
app.intent('Test Notification', (conv) => {
 // Use the Actions API to send a Google Assistant push notification.
 let client = auth.fromJSON(require('./service-account.json'));
 client.scopes = ['https://www.googleapis.com/auth/actions.fulfillment.conversation'];
 let notification = {
   userNotification: {
     title: 'Test Notification from Action Gym',
   },
   target: {},
 };
 client.authorize((err, tokens) => {
   if (err) {
     throw new Error(`Auth error: ${err}`);
   }
   // Iterate through Firestore and send push notifications to every user
   // who's currently opted in to canceled class notifications.
   db.collection(FirestoreNames.USERS)
       .where(FirestoreNames.INTENT, '==', 'Class Canceled')
       .get()
       .then((querySnapshot) => {
         querySnapshot.forEach((user) => {
           notification.target = {
             userId: user.get(FirestoreNames.USER_ID),
             intent: user.get(FirestoreNames.INTENT),
           };
           request.post('https://actions.googleapis.com/v2/conversations:send', {
             'auth': {
               'bearer': tokens.access_token,
             },
             'json': true,
             'body': {'customPushMessage': notification, 'isInSandbox': true},
           }, (err, httpResponse, body) => {
             if (err) {
               throw new Error(`API request error: ${err}`);
             }
             console.log(`${httpResponse.statusCode}: ` +
               `${httpResponse.statusMessage}`);
             console.log(JSON.stringify(body));
           });
         });
       })
       .catch((error) => {
         throw new Error(`Firestore query error: ${error}`);
       });
 });
 conv.ask('A notification has been sent to all subscribed users.');
});

푸시 알림 테스트

터미널에서 다음 명령어를 실행하여 업데이트된 웹훅 코드를 Firebase에 배포합니다.

firebase deploy

작업 시뮬레이터에서 알림을 테스트하려면 다음 단계를 따르세요.

  1. Actions 콘솔에서 Test 탭으로 이동합니다.
  2. 입력 필드에 Talk to my test app를 입력하고 Enter 키를 누릅니다.
  3. Learn about classes을 입력하고 Enter 키를 누릅니다.
  4. Get notifications을 입력하고 Enter 키를 누릅니다.
  5. 푸시 알림을 보내기 위한 작업 권한을 아직 부여하지 않았다면 yes을 입력하고 Enter 키를 누릅니다.
  6. yes을 입력하고 Enter 키를 누릅니다. 이제 Google 계정에서 이 작업에 대한 푸시 알림을 구독하게 됩니다.

3a8704bdc0bcbb17.png

  1. no를 입력하고 Enter 키를 눌러 종료합니다.
  2. Talk to my test app을(를) 입력하고 Enter 키를 눌러 새 대화를 시작하세요.
  3. Test notification을 입력하고 Enter 키를 누릅니다.

634dfcb0be8dfdec.png

몇 분 안에 'Action Gym에서 테스트 알림'을 받게 됩니다. 휴대기기의 어시스턴트 푸시 알림 이 알림을 탭하면 작업의 Class Canceled 인텐트로 연결되는 딥 링크가 표시됩니다.

33cbde513c10122e.png

5. 어시스턴트 링크 만들기

지금까지 사용자가 내 작업을 계속 찾게 하기 위해 구현할 수 있는 참여 기능을 살펴보았습니다. 그러나 이러한 기능은 사용자가 내 작업을 발견하고 사용하는 것을 전제로 합니다.

휴대기기 사용자를 어시스턴트의 작업으로 바로 연결하는 어시스턴트 링크를 만들 수 있습니다. 어시스턴트 링크는 표준 하이퍼링크이므로 웹사이트나 블로그나 소셜 미디어 게시물과 같은 웹 마케팅 자료에 추가할 수 있습니다.

이 단계에서는 어시스턴트 링크가 무엇인지, 작업의 환영 인텐트를 위한 링크를 만드는 방법, 테스트를 위해 간단한 웹사이트에 추가하는 방법을 알아봅니다.

어떻게 사용자의 참여를 유도할까요?

사용자를 처음으로 작업에 끌어들이는 것은 어려울 수 있습니다. 특히 사용자가 어시스턴트에서 작업을 명시적으로 호출해야 하는 경우에는 더욱 그렇습니다. 어시스턴트 링크는 사용자에게 작업으로 직접 연결되는 링크를 제공하여 이러한 불편을 줄여줍니다. 사용자가 어시스턴트 지원 기기에서 어시스턴트 링크를 따라가면 작업으로 바로 이동합니다. 사용자가 휴대기기가 아닌 기기 또는 어시스턴트를 지원하지 않는 다른 기기에서 링크를 여는 경우에도 작업 디렉터리 등록정보 (게시된 경우)로 이동하므로 링크를 통해 여전히 작업을 사용자에게 홍보할 수 있습니다.

어시스턴트 링크는 유용한 참여 도구이므로 웹사이트나 소셜 미디어를 통해 액션을 광고할 계획이라면 어시스턴트 링크를 만드는 것이 좋습니다. 어시스턴트 링크를 만들고 배포하기 전에 다음 도움말을 숙지하시기 바랍니다.

  • 어시스턴트 링크는 작업이 게시되어야만 작동합니다. 프로젝트가 초안 상태인 동안에는 링크가 내 기기에서만 작동합니다. 다른 사용자는 작업 디렉토리의 404 페이지로 이동합니다.
  • 알파 또는 베타 환경에서 작업을 출시하여 게시 전에 사용자가 어시스턴트 링크를 테스트하도록 할 수 있습니다. 알파 또는 베타에 참여하는 사용자만 어시스턴트 링크를 테스트할 수 있습니다.
  • 어시스턴트 링크의 도착 페이지 인텐트가 신규 사용자에게 좋은 첫인상을 주는지 확인하세요. 환영 인텐트는 이미 작업을 소개하는 데 효과적이므로 어시스턴트 링크의 기본 대상이 됩니다.

다음 단계에 따라 환영 인텐트의 어시스턴트 링크를 만듭니다.

  1. Actions 콘솔에서 개발 탭을 클릭하고 왼쪽 탐색 메뉴에서 작업을 선택합니다.
  2. 작업 목록에서 actions.intent.MAIN을 클릭합니다.
  3. 링크 섹션에서 이 작업에 URL을 사용 설정하시겠습니까 옵션을 전환합니다.
  4. 작업을 설명하는 구체적인 링크 제목을 설정합니다. 사용자가 작업으로 할 수 있는 작업을 설명하는 간단한 동사-명사 쌍으로 제목을 만듭니다. 이 예에서는 링크 제목learn about Action Gym로 설정합니다.
  5. 이 페이지 하단에서 HTML 스니펫을 복사한 후 저장하여 나중을 위해 저장하세요.
  6. 페이지 상단의 저장을 클릭합니다.

55341b8102b71eab.png

테스트 웹사이트 배포

어시스턴트 링크를 테스트하려면 Firebase 도구를 사용하여 처리와 함께 테스트 웹사이트를 배포하면 됩니다. 이 예시에 관한 간단한 테스트 웹사이트는 이미 만들었으므로 어시스턴트 링크만 추가하면 됩니다.

처리의 /user-engagement-codelab-nodejs/start/public/ 디렉터리로 이동하여 텍스트 편집기에서 index.html 파일을 엽니다.

b2f84ff91b0e1396.png index.html 파일에서 어시스턴트 링크의 HTML 스니펫을 본문 요소에 붙여넣습니다. 파일은 아래의 스니펫과 같이 표시됩니다.

index.html

<body>
    <p>
     <a href="https://assistant.google.com/services/invoke/uid/000000efb5f2fd97">🅖 Ask my test app to learn about Action Gym
     </a>
    </p>
</body>

터미널에서 다음 명령어를 실행하여 테스트 웹사이트를 Firebase에 배포합니다.

firebase deploy

배포 명령어 실행이 완료되면 출력의 호스팅 URL을 기록해 둡니다.

b01e8d322fb5d623.png

휴대기기의 웹브라우저에서 이 URL로 이동하면 테스트 웹사이트에 어시스턴트 링크가 표시됩니다. 휴대기기에서 이 링크를 클릭하면 어시스턴트의 작업의 환영 인텐트로 이동합니다.

599845d647f5b624.png

데스크톱 브라우저에서 호스팅 URL로 이동하면 작업이 게시되지 않으므로 어시스턴트 디렉터리의 404 페이지로 이동해도 됩니다.

6. 다음 단계

수고하셨습니다.

지금까지 작업 개발 시 사용자 참여의 중요성, 플랫폼에서 사용할 수 있는 사용자 참여 기능, 각 기능을 작업에 추가하는 방법을 알아보았습니다.

추가 학습 자료

다음 리소스를 살펴보고 작업의 사용자 참여에 관해 자세히 알아보세요.

Twitter에서 @ActionsOnGoogle을 팔로우하여 최신 소식을 확인하고 #AoGDevs로 트윗을 보내 내가 빌드한 결과물을 공유하세요.

의견 설문조사

상담을 종료하기 전에 이 양식을 작성하여 파트너님의 의견을 보내주세요.