マンガでわかるLINE Clova開発 第4話 Azure Functionsでバックエンドを作ろう

プログラミング
LINEのスマートスピーカー「LINE Clova」スキル開発 第4話では、Microsoft のサーバーレスのサービス Azure Functions(アジュール ファンクションズ)を使ってバックエンドを作っていきます!
マンガでわかるLINE Clova開発 第4話 Azure Functionsでバックエンドを作ろう
前回のお話(第3話)では、話しかけると今日の運勢を教えてくれる「占いスキル」の対話モデルを作りました。今回はMicrosoft のサーバーレスのサービス Azure Functions(アジュール ファンクションズ)を使って、バックエンドを作っていきます!

(アイキャッチイラスト・マンガ・解説:湊川あい)

※「サーバーレスって何?」「Azure Functionsって何?」という方は、マンガでわかるLINE Clova開発 第1話を読んでみてね!

開発環境を用意しよう

ちょまどさん
まずはこれらのツールをインストールしてね!

Windowsの場合

Azure Functions Core Tools は、Node.js までインストールした後、次のコマンドでインストールできます。

terminal
 $ npm install -g azure-functions-core-tools

macOSの場合

Azure Functions Core Tools は、Homebrew までインストールした後、次のコマンドでインストールできます。

terminal
 $ brew tap azure/functions
 $ brew install azure-functions-core-tools

Visual Studio Code の設定をしよう

ちょまどさん
Visual Studio Codeを開いて、次の拡張機能をインストールしてね!
  • C#
  • Azure Functions
わかば
おおっ! 今回、プログラミング言語はC#を使うんですか?
ちょまどさん
うん、そうだよ! どの言語を使った解説が見たいかTwitterでアンケートしてみたら、C#に最も票が集まったからね

ちょまどさん
2019年1月 記事執筆現在、Azure Functionsでフルサポートしている言語は、C#、JavaScript、F#の3種類だよ。TypeScriptも、JavaScriptへトランスパイルすることで使えるよ。ちなみにJavaやPythonはプレビュー版が使えるんだ!

Azure Functionsでサポートされている言語について、詳しくはこちら:
Azure Functions でサポートされている言語 | Microsoft Docs

Visual Studio Codeに、拡張機能 C#を追加

ちょまどさん
これで、C#でコーディングしやすくなったよ。この拡張機能を入れることで、C#のコードを補完してくれたり、使われていない変数があるときに自動で注意してくれたりするようになるよ!

Visual Studio Codeに、拡張機能 Azure Functionsを追加

ちょまどさん
Azure Functionsの拡張機能を追加することによって、プロジェクトや関数を簡単に生成できるようになったり、Azureに直接デプロイできるようになったりするんだ!

【コラム】Visual Studio Codeのおすすめ拡張機能

わかば
Microsoftの中の人の @okazukiさん に、特にお気に入りの拡張機能を聞いてみたよ!
  • Paste Image
    Ctrl+Alt+V (Cmd+Alt+V) でMarkdownにクリップボードから画像を貼り付けることができる拡張機能。Markdown書くのが捗ります。
  • VS Live Share公式紹介サイト
    複数人とコード共有して作業できるようになる拡張機能です。
  • VS Live Share Extension Pack
    Live Share するときに、チャットやボイスチャットができるようになる拡張機能です。
  • EditorConfig for VS Code
    EditorConfig のVisual Studio Code用の拡張機能です。チームでコーディングスタイルを共有するのに役立ちます。
  • GitLens
    Git のリポジトリのブランチやリモートや履歴などを確認するのに便利です。
  • GitHub Pull Requests
    2019年1月22日時点でプレビューですがVisual Studio CodeからGitHubのプルリクエストを見たり編集したり作成したりできてすごく便利です。
わかば
拡張機能は他にもいろいろあるから、みんなのお気に入りも見つけてみてね!

コードを書こう

1. 新規プロジェクトを作ろう

▼作業用のフォルダを作り、Visual Studio Codeで開きます。画面左にあるAzureのアイコンをクリックします。 Sign in to AzureをクリックしてAzureにログインします。
(画面左のアイコンが見当たらない場合は、Visual Studio Codeを再起動してみてください)

▼ブラウザが開くので、Azureに登録済みの自分のメールアドレスを入力します。このような画面になればログイン完了です。

▼FunctionsのCreate New Project... (フォルダのアイコン)をクリックします。

▼今開いている作業用のフォルダを選択します

▼続いて、使う言語を選びます。今回はC#を選択します。

▼以上で、新規プロジェクトができました。先ほど選択したフォルダの中身を見てみましょう。

わかば
すごい! 新規プロジェクトを作っただけで、アプリケーションを作るのに必要なファイルたちが一気に用意された!
わかば
Azure functionsの拡張機能には、他にもアイコンが並んでるけど、これは何だろう?

ちょまどさん
左から順に「プロジェクトを作る」「関数を作る」「デプロイする」機能だよ。この順で作れば、サーバーレスで動くアプリケーションをひとつ作れるというワケ!
わかば
へぇ~!シンプルでわかりやすいですね!今はプロジェクトを作ったから、次はその隣の関数を作ればいいんですね!

2. 関数を作ろう

プロジェクトができたので、続いて関数を作成していきます。

▼Create Function (稲妻のアイコン)をクリックします。

▼先ほど作成したプロジェクトのフォルダを選択します。

▼HttpTrigger を選択します。

▼関数名を入力します。今回はClovaとしました。

▼関数の名前空間を入力します。今回はMangaClovaとしました。

▼認証方法はFunctionを選択します。

▼数秒後、Clova.cs が作成されます!

わかば
びっくり!C#のソースコードが自動生成されました!
ちょまどさん
すごいでしょ!このソースコードをベースにして、必要な処理を書き加えていくよ!

3. ライブラリを追加しよう

コードの編集に入る前に、Clova の Extension(スキル)を作るための CEK.CSharp というライブラリを追加しておきましょう。
C# のライブラリは NuGet でホストされています。
ライブラリを追加するにはdotnet add package コマンドを使います。

Visual Studio Code のターミナルを開いて、次のコマンドを入力しましょう。

terminal
 $ dotnet add package CEK.CSharp

※ Visual Studio Code上のターミナルの開き方
上部メニューの View > Terminal から開けます。

試しにビルドしてみましょう。
Ctrl + Shift + B でビルドします。(macOSの場合は ⌘ + Shift + B)

「ビルドに成功しました」と表示され、エラーが出ないことを確認します。

4. Clova.cs の中のRunメソッドを書こう

Clova.csの中のRunメソッドを書いていきます。

元々のコード

C#
 using System;
 using System.IO;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Azure.WebJobs;
 using Microsoft.Azure.WebJobs.Extensions.Http;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;

 namespace MangaClova
 {
     public static class Clova
     {
         [FunctionName("Clova")]
         public static async Task Run(
             [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
             ILogger log)
         {
            // ここに実行したい処理を書く
         }
     }
 }
ちょまどさん
名前空間の追加や各種補間機能を使って書くと、快適にコーディングできるよ!

▼例:まだ using namespace していないクラスを使うとき
(JavaScript でいうところの、importしていないクラスを使うとき)

① クラス名を打つ
Ctrl + . を入力
using namespace を追加する選択肢が出るので選択
・・・(この例では、先ほど追加したライブラリ CEK.CSharp が候補に表示されている)
④ コード上部に using namespace; が追加される
・・・(この例では、using CEK.CSharp;

わかば
わぁ~っ!これは便利ですね!

何が来ても「こんにちは」を返す関数

ちょまどさん
まずは、どんなリクエストが飛んできても「こんにちは」を返す関数を書こう
C#
 using System;
 using System.IO;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Azure.WebJobs;
 using Microsoft.Azure.WebJobs.Extensions.Http;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
 using CEK.CSharp;
 using CEK.CSharp.Models;

 namespace MangaClova
 {
     public static class Clova
     {
         [FunctionName("Clova")]
         public static async Task Run(
             [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
             ILogger log)
         {
             // リクエストのボディの JSON を検証して C# のクラスに変換。
             var clovaClient = new ClovaClient();
             var clovaRequest = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);

             // 返事を作成
             var clovaResponse = new CEKResponse();
             clovaResponse.AddText("こんにちは。");

             // レスポンスとして作成した返事の内容を返す
             return new OkObjectResult(clovaResponse);
         }
     }
 }

5. デバッグを実行

コードを実行してみましょう。
画面左のメニューからデバッグを選択し、緑の三角形をクリックして実行します。

6. ngrokを使ってインターネットからアクセスできるようにしよう

ngrok を使ってインターネットからアクセスできるようにします。VSCode のターミナルで新しいターミナルを開いて、次のコマンドを実行します。

terminal
 $ ngrok http 7071

ngrok: command not found になった場合・・・ローカルでngrokを参照できていない可能性があります。たとえばngrokをアプリケーションフォルダに保存した場合は $ cd /Applications してから $ ./ngrok http 7071 してみてください。

成功すると、ターミナル上にこのように表示されます。

https://b71XXXXX.ngrok.ioというURLがあるはずです。今からこのURLをClova Extension Kitに登録します。

ブラウザで Clova Extension Kit を開きましょう。スキルの基本情報 > 修正 > サーバ―設定 の、WebhookのURLを入れるところに ngrokで表示されたURL + /api/Clovaを入力します。

例:https://b71XXXXX.ngrok.io/api/Clova

では、Clova Extension Kitの対話モデルのテスト機能で話しかけてみましょう。 何を話しかけても「こんにちは。」と返ってくるはずです。

▼テストしてみた様子

わかば
ほんとだ!ちゃんと「こんにちは。」って返ってきますよ!
ちょまどさん
素晴らしい!
わかば
ここから占いの結果を返すようにするには、コードをどう書き換えればいいのかなぁ……?

◆おみくじ機能を追加しよう

ちょまどさん
じゃあ、さっきのコードにおみくじ機能を追加しよう!
C#
 using System;
 using System.IO;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Azure.WebJobs;
 using Microsoft.Azure.WebJobs.Extensions.Http;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
 using CEK.CSharp;
 using CEK.CSharp.Models;

 namespace MangaClova
 {
     public static class Clova
     {
         [FunctionName("Clova")]
         public static async Task Run(
             [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
             ILogger log)
         {
             // リクエストのボディの JSON を検証して C# のクラスに変換。
             var clovaClient = new ClovaClient();
             var clovaRequest = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);

             // 返事を作成
             var clovaResponse = new CEKResponse();
              switch (clovaRequest.Request.Type)
             {
                 case RequestType.LaunchRequest:
                     // 起動時の処理
                     clovaResponse.AddText("こんにちは。何を占ってほしいですか?");
                     clovaResponse.AddText("健康運と恋愛運と金運を占えるよ。");
                     clovaResponse.AddText("例えば健康運を占ってって聞いてみてね。");
                     clovaResponse.ShouldEndSession = false; // スキルを終わらせないように設定する
                     break;
                 case RequestType.SessionEndedRequest:
                     // 終了時の処理。スキルが終了したときに何かしたい時は、ここに処理を追加します
                     break;
                 case RequestType.IntentRequest:
                     // インテントの処理
                     switch (clovaRequest.Request.Intent.Name)
                     {
                         case "FortuneTellingIntent":
                             // 占いのインテント
                             // 占い対象がスロットに無い場合は総合運勢を占う
                             var fortune = "総合運勢";
                             if (clovaRequest.Request.Intent.Slots.TryGetValue("FortuneSlot", out var fortuneSlot))
                             {
                                 // 占いの対象がある場合は、それをスロットから取得する
                                 fortune = fortuneSlot.Value;
                             }

                             // 占いの結果を返す
                             var result = new[]{ "大吉", "中吉", "小吉", "末吉" }[new Random().Next(4)];
                             clovaResponse.AddText($"{fortune} は {result} です。");
                             break;
                         default:
                             // 認識できなかったインテント
                             clovaResponse.AddText("ごめんなさい。よくわかりませんでした。例えば健康運を占ってと言うと健康運を占います。");
                             clovaResponse.ShouldEndSession = false; // スキルを終わらせないように設定する
                             break;
                     }
                     break;
             }

             // レスポンスとして作成した返事の内容を返す
             return new OkObjectResult(clovaResponse);
         }
     }
 }

コードを保存したらデバッグを実行してください。 これで話しかけると、毎回違った結果が返ってくるようになります。

わかば
やったー!占いの結果が返ってくるようになりました!

デプロイしよう

1. Azureにデプロイしよう

テストしてみて正常に動いたので、いよいよ本番環境にデプロイしてみましょう。

▼Visual Studio Codeの左側にあるAzureのアイコンをクリックし、Deploy to Function App...(上向き矢印のアイコン)をクリックします。

▼Create New Function App を選択します。
Function App の名前の入力を求められます。URL に使われるので世界中で一意である必要があります。使える文字は、a-z0-9- です。

わかば
他の人のものと名前が被っちゃダメなんですね

▼リソースグループを作成します。Create new resource group を選択します。 リソースグループとは、Azure 上の作成するアプリや DB をひとまとめにして管理するフォルダのようなものです。

▼リソースグループ名を入力します。

▼Azure Functions が内部で使うストレージを作ります。Create new storage account を選択します。

▼ストレージアカウント名を入れます。これも世界中で一意の名前である必要があります。

▼続けてリージョンを選択します。日本はJapan WestとJapan Eastがあります。

ちょまどさん
リージョンっていうのはデータセンターが設置されている場所のことだよね。どこに置かれているサーバーを使うかを選ぶよ

▼リージョンを選択するとデプロイが始まります。画面右下にポップアップが表示されます。

▼出力ウィンドウ(OUTPUTウィンドウ)でAzure Functionsを選択するとデプロイの状況が確認できます。

▼デプロイが完了するとVisual Studio CodeのAzure Functions拡張機能から関数(Functions)が確認できます。

▼関数Clovaを右クリックして関数のURLをコピーします。

▼このURLを Clova Extension Kitスキルの基本情報 > 修正 > サーバ設定 に設定することで、Azure FunctionsでLINE Clovaのスキルが動くようになります!

▼無事、Azure Functionsを介して返答が返ってきました。

▼ちなみに、ブラウザから Azureポータルを確認してみると、デプロイできているのが確認できます。

わかば
エディタから直接デプロイできちゃいましたね!すごーい!
ちょまどさん
次回は、いよいよ実機でLINE Clovaに喋らせてみよう!
わかば
わーい!楽しみです!


※ 本記事は2019年1月作成時点での情報です。

次回、第5話へ続く


マンガ・解説: 湊川あい

他にもある「わかばちゃんと学ぶ」シリーズ

マンガと図解で技術がわかる「わかばちゃんと学ぶ」シリーズ。
全国の書店・Amazonで発売中です。

わかばちゃんと学ぶ Git使い方入門:湊川あい 著・DQNEO 監修

著者プロフィール

湊川あい

絵を描くWebデザイナー。高等学校教諭免許状 “情報科” 取得済。マンガと図解の力で、物事をわかりやすく伝えることが好き。2014年より「マンガでわかるWebデザイン」をインターネット上に公開していたところ、出版社より声がかかる。
Twitter: @llminatoll
Webサイト: マンガでわかるWebデザイン


ちょまど(千代田まどか)

エンジニア兼マンガ家。Microsoft 社のソフトウェアエンジニアとしての本業のかたわら、マンガ家やイラストレーター、松屋エバンジェリスト(非公式)としても活動。MS入社前から Twitter 廃人であり、フォロワーは4万人を超える。
Twitter: @chomado
ホームページ: http://chomado.com/

おすすめのコラム