読み込み中...
CHIYUU

Services

お問い合わせ
PraLoopを支える技術スタックの紹介

従業員と共にPraLoopというスマホアプリを、iOS/Android向けに開発/リリースしました。

本記事では、PraLoopで使用している技術スタックについて紹介したいと思います。

概要

リポジトリはモノレポ構成で、主なディレクトリは次のように分かれています。

- `mobile/`: Flutter 製のモバイルアプリ
- `api/`: Go 製のバックエンド API
- `deploy/`: Ansible、Terraform、デプロイスクリプト
- `web/`: 公式サイト、ヘルプページなどの Web 側実装
- `.github/workflows/`: mobile,api,webのCI/CD
- `docs`/: Claude Code, CodexでSDDができるように、仕様や開発時のガードレールなどのルールを記載

以降、それぞれ解説していきます。

moible(Flutter)

mobileで使用している技術スタックは以下となります。

領域技術
フレームワークFlutter
言語Dart
状態管理Riverpod 3、hooks_riverpod
コード生成riverpod_generator、freezed、json_serializable、build_runner
アーキテクチャDDD / Onion Architecture 風のレイヤードアーキテクチャ
アーキテクチャ検証import_lint
ルーティングgo_router
ローカル DBDrift / SQLite
課金in_app_purchase、in_app_purchase_android、in_app_purchase_storekit
認証google_sign_in、sign_in_with_apple、flutter_secure_storage
通知flutter_local_notifications、timezone、flutter_timezone
監視sentry_flutter

ポイントとしては、保守性を考慮し、メジャーかつメンテナンスされているパッケージを選んだのと、レイヤードアーキテクチャを用い、import_lint により、CIのlinterで依存方向違反を自動で検知できるようにしたところです。

Claude CodeやCodexに指示を出す際、 AGENTS.md にルールを詰め込みすぎると、コンテキストを圧迫し、トークン消費の向上や推論レベルの低下が起き得るため、コードの書き方などのルールはlinterやskillsで担保するようにしていました。

modile配下のディレクトリ構成は以下となります。

- `presentation/`: UI、ViewModel、State
- `application/`: ユースケース、DTO、アプリケーション固有のワークフロー
- `domain/`: エンティティ、Repository interface、値オブジェクト、ドメインルール
- `infrastructure/`: Repository の具象実装、Drift / SQLite、外部 API、端末機能
- `core/`: ユーティリティ、エラー、i18n、Dependency Injection

API(Golang)

APIで使用している技術スタックは以下となります。

領域技術
言語Go 1.25
HTTP フレームワークGin
アーキテクチャDDD / Onion Architecture
API スキーマOpenAPI
型生成oapi-codegen
DBMySQL
SQL 生成sqlc
マイグレーションAtlas
認証JWT、OIDC、メール認証
バリデーションgo-playground/validator/v10
メール送信gomail
キャッシュ / PubSubRedis / Valkey
多言語対応go-i18n
監視Sentry
Lint / アーキテクチャ検証golangci-lint、depguard、errcheck、govet、staticcheck

API 側でも、mobile と同じく各レイヤーの境界は linter で守っています。api/.golangci.yml では golangci-lintdepguard を使い、外部からの依存方向がドメインに対し一直線となるようにCIのlinterで制御しています。

また、OpenAPI を用い、oapi-codegen で型とインターフェースを生成しています。
これにより、仕様書を書くだけで一通り必要なコードが自動で出力されるため、開発者やAIによって実装がバラバラという問題がなくなりました。

api配下のディレクトリ構成は以下となります。

- `cmd/api/`: API サーバーのエントリーポイント
- `internal/presentation/`: HTTP handler、middleware、OpenAPI generated schema
- `internal/application/`: 認証、同期、課金などのユースケース
- `internal/domain/`: ユーザー、認証セッション、同期モデルなどのドメイン
- `internal/infrastructure/`: DB、repository、JWT、OIDC、Redis、Google Play、App Store などの具象実装
- `internal/core/`: 設定や横断的な処理
- `sql/`: schema、migration、sqlc query
- `openapi/`: OpenAPI 定義

Infrastructure

Infrastructure(deploy/ 配下)で使用している技術スタックは以下となります。

領域技術
構成管理Ansible
IaCTerraform
コンテナDocker
API デプロイKamal 2、GHCR、Kamal proxy
デプロイ実行基盤GitHub Actions、self-hosted runner
デプロイ方式Kamal proxy によるゼロダウンタイムデプロイ
監視Datadog Agent、Sentry、Cloudflare

ネットワーク図は以下となります。現状、単一ホストですが、負荷に応じて水平スケールする構成としております。

まだ、リリースしたばかりで、トラフィックも少ないため問題ありませんが、ゆくゆくはAPIサーバーの冗長化、DBのリードレプリカ追加、各サーバーの垂直スケーリングなども行う想定です。

また、ネットワーク図を見るとお分かりの通り、CI/CDパイプラインによるデプロイフローの自動化を行っております。

具体的には、GitHub Actionsにより、linter/testが通ったブランチがmasterブランチにマージされると、自動でwebディレクトリの内容がデプロイされます。APIに関しては、DBマイグレーションなどの関係から手動でworkflowを実行するフローとなっています。

実は、mobileに関してもローカルでのスクリプト実行ではありますが、以下を自動化しております。

  • スクショからApp Store/Google Play用の画像生成
  • アプリ紹介文の自動多言語翻訳
  • 生成された↑の画像/テキストのApp Store/Google Playへの反映

これについては、別途記事をかければと思ってます。

終わりに

以上、簡単ではありますが、PraLoopを支えている技術スタックの紹介でした。

PraLoop は、動画や音楽、YouTubeの特定の箇所を繰り返し再生出来るアプリです。

僕自身、ギターのTab譜動画や、ピアノの上から弾く場所が流れてくる動画を見て楽器を練習しており、速度再生や、繰り返し特定の箇所を再生できたら嬉しいなというニーズがあり、開発しました。

便利だと思いますので、同じようなニーズがある方はぜひ、DLしてみて頂ければと思います。

また、今後、各技術を掘り下げて紹介する記事も書いていければと考えておりますので、よければそちらも見て頂けると嬉しいです。

ご相談お待ちしております

システム開発やDX戦略、AI導入などでお困りの際はお気軽にご相談ください。
※通常1営業日以内に回答致します。

無料で相談する