見出し画像

ペンマークを支える技術の紹介

みなさま、こんにちは。エンジニアリングマネージャーの墨崎です。

このたびペンマークの技術や開発組織、カルチャーをお届けするTech noteを開設いたしました。ペンマークがnote上で運営するPenmark Magazine内のマガジンで連載していく予定です!

ペンマークは「学生の一生を豊かにする」ことをミッションに掲げ「大学生活のDX」を推進しているスタートアップ企業で、大学生向け履修管理SNS「Penmark」を開発・提供しています。
本記事ではペンマークで採用しているアーキテクチャや技術スタック、技術選定の方針などを紹介致します。

技術選定の方針

サーバレスアーキテクチャ

全体として、プロダクトの開発速度を最重要視しサーバーの管理運用コストやスケーラビリティを考慮したサーバレスなサービスやマネージドサービスを採用する方針としています。

Z世代の大学生向けアプリというプロダクトの性質から、UI/UXの品質を担保しつつ仮説検証を高速で行いたいという要件があります。
プロダクトローンチ当初のエンジニアは1名のみであったこと、開発速度を重視してクライアントサイドの開発にリソースを充ててバックエンド開発のコスト・工数を削減したいという背景もあり、Firebaseを採用しました。

プロダクトのグロースとともにFirebaseを軸とするサーバレスアーキテクチャのノウハウが社内で溜まったこともあり、プロダクト規模が大きくなった今でもFirebaseを使い続けています。
限られたリソースの中で仮説検証を高速で行い、機能追加を行う上でFirebaseの採用はとても効果的でした。

開発言語

開発リソースを柔軟にやりくりできるようにするため、開発言語はDart(モバイルアプリ)・TypeScript(バックエンド・Webフロントエンド)のみとなっています。どちらもモダンな言語で静的型付けに対応したオブジェクト指向言語であるという点が特徴として挙げられます。

DartはJavaScript/TypeScriptとも親和性が高いため、低い学習コストやスイッチングコストで開発リソースを確保することが可能となっています。
実際に弊社でも、元々Webフロントエンドを本職としていたエンジニアがモバイルエンジニアとして開発を行っているという事例があります。

また、Webフロントエンド・バックエンドにてTypeScriptで統一している理由も、同様に開発リソースを柔軟に確保したいという点が挙げられます。

技術スタック

ペンマークで扱う主な技術スタックは以下の通りです。

モバイル

Flutterを用いたモバイル開発を行っています。
Flutterで開発を行っている理由は、開発スピードを重視してクロスプラットフォーム開発できる点が魅力的であったためです。

クロスプラットフォーム開発においてはReact Nativeも候補に上がると思います。しかし、Expoでの開発時の制約や、eject時の断続的にアップデートされるサードパーティのパッケージに依存してしまう点や、バージョンアップデートへの対応の大変さがネガティブポイントでした。

Flutterは公式パッケージの豊富さや、バージョンアップデートが継続的に行われている点も魅力的です。
(また、最近Flutterバージョンを1.22.6から3.0.1へアップグレードしました。詳細は別記事にする予定です。)

以上の通り、総合的に開発体験が安定していると判断してFlutterでの開発を推進しています。
また、状態管理にはBLoC、アーキテクチャはクリーンアーキテクチャでフロントエンドDDDを採用しています。

FirebaseへのアクセスはクライアントでFirebase SDKを用いて、Firebase Authでの認証やFirestoreの操作、Cloud Functionsの呼び出しを行います。CI/CDツールはGitHub Actionsを導入していて、GitHub Actions経由でビルド・テストの他、App Distributionへの配布やTestFlightへのアップロードを行っています。セットアップが手軽でCI/CDをGitHubで完結できる点がメリットです。

バックエンド

Node.jsをランタイム環境としてCloud Functions(Firebase Functions)で開発を行っています。

Cloud Functionsはサーバレスなコンピューティングサービスで、関数単位でデプロイ・実行が可能です。
Cloud Functionsは大きく分けて、クライアントから呼び出されるHTTP関数とバックグラウンドで実行されるイベントドリブン関数があり、弊社ではその両方の開発を行っています。
Node.js環境のHTTP関数はExpressと互換性があるため、直感的に開発をすることが可能です。

処理の内容としてはFirebase Admin SDKによるFirebase各種サービスへのアクセスや、外部APIへのリクエスト等を行います。クライアント側で実行できない処理、バックグラウンドで行いたい定期実行タスク、Cloud PubSubを用いたメッセージングに活用しています。

サーバレスの特徴としてデプロイ・スケーリングが楽な反面、デメリットとしてコールドスタートが挙げられます。
コールドスタートの対策としては最小インスタンスの設定や、関数ファイルの分割やdynamic importといったコードレベルでの対応を行っています。

CI/CDツールはモバイルと同じくGitHub Actionsを採用しています。
ビルドとテスト、Firebase環境へのデプロイを自動化しています。

Webフロントエンド

フレームワークは基本的にNext.jsを扱っています。社内にReactの知見があるメンバーが多く、TypeScriptとも相性が良いため採用しました。
Web版、管理画面ともにNext.jsで構築されており、それぞれVercel, Firebase Hostingにホスティングしています。
Web版ではMVPやキャンペーン用のページ開発を行っており、SSG/ISRが要件として出てくるためVercelをホスティング先としています。

管理画面のみFirebase Hostingを採用している理由はCSRのみであることと、GCPで統一したかったためです。
CSRのみであったとしてもNext.jsのRouting機能やconfigファイルが不要であること、Fast Refresh機能などは開発体験において恩恵を受けています。
また、状態管理はReduxを使って開発しています。
CI/CDツールも同じくGitHub Actionsを採用しています。

インフラ構成

プロダクト全体のインフラ構成図は以下の通りです。

前述の通り、Firebaseを軸としたGCPがメインのサーバレスな構成となっていますが、一部技術的な制約のためAWSを採用しています。

GCPのプロジェクトについてはアプリ用のプロジェクトとAdmin用のプロジェクトの2プロジェクトの構成となっています。2プロジェクト間でのデータのやり取りを行う際はCloud Functionsをハブとしています。

DBはFirestoreの他にBigQueryとElasticsearchを採用しています。
BigQueryは分析用途で、Cloud FunctionsのロギングやGoogle Analytics, Adjustといったマーケティングツールにて収集したrawデータを格納させています。
ElasticsearchはFirestoreが全文検索にサポートしていないため、検索用DBとして採用しています。ElasticsearchにFirestoreのデータをインサートし、検索時にはこちらを呼び出します。以前はAlgoliaを採用していましたが、保存するデータ量が多くなるにつれて料金が膨大になったためElasticsearchに移行しました。またElasticsearchはクライアントから直接呼び出しは出来ないため、Cloud Functionsを通じてクライアントから呼び出します。

各種KPI等のデータ分析にはRedashを使っています。各プロジェクトのBigQueryとAWS AthenaをRedashに接続し、SQLを書いて可視化する、といった流れで行っています。

まとめ

本記事ではペンマークにおける技術選定の方針や技術スタック、インフラ構成についてご紹介しました。開発スピードやコストを重視した、NoSQLでかつサーバレスファーストな技術選定であることが最大の特徴です。
しかしプロダクト規模が大きくなるに伴い、エンジニア組織も拡大し、これまでになかった課題も浮き彫りになってきています。この大規模化にいかに対応するのかという点がペンマークの技術選定やアーキテクチャ設計における最大の議題となってきています。
こういった技術的な課題を解決し、一緒にプロダクトを成長させられる仲間を求めています!

エンジニア積極採用中です!

急成長するプロダクトを一緒に開発して頂けるエンジニアを積極採用中です。ペンマークのエンジニアは様々なバックグラウンドを持った魅力的な仲間が多いのが特徴です。ペンマークに興味を持ってくださる方は、是非一度お話しましょう!


アプリのダウンロードはこちらから