TypeScriptでGoogle Cloud Functionsを実装する方法

# はじめに
Google Cloud Functionsは、イベントに応じてコードをサーバーレスで実行できるGoogle Cloud Platformのサービスです。イベント駆動型のサーバーレスアーキテクチャを利用することで、インフラ管理の手間を大幅に削減できます。加えて、TypeScriptを使用することで、静的型チェックと最新のJavaScript機能を活用し、信頼性の高いコードを記述できるのがメリットです。

本記事では、TypeScriptを使用してGoogle Cloud Functionsをセットアップし、簡単な関数をデプロイするまでの手順を解説します。

# 必要な環境
1. Node.js
1. Google Cloud SDK（認証済み）
1. Google Cloud Consoleでプロジェクトを作成済み

# プロジェクトのセットアップ
まず、TypeScriptとGoogle Cloud Functionsのプロジェクトをセットアップします。
### 1. Google Cloud SDKのセットアップ
```
gcloud init
```

プロジェクトの選択が完了したら、Cloud Functionsを利用するためのAPIを有効化します。
```
gcloud services enable cloudfunctions.googleapis.com
```

### 2. TypeScriptプロジェクトの作成
新しいディレクトリを作成し、TypeScriptプロジェクトを初期化します。
```bash
mkdir cloud-functions-ts
cd cloud-functions-ts
npm init -y
```

必要な依存関係をインストールします。
```
npm install --save typescript @google-cloud/functions-framework
npm install --save-dev @types/node
```

tsconfig.jsonを作成し、以下のようにTypeScriptコンパイラの設定を行います。この設定により、ES6スタイルでコードをコンパイルし、出力先をdistフォルダに指定します。
```json:tsconfig.json
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "outDir": "dist"
  },
  "include": ["src/**/*"]
}
```

# Cloud Functionのデプロイ
### 1. Cloud Functionの作成
新しいHTTPリクエストに応答する簡単なCloud Functionを作成します。まずは、src/index.tsファイルを作成し、以下のコードを追加します。

```typescript:hellowWorld.ts
import { Request, Response } from 'express';

export const helloWorld = (req: Request, res: Response) => {
  res.send('TypeScriptで作成したGoogle Cloud Functionからのメッセージです！');
};
```

### 2. ローカル環境でのテスト
ローカルでの開発をサポートするために、Functions Frameworkをインストールし、ローカルサーバーを起動します。
```
npm install @google-cloud/functions-framework
```

次に、package.jsonに以下のスクリプトを追加して、ローカルサーバーを起動します。
```json:package.json
"scripts": {
  "start": "functions-framework --target=helloWorld"
}
```

ローカルで関数を実行するには、以下のコマンドを実行します。
```
npm start
```
ブラウザやPostmanなどを使って、localhost:8080にリクエストを送り、正常に動作しているかを確認してください。

### 3. Cloud Functionのデプロイ
ローカルで動作を確認したら、次はCloud FunctionをGoogle Cloudにデプロイします。以下のコマンドを実行してください。
```bash
gcloud functions deploy helloWorld --runtime=nodejs16 --trigger-http --allow-unauthenticated
```
--runtime=nodejs16は、Node.jsのバージョンを指定しています。
--trigger-httpは、HTTPリクエストをトリガーにする設定です。
--allow-unauthenticatedは、認証なしでリクエストを許可します。

### 4. ログの確認
Cloud Function内でエラーハンドリングを行い、問題が発生した場合はログに出力できます。
```typescript: helloWorld.ts
export const helloWorld = (req: Request, res: Response) => {
  try {
    res.send('正常に動作しています！');
  } catch (error) {
    console.error('エラーが発生しました:', error);
    res.status(500).send('エラーが発生しました。');
  }
};
```

デプロイが完了すると、関数のURLが表示されます。ブラウザやcurlでアクセスして、デプロイした関数の動作を確認できます。
```
curl https://<your-function-url>
```

デプロイ後のログは、以下のコマンドで確認できます。
```
gcloud functions logs read helloWorld
```

### 5. CORS対策
HTTPリクエストで他のドメインからアクセスする場合、CORS（クロスオリジンリソース共有）エラーが発生することがあります。この問題を解決するには、レスポンスヘッダーにCORS設定を追加します。
```diff_typescript: helloWorld.ts
export const helloWorld = (req: Request, res: Response) => {
+  res.set('Access-Control-Allow-Origin', '*');
+  res.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
+  res.set('Access-Control-Allow-Headers', 'Content-Type');
  
  try {
    res.send('正常に動作しています！');
  } catch (error) {
    console.error('エラーが発生しました:', error);
    res.status(500).send('エラーが発生しました。');
  }
};
```

# まとめ
この記事では、TypeScriptを使用してGoogle Cloud Functionsをセットアップし、ローカルでテストし、Google Cloudにデプロイする手順を紹介しました。TypeScriptの型チェックにより、バグの早期発見が可能になり、堅牢なサーバーレスアプリケーションを開発できます。

次のステップとして、FirestoreやPub/Subなどの他のGoogle Cloudサービスと連携することで、さらに高度なアプリケーションを構築できます。