Open19

react-native

ともけんともけん

参考

https://zenn.dev/hayato94087/books/9ba8aa1f337dd5/viewer/daik6rm7j7gh5j

Expo

  • React Nativeのフレームワーク
  • 特徴
    • OTAアップデート:アプリストアを解さずにアップデート可能
    • Expo SDKカメラや位置情報、通知などが使用可能
    • ExpoGoでテストが容易
    • Web対応
      https://expo.dev/

起動

https://docs.expo.dev/more/create-expo/

pnpm create expo-app@latest react-native-expo-tutorial --template blank-typescript
pnpm expo install react-dom react-native-web @expo/metro-runtime

npmとpnpmの違いについて

https://pnpm.io/ja/feature-comparison

package.json

androidもiosもwebも動作確認ができる

  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },

スクリプト

pnpm run ios	iOS エミュレーターで動作確認
pnpm run android	Android エミュレーターで動作確認
pnpm run web	Web ブラウザーで動作確認
pnpm run start	上記すべてで動作確認

watchman

https://facebook.github.io/watchman/docs/install
watchman とは、ファイルシステムの変更を監視するためのツールです。watchman は、ファイルの変更を監視し、必要に応じて自動的にリビルドやリロードを行うのに利用されています

クリーンアップ

一時的に生成されたファイルを削除できる

pnpm run clean
tree

再度、インストールをする

pnpm i

命名規則について

ともけんともけん

Typescriptの特徴

静的型付け:変数、関数、オブジェクトなどに型が定義できる
JavaScriptのスーパーセット:すべての有効なJavaScriptコードは、TypeScriptでも有効
オブジェクト指向プログラミング:クラス、インターフェース、モジュールなどの機能をサポート
コンパイル時のエラーチェック:実行前に多くのエラーを検出でき、バグを早期に発見。
強力な開発ツールのサポー:IDEでの自動補完、リファクタリング、ナビゲーションが向上
最新のECMAScript機能:最新のJavaScriptに対応し、古いブラウザにコンパイル可能
大規模アプリケーション開発:型安全性が高く、大規模アプリケーションの開発に最適

tsconfig.json

  • Typescriptの設定ファイル
  • コンパイラに対してどのようにコードをコンパイルするかを指示している

Expoプロジェクトのガイド

https://docs.expo.dev/guides/typescript/

ともけんともけん

ESlint

  • ソースコードを解析し、コーディングスタイルやパターンに関する問題を特定するための静的解析ツール
  • コーディングのルールを追加することができる
    https://eslint.org/

Prettier

  • コードのフォーマット設定
フォーマットが必要なファイルを列挙
pnpm run format

修正が必要なファイルを修正
pnpm run format:fix

ステージングエリアに追加されたファイルに対して、コードの品質をチェック

husky

  • git のフックを使用して、コミットやプッシュなどの前に任意のコマンドを実行できるツール
  • コミットやプッシュの前にlintやテストを実行できる

lint-staged

  • Gitステージングエリアに追加されたファイルに対してlintやそのほかのコマンドを実行するツール
ともけんともけん

Git Hub Actions

VScodeの設定

$ mkdir -p .vscode
$ touch .vscode/extensions.json
{
  "recommendations": [
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "yoavbls.pretty-ts-errors",
    "bradlc.vscode-tailwindcss",
    "expo.vscode-expo-tools",
    "usernamehw.errorlens",
    "wix.vscode-import-cost"
  ]
}
ともけんともけん

起動方法

pnpm run start

//iosの場合
i

//androidの場合
a

//webの場合
w

iosシミュレーターの開き方

ともけんともけん

サーバー構成

カテゴリ 技術/サービス 説明
フロントエンド React Native - GraphQL API と通信してデータを取得・処理
- ユーザーのモバイルデバイス上で動作
- Cloud Run や Docker には含まれない
Apollo Client 状態管理
バックエンド Firebase 認証など
GraphQL (API) - データベースへのアクセス
- バックエンドのアクセス制御
Cloud Run - 実行環境(サーバーレスプラットフォーム)
- バックエンドの GraphQL API やサーバーサイド処理を Docker コンテナ内で実行
- サーバーレスでホスティング・スケーリング
- バックエンドのインフラとして機能
コンテナ Docker GraphQL API を含むバックエンドアプリケーションをコンテナ化し、Cloud Run 上で実行
データベース Cloud SQL - GCP上の完全管理型データベースサービス
- パブリックIPでもプライベートIPでも接続可能
- Google Cloud VPC 内に配置
CI/CD GitHub Actions
セキュリティ Firebase Authentication と GraphQL API の間で認証トークン(例:JWTトークン)を使用
ホスティング Firebase Hosting フロントエンドのホスティング(ユーザーが見える側)
ORM Prisma

実装手順

1. バックエンド基盤の準備

Cloud SQL のセットアップ

  • Google Cloud Console で Cloud SQL インスタンス(PostgreSQL または MySQL)を作成し、必要なテーブルを設計
  • Firebase Authentication で認証が必要なユーザー管理のため、ユーザー関連のテーブルも用意します。
    GraphQL API の構築
  • Node.js や TypeScript を使って、GraphQL API を構築します。
  • Apollo Server を使って、Cloud SQL にアクセスするリゾルバを実装します(データベースからユーザーデータやアプリケーションデータを取得・操作するロジック)。
    Docker コンテナ化
  • GraphQL API を Docker コンテナとしてパッケージ化します。
  • Dockerfile を作成し、コンテナイメージをビルドします。
    Cloud Run へのデプロイ
  • Docker コンテナを Google Cloud の Cloud Run にデプロイします。
  • Cloud Run と Cloud SQL を接続して、API がデータベースにアクセスできることを確認します。

認証システムの実装

*Firebase Authentication の設定:

  • Firebase プロジェクトを作成し、Firebase Authentication を有効化します。
  • Google OAuth や メール・パスワード認証を設定します。
  • GraphQL API と連携させ、JWT トークンを使って認証済みユーザーが API にアクセスできるようにします

フロントエンドの開発

React Native + Apollo Client のセットアップ

  • React Native プロジェクトをセットアップし、Apollo Client を使って GraphQL API と通信するクエリやミューテーションを実装します。
  • 認証済みユーザーがアプリからデータを取得できるように、Firebase Authentication を使ってログイン機能を実装します。
    Firebase Hosting でフロントエンドのホスティング(Web版)
  • Firebase Hosting を使って、もし Web 版が必要であれば React Native Web をホスティングします。

CI/CD の導入

GitHub Actions のセットアップ

  • バックエンド(GraphQL API)とフロントエンド(React Native)のために GitHub Actions を設定し、自動ビルド・デプロイを行います。
  • 例えば、Cloud Run や Firebase Hosting へのデプロイを GitHub Actions で自動化します。

セキュリティの強化

JWT トークンの実装

  • Firebase Authentication を通じて発行された JWT トークン を GraphQL API の認証に使います。
  • ユーザー認証が必要な GraphQL リクエストに対して、正しいトークンをチェックし、必要な認可を実施します。

CloudSQLの構築

https://cloud.google.com/sql?hl=ja

クイックスタート
https://cloud.google.com/sql/docs/mysql/connect-instance-auth-proxy?hl=ja

google CLIのインストール→psglインストール→cloudSQLに接続

https://cloud.google.com/sdk/docs/install?hl=ja

  1. インストール
    2. google-cloud-cli-477.0.0-darwin-arm.tar.gz
  2. ホームに配置して、./google-cloud-sdk/install.sh
  3. source ~/.zshrc
  4. gcloud init
  5. gcloud auth application-default login //認証
  6. TCPで接続をする
    8. ./cloud-sql-proxy --address 0.0.0.0 --port 1234 [接続名] // 「-」か「_」に注意
    9. https://cloud.google.com/sql/docs/mysql/connect-auth-proxy?hl=ja#tcp-sockets
  7. brew install postgresql / postgresのインストール
  8. source ~/.zshrc
  9. psql --version // インストールの確認
  10. psql -h 127.0.0.1 -p 1234 -U app-user -d picture_book_db Password for user app-user:

メモ

CloudRunとかチュートリアルがある
https://cloud.google.com/sdk/auth_success?hl=ja

ともけんともけん

Prism

// prismaのインストール
pnpm add prisma
pnpx prisma init
// prismaスキーマファイルの設定
model BookRecord {
  id            Int      @id @default(autoincrement())
  title         String
  author        String?
  date_read     DateTime?
  user_feedback String?
  child_feedback String?
  notes         String?
}
// envに以下を設定する
DATABASE_URL="postgresql://app-user:[password]@localhost:1234/picture_book_db"
//マイグレーション
pnpx prisma migrate dev --name init
// ローカルでprismaの管理画面にアクセス可能
pnpx prisma studio
ともけんともけん

GrapQLの構築

pnpm add apollo-server graphql @prisma/client
pnpm add -D typescript ts-node @types/node @types/graphql

Prismaの設定

  • 既に Prisma と Cloud SQL はセットアップされているので、次に Prisma のクライアントを生成します
  • ``scheme.prisma`を更新したら実行
// prisma clientの再生成
pnpm prisma generate

// migration
pnpx prisma migrate dev --name init
リゾルバ
  • リゾルバ(Resolver)とは、GraphQL API の世界で、クエリやミューテーションが実行されたときに、どのようにデータを取得したり操作するかを定義する関数
  • GraphQL のスキーマに従って、クライアントのリクエストに対して実際のデータを返す役割

Dockerfileの作成

# 1. ベースイメージとして公式のNode.jsイメージを指定
FROM node:18

# 2. pnpm をインストールする
RUN npm install -g pnpm

# 3. 作業ディレクトリを設定
WORKDIR /usr/src/app

# 4. package.json と pnpm-lock.yaml をコピー
COPY package.json pnpm-lock.yaml ./

# 5. 依存パッケージをインストール
RUN pnpm install

# 6. アプリケーションコードをコピー
COPY . .

# 7. アプリケーションが使用するポートを公開
EXPOSE 4000

# 8. コンテナ内でアプリケーションを起動するコマンド
CMD ["pnpm", "start:graphql"]


  • Docker イメージをビルド
docker build -t my-graphql-api .
  • Dockerコンテナをローカルで実行
docker run -p 4000:4000 my-graphql-api

graph-ql実行のためファイル作成

  • src/graphql-server.ts
  • src/resolvers.ts
  • src/schema.ts

package.jsonの更新

    "start": "expo start",
    "start:graphql": "ts-node src/graphql-server.ts",
ともけんともけん

コマンド

// prismaの管理画面
pnpx prisma studio

// graphQLの起動
docker run -p 4000:4000 my-graphql-api

//うまくいかない
(docker compose up --build -d)

// GraphQLの起動と更新
docker build -t my-graphql-api .
docker run -p 4000:4000 my-graphql-api

// cloudSQLの起動
./cloud-sql-proxy --address 0.0.0.0 --port 1234 ******:asia-northeast1:my-cloud-sql-instance-picutre-book

// DB確認
psql -h 127.0.0.1 -p 1234 -U app-user -d picture_book_db Password for user app-user:

docker run と docker-compose の比較

項目 docker run docker-compose
単一コンテナの起動 単一のコンテナを簡単に起動するためのコマンド 複数のサービス(コンテナ)を一括で管理・起動可能
複数サービス管理 難しい。手動で複数の docker run コマンドを実行する必要がある 複数のコンテナやサービスをまとめて定義・起動できる
構成管理 手動でコマンドラインオプションを指定する必要がある docker-compose.yml で全ての設定(ポート、環境変数、コマンド)を管理
再現性 手動のコマンドのため、環境が変わると再現が難しいことがある docker-compose.yml を使って一貫した環境を提供できる
利便性 シンプルなコンテナ起動には便利だが、複雑な設定には向いていない 複数コンテナの起動や依存関係の管理が容易
バックグラウンド実行 -d オプションを指定する必要がある docker-compose up -d でバックグラウンドで実行可能
ともけんともけん

Cloud Run へのデプロイ手順を説明します。これにより、GraphQL API を Docker コンテナとして Google Cloud Run にデプロイし、Cloud SQL に接続することができます。

手順 1: Google Cloud SDK のインストールと設定

もしまだ Google Cloud SDK をインストールしていない場合、まずインストールしてください。

  1. Google Cloud SDK をインストールし、セットアップします。

    gcloud init
    
  2. プロジェクトを選択します。

    gcloud config set project [YOUR_PROJECT_ID]
    
  3. 必要な API を有効化します。

    gcloud services enable run.googleapis.com sqladmin.googleapis.com
    

手順 2: Docker イメージをビルドして Google Container Registry にプッシュ

  1. Docker イメージをビルドします。以下は、Dockerfile があるディレクトリで実行します。

    docker build -t gcr.io/[YOUR_PROJECT_ID]/my-graphql-api .
    
  2. Docker イメージを Google Container Registry (GCR) にプッシュします。

    docker push gcr.io/[YOUR_PROJECT_ID]/my-graphql-api
    

手順 3: Cloud SQL Auth Proxy の設定

  1. Cloud SQL インスタンスにアクセスするため、Cloud SQL Auth Proxy を使用します。以下の手順で Cloud SQL インスタンスの接続情報を取得します。

    gcloud sql instances describe [INSTANCE_NAME]
    
  2. INSTANCE_CONNECTION_NAME(プロジェクトID、リージョン、インスタンスID)が必要になります。

  3. 環境変数ファイル (.env など) に Cloud SQL インスタンス情報を追加します。

    DB_HOST=/cloudsql/[INSTANCE_CONNECTION_NAME]
    DB_USER=[YOUR_DB_USER]
    DB_PASS=[YOUR_DB_PASSWORD]
    DB_NAME=[YOUR_DB_NAME]
    

手順 4: Cloud Run へのデプロイ

  1. Google Cloud Run にデプロイします。--add-cloudsql-instances オプションを使って Cloud SQL インスタンスとの接続を設定します。

    gcloud run deploy my-graphql-api \
    --image gcr.io/[YOUR_PROJECT_ID]/my-graphql-api \
    --add-cloudsql-instances [INSTANCE_CONNECTION_NAME] \
    --platform managed \
    --region [YOUR_REGION] \
    --allow-unauthenticated
    
    • [YOUR_PROJECT_ID] は GCP プロジェクト ID です。
    • [INSTANCE_CONNECTION_NAME] は Cloud SQL インスタンスの接続名です。
    • [YOUR_REGION] は、Cloud Run サービスをデプロイするリージョンです(例: us-central1)。
  2. デプロイが成功したら、Google Cloud Console の Cloud Run セクションでデプロイしたサービスを確認できます。URL が表示され、その URL を使用してデプロイされた GraphQL API にアクセスできます。

手順 5: Cloud Run と Cloud SQL の接続を確認

デプロイが完了した後、Cloud Run のログを確認して、Cloud SQL への接続が正常に行われているかを確認します。

gcloud run logs read my-graphql-api --region [YOUR_REGION]

これで、Cloud Run へのデプロイと Cloud SQL との接続設定が完了です。

ともけんともけん

NextStep

  • GrapQLAPIがPrismaを通じてCloudSQLに接続できるか確認
    • prismaを通じているのはどのように確認するのか
  • Firebase Authentication の実装
  • Docker コンテナの最適化
  • CI/CD パイプラインの構築
  • Cloud Run へのデプロイ
ともけんともけん

cloudSQLとGraphQLの接続

1. src/graphql-server.ts - Apollo Server の設定

import { ApolloServer } from "apollo-server";
import { resolvers } from "./resolvers";
import { typeDefs } from "./schema";

// Apollo Server のインスタンスを作成
const server = new ApolloServer({ typeDefs, resolvers });

// サーバー起動
server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

  • 役割

    • ApolloServerをセットアップし、GraphQLスキーマとリゾルバをサーバーに私知エル
  • つなぎの役割

    • resolversがDBに接続するロジックを持っているので、ここでresolversをApolloServerに渡すことで、GraphQLクエリを受けとった時にDBにクエリを投げることができる

    2. src/resolvers.ts - Prisma 経由で Cloud SQL へのクエリを実行

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

// リゾルバの定義
export const resolvers = {
  Query: {
    users: async () => {
      return await prisma.user.findMany();
    },
  },
};

  • 役割
    • GraphQLのクエリusersが受け取られた時に実行される処理を定義
  • Prismaとのつながり
    • PrismaClient が Prisma のクライアントを初期化しています。このクライアントは、Prisma の設定ファイル(prisma/schema.prisma)に基づいてデータベース(Cloud SQL)に接続
    • User テーブルからすべてのユーザーを取得
    • Cloud SQL との接続: Prisma クライアント (PrismaClient) は、環境変数で設定されている DATABASE_URL(例: postgresql://user:password@localhost:5432/dbname)に基づいて Cloud SQL に接続しています。つまり、PrismaClient は自動的に Cloud SQL に接続され、データベースへのクエリを実行

3. src/schema.ts - GraphQL スキーマ定義

import { gql } from "apollo-server";

// GraphQL スキーマの定義
export const typeDefs = gql`
  type User {
    id: ID!
    name: String!
    email: String!
  }

  type Query {
    users: [User!]!
  }
`;

  • 役割
    • このファイルは GraphQL のスキーマ(データモデルとクエリ)を定義しています。
    • User タイプは、データベースの User モデルと対応
    • users クエリは、すべてのユーザーを取得するためのエントリポイント
  • つなぎの役割
    • クライアントが users クエリをリクエストしたとき、このスキーマに基づいてクエリが resolvers ファイル内の users リゾルバにマッピングされ、そのリゾルバが Cloud SQL にクエリを実行します。

まとめ

src/graphql-server.ts: Apollo Server をセットアップし、GraphQL スキーマとリゾルバをサーバーに渡しています。
src/resolvers.ts: Prisma クライアントを使って、Cloud SQL に接続し、データベースにクエリを実行する役割を持っています。ここで実際にデータベースとの通信が行われます。
src/schema.ts: GraphQL スキーマを定義し、どのようなデータを取得するかを決めています。

ApolloServerをGraphQLのつながり

app/_layout.tsx において、ApolloProvider がアプリケーション全体をラップします。この設定により、アプリ内のどのコンポーネントからでも Apollo Client を通して GraphQL サーバーと通信できるようになります。

各ページ(例えば app/index.tsx)では、Apollo Client の useQuery フックを使って、GraphQL クエリを実行し、サーバーからデータを取得します。

取得したデータは、React Native の UI コンポーネントを使って画面上に表示されます。

ともけんともけん

Docker化

DockerとGraphQLの関係

GraphQL API のコンテナ化: GraphQL サーバー(例えば Apollo Server)を Docker コンテナにパッケージ化することで、開発環境から本番環境まで一貫した環境を提供できます。これにより、GraphQL API をどのマシンでも同じ方法で動作させることができ、セットアップの手間が大幅に減ります。

利点: GraphQL サーバーの依存関係(Node.js、データベース、ライブラリなど)をすべて Docker イメージ内にパッケージ化できるため、環境構築が簡単になり、どこでも同じ動作を保証できます。
GraphQL サーバーのデプロイが容易に: Docker はクラウドプラットフォーム(Google Cloud Run、AWS ECS、Kubernetes など)と連携しやすいため、GraphQL API をコンテナ化することで簡単にクラウドにデプロイでき、スケーラビリティを高めることができます。

利点: GraphQL API をコンテナ化することで、クラウドサービス上でのスケーラブルなデプロイや管理が容易になります。例えば、コンテナがあれば、GraphQL サーバーを複数インスタンスで動かし、負荷分散を行うことができます。
マイクロサービスアーキテクチャでの GraphQL: マイクロサービスアーキテクチャを使用する際、各マイクロサービスを独立した Docker コンテナで管理します。GraphQL サーバーがその中で API ゲートウェイ として機能し、各マイクロサービスからデータをまとめてクエリできるようになります。

利点: GraphQL サーバーを API ゲートウェイとして活用することで、複数のマイクロサービスを一つのエンドポイントから効率的に管理できます。Docker で各マイクロサービスをコンテナ化すれば、個別にスケーリングや管理が可能です。
開発とテストの一貫性: Docker コンテナは、開発・テスト・本番環境間で一貫した動作を保証します。GraphQL API の開発では、Docker コンテナ内で依存関係や設定をまとめることで、テストやデプロイにおいて一貫性が保てます。

利点: 開発環境と本番環境が一致し、テスト時に見つけた問題が本番でも同じように再現されるため、バグの発生率が低下します。

ともけんともけん

Cloud Runへのデプロイ

 $ gcloud auth login # アカウント追加
 $ gcloud config set account `ACCOUNT` # このコマンドでアカウントを切り替えできる
#  現在のプロジェクトIDがわかる
❯ gcloud config get-value project

#  現在のプロジェクトNo.がわかる
❯ gcloud projects describe brilliant-forge-437512-j6 --format="value(projectNumber)"
640025738152

#  Cloud Run サービスのデフォルト プロジェクトを設定
 gcloud config set project PROJECT_ID

#  Cloud Run Admin API を有効
gcloud services enable run.googleapis.com

# Cloud Build がソースを構築できるようにするには、次のコマンドを実行して、Compute Engine のデフォルト サービス アカウントに Cloud Build サービス アカウントのロールを付与

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member=serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --role=roles/cloudbuild.builds.builder

#  プロジェクト一覧の確認
❯ gcloud projects list

# ロールの付与
gcloud projects add-iam-policy-binding [PROJECT_ID] \
    --member=serviceAccount:[PROJECT_NUMBER]-compute@developer.gserviceaccount.com \
    --role=roles/cloudbuild.builds.builder
******