asoview! TECH BLOG

アソビュー株式会社のテックブログ

ゴールデンウィーク累計2,300万PVのアクセスを捌いた負荷対策 ~ アソビュー!が行った3つの手法 ~

こんにちは! アソビュー開発チームの山内です!

先日、自転車でしまなみ海道を渡ってきました。 途中、ゲリラ豪雨に遭いながらもなんとか75km完走しました。ゴール後の温泉は最高ですね。 次は、晴れた日に渡って温泉に入ろうと思います。

はじめに

アソビュー!では、2022年のゴールデンウィークの4/29 ~ 5/8の間に約2,300万のPVがありましたが、システムダウンすることなく、多くのゲストにワクワクを届けることができました。 今回は、私達がゴールデンウィークに向けて準備した背景と、アプリケーションでの負荷対策を紹介します。

背景

アソビュー!は、全国の遊びやレジャーチケットを予約・購入して体験できるサービスになります。 そのため、サービスの特性上、行楽シーズンの大型連休にアクセスが集中しやすくなっています。

また、今回は2022年4月15日〜2022年5月5日までの期間中に関東・東海・関西・九州の地域でTVCMを放映しました。 更には、2年ぶりの制約のないゴールデンウィークということもあり、今まで体験したことのない多くのアクセスがあることが予想されました。

日本国内で待ちに待った大型連休、アソビューのシステムダウンにより、ゲスト・パートナーに迷惑をかけることは絶対に起こしてはなりません。

インフラ側での負荷対策はもちろん、アプリケーション側でも負荷対策を行いました。

負荷対策について

アプリケーション側で行ったシステム負荷対策は主に以下の3つです。

  • OLTPのパフォーマンス改善

  • 各ページのCDN配信

  • APIタイムアウト設定・サーキットブレーカー設置

それぞれを紹介していきます。

OLTPのパフォーマンス改善

概要

データ構造の更新や、追加によりOLTP(オンライントランザクション処理)性能は劣化することがあります。 性能の劣化により、SQLのレイテンシが大きくなることで、負荷を増大させシステムダウンの原因となり得ます。

主要となる導線の各ページの全てのSQLの性能を確認し、改善の余地が無いかを検討しました。

どうやって行ったのか

レイテンシが大きい各SQLを確認し、以下のようなパターンでSQLを改善していきました。

1 indexが貼られているかどうか

参照しているテーブルの適切なカラムにindexが無いと、処理速度が遅くなることがあります。 indexを確認し、適切に設定されていない場合はindexを追加していきました。

2 不要な相関サブクエリがないか

相関サブクエリは、結果行に対して全てチェックしていくため、パフォーマンスが悪いと言われています。 また、EXSITS句も相関サブクエリを利用している場合においては、パフォーマンスが悪いケースがあります。 これらは内部結合に書き換え、不要な相関サブクエリの排除を行い、再度実行計画を確認して処理の改善をしていきました。

3 ユースケースや処理の見直し

改修が重なり、仕様が変更されるにつれ、そもそも不要なデータを取得している場合や、処理自体が不要になっている場合もあります。 SQLのみに着目するのではなく、そもそもの処理の見直しをすることで改善につながったケースもありました。

結果

パフォーマンス改善の一例を紹介します。 上記の改善を行うことで、多くのSQLの処理を改善することができました。 以下の例では、レイテンシが100ms ほどでしたが、改善後は 2msほどになっています。

各ページのCDN配信

概要

以前のアーキテクチャでは、Javaアプリケーションが直接リクエストを受けて、コンテンツを返却していました。 そのため、アプリケーション及びDBに大きな負荷がかかっている状態でした。

そこで、主要なページをURLパスごとにキャッシュし、CDN配信することで負荷を軽減させました。

どうやって行ったのか

アソビューはSSRでコンテンツを表示しております。 そのため、そのままページをキャッシュしてしまうと、以下のような問題が発生します。

  • 会員情報がそのままキャッシュされてしまう
  • Cookieで判定や処理していたものが動かなくなる
  • SpringMobileでデバイス判定していたので、初回にキャッシュされたデバイス表示でコンテンツが表示されてしまう
  • ページ内容を変更した際に、瞬時に反映されない

各問題に対して、以下のように解決しました。

  • 会員情報や、Cookieの問題

会員情報を取得するAPIを作成し、フロントから取得するように変更いたしました。 また、Cookieに関してもAPIで代替できるものでしたので、APIを作成し適用していきました。

  • SpringMobileでデバイス判定

こちらは、CloudFrontのヘッダーを条件とするPC/SPの表示切り替え対応を行いました。 具体的には、SpringMobileでデバイス判定をした後に、CloudFrontで判定した結果を上書きすることで解決できました。

  • ページ内容を変更した際に、瞬時に反映されない

社内システム等でページ内容を適用すると同時に、CloudFrontのinvalidationが走るようにすることで、瞬時にコンテンツを更新することができました。

結果

主要なページをCDN配信にすることで、オリジンへのアクセスを大幅に減少することができました。 アプリケーション、DBに直接アクセスが行かないことで、負荷を減少することができています。

CDN配信前後のオリジンへのアクセス件数

APIタイムアウト設定・サーキットブレーカー設置

概要

アプリケーション間や外部連携先との通信において、高負荷状態のためにアプリケーションのスレッドが枯渇し、クライアントからアクセスができないケースや、 そのアクセスが更に高負荷状態を促進させてしまう悪循環に陥ることがあります。

この状態を解決すべく、APIタイムアウトとサーキットブレーカーの導入を行いました。

どうやって行ったのか

APIタイムアウト設定

まず、アソビューのフロントとバックエンドから呼んでいるAPIのうち、タイムアウト設定がされていないものに対して設定していきました。

タイムアウトの設定値については、直近のAPMを参考に正常時ではタイムアウトが起きない値をAPIごとに設定しました。

以下、RestTemplateでの実装イメージです。

@Bean
RestTemplate restTemplate() {
    RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
    RestTemplate restTemplate = restTemplateBuilder
            .setConnectTimeout(3000)
            .setReadTimeout(3000)
            .build();
    return restTemplate;
}

サーキットブレーカー

サーキットブレーカーとは、呼び出し先のアプリケーションが高負荷や障害等で一定のエラーやレスポンスがない際に、呼び出し元で判断して一定時間リクエストを遮断する仕組みです。 これは、障害の際に復旧するまでの期間にアクセスをしないことで、呼び出し先に不要な負荷をかけず復旧を早める狙いがあります。

アソビューから呼び出している複数のアプリケーションの呼び出し部分に対して、サーキットブレーカーを設置しました。

サーキットブレーカーは、リクエスト先アプリケーションの状態を以下3つのステータスで管理しています。

サーキットブレーカーの状態遷移

  • CLOSED

    正常な状態。直近のエラー数をカウントし、閾値を超えるとOPENに移行します。

  • OPEN

    エラーによりリクエストを遮断している状態。指定の時間を超えると、復旧の確認であるHALF-OPENに移行します。

  • HALF-OPEN

    システムが障害から復旧したかを確認している状態。少数のリクエストを行い成功すればCLOSEDに移行します。

これらのステータス変化の設定値を直近のAPMから計算して設定していきました。

以下、Resilience4jでの実装イメージです。

public CircuitBreakerConfig circuitBreakerConfig() {
    return CircuitBreakerConfig.custom()
            .failureRateThreshold(100)
            .slowCallRateThreshold(1000)
            .slowCallDurationThreshold(Duration.ofSeconds(10))
            .minimumNumberOfCalls(10)
            .slidingWindowSize(50)
            .waitDurationInOpenState(Duration.ofSeconds(60))
            .permittedNumberOfCallsInHalfOpenState(10)
            .automaticTransitionFromOpenToHalfOpenEnabled(false);
            .build();
}

結果

これらの設定の成果としては表しにくいのですが、 APIタイムアウト設定による高負荷状態の悪循環の防止や、万が一のためにサーキットブレーカー設定をしたことで、 高負荷状態の助長を防ぐことができ、大量のアクセスでもさばききれたのだと思います。

最後に

今回は、アプリケーションで行った負荷対策の一部を紹介しました。 参考になる情報があれば幸いです。

エンジニアチームとして、できることはまだまだあると思っております。 アソビュー!は、遊び、レジャーのインフラとして快適安心なサービスをゲスト・パートナーに届けれるよう、更に改善していきます!

アソビューでは「生きるに、遊びを。」をミッションに、一緒に働くメンバーを大募集しています! カジュアル面談もありますので、少しでも興味があればお気軽にご応募いただければと思います!

www.asoview.com

RDRA + JavaによるレジャーSaaSプロダクトの要件定義と実装のシームレスな接続 / JJUG CCC 2022 Spring 登壇レポート #jjug_ccc

JJUG登壇してきました。

こんにちは。アソビューCTOの江部です。 いきなり私事ですが昨日6/30は誕生日でした。ハッピーバースデー俺。 そして10年前の2012/6/30にアソビュー!はβ版をローンチしたのでした。おおきゅうなったのー。あの頃の若さを取り戻したい!!

さて、今日は6月19日に開催されたJJUG CCC 2022 Springに登壇してきましたので、そのレポートを投稿しようと思います。 登壇資料はこちらになります。

動画版はこちら https://www.dropbox.com/s/j7695fq2b2inbgp/jjugcccspring2022_ebe.mp4?dl=0

ちなみに、JJUG CCCへの登壇は初めてでして、無事発表できて良かったです。 Session自体は事前に録画して提出、当日はそれを放映し、質疑応答の部分だけリアルでリモート参加するという形でした。 録画&リモートは楽でよいのですが、個人的にはこういうイベントもそろそろオフラインでやれると参加者の方々の反応もみれるし交流がはかれて良いなーと思いました。

ざっくり概要

弊社でとりくんでいる現行システムの刷新プロジェクトを題材に、RDRAをつかった要件定義 + Javaによる実装を接続させようという試みを紹介しました。

  • プロジェクトの体制と要件定義のススメ方
  • Spreadsheet式RDRAのアウトプットイメージ
  • RDRAからJavaの3階層アーキテクチャへの実装マッピング

を紹介していますのでご覧ください。

ちなみに、JJUG当日や社内外で、以下のような質問をいただきました。

今回は既存システムの刷新とのことでしたが、完全新規のプロジェクトで今回の手法はどうでしょうか? どのようなプロジェクトでRDRAを取り入れるべきですか?

完全新規プロジェクトでも適用できると思いますが、既存システムの刷新以上に要件定義メンバーにビジネス面を含めて意思決定できる or 情報を持っている人を入れることがスムーズにすすめる上では必須だと思います。 セッション形式で進めていくので、その場で決めていけないと持ち帰りが多くなり効率が下がることになってしまうためです。 逆に、ビジネスの意思決定者を開発に巻き込むことでユビキタス言語の形成に役にたちますし、長期的に円滑なプロダクトづくりができる組織づくりができると思います。

また、何を作るのかによっても今回の手法を取り入れるべきかどうかは分かれるとおもいます。 なぜなら今回の進め方は要件定義セッションを毎回みんなでやるのでそれなりに時間とコストの初期投資がかかるからです。 よって、この投資回収が確実に見込めるかどうかが重要かとおもいます。

有効なプロジェクト

  • 一定以上の複雑なビジネスルールやユースケースの構造をもっている
  • プロダクトのニーズがすでに証明されており、ある程度成長したシステムの刷新(今回のケース)
  • 業務システムなど、既存のオペレーションを自動化などで改善することでコスト改善が見込めるプロジェクト

上記のようなプロジェクトは、構造化されたモデリングで表現することによるコミュニケーションコストの低減や手戻りリスクの削減がROIとして良いケースが多いのではと考えています。

有効ではないプロジェクト

  • 複雑なビジネスルールを持たない至ってシンプルなシステム
  • PMFにいったってない、仮設検証段階のプロダクト。スタートアップのランウェイを走り抜けている最中のプロジェクトなど

こういったプロダクトやプロジェクトでは今回のようなセッションベースの要件定義のモデリングプロセスは冗長かもしれません。 1点目は開発も単独か少人数になりますし仕様も単純なことからソースコードベースで会話することも可能だとおもいます。 また、2点目のようなプロダクトは、PMFに至った段階で一旦すべて作り直す覚悟で、シンプルな仕様から早くプロトタイプつくって市場のフィードバックを得ながら改修を重ねてグロースさせていったり、トラクションを得ることに目一杯時間やコストを掛けたほうが良いと思います。

簡単ですが以上になります。 こういった手法に興味がある、もう少し話聞きたい、という方はお気軽にご連絡ください!

Meety https://meety.net/matches/HHAUaMpxUftI

仲間も常時募集中です。 私達は「生きるに、遊びを。」をミッションに掲げ、本質的な人の幸せに貢献することを自分たちの存在意義としています。 あなたの技術力で「衣食住遊」を実現し、より遊びが充実した社会を作って行きませんか? ご応募お待ちしています! https://www.asoview.com/brand/engineer-career/

hooks APIで整理することでReduxが不要に。asoview.comにおけるReact状態管理の変遷

こんにちはアソビューのフロントエンドエンジニアの井上です。
ヌルゲーマーなので満月の女王レオナを昨晩ようやく倒せてガッツポーズです。#エルデンリング

はじめに

Reactベースのフロントエンドの状態管理、よそはどうやってるんだろう。。
気になりますよね?私も気になります。
今回はアソビューにおける状態管理の変遷と今どのように扱っているか、について紹介したいと思います。
結論から言うとReactとその周辺のライブラリの変遷に振り回されましたが、hooks APIの登場でしがらみから開放されて(Reduxを使わずに)スッキリしました。
なので最初に言っておくと、Reduxやその他状態管理ライブラリの話はあまりしないです。。それらは誰にとっても必要なものではないのでは?というスタンスです。
共感できる方は「あるある」とか「それな」とか言いながら読んでいただけると幸いです。

これまでのアソビューのReact状態管理

クラスコンポーネントとflux(〜2017年頃)

私は5年ほど前に入社したのですが、その段階だとfacebook/fluxというfacebook社(現Meta社)の提唱したfluxのリファレンス的なライブラリを導入していました。
こちらのライブラリを実際に使っているところを今まで他で聞いたことがないので渋い選択をしたんだなとは思います。(経緯は今となってはわからないのですが)
また、Reactのコンポーネントは全てクラスコンポーネントで構成されていました。

関数コンポーネント、Redux、HoC構成へ (2018年以降)

fluxの使い方も冗長になってる部分もあったことや、状態管理として一般的に普及していなかったため活用事例も多くベストプラクティスなども世に溢れているReduxに書き換えていきました。
また、当時はHoC(Higher-order component = 高階コンポーネント)が流行(?)で、また、関数コンポーネントでもクラスコンポーネントで使えたローカルstateやcomponentDidMountなどのような各関数を使えるようにするrecomposeというライブラリが出てきて使い勝手が良かったので導入し、 関数コンポーネント、HoC with Redux & recomposeという構成で整理していきました。
また、Reduxの設計パターンとしてはDucksが見通しが良かったのでそちらを使ってました。

コンテナコンポーネント(HoCとして状態管理や副作用を管理)とプレゼンテーショナルコンポーネント(コンテナから状態やアクションをpropsとして受け取って宣言的にUIの変化を記述)を分けて複雑な状態管理があるようなページやコンポーネントでも煩雑で読みづらいコードにならないようにしていました。

大体こういう見た目でした。

// SomeComponent/index.js

export default compose(
connect(
  state => ({
    ...state.someModule
  }),
  dispatch => ({
    onClickXxxxx: () => {
      dispatch(someReduxAction())
    }
  }),
  mapProps(
     // ...
  ),
  withState(
     // ...
  ),
  withStateHandler(
     // ...
  ),
  lifecycle({
    componentDidMount () {
        // ...
    }
  })
))(SomeComponent)
// SomeComponent/SomeComponent.js

const SomeComponent = (props) => {
  return (
     {/* JSX */}
  )
}

export default SomeComponent

これらの構成で機能的には事足りていましたが、やはり記述が煩雑になったり手数が多く、シンプルさ、可読性でいうとネガティブな面が目立ってきました。

良かったこと

  • recomposeで関数コンポーネントのままでクラスコンポーネントの機能が使える!
  • Presentational Componentの宣言的UIに対してAPIからのデータ加工、画面操作による状態の変化などの処理はReduxやHoCに寄せることで分離することができ可読性が上がった
  • ajaxの非同期処理をReduxのモジュールの中で完結させ、Presentational Componentには一切それらの記述を書かないようにできた(Redux thunkを使いました)
  • Redux devtoolsで状態の変化がわかったりタイムマシーン機能でデバッグがしやすかった
  • reselectも合わせて使うことでメモ化によりレンダリングコストの削減することができた

課題

  • 手数が多い。
    • ducksパターンでReduxのファイルはドメインごとに一つで全てまとめたものの、やりたいことに対して回りくどくなりがち
    • API一本からデータを取得したいだけで、Reduxモジュールを作ってアクション定義して、コンポーネント側でcomponentDidMountでアクションdispatchして結果をmapStateToProps経由でもらって、、のような。
  • どこに何を書くか、が曖昧になってしまった。
    • HoCはあらゆるコンポーネントに使っていいのか?
    • それだと複雑になりそうなので一番上のPageコンポーネントでのみconnectする形にした。
    • そうなると下位のコンポーネントへのpropsリレーが発生してしまい、特にtypescript導入前だとミスが発生してしまった。typescript導入後は型定義が面倒なことに。。
    • Presentational Componentの状態はコンポーネント付きのHoC(recomposeのwithStateHandler)で持つのかReduxで持つのか?など。
  • これはよく言われていると思いますがHoCと上のコンポーネントから渡されたpropsの重複に気づけずバグにつながったりした。
  • Reduxモジュールのtypescript型定義が煩雑になりがちでany型に逃げてしまうこともあった。

そしてhooks APIの登場(2019年以降)

ある程度それらの構成で作って行きましたが、2019年2月頃にReact 16.8で待望のhooksの正式導入されました。
これまでやってきたことが全て標準のAPIでできるしとてもシンプル、、!

※「HoCは良い設計では無かった、おすすめしない」という趣旨の事をFacebookの中の人か誰かが言っていた気がしたのですがソース見つからず。。

hooks APIが使えるようになってどうなったか

HoCが全く不要になりました。

recomposeの各関数の置き換え

  • 下記の様にrecomposeのAPIは完全にhooks APIに置き換えることができたので変更
  • mapProps -> useMemo
  • withStateHandler -> useState
  • lifecycle + componentDidMount -> useEffect

Reduxの置き換え

  • まずはRedux hooksに変更してconnectのHoCを使わないように
  • reselectのメモ化の恩恵はuseMemoでまかなえるのでそちらに移行
  • 中途半端にビュー関連の状態も持ってしまっていた(例えばモーダル開閉とか)ものをコンポーネントごとのuseStateへ
  • あれ?APIのやり取りとその結果の管理しかしてないReduxモジュールが出てきたぞ。。。↓

REST API処理もhooks化

  • 弊社ではREST APIでデータを取得するケースが多いのですが
  • 以前の記事でも書きましたがREST API用のクライアントhooksを作りました。
  • また、キャッシュ機構が協力なswrをfetch用に優先的に使ってます。
    • postでの通信が必要だったり、環境によって認証情報が違うためswrをラップしたカスタムhooksを作って対応しています。
  • APIのやり取りしかしてないようなReduxモジュールはこちらに移行していきました。

tech.asoview.co.jp

swr.vercel.app

結局Reduxが必要なくなった

  • もちろん弊社の一部のアプリケーションでは、という注意書き付きです!
  • 上手く整理するとコンポーネントに対しての状態管理をそのコンポーネント内で完結させることができた
  • コンポーネントをまたぐ状態管理が必要なケースがそれほど無かった
  • コンポーネントを分割してコンポーネントをlazyロードするようにしてもReduxのStoreは分割できないというバンドルサイズ観点でデメリットがあり、しかもasoview.comはまだspringベースのMPAが中心のため、関係ない画面のReduxモジュールの重さが全画面に影響してしまっています。
  • これらから、カスタムhooksを適切な粒度で分けて組み合わせることで状態管理だけを切り出して整理する必要性があまり感じられなくなってきたため、新規の機能ではReduxを使わなかったり既存でReduxを使用しているものも修正のタイミングで解体していきました。

カスタムhooks活用している具体例

APIのレスポンスを加工して返す

  • JSON色付け係たるフロントエンドエンジニアであれば親の顔より見てきたパターンですね
  • 弊社では基本fetchはuseSWRを使います。(REST API)
  • 一箇所でしか使わず、かつAPIから来た値をそのまま使うのであれば関数コンポーネントのボティ部分にそのまま書くこともありますが、加工したりいくつかのコンポーネントで共用するなどの場合は切り出すことが多いです。
  • 例えば2つのAPIの結果をクライアントサイドでアグリゲーションする、とかだと下記のような形でしょうか。
  • Reduxでreselectで同じことやるとselector関数2つ作ってそれに依存するselector関数をuseSelectorで呼んで、、とかになると思いますがカスタムhooksだとシンプルに済みますね。
export const useSomethingApi = () => {
  const {data: dataApi1} = useSWR('/pass/to/api1')
  const {data: dataApi2} = useSWR('/pass/to/api2')

  return useMemo(() => {
    if (!dataApi1 || !dataApi2) return null
    return /* 何かdataApi1とdataApi2組合わせて複雑な加工する処理 */
  }, [dataApi1, dataApi2])
}
const someData = useSomethingApi()

認証情報を取得した結果をuseContextで管理して全体で使う

  • ログイン後にセッションcookieを使ってAPI通信し、会員情報などを取得する処理
  • ReactのuseContextとswrを使った通信をまとめて専用のContext Providerを作りました。
  • 基本的には一回APIリクエストしてその結果を受け取るだけなのでレンダリングパフォーマンスの心配も不要かと思います。

MemberContextProvider

const MemberContext = React.createContext<CombineMemberContext>(initialContext)

export const MemberContextProvider = () => {
  // useSWRをラップしたカスタムhooks
  const { data: memberInfoData } = useSWRGateway<MemberProfile>('/[会員情報問い合せAPI]')
  // 中略
  return (
    <MemberContext.Provider
      value={{
        ...initialContext,
        ...memberInfoData,
        // 中略
      }}
    >
      {children}
    </MemberContext.Provider>
  )
}

export function useMemberContext() {
  return useContext(MemberContext)
}

使い方

<MemberContextProvider>
  <App />
</MemberContextProvider>
const {isLogin} = useMemberContext()

{isLogin && <MemberFavoritePlans />}

コンポーネントとそれを制御する関数を共通化する(例えばモーダルなど)

  • これまでReduxを使っていたモーダルについてリファクタし、モーダルのコンポーネントと外からモーダルを開く関数をカスタムhooksで返すようにしました。
  • Reduxで作ってたときは、Reduxモジュールの中も使うコンポーネント側も結構な記述量でしたがこのくらいにまとめられました。

※口コミ投稿ボタンはいろんなとこに置くことができて、押すとモーダルが開くというもの

export const useReviewModal = () => {
  const [isReviewModalOpen, setReviewModalOpen] = useState(false)
  const { isLogin, isValidating } = useMemberContext()

  // モーダル開く用の関数。レビュー投稿機能はログインしてなかった場合はログイン画面に飛ばすのでその処理含む。元々はここもReduxのアクション経由で行っていた。
  const openModal = useCallback(() => {
    if (isValidating) {
      return
    }
    if (isLogin) {
      setReviewModalOpen(true)
    } else {
      fallBackLogin()
    }
  }, [isLogin, isValidating, setReviewModalOpen])

  // 同じくモーダル閉じる用
  const closeModal = useCallback(
    () => setReviewModalOpen(false),
    [setReviewModalOpen]
  )
  const ReviewModalHooks: React.FC<ReactModalHooksProps> = (props) => {
    return (
      <Suspense fallback={null}>
        {/* 別で定義してるモーダル本体。この中身はシンプルに別で作った共通のModalコンポーネントを利用してる。 */
        <ReviewModal {...props} isOpen={isReviewModalOpen} onClose={closeModal} />
      </Suspense>
    )
  }
  return [ReviewModalHooks, openModal, closeModal]
}

使うときはこれだけ。これを色々なページに配置していきました。

const [ReviewModal, openReviewModal] = useReviewModal()

<ReviewModal />
<Button onClick={openReviewModal}>
   口コミを投稿する
</Button>

状態管理の方針

なんでフロントエンドの状態管理のツールが必要なのか

個々のReactコンポーネントにおいては宣言的UIで描画するためにコンポーネントに渡されるpropsがあり、それを何らかの操作などで制御したくなったときに持つローカルステート(クラスコンポーネントのstate、FCでhooksで扱うならuseState)ということになるでしょうか。

それを扱うときの注意点としていかに無駄な再レンダリングを防ぐかということが特にアプリケーションが大きくなったときにユーザーの操作感や表示速度にも直結するための大きな関心事であると思います。

そのpropsの変化のタイミングをReduxなどのアクションdispatchに限ったりRedux内部でselectorを使うことで着実に制御するというのが状態管理ライブラリのメリットの一つということになると思います。
また、コンポーネントを跨いで(コンポーネントツリー上で親子関係に無いコンポーネント同士)同じ状態に依存するUIがある場合に、遥か上位からpropsをリレーしたりして見通しが悪くならないようにするというのも可読性やメンテナンス性観点のメリットです。単純にグローバルstateとして例えばAPIから取得したデータを反映したり同期したりという用途でも使えます。
グローバルstateとしての使用は誤ると昔多用されていたwindow領域のグローバル変数のようになってしまいますので最小限にしたいところです。。
アプリケーションが大規模になって複雑になっていくとルールが無いと副作用を含んだ実装をされてしまいどんどん可読性が下がっていく実感はあります。

というわけで、まとめると大規模なアプリケーションにおいてパフォーマンスを落とさずに、実装ルールがつけやすくなるので、誰がやっても開発しやすく壊れにくいようにするというのが状態管理を切り出すメリットだと理解しています。

※ただ、開発しやすい、でいうとReduxは使う上でのボイラープレートが大きいというデメリットがあり、そういう観点でも今だとRecoilは最有力になるかとは思います。

asoview.comにおける状態管理

asoview.comはアクティビティやチケットの検索、予約サイトです。
サーバーとクライアントで頻繁に(例えば数秒単位やそれ以下)情報の取得、更新を行うほどのリアルタイム性のある要件がそこまで多くありません。(在庫など一部はその傾向はあるものの)

「状態」と一言で言っても解釈は多岐にわたると思いますが、asoview.comでは基本的にはページを開いたタイミングでのサーバー(DB)のデータと同期する、必要ならそのデータを加工した上で唯一の情報源として宣言的UIの関数コンポーネントに渡して表示する。

それに対しての検索や購入などの行動を完結させるためのUIのためにコンポーネントの状態が変化していくような流れであり、一連のUIの中でサーバーとの同期や更新などが必要なタイミングはそれほど多くありません。
サーバーとの同期という観点ではswrのkeyベースのキャッシュ機構が優秀でReduxでグローバルstateとして扱っていたようなAPIレスポンスの結果をswrで管理して同期を取るやり方ができています。(swrはとてもお気に入りのライブラリなのでまた別で語りたい。。)

そのため、基本的にはReduxやRecoilなどのReactの外で状態を管理するライブラリは使用せず、Reactの中でカスタムhooksを利用して管理する形を推進しています。

メモ化などで気をつければレンダリングパフォーマンスにも影響無くできると思います。(ここに関しては目を光らせてないと行けないですが)
範囲や更新回数が限定できれば、useContextを活用してコンポーネントツリーの各階層でコンテキストを共有するやり方も有効だと思います。

また、アソビューではB向け(施設パートナー向け)管理画面なども開発しておりそちらではもう少し複雑な状態が必要になる機能を作る可能性はあります。
ただ、現状HoC with Redux & recomposeになっていますがasoview.com同様そこまで状態管理を切り出すことが必要なロジックは無さそうです。

これらから基本的にはReactの標準API(useState, useEffect, useContext, useRefなど)で完結させるように必要に応じてカスタムhooksを作成して整理しています。

hooksで完結させる上で気をつけてること

  • 不必要に再レンダリングを招くstateをuseStateで作ってないか?
    • 直接UI変化に関与しないのであればuseRefを用いる
  • 関数コンポーネントでuseEffectを安易に使ってないか?
    • Reduxで整理していたときにuseEffect + useStateを組み合わせて使ってしまってdepsの副作用地獄(?)になってたことがあるので。。useStateは明示的なユーザーアクションで変化させるようにした方が良いと思います。
  • カスタムhooksの機能はI/Oは妥当か?
    • テストしやすく整理できているか?副作用とそうじゃない部分を上手く分ける。

まとめ

アソビューでは基本的にはバンドルサイズなどのことも考えてライブラリなどの導入は必要最低限にしています。

まだ、先が見越せない段階で安易にライブラリを導入を決めてしまうのは容易に引き返せない(技術的にというよりは一度作ってしまうと引っ剥がしたり別のライブラリの移行する時間や工数を捻出できないという面が多いです。)デメリットがあるので良くないと思っています。

これからも流行っているかどうか(もちろんこれも大事ではあるそうではないfacebook/fluxの扱いなどは苦労しましたので)以上に必要かどうか、他にライトな選択肢は無いかを考えながら設計していきたいと思います。


さて、アソビューではまだまだ変化の早いフロントエンド、Reactにおいて私達と一緒にあーだこーだいいながら設計、実装を進めてくれる仲間を探しております!
興味のある方、ちょっと話を聞いてみたいと思った方は、ぜひ下記ページをご覧いただきお気軽にエントリーいただければと思います。(まずはカジュアルに面談させてもらえればと思っております。)

www.asoview.com

アソビュー!でのEKSクラスターの今までとこれから

こんにちは、アソビュー!SREチームのkirimaruです。 コロナも少し落ち着き、皆さんもGWは大いに満喫していたのではないでしょうか。 残念ながら僕は本を読んで引きこもっていましたが......。

以前「アソビュー!がECSではなくEKSを選んだ理由」という内容でランサーズさんとのイベントでお話させていただきました。

speakerdeck.com

今回はこの時から約2年、アソビュー!がEKSとどう向き合ってきたのか、どう向き合っていくのかを採用している技術とともにご紹介できればと思います。


Intro

前述のイベントでは「大量のAWSアカウントとECSクラスターの管理が辛いから、整理してEKSに統合していくぞ!」とお話させていただきました。このイベントは2020年ですが、2019年に試験的にEKSを導入し、2020年に本格移行の意思決定を行っています。SREチームはまだまだ人数が少なく他の業務と平行しながらではあるものの、既存のAWSリソースの移行とECSからEKSへのアプリケーションの移行、AWSアカウントの閉鎖を現在も行っています。

ではこれが実際どうだったのかというと、現在約7割程のアプリケーションがEKSで起動するまでに至っています。また、AWSアカウントやECSクラスターも整理が順調に進んでいます。

EKSクラスターは繁忙期にはPod数は200を超え、ノードはEC2のスポットインスタンスが100を超える大きなクラスターに成長しました。EKSクラスターはマルチテナント・シングルクラスターで進めており、クラスター内にはワーカータイプやバッチ、プロキシサーバーやAPIゲートウェイ、そしてもちろんWebアプリケーションなど様々なタイプのアプリケーションが起動しています。

この過程で、最初期に構築した試験的なクラスターでは運用に耐えられなくなり、2021年の初頭に大きなクラスターの再構築を経て、現在も継続的に改善を行っています。

再構築の大きな原因はPrivate IPの枯渇でした。今では広く知られている気がしますし直近IPv6への対応*1もありましたが、当時はaws-nodeの設定変更だけでは追いつかず、かといって構築済みのEKSクラスターに新しいサブネットも割り当てることができないため、大きく構成を変える結果になりました。

ここからはいくつかのトピックに分けて、再構築時の分岐点に焦点を当てつつ、今までとこれからをご紹介します。


Infrastructure as Code

2021年のクラスターの再構築に当たり、最も変化の大きかった部分がここになると思います。

それまではEKSクラスターもそれが利用するVPC等もTerraformで構築していました。特にEKSクラスターの構築にはTerraformのモジュール*2を利用していましたが、再構築に当たり下記の理由でeksctlを利用することにしました。

  • Kubernetesバージョンアップの容易性
  • 公式ツールなので、今後の改善や知見の集約が高い確度で見込める
  • 必要な機能がTerraform moduleで実装が遅い場合がある

eksctl.io

ただし、EKSクラスターとそれ以外のVPC等のAWSリソースのライフサイクルが異なること、バージョンアップの容易性の担保やクラスターの作り直しも加味して、EKSクラスターはeksctlで管理し、VPCなどそれ以外のリソースをTerraformで管理運用していく形に決めました。

少し話が逸れますがアソビュー!は2022年7月から11期に入る、ベンチャー企業の中では歴史を持っている会社です。この歴史の中でインフラが混沌としていったのは先のイベントでも触れさせていただきました。新しい技術もその有用性があれば積極的に導入をしていっているアソビュー!ですが、混沌期の急速なサービスの成長と拡大にIaCが完全には追いついていけてなく、一部分のみの適用になっていました。そこで、今後のIaCの利用の拡大を推進するためにも、eksctlの導入と同時にTerraformとeksctlを並行して使えるような形でIaC用のリポジトリとCICDの再設計を行いました。

これらの対応により直近あったEKSのバージョンアップ対応もスムーズに行え、IaCの利用も順調に加速していっています。積み重ねが多いので100%すべてできたぞ!とはまだいきませんが、この調子で進めばそう遠い未来でもないと感じています。

CICD

IaCの項目も一部含まれますが、CICDも2021年のクラスターの再構築で手を入れました。

これまでのCICDはCircleCIでビルドからデプロイまでを一気通貫で行っていました。所謂CIOpsと呼ばれるオペレーションです。この際のKubernetesのマニフェストの管理はアプリケーションとミドルウェアで分かれており、アプリケーションはアプリケーションリポジトリ内、ミドルウェアはミドルウェアを一括でまとめたリポジトリで行っていました。これにより見に行く箇所が多く、マニフェストの変更にトリガーされてビルドとデプロイが走るなど、管理運用に課題感を持っていました。前述のIaCの見直しに合わせて、この課題の解決のためKubernetesのマニフェストの管理も整理していくことにしました。

そこで目を付けたのが Argo CD です。

argoproj.github.io

CIOpsにはシンプルで理解しやすく容易に構築できるメリットがあります。しかし、カナリアリリースなどの高度なデプロイ手法の導入や、CIツールが過剰に権限を持つことによるセキュリティリスク、冪等性担保の難しさ等を鑑み、Kubernetesとの相性も良いGitOpsの導入を考えました。また、その中から検討当時UIを持っていることでの取っ掛かりやすさや、周辺エコシステムによる拡張性の高さから、アソビュー!ではArgo CDを導入することにしました。

導入当初はミドルウェア用のリポジトリを改修してミニマムに利用を開始していましたが、現在はアプリケーションにも適用して段々とその利用を拡大させています。同時に、Kustomizeを導入することによりマニフェスト管理自体も効率化させています。

Argo CDを使ったCICD Pipelineの簡易構成図

今後はよりアプリケーションでのArgo CDの利用を拡大していくとともに、元々予定していた高度なデプロイ手法の導入や、Kustomizeのプラグインを利用した効率的なマニフェスト管理の導入を予定しています。

また、CI部分ではコンテナイメージのビルドに一部でCNBでのビルドも導入し始めました。こちらも今後利用の拡大を行っていく予定です。

ミドルウェア

最後に導入しているミドルウェアについて、一部ご紹介させてください。

Argo Workflows

argoproj.github.io

当初EKSクラスター上で起動するバッチはCronJobで定義していましたが、より複雑な条件を付けて実行する必要のある案件やPipelineの構築が必要になってきました。ワークフローエンジンはいくつか選択肢がありますが、アソビュー!ではArgo Workflowsを導入しました。

ざっくりとArgo Workflowsでできることを挙げると下記のようになります。

  • Kubernetes上にworkflow管理のためのUIとCRDを展開
  • workflowの各ステップそれぞれをKubernetesのmanifestとして定義、podで実行
  • マルチステップ、DAGなど複雑な依存を定義、UI上での操作、確認
  • EKS on Fargateでの実行

Argoのツール群のひとつであるArgo CDを導入していることもありますが、Argo Workflowsを選んだ理由はArgo Workflowsの方が開発者と管理者にとって学習・運用コストが低いと考えたことにあります。Kubernetesクラスター上で動かすだけであれば他にも選択肢はありますが、EKSを使っていく意思決定をしているため、アプリケーションと似たように設定できることや処理の全体感を確認できるUIを持っていることが導入の決め手になりました。管理しているcronの一覧が見られるだけでもワークフローエンジンは導入する価値あります。非常に便利です。

構成は下記のようになっています。

Argo Workflowsの構成

失敗したときの通知をDefault Workflow*3の機能を使ってSlack通知を行っている部分が工夫ポイントです。

今後利用を拡大させていく予定ですが、すでに既存の一部のバッチをArgo Workflowsに移行しているだけでなく、機械学習用のデータPipelineの構築も行っています。EKS on Fargateはログの扱いがやや難しいので、Firelensのこれからのアップデートにも期待したいところです。

AWS Load Balancer Controller

定番ではありますが、AWS Load Balancer Controllerも利用しています。

github.com

アソビュー!ではそれぞれのサービスと環境を分離させるため、それぞれに対して個別にNamespaceを区切って1つのクラスター内で同居させる構成をとっています。v2になってからNamespaceを跨いだ定義ができるようになったことで、非常に管理がしやすくなりました。以前は中間にNginx Ingress Controllerを挟んだ構成になっていたため特に痛感しています。

よく一緒に使われているExternalDNSですが、アソビュー!では利用していません。これはEKSクラスターとDNSのライフサイクルの差が大きいです。Load Balancerも含め、ライフサイクルを意識する機会がEKSを運用する中で何度もでてくると感じています。AWSの設計思想とKubernetesの設計思想の差異の中でどうそれぞれを管理運用していくか、面白い部分でもありつつ非常に難しい部分です。

Kubernetes External Secrets

非推奨に……なりましたね……。

github.com

以前ご紹介させていただいたものですが、移行先としては上記で案内されている「External Secrets Operator」が良いと思っています。導入後には改めてご紹介できればと思います。

tech.asoview.co.jp

github.com

最後に

振り返ってみるとここ数年でアソビュー!のインフラは大きく進化を遂げているなと改めて感じました。

目まぐるしくアップデートが重なる界隈ですが、自社のValueである「For You」を実現するためにこれからもよりよい技術を積極的に取り入れて改善を続けていき、サービスを成長させていきます!

アソビュー!では一緒にサービスを成長させていく仲間を積極的に募集しています!少しでもご興味の湧いた方は以下のリンクからぜひご応募ください。

www.asoview.com

アソビューの SaaS 事業を支えるウラカタチケット - 開発チームからプロダクトまで紹介

エンジニアの村松です。最近は低温調理にハマっており週末にはいろんな肉や魚を低温調理しています。オススメは鶏むね肉を64℃で2時間です。2時間待ってる間にビール2-3杯は飲めます。オススメです。

はじめに

アソビューでは、サービスECSaaS の大きく2つの事業を展開しています。

SaaS 事業の1つに、テーマパークや水族館などのレジャー施設向けチケッティングシステムとして「ウラカタチケット」を提供しています。

今回は、ウラカタチケットの開発を担当している「プロダクト部 SaaS ユニット」のことや開発/運用しているプロダクトについて紹介します。

SaaS ユニット紹介

2022/05時点、SaaS ユニットは11名のメンバーで構成されています。メンバーの内訳は、バックエンド8名、フロントエンド1名、QAエンジニア2名となっています。

現状、フロントエンドエンジニアが少ないのですが、タスクベースに開発を担当することが多く、バックエンドエンジニアがフロントエンドの開発をすることは多々あります。もちろん、フロントエンド/バックエンドのエンジニアが相互に PR をレビューするため、業務を通してスキルの幅を広げられる機会にもなっています。

QA に関しては、現在、リリースサイクルの見直しを図っており、それに合わせてテストプロセスの改善を進めています。以前は案件ごとにテストを実行することが多かったのですが、リリースサイクルを固定してリリース前にリグレッションテストを実施することでより品質を安定させられるようなプロセスを準備しています。

また、Autify の導入を推進しており、リグレッションテストの自動化にも取り組んでいます。Autify 社の事例紹介にも載せていただいているので、ぜひご覧ください。

autify.com

プロダクト紹介

SaaS ユニットでは、施設/社内向けのプロダクトを開発/運用しており、約1000の施設にサービスを提供しています。

パートナーダッシュボード

パートナーダッシュボード は、レジャー施設 (弊社ではパートナーと呼んでいます) の担当者が購入情報や販売実績/着券実績、在庫情報などを閲覧/管理するためのシステムです。パートナーの基幹業務の中核を担う、ミッションクリティカルなシステムです。

主な利用技術 : Java, Spring Boot, React など

チケットマネージャー

チケットマネージャー は、社内向けのシステムで、施設の情報やチケットの情報を登録/管理するためのシステムです。社内向けシステムではありますが、パートナーが販売する商品を扱うシステムであり、こちらもミッションクリティカルなシステムと言えます。

主な利用技術 : Java, Spring Boot, Thymeleaf など

バックエンド API

バックエンド API は、アソビュー! で表示する施設やチケット情報、購入/着券する際の API 群を提供するバックエンドシステムです。また、アソビュー!だけでなく、外部サービスにチケット情報を連携したり着券するための API も提供しています。これらの API がダウンしてしまうと、購入や着券ができなくなり多方面に影響が発生していまいます。こちらもやはりミッションクリティカルなシステムだったりします。

主な利用技術 : Java, Spring Boot

チケットダイレクト

チケットダイレクト は、レジャー施設のサイトから直接チケット購入するためのランディングページを提供するシステムです。EC の仕組みを持たないレジャー施設でもチケットダイレクトを導入することでチケット販売できるようになります。

主な利用技術 : React

Fast-In

Fast-In は、レジャー施設の担当者が、来場したお客様 (弊社ではゲストと呼んでいます) がスマホなどで提示するQRコードを読み取って着券する (チケットを使用済みにする) 際に使用する Android/iOS アプリです。着券業務はパートナーにとっても重要な業務であり、特に繁忙期には非常に多くのゲストが来場するため、迷いなくスムーズに着券操作できる UI/UX が求められます。

主な利用技術 : React Native, Expo

SaaS ユニットは、エンドユーザーにとって重要なシステムを開発/運用しているチームです。 アソビューの開発事例としてこちらのインタビュー記事もぜひご覧ください。

type.jp

どのように開発しているか

SaaS ユニットでは、パートナーの経営効率化を実現するために案件ベースで新規機能開発に取り組んでいます。各案件はそれなりの規模になることもあるため、数人のメンバーでプロジェクト体制を組んで開発を進めています。

その他、パートナーからの要望や個別の改修などもあり、これらはタスクベースで各メンバーが開発を担当します。冒頭で述べた通り、バックエンド/フロントエンド関係なく開発を担当することが多いため、スキルの幅や柔軟性が求められます。

どういうひとが活躍しているか

案件ベース/タスクベースの開発いずれにしても、パートナーやビジネスサイド、プロダクトオーナー、チームメンバーといったステークホルダーとコミュニケーションして DX を推進する力が求められます。

アソビューと言えば、BtoC プロダクトを開発している会社というイメージがあるかもしれませんが、このように BtoB プロダクトの開発もやっており、SIer 出身者も多く在籍しており活躍しています。

横浜・八景島シーパラダイス様との取り組みに関してインタビュー記事を掲載しています。ぜひご覧ください。

www.asoview.co.jp

まとめ

今回は SaaS 事業のうち、ウラカタチケットの開発を担当している SaaS ユニットとプロダクトについて紹介しました。その他の話にもご興味がありましたらこちらもぜひご覧ください。

www.asoview.com

アソビューでは「生きるに、遊びを。」をミッションに、一緒に働くメンバーを募集しています!ご興味がありましたらお気軽にご応募いただければと思います!

www.wantedly.com

【社外講師講演】株式会社Preferred Networks 執行役員 福田様に講演いただきました!

はじめに

アソビューの井上です。
弊社では毎週1時間全プロダクトメンバーが集まるテックトークという場を設けており、何らかの技術ネタなどについて共有、LTなどを行って部やチームをまたいで知見やノウハウの共有や意見交換などをしています。

普段は社内のメンバーでの実施なのですが、弊社CIO田中の元同僚というつながりでなんと、株式会社Preferred Networks 執行役員 福田昌昭 様にお話いただけることになりました!
※以下Preferred Networks様はPFN社様とさせてください、

※ちなみに福田さんと田中はソニーでプレイステーションネットワーク(PS3時代)などの開発をされていた時の同僚とのことで、それだけで私のような当時の学生時代の青春をゲームに捧げていたようなものにとっては感謝の気持ち、畏敬の念でいっぱいでございます!本当にありがとうございました!

f:id:masino83:20220322155428p:plain

福田様のご経歴

ソニーでプレイステーション3やプレイステーションネットワークの開発に携われた後に 当時まだ80人程度(!)だったグリーにご入社されています。
今では考えられないほど小規模の段階なのでエンジニアとして開発プロセスもその場で作りながらやっていくような環境だったとのことです。 そこからソーシャルゲームのブームでどんどん事業も組織も拡大する中まさにその拡大にも貢献されていたそうですが、(退職されるときは3000人になっていたそうです。すごい。。) グリーで統計や機械学習を用いた分析をご経験されていたこともあり、そこからソニー時代の上司の方からのお誘いでPFNにジョインされたそうです。
そしてやはり規模の比較的小さい組織で企画から開発まで全部やるような環境で様々な事業を手がけられているとのことです。
ソニーのPS3、プレイステーションネットワークに始まりソーシャルゲームブーム期のグリー、そして現在のAI技術活用のトレンドの中でのPFNという熱い時代の熱い会社で活躍されてきたとても濃いご経歴だなと思いました!

謎多き企業PFN様の事業

今回の講義ではPFN様の事業の内容をいくつかピックアップして紹介いただきました。
個人的にPFN様は日本を代表するユニコーン企業!として認識しており、創業者を始めとして手練のエンジニア集団である。
というイメージだったのですが、一方具体的にどういった事業をやっている企業なのかはほとんど知りませんでした。
印象的だったのは

  • 自社スパコンを持っている(省電力性能ランキング2020年、2021年世界1位)
  • ディープラーニングに特化したプロセッサを作っている
  • Chainerという深層学習フレームワークの開発をしていた(現在はメンテナンスモードでPyTorchの開発に参加されているようです 参考

というところでこれだけ聞いても私達アソビューのようなWebサービスのベンチャーとはだいぶ趣が違いますね。

また、今回お話を聞いて改めてAIや機械学習を軸にかなりの幅広い業態のクライアントとコラボして様々な活動をされているということを認識出来ました。
お聞きした中でいくつか印象的なポイントをピックアップすると。

イラストをAIが着色してくれるサービスPetalica Paint

petalica-paint.pixiv.dev pixiv社とのコラボということで。こちらに関しては無料で運営されているようです。無料。。

アニメーション映画の制作にニューラルネットワークを活用

projects.preferred.jp これまで膨大な工数が必要であった群衆シーン(モブ)の映像を作成できるとのことです。

東映アニメーションとコラボして背景美術制作工程の効率化

www.preferred.jp PFNが開発するアニメの背景美術制作支援ツールScenify™を活用して背景美術作成を効率化。

小学生向けのプログラミング教材開発

playgram.jp まるでプレイステーションのゲームのようなIFで遊びながら学べる本格プログラミング教材です。

高精細な3Dスキャン

projects.preferred.jp

これまで難しかった透明なものも含め質感も再現した3Dデータに数分レベルの速さでスキャンしてモデリングできるとのことです。

今回の共有いただいた資料では馴染みやすいクリエイティブ分野の話を多くしていただきましたが、他にも工業分野を始め様々な業界向けに事業展開されています。
アニメから工業製品の検査という振れ幅の広さは圧巻です。。 www.preferred.jp

技術ありきのプロジェクト、ニーズとシーズと

PFN社様のプロジェクトの進め方についてのお話を聞いていて弊社には無いパターンだなと思ったのが、テーマによっては研究からはじまる技術題材があって、後からニーズが付いてくるようなケースです。

例えば弊社アソビューのようなビジネスモデルだとゲスト(一般消費者)の「週末何をしよう」や、パートナー(体験事業者、施設)の集客したい、というお困りごと=ニーズに対してマッチングするプラットフォームを提供している構図で、そういったニーズを顧客ファースト志向で掘り下げていってサービスの改善や提供をしていきます。
そのために必要な技術やシステムなどを開拓したり構築したりするという進め方となっています。

一方PFN社様の場合はAI、機械学習を軸としてできることのシーズが有ってそれを社会の課題=ニーズに対してマッチさせていくという方向性が多いと思いました。
例えばアニメーション業界の制作側の人材難、特に背景制作できる人材は需要に対して少ないという課題において先程の支援ツールが適合しないかというところを実際に美術の人にヒヤリングしながらエンジニアとすり合わせていってできることを探っているとのことです。
おそらくここはプロジェクトにもよるとは思いますがアプローチが全く違うのは興味深かったです。

これはAI、機械学習という汎用性がものすごく高い技術領域であるということと、その領域に対して高度な応用技術や知見を持ったエンジニアが多く在籍されているというPFN社様ならではの課題解決のやり方という理解をしましたが、一般のWeb企業の研究開発部門でもこういった進め方は非常に参考になりそうだなと思いました。
アソビューではR&Dに特化した部門はまだ無いですが、例えばレコメンドに機械学習を取り入れる検証を始めようとしておりシーズとニーズをすり合わせて課題解決のための実装をしていくプロセスなどは参考にできそうかも?という印象を受けました。

事業と技術とプロダクトと組織と

一方、課題だとおっしゃっていたのが、以前までは個々のエンジニアが企画開発運用まで全部やるような形で進められていたようで
例えば技術観点でエンジニアの個々の判断で違った言語を使ったり(今はpython中心とのことです)してしまい保守性に乏しくなったりすること、 エンジニアのできること、やりたいことベースにプロジェクトが進んだりして課題に対してコストが高い(いわばオーバーキルのような状態)になるなどがあったそうです。
そういった課題に対して、今はプロダクトマネージャーやビジデブ人材を採用したり組織体制をある程度階層化したりして事業の拡大に合わせてスケールできる組織を作っているとのことでした。

エンジニアの自主性が高いというのは強みでありながらスケールするに従って課題にもなりうるというのは共感できます。
弊社でも現在エンジニア採用強化中で、人数規模を拡大している最中ですが、エンジニアが10人台程度だったころから比べると求められる人材やスキルセットが変わり、プロダクトを作る上で意識しなくてはならない長期的な保守性や可用性をどう開発組織として担保するかなどを考えるフェーズに入ってることを実感しております。

まとめ

今回の話を聞いて、「最先端の技術を最短路で実用化する」ということを掲げられているPFN様の課題解決の範囲の広さや展開しているプロジェクトの一端を知ることができ、私達の課題解決とは違いが垣間見えました。
一方課題解決に対して技術やプロダクトを用いてどう解決していくか、それをスケールさせていく課題などはつながるところがあり、今後アソビューのプロダクトを発展させていく中で参考になりそうな視点もあると思いました。

福田様、ご講演いただきありがとうございました!


We are hiring!

今回は特別会でしたが、アソビューのテックトーク(週次の社内LT会)ではこれからも、今回のような自分たちの事業から少し離れて俯瞰的な視野を持てるような講義なども含めて様々なコンテンツを用意して社内エンジニア同士の交流を増やし、技術力や知見を増やせる場にしていきたいと思っています!

アソビューでは一緒に事業を作っていく仲間を募集しています!
そんなアソビューの環境で働きたいと思った方は、ぜひカジュアル面談をしましょう! www.wantedly.com

カジュアル面談しませんか?

f:id:jjebejj:20220331202210j:plain

こんにちは。アソビューCTOの江部です。

アソビューのことをもっとよく気軽に知っていただくために、みんなでMeetyをはじめました。

  • 最近よく聞くけど実際どうなの?
  • どんなサービスをやっているの?
  • アソビューからスカウトがきた!
  • 自分に合うのか?
  • どんな人がいるの?
  • etc

いきなり選考プロセスに乗るのは抵抗があるという方も、とりあえず中の人の話聞きたいとおもったら誰とでもお気軽にどうぞ!

 

meety.net

meety.net

meety.net

meety.net

meety.net

meety.net