大学二回生がインターンとして入社し半年が経った話

初めまして、Baseconnectのエンジニアインターンの秀と申します。今回は現在大学二回生である僕が、半年間勤めて初心者ながらも気づいたことや、感じたことをお話ししようと思います。 (執筆時点で二回生、この4月で三回生になります)

はじめに

まずは、僕自身とBaseconnectのエンジニアインターンについて軽く紹介しておこうと思います。冒頭でも少し触れた通り、僕は現在大学二回生で文理混合の情報学部に通っています。

元々情報系に興味があったので、Baseconnectに入社する前から一応教本などでプログラミングの勉強はしていましたが、小さい頃からコンピューターを触っているような人間ではありませんでした。

参加したきっかけはコロナの影響が大きかったと思います。大学入学直後から講義はほとんどリモートで、出される課題は多いものの意外と自分に使える時間が沢山ありました。そんな中、見かけたのがBaseconnectのエンジニアインターン募集の記事でした。

他のサマーインターンなどと違って、期間が決められておらず最短で15ヶ月以上と長期的です。仕事に慣れてくるとリモートでの勤務も可能なので働き方には融通が効きます。僕は、ただただ課題をこなす日々を変えたくて、応募を決意しました。

その1...触れるコード量が多い

晴れてBaseconnectに入社でき、いざ初めのタスクに取り掛かるぞ!と息巻いたところ、コード量の多さに圧倒されました。ディレクトリはしっかりと階層構造で分けられていたものの、教本や映像教材でも見たことのない単語がずっしり......。最初に振られたタスクはとても簡単なものでしたが、変更箇所を探すだけでも一苦労でした。

その2...ツールの重要性

早速エンジニアとしての洗礼を受けた僕ですが、いくつかタスクをこなしたり、先輩達のありがたいアドバイスを受け、徐々に徐々にコツを掴んでいきました。その一つがズバリ検索です!!先ほど、簡単なタスクでも変更箇所を探すだけで苦労したとお話ししました。

しかしこの問題...テキストエディタの検索機能を使えば一発で解決します!!と言っても世のエンジニアの方からするとこれは当たり前の手段でわざわざ本やブログなんかに書くことでもないかと思います。

しかし、大量のコードに触れた事がなく、これまで手探りでコードを探しても困らなかった僕には無かった発想でした。この時ぐらいから今まで使っていたツールを見直し、ショートカットを覚え、真の意味でツールを使い始めました。

その3...複数人での開発

ある程度業務に慣れ、多少は周りに目を向ける余裕が出来た頃、ふと思ったのが複数人での開発はやはり個人のとは違うということです。

個人で好きなようにアプリケーションを作ってみたり、教本のコードを写経していた時というのは他人の目を気にする必要がなかったので、ファイル名・メソッド名・変数名が何であろうが自分が理解できれば関係ありませんでした。テストコードも大して書いておらず、フォーマッターやリンターなどは概念すら知らなかったです。

そんな僕だったので、Rspecをちゃんと書いたり、rubocopを通したりというのはBaseconnectに入って初めての経験でした。ですが、やはり複数人での開発を意識したコードは圧倒的に見やすく、レビューが入ることを考えても効率的です。

その4...マネジメントの意識が高い

業界の色なのでしょうか、Baseconnectに入社して一番驚いたのがこのマネジメントの意識の高さでした。僕自身昭和チックな指導スタイルの体育会系部活に長年所属していたこともあって、ちゃんとした本物のマネジメントらしいマネジメントを初めて受けて、本当に感動しました。

今、日次でデイリーミーティングを、隔週で振り返りを行っているのですが、部活をやっていた頃は怒鳴られ叫ばれは日常茶飯事でしたが、ここではそんな事は一切なく、失敗した時でも理論的に解決方法を探り、関係性の向上をモットーに改善を意識したサイクルを心掛けています。

人によっては昭和テイストのマネジメントが合う方もいると思います。しかし、僕の場合はこちらのやり方の方が確実に成長出来ていると思います。

最後に

恥ずかしながら、Baseconnectに入りたての感覚をそのまま書き綴ってみました。まだ実務を経験した事がない方には実際の様子が少しでも伝われば嬉しいです。つよつよエンジニアの方には、駆け出しのメンバーがどんなことを考えているのか少しでも伝われば嬉しいです。拙い文章の中、ここまで読んでいただきありがとうございました。

週刊データサイエンスなるデータ分析レポーティング企画をやってみた話

こんにちは。Baseconnectのオコドンです。 BI (BussinessIntelligence)ユニットに所属しており、データエンジニアとデータアナリストの両方の業務を行なっております。

今回の記事では、データアナリスト業務の中で生まれた施策である「週刊データサイエンス」なるものについて紹介したいと思います。 この施策はちょうど1年前くらいに僕が「こんな施策やりたい」と開発マネージャーにお願いして、チームの業務としてやらせてもらったものとなります。

週刊データサイエンスって?

ざっくり説明すると弊社が提供している営業活動支援サービスMusubuから取得した様々なデータを、アナリスト発信の切り口で分析して、毎週記事化する取り組みです。

どんな記事を書くの?

「◯月にリリースした新機能Aの使われ方について分析してみた」

みたいなタイトルで、分析の結果、分かったfactをTableauでグラフを作成したり、文章を書くことで表現しております。

記事テーマの決め方は色々ありますが、

  • 「たくさんの人に見てもらえるように社内でちょっと議論になっていることをテーマ化」
  • 「使ってみたい統計手法が上手く使える事例だったからテーマ化」
  • 「新機能がリリースされたからそれについてテーマ化」

などなどいろいろなパターンがありました。

記事の例

例を出した方がイメージしやすいと思うので2021/04/08刊行: メール機能が進化♪確かめるぜその真価♪の記事を紹介します。

この記事は弊社が提供しているMusubuサービスにテストメール配信機能や配信禁止リスト一覧機能が追加された直後に、速報的な形で出したものです。

  • 新しくリリースされた機能が期待通り使われているのか
  • リリースされた機能に相関がありそうな指標に影響が出ていないか

などを分析して記事にまとめました。

なぜ始めたの?

この施策は以下の4つの背景から始まっております。

データ活用意識の向上

プロダクトグロースへのデータ活用意識

プロダクトステータスをモニタリングするようなKPI作成や、自分たちの業務の最終結果であるプロダクトに対して、定量的なフィードバックを受け取る流れを作ろうとしていました。

意思決定の質の向上のためにはインプットの多角化が必要だと考えており、 仮説ベース、定性ファクトベース、定量ファクトベース、これらそれぞれのサービスステータスのインプット方法をプロダクトマネージメント層に保持してもらうためにも、定量的なサービスステータスのフィードバックを受け取る文化を作ろうと邁進しておりました。

またプロダクトグロースを担当するチーム以外にも「我々が売り出しているMusubuサービスが今どんなステータスなのか」をすぐに把握できるようにしたいと思っていました。

Rettyさんの新卒の方の記事に影響を受けて

Rettyさんの新卒アナリストの方が、毎日自身が分析したサービスステータスについてslackで一言語るという記事を見かけて、当時社内に対して定量視点での知見の共有ができていなかった僕の強い刺激になったのを覚えています。

当時のslack⬇︎ f:id:yuri_terao:20220225135718p:plain

統計技術・機械学習の試し打ちをする場の不在

当時、毎週kaggle勉強会という勉強会をチーム内で開催しており、kaggleへの参加だけではなく、効果測定の統計手法の勉強会や、統計の赤本や緑本の輪読会などを行なっておりました。

ここで勉強した手法なども、前述したプロダクトグロースに活用できていなかったので、トレーニングを兼ねていた部分もあります。

社内におけるBIユニットが実現できることの広報

  • どんなデータが現在使えるのか
  • 統計を活用したらどんなことがわかるのか

などBI領域でできることを他メンバーが把握できていないと、結果として社内からの依頼が減り、データ活用意識が下がるという負の連鎖を産んでしまうので、記事のアウトプットを通して、社内メンバーが「BIに色々頼んでみよう」と思ってもらえることが目的の一つでした。

週刊データサイエンスやってよかったこと

  • 社内にファンが出来ました
    • 事業企画室や開発チームの中に記事を楽しみにしてくれるメンバーがチラホラと出てきました。
  • より高度な仕事に繋がった
    • BIができることを広報する効果は出せたと思っており、例としては「会社データのスコアリングを作成してほしい」などの高度な仕事に繋がったと思っています。
  • 文章力・説明能力の向上
    • 読者には社内全メンバーを想定していたため、分析対象となるサービス内の特定ドメインに対する知識なんかを、記事の中でざっくり説明する能力だったり、統計の知識がないメンバーに対して「つまりこういうことがわかりました」と要約する能力がチーム内で身に付きました。

週刊データサイエンスやってうまくいかなかったこと

  • リソースが鬼のように取られる
    • 「テーマを決める➡︎データ探索・データ可視化を行う➡︎記事として仕上げる」この一連の流れはものすごいリソースが消費されて、 1人日以上は覚悟しなければならないくらいのリソース感でした。
  • 目指していたところまでの意思決定への影響は与えられなかった
    • 「明確に意思決定へ影響を与える」ことまで意識していましたが、まだそこまではいけなかったなあと思ってます。

読んでもらうために工夫したこと

  • 刊行当時はインパクトを出したかったため、毎日記事をパブリッシュしていました
    • 刊行開始した12月は1日に2つの記事を毎日書く施策を実行しました。
    • 通常業務と並行して記事を書いていたため、当時並走してくれたインターンの子と「あの時期は大変だったね」と今でも話します。
  • 共有時に一言コメントを付与
  • タイトルを興味を持ってもらえるような楽しい感じにする
  • インデックスを作成してバックナンバーが追えるようにしました

f:id:yuri_terao:20220225140305p:plain

書くために工夫したこと

依頼ベースではないレポーティング業務故にかなり書きづらいこともありました。

  • そもそもテーマ何にしたらいいかわからない
  • 決めたテーマを深掘りしても示唆が得られるかわからない
  • 結論の出し方も自分次第

BIインターンメンバーがこの課題感を言語化及び指摘してくれて コンサルの資料作成術を参考にしたフローを自発的に組んでくれたこともあり、一定この課題感の解消をしてくれました。

参考にした記事はこちら⬇︎

外資系コンサルが用いる「資料作成」という技術 | 日経クロステック(xTECH)

要するとレビューのフローを、スケルトンレビュー、ドラフトレビュー、フィックスレビューに分割する手法で

  • まずテーマだけ決める(〇〇機能についてなどのザックリしたレベル)
  • テーマに関するデータ探索を一通りする(Tableauでその機能テーマ周辺の情報をザックリ探索)
  • 探索結果とテーマをもとにどんな記事にしたいかをスケルトンレビューに出す
  • ケルトンレビュー結果から方向が定まったら記事の大枠を書く => 結論の方向性などまで
  • 大枠ができたらドラフトレビューに出す
  • ドラフトレビューが通過したら、細かい表現などを修正してフィックスレビューに出す
  • フィックスレビュー通過 => 記事として出稿

といった流れです。

週刊データサイエンスは現在どうなってるの?

当社のBIユニットは業務範囲として、ユーザー行動のログ化 - データエンジニアリング - データアナリティクスの全領域をカバーしております! 現在社員が僕1人とインターン2名という構成になっているので、データ基盤のフルリプレイスなどの業務が並行すると、どうしても記事に回すリソースが少なくなってしまいます。

結果として週刊リリースが難しくなってしまいまして、夏頃から月間データサイエンスにリネームされて、現在は毎月リリースの形を取っています。

発信はいいゾ

「なぜ始めたか」の項にさまざまな理由を羅列しましたが、一年通してやってみた感想としては データの説明、結果の解釈、サービスドメイン知識、統計、などなどを文章化して伝える技術をチーム全体で向上させられたことが何よりの価値だと思います。

アナリストのトレーニング・武者修行に是非やってみてください!

Baseconnectのデータ分析基盤変遷の歴史

挨拶

どうも!BaseconnectのBIチームに所属してます。おこどんです。 弊社BIチームは ユーザー行動のログ化 <=> データ収集・蓄積 <=> データ可視化・分析までの領域を社内で担当しております!

担当領域の都合から、クライアントサイドログ収集関連リソース, ETL, データレイク, データウェアハウス, BIツールなどなどデータ分析基盤周りのインフラリソースの作成と管理も担当してまいりました。

立ち上げから2年ちょっとの歳月が経ち構成も一旦落ち着いたので、弊社の分析基盤周りの構成の歴史・変遷を今回記事にすることとしました!

(※社員1人インターン1,2名のチームでずっと作ってきたため、人的リソース依存の課題感や技術選択があります。ベストプラクティスの参考としてではなく、失敗の歴史を温かく見守ってもらえたら幸いです)

黎明期(2020/02~) 

〜データレイクという概念の不在〜 f:id:yuri_terao:20220309233024p:plain

どのような変更を加えたか

  • パフォーマンス監視及びReact製SPAのフロントログ収集を目的としてElasticAPMを導入しました。

    • APMのサービスエージェントのログにアカウント情報を載せて、バックエンド・フロントエンド共通のロギングツールとして運用しました。
      • 尖った使い方だと思うので、これは別で記事化出来たらと思ってます。
  • ETLツールのLogstashをEC2内で運用しました。

    • 弊社がストレージ用途としても活用しているElasticsearchのデータをDWHに転送しました。
    • ElasticAPMによって収集されたクライアントサイドユーザーログをElasticsearchからDWHに転送しました。
    • 弊社のアプリケーションのメインDBであるNeo4jのクエリAPIから取得したデータをDWHに転送しました。
  • ETLツールのembulkをEC2内で運用しました。

    • アプリケーションで活用しているRDS内のデータをDWHに転送しました。
  • DWHにBigQueryを採用しました。

  • BIツールにTableauを採用しました。

この構成になった理由

分析基盤の構成自体が存在しなかった状態で入社して「数ヶ月以内に何かデータが見られるようにする」ことを目標にしていました。 1人目データ人材として入社しており、データが見られるようにしないと存在価値を発揮できないと考えていた焦りと当時の経験不足故にデータレイクなんてものは存在していませんでした。

  • ETL

    • 国内では珍しいかもしれませんがfluentdではなくLogstashを採用しています。
    • 弊社はElasticsearchをストレージ目的としてもかなり活用しており、Elastic社のデザインパターンであるELK構成で推奨されているLogstashの採用をした方が、何かと良いことがありそうと考えての採用でした。
      • 現在の感想は「fluentdでもLogstashでもどっちでも良いなあ」です。
  • DWH

    • マネージドで1人体制でも管理が楽そうな点とパフォーマンスなどについて評判が良かった点から、クロスクラウド構成にはなりますが、RedshiftではなくBigQueryを選択しました。
  • ログ生成

    • バックエンド, フロントエンドの両アプリケーションのパフォーマンス監視ができるツールの検討が社内で既に行われており、ElasticAPMのreactエージェントであればページ遷移やコンポーネントのマウントまでをログ化可能なことが技術調査されていたので、その導入とカスタムログの作成などを行いました。

この構成で得られた学び

APM as ログ基盤構成について

APMツールのログにアカウント情報を付与してユーザー行動ログとして扱ってみる」というほぼ前例が無いAPMツールの使い方をしてみました。

  • フロントエンド、バックエンドで同様の形式のログが発行されて加工などが楽な点
  • ログの格納場所が統一され、パイプラインの数が1つで済む点

などなどプラスポイントもあったので、この使い方はそこまで悪くなかったのでは?と考えています。

データレイクが無いと

日ごとに取り込んだテーブルに*_YYYY_mm_ddのようなsuffixを付けて全て保存して、BigQuery内に擬似的なデータレイク層を作っていました。 dbtやdataformのようなデータモデリング技術を導入できていなかったので、BigQueryのスケジュールクエリでデータレイク=>データウェアハウスの変換を全て書いており、保守もしづらくカオスな状態でした。

データレイク作成(2020/06~)

f:id:yuri_terao:20220309233116p:plain

どのような変更を加えたか

  • GoogleCloudStorageをデータレイクとして採用して、ETLのデータ輸送先をBigQueryからGCSに変更しました。

  • GCS to BigQueryの転送はCloudDataflowで行いました。

    • CloudDataflow内の定義はApacheBeam JavaSDKで記述しました。
  • CloudDataflowのジョブをキックするための関数をCloudFunctionで作成しました。

  • Cloud Functionの定期実行はCloudSchedulerからCloudPubSub経由でメッセージを投げる形で起動させました。

この構成になった理由

  • 何やらデータレイクなるものがあれば先述したBigQueryのカオスな状態が解決されるらしいとのことで、BigQueryとの親和性が高いGCSをデータレイクとして採用しました。

  • データレイク => データウェアハウスのデータ輸送はCloudDataflowで行いました。DataTransferServiceなども考慮したのですが、Transform処理(データのマスクなど)を挟むことが出来る点や動的に取得元テーブルを宣言できる点などから、Cloud Dataflowに軍配が上がった形です。

CloudComposer高すぎ問題

Cloud Dataflowの実行にCloudFunction, CloudPubSub, CloudSchedulerの3リソースの構成をわざわざ組まなくても、DataflowのマネージドサービスであるCloudComposer使えばいいじゃんと思われるかもしれません。

Cloud Composerを使わなかった理由は試験的に運用してみたらとても高かったという金銭的な理由からです。 CloudComposerの使い道が当時はデータレイク<=>DWH間の輸送の用途しかなかったため、TooRichだと感じて採用を見送りました。

この構成で得られた学び

  • やりたいことが実現できる技術 < 理解しやすい技術にしないと属人化が進む

    • DataflowをApacheBeam JavaSDKで書いたのですが、難しくて保守しづらいものにしてしまったのが失敗だと感じています。
    • PythonSDKには存在しないNestedValueProviderオブジェクトを使って、動的にパラメータを取得してコード内に反映する実装をしたいがために、pythonではなくJavaを選択しており、キャッチアップが難しい技術選択をしてしまったと感じています。
    • 導入をした僕と当時のインターンの2人だけがApacheBeamパイプラインを作れるが、後からジョインしたインターンメンバーなどはパイプラインを作れないといった状況になり、同じチーム内でも技術格差が生まれてしまいました。
  • データレイクができて感じたメリット

    • GCSに日付ごとのマスターデータを格納して、BigQuery内のデータは最新のテーブルのコピーを持つ形としたので、BigQuery UI上でのデータの一覧性が著しく上がりました。
    • マスターデータをBigQuery上で持つ形では無くなったため、元の構成に戻せる安心感を持ちつつ、立ち上げ時のぐちゃぐちゃな構成のBigQueryに対して、データセットの整理やパーティショニングなどの構成変更を行えるようになりました。
    • DataflowのETLの段階で個人情報にあたるものなどに列単位で閲覧制限をかけることで、BigQueryの権限を他者に渡しやすくなりました。

dataformの導入 (2021/01~)

f:id:yuri_terao:20220309233613p:plain

どのような変更を加えたか

  • DWH内のデータモデリングツールとしてDataformを採用しました。

    • Dataformを使うことで、BigQuery内でダッシュボード表示や特定の計算を走らせるためのテーブルをデータマート層として定義しました。
  • BigQuery内の100個くらいあったスケジュールクエリを根絶しました。

  • Dataformを使うことで依存関係が明示的に示され、複雑なロジックも保守性が高い状態で書くことができるようになりました。

    • コード管理されるおかげで、SQLのレビューも徹底されるようになりました。

この構成になった理由

  • 確か当時「DataformというBigQueryを便利にするツールがGoogleに買収されて〜」みたいな話を聞いて、こんな便利なものがあるのかと感動して導入を決定したと思います。

    • 恥ずかしながらデータモデリングツールという存在をこのタイミングで初めて認知しました。
    • なんでdbtじゃないの?という疑問が湧くと思いますが、純粋にdbtをこの時知らなかったので選択肢にも上がりませんでした。
  • スケジュールクエリでのDWH内データ変換が地獄すぎた。

    • スケジュールクエリは一覧性が悪く、管理もしづらく悩みの種でした。

この構成で得られた学び

  • データモデリングはBIの最重要業務。良いこと尽くし

    • 複雑な定義のKPIなどのテーブルも、テーブルやViewに分割することで理解及びレビューをしやすくなる。
    • 更新タイミング、Table化、View化などの管理すべき項目が全て定義可能。
    • テストを書くことで、データ欠落やロジックの意図せぬ変更などを補足可能。
    • テストユーザー除外処理やタイムゾーン変更処理などの共通する処理を作ることで、今後の開発の高速化に繋げられる。
  • dbtでもdataformでもどっちでも良さそう

    • 1年以上dataformのSQLX書きまくってますが困ってないので、どっちでもやりたいことできるんだろうなあと思ってます。
    • ただdbtのユーザーコミュニティの盛り上がりは羨ましかったです

事件:Neo4jがREST APIを廃止 (2021/06~)

アプリケーション開発の都合から、弊社アプリケーションのメインDBであるNeo4jがver4.0に更新されたのですが、この更新によってboltプロトコルによる通信のみが許可される形となり これまで活用していたREST APIが使えなくなることになりました。

手持ちのETLツールであるembulkやLogstashなどではboltプロトコルによるNeo4jからのデータ取得をサポートしてくれるようなものは存在せず、既存のETLツール以外の何らかのデータ取得手段を作成する必要が発生してしまいました。

データレイクお引っ越し・分散処理・インフラのコード管理(2021/09~)

f:id:yuri_terao:20220309233736p:plain

どのような変更を加えたか

  • AWS内でBIのデータエンジニアリングに関するリソースを別アカウントに切り出しました。
  • Terraformによる全BIリソースのコード管理を実施しました。

    • IAM, ネットワーク, ETL, データレイクなどのコード管理をしました。
  • ETLツールをAWS Glueに一本化しました。

    • Neo4j ApacheSpark connectorを使うことで、Neo4jからのデータ取得を可能としました。
    • GlueのSpark定義ファイルはScalaで記述する方針としました。
  • データレイクをGCSからS3に変更しました。

この構成になった理由

  • BIリソースの別アカウントへの切り出し

    • これはBI発信ではなくSREの方のAWSアカウント設計に則ってリソースを引っ越しました。
    • この辺りのAWSアカウント設計周りなどは SREの方が記事化してくれると願っています。
  • Terraformによるコード管理

    • 長年連れ添ったインターンの子が退職することとなり、BIリソースについて知識を持っているメンバーが僕だけになってしまったので、属人化とリソース枯渇が顕著な問題になってしまいました。
    • また、インフラに強みがあるわけでも無いため、社内メンバーから僕がインフラを触ることに対する不安の声が結構上がっていました。
    • そこでアカウント分割を機にコード管理をすることで、属人化の解消、インフラリソースの透明化、BI業務の安全性の担保を行いました。
  • ETLとしてGlueを採用

    • Neo4jからのデータ取得が可能なドライバーがApacheSparkくらいでしか見つけることができず、ApacheSparkを動作させられる環境が必須要件でした。
    • 管理するコストはできるだけ少なくしたいため、フルマネージドなサービスを検討しました。
    • ETLツールは複数あるとキャッチアップコストや管理コストがかかると考え、 ETLを全てGlueに統一することにしました。
      • ApacheSparkが動作環境になるので、ほぼ全てのデータソースへの接続が可能となりました。
    • ETL処理の分散処理化
      • データが大きすぎてETLが動かなくなるといった事故が時々起きていたのですが、スケーラブルな分散処理にすることで防止しようと考えました。
    • pysparkだとできないことがあったり、Scalaを触ってみたかったり、pythonだとDataframeの変換の時にパフォーマンスが良くないらしいとの噂を聞いたのでScalaでコードを書く方針とした。
  • データカタログの作成

    • データレイクに格納されたデータはGlueCrawlerによってカタログテーブルに登録する方式としました。
    • カタログテーブルを指定してデータ輸送ができるので、Glueのデザインパターンに寄せたコードを書くことができるようになります。
  • データレイクをS3に移行

    • これまでは「データレイクとは分析のための生データを保存する場所」という考え方だったのですが、より役割を拡張して「データレイクとはアプリケーションの種々の生データを保存する場所」としました。
    • サービスが稼働しているAWS環境のS3に変更することで、AWSマネージドなデータ輸送の仕組みが活用でき、上記のようなデータレイクの実現が容易になると考えました。

この構成で得られた学び

  • Glue高い

    • AWSはDPU (DataProcessingUnit) の起動時間に比例して課金されます。
    • プロセスの立ち上がりにも結構時間がかかるので、小さいボリュームのデータ輸送であっても、立ち上がり時間などを考慮すると結構な金額が発生することになってしまいます。
    • マネージドサービスなので覚悟はしていましたが、Logstashやembulkの維持費と比較するとかなり高額なため、ワーカー数のチューニングや取り込み回数の見直しなどの考慮点が新しくできました。
  • Spark難しい

    • RDD, DataFrame, DynamicFrameなど、Glue上で扱えるデータオブジェクトの種類が色々あって理解が最初難しい。
    • Dataflowの時の反省を生かさずに、pythonではなくScalaで書いてしまったため、キャッチアップのハードルがpythonと比較して結構上がってしまったなあと反省しています。
    • 静的型付け言語なので、「大規模データ基盤を安定したものにしたい」意図には沿っているかなと思ってます。
  • ETLツールを1つに統一したことに意味はあったのか

    • ETLという役割を複数ツールで実行するのではなく、スケーラブルでマネージドな1つのリソースにまとめたら無敵なのでは?と考えたのですが、先述した料金の問題などを考えるとそこまでのメリットを感じられていないのが現状です。
    • 管理コストというか意識するべきことが減ったので、少人数でも基盤の運用はしやすくなったことは明確なメリットとして感じています。
  • Terraform鬼便利

    • 導入目的として挙げていた、「属人化の解消」「インフラリソースの透明化」「BI業務の安全性の担保」は全てリソースのTerraform化によって解消されたと考えています。
    • モジュール化などリファクタリングすべきことはまだまだありますが、同一リソースの作成などは思考リソースほぼ使わずに実装できるようになりました!

Lookerの導入 ( 2021/12 ~ )

f:id:yuri_terao:20220309233252p:plain

どのような変更を加えたか

  • BIツールをTableauからLookerに変更しました。

この構成になった理由

  • データ基盤が一定整ってきたが、ビジネスサイドのメンバーでSQLを叩けるメンバーはおらず、データ活用をしているとは全く言えない状態でした。

    • ダッシュボードや分析レポートなどは全てBIチームが出力している状態でした。
  • いざビジネスサイドに活用してもらおうと考えても「BigQueryデータの整理」「データにラベリング」「テーブルの関係性の説明」「SQL講習の実施」など途方もない道のりでした。

  • Lookerによるデータラベリングと探索環境の提供によって、これまでできなかったデータ活用を推進できると考えました。

この構成で得られた学び

  • Lookerの圧倒的なビジネスインパク

    • Tableauを使用している時は「使えるようになりたい」と名乗り上げるメンバーも現れなかったのですが、Lookerでの日本語ラベリングされたデータと探索環境を紹介することで、データ探索希望者が複数人出てきました。
    • これまでどんなアウトプットであれBIチームが手を動かしていたのですが、LookMLを作れば作るほど、データ探索者が自身でアウトプットできる環境が整うため、BIがより本質的な業務に集中できるようになりました。
    • 実際にデータを触ってもらうことで、「こんなものも見れるようにならないか」とBI以外のメンバー発信による環境作成依頼が来るようになりました。
  • Looker導入の工数

    • Looker定義用ファイルであるLookMLを書いていくのに時間がかかると考えていたのですが、そこまで時間はかかりませんでした。
      • 事前にDataformを活用することで、データモデリングをある程度のレベルまで行えていたからだと思います。
  • LookMLは考えることがいっぱい

    • 一通り作ることができたのですが、適切な権限設計、キャッシュとスケジューリング、テンプレートフィルタやリキッドフィルターなど、データ活用者がより便利に使えるようにするために、考慮したりやることが山積みです。
    • LookMLと Dataformの責任分界点、「どこまでをどっちでデータモデリングするか問題」は永遠のテーマ感があります。

まとめ

弊社データ基盤のNext To Do

  • データ発生からデータ閲覧可能になるまでの時間の短縮

    • データ基盤のSLIを「データが見られるようになるまでの時間」と定義づけるならば、その短縮に対するアクションはほとんど打てていない状態です。
      • 直近だとデータ取り込みジョブのイベントをフックにして次のイベントを起動するような構成を実装中ですが、データモデリング層やダッシュボード表示までを含めた部分は、改善どころか実態把握からのスタートになりそうです。
  • リバースETL

    • BIチームでは、弊社内で製造したデータを統計的に評価するモデルなんかも作成したりしています。 モデルの評価結果なんかをサービスに還元するようなリバース ETLのような機能の立案と構成作成には挑戦してみたいです。
  • データガバナンス

    • 「誰がどのデータを見られるべきか」といった権限設計は作り切れておらず、どのメンバーが見ても問題がないデータのみを提供している状態です。
    • データガバナンスの設計をしっかりとして、アクセスするべき人が自らの意思決定のために必要なデータにアクセスできるような、権限管理の設計は詰めていきたいです。

BIはいいゾ

今回の記事で紹介した通り、BIという領域に絞っただけでも GCP/AWSの基礎的なリソース, SQL, ApacheBeam(Java), ApacheSpark(Scala), Dataform, Terraform, LookMLなどの様々な技術が弊社内では使われています。 最近ホットな領域であるため、新しくやるべきことが次から次に出てきて楽しいです。 読者の方々もこれを機にBIのエンジニアリング部分に興味を持ってみてはいかがでしょうか?

(まだまだやりたいことはありますが、リソース的に限界なので、興味ある方は是非採用ページから応募してください)

meety.net herp.careers

Regional Scrum Gathering Tokyo 2022に参加しました!

こんにちは、エンジニアの富田です!

2022年1月5日〜1月7日まで開催されたRegional Scrum Gathering℠ Tokyo 2022に参加してきました!

twitter #RSGT2022 #RSGT2022 hashtag on Twittertwitter.com

[Regional Scrum Gathering Tokyo 2022のスライドまとめ #RSGT2022

scrummasudar.hatenablog.com


Regional Scrum Gathering Tokyo(RSGT)とは?

「Regional Scrum Gathering Tokyo」は、日本最大級のアジャイル関連のカンファレンスです。 毎年、1月上旬に東京で開催されます。

去年はオンラインで参加したのですが、今回は会社から参加費を出してもらい、現地参加しました。

コロナ禍でオフラインの集まりにほとんど参加していなかったのですが、久しぶりに大勢の人と話すことが出来、3日間、どっぷりとアジャイルの世界に浸かることが出来ました。

また、オンラインの参加者はDiscordで活発にやりとりされていたのですが、そちらを見て感想を楽しんだり、投稿内容から知識を得ることもできました。


参加してみてどうだったか?

f:id:yuri_terao:20220205215547p:plain

一番、印象に残っているのは、プロダクト・スプリントのそれぞれのゴールの話でした。

現在、私のチームではスクラムで開発を行っているのですが、スプリントゴールがあいまいになりがちでした。

スプリントゴールは、プロダクトゴールから逆算して、直近(現在のスプリント)で実現すべきものかなと思います。

プロダクトゴールがぼやけてしまっているのが、スプリントゴールにも波及していることが理解出来、帰ってきてからプロダクトオーナーとこの点を話しました。

また、システムコーチングを体感するワークショップにも参加しました。 オフラインのワークショップも久しぶりなので、かなり緊張しましたが、楽しく実体験として学ぶことが出来ました。


参加後

参加後は、レポートを作成して社内に公開したり「共有会」を開催しました。 「共有会」はレポートを元に、1日目から順に登壇の内容や感じたことをを報告していきました。

RSGTの3日目は、毎回Open Space Technology(OST)が開催されるのですが、その動画を見ながらどんな風に開催されるのか共有しました。

社内では、まだアジャイル開発が広まっているわけではないので、上記のような活動で少しずつでもアジャイルのファンを広めていこうと企んでいます 😎

来年は、社内の他の人も巻き込んで参加出来ればと思っています!


ちなみに、参加中、東京は、歴史的な雪景色でした。

f:id:yuri_terao:20220205215450p:plain

Baseconnectではエンジニアメンバーを絶賛募集しております! もしご興味をお持ちいただけた方がいらっしゃいましたら、下記のリンクよりぜひカジュアルにお話しさせていただけましたら嬉しく思います!

meety.net

herp.careers

課金システムをマイクロサービス化したお話

はじめに

こんにちは、Baseconnectのエンジニアインターンの東野です!

20xx年某日、僕はあるプロジェクトにアサインされました。その名も「課金システムマイクロサービス化」プロジェクトです。

このプロジェクトにはもちろん社員メンバーの方と一緒に携わらせてもらったのですが、今回代表して、Musubuの課金システムをマイクロサービス化した話を執筆させていただくことになりました!

まずMusubuって?という方にはぜひこちらを見ていただけたらと思います。 (ざっくり一言で説明するなら「営業支援ツール」になります。)

もともとMusubuはモノリシックなシステムだったのですが、課金システムをマイクロサービス化しようという流れになり、プロジェクトが開始しました。

課金システムの主な機能

  • 定期課金情報の管理
  • 支払情報の管理
  • カードへの請求や請求書払いなどの支払いに関する処理です

システム構成図

まずは大まかな課金実装のシステム構成は以下の通りです。

モノリシックな状態 f:id:yuri_terao:20220217141023p:plain マイクロサービス化後の状態 f:id:yuri_terao:20220217141037p:plain

端的に言うとMusubuでカード決済代行サービスの処理を実行していたり、データベースの中に定期課金や支払いに関する処理を保持していたものを切り離しました。

課金システムのER図

次にどのようなデータがあるかについてです。以下の他にもモデルはありますが、概ねの流れを理解するのに必要な部分を抜き出したいと思います。 f:id:yuri_terao:20220217141049p:plain

クライアントデータ

クライアントデータは、課金システムからみた外部システム、つまり今回でいうとMusubuになります。Musubu以外のサービスでも利用できるようにクライアントデータという名前で抽象的な概念として情報を持っています。

顧客データ

顧客データはユーザー情報のうち請求処理に必要な情報のみを保持しています。

課金データ

ユーザーの定期課金の情報を保持しています。次の支払い時期や月額単価などの情報を保持しています。

購入データ

毎月発生する定期課金の支払いや個別での支払いの情報を保持しています。

課金登録時の処理

f:id:yuri_terao:20220217141138p:plain

  1. Musubuのユーザーが定期課金(有料プラン)登録
  2. Musubu内でアイテム(企業情報を取得することができる件数等)付与
  3. 課金に関するデータを作成
  4. カード決済代行サービスへカード情報作成と支払い処理をリクエス

この2~4の処理はすべて同一トランザクションにしています。 マイクロサービス化されているので、外部への処理の委託をトランザクションの最後に実行して、失敗した場合(レスポンスのステータスが2xx以外のとき)ロールバックするという風にすると、アトミックな処理に対して一貫性を保つことができます。

しかしリクエストの結果からさらにデータを更新する必要がある場合、トランザクションという方法で完全に一貫性を保つことはできませんので、リトライ等で対策する必要があります。

契約更新時の請求処理

f:id:yuri_terao:20220217141152p:plain

  1. スケジューラが支払い処理を開始させる
  2. 更新日に達した課金データに対して支払い取得し支払い処理を実行します
  3. 支払い処理の成否をMusubuに通知して、Musubu側でのユーザーにアイテム付与や利用停止などの処理を行います

わかったこと

マイクロサービス化で難しい点

  1. データの整合性の担保
  2. 複雑な条件での検索(データが分散しているため)
  3. 各システムの責務の切り分け方(これが実装のしやすさや安全性に大きく関わってきます)
  4. 外部システムの知識を汎用的に表現すること(責務の切り分け方が悪い場合もありますが、どうしても外部システムの知識が必要になることがあります)

データの整合性の担保

課金登録時の処理の説明のところでも出てきていますが、どうしてもアトミックな処理が複数のシステムの処理をまたがってしまい、ぶつ切りになってしまいます。そんなときはアトミックな処理をできるだけユーザーにとってストレスのない単位で切り分けて、すぐに検知して正しいデータに戻せるようにする必要があります。

複雑な条件での検索

データが複数のDBに分散しているため、それぞれのDBにしかないプロパティを組み合わせた条件などで検索するには少し工夫する必要があります。一例として片方のデータベースにメタ情報として外部のシステムのデータを保持する方法があります。ただメタ情報をもたせすぎるとマイクロサービスではなくサブシステムっぽくなってしまうので注意が必要です。

各システムの責務の切り分け方

マイクロサービスは外部システムの知識を減らすことで、他のシステムでも利用できるようになったり、コードがシンプルになるというメリットがあります。なので責務を切り分けたタイミングで、外部システムの知識が混ざるような構造になっていると、サブシステムのようになってしまい他のシステムで利用できないようになったり、実装が複雑になったりしてしまい、あまり意味がなくなってしまうこともあります。

外部システムの知識を汎用的に表現すること

どこまでしっかり責務を切り分けたとしても、やむを得ない事情で外部システムの知識を保持する必要がでてくることがあります。そんなときはできるだけ汎用的にメタ情報(外部システムの情報)を表現することが大切ですが、その結果万能モデルみたいになってしまいコードやデータが複雑になりすぎてしまうことがあるので、できるだけ利用しないように運用を工夫するなどの対策をしなければならないです。

終わりに

今回は課金サービスの実装した経験を書かせていただきました。自分でもこんなにも重要なプロジェクトに参加させていただけるとは思っておらず、大変貴重な経験となりました。皆様にとって少しでも役に立てるような記事になっていたらとても嬉しく思います。ありがとうございました!

Baseconnectではエンジニアメンバーを絶賛募集しております! もしご興味をお持ちいただけた方がいらっしゃいましたら、下記のリンクよりぜひカジュアルにお話しさせていただけましたら嬉しく思います!

meety.net herp.careers

Amazon SageMaker BYOCとAWS Step Functionsで推論エンドポイントを構成する

はじめに

この記事はAWS Summit Online 2020で登壇した内容ですが、テックブログのため再度まとめ直した記事です。

目的と課題

Baseconnectでは500万件ほどの企業情報を保持しており、その内140万件ほどをサービスで提供しております。 その中から利用者が欲しい情報を探し出すために、検索軸や検索性能を改善し続けています。 ただ、検索で探し出すのではなく、利用者自身が保持しているリストと突合させて情報を補完(名寄せ)したいという要望があり、それに応えるためにAIを補助的に入れることを目的としました。

進めるにあたり、以下のことを意識して進めました。

  • ゴールはどのような状態か
  • 精度の基準はどうするか
  • どのような手法で機械学習を行うか

取り組み

ゴールはどのような状態か

今回は既にサービスで提供している部分をAIでリプレースすることを目指しました。

これまでに、利用者の手持ちの営業先リストがアップロードされた際に140万件の企業情報との名寄せを実装済みでした。
そのため、ゴールとしては利用者としては意識すること無く、バックエンドをAIへリプレースすることで利便性の向上を目指しました。
精度の基準はどうするか

今後入力項目や名寄せ対象が増加されることも考えられましたが、まずは既存の仕組みでの精度よりも向上させることを基準としました。

※入力データの状態により異なるため、サンプルデータを用意 ※取り組み前の時点で既存の機能でサンプルデータを用いた精度は名寄せ率が55%ほど

どのような手法で機械学習を行うか

機械学習として教師あり、教師なし、強化学習とありますが、大きくはどれで(もしくはどの組み合わせで)取り組むかについて検討しました。(以下、検討の一部)

  • 教師あり
    • 名寄せ先となるデータが140万件あり、それらは日々増加や更新が行われている
    • 正解が140万件となるのは現実的では無さそう
  • 教師なし
    • クラスタリングを活用するのは一定の効果がありそう
    • if文などのロジックが増えてきたら、最初からロジックで作るのとあまり変わらない
  • 強化学習
    • 名寄せした結果が求めているデータに近いかどうか判断をすることで、名寄せ先のデータに変動があっても耐えられる仕組みに出来そう

ただ、ブレストの中で教師なし学習も今回の目的の中で活用は出来そうと話はしていました。 クラスタリングなども間に含めて多段的にAIを使うことも考えましたが、まずはシンプルに強化学習でどこまで精度が出せるのか取り組んでみました。

取り組み内容

具体的に取り組んだ内容です。

全体構成

Amazon SageMakerをコアに使うことを考え、そのフローをどうするかとして全体を設計しました。

当初推論はLambdaで構成しようとしてましたが、メモリの制限や起動に時間がかかる(プロビジョニングにすると高くなる)ため、Amazon SageMakerの利用を選択しました。 Amazon SageMakerはモデルの学習や推論エンドポイントの提供、またマルチエンドポイントで利用者毎のモデル提供など将来的に展開を考えられそうでした。

また、名寄せ先となるデータは変動が考えられるため、今回はデータベースを直接参照するという手段を取りました。 なお、学習・推論と検証する中でデータベースのパフォーマンスも負荷がかかりすぎないか監視しながら実施しました。

学習とDocker Imageの作成

Amazon SageMakerで推論エンドポイントを利用するために、そのコンテナ構造に合わせています。

◆ディレクトリ構成
project-root/
  ├ opt/
  │  └ ml/
  │      ├ code/
  │      │  ├ agent.py
  │      │  ├ environment.py
  │      │  ├ train.py
  │      │  ├ eval.py
  │      │  ├ handler.py … Amazon SageMakerの推論API用
  │      │  ├ nginx.conf … Amazon SageMakerの推論API用
  │      │  └ serve … Amazon SageMakerの推論API用
  │      │
  │      ├ failure/
  │      ├ input/
  │      │  ├ config/
  │      │  ├ data/ … 学習用データ
  │      │  └ eval/ … 評価用データ
  │      ├ model/ … 学習済みモデル
  │      └ output/ … 評価結果
  ├ build_and_push.sh
  ├ buildspec.yml
  ├ Dockerfile
  └ requirements.txt

Amazon SageMakerにもNotebookがあり、そこでもコーディングと実行は出来るのですが、今回は先に開発端末で試していたこともあり開発端末にて学習/評価を実行し、GitHubのPullRequestでAWS CodePipelineを利用してDocker Imageを作成(AWS CodeBuildでイメージを作成し、Amazon Elastic Container Repositoryへプッシュ)するようにしました。

Docker Imageの作成はサンプルを参考にしましたが、一部変更しました。

  • DockerHubの tensorflow/tensorflow:2.0.0-py3 を利用
    • その当時の新しいバージョンを利用したかったため
  • 学習済みモデルもDocker Imageに含める
    • パイプラインにAmazon SageMakerでトレーニングも含めることも出来たのですが、ひとまず開発端末でモデル作成まで行っていたため
  • Docker Image内にDBの接続情報も環境変数で定義
    • 秘匿情報を限定的に参照としたく、暫定的に進めたかったため
  • Docker Image内でもPythonライブラリをセットアップ
    • 後述のhttp serverもサンプルとは異なる方式を取ったため
  • tensorflow-model-server は利用しない
    • 深層強化学習で作成したモデルがtensorflow-model-serverでそのまま使えなかったため
    • 学習済みモデルのServingにはPythonのHTTServerを利用
Docker Imageの動作確認

まず開発端末で動作を確認したかったため、以下のコマンドでDocker Imageの作成とコンテナの起動を行いました。

$ docker build -t demo . --build-arg DB_HOST=”xxxxxx” --build-arg DB_USER=”xxxxxx” --build-arg DB_PASS=”xxxxxx”
$ docker run -p 8009:8009 -it demo serve

ECRの設定まで済んでいる場合は以下でも出来出来ます。

$ ./build_and_push.sh
$ docker run -it 8009:8009 -it {account}.dkr.ecr.{region}.amazonaws.com/demo:latest serve

動作イメージは以下のようになっています。サンプルで作成するとエンドポイントは決まるので、そこに対してPostmanなどで確認しました。

AWS Step Functions Data Science SDKの利用

Amazon SageMakerで推論エンドポイントを更新するまでを自動化するためにAWS CodeBuildからAWS Step Functionsをトリガーするようにパイプラインを構成しました。 そして、AWS Step Functionsを構成するためにAWS Step Functions Data Science SDKを利用しました。 SDKPythonで利用でき、notebook上で記述と実行を試しながら進めました。

AWS Step Functionsの構成としては以下となっています。

各ステップで気にした点は以下です。

[モデル] ・独自Docker Imageでは学習済みなのでトレーニングは行いませんでした ・データベースへの接続が必要なのでVPC内で構成する必要がありました ・上記2点を考慮して構成する場合はSDKではダメでAWS Lambdaを構成に含める必要がありました

[エンドポイント設定] ・モデルの指定 ・インスタンスタイプを ml.t2.medium(最小)で構成

[エンドポイント] ・既存のエンドポイントを新しいエンドポイント設定で更新するように構成

[その他] ・SDKではAWS Step FunctionsのCreate or Updateは出来なかったので別々に構成しました ・AWS Step FunctionsではエンドポイントのCreate or Updateは出来なかったので別々に構成しました ・SDKのドキュメントはstableだと詳細の記載が無かったのでlatestで見ていました

推論エンドポイントの確認

まず、Amazon SageMakerのエンドポイントはsig-v4で保護されており、通常のREST APIのように呼び出すためには手順が必要なため、boto3でクライアントを構成して推論エンドポイントの確認をするようにしました。 https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_runtime_InvokeEndpoint.html https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html

aws cliに同梱されているboto3で動作確認した サービスから利用する場合も各言語で提供されているaws-sdkのboto3で実装

呼び出しサンプル(Python)
import json 
import boto3 

sagemaker_runtime = boto3.client("sagemaker-runtime") 

data = dataset[start : start + SPLIT_SIZE] 
headers = { "Content-Type": "application/json" }
payload = { "mode": "bulk_linkage", "clients": data }

# 推論エンドポイントにリクエスト 
response = sagemaker_runtime.invoke_endpoint( 
                        EndpointName="demo-endpoint", 
                        Body=json.dumps(payload), 
                        ContentType="application/json", 
                        Accept="application/json" 
) 

decoded_response = response["Body"].read().decode() 
# bodyがstringになっているのでjson化 
result = json.loads(decoded_response) 

結果

評価と改善を繰り返すことで既存の名寄せ率が23%向上しました。(サンプルでの結果)  既存:55%  新方式:78%

その後一部改善などを行い、以下の精度になっています。
 名寄せ率:77%
 正解率:86% (後から確認したところ、取り組み時の正解率はおおよそ65%ほどでした)

また、リポジトリを分離でき、マネージドサービス上にDevOpsを構築できました。 既存の処理はプロダクトと同一リポジトリ内に実装されていたため、変更をリリースする際にもプロダクト全体のリリースとなっていた点が解消されています。 リリースの運用についても、分離する際にAWS Step Functionsなどを利用することで軽減した状態で構成することが出来ました。

さいごに

今回の取り組みでAmazon SageMakerを用いた本番環境までの流れを把握出来たので、次は監視やスケール、Amazon SageMaker上での学習もDevOpsに組み込んで最適化していくとさらに他の領域も展開しやすくなると考えています。

また、SageMakerのマルチエンドポイントは現在のサービスにもフィット出来そうなので、自社で作り上げる膨大なバックエンドのデータを用いてエンドユーザー毎に最適なAIを届けることも取り組んでいければさらに価値が出せるのではないかと思います。

名寄せの精度という点では、今回は深層強化学習を利用したところですが、他にも辞書の改善や多段的な推論など含めてアプローチできることはあるので、そういうところにも手を入れることによって向上出来るのではないでしょうか。

Baseconnectではエンジニアメンバーを絶賛募集しております! もしご興味をお持ちいただけた方がいらっしゃいましたら、下記のリンクよりぜひカジュアルにお話しさせていただけましたら嬉しく思います。

meety.net

herp.careers

Baseconnectプロダクトの技術スタックのご紹介

こんにちは、Baseconnectでエンジニアをしている米丸です。開発部門の組織改善や採用ロールを担当しています。この度、情報発信と業界貢献を目的にテックブログを始めることになりました。パチパチパチ!

Baseconnectでは現在、法人営業向けのクラウド型企業情報データベースサービスであるMusubuとその集客の役割を持つBaseconnect.in、協業企業向けのPartnershipAPIの3つのプロダクトを運用しています。

また、外からは見えませんが、社内向けにMusubu管理システムと企業情報登録システムといったものが存在します。一発目のテックブログということで、今日はこれらの弊社プロダクトの主要な技術スタックをご紹介したいと思います。

私自身はまだ昨年10月にBaseconnectに入社したところなので、社歴のあるエンジニアメンバーヒアリングして導入経緯なども含めまとめた内容になります。

前提として、Baseconnectでは特定の技術にとらわれずスピードや保守性を重視し、エンジニアで議論をしながら技術選定を行ってきました。バランスを見ながら責務を切り分けられるものを対象にマイクロサービス化を進め、サービスに合わせた技術を選定してきたことで、いくつかの技術をくみあわせた技術スタックとなっています。

技術スタックや利用ツールの全体像としたは以下のようになっています(Baseconnectのエンジニアリングについてまとめた Engineering Recruite Book より抜粋したものです。興味がある方はこちらもぜひご一読ください)。

f:id:yuri_terao:20220202183922p:plain f:id:yuri_terao:20220202183927p:plain

ここからいくつかピックアップしてご紹介します。

バックエンド

Ruby / Ruby on Rails

Baseconnectの各プロダクトではベースとして Ruby / Ruby on Rails の言語 / フレームワークが用いられています。創業当初、限られたリソースの中で短期間での開発を実現するため、Rubyが採用されました。

採用戦略として、京都の優秀な学生をインターンシップメンバーとして積極的に採用していて、初学者でも習得のしやすいRubyは相性の良さがありました(現在インターンシップメンバーの採用は当時より縮小しています)。その後も、エンジニアが多く採用しやすいことからメインの言語として利用しています。

ただ、Rubyしか使わないと決めているわけではなく、目的に応じて以下のサーバサイド言語も採用しています。

Go(Golang / Go言語)

コンパイラ言語のメリットを活かせる一部のシステムでGo(Golang / Go言語)を導入しています。具体的には、企業情報データベースサービスであるMusubu内で得られた企業情報は、Musubu内でメール配信やアプローチ管理を行えるだけでなく、CSVデータでダウンロードし利用することができるのですが、そのダウンロード時のデータエクスポート要求を処理するサブシステムで、Goが採用されています。

当時、メモリ使用量が大きくシステムを切り分けたかった事があり、その際にコンパイラ言語による処理速度の向上とライブラリなどが軽くなり立ち上げやすくなることを期待してGoを選択しました。また、当時Goの注目度が高かったというのも正直あったそうです笑。

Python

Pythonは、機械学習との相性を考慮し、一部のシステムで導入しています。一つは、Musubuサービスで提供しているマッチ度の算出に用いています。マッチ度は成約確率の高さを表す独自の指標で、成約先企業の特徴ベクトルのクラスタリングを行うことで算出しています。計算には scikit-learn とういう python機械学習ライブラリを使用し、Kmeans法でのクラスタリングを行っています。

もう一つ、企業情報の名寄せシステムにも用いられています。ユーザーが登録した営業先情報とMusubuが保有する企業情報を名寄せする(同じと思われるものを突き合わせる)システムがあり、SageMakerを利用し機械学習による精度向上をはかっています。

フロントエンド

TypeScript

当初はJavascriptで開発が開始されましたが、徐々に開発規模が大きくなっていく中で安全な開発を行うために、型定義を行えるTypeScriptを導入しました。Musubuの前身であるプロダクトにおいて、ビジネスロジック部分(Model、Service、Redux) のコードから段階的に移行してきており、現在はReact Component 等、ビジネスロジック以外のコードも TypeScript で書くようになっています。

React / Redux

Musubu のフロントエンドではReactを採用しています。また、状態管理のフレームワークとして Redux を利用しています。もともと画面描画は Ruby on Rails のview上で行っていましたが、メイン機能である企業情報検索画面のおいて、動的でリッチなUIを実現し検索体験の向上をはかるために導入されました。

フロントエンドはどんどん新しい技術が出てきてキャッチアップが難しい領域ではあると思いますが、2021年に積極的なリファクタリングを行ったことで、比較的モダンなシステムを取り入れることができていると感じています。いくつかピックアップすると、xstyledやRTK Query を導入しました。

xstyledは、styled-component を拡張したもので、tailwindow のようなCSS指定を props ベースで行えるようになっています。 わかりやすい恩恵としては、テーマカラーの管理がかなり楽になりました。RTK Query は、SWR や React Query の API を Redux で再現したもので、Reduxとの相性の良さを考慮して採用しました。

フロントエンドのリファクタリングの取り組みについては他にも行ってきたことがあるので、また別の記事でご紹介できれば嬉しいなと思います。

データベース

Neo4j

Musubu ではグラフデータベースであるNeo4jをメインDBとして利用しています。グラフデータベースの特徴として、一般的なリレーショナルデータベースにはない、ネットワーク上のデータ構造をもちデータ同士の繋がりを可視化する表現力があることがあげられます。

Baseconnectでは 「世界中のデータを繋げることで、ダイレクトに必要な情報にアクセスできる世界を作る」 ことをビジョンに掲げていて、将来的に企業データだけでなく人物データや与信データといった様々な情報を繋げる構想に向けて Neo4j を採用しました。

一方で、グラフデータベースには苦手なこともあるため、以下に紹介する他のデータベースを組み合わせることで弱いところを補完するようにしています。

Elasticsearch(Elastic Cloud)

企業情報検索システムにて、検索速度を上げるためにElasticsearch(Elastic Cloud)を用いています。Elasticsearchの利用にあたっては、複雑なデータ構成の中でいかにパフォーマンスを向上させるかというところを、試行錯誤しながら取り組んできました。

特に、直近行ったデザインリニューアルでは大幅な検索システムの改善を行ったのですが、その中の技術要件として複数のデータを組み合わせた複合検索を実現する必要があり、技術探索のフェーズを設け課題をクリアしてきました。

※ Elasticsearchは正確には検索エンジンですがグラフデータベースの補完として位置づけているため、このブログ上はデータベースに分類しています。

MySQL

メール配信システムや課金システムといったMusubuのサブシステムでは、MySQL を採用しています。グラフデータベースよりもRDBの方が、表形式での集計といったところがやりやすく管理しやすいという利点があり、採用しています。

データベース全体の課題として、正規化や実行計画などパフォーマンスに影響するところや特徴であるグラフデータベースの利点を意識した設計を、一人ひとりが高いレベルでできているとは言えずまだまだ道半ばというところがあります。

インフラ

AWS

細かいサービスを含めるとキリが無くなってしまうので、(乱暴だと自覚しつつ)ひと括りにまとめてしまいますが、サービス発信環境は基本的にAWSのサービス群を用いて構成されています。GCPMicrosoft Azure ではなくAWSをメインにしているのは、特に深い理由はなくスタートアップ向けのクレジットをもらえたからだそうです笑。同じ理由で当時はGCPも使っていたようですが、管理のしやすさのためAWSに集約しました。

Kubernetes

Baseconnectでは Amazon EKS(AWSマネージドのKubernetesコントローラー)を導入しています。VagrantからDockerに置き換える過程で導入されました。導入のきっかけは、当時コンテナを使わないことにリスクを感じたメンバーからの発案によるもので、Musubuのサブシステムである課金サービスから段階的に対応していきました。

BigQuery(GCP

BIエンジニア向けの分析用データウェアハウスとしてBigQueryを用いています。データウェアハウスにはBigQueryを使っていますが、データレイクにはS3を使っていて、GCPAWSのいいとこ取りのような使い方をしています。データ分析ソフトウェアとしてはTableauを使っていましたが、「データの民主化」を合言葉にBIエンジニア以外も気軽にデータが見れる環境を整えるため、最近 looker に移行しました。

Terraform

主にインフラ管理の権限移譲の課題を解決することを目的に、SRE/BIチームにより導入されました。インフラの設定変更や立ち上げを行う際に本番環境などはSREメンバーに権限が偏っていたため、SREチームがボトルネックになる課題がありました。絶賛進行中ですが、Terraform導入によりインフラのコード化を行い、SREメンバーはコードをレビューし許可を出すだけで実行に移せるようにフローを変更することで、ボトルネック解消をはかっています。BIでは分析基盤の属人化を解消するためにTerraformによるコード管理が使われています。

DataDog

プロダクトの成長にともないパフォーマンス監視の優先度も上がってきました。当初のCloudWatchからZabbixに移行し、直近ではDataDogへの入れ替えを行っているところです。Zabbix では、エスカレーション基準の設定や異常検知などの機能が弱く、また他のモニタリングツールも併用しているためツールの運用負荷が高いといった課題があり、統合監視ツールであるDataDogを導入することになりました。 DataDogを使ってみたメンバーの感想では、UIが直感的でめちゃくちゃ使いやすいとのことで、開発者体験としてもよさそうでした。


Baseconnectプロダクトを構成する主要な技術スタックをご紹介しました。ミドルウェアやライブラリといったレイヤーまで含めるとご紹介できる技術スタックは他にもありますが、長くなりすぎるのでここまでとします。今後も、新しい挑戦もしつつ不用意に手を広げすぎないよう、バランスをみた技術選定をおこなっていきたいです。

もし今後の技術選定に関わっていきたい方や、もう少し詳しい話を聞いてみたいという方、ぜひカジュアルにお話ししましょう! Baseconnectではエンジニアメンバーも絶賛募集しています!

meety.net

herp.careers