タクトピクセルの玉城です。ブログを初めて最初の記事ですが、今回は社内の開発環境について書きたいと思います。
当社の開発環境は、初期のスタートアップが取る割と一般的な構成なのではないかと思います。AWSで構築しています。
近年は選択肢も多くなってきて、特殊な処理を行わない一般的なSaaSであれば、どの技術を採用するかはトップや初期の開発メンバーの好みに依存している気がしていて、そういうバックグラウンドがない場合は逆に判断に迷う部分が多いのではないかと思い、この記事を書いています。当社と同じような道を辿っているスタートアップや、新規事業を立ち上げる方の参考になればと思います。
私達の少し特殊な事情があるとすれば、画像を多く使うということと、機械学習のためのバッチ処理が入ってくるということくらいです。あとはtoBのビジネスであることからインフラ部分は特殊なことをしなくてもそこそこアクセスをさばけますし、DBも通常のRDS(AWS Aurora)、ストレージはAWS S3です。
※ 当社は2つのSaaS製品を開発しており、実は若干の違いがあります。その点を詳しく説明してしまうと長くなってしまうため、この記事では2つの製品を区別せずに書いています。ご了承下さい。
現在のチームの状況
合計4〜8名体制(常勤4名+非常勤)
最初は1名で、2年かけて徐々に増えてきた、という感じです。非常勤の方は入れ替わりがあったりしていますが、最近は大体同じメンバーで回しています。
コンテナ&マイクロサービスアーキテクチャ
Dockerを使っており、ローカルPCの開発環境ではdocker-compose、本番環境ではAWS ECS Fargateで稼働しています。
フロントエンド、バックエンド、画像処理はそれぞれ別々のサービスで立ち上げて相互にやり取りするような、マイクロサービスアーキテクチャを採用しています。その間はJWT認証でボディはjson形式のいわゆるREST APIで通信しています。
スモールスタートで行うのであればモノリシックな構成でも良かったのですが、創業当時の資金状況である程度は精神的な余裕が出来たので、初期投資が大きくなってもスケーラビリティを優先させてマイクロサービスアーキテクチャをいきなり採用しました。マイクロサービスが必ずしも正解ではない、というのその通りだと思います。ただ、これに慣れてしまうと、技術選定のリスク感や新メンバーをアサインするときにこの方法を基準として考えてしまうため、モノリシックには戻れない体になってしまった、という実感があります。
この判断は現在の開発スピードの加速に貢献しています。GraphQLも出始めてカンファレンスではかなり話題になっていたのですが、全体の複雑性もまだ決まっていない状態では敷居が高く採用を見送りました。Dockerはローカル上のデバッグでも本番環境でも大活躍しています。素晴らしいツールに恵まれた、とてもいい時代になりました。
プログラミング言語 / フレームワーク
選定の基準としたのは主に3つです。
- 自分(CTO)が理解できる技術(知っている、またはキャッチアップが容易)であること
- 将来的な拡張性が見込めること
- 開発者人口が多いもの
フロントエンド
フロントエンドはJavaScript/Vue.jsを使っています。
まず、SPA(Single Page Application)で作ろう、と最初に決めました。フロントエンドは当時、Angular, Reactをよく耳にしていて、まずはAngularで作り始めたのですが、これが難しかった。ちょうどAngularJSからAngularへの移行の時期で和書もまだ多くなく古いバージョンのみ、実際に作ってみるとちょっとしたアプリケーションでも仕組みの理解が難しく苦労しました。その時、Vue.jsのチュートリアルを試してみたところ非常にあっさりと実現出来たことや、その上のエコシステムが素晴らしくVue.jsを選択しました。UIコンポーネントは主にElementを利用していますが、こちらも素晴らしいプロジェクトです。
バックエンド
バックエンドにはPHP/Laravelを使っています。
バックエンドはまだまだPHP言語が根強い人気があり国内の開発者人口が多いので、事業拡大期に人材採用しやすいのではないかと思い採用しました。Rubyは不勉強であまり知っておらず、goやNode.jsはまだ手を出すには早すぎると考えました。
Webフレームワークについては、CakePHPとZend Frameworkはどちらも大規模な開発には難易度が上がる事がわかっていたので代替を検討していたところ、Laravelを見つけました。明快なルールがありコードが気持ちよく書けるのが気に入っており、活発に開発が進められているのも安心感があります。最近になってますます人気が高まっているのを感じます。東京のイベントにも何度か行きましたし、日本のコミュニティも存在感があり今後の発展が楽しみなフレームワークです。
画像処理・機械学習
当社が開発・運営しているPOODL(プードル)も proofrog(プルーフロッグ)も画像処理を行う必要があり、その開発にはPython/Djangoを使っています。
画像処理自体はOpenCVや一部C++で書かれており、機械学習部分はTensorFlow, Keras, scikit-learn等の機械学習ライブラリを利用しています。
一般的に、画像処理とWebアプリケーション開発者の経験は大きく異なっていると考えていて、求める開発業務もなるべく分けるようにし、別々の専門性を要求したいと考えています。画像処理・機械学習のWebAPIは、アーキテクチャの中に隠してユーザーからは直接触れられない領域にデプロイして利用するアーキテクチャを取っています。そうすることで、認証機能やWebサーバーとしての役割はこのサービスには求められていないため、Djangoが提供するWeb APIの機能は重厚になりすぎずに済みます。これにより、画像処理の動作テストはコマンドラインベースで行う事ができ、複雑なアルゴリズム検討に集中出来ます。
その他の開発技術
POODL(プードル)では、多くの業務アプリケーションで採用されているWindows .NET系の環境で動作するよう、C#言語で深層学習モデルが動作するようなサンプルプログラムを提供しています。SciSharpプロジェクトにはとてもお世話になっています。
また、画像データセットをPOODLにアップロードするクライアントアプリケーションとしてElectron.jsを使ったGUIアプリケーション poodl-client も提供しています。
TensorFlow/Kerasのモデルを.NET系やElectron.jsで動かすのは可能なのですが、バージョン依存が激しかったりモデルの変換が必要だったりと一筋縄ではいかない部分がありました。これはまた機会があれば別の記事にまとめたいと思います。
アプリケーション開発とは別で、データ分析の依頼を受けることもあります。その場合は、Python/pandasをよく使っています。Jupyter notebookも使います。
深層学習技術やWebの技術は、日進月歩ですので日頃からのキャッチアップが欠かせません。提供するべきアプリケーションのニーズに合わせて新しい技術を吸収しながら、現場の役に立つ機能開発を行っています。
プロジェクト管理
Git/Github Issueで管理しています。現在、マイクロサービスごとにリポジトリを作っているので、2つの製品の主要なリポジトリだけでも10個ほど、すべて合わせると20個ほどが動いています。
開発の流れは以下のような形です。簡易版git flowを採用しています。
- Project Manager (PM, 私)がIssueを追加してメンバーをアサインする。
- 開発メンバーがブランチを切って実装作業を行う。
- 完了したらPull Requestを送る。
- PMが内容を確認して問題なければmergeする。
- 適切なタイミングでPMが判断して本番環境にリリースする。
この流れの中で、Github Issueの機能は非常に便利に使っています。最近は、徐々にメンバーも増えるとともに、私の仕事が開発から広報にシフトしてきたこともあり、体制とツールの見直しを行っています。
git flowをフルで採用するにはプロダクト開発初期には重厚すぎるので、ケースバイケースで部分的に使うのが良いと考えています。例えば、私達はまずはfeatureとreleaseの運用のみを行ってきました。今後はsupport, hotfixなどのブランチなども活用してDevOpsを推進していきたいとも考えています。
また、最近は人が増えたこともあり、リポジトリを横断するタスク管理ツールの検討も始めています。この辺りはチームのフェーズに合わせて柔軟に変えてく必要があると思います。
そのほか利用している外部サービス
認証
見えないコストですが重要なのが認証サーバーです。当初、POODL(プードル)という製品では工場の特殊な権限管理を実現するために自前の認証サーバーをPHP/Laravelで用意していました。これがとても辛く、登録時のフローからメンバーの権限管理、パスワードの再発行、IPアドレス制限などの機能を一つ一つ実装するだけでも何人月もかかるという状況でした。
もう一つの製品を作るにあたって便利なものがないか探した結果、Auth0を見つけ、とてもお世話になっています。難しい認証の規約を理解しなくても、ある程度はサクサクと実装出来るのと、Social Signin (FacebookやTwitterなど)の認証が手軽に出来るのが素晴らしいです。
決済
基本的には「BtoBの商売であれば、クレジットカードなどの決済に対応しなくても、プロダクトのリリース初期ではなんとかなってしまうもの」だと思います。当社も最初の製品POODLをリリースしてから1年間は特に必要性も感じていませんでした。2つ目の製品proofrogが多少のtoC要素もあったことから、クレジットカード決済機能の実装が必要になりました。
自前で実装するのはセキュリティとしてもリスクが高いのでいくつか調査して、最終的にはStripeを利用することにしました。サブスクリプションビジネス用の機能も最近になってどんどん追加されていっているので期待が持てます。
もう一つ便利なのが、APIキーを入れ替えるだけでテスト用の決済処理を手軽に行えることです。テストの度に実際の決済がおりてしまうと高額商品の場合はそれだけである程度のコストになってしまいますが、Stripeの場合はテスト用のクレジットカード番号で試しに決済したり、エラーを起こしたり出来るので安心して開発することが出来ました。
さほど優先度も高くなかった中で工数もあまり使えず、セキュリティの不安を抱え続けることもできなかったため、ひとまず決済手段を手軽に実装できたのはとても助かりました。
今の所、当社製品のオンライン決済はStripe経由のクレジットカードだけです。他にもPayPalやPay系決済が増えてきているので、提供しているサービスの性質によっては必須となるかもしれません。
エラートラッキング
Sentryを使っています。最初はフロントエンド側だけでしたが、バックエンド、画像処理などあらゆるマイクロサービスに対して埋め込みました。当初はAWS CloudWatchのアラートを設定してエラーの原因を探る、ということを行っていたのですが情報が足りなかったりログを探すのが手間だったので、Sentryはとても便利に使っています。
特にフロントエンドではエラーが起こったとしても特に何も用意していない場合は運営サイドには感知できないため、このようなトラッキングのアプリは必要不可欠だと思います。
監視
エージェント監視と外形監視をMackerelで行っています。他にも、AWS CloudWatchのアラートも設定しています。最初は別の製品を使っていたのですが、Docker対応が遅れていたのとあまり細かい機能を使いこなせずに移行しました。いまはこれで問題なく運用できています。
チャットサポート、オンラインマニュアル
お客様とのチャットによるサポート用にIntercomを使っています。かゆいところに手が届く、とても便利なツールです。今の所、唯一無二のサービスだと思っていたのですが、もう少しエディタの充実や日本語環境のUI対応がうまくいくと良いなと思っているところです。
オンラインマニュアルには、IntercomとHelpDocsを併用しています。Intercomはチャットやカスタマーサクセスのためのコミュニケーションツールとしての色合いが濃く、Articleと呼ばれるオンラインマニュアルについてはまだ機能や使い勝手の面で十分ではないと考えていました。いろいろ試してみて、Intercomの資産をそのまま移行でき、使い勝手も良いHelpDocsを追加で使用しています。オンラインマニュアルに特化した機能がいくつかあり、多言語化の機能もあるのでおすすめです。Intercom側にHelpDocsを統合する機能も用意されています。
オフィス環境とリモートワーク
これは開発とは直接関係がないですが、PMとしては結構悩むポイントなのではないかと思います。プロジェクト管理をきちんと行っていけば、まず緊急的には昨今のリモートワークに対しても柔軟に対応出来るのではないかは思います。現在私達は半々くらいの人数でオフィス出社組とリモートワーク組に分かれています。今後はますますリモートワークが多くなっていく見込みです。
中長期的に会社のスタンスとしてリモートワークを推進するのかどうなのか、個人的には、リモートワークは一長一短で、メンバーの特性に依存するため、トップダウンで決めるのではなく個々の希望を聞きながら制度設計を行っていくのが良いと考えています。コミュニケーション能力はチーム開発では重要なのは言うまでもありません。しかしより詳しく見れば、「対人コミュニケーション能力」と「リモートコミュニケーション能力」と2種類あり、それぞれのメンバーの得意不得意にはばらつきがあるので、そのレベル感をうまくバランスとりながら進めていくことが必要と思います。
実際、メンバーの好みによって、会社に来たほうが捗る、ということもあるようです。それは尊重しつつ、働きやすい環境を作って開発が加速できるようにルールを整備しています。
まとめ
実はこの記事はWantedlyに書いた自社広報用の記事で書ききれなかった仕組みについて、より膨らませてまとめたものです。OSSや素晴らしいSaaSプロダクトの力を借りながら私達の製品が構成されています。その上に独自の新しい価値を生み出し、お客様を幸せにできるプロダクト開発を目指して行きたいと思います。
溜まってきた個別のノウハウ(+つらみ)については機会があればまとめていきたいと思います。同じように試行錯誤しながら進めているスタートアップのチームも多いと思うので、何らかの参考になれば幸いです。
また、Wantedlyではフロントエンド、機械学習のメンバーを募集しています!興味ある方は是非見てみて下さい。