セキュリティの改善における OAuditToolbox の活用

Indeed が世界 No.1 の求人検索サイトであり続けているのは、ユーザーからの信頼が大きく貢献しています。ユーザー は Indeed が情報を安全に管理してることを信用しています。個人情報の悪用が常にニュースになる世の中において、私たちは、その責任を真摯に受け止め、注意を怠るわけにはいきません。だからこそ、Indeed の社員や企業のデータだけでなく、Indeed に信頼を寄せるユーザーのデータを保護するために、データを安全に管理する必要があります。

私は Indeed の情報セキュリティチームに所属しており、2017 年の初頭より、Indeed の Google GSuite 使用における問題点の改善に取り組んできました。これに対する Indeed のソリューションである OAudit Toolbox が、オープンソースのツールとして皆さんにもご利用いただけるようになりました。

問題:サードパーティアプリのリスク

Indeed が Gsuite を使用するにあたり、最もリスクの高い部分はサードパーティアプリの連携でした。

GSuite ユーザーは、自身のアカウントへのアクセスをアプリケーションに許可することができます。これは、基本的なアカウント情報から、Gmailの 閲覧・編集する権限にまで渡ります。確認画面の中に表示されている OAtuth のScope (権限) によって、Google 情報へのアクセスが管理されています。

GSuiteを利用している企業にとって、これには複数の問題点があります。

ユーザーの教育 ユーザーが気づかずにアクセスを許可してしまったり、自分の選択した動作がプライバシーやセキュリティにどのような影響があるか理解していない可能性があります。

データの共有 特定のScopeに対して、アプリを認証することでサードパーティに機密データへのアクセスを許可してしまいます。企業としては、こうした種類のアクセスに対し、適切なデータ共有の契約で明示していないかもしれません。

データの抜き取り 悪意のあるアプリケーションが OAuth のフローを使用し、フィッシングを行い、Google アカウントからデータを抜き取る可能性があります。

限られたツール 私が調査を行った時点では、Googleの提供によるアプリ制限のための選択肢は限られていました。API は、対処が後手に回りやすいブラックリスト方式だけが利用可能でした。比較的新しい機能では、接続したアプリのホワイトリスト化が可能になりましたが、これは、アプリのホワイトリストを実際に用意しておく必要がありました。

ポリシー文化 多くの企業は寛大すぎる Scope でアクセスを許可しています。Google の新しいホワイトリスト機能を使用するためには、セキュリティチームが大量のアプリのバックログの調査、承認、そしてホワイトリストの作成を行う必要があります。怪しげなメールトラッカーアプリを使わないと生産性があがらないと主張する社員からのリクエストをさばいたりもしなければいけません。

そうこうしているうちに、Indeed は実際に攻撃を受けたのですが、これにより、問題が浮き彫りにされ、ソリューションを定義することができました。

決定的な事件: 大規模のフィッシング攻撃

2017 年の 5 月には、世界中の Google Apps ユーザーに、Google ドキュメント を装った大規模のフィッシング攻撃がありました。

ユーザーは、知り合いから届いたように見える、ドキュメント共有の招待メールを受信しました。GSuite を利用している企業で働いている場合、こうしたリクエストは何の変哲もありません。ただし、この偽の Google ドキュメントは、受信者のメールと連絡先へのアクセス権限を要求するものでした。もしユーザーがアクセスを許可してしまった場合、偽 Google ドキュメントのアプリはこの被害者のアカウントを利用し、被害者になりすまして連絡先に同じフィッシングメールを送信していました。

Indeed のセキュリティチームの一員として、私は最前線に立ってこの攻撃に対応していました。数時間に渡るパニックと、OAuth トークンの無効化を行った後、私は不思議と刺激を受けていました。GSuite の利用可能なツールの隙間を埋め、このような攻撃をもっとすぐに検知し、ユーザーにサードパーティアプリ認証の危険性に関する知識を深めてもらう方法を見つけたいと考えたのです。こうして、同僚のDustin Deckerと共に、完璧なソリューションに近づけるような一連のツール開発に取り組み始めました。

Indeed のソリューション: OAudit Toolbox

OAudit Toolbox はサードパーティアプリの統合を検知し、ユーザーに危険性とそのアクセス許可する範囲を通知する一連のツールです。

OAudit Toolbox の仕組み

OAudit Toolbox は 2 つの主要なコンポーネントからなります。

  • Oaudit-collector は Google Admin API から認証イベントを Elasticsearch内にインデックス化します。
  • Oaudit-notifier は、OAuth の Scope に関する通知を送り、またホワイトリスト/ブラックリストを管理するロジックを持っています。

ブラックリスト方式は、リスト化された既知の悪質なアプリのアクセス権限の取り消しを、ほぼリアルタイムで行うことができます。このリストは、悪意のあるアプリや企業のポリシーに違反するアプリを含みます。ブラックリストとしてアプリが定義された後にだけ、認証されたアプリのアクセス権限は取り消されます。

ホワイトリスト方式は、信頼されたアプリに関する通知を停止するので、ユーザーが度重なる警告にうんざりせずに済みます。

  1. Oaudit-collector は、Google Admin SDK APIを利用し、認証トークンのイベントデータを取得します。
  2. Oaudit-collector は、Elasticsearch 内に取得したデータをインデックス化します。
  3. Oaudit-notifier は、認証されたアプリケーションがホワイトリストやブラックリストに入っているか、または未知のものであるかどうかを確認します。
    • もしアプリがホワイトリストに入っている場合、通知は送られません。これは通常セキュリティ審査を受けたアプリに使用されます。サードパーティアプリは、(該当する場合)Indeed に対して適切なデータ共有の規約の提示が必要になります。
    • もしアプリがブラックリストに入っている場合、ユーザーにその旨とアクセスが拒否されたことを通知します。これは悪意のあるアプリ (例: 2017年に起きたフィッシング攻撃) や、企業のポリシーに準拠してないアプリに対して使用されます。
    • ブラックリスト・ホワイトリストのどちらにも記載のないアプリは、信頼されていないアプリケーションを認証することに対する潜在的リスクと、望まないアクセスを拒否する方法をユーザーに通知します。

OAudit Toolbox の活用方法

OAuth Toolbox は、私が発見した GSuite の利用に伴う各問題を解決、または少なくとも軽減します。

ソリューション:ユーザーの教育

ユーザーがサードパーティアプリを認証してしまうのには、以下のように沢山の理由が考えられます。

  • マネージャーの指示があった。
  • ユーザーが確認画面の内容を理解していない。
  • ユーザーがDPA (データ処理規約。Data Protection Agreement) や、 MNDA (相互秘密保持契約書。 Mutual Non-Disclosure Agreement) などのサードパーティと情報を安全に共有する上で役立つ情報の周知を受けていない。
  • その他色々。

OAudit を有効にすると、ユーザーは、各サードパーティアプリに関連するリスクが理解しやすいように視覚化された通知を受け取ります。これには、リスクの説明がわかりやすく記載されています。各 Scope は機密情報を共有するリスクに基づいたスコアを割り当てられ、それを想起する色で表記されています。

この機能を有効にした後、アプリの使用が安全かどうかというユーザーからの質問が、著しく増えました。アプリケーションセキュリティチームへのサードパーティアプリのレビューの依頼もさらに増えました。また、エンジニア組織外のチームからの連絡も受け取りました。これまでは、技術職ではないユーザーが、サードパーティのツールの使用に不安を感じても、その理由を説明する技術・セキュリティ上の知識が不足していたのです。

ソリューション:データ共有

ユーザーは、スプレッドシートの見栄えをよくしたり、メールでのマーケティングキャンペーンを有効にしたり、Google フォームの結果を自身に送信したりするために、Google Apps にツールを追加します。

一般的なユーザーには、こうした統合は GSuite 側ではなくサードパーティ側のサーバーに存在するということは、知られていません。あるユーザーは、Google が各アプリを入念に検査していると思い込んでいます。また、別のユーザーは、一度サードパーティの機器にデータが渡ってしまうと、規約を超えた、細かい使用法や共有方法に対しては管理できないという事に気付いていません。GDPR に対応しなければならない企業にとっては、この問題はセキュリティ以上の問題となり、規制しなければならなくなります。

OAudit Toolbox の利用は、リスクの高いデータ共有の概念を周知するのに役立ちました。同時に、プライバシー規約と契約書を管理するチームと連携して、適切な同意書を必要な場合には用意し、社内の審査で却下されたアプリへのアクセスを取り消せるようになりました。ブラックリストを利用して認証されていない(けれど悪意のない)アプリへのアクセス権限の取り消しを遡って行うことも、これらのアプリの機能はデータの抜き取りには直結していなかったので、それなりに効果がありました。

ソリューション:データの抜き取りについて

安全で便利なサードパーティアプリが存在する一方で、2017 年に Google Docs をめぐり起きたフィッシング攻撃のような、便利なツールを装った悪意のあるアプリも存在します。

悪意のあるアプリのアクセスは、いつでも拒否できますが、これらのアプリはデータの抜き取りやアカウントの悪用をすぐに実行する可能性が高く、このような対処の効果はわずかなものです。また、この方法の信頼性は、トークンのログの遅れにも依存します。このタイムラグは、Google ドキュメントのフィッシング攻撃の際には、12 時間の遅れがありました。もっと最近では、トークンのアクティビティのタイムラグは 1 – 10 分ですが、Google は数時間にのぼることもあると明言しています。

OAuth Toolbox は Elasticsearch にもデータを送信するので、Indeed で ElastAlertWatcher の設定を推奨しています。これらは、これまでに見たことのないアプリが認証されていたり、一つのアプリが短期間で認証される数が急激に増加していたりする場合に、検知します。

問題が起きる前にユーザーに危険について警告するので、OAudit Toolbox は、IPS (侵入防止システム) のような事前にブロックするものというより、IDS (侵入検知システム) と呼ばれる、悪意のあるアプリに対する早期警報装置のようなものになっています。

ソリューション:利用可能なツール

OAuth Toolkit の開発が始まった頃、アプリのアクセスを拒否する機能は GSuite の中の色々な場所に点在していました。 Google Apps の管理者は Marketplace のアプリ、Drive API、そして Chromeの拡張機能をブロックすることができました。私たちがそれを実際にうまく実装するには、手荒すぎるものでした。ソリューションが不完全だったので、最小限の費用対効果では管理するのは難しかったのです。

Google でも今は Drive や Gmail、コンタクトなどの Google Apps への OAuth のアクセスを、Google 管理者セキュリティパネルでブロックできるようになりました。オプションとして、「リスクの高い」Scopeのみをブロックすることも可能ですが、どのScopeのリスクが高いかを示すドキュメンテーションはありません。信頼できるアプリの使用許可を行うホワイトリストは利用可能です。

このホワイトリストは、もしチームで以下の準備が揃えば、便利な追加機能となるでしょう。

  • 使用中の全てのアプリをブロックする。
  • ホワイトリストに入れるべきものを把握している。
  • 新しいアプリケーションを承認するためのワークフローが存在している。
  • アプリ審査のためのアプリケーションセキュリティの資料を持っている。

Googleがこれらの措置を講じているのは喜ばしいことですが、OAudit Toolkit は、もっと簡単に実装し、ワークフローをそこまで崩さないソリューションを私たちにもたらしました。

ソリューション:ポリシー文化

このツールの実装とそれに続くレビューの工程にとって一番のハードルとなったのは、技術的な部分ではなく、人と関わる部分でした。オープンな「各自好きなアプリを持ち込みOK」な文化から、より規制のある、一見するとお役所仕事のようなプロセスへと移行するのは、困難なものでした。透明性が自社の企業文化にとって重要な要素とされているので、なおさらです。

私たちは、以下のような施策が役立つことを学びました。

  • (OAudit Toolbox などの) ツールや研修、テックトーク、そして社内ブログの記事を使用して、ユーザーにサードパーティアプリが引き起こすリスクを紹介する。
  • 山のような法律用語を利用規定に追加する代わりに、ユーザーが実行しなければいけないアクションをシンプルにまとめ、イントラネットのホームページや、社内 wiki、または IT サポートのランディングページなど、簡単にアクセスできるページで閲覧可能にする。
  • 「メールの統合」や「スプレッドシートの自動化」などのカテゴリーで、よく使われる高いリスクのツールをバケット化する。こうすることで、50件の異なるアプリを調査するのではなく、認証された一つのアプリとこれらのアプリをより簡単に交換が可能。
  • 一晩では問題を解決できないということを受け入れる。もし、一部のアプリのアクセスを継続して許可したり、新しいアプリを認証したり、規制したりすることで問題を軽減することしかできないとしても、今までよりは良い状況になる。

OAudit Toolboxをご活用ください

私たちの経験が皆さんにも役立つように、OAudit Toolbox をオープンソースとして公開しました。組織の教育を向上し、次に起こりうるフィッシング攻撃に対して備えるために、このブログに記載したような手順で自社の Google Suite に統合してみてはいかがでしょうか。悪者たちを出し抜いて、せめて私たちの手の届く範囲でウェブを安全な場所にしていきたいと思います。


(この記事は英語版から翻訳されました。原文:Improving Security with OAudit Toolbox

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Share on RedditEmail this to someone

Indeed MPH:高速で小さいイミュータブルなキー・バリューストア

膨大なデータを抱えるアプリケーションをスケールする際に、どのようなストレージを導入するべきなのでしょうか?どうしたら大量のデータセットを安全に保存し、効率的に読み書きを行えるのでしょうか?こうした疑問は、よく SQL か NoSQL のどちらを使うべきかという議論になりがちですが、どちらもそれぞれメリットとデメリットがあります。

ですが、もしデータデースにまつわる問題を全て回避できる三番目の選択肢があるとしたらどうでしょうか?

コンシューマは数分おきにしか更新を必要としていないかもしれません。この場合、データセットをメモリ内に読み込めると、劇的にアクセス速度があがり、大規模のスケールが可能になります。このことから、 Indeed では多くのプロジェクトで、必要なデータの完全なコピーを、各コンシューマに渡しているので、 SQL 対  NoSQL の議論をする必要がありません。これを実現するにあたり、私たちは最小完全ハッシュ関数に基づく新しいキー・バリューストアを作り、データサイズを管理しています。私たちは、 Indeed MPH と呼ばれる Java ライブラリとして、このストアを実装しました。

データ配布の課題

一般的に、データの全コピーをコンシューマに渡すのは実現が難しいのですが、それには理由が二つあります。一つは、データがほぼ読み取り専用(read-only)である必要があること、もう一つは、配布や処理を防いでしまうほどデータが大きくてはいけない、ということが課題にあげられます。

一つ目の課題は、バッチの更新を実装すれば解決できます。毎日、毎時間、もしくはもっと頻繁にデータを再配布させれば、データの有用性を保ちつつ 読み込み専用として維持できるでしょう。けれど、サイズを小さく留めておくにはどうすればいいのでしょうか。分かったことは、二つ目のサイズの課題に対しても同じようにバッチ更新の方法で対処できる、ということでした。

最小完全ハッシュ関数(Minimal perfect hash functions, MPH

読み込み専用のデータセットを生成するということは、事前に自分のデータセットのキーを全て把握しているということです。これは、データセットのサイズを削減する最適化を可能にします。ハッシュテーブルの場合は、完全ハッシュ関数の計算が出来るようになります。

完全ハッシュ関数は、すべての要素を相異なる整数に衝突なくマッピングします。数学用語では単射と呼ばれます。 最小完全ハッシュ関数 は n 個のキーを 0 から n-1 までの n 個の連続した整数にマッピングします 。こうした構造は、テーブルを 100% 活用している状態を維持しながら、一回のディスクシークで参照できるようにします。他にもまだメリットはあるので、後ほど述べたいと思います。

こうしたハッシュ関数を見つけるのは難しく、事実、誕生日のパラドックスは、ハッシュの範囲がキーの個数の何倍も大きい場合でも全くキーが衝突しないというのはありえにくいとしています。けれど、最近の研究の成果のおかげで、効率的なテクニック質の高いライブラリを使用して、最小完全ハッシュ関数を生成できるようになりました。これらのテクニックは、小さな不都合はあったものの、私たちのメソッドを成功させました。結果として生成されたハッシュ関数自体が、キーごとに ~2.2 ビット の探索テーブルを必要とするので、定数サイズにはならないのですが、この探索テーブルはブルームフィルタのサイズの一部くらいしかないため、 100 万件のエントリに対し 26MB 程度を必要とするだけなのです。実用上では、この探索テーブルのサイズは保存されたデータのサイズに比べれば、取るに足らないものと言えます。

実用性

MPH は、キーから 0 から n-1 の整数へのマッピングを提供しますが、やはり実際のテーブルを実装する必要があります。メモリ内にテーブルを保存する場合は、通常配列の形でデータを保存します。これをオフラインのストレージに変換するためには、プログラミング言語の配列が暗黙のうちに設定しているメモリーオフセットを明示的に作らなければいけません。私たちの表現は 3 つのファイルを持つディレクトリでした。

  • data.bin: raw のシリアライズされた key/value のペア
  • offsets.bin: data.bin 内のデータの(一定サイズの)オフセット配列。i 番目の値がハッシュ値が i であるエントリのオフセットに対応する。
  • meta.bin:  シリアライズされたハッシュ関数そのものとその他の必要なメタデータ

以下の図は、色から動物へのマップを持つ場合の、このデータ表現を表しています。


この表現の便利な部分は、 data.bin が、ハッシュ関数に依存することなく、そのままイテレートできる生データであるということです。加えて、キーがユニークでさえあれば、同じ data.bin を異なるキーでインデックス化するような複数のハッシュ関数を構成することも出来ます。

この表現のデメリットは小さなエントリが沢山存在するときに顕著になります。この場合は、オフセットのサイズはデータ自体と同じ位かさらに大きくなります。極端な例をあげると、データに 4 ビット整数から半精度浮動小数点数(half-precision float)への 7 億 5000 万個のマッピングが含まれる場合、 data.bin は 7.5e8 * 6 = ~4.2G になりますが、 offsets.bin にはなんと 7.5e8 * 8 = ~5.6G も必要になるのです。この例では、全てのエントリが一定のサイズである点を活かすことができ、オフセットを保存することなく、 data.bin に直接インデックス化できるのです。けれど、サイズが可変の場合も最適化したいと考えました。

こうした高いコストは、小さなエントリを扱う際に特に発生するものです。もしエントリが大きい場合、オフセットのサイズは、それに比べれば取るに足らないものでしょう。合計サイズが小さいので、1 エントリにつきバイトではなくビットのオーダーで rank 辞書 として表現することが可能です。もう少しオーバーヘッドを大きくして良い場合は、同一のデータ構造上での定数時間で、 select と呼ばれる rank の逆関数を計算することができます。何故これが便利なのでしょうか?もし、この辞書で data.bin の中の全エントリの開始バイトの集合を表すことにするならば、  i 番目のエントリのオフセットを見つけるには、 select(i) を計算すれば良いのです。

この構造は以下のようになります。この場合は、ハッシュ値で data.bin をソートする必要があります。


更に最適化するためのヒントは、データ内のまさに通常の構造の中にしばしば存在します。例えば、 long を long のリストへ(1つのバイトをカウントに使用して)マッピングする場合、 ( key と valueを含む)  個々全てのエントリiのサイズは、リストの長さが xi だと仮定すると 8xi + 9 として表すことができます。k 番目のエントリのオフセットは ∑(8xi + 9) = 9k + ∑8xi = 9k + 8x となります。言い換えると、保存しなければいけないのは、 x だけなのです。これは実際のオフセットよりもずっと小さいので、 select を使ったアプローチを利用すると大きな削減となります。この場合は、リスト内に平均 2 つの要素を持つ 1000 万件のエントリがある場合、その data.bin のサイズは 10000000 * (9 + 16) = ~250Mになり、圧縮された select の手法は ~2.5M に収まります。

私たちの実装はオフセットの配列と select の手法両方のサイズがどうなるか計算し、適した方を選択するようになっています。

さらなる最適化

キーを捨てよう!

衝突する値もなく、私たちの探しているキーはテーブルの中にあると分かっていれば、キーの存在を検証する必要はありません。かわりに、値そのものや、値を元にして他のソースからキーを検証できるかもしれません。そして最後に、低い確率で誤検出をしてもよいならば、キーがテーブル内にあるかどうかをブルームフィルタを使用して、確率論的に検証することが可能になります。

もう一つこれよりも良い選択肢に、元のキーの集合の中では衝突しないような固有のハッシュを既に計算したので、キーの k ビットの署名(どんな一般的なハッシュの下位ビットでも可)を保存する方法があります。同じハッシュ値になるような元の集合にないキーは、2^(-k) の確率でしか署名が一致しません。これはブルームフィルタを使用するときよりも、ずっとマシなエラー率です。

これら全ての場合において、テーブルからキーを削除することができます。値が小さければ、キーはテーブルの大きな割合もしくは過半数を占めている可能性があります。

キーでなくハッシュでリンクさせる

あるテーブルの値が他のテーブルの外部キーになっている、または外部キーを含んでいるなど、複数のテーブルを一緒にリンクさせたい状況はよくあると思います。

MPH 関数を使用するもう一つの利点は、小さな整数の範囲にキーを圧縮してくれるところです。ハッシュ値をキーの代わりに保存できるので、殆どの実践的な用途では、4 バイトの整数におさまります。それに対して、その他の外部キーの多くは 8 バイトの long やそれ以上の大きさ になります。これは、より小さいというだけでなく、二回目の参照の際にハッシュを再計算する必要がないため、読み込みもさらに早くなります。

コードとベンチマーク

わたしたちは、自社開発した MPH のコードをオープンソース化しました。ベンチマークとして、別のオープンソースの選択肢といくつか比較してみます。

  • SQLite3:  1 つのファイルでできている複製に適した RDBMS
  • LevelDB:  Google の LSM ツリー構造のキー・バリューストア
  • lsm:  Indeedの LSM ツリー構造のキー・バリューストア
  • discodb:  MPH に基づいたイミュータブルなキー・バリューストア
  • TinyCDB:  完全でないハッシュを使用したイミュータブルなキー・バリューストア

これらの選択肢は、同じような機能セットを持っていない点をご注意ください。SQLite関係演算を全て提供し、 lsm や LevelDB は範囲のクエリを提供します。そして、これら 3 つのストアはミュータブルです。ここではこれらのソフトウェアに共通した一機能だけを見ていきます。

本番環境のデータにもとづいた、概念上リンクした 2 つのテーブルの結果を見ていきますが、こうすることで、上記に説明したハッシュでリンクする最適化の効果を示すことができるほか、さらに自然な表現が SQLite でできるようになります。この最初のテーブルは 5000 万件の 64 ビットのハッシュを項目の小さなクラスタにマッピングしたものです。これらの項目は 80 ビットの整数で 16 桁の Base32 文字列として表されます。二番目のテーブルは、クラスタ内の各項目に対応するハッシュにリバースマッピングしたものです。

Indeed のキー・バリューストアの特筆すべき点は、任意のシリアライズ手法を様々なプラグインの中から選んで使用することができる点です。公平に比較するために、LSM ツリーと MPH については、単なる文字列から文字列のマッピングの場合と、 2 つの最適化を適用した場合のテーブルサイズの両方を含めました。固定長の 8 バイトの long の値としてキーをエンコードし、 80 ビットの整数の短いリストとして値をエンコードしました。 SQLite に関しては、整数としてキーをエンコードしました。

文字列のマッピングの通常のケースでは、 LevelDB 、 lsm 、MPH は全て同等のサイズで、他のソリューションにくらべて格段に小さいものとなります。より効率的なシリアライゼーションを適用すると、 lsm と MPH はさらに小さくなり、MPH はこれによりさらに、データサイズの規則性を活かし、一番サイズの小さい選択肢になります。

ここでは、 lsm と MPH の最も良いシリアライゼーションだけを考えます。 MPH は、上記で説明した、キーを保存せず、その後で上記のテーブルを完全ハッシュ値経由でリンクする最適化を利用した場合のサイズも示しています。 SQLite は、両方の列をインデックス化した際のサイズを併記しています。このようなインデックスを作ると、前述の実験で作ったようなテーブルは不要になります。この場合は、 SQLite のインデックスは discodb と TinyCDB に関しては、前述の実験のテーブルを合わせたサイズよりも小さくなり、LevelDBでは同じ位になります。しかし、 MPH は最後まで他のものより小さく、事実、全ての最適化が適用された理想的なケースでは一桁分小さくなります。

ハッシュに基づくソリューションは、少ないシーク回数で済むので、より早くなる傾向があります。MPH は全体の中でも最も速く、抜きん出ています。

書き込みのパフォーマンスは lsm と MPHが最も高いパフォーマンスを見せています。 TinyCDB はこの時点ではデータの破損により、除外されています。 4GB と決められた保存容量がデザインされているのですが、 3GB の時点で、キーの 30% を取得することができなくなりました。

お試し下さい

IndeedのMPHは、Gitでオープンソース化し、利用可能となりました。

もし、既にキー・バリューストアをサーバーに移している場合、 Indeed の MPHテーブルはサイズを小さくし、読み込みを早くできるかもしれません。コンパクトな表現を使用して、より多くのデータを同じ容量内に保存し、以前には大きすぎると考えていたデータサイズも削減することが可能になります。集中型データベースの代替案をまだ決定していない場合、是非ご検討下さい。

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Share on RedditEmail this to someone

Job Spotter を iOSへ: Indeed初の React Native アプリ

2013 年、 Facebook は ReactJS をリリースし、(Indeed も含む)多くの人々の Web 開発に対する考え方を変えました。そして 2015 年に Facebook が  React Native をリリースすると、開発者が JavaScript と React を使用して、パワフルなネイティブモバイル体験を生み出せるようになりました。 Indeed でも Job Spotter というアプリの iOS 版リリースをちょうど計画しており、React Native に期待を寄せていました。

ネタバレ注意:期待通りでした。

React React Native について

React のウェブ開発に対する捉え方は独特で、関数ごとにコードを分けるのではなく、コンポーネントごとにコードを分けることを奨励しています。各コンポーネントは必要なレイアウト、スタイリング、ビジネスロジックを全て含んでおり、多くの場合それらは同じファイル内にあります。

React のその他の重要な特徴は一方向のデータフローです。他のフレームワークで用いられるような双方向のフローに比べ、 React を利用した環境では、状態(state)の変化がアプリにどんな影響を与えるか、非常に簡単に確認できます。こうした一方向のデータフローは、 Redux のようなパワフルなライブラリも作成可能にしました。

そしてReact Native は、 React を利用した、 JavaScript での Android/iOS ネイティブアプリ開発を可能にします。ウェブ開発者が、あまり知見をもたないネイティブモバイル開発技術を学ぶことに時間を割かずとも、パワフルなネイティブアプリを開発できるようになりました。

使用するメリット

React Native のおかげで、私たちのモバイル開発サイクルのスピードは上がりました。追加設定がいらないツール達を使用することで、ローカルの iOS シミュレータを使用して React Native アプリを実行できるのです。これにより、 Web 開発と同様に、変更をテストするためにアプリを更新する作業が、再コンパイルせずにできるようになりました。さらにありがたい事に、アプリケーションの状態はこのホットリロード中も維持されます。これらの React Native の開発機能は、時間と労力を節約し、新しい機能の開発に集中させてくれるものだと思います。

また、以前の React に関する知識を活用できたので、新しい言語を学ぶ必要もなく、すぐに開発に取りかかることができたのですが、私たちのチームに Objective-C や Swift での開発経験者が一人もいなかったので、これは非常に助かりました。一部のカスタムイベントログの作成を除き、React独自のコードを書く必要がほぼなかったことも、得した感じでした。

もう一つ、 React Native の興味深い点をあげるとすると、インラインスタイルを使用する必要があることです。これにより、 CSS の「クラス」は実際のところ JavaScript のオブジェクトとなっているのです。初めは変な感じがしましたが、慣れた今はとても気に入っています。オブジェクトを扱っているので、パワフルで、オブジェクトの組み合わせと拡張が可能な CSS クラスを作成ができるため、従来の Web アプリで見られたようなスタイルの重複を避けられます。異なるニーズに合わせて、同じスタイルを使い回すのではなく、異なる体裁や機能を必要に応じて開発することが可能なのです。

また React Native は、スタイリングをより一貫してシンプルにするために作られた新しい CSS モジュールの Flexbox を多用しています。これは、 CSS の従来の妙な挙動を取り除きました。私たちのチームでもFlexboxを色々学習した今では、 Flexbox の宣言型アプローチを使うことで、従来の CSS を使用するよりも、素早く新しいコンポーネントをスタイリングできるようになりました。

デバッグも想像よりもずっと簡単でした。 Chrome のデベロッパー・ツールのデバッガーに接続し、 Web 開発と同じやりかたでデバッグをするだけでした。 React Native では他にもいくつかツールが利用できるのですが、エレメント・インスペクターという機能はコンポーネントに適用されるスタイルを判断します。また、ネットワーク・インスペクターはアプリが作成する XHR リクエストを解析してくれます。慣れたツールを使えるので、問題が発生した際にも追跡し解決しやすいと思います。

課題

React Native はより高速に開発することを可能にしましたが、 React Native 自体も短期間で開発されたものです。 Job Spotter というiOSアプリを開発していた二ヶ月の間に、 React Native は六回もリリースを行いました。新しいバージョンがリリースされる度に、こちらもバージョンを更新し、アプリのリグレッションテストを全て行わなければなりませんでした。

もう一つの大きな課題は、React Native の新しさです。カメラやファイルシステムへのアクセスやパーミッションの処理などの、デフォルトで提供してほしい多くの機能がサードパーティ(外部の)ライブラリを必要としています。 React Native を使用するコミュニティでは、 React Native のコアでまだ必要とされる作業を必死に行っています。それでも場合によっては、これら外部ライブラリはコア・ライブラリに望むような品質を持ち合わせていないこともあるので、私たちはライブラリに対してパッチをあてることもありますが、実際にそうしたパッチをあてているライブラリは複数あります。

また、ナビゲーションやスクリーンの遷移に対して利用できるコンポーネントには一貫性がありませんでした。Navigator のコンポーネントは、遷移するごとに特定のアニメーションが必要とされ、空の遷移をする選択肢がない、という問題がありました。これは当初、シーンの遷移を変な風にしていました。NavigatorIOS コンポーネントを使用しようとしましたが、インターフェースがわかりにくく、シンプルではなかったほか、Navigator 機能の多くが欠けていました。

同様に、 TabBarIOS のコンポーネントはとても良い感じに動作するのですが、遷移は、私たちの使用していた Navigator から完全に独立していました。私たちは、その一つで全てを処理できる Navigator が欲しかったのです。そうした Navigator を欲しい時には、ナビゲーションに対応した異なるコードパスを使用する必要がありました。

挑戦する価値あり

こうした課題があるものの、React Native は私たちの使う技術に合っているので、今後も使用していきます。Android や iOS のエキスパートにはならずとも、Web 開発の強みを活かして、豊かなモバイル体験を作っていければと思います。 React Native が成熟した際には、現在抱えている問題の多くは解決すると見込んでいます。

そんな私たちの次なる目標は、 既存の Job Spotter の Android ネイティブアプリを、 React Native 版に変更する事です。

Tweet about this on TwitterShare on FacebookShare on LinkedInShare on Google+Share on RedditEmail this to someone