こんにちは。M&Aクラウドのエンジニアの鈴木智也です。
「自分たちのプロダクトが市場にまだ受け入れられておらず、開発チームが小さく、さらに作ろうとする機能が実際に使われるか分からない。」
そういう時にどういう技術選定をしてきたか、というM&Aクラウドの開発チームの歴史についての話です。
概要
ざっくりいうと
- サイト立ち上げから4ヶ月目の2018年8月。サイト内検索を作るのに Amazon CloudSearch というAWSにロックされた導入が楽チンなソリューションを選択してしばらく運用していた
- それから1年弱たった2019年7月。諸々の問題が発生した。全環境で可能な限りインフラ構成を合わせようと Elasticsearch を使うように変更する
当時のイメージ図でいうと以下のパーツだけです。
現在の検索は以下のような形で高機能になってきました
最初にAmazon CloudSearchを導入した。その時何を考えていたか?
Amazon CloudSearch (以下CloudSearch)は超ざっくりいうと「全文検索エンジンを細かい設定とか気にせずすぐに使えるAWSフルマネージドのサービス」です。 CloudSearchの裏では OSS の Elasticsearch が動いているらしく、だいたい同じことができますが、CloudSearchの方は細かいこと気にしなくていいです。自分で ElasticSearch 立ち上げてクラスタ設定して、細かい日本語形態素解析設定とか、そういうことを気にしなくていいのは良いです。
CloudSearch導入時に考えていたこととやったこと
当時の状況
- 開発チームはエンジニアが2人だけ
- プロダクトはローンチしたばかり
- そもそもプロダクトに何が求められているか手探り状態。検索ワードを取得すればニーズを探ることができるのでは???
- 買い手検索機能が求められているかどうかも分からない。精度は低くてOK
技術調査
当時の状況に合わせて最適な解を探しました。
- そもそもサイト内検索であればGoogleサイト内検索を組み込めばいいのでは?
- => 必ず広告が表示されることが判明。苦労して集めた顧客に対して競合の広告が出るのは望ましくないのでNG。広告なし有料プランは直前まで提供されていたようだが廃止されていた。
- Yahooのサイト内検索(カスタムサーチ)は?
- 専用のソリューション
- => いい感じのがありそうでしたが、初期導入費用に数十万、月額で数万かかるものだったのでNG。ベンチャーはお金ないのだ。
- Elasticsearch は頑張れが導入できるけど、使われるか分からない機能のためにインフラ設定を初期投資としてがんばるの??
- => 今はやめておこう。NG
- AWS に Elasticsearch っぽいいい感じに使えるのがあるっぽいぞ?
- => これが CloudSearch でした。1インスタンス4000円安い!(上記の専用ソリューションに比べたらだけど)
構成を考える
- 本番環境と開発環境の2つのCloudSearchインスタンスを作る
- 開発者が当時2人だけ。だからLocalで開発するときも開発環境のCloudSearchインスタンスに繋げれば OK。Localの環境整えるのも手間だしね
- Localと開発のデータ差異もプロジェクトが始まって間もなく、そんなにないのでDBの内容と CloudSearch の Index が多少食い違ってもOK
- サイト内検索の精度は、最初はその機能がどう使われるかの検証するレベルなのでそんなに高くなくて良いし、導入コストをたくさん払いたくない
会社が大きくなってくると最適解も変わる
より高機能な検索が必要だ
2019年も半ばになって、プラットフォームの売り上げも上がってきて、買い手も増えた。どういう機能が顧客に求められているかも徐々にはっきりしてきた。 例えば、買い手が100件超えそう。売り手は全ての買い手の記事に目を通すのができなくなってきた。絞り込みをする必要がある。買い手検索を高機能にしよう。 というわけで雑に作ってあまり使われていなかった買い手検索に光が当たることになりました。
起こるトラブル
高機能な買い手検索の開発にあたりいくつかトラブルが起こりました。
- LocalからCloudSearch繋げないと検索周りの確認ができないが、env設定変更が面倒
- 面倒がゆえに、開発中に一時的にCloudSearchに繋げないでメソッド内部で固定値を返すように無理やり変更。これがうっかりプルリクエストに入ってマージされて本番でも固定値しか返らないようになるトラブル
- 無理やり固定値を返さなくても良いようにLocalではDBから検索するように分岐をするようにした(LaravelのServiceProviderでの分岐)。本格的なサイト内検索を作ろうとすると、CloudSearch叩く方とDBから検索する方と両方の開発を同時に進めなくてはならず、コストが膨らんでいった
- ちゃんと検索機能を開発しようとするとDBとの整合性も大事なので、手元で書いて開発環境にデプロイして確認、また書いてを繰り返すのがコスト
インフラアーキテクチャがいけてないからトラブルが起こるんだ・・・!
根本対応をしたい。環境差異を無くそう。 エンジニアも3人になった(注: 2019年11月時点ではエンジニア4人デザイナ1人)。Localと開発環境のDBデータの差異も大きくなってきた。もう環境差異があってはやっていけない! ということでこの二つの環境を合わせることに。
環境を合わせる選択肢は以下のものが現れました
- CloudSearch を各開発者向けに1台ずつ立ち上げる
- 10人いたら10台*4000円? 無駄じゃね
- 裏で ElasticSearch 動いているんだから ElasticSearch 動かせばよくない?
- EC2 に ElasticSearch 立てて自分たちでマネージしていくの? きつくない?
こんな話があり、しかしちょっと調べてみると ElasticSearch は思ったよりも簡単に導入できそうだということがわかりました。
- Localに関しては、Laradock で docker-compose up するときに elasticsearch を追加したらすぐに立ち上がることがわかりました。しかもkibanaも同様に簡単につけられる
- 開発/本番環境に関しても、フルマネージドのAWS Elasticsearch Serviceがある
というわけで、Elasticsearchが導入されました
そこらへんの技術記事は以下のような形で qiita に断片的にまとまっているので参照してください
- PHP から ElasticSearch で日本語検索をするためのインデックス作成と設定 - Qiita
- 日本語検索で苦労した記録です
- Kibana で使える Elasticsearh の状態確認のためのリクエストたち - Qiita
- Elasticsearchのクエリビルダをコンポジットパターンで書いた - Qiita
- こちらはElasticsearch用クエリビルダを自前で書いた記事です。CloudSearchには便利クエリビルダなかったので自前で書くしかなく、それをElasticsearchに移行したのでElasticsearch向けという形になっています
終わりに
問題が起こった時に気合いで解決せず、あるべき形の判断材料を並べてチームで判断できたのはよかったと思います。 みんなでスクラム組んで、より生産性を高い状態にしようということを努力しているチームです。
そういうわけで、私たちと一緒に四苦八苦しながら最高のプロダクトを作ってくれる仲間を募集しています。