こんにちは! BASE BANKです。 最近は大きなカンファレンスだけでなく様々なコミュニティのオフラインイベントも増え、かつて以上の活気で溢れているなと感じています。 我々BASE社も大小さまざまなカンファレンス、イベントにスポンサーをさせていただいておりますが、今回はBASE BANKとしてももっとスポンサーの頻度をあげていくぞ!スポンサーさせてください!という内容の記事です。 BASE BANKって? スポンサーの理由やイベントとのマッチングのために、まずは軽くBASE BANKについて自己紹介させてください。 BASE BANKはBASE社の1事業部です。 「銀行をかんたんにし、全ての人が挑戦できる世の中に」というミッションを掲げ、個人やスモールチームの資金繰りに関する課題解決を行っています。 https://speakerdeck.com/base/basebank 現在、「BASE」のショップオーナー向けには、「YELL BANK」、「BASEカード」、「お急ぎ振込(振込申請)」の3つを提供しており、グループ会社のPAY.JPと協業し「PAY.JP YELL BANK」として「BASE」以外のプラットフォームへも広く価値提供をし始めたところです! 8月に公開したIR資料からもわかるように、ありがたいことに「YELL BANK」を筆頭に各プロダクトがめちゃくちゃ順調にグロースしています。 しかし、もっとBASEグループ全体をリードできるような事業部へと成長していくために、現事業のグロースと新規事業の創出の2軸をフルアクセルで推進しています。 https://contents.xj-storage.jp/xcontents/AS08546/360b2858/87ab/484c/9da2/062c0fb17663/140120240806563776.pdf 現在、エンジニアとBizdev、事業企画のポジションをオープンしていますが、特にエンジニアを積極大募集中です! https://open.talentio.com/r/1/c/binc/homes/4380?group_ids=9203 なんでスポンサーしたいの? スポンサーをしていきたい理由の1つは事業部の認知度向上のためです。 BASE社としては、ありがたいことにこれまでのスポンサーの積み重ねやCMなどを通じて認知してくださっている方が多くいらっしゃいます。 しかしBASE BANKという事業部としてはまだまだ認知度に伸びしろがあり、”BASEってECだけじゃないんですね!”とスカウトやイベントなどで初めて知っていただく機会がまだまだ多いです。 上にも書いたように、さらなる提供価値や提供顧客の拡大のために現在フルアクセルで事業と組織の増強をおこなっているところですが、まだまだ仲間が足りません。 めちゃくちゃおもしろいことやってる事業部があるよ!やっていきたいことのためにまだまだ仲間が必要だよ!というアピールの場を増やしていきたいと考えているのが1つ目の理由です。 理由の2つ目として、コミュニティの発展をサポートしていきたいという思いがあります。 コミュニティやイベントの存在が日々のトレンドキャッチアップやアウトプットの起点にもなり、さらにそれを通じた”ゆるいつながり”が生まれることで会社の組織文化を見直すよい機会にもつながったりします。 我々もこういったコミュニティの恩恵を受けてきたこともあり、会社としても昔から様々なコミュニティへスポンサーとして微力ながら応援をさせていただいていました。 これまではPHP ConferenceやGo Conferenceなど、比較的大きなイベント、コミュニティへのスポンサーがメインでしたが、より細かく継続的にBASE BANKを知ってもらえる機会を増やしたい、コミュニティの裾野を広げるお手伝いをもっとやっていきたいという思いもあり、今回スポンサー立候補をするに至りました。 一緒に組んでいきたいイベント、コミュニティ BASE BANKとしても、事業や組織のあり方、技術スタックと親和性の高いコミュニティ、イベントとタッグを組んでいきたいと考えています。 具体的なジャンルとしては以下を想定しています。 事業領域 Fintech EC 開発プロセス スクラム アジャイル プログラミング言語 PHP Go TypeScript(React, Vue) 規模としては~100人規模を想定しています。 あくまで現時点での想定なので、上に書いた以外でも理念に強く共感させていただいたり、親和性の高さを感じたコミュニティやイベントとのご縁があればぜひお手伝いさせていただきたいです! BASE BANKとしてご提供できるもの 会場スポンサー 東京都港区六本木三丁目2番1号 住友不動産六本木グランドタワー 37F 最大50名程度収容可能(椅子、テーブルありの場合) レイアウト例 (約40名規模のイベント) https://devblog.thebase.in/entry/welcome_fintech2 発表用の演台があり、その左右にプロジェクタを使って投影することができます。 飲食スポンサー 予算は10万程度までを想定しております。 一旦10万以下とさせていただいておりますが多少調整は効くので、予算と提供するドリンクや食事については都度ご相談させてください! イベント時にさせていただきたいこと イベントの何処かのタイミングでBASE, BASE BANKの会社紹介をさせてください! 3分程度お時間を頂戴します。 ご連絡先 とりあえず話を聞いてみたい!というだけでも構いません。以下フォームからぜひお問い合わせください! https://binc.jp/contacts/jobs 会場や予算の確認のため、イベント開催の1ヶ月前にはお声がけいただけると幸いです。 おわりに 今回ブログとして告知を出させていただきましたが、こちらからも積極的に直接お声がけさせていただきます。 また、事業を一緒に作っていく仲間も大募集中です! https://open.talentio.com/r/1/c/binc/homes/4380?group_ids=9203 少しでもご興味ある方は是非お話しましょう!
はじめに BASEのProduct Dev / Feature Dev1 GroupでアプリケーションエンジニアをしているTorataです。 BASEに入社して早くも3ヶ月がたちました。 少しづつBASEの仕事や環境、文化にも慣れてきたので振り返りを兼ねて入社エントリーを書こうと思います。 BASEに興味を持っている方の参考になれば嬉しいです! 入社の経緯 前職では、新卒から約5年間、バックエンドエンジニアとして働いていました。 周りには信頼できる素晴らしい方々が多く、幅広い経験をすることができました。 ただ自身のキャリアを考えたときに、より大きなチームで大規模なシステムを扱う経験を積みたい、その中でさらにエンジニアとしての専門性を高めていきたいと思い転職を決意しました。 BASEに入社した理由は、ビジョンに共感し、成長できる環境が整っていると感じたからです。BASEのプロダクトは「個人やスモールチームをエンパワーメントする」ことにフォーカスしており、誰もが大きな組織に頼らずとも活躍できる時代に非常にマッチしたサービスだと感じました。 また、私の身近な人もBASEを利用していたこともあり、彼らのような人々を支えたいという強い思いが芽生えました。 さらに、BASEのエンジニア組織ではカンファレンスでの登壇や、現在私が書いているテックブログのような発信活動が盛んに行われており、そうした環境で自分が成長できる姿をイメージできたことも、入社を決めた大きな理由です。 BASEのいいなと思うとこ 1. チーム外のメンバーと交流できる機会がたくさんある BASEでは、入社後8回までチーム内外のメンバーとランチに行ける「メンターランチ」や、3ヶ月に1度オフィスで開催される「締め会」、午後7時以降にオフィス内のバーカウンターでアルコールを含む各種ドリンクを楽しむことができるなど、社員同士が交流できる機会が多く設けられています。 私も入社してからチーム内外の多くの方々と交流することができました。 私は前職は毎日オフィス出社の会社だったのでハイブリットワークを実施しているBASEでのコミュニケーションの取り方に不安があったのですが、なんなら前職よりも他の方と話す機会が多いんじゃないかと思うくらいにコミュニケーションを取れる機会が多く設けられています。 コミュニケーションを通してどういう人か分かっている方が業務もスムーズに進められるし、こういう機会を通して普段業務では関わりのない人とも交流を持つことができるので大変助けられています。 2. 「Move Fast」で支え合う文化がある チャットで困りごとや疑問を呟くと、すぐに多くのメンバーが助けてくれます。 特にオンボーディング期間中は、新しい環境に対する不安や疑問が多かったのですが、何度も助けてもらいました。 実際、自分のオンボーディングチャンネルに「ここってどうなっているんだろう?」とか「これ詰まっちゃったなー」みたいな困りごとを雑に投げても誰かしらがそれを拾ってくれて説明したり解決まで持っていってくれます。 細かな疑問やちょっとした悩みにも迅速に反応してもらえることで、何かあった時には誰かが助けてくれるという安心感と、もし困っている人を見かけたら自分も同じように助けてあげたいといういい循環ができているなと感じています。 BASEにはMove Fast以外にも行動指針があって、これらの”BASEらしさ”を個人的には魅力に感じています。 3. モダンとレガシー2つの環境を経験できる BASEは10年以上続いているサービスであり、長年使われてきたリポジトリと、リプレイス先の新しいリポジトリの2つが存在しています。 新しいリポジトリではモジュラモノリスが採用されており、現代の水準に合ったクリーンなコードに触れることができます。 一方で、古いリポジトリも改善が進められており、レガシーコードにどう立ち向かっていくかを経験できます。 エンジニアとしては常にモダンな環境で開発をする方が楽しいかもしれませんが、現実的にはレガシーコードとも向き合うことが避けられないと個人的には考えています。 モダンとレガシー2つの環境を経験することでエンジニアとして大きく成長できるんじゃないかと今からワクワクしています。 今後やりたいこと 私の周りには、非常に優れた、尊敬できるエンジニアが多くいます。まずはそのレベルに追いつくことを目標に、日々努力しています。 現在は多くを学びながら、チームのサポートを受けている段階ですが、将来的には「自分だからこそできる」貢献を模索し、チームや組織に新たな価値を提供できるエンジニアを目指したいと考えています。 おわりに 以上で私のBASEの入社の経緯や入社していいなと思うところを紹介しました。 この記事を読んで少しでもBASEに興味を持ってもらえたら嬉しいです。 BASEは現在エンジニア積極採用中なので興味があれば採用情報ぜひご覧ください! BASEで一緒に働きましょう! binc.jp
はじめに こんにちは。Product Management Group で プロダクトマネジメント をしている坂東( @7auto )です。 リソース的な問題で「やるべきことがたくさんあって、小さめの改善やPJに手が回らない」そんなお悩みを持つ方はたくさんいらっしゃるのではないでしょうか。 サービスが大きくなるとPJの規模も大きくなっていきます。その結果、小さめのPJや改善の優先度が下がりがちになります。 一方で、小さめのPJや改善はサービス利用者の声から生まれることも多く、これを放置し続けることはサービス体験の悪化に繋がります。 そこで大きなPJと並行して、こうした小さめのPJや改善に対し「最小のコミュニケーションコストで機能リリースする」というコンセプトで立ち上げからリリースを行いました。 「全員集まったのはキックオフと振り返りだけ」そんな定例もDailyも無いPJを通して、低コストなだけでなく個人の成長にもつながるメリットがあるように感じられました。 本稿ではそこから得られたことを共有できればと思います。 低コストをコンセプトにした背景 当時、自分は本件の他に3PJ(そのうち開発が2件)を同時進行していました。 他のPJではアジャイルな開発方式を取っており、毎週スプリントイベントDailyMTGを実施しながら漸進的に進めていました。 アジャイルな開発方式を取ることで不確実性への対処は容易になる一方、コミュニケーションに割く時間が大きくなります。 そのため、3開発をアジャイルにすると時間的な面で自分がボトルネックになる懸念を感じました。 そこで、開発規模が一番小さかった本件のPJはアジャイルにとらわれず、できるだけコミュニケーションコストを下げるようPJを設計しました。 メンバー構成・削ったこと・スケジュール感 このPJメンバー構成はプロダクトマネージャー(自分)、デザイナー、バックエンドエンジニア、フロントエンドエンジニア、プロセスエンジニア、直接手は動かさないプロジェクトマネージャーの6名で、それぞれが別のPJも兼務していました。 プロダクトマネージャー、デザイナー、エンジニアは一緒に仕事するのが初めてのメンバー同士でした。 また、各メンバーが別のPJを兼務している都合上、全員が揃うのを待つことはせず、各工程をFIXさせて次の工程に進めるウォーターフォールに近い形になりました。 実際のリリースまでのスケジュールはざっくりと以下のような流れになりました。 2週間:PdMが企画・ドキュメント化 2週間:デザイナーがUI/UXを確定 4週間:エンジニアが開発 2週間:PEがQA リリース コミュニケーションを削れるだけ削ったため、リリースするまでに全メンバーが顔を合わせたのはキックオフだけで、アドホックなMTGも数えるほどでした。 PdMとして気をつけていたこと コミュニケーションを削るということは、デザイナーやエンジニアはドキュメントから必要十分な情報を引き出せる必要があることを意味します。 なので企画の段階で体験やお問い合わせ時の対応なども考慮し、要件・体験・実装を意識したPRDを作成していきました。 それでもいくつか質問を受けるケースがありましたが、質問を受けた際は2分以内で答えるくらいの気持ちでやりました。 *1 結果的に特に大きなトラブルもなくスムーズにリリースできました。 このPJを通して得られたこと 低コストで大きな手戻りもなかったので、全体的にスピーディーに無駄なく価値提供できました。 今回のような方針でPJを設計することで、手が回りにくい小さめのPJも並行して動かせると感じました。 また、リリースを通して客観的に自身を見直す機会を得られたことも非常にポジティブにとらえています。 ウォーターフォールに近い開発スタイルとなったことで以下を意識する必要があったため、(仕事をする上で当たり前でありますが)普段の仕事の姿勢を改めて考える良い機会になりました。 自身で作成したスケジュールに責任を持つ 情報伝達の内容に責任を持つ 状況変化に対する報連相の意識が高める 特にこのPJではDailyもないので「明日共有すればいいや」という気持ちにならなかったことが大きいと感じました。 また、自身のドキュメンテーションの質を客観的に見直す良い機会となりました。 PdMとしてはドキュメントで必要十分な情報を伝えなければならなかったことで、以下を改めて意識することになったためです。 不明瞭さを残さない 無駄なことを書かない 読み手のコンテキストを意識する 最後に、今回は小さいPJかつ初めてのメンバーとの仕事だったので、PJ運用でトライしたかったことを小さく試すことができました。 PJ規模が大きくなると、PJ運用のスケジュールへの影響も無視できないため、積極的なトライがしにくくなります。 そのため、こうした方式のPJは実験、息抜き、マンネリの解消といった意味も持たせることができるように感じました。 おわりに 小規模なPJであれば、コミュニケーションを削ぎ落としてPJの並列数を増やすことができました。また、副次的に仕事の質やプロセスを見直すという価値も持たせることができました。 小規模の開発に割くリソースがない方、時間がないとお悩みの方、いつものやり方にマンネリを覚えている方は、勇気を持ってどこまで軽量にリリースできるかを楽しんで見てはいかがでしょうか? 最後に宣伝です。BASE ではプロダクトマネジメントをするメンバーを募集しています。 興味がある方は下記の紹介資料や、採用情報もぜひご覧ください。 binc.jp *1 : リリース後の振り返りでエンジニアからFBを頂いたのですが、すぐに返答することがDaily(強制的に集まって問題を確認する場)を設けずに済んだ要素になっていたようです。
はじめに はじめましての人ははじめまして、こんにちは!BASE BANK Divisionのフロントエンドエンジニアのがっちゃん( @gatchan0807 )です。 ネットショップ作成サービス「BASE」の開発チームからBASE BANKチームに 社内異動をして 、チームの人数が半分以下のチームになってから約半年が経ちました。 そんなチーム環境の変化と共に、私がどんなことを考えるようになったのか、BASE BANKチームとはフロントエンドエンジニア目線でどのようなチームなのかを、「小さなチームでフロントエンドエンジニアという職種で働くことの面白さ」と合わせて紹介させてください! 個人的には、今回紹介するような活動をすることでプロダクトを前に進めてユーザーに価値提供することもできるし、ビジネスの成長にも寄与することが出来るだろうと考えているので、読んでくださった皆さまの参考になれば嬉しいです! チームの面白さの紹介の前に… チームの紹介をする前にまず、ちょっとだけ私の自己紹介がわりに私が「フロントエンド」という業務領域をどう捉えているのかについて共有させてください。 ひとことで言うと、私はフロントエンドを「データ(システム)とユーザーの 境界面 である」と考えています。だからこそ、とても面白くて大好きな領域なのです。 もう少し具体的なお話をすると、サービス・プロダクトを利用しているユーザーは画面に表示されているデータしか知り得ません。それは、社内用の管理画面であってもBASEやPay IDが提供しているサービスであっても同じです。 この前提に立つと、 UIを実装するフロントエンドエンジニアが正しくUIに表示させる事ができないと、ユーザーに対して正しく価値提供が出来ない ということになります。 さらに、その実装者であるがゆえに、デザイナーよりも そのプロダクトの「挙動」に対しての深い知識がある とも言えます。 具体的には、APIやDB、DOM上にのみ表示されている、画面には見えないデータの扱い方とそのデータに基づいたUIのパターンにも深い知識があるし、そうあるべきと言えます。 つまり、フロントエンドが境界面になるからこそ、 ユーザーへの価値提供とUIのパターンの管理に責任を持つことが重要な職務 だと私は捉えています。 フロントエンドエンジニアの責務を全うするためにアンテナを張る場所 上述のとおり、フロントエンドエンジニアは画面に何がどう表示されているのかに責務を持つと考えているので、私は 「ユーザーからのお問い合わせ」と「素早く目に見えるUIを作る手段」に感度高くあることが重要 だと考えて常々そこにアンテナを張るようになりました。 前提として、お問い合わせは「ユーザーが実際に画面で見たもの」を元に行われています。 ここに関して、もう少し具体的に解説していきます。 「お問い合わせ」はUI改善の起点になるありがたい機会 これをもう少し抽象的に書くと「ユーザーが、とあるパターンのUIで表示された情報を見て 困った・迷ったポイントのうち、サービスを利用する上でクリティカルで熱量が高くなる部分の不備 」 を教えてくださっている 状態です。 これは、フロントエンドエンジニアにとっては「どのパターンのUIをみるとそのような問い合わせが生まれるのか?」「その課題をどう解決するべきか?」を考えることに使える、ひじょ〜〜〜にありがたいキッカケだと捉えています(さらに、各種テストケースの拡充や新機能の仕様考慮時の助けにもなります) 少し話はそれますが、現在BASE BANKチームでは、お問い合わせ内容の管理用ツールZendeskとSlackの連携を行っており、お問い合わせの具体的な内容をチーム内で確認できるSlackチャンネルにも流しています。そのため、チームメンバーは誰でも直近頻発している問い合わせ内容を察知したり、一次対応の内容を検討しているスレッド内でエンジニアやPdMを呼んで来て仕様面や技術面での確認や調査を行うようになっています。 Slack上に流れてくるお問い合わせのイメージ さらに、2週間に1度のMTGで各チームからの共有時間があるので、普段お問い合わせ対応を行っているOperationチームから、お問い合わせ対応の中でのプロダクトに対する困り事やこういう問い合わせが多かった。という情報共有をもらうこともあります。 以下のように、Operationチーム内でLookerダッシュボードを使って可視化も行っているため、数の増減や割合なども理解しやすく共有してもらっています。 Operationチームの発表時に使っていたNotionのキャプチャ OperationチームのLooker活用事例に関しては、ぜひ以下のPodcastも合わせてお聞きください。 https://open.spotify.com/episode/7wD9QCv6imYPOGsGIuvSTU?si=eA8ENSswQBWoGrOFkaz7fg このような形でBASE BANKチームのフロントエンドエンジニアはOperationチームのメンバーとデザイナーチームのメンバーと一緒にお問い合わせを基にUIの改善に取り組んでいます。 課題解決のための手段としてChrome DevToolsを活用しよう 2つ目のアンテナを張っていることは、 エンジニアと他職種のチームメンバーのコミュニケーションコストを下げるための手法について です。 上述の「お問い合わせ」があった際のUI改善やプロダクトの機能開発をサクサクできるように、メンバー間のコミュニケーションコストが下がることで、意思決定の精度とスピードが上がりより早くユーザーに価値提供をすることが出来るようになります。 これを実現するための具体的な手段として Chrome DevToolsの活用 を推していて、ステージング環境などで実際のUIを表示し、Chrome DevToolsでHTMLやCSSをサクッと変更して画面キャプチャするだけで事足りることも多々あります。 実際にあったやり取りだと、以下のようなものがあります。 この事例の他にもGoogle MeetにデザイナーとPdMの方に集まってもらい、画面共有をしながらChrome DevTools上でHTMLやCSSのスタイルを変更して実装方針をああでもないこうでもない。という話をしたこともあります。 その他、ちょっとした文言の修正の場合は document.designMode = ‘on’ ( 詳しい解説はこちらのW3Schoolで実際に触ってみる のがわかりやすいです)をパッと設定して画面キャプチャすることもよくあります。 こういったUIの検討時に文章ではなく視覚的に理解しやすいものを作るために、フロントエンドエンジニアが「Figmaを使いこなしてデザインファイル自体をサッと変更してキャプチャを作る」という選択肢もあります。 ただ、個人的にはChrome DevToolsがフロントエンドエンジニアにとっての最高のIDEだと思っていますし、ビルド後のDOM構造がどうなっているのか把握しておくことで得られるメリットもあると思っているので、この方法を活用することをおすすめしています。 Chrome DevToolsについてより詳しく知りたくなった方はぜひ、 公式Docs を眺めてみてもらえればと思います。 時々、 新機能ニュースページ を眺めると「エッッ、こんな便利な機能増えてたの!」とお宝を見つけたような気分になれるのでとってもおすすめです。 おわりに 以上がBASE BANKチームに異動して考えるようになった、フロントエンドエンジニアとして出来ること・やるといいと思ったことのご紹介でした。 Operationチームとの協業の仕方はBASE BANKチームに異動してから大きく変わったなと感じますし、BASE BANKチームが担当しているのはまだまだ探索フェーズの機能・プロダクトがたくさんなので、どんどんリリースしてどんどんフィードバックを受け取って改善を進めていく感覚が強いです。 もし、こんなことを考えている私やBASE BANKチームに興味を持たれたらぜひ採用ページからお声がけください!(↓のページの募集職種一覧から、BASE BANKチームでフィルタリングしてもらうと積極採用中であることが伝わるかと思います!) binc.jp また、いきなり仰々しいカジュ面はちょっとアレだし、がっちゃんとは個人的に話してみたいぞ!という方はPittaやX(旧Twitter)のリプ・DMなどでお声がけください🙋 https://pitta.me/matches/PDWMyhvOjUOy https://x.com/gatchan0807
こんにちは! BASE BANK Divisionの 松雪 です。 8/5に Welcome Fintech Community #2を開催しました。 お盆を挟んでドタバタしていたら3週間ほど経ってしまいましたが、今回も大盛況だったのでその様子をお届けします! Welcome Fintech Communityについて コミュニティ立ち上げの経緯はこちらに記載しているのでぜひご覧ください。 devblog.thebase.in 6/20に開催した第1回がありがたいことに大反響だったため、鉄は熱いうちに打て!ということで1ヶ月半ほどで第2回を開催しました。 今回は第1回の懇親会で是非次があれば話したい! と意思表明してくださっていたSTORESさんとMIXIさんにお声がけし、公募LTと合わせて5人にご登壇いただきました。 また今回は初の試みとして、エンジニア転職サービスForkwellを運営するGroovesさんに飲食スポンサーをしていただきました! この場を借りて改めてお礼申し上げます。ありがとうございました! 当日の様子 今回はLT後の懇親会へスムーズに移行できるよう、アイランド形式のテーブル配置に。 第1回に引き続き司会のBASE 柳川さん Forkwell のしもおかさん!飲食サポーターありがとうございました!! LT LT一発目は 株式会社MIXI から浅見さん。 ウォレットサービスとしてのMIXI Mは知っていましたが、ID、認証基盤としても展開しているのは個人的には初耳でした。 確かに決済サービスは本人確認などユーザーと強く紐づいているので、それを認証基盤として切り出して提供するというのは意外と思いつかなかったなあと新たな発見がありました。 続いて STORES株式会社 からSTORES 決済 に関わっていらっしゃる西村さん。 決済時の基本的な座組の話や、STORES決済を使った決済時の電文の経路についてお話しいただきました。 電文の経路は一般的なカード決済とは少し違う経路で問い合わせが行われており、カード決済などに詳しい参加者からは”そんなことできるの??”という声も上がっていました。 3人目は クラスメソッド株式会社 の和田さん。 DevelopersIOにはいつも助けられていますありがとうございます。 AWSと PCI DSS についてのお話で、責任共有モデルからReserved InstancesやSavings Plansまで、決済だけでなくAWS上で事業を行うすべての方に必要な情報をたくさん共有いただきました。 4人目は 株式会社dinii の角田さん。 diniiさんはモバイルオーダーだけでなくPOSやオンライン決済機能もあるため、決済サーバやPOSサーバ間でどのようにデータの整合性を保ちながら決済を実現するかなど、飲食店でのオペレーションならではの苦労するポイントなどがたくさんあるんだなととても勉強になりました。 最後に 株式会社LayerX からken5scalさん。 金融庁が”金融分野におけるサイバーセキュリティに関する ガイドライン(案) ”というものを公開していたようで、その中から所感や我々fintechに関わる人間にも関係がありそうな内容をピックアップしてくださりました。 ルールに従うだけでなくルールを一緒に作っていくために、パブリックコメントで意見を出そう!というメッセージが参加者の皆さんにもとても刺さっていたようです。 懇親会 懇親会も前回に引き続き大盛況! (盛り上がりすぎて写真撮影を完全に忘れていました・・・) 事前に懇親会に移行しやすいようなテーブル配置にしたからかな?と思いつつ、もっといい配置や進め方はありそうだなと感じる場面もあったので、このあたりはこれからも色々と試行錯誤しながら参加者のみなさんが盛り上がりやすい場の設計をしていきます! おわりに 改めて、今回ご参加いただいた皆様ありがとうございました! そして!!!!第3回の開催も決定しました!10~11月ごろを予定しています。 また追って開催日やconnpassの公開など行っていきますので、ぜひコミュニティメンバーになっておいてください! https://welcome-fintech.connpass.com ではまた、第3回で初参加したい方もリピーターの方もお待ちしております!!
はじめに こんにちは。ProductDev FeatureDev3 でエンジニアをしています、 endu です。 先日、自分が所属するチームで「良いコード/悪いコードで学ぶ設計入門」という本を題材に輪読会を開催しました。 gihyo.jp この記事では、「良いコード/悪いコードで学ぶ設計入門」を読もうと思った背景や、チームで実際に行った輪読会の進め方、輪読会を通じて得た学びについて共有できればと思います。 輪読会を開催した背景について BASEではショップを独自にカスタマイズする拡張機能として「Apps」を提供しています。 自分が所属するチームでは特に「 Google商品連携・広告 App 」や「 Instagram広告App 」、「 Instagram 販売App 」、「 TikTok商品連携・広告 」など、主にSNS Apps周りの保守や機能改善を行っております。 当然GoogleやMeta側から提供しているAPIのアップデートがあるので、アップデートの対応をおこなったり、お問い合わせ起因での細かい修正も発生します。 これらのSNS AppsはBASEでも歴史が長く、チームに配属したばかりの頃は全体の仕様が把握できてない事もあり、既に書かれているコードを参考にして追加したものの、いまいち良いコードをかけているかの自信がありませんでした。 そうこうしている内に、チーム内で輪読会を開催する話が上がったのと、自分が書いたコードに対してモヤモヤがあったので、「良いコードとはなにか? 悪いコードはなにか?」を考える機会を作る為にこちらの本を提案し、輪読会を開催する事になりました。 輪読会の進め方について 今回、私達のチームでは以下のフォーマットに沿って進めました。 章や項など、書籍や文書の構成単位毎に担当者を割り振り分ける。 担当者は担当分のページを読み、必要に応じて調査などして理解した上で要約・感想をNotionに記述する。 輪読会の開催日に担当者は自分が読んだ分の要約・感想などを発表する。 輪読会参加者は担当者の発表を聞き、質問を投げたり、担当者と自身の解釈の差を述べるなどして議論し、理解を深める 次回の予定と担当者の確認をして終了。 なお、担当者以外の方の予習は任意で、基本的には担当者の方が記事を読んで要約して発表するスタイルで輪読会は開催しました。 輪読会を通じた学びについて まずこの本が何を目的に書かれたか?については「15章 設計の意義と設計の向き合い方」で以下のように著者は書いています。 本書はソフトウェア開発上の悪魔を退治する設計方法を記述したものです。悪魔はさまざまな悪事を働きます。デバッグ時や仕様変更時、どのロジックが影響しているのか影響の把握を困難にさせます。また、仕様変更時に修正漏れが起こりやすく、バグが発生するなど、正確な動作ができるようになるまで時間を浪費させます。こうした悪魔の性質と最も関係がありそうな品質特性はどれでしょうか。保守性をみてください。「システムを修正する有効性や効率度合い」とありますね。そうです、本書で取り扱っているのは保守性に関係する設計です。 このように1章から~17章まではほぼ一環して、この保守性に関連する手法が紹介されています 第1章の「悪しき構造の弊害を知覚する」と第2章の「設計の初歩」はこの本の導入部として読みやすいです。良い設計を行うにはまず、悪い設計とはなにか?を考えて自分の中で基準を持つ必要があります。 そういった意味で最初に1章で悪いコードとはなにかの事例を学び、2章では「設計の初歩」として、意図した名前付けを使う、理解を困難にする条件分岐のネストは避けるなど、基本的な手法が紹介されています。 第3章「 クラス設計 ―すべてにつながる設計の基盤―」からクラス設計の話が始まるのですが、ここの章から少しづつ「自分達のコードどうなのか?」という話題がチームメンバー内で出てきました。実際にここで書かれているコード通りにできているのか?だったり、他のチームや過去の経験談などの話題などを出しながらチーム内で設計について、議論ができて良かったです。 また個人的には第6章「条件分岐 ―迷宮化した分岐処理を解きほぐす技法―」では、switch caseを使わずにinterfaceを使い、ストラテジーパターンで処理を分ける方法についてはサンプルコードが提示されていて、わかりやかったです。 6章以降についても、より実践的なテクニックや、設計の向き合い方についても書かれていますが気になる方はぜひ本誌を手に取って読んでみください! 輪読会後に得た良い体験としては、実際に業務の会話で「これって本の例で書かれていた悪いパターンでは?」という話があがって、実装を変更する機会がありました。 「良いコード/悪いコードで学ぶ設計入門」の輪読会を開催した事で、少しづづですが良いコードを書く自信が持てたと思います。 輪読会に参加したメンバーからのコメント 輪読会に参加メンバーからも感想をいただいたのでご紹介します! 保守を観点に実例を交えながら実践的な形でまとめられていたので、開発やレビューについて見直すいい機会となりました。メンバーとも体験談を交えながら話し合うことができたので有意義な時間だっと思いました。 わかっている ”つもり” になっているようなことも多く出てきて、読みながら再認識(と少し反省、、)できてとてもよかったです。チームメンバーと設計の良し悪しの目線を揃えられる点でもとても有用だったと思っています。参加できてよかったです。 サンプルコードや具体的な事例が豊富で、身の覚えのあるものも多く、学びがありました。各メンバーの知見も得られる、良い機会にもなりました。 この本の輪読会は通算2回目でしたが1度目で吸収しきれなかった部分やその他思い出すいい機会になったため更に知識が深まりました。また、過去の事例や「この場合どうする?」みたいな議論も毎回挟めれたので有意義な時間でした おわりに 「良いコード、悪いコードで学ぶ設計入門」の輪読会を通じ、チーム内で議論しながら設計について学べる機会ができました。 この本を読んでからは自分の中で良い設計、悪い設計とは何か?の基準を持てるようになり、リファクタリングする際も選択肢が増えました。 今後の業務でもこの本にかかれていた内容を元に良い設計を作っていきたいと思います! 最後に宣伝ですが、BASE ではエンジニアを採用中です! 今回のような輪読会の他にも社内LT会など開催されているので興味がある方は下記の紹介資料や、採用情報やもぜひご覧ください! speakerdeck.com binc.jp
はじめに Data Strategyチーム(以下、DSチーム)でDWHやBIツールの運用をしている@shota.imazekiと不正検知やAWS基盤運用をしている @tawamura です。 Aurora MySQL v2(MySQL5.7互換)が2024/10/31に標準サポート終了となるため、DSチームでは2024年6月にAurora MySQL v3(MySQL8.0互換)へのアップグレードを実施しました。 その際に得られた課題や知見について紹介していきます。主に AWS DMS や Amazon RDS ブルー/グリーンデプロイ を用いたアップグレード方法の話になります。 DSチームのインフラ構成 DSチームはBASEの機械学習基盤を構築・運用しており、APIなどを介してプロダクト側へ機械学習モデルの推論結果などを返しています。学習・推論のために使うプロダクト側のデータはDMSを用いて、DS環境にレプリケーションしています。 具体的には、本番環境にあるレプリカDBをDMSタスクのソースに指定し、DS環境で使用するDBへと同期を行っています。 また、DMSで同期したDBをさらにソースとして指定し、DMSの変更検知(CDC)によって取得した差分をAmaon MSKに流しています。これによって特定のテーブルにデータが挿入/更新されたというイベントを取得することができ、それをトリガーにworkerで他の処理を行っています。そういったworkerや、定期実行されるバッチによる処理結果を保存しておくためのDBも同じDBクラスター内に存在しています。 今回アップグレード対象となったのは、図で赤枠で示した「DS DBクラスタ」部分になります。 事前検証 DSチームのDB(以下、DS DB)では上述した通り、DMSを用いてプロダクト側のデータをレプリケーションさせています。DSチームの方がアップグレードを早めに実施するスケジュールで動いていたため、メジャーバージョン単位でのバージョン差異があってもDMSによる同期が可能なのかを事前に検証しました。できない場合はアップグレードのタイミングをプロダクト側と合わせる必要があるためです。 検証方法としては3つのDBクラスターA(MySQL5.7), B(MySQL5.7), C(MySQL8.0)を用意し、以下のような形でDMS連携を行いました。 その後、BをMySQL8.0にアップグレードさせることで2つの事象を同時に見ることができます。 A(MySQL5.7)→B(MySQL8.0): DMS連携先(DS DB)がアップグレードした時の挙動 ここについては特に問題は発生しませんでした B(MySQL5.7)→C(MySQL8.0): DMS連携元(プロダクト側のDB)がアップグレードした時の挙動 BをMySQL8.0にアップグレードさせると、B→CへのDMSタスクが失敗していました。 DMS連携の際にONにしておく必要のあるシステム変数log_binがOFFになっていたためでした。 こちら を参考に再起動したところ、エラーは解消されました。 一部エラーは発生しましたが、メジャーバージョン単位でのバージョン差異があってもDMS連携は問題ないと判断しました。またDMS連携元(プロダクト側のDB)をアップグレードする際にはlog_binの値に注意する必要があることも分かりました。 アップグレード方法の検討 Amazon Aurora MySQL バージョン 3(MySQL 8.0 互換)へのアップグレード を参考に以下3つの選択肢からアップグレード方法を検討しました。 インプレースアップグレード ブルー/グリーンデプロイ スナップショットからの復元 アップグレード後に問題が発生しても、旧バージョンに戻す古いクラスターに切り替えることが可能な点やダウンタイムを最小限に抑えられる点からブルー/グリーンデプロイを選択しました。 ブルー/グリーンデプロイは、ブルー環境(稼働中のDB)とは別でグリーン環境(MySQL8.0にアップグレードされたDB)を構築しておき、任意のタイミングで本番環境をブルー環境からグリーン環境に切り替えるものです。データはブルー環境からグリーン環境にレプリケーションされているため、差分が生じることはありません。 次にAWSのブルー/グリーンデプロイ機能を使うか、グリーン環境をDMSを用いて自前で構築するかの検討を行いました。後者は準備に時間がかかるのですが、AWSのブルー/グリーンデプロイ機能でロールバックが行えるか、など不明な点が当初いくつかあり、反面DMSの環境構築に関しては既に知見がありあまり困ることがなさそうだったので自前で構築することにしました。 DMSを用いたグリーン環境の構築 DMSを用いてブルー環境のデータをレプリケーションする準備をしていましたが、その作業を行なっていくうちに一つの課題にぶつかりました。 カラムのデータサイズが大きすぎるとDMSタスクがタイムアウトになる まず、DMSでDS DBのデータをグリーン環境に同期して、全く同じ状態のDBを構築することにしました。 DS DBには、プロダクトからDMSで同期しているテーブルに加えて、DSチームで動かしているリソースが新規保存・更新を行なっているDBやテーブルが含まれています。このテーブルの一部で、 MEDIUMTEXT など大きめのデータ(LOB: ラージバイナリオブジェクト)を保存しているカラムが存在しています。 DMSでこれらのLOB列を含むテーブルのレプリケーションを行う際、通常のバイナリログによる同期ではなく、選択可能なLOBモードによる処理方法を適用することになります。 AWS DMS タスクでのソースデータベースの LOB サポートの設定 グリーン環境へレプリケーションを行うDMSタスクを実行していると、以下のようなエラーが発生しました。 Table ' db_test ' . ' table_test ' was errored/suspended (subtask 1 thread 1 ). Failed (retcode -1 ) to execute statement; RetCode: SQL_ERROR SqlState: HY000 NativeError: 3024 Message: [MySQL][ODBC 8.0 (w) Driver][mysqld -5.7 . 12 - log ]Query execution was interrupted, maximum statement execution time exceeded (replicationtask.c: 3066 ) LOB列に対しては、ステートメントを発行して別途データを取得するようなのですが、そこでタイムアウトが発生したものかと思われます。 AWSにてサポートケースを作成し、状況を共有しつつ以下のような項目を実施しました。 自主的に検証(DMSタスク設定) CommitRate を1000から100に TransactionConsistencyTimeout を60から600に HistoryTimeslotInMinutes を5から60に サポートから共有を受け実施(DMSエンドポイント設定) ExecuteTimeout を60から3600に しかしこれらの変更を行なっても改善がみられませんでした。 続けていくつかの対応方針も提供していただいたのですが、これ以上時間をかけて対策を進めるより、AWSのブルー/グリーンデプロイ機能を試した方が良いかもと思う点がいくつか発生してきました。 DS DBのデータは小さくないので、DMSによる同期もかなり時間がかかることが想定される 自前でブルー/グリーンデプロイを行うとしても、書き込みを行なっているリソースがあるために、データの不整合なくロールバックを行うことはほぼ不可能 今後もアップグレードの機会はあるので、公式機能で楽に対応できることがわかっていればそれに越したことはない ブルー/グリーンデプロイ機能でも想定しているテストや切り戻しができそう 以上からDMSを用いたブルー/グリーンデプロイは断念し、AWSのブルー/グリーンデプロイ機能を使う方針に変更しました。 AWSブルー/グリーンデプロイ 事前確認 準備については ブルー/グリーンデプロイの作成 を参考に進めていきました。ブルー/グリーンデプロイ作成時に考慮すべき点を列挙しておきます。 ブルー/グリーンデプロイでサポートされていない機能を利用しているか 以下の機能はブルー/グリーンデプロイでサポートされていないため、利用している場合は一時的に接続を切るなどの検討が必要になります。DS DBでは利用していなかったため特に困ることはありませんでした。 Amazon RDS Proxy カスケードリードレプリカ クロスリージョンリードレプリカ AWS CloudFormation マルチ AZ DB クラスターのデプロイ ブルー環境のDBクラスターのbinary loggingがONになっているか ブルー環境からグリーン環境へのレプリケーションを行うためにバイナリログが必要になるため、パラメータグループの binlog_format を確認する必要があります。フォーマットは複数あり、どれでもレプリケーションできるそうですが推奨は ROW でした。DS DBでは元々、DMSを利用している点から元々、 ROW に設定していたのでこちらも特に問題なかったです。 ブルー/グリーンデプロイの作成 作成自体はグリーン環境のエンジンバージョンの設定や事前に作成しておいたパラメータグループを指定するだけだったので簡単でした。 https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/blue-green-deployments-creating.html#blue-green-deployments-creating-preparing-mysql 作成開始後、まずブルー環境のDBクラスターを複製後にアップグレードをしてグリーン環境を構築します。複製自体は数十分程度で終わったのですが、アップグレード時にエラーになりました。 Database cluster is in a state that cannot be upgraded: Upgrade prechecks failed. For more details, see the upgrade-prechecks.log file upgrade-prechecks.log ファイルを確認したところ、とあるテーブルのパーティションをアップグレードする必要があるようです。 Partitioning upgrade required. Please dump /reload to fix it or do: ALTER TABLE `database`.` table ` UPGRADE PARTITIONING " 対象のテーブルはDSチームで現在利用していないものだったため、今回は削除することにしましたが必要な場合はエラーの案内に従って更新をかけることで解消できたと思います。 再度作成作業を行い、グリーン環境の構築が完了しました。構築する時間は大体1時間程度でした。 検証 グリーン環境の構築が終わったため、DS DB周りで動いているバッチやAPIを動かしてみて、動作に問題がないかできる限り確認を行いました。 ブルー/グリーンデプロイ機能では、グリーン環境構築後にグリーン環境に接続を行えるエンドポイントが作成されます(データはブルー環境のものが論理レプリケーションされており、基本的に同じものを扱える)。これにより、テストしたいリソースの向き先をグリーンのエンドポイントに向けて実行してみることで、切り替え後の問題が発生しないかを事前に確認することができます。 https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/blue-green-deployments-overview.html 確認の中で、書き込み処理のテストを行おうとしたところ、パラメータグループのread_onlyは0になっているが、グリーン環境側ではONの状態になっていることに気づきました。 パラメータグループ MySQL MySQL [(none)]> show variables like ' read_only ' ; + ---------------+-------+ | Variable_name | Value | + ---------------+-------+ | read_only | ON | + ---------------+-------+ AWSのドキュメント で、グリーン環境は読み取り専用に保つことを勧めているため、このような差異が生まれているのかと推測しています。なお、スイッチオーバーした際にはread_onlyパラメータはOFFになっていましたので、気にする必要があるのはテスト時のみでした。 テスト中は、グリーン環境のデータベースを読み取り専用に保つことをお勧めします。グリーン環境ではレプリケーションの競合が発生する可能性があるため、書き込み操作を有効にする場合は注意してください。また、スイッチオーバー後に本稼働データベースに意図しないデータが発生する可能性もあります。Aurora MySQL の書き込み操作を有効にするには、 read_only パラメータを 0 に設定し、DB インスタンスを再起動します。 実施 メンテナンス当日、DMS, CDCタスクを停止後にグリーン環境への切り替えを実施しました。ダウンタイムは3分程度で終わり、この切り替え自体は特に問題が発生しませんでした。 ただ、DMS、CDCタスクを再開した後、DS DB→Amazon MSKへのCDCタスクがエラーとなっていました。確認したところ、log_binがOFFになっていたことがわかりました。 show global variables like " log_bin " ; + ---------------+-------+ | Variable_name | Value | + ---------------+-------+ | log_bin | OFF | + ---------------+-------+ DMSの事前検証の時点で同様の現象が起きていたため、ライターインスタンスを再起動してみたところ、ライターインスタンスでlog_bin=ONになってCDCタスクも動くようになりました。再起動自体は1分程度で完了しました。 おわりに AWSのブルー/グリーンデプロイ機能は、パラメータ周りには少し悩まされましたが大した問題にはならなかったですし、簡単に利用できて実施もすぐに終えられたので非常によかったです。今後のDS DB関連のメンテナンス方法において有力な候補になると思いました。 最後となりますが、弊社ではデータエンジニアを募集しています。ご興味のある方は気軽にご応募ください! open.talentio.com
welcome fintech communityのバナー。かっこいい! こんにちは! BASE BANK Divisionの松雪です。 今回、金融決済の技術領域を中心としたコミュニティを立ち上げ、6月20日にイベントを初開催しました。 その模様をお届けします。 Welcome Fintech Communityとは? 特定の技術や職能に関するコミュニティは数多くありますがfintechに関するコミュニティは少なく、fintech領域を盛り上げていくために知見やお悩みの共有ができるようもっとオープンなコミュニティがほしいなと感じていました。 そんなとき、EMゆるミートアップでスマートバンク社の 三谷さん と出会い、「fintech界隈で集まってもっと色んな話したいよね???」と盛り上がった結果このコミュニティを立ち上げることにしました。 welcome-fintech.connpass.com 当日の様子 LT 司会の柳川さん。さすが盛り上げ上手。 申し込みについては、ありがたいことに40人枠が一時いっぱいになるほどの盛況! こういうイベントは申込み人数に対して6~70%くらい来場してくだされば御の字と言われていますが、80%近い方にご来場いただき、熱量の高さを感じました。 最初はBASE BANKから、根本さんの “BASEカードから見る決済サービス"。 カード決済の基本的な仕組みやそれを実現するための「BASEカード」 のシステム構成、さらにはキャンペーンなどの施策をどう実現するか?など具体的な話までしてもらいました。 決済パターンが本当に多様で実際にリクエストが来るまで存在自体知らないものもたまに発生するという話に、カード決済に関わっていらっしゃる参加者の方々が深く頷いており、皆さん苦労されているんだな・・・と思いました。 BASE BANKの根本さん speakerdeck.com 次に株式会社スマートバンクのCTO 堀井さん から”カード発行会社(イシュア)を支えるシステム解説”というタイトルで「B/43」のアーキテクチャについて発表いただきました。 イシュアという立場では「BASEカード」と同じですが、より深くVISAの決済ネットワークと接続しているためPCI DSSというセキュリティ基準をクリアする必要があり、そのためにどのような技術選定、アーキテクチャ構築を行ってきたか赤裸々に発表してくださいました。プリペイドカードのプロダクトを立ち上げる機会がもしあれば必読の資料です!! スマートバンクの堀井さん speakerdeck.com 最後にPAY株式会社からクリスさん。 PAY社でもPCI DSSの基準をクリアするための様々な対応を行っているのですが、今年実際に発生した対応事案についてサスペンスのごとく追体験していくような発表をしてもらいました。 詳細は是非資料を見てみなさんも追体験していただきたいですが、問題を特定し、無事解決したときには会場からお〜と歓声が上がっており、会場が一体感に包まれていました。 PAYのクリスさん speakerdeck.com パネルディスカッション パネルディスカッションでは、事前に用意していたテーマとXに投稿いただいた質問を拾いながら進めていきました。 決済の確定やキャンセルを考慮したキャンペーン予算設定の質問や、PCI DSSを考慮したシステム分割に付いての考察など、明らかにfintech経験者からの質問だ!という内容もあり、大いに盛り上がりを見せました。 パネルディスカッションの様子 懇親会 LTやパネルディスカッションの時間が足りなかったのか、懇親会でも各方から決済や送金、PCI DSSなど様々な決済談義が聞こえ、非常に盛り上がっていました。 次こういうテーマで話したい!という声や次回はいつやるんですか???など早速次回開催の要望をいただくなど参加してくださった皆さんの熱量が最初から最後まで高く、このコミュニティを立ち上げた意味があったなあと非常にありがたかったです。 懇親会の様子 おわりに 正直ある程度需要はあるだろうなとは思っていたものの、想定以上の盛り上がりを見せ、今後も継続してこのコミュニティを育てていきたい!と思えるイベントになりました。 当日の様子もXのハッシュタグを追うとさらにわかりやすいかと思います。是非ご覧になってみてください。 https://x.com/hashtag/welcome_fintech 最後に、この場を借りて共済してくださったスマートバンクさん、そしてご参加の皆さん双方に感謝申し上げます。本当にありがとうございました! まだ未定ですが、第2回以降も開催したいと思っているので、ぜひご参加ください!
こんにちは。BASE BANKです。 先週BASE BANKメンバーの登壇やイベント参加が偶然重なったため、今週は実質イベントレポウィークとなっております。 今回は去る6月21, 22日に開催されたスクラムフェス大阪2024での登壇についてコメントをお届けします! スクラムフェス大阪2024 今回参加したスクラムフェス大阪は、オンライン開催ではありますが大阪をはじめとした各サテライト会場が存在し、トラックごとに各会場の名前がつけられていました。 そのため、スクラムフェス”大阪”の”仙台”トラックだが”虎ノ門”会場から登壇など、なかなかハイコンテキストな状態になっている人もおり、ユニークでそれもまた話の種となっていました。 ”ズームイン”と銘打って各会場の模様を中継したりとオンラインならではの交流もありつつ、各会場ごとにもワークショップや懇親会も大いに盛り上がるなど、オンラインとオフラインの両方のメリットを最大限活かした場つくりがされていました。 スクラムフェスに関わるみなさんのイベント運営スキルの高さを肌で感じることができ、とても学びが多く楽しかったです。 今回のセッション BASE BANKからは松雪( @applepine1125 )と柳川( @gimupop )の2名が登壇しました。ちなみに2人とも今回の登壇がスクラムフェス初参加でした! 柳川 -「アジャイルソフトウェア開発宣言」を実践するために事業責任者になる話 Scrum Fest Osaka 2024 - 「アジャイルソフトウェア開発宣言」を実践するために事業責任者になる話 | ConfEngine - Conference Platform 登壇者コメント XP祭りへの参加経験はありましたが、アジャイルコミュニティへの参加は今回がほぼ初めてでした。 リモート配信の仕組みが整っておりサテライト会場とオンラインを同時に繋がっていました。人の顔が見える場所を用意していただいたので、非常に発表しやすかったです。空気感もとても温かく、45分間虚空に向かって発表し続けるのは辛いなーと思っている中で非常に助かりました。オンラインなのに集まれて、終了後飲み会ができる体験が最高でした。品川葛飾トラックラブ。 今回の私の発表はWebサービスを作るならプロダクトマネージャーは事業責任者になれという、脳筋的な圧強めメッセージなんですが、資料読んでいただけると納得いただける・・・はず! BASE BANKのチーム作りの背景が見える発表でもあると思います。 動画も後日出るそうなのでお楽しみにお待ちいただけますと。 松雪 - 新規事業立ち上げ、グロースできちんと"ディスカバリー"し続けられるアジャイル組織の作り方 Scrum Fest Osaka 2024 - 新規事業立ち上げ、グロースできちんと"ディスカバリー"し続けられるアジャイル組織の作り方 | ConfEngine - Conference Platform speakerdeck.com 登壇者コメント 今回スクラムフェス大阪にてスクラムフェス自体に初参加、初登壇させていただきました。 はじめはどういった雰囲気かわからなかったのですが、他の方々の発表から得るものが非常に多かったのはもちろん、登壇者だけでなく参加者同士でも相互にコミュニケーションをとる場が設けられていたりと、学びを最大化するための工夫が随所に施されており非常に器の大きいコミュニティだなあと感じました。 自分は時間の都合で懇親会には参加できなかったのですが、参加者用のDiscordに各地の懇親会の楽しそうな写真が上がっており、次は絶対懇親会まで参加するぞ・・・!と心に決めました。 発表では、ただスピーディにアウトプットするだけでなく、ちゃんと仮説検証のサイクルを回し続けられるような組織づくりが大事だよ!という話をしました。 新規事業立ち上げ、グロース時期はどうしてもアウトプットにばかり目が行きがちかもしれませんが、そういう状況こそ丁寧かつ素早くディスカバリーサイクルを回し、”正しい”プロダクトを作り続けることが何より大事だと思っているので、同じような状況の方がいらっしゃればぜひ一事例として参考にしていただければと思っています。 おわりに どうやらオンラインとオフラインのハイブリッド形式での開催は今回が最後だったようで、次回以降はオフライン開催になるようです。 各会場の熱量も高く、いろんな地方でいろんな仲間と出会ってみたいと思ったので、今後もまた参加していきたいです! 最後に宣伝ですが、BASE BANKでは今回発表したような事業づくり、組織づくりを一緒にやっていってくれる仲間を募集しています! 技術、組織、事業、なんでもよいのでもしBASE BANKに興味を持ってくださった方がいたらぜひお話しましょう!お待ちしています! open.talentio.com
はじめに BASE BANK Division で フルサイクルエンジニア をしている02 ( @cocoeyes02 )です。 2024/06/22(土)に開催されたPHPカンファレンス福岡 2024に登壇しました。今回の記事では登壇についてのコメントと、会場の様子についてお届けします! 今回のセッション 今回は15分枠での登壇です。 speakerdeck.com 02 @cocoeyes02 さんのトークがはじまっています❣️ #phpconfuk #hall_hz https://t.co/AFxNus3Zay pic.twitter.com/DyCkj3fD8D — PHPカンファレンス福岡 公式 (@phpcon_fukuoka) 2024年6月22日 時間が許す限り、PHPUnit 11のアップデートについて話しました! Ask the Speakerで聞いていると、前回のPHPUnit 10も含めPHPUnitのバージョンアップに苦労している方が多いように感じました。 最初は興味や登壇のネタになるという理由から始めたPHPUnitの学習でしたが、現在は将来の必要性を感じて取り組んでいます。今後も、翌年にリリースされるPHPUnit 12についてや、まだ話していないPHPUnit 10 / 11 の変更点など、ブログや登壇で話せればと思っています。 現地の様子 ここからは、現地の様子を一部お届けします! オープニング オープニングは実行委員長の元気溢れる挨拶からスタートしました。 朝にも関わらず多くの人が参加しており、オープニングの時点でスタッフや参加者の熱量の高さを感じました。 #phpconfuk 2024、開幕です🎉 実行委員長 @BkNkbot のオープニングからスタート❣️ pic.twitter.com/WE182JzXOW — PHPカンファレンス福岡 公式 (@phpcon_fukuoka) 2024年6月22日 自由に表現できるネームカード 参加者のネームカードは、自分で書いたり、属性シール(普段触っている技術や、ロール、熟練度など)を貼ったりと、自由に表現できるようになっていました。 どんなバックグラウンドやキャラクターの人が参加しているのか、ひと目でわかるようになっていて最初の話題を出しやすかったです。 ネームカードを書いたりシールを貼る場所の様子 対よろです(眠気で字がぐちゃってる) #phpconfuk pic.twitter.com/evxBil9LEl — 02 (@cocoeyes02) 2024年6月22日 スポンサーブースの様子 どのスポンサーブースも賑わっており、参加者同士のコミュニケーションで溢れかえっていました。 また、コーヒースポンサーによるコーヒー飲み放題や、福岡ならではのお菓子もいくつかおいており、福岡を満喫できるようなホスピタリティを感じました。 スポンサーブース周辺の様子 早速東京近辺に集中してる #phpconfuk pic.twitter.com/Sc8I3xetr9 — 02 (@cocoeyes02) 2024年6月22日 コーヒースポンサーが提供しているコーヒーと福岡ならではのお菓子 また、Ask the Speakerもこのスポンサーブース近辺で開催されました! \CホールにてAsk the speaker 開催中🎙/ おかしょいさん @okashoi と、02さん @tadsan と、チャンさん @zosokh と、sora さん @_fs0414 と、とうださん @picopico_dev と、Kanon さん @samurai_se に質問したい方はCホールへ🏃 珈琲片手に、お気軽にお越しください☕ #phpconfuk pic.twitter.com/KFEBskbbqZ — PHPカンファレンス福岡 公式 (@phpcon_fukuoka) 2024年6月22日 アンカンファレンスルーム アンカンファレンスも賑わっていました。最後の時間の「Round Tablle Session テーマ:学習どうしている?」に参加しましたが、 「どのくらい技術書を読んでる?」 「どういう目的で技術書を読んでいる?」 「どういう基準で技術書を選んでいる?」 といった技術書に関する質問について、各PHPerと自分の基準を共有したり、議論したことが面白かったです。 アンカンファレンスルームのタイムスケジュール クロージング クロージングが始まり、各情報の共有が行われました。PHPカンファレンス福岡 2024の参加者は約300人で、日本で開催されるPHPカンファレンスの中でも人数が多いカンファレンスだと再確認しました。 さらに、委員長から参加者のPHPカンファレンス参加歴(例えば、PHPカンファレンス福岡に初めて参加した人など)について尋ねる場面がありましたが、初めてPHPカンファレンスに参加した人や、技術カンファレンス自体に初めて参加した人が少なからずいることが印象的でした。 #phpconfuk 2024 、あっという間にクロージング😭 実行委員長 @BkNkbot のクロージングがスタートしました❣️ pic.twitter.com/no8lPwYsYm — PHPカンファレンス福岡 公式 (@phpcon_fukuoka) 2024年6月22日 クロージング終了後には懇親会が始まり、色んなPHPerとご飯を食べて、お酒を飲みながら交流しました。 おわりに スタッフの方々にはお忙しいにも関わらず、多くの時間を準備に費やしていただいたと思います。この場を借りて御礼申し上げます。 初九州 / 初福岡 / 初飛行機を使って遠くへ出かけた技術カンファレンスだったので不安もありましたが、とても楽しめた素敵なカンファレンスでした。また開催されたら是非参加したいですね。 BASE / BASE BANKでは、絶賛PHPerを採用中です。下記の採用情報やカジュアル面談リンクからぜひご覧ください! binc.jp open.talentio.com
はじめに BASE BANK Division で フルサイクルエンジニア をしている02( @cocoeyes02 )です。 AWS Summit Japan 2024のDay 1にオンサイトで参加してきたので、現地の様子をお届けします! AWS Summit Japan 2024とは? AWS Summit Japan 2024とは、2024/06/20〜2024/06/21に開催されたAmazon Web Services(以下AWS)を学ぶイベントです。 参加登録人数は5万人を超えるなど、文字通り日本最大のAWSを学ぶイベントになります。 aws.amazon.com 会場まで AWS Summit Japan 2024の会場は幕張メッセです。 お昼前にもかかわらず、入場まで人が並んでいました。日本最大のAWS学習イベントという表現は実にふさわしい、というほどの大盛況でした。 きたわね #AWSSummit pic.twitter.com/Aabz8OmdXd — 02 (@cocoeyes02) 2024年6月20日 AWS Summit Japan 2024会場への入場を待つ長蛇の列 AWS Summit Japan 2024会場入口の様子 会場全体の様子 入場してみると、たくさんの展示ブースやセッション会場が目の前に広がっていました。 エンタープライズサポートでやり取りのあったAWS SAの方々や、普段から接点のある方々にご挨拶するために、ブースを巡りました。会場は非常に広く、少し迷ってしまったのは内緒です。 入場してすぐのエリアを俯瞰して撮った様子 いくつかのセッションを聴講しましたが、その聴講環境が整っていると感じました。例えば、各セッション会場は大人数を収容でき、全席には登壇者のマイク音声をイヤホンで聞くためのレシーバーが用意されていました。 各セッションの会場を横から撮った様子 魅力的なコンテンツも盛りだくさん 全ては紹介しきれないですが、現地で体験したコンテンツを一部紹介します。 AWS Snowball Edgeデバイスを持ち上げてみた AWS Snowball Edgeデバイス の実物が展示されていたので、持ち上げさせていただきました。AWS Snowball Edgeデバイスは約20kgほどあり、両手でないと持ち上げられないほど重かったです。 AWS SnowballについてはAWS認定試験で学んだ程度の知識しか持っていなかったので、実際に触れることができるのは良い経験になりました。 snowball持ち上げさせてもらった #AWSSummit pic.twitter.com/oZRG9rHNvC — 02 (@cocoeyes02) 2024年6月20日 Chaos Kitty ゲーム形式でカオスエンジニアリングと可視化を学べる Chaos Kitty が展示されていました。ゲームモードはレジリエンスとセキュリティ、難易度はEasyとHardがあり、それぞれの復旧タイムランキングリストがありました。 私はレジリエンスモードのEasyをプレイさせてもらいましたが、擬似的に障害訓練をしているような感覚でした。自社向けのデモ環境があったら、楽しみながらインシデント対応力向上するきっかけになりそうだと思いました。 ゲーム形式でカオスエンジニアリングと可視化を学べるchaos kitty 面白かった! #AWSSummit pic.twitter.com/Gv1y7KfhsX — 02 (@cocoeyes02) 2024年6月20日 Industry Zone このエリアでは、各業界ごとの最新の AWS ソリューションの紹介やデモが行われていました。私は流通小売消費財インダストリーに訪れ、EC体験の向上目指した様々な技術や機能を見てきました。 例えば、生成AIを使った商品説明文や商品背景画像の生成や、商品の細部を確認できる3D ホログラムディスプレイなどがありました。 Industry Zone:流通小売消費財インダストリーの様子 AWSで妄想してみた QuizKnock さんとのコラボ企画によるパネル展示です。「こんなことができたら良いのに」という妄想と、それを実現するための仕組み、そしてAWSアーキテクチャ図が描かれていました。 個人的には、SAの佐藤さんが妄想した「過去の自分へ相談するため、分身と会話できるようにする」がとてもエモくて試してみたいと感じる良いアイディアだと思いました。 「AWSで妄想してみた」のパネル展示の様子 SAの佐藤さんの妄想してみたパネル AWS 認定者ラウンジ AWS 認定試験 に合格した人専用のラウンジです。ラウンジ専用のWi-Fi SSIDとパスワード、飲み物、電源が提供されており、歩き疲れたり作業をしたい方に最適な場所となっていました。 特典として、合格した試験ごとにステッカーがもらえます。私は AWS Solution Architect Associate のステッカーをもらいました。 AWS 認定者ラウンジの様子 AWS Solution Architect Associateのステッカー 他にも紹介しきれないほどたくさんの魅力的なコンテンツ 他にも、AWSのサーバレスサービスで作られた Serverlesspresso や、 AWS DeepRacer Japan Championship Cup のレース会場などがありました! AWSのサーバレスサービスで作られたServerlesspresso AWS DeepRacer Japan Championship Cupのレース会場 AWS DeepRacer Japan Championship Cupのサテライトディスプレイ おわりに スタッフや登壇者の方々にはお忙しいにも関わらず、多くの時間を準備に費やしていただいたと思います。この場を借りて御礼申し上げます。 セッションは2024/07/05まで見れるとのことなので、会場に直接行けなかった方もぜひご覧ください。 aws.amazon.com BASEでは、ロールや所属に関わらずAWSを使ってビジネスをリード、あるいはビジネスを守るエンジニアを募集しております。ご興味がある方は、ぜひ下記の採用情報のリンクをご覧ください! binc.jp
はじめに Platform Group の久保田( @ykbt13 )です! BASEではリアーキテクチャとしてバックエンドの既存機能を旧リポジトリから新リポジトリへ移行する作業を日々行っています。詳しく知りたい方はぜひこちらを参照してください。 www.youtube.com そんななか、BASEにおけるコア機能の1つである商品の発送機能の移行が行われました。しかしながら、コア機能であるがゆえに様々な改修が繰り返されて複雑化してしまった発送機能では移行前の動作を保証する術がテストのみでは不安があります。 そこで、リアーキテクチャを円滑に進めるべく、 本番環境上で 移行前後の処理を同時実行しデータベースの結果を比較することで動作の保証を行うツールを開発しました。 この記事では、同様にリアーキテクチャを進めている方々を対象に、そのツール(BASE内では通称DryRunと呼んでいますので以降DryRunと記載させていただきます)について、記載していきます。 TL;DR リアーキテクチャを手助けするツール DryRunを開発しました 実運用では部分的に本番環境を使ったDryRunを行いました DryRunを作っていくにあたって、いかに外部影響が少ないサンドボックスを作り上げることが重要なのかということに気づきました リファクタとリライト 少し本記事の内容から反れますが、背景につながりますので、リファクタとリライトについて触れていきます。 「 レガシーソフトウェア改善ガイド 」において、レガシーなソフトウェアを改善していく方法として リファクタ と リライト について触れられています。 www.shoeisha.co.jp リファクタリングは 外部から見た際に内部の挙動を変えずにソフトウェアを改善していく作業 であり、リライトは 同一機能を一から作り直す作業 に当たるものです。そのうえでリライトはリスクとコストのかかるものであり、 できるだけリファクタリングのみで改善ができないのか を検討したうえでリライトを選択すべきであるとしています。ただ逆説的に言うと、その リスクの保証やコスト面の解決ができれば 、リファクタリングでは得られなかったメリットを享受したうえで改善ができるのではないかとも言えるではないかと思っています。 リアーキテクチャをお手伝いするツール DryRun さてBASEにおいては、レガシーソフトウェアの改善としてリアーキテクチャが行われています。直近ではBASEにおけるコア機能である商品の発送機能の リライト によるリアーキテクチャが行われました。 なぜリファクタではなくリライトによる移行なのかというと、旧リポジトリでは MVC フレームワークでの密結合を前提としたモノリスですが、新リポジトリではDDDとクリーンアーキテクチャをベースとした疎結合なモジュラーモノリスであるため、アーキテクチャのパラダイムシフトが起きておりチームとしてリライトによる移行を選択したからです。 リライトによる大きなリスクの1つとして、 移行前後でのリグレッションリスク というものがあります。これはもちろんテストを通して保証することになりますが、 移行前の挙動と同義である というのを保証するのにテストのみでは限界があると思っています。そこで、移行前と移行後の更新処理に着目して、 データベースに対する永続化が同じものであるかどうか というものを確認することでその保証が行えるのではないかと考えました。これを実現するツールを作成しています。 DryRunの概要図 永続化を行っている箇所をある種の サンドボックス として提供して、移行前の旧機能と同時実行し 各処理で更新されたテーブルを比較すること で、データベースに対する永続化が同じものであるかどうかを比較するものとなっています。移行後のリライトされたコード視点ではサンドボックスであるかの区別はできず、 あたかも本来行うべき永続化処理を行っているかのように振る舞っている ため、DryRunという命名をしました。 かなり単純化されたものにはなりますが、擬似的なPHPのコードでDryRunの挙動を示しますと 移行元の擬似コード // 移行先の機能へのリクエスト function requestNewFeature(): NewResult { } // 更新された各データベースの比較 function compareDatabase(NewResult $newResult, OriginResult $originResult): CompareResult { } // 本来実行される移行元の処理 function executeOrigin(): void { if ($isDryRun === true) { $newResult = requestNewFeature(); } // 移行元の処理の実行 // DryRunであってもなくても必ず実行されます if ($isDryRun === true) { compareDatabase($newResult, $originResult) } } 移行先の擬似コード // データベースにアクセスする根本のinterface interface DatabaseAccess { } // DryRun中のデータベースアクセス class DryRunDatabaseAccess implements DatabaseAccess { } // 通常のデータベースアクセス class OriginDatabaseAccess implements DatabaseAccess { } function getDatabaseAccess(): DatabaseAccess { return $isDryRun == true ? new DryRunDatabaseAccess() : new OriginDatabaseAccess(); } // DryRun向けの処理結果を作成する function createDryRunResult(): DryRunResult { } // 本来実行される移行先の処理 function executeNewFeature(): void { $databaseAccess = getDatabaseAccess(); // 移行先の処理 // DryRun中だとしてもそうじゃないとしても挙動は変わりません。 return $isDryRun == true ? createDryRunResult() : $result } となります。実際には移行先環境ではDoctrineというORMを利用しており、DoctrineのDBコネクタをオーバライドしているのと、Ray.DiというDIフレームワークを利用して、擬似コードのような形でデータベースの向き先を変更しております。 仕組み上ある程度部品化されたコードが準備されているものの、移行対象の機能ごとにサンドボックスを一つ一つ作り上げる必要があるため、頻繁に使えるツールではありません。しかしながら、準備できさえすれば各種環境で動作させることが可能であり、移行元のコードが必ず実行されるようになるため、 本番環境でさえ も動作させることができます。 発送処理におけるDryRunの実運用 発送処理のリアーキテクチャは実働部隊が別途おりまして、DryRunはPlatformチームにて開発をいたしました。DryRunの開発が終わったタイミングで、リアーキテクチャされた発送処理に対して細かい単位(具体的には、支払い方法別)に分割して順次DryRunを適応していき、本番環境へのDryRunを実行していきました。 本番環境で動作させるということで安全に倒すように様々なガード処理を加えていたのですが、意外にもスムーズに動いてしまい、安心するとともにすごいものを作り出してしまったなあと開発当時に思っていた記憶があります。 また特に苦労した点なんですが、BASEのプロダクトの制限で個人情報を保存できる環境に制限があり、比較結果のログの出し方やサンドボックスに保存する際のマスク処理など、細かい単位での対応が必要なところに苦労いたしました。振り返ると1つの共通化したパーツを作り込んでいくというよりかは、泥臭く細かいサンドボックスを作り込んでいくという作業がメインだったなと思います。 そうして順次DryRunを稼働していく中で、実際に開発していただいていたエンジニアと協力して、見つかっていったバグなどの修正を加えてもらいました。 DryRunを利用する目的として、 データベースに対する永続化が同じものであるかどうか というものがありましたが、実運用していくうえで副次的にこのようなメリットも見つかっています。 実際に本番で運用されているデータという膨大なパターンのあるデータを使ってリリース前にコードを走らせることができた リライト中に旧機能への新規開発が行われていてその追従がきちんと行われているのかを確認できた これによって、細かいバグなどがリリースまでに解消でき、また本来の目的であるリグレッションへの対応も行えました。BASE内部の話になってしまいますが実際に開発を行ったエンジニアの方々お疲れ様でした。 反省点や課題点 実際に運用してみたうえでメリットだけはなく、デメリットもいくつか出てきてしまったのでそれらも振り返っておきます。 少し細かい点となってしまいますが、こういった課題がありました。 移行前後で同時に実行することによるパフォーマンスへの影響があった データベースへの書込は実際のRDBMSに書き込んでいたことにより、他のDryRun処理への影響が完全には分離できていなかった いかに 他への影響が少ないサンドボックスを作り込んでいくべきか という点が重要だったんだなと作ってみて改めて感じました。 特に今回、仕組みづくりに使える人員コストを加味して、PHPコード上(つまりはアプリケーションレイヤー)でサンドボックスを作り込んでいたのですが、そもそもデータベースから分けることやモック自体もHTTPサーバ化してPHPコード外で行うなど、各サンドボックスが得意な部分で分割して作り込んでいくというのが良かったのかもしれないと思っています。また、他のDryRun処理への影響という意味ではバージョニングがなされた形でデータベースへの書込みを行うことで回避できたなという反省点もあります。 このあたりはリアーキテクチャが続いていく中で、またDryRun機能を使う機会はあると思っているので、改善していければなと思っています。 おわりに 本記事では、リアーキテクチャをお手伝いするDryRunというツールについて紹介させてもらいました。 いざ作って動かしてみたときに想像していたよりもきちんと動作してしまい、本番環境でデバッグをするというとんでもないものを生み出してしまったなという感覚がありますが、個人的には作っていった中でいろいろと学びがありました。 BASEという環境において作られたものになるので、どこまで外部の方々に参考になるのかはわかりませんが、こういったリアーキテクチャの方法もあるんだなという一例として掲示させていただきます。 どこかでこんな方法で移行作業を行っているのだなと参考になるときが来れば幸いです。 binc.jp
はじめに BASE Feature Dev1 Group の cureseven です。 Google と米Yahoo が定めた 「メール送信者のガイドライン」 が、2024/06/01に対応の最終締め切りを迎えました。 BASE から送信しているプロモーションメールも対応が完了しましたので、対応する過程で起こったトピックを紹介します。 「メール送信者のガイドライン」とはなにか簡単に説明 1回でも月あたり 5,000件以上個人メールにメールを送信したことがあるドメインを持つ「一括送信者」は、以下の規定に則ってメールを送信する必要があります。 DMARC の対応 プロモーションメールには、購読解除ヘッダーが挿入されていること 迷惑メール率が 0.3%を超えないこと AWS が出している こちら の記事がスッキリしていて読みやすいです。 アプリケーション開発チームの私は、購読解除ヘッダーの挿入を主に担当しました。 迷惑メール率は幸運なことに 0.3%未満だったので、減らすための施策を行うことはありませんでした。 サービス関連のメールを全て洗い出す BASE ではシステムからメールを送信する以外にも、他社サービスを使っています。 いつも扱っているサービスのコードを見るだけでは見落としてしまいそうなメールもあったため、自分で登録している BASE アカウントに対して来たメールを見たり、さまざまなチームに問い合わせたりして、全体像を把握していきました。 BASE には、以下の種類のプロモーションメールがありました。 バッチで送信しているオーナー向けプロモーションメール 購入者がショップから受け取るメルマガ、再入荷自動通知、期間販売通知メール 営業チームが使っているメールサービス(SendGrid, kintone)から送信するメール 機械学習チームがショップ開設から最適なタイミングで送信するオーナー向け機能紹介メール(Amazon Pinpoint) 「プロモーションメール」なのか「トランザクションメール」なのか プロモーション メールとトランザクション メールの区別は、業界や適用される規制によって異なります。メールの性質は、Google ではなく受信者が判断します。迷惑メール率が高くなることを防ぐために、マーケティングやプロモーション関連のメール配信の登録をユーザーが簡単に解除できるようにすることを検討しましょう。また、メールを設計する際は、ユーザーを念頭に置くようにしてください。 メール送信者のガイドラインに関するよくある質問 より引用 とあるように、「プロモーションメール」が、業界によって異なる定義であること、判断するのはメールの受け取り手だという記載があります。 チームメンバーに意見を聞きながら、送信しているメールが「プロモーションメール」なのか「トランザクションメール」なのかを判断し分類していきました。 AWSとコミュニケーションを取りながらの実装 予約した時刻にメールを一括送信する機能には、Amazon SES を採用しています。Amazon SESの sendBulkEmailメソッド を使えば複数のメールを一括で送信できます。 AWS SDK for PHP 3.x のドキュメントに従って実装しましたが、sendBulkEMailの仕様通りに実装してもヘッダーが適応がされず困ったため、AWS に問い合わせながら進めました。 問い合わせたところ sendBulkEmail が、送信先ごとのヘッダー挿入に対応したのは 3.305.9 以降とのことで、バージョンアップをすることで解決しました。AWS SDK for PHP 3系ドキュメントに書いてあったため、3系だし大丈夫だろうと思っていました。 3.305.9 がリリースされたのは、メールの規定が開始する2週間前でした。 List-Unsubscribeで指定するURLの要件が厳しい ワンクリック購読解除APIは RFC8058 にしたがって実装する必要があり、以下があったことで、工数が膨らみました。 リクエストパラメータを使ってデータを送信しなければならない 個人を特定できるようなデータを送信してはならず、暗号化されていなければならない 既存のAPIを利用すれば購読解除ができないかと思っていましたが、メールクライアントからワンクリックで購読解除を行うために使う API はリクエストボディが使えなかったため、既存のAPI を修正する必要がありました。 また、リクエストパラメータに含めるハッシュ値の暗号化と、復号化の処理を新規で作成することになりました。 AWS のアカウントをまたいで、同じ方法で暗号化したハッシュ値を使って購読解除APIにリクエストする為、 AWS KMSを使った方法 を採用しました。 AWS KMS を利用して暗号化、復号化ができるようにインフラチームと相談しながら進めました。 開発環境で購読解除リンクが表示されないことがある 開発環境で利用しているドメインからのメールには、購読解除ヘッダーが適切に貼られていても購読解除リンクが出現しない事象がありました。 そのルールが明確に提示されておらず、調査に工数を取られてしまいました。そのため API を直接叩き、購読解除できること 購読解除ヘッダーが適切に貼られていること を確認した上でリリースしました。開発環境で購読解除リンクが表示されていなくとも、本番では全ての購読解除ヘッダーが挿入されているメールに購読解除リンクが表示されていました。 今後も対応されるように社内へ周知 エンジニア全体に、対応方法を周知しました。簡単に実装してもらえるように、以下を工夫しました。 暗号化、復号化のサービスを作り、それを利用するだけで API のパラメータに利用する hash を作成できるようにしました 各メール送信方法に対応するように、購読解除ヘッダーの挿入方法を記載しました BASE以外にも、BASE BANK, PayID チームなどがあります。広く周知しました 上記の詰まったこともドキュメントにし、開発者の対応が詰まらないようにしました おわりに プロモーションメールのワンクリック購読解除は、メールの受け取り手からすると、便利でいい機能ですね。 私のメールボックスも、プロモーションメールでいっぱいになっているので、ポチポチ解除してスッキリさせることができそうです。 規定の適応は開始されていますが、月あたり 5,000 件以上個人メールに送信していないドメインは迷惑メールに入るなどの処置が取られないため、未対応のシステムをお持ちの方もいらっしゃると思います。 今後対応することになった際参考にしていただけると嬉しいです。 binc.jp
はじめに こんにちは、バックエンドエンジニアのSakiです!バックエンドでPHPを書いたり、PHPという言語そのもののメンテナーもしています。 この度、注文データダウンロードAppのパフォーマンスをアップさせるため、とても入念にデータベースまわりの処理を見直しました。その中でも特に速度に関わってくる「index」についての考え方をまとめたいと思います。 この記事はMySQL(InnoDB)についての記事であり、他のRDBについては当てはまらない場合もあるということにご注意ください。 indexとは何か、おさらい ご存知の方ももちろん多いと思いますが、indexについておさらいさせてください。 indexとは辞書でいうところの目次に相当するもので、目的のデータをいち早く検索するために重要なものです。もし辞書に目次が存在しなかった場合、目的の情報を探すのにとても苦労するだろうというのは想像しやすいと思います。 特別なindex、プライマリキーindex DBテーブルには、大抵プライマリキーindexというものが存在します。これはMySQLでは各テーブルに1つずつしか持つことができない特別なindexです。 プライマリキーのカラムで構成され、これはテーブルで必ずユニーク(一意)になります。 必要に応じて追加するセカンダリindex 検索効率を上げる、カラムに対する制約を追加するなど、さまざまな目的で必要に応じて追加するのがセカンダリindexです。言い換えると、プライマリキーindexではないindexは、全てセカンダリindexです。これは1カラムのみで構成されることもあれば、複数のカラムの複合で構成されることもよくあります。また、ユニークなindexにすることも、重複を許すこともできます。 複合indexが使えるシーン、使えないシーン 次のようなindexがあるとします。 単一カラムのindexであればプライマリキーindexと使用感は変わらないので、複合indexについて少し詳しくおさらいします。 // test table UNIQUE KEY `test_prefecture_city` (`prefecture`, `city`) // 都道府県と市の組み合わせ この時、次の2つのクエリを考えてみます。 SELECT * FROM test WHERE prefecture = ' Tokyo ' // 例 1 SELECT * FROM test WHERE city = ' Chiyoda ' // 例 2 ご存知の方はもちろん多いと思いますが、この場合、例1ではindexが効きますが、例2ではindexが効きません(使えません)。 なぜそうなるのかは、本の目次を例にするとわかりやすいです。大カテゴリとして都道府県の並びがあり、それぞれの都道府県の項目の中で市が並んでいるとしましょう。 東京 - 足立区 - 荒川区 ...(略) 千葉 - 千葉市 ...(略) さて、このような構成の目次から、都道府県を無視して(純粋に市だけで並べた場合の)例えば「あいうえお」順で市を探すことは理にかなっているでしょうか?無理があることがわかるかと思います。 したがって、複合indexを使用する場合、必ず左側のカラムから順に絞り込んでいけるクエリである必要があります。 必ずしもメリットばかりではない セカンダリindexはあればあるほど検索効率の向上に繋がりますが、反面、データのinsertやupdate時に全てのindexを更新する必要があるため、indexが多ければ多いほど書き込み処理の負荷が上がるというトレードオフの関係でもあります。 クエリの妥当性はexplainで評価する 実際に業務で使用するクエリは、例でよく見るクエリほど単純ではないことが多いです。実際にクエリが「きちんとindexを使える」かどうかは、 explain という機能を使って評価します。 explain の実行方法と結果の見方は記事がたくさんあるので、ここでは割愛します。 本題: explainだけじゃわからないことがある ここからがこの記事の本題です。 実は、 explain の結果がとても良いのに「なぜか遅い」クエリというものが存在します。これは、主に次のような状況が関係します( Profile を見ても、「データ転送が遅い」というざっくりしたことしかわからなかったりする)。 テーブルが巨大(レコード数が多い) IN句で大量の条件を指定している(取りたいデータの対象が多い) SELECTで取りたいカラムのデータ取得コストがかかっている どういうことなのか、なぜ遅くなるのか、詳しく見てみましょう。 IN句は遅くなりやすい 不等号の範囲指定と違い、IN句(等価範囲)検索は、IN句に渡す値が増えれば増えるほど遅くなりやすい傾向があります。 例として、次のようなクエリを考えてみましょう。 // shipping_number = 配送番号 // shipping_numberのユニークindexがあるとする SELECT * FROM test WHERE shipping_number IN ( ' 0000-0000-0000 ' , ' 0000-0000-0002 ' , ...(略) ); 等価範囲検索の性質上、単に「ここからここまで」という不等号的な検索方法ではなく、IN句の値ひとつひとつについて検索する必要があります。例の場合、 0000-0000-0000 〜 0000-0000-0002 という不等号的な範囲の検索では間の 0000-0000-0001 が含まれてしまいます。 テーブルが巨大であればあるほど、検索コストが大きくなりやすいことがわかります。 ただし、このようなクエリであったとしても、indexを適切に使用できているため、explain上ではかなりいい結果に見えるはずです。このクエリの問題点は、indexを使用することそのものにコストがかかっている、という点です。 取得したいカラムのデータ取得コストがかかる 次のクエリをご覧ください。 // prefecture = 都道府県 // city = 市 // zip_code = 郵便番号 // prefecture, cityの複合indexを持つとする SELECT prefecture, city, zip_code FROM test WHERE prefecture = ' Tokyo ' ; このクエリもまた、indexを適切に使用できるため、explainでは良い結果となります。しかし、テーブル自体が巨大であったり取得件数が多いと「なぜか遅い」ということになりやすいクエリです。 葉ノードという概念を考える ここで重要になるのは葉ノードという概念です。MySQLの使用しているindexの構造は木に例えられるのですが、そこから生えているデータなので「葉」というわけですね。 葉ノードには、カラムのデータが含まれています。冒頭のあたりで使用した、都道府県と市の目次の例を見てみましょう。 東京 - 足立区 - 荒川区 ...(略) 千葉 - 千葉市 ...(略) この例では、目次(index)で指定されている本のページ(テーブルデータ)にアクセスせずとも、都道府県と市の情報は目次の時点で手に入ることがわかります。東京 - 足立区というデータが存在することは目次を見ただけでわかる、ということです。 この情報が、すなわち葉ノードに含まれるデータだと考えてください。 indexは、そのindexに使用するカラムのデータを葉ノードに持っています。ただしプライマリキーindexだけは例外で、全てのカラムのデータを持っています(なので特別なindexなのです)。 ここで追加で「郵便番号」のデータを取得するとします。その場合目次には郵便番号の情報が書かれていないため、実際に目次の示すページを開き、そこから郵便番号を取得する必要があります。 セカンダリindexの使用時は、indexに含まれないカラムのデータを取得する際にテーブルデータへのアクセスが発生し、それがコストになる、と考えることができます(このコストは1件取得程度では誤差ですが、数万件取得、というような規模になってくると大きな差となります)。 解決方法 大量のIN句問題と取得カラム問題、2つの問題を提示しました。これらの解決策を考えてみましょう。 IN句問題: IN句の絞り込みの前に、絞れるだけ絞る 次のクエリをご覧ください。 // shipping_number = 配送番号 // prefecture = 都道府県 // prefecture, shipping_numberの複合ユニークindexがあるとする SELECT * FROM test WHERE prefecture = ' Tokyo ' AND shipping_number IN ( ' 0000-0000-0000 ' , ' 0000-0000-0001 ' , ...(略) ); 問題の提示に使用したクエリとの差は、indexと検索条件に都道府県を加えていることです。こうすることで、IN句の絞り込みの前に都道府県で絞り込んでくれるので、「テーブルの全てのレコード」に対してIN句の絞り込みを行うコストが、「都道府県分のレコードに対して」の規模まで小さくなります。 可能であれば、「都道府県, 配送番号」から「都道府県, 市, 配送番号」、というindexにして、都道府県まで絞り込んでから配送番号をIN句検索、ではなく、市まで絞り込んでからIN句検索にすると、もっと早くなります。 トリッキーな例 // prefecture, ordered, shipping_numberの複合ユニークindexがあるとする // それぞれ、都道府県、注文日時、配送番号 SELECT * FROM test WHERE prefecture = ' Tokyo ' AND ordered < {クエリ実行時よりも十分に未来の日時} AND shipping_number IN ( ' 0000-0000-0000 ' , ' 0000-0000-0001 ' , ...(略) ); 普通に考えて「未来に注文された注文」というものは存在するはずがありません(少なくともこのテーブルの運用では存在しないとします)。 そんなデータあるわけがないのでわざわざWHERE句に含める意味などないように思えますが、例示したindexを使用するためには、実はこの条件指定は有効です。 ORDER BY 句で日時カラムを使用したい場合など、日時系の入ったindexを使用したい、しかし、検索条件そのものに日時データは不要…というシーンはあると思います。そのような場合に有用な、少しトリッキーな方法です。 取得カラム問題: 取得するカラムが本当に必要かをよく考え、使用するindexをよく考える まず、特に理由のない SELECT * は避けるべきです。これは、ただデータ取得コストを増やすことに繋がります。 処理に必要なカラムが何であるのかをしっかり考えて、最低限のカラムだけを取得することがパフォーマンス面では重要です。 そして、使用するindexを吟味することもとても重要です。クエリに使用可能なindexが複数存在するのはよくあることなので、使用できるindexの中で、indexへのアクセスのみで必要なデータが全て取得できないかを検討します。 また、その処理がアプリケーションの中でとても重要で、indexを追加してでもパフォーマンスを上げたい場合、indexを新しく追加することは十分に価値のあることです。 余談ですが、私の試した中では、indexを追加したことで30秒オーバーのクエリが1.6秒まで短縮できました。それだけの速度差があっても、explainの結果に差はありません。 あえてクエリを分割するという選択肢 次のクエリをご覧下さい。 // idはプライマリキー // shipping_number = 配送番号 // prefecture = 都道府県 // zip_code = 郵便番号 // name = 注文した人の名前 // prefecture, shipping_number, zip_codeの複合ユニークindexがあるとする // 別で、prefecture, shipping_number, nameの複合ユニークindexがあるとする SELECT id, shipping_number, prefecture, zip_code, name FROM test USE INDEX (`test_prefecture_shipping_number_zip_code`) WHERE prefecture = ' Tokyo ' AND shipping_number IN ( ' 0000-0000-0000 ' , ' 0000-0000-0001 ' , ...(略) ); USE INDEX を使用して、使用するindexを固定しています。 この例では、 name カラムについて、テーブルアクセスしてデータを取得するコストが発生します( id はコストがかかりません。InnoDBでは、暗黙的にセカンダリindexの最後にプライマリキーが勝手に入るため、葉ノードに id は常に含まれます)。 一方で、使用するindexを test_prefecture_shipping_number_name にすると、今度は郵便番号の取得コストがかかります。 実際にやってみて計測して判断する必要がありますが、これは、次のような方法で解決できる場合があります。 // クエリ 1 SELECT id, shipping_number, prefecture, zip_code FROM test USE INDEX (`test_prefecture_shipping_number_zip_code`) WHERE prefecture = ' Tokyo ' AND shipping_number IN ( ' 0000-0000-0000 ' , ' 0000-0000-0001 ' , ...(略) ); // クエリ 2 SELECT id, name FROM test USE INDEX (`test_prefecture_shipping_number_name`) WHERE prefecture = ' Tokyo ' AND shipping_number IN ( ' 0000-0000-0000 ' , ' 0000-0000-0001 ' , ...(略) ); このように、indexのみでデータ取得が完結するようにクエリを分割し、後からアプリケーション側で id を使用してデータをマージする、という方法です。 USE INDEX を使用することで、MySQLのオプティマイザによる自動的なindex選択に任せず、使用するindexを常に固定することができます。 繰り返しになりますが、これは実際に速度計測を行なって検討する必要があります。カラムの型やサイズによっても結果が異なってくるためです。 余談になりますが、私が色々と試した中では10秒かかっていたものが1秒未満まで短縮したというような例もあったため、試してみる価値は十分にあります。 さいごに 「クエリでちゃんとindexを使用できる」からさらに一歩踏み出して「パフォーマンスの出るクエリとindexの組み合わせを検討する」ことで、より速度を出すことできました。 どうしても複雑に見えるindexですが、読み解いていくと意外と単純な側面もあり、基本に立ち返って「辞書の目次」の例で考えてみると理解しやすかったです。 もしこの記事を読んで興味を持たれたなら、ぜひトライしてみてください!
BASE BANKでPdMをしている岡です。 先日、あるプロダクトの機能開発にあたってデザインスプリントを実施しました。 すると、 「デザインスプリントはチームビルドとしても良い効果がある」 という意外な発見がありました。 今回の記事では、このデザインスプリントの意外な効果について書きます。 この記事で述べることのまとめ デザインスプリントはチームビルドとしても良い効果がある 良い効果1:長期的なミッション・ビジョンに立ち返る 良い効果2:不確実性やイレギュラーケースを洗い出せる 良い効果3:機能要件をアクティブラーニングできる 良い効果4:メンバーのプロダクトへのエンゲージメントを高める デザインスプリントとは デザインスプリントとは、新しいプロダクトや機能のアイデアを迅速に検証するための 5日間の集中ワークショップ形式のプロセスです。 具体的には次のようなプロセスで行われます。 各プロセスの詳細は、次の記事を参考にしてください。BASE BANKチームでは以前にもデザインスプリントを行っており、そのときの内容を詳しくまとめた記事です。 note.com 以前のデザインスプリントでは、参加人数が過多になりそうだったため、PdMとデザイナーだけで実施しました。 しかし今回は、PdM・デザイナー・エンジニア・CSと多様なメンバーを含めて実施しました。 このように多様なメンバーを含めて実施したことで、アイデアの高速検証という効用だけでなく、チームビルドとしても良い効果が生まれました。 「チームビルドとしての良い効果」は、特に day1:理解 と day2:発散 のプロセスで実感したので、それぞれ順を追って書きます。 day1:理解(知識を共有しゴールを設定する) やったこと day1は、プロジェクトに関する知識を共有し、プロジェクトのゴールを設定するプロセスです。 具体的には次の4つのワークを行いました。 プロジェクト背景の共有 懸念点の洗い出し プロジェクトの成功の定義 コンセプトシートの作成 最後のコンセプトシートは、次のようなフォーマットで作成しました {ターゲットユーザー} は、 {具体的なペイン・ニーズ} という要望を持っているが、 {特定のハードル} という理由で満たされていない。 そこで、{新しいソリューション・アイデア} によって、 ユーザーに{理想の体験}という価値を届けたい。 良い効果1:長期的なミッション・ビジョンに立ち返る day1の「プロジェクト背景の共有」や「コンセプトシートの作成」というプロセスを通して、 長期的なミッション・ビジョンに立ち返る ことができました。 特定の機能の開発プロジェクトでは、どうしても機能単体の「なぜやるか」に焦点をおいてしまいます。 しかし、デザインスプリントのday1 では 「そもそもどのユーザーの何のペインを解決して、どういったビジョンを目指すか」 といった、原点を思い出させてくれる問いが用意されています。 実際に、この問いに答えるにあたって、 会社のミッション → チームのミッション → プロダクトのミッション→プロジェクトの目的 といった順番で、 本来の目的からプロジェクトの目的までブレイクダウンしながら詳細に伝えるように工夫しました。 全体から個別のミッションの繋がりを理解することは、ブレない組織を作る上で重要で、PdMとしては何度でもメンバーに伝えたい内容です。 こういった内容は、どうしてもメンバーに話す機会が限られているように思えます。メンバーとの日々の会話では、目の前の仕事を進めるための、もっと具体的で差し迫った話題が多くなりがちなので。 このように、デザインスプリントのday1は、我々の原点をメンバーに共有できるような仕組みになっています。 良い効果2:不確実性やイレギュラーを洗い出せる day1の「懸念点の洗い出し」というプロセスを通して、 PdMだけでは想定しきれなかった不確実性やイレギュラー が洗い出せました。 「懸念点の洗い出し」は、PdMから一通り実現したい機能について詳細まで伝えた後で、どのような懸念があるかをメンバーから述べてもらうプロセスです。 このプロセスでは、PdMやデザイナーだけではなく、エンジニア・CSと多様な職能のメンバーで実施したおかげか、 「このようなユーザーからの問い合わせが月にXX件くらいある」 「この機能を実現するにあたって、〇〇というエッジケースを想定した実装が必要だ」 など、想定していなかったユースケースや技術制約を発見できました。メンバー同士が対話しながら開発を進めるという、アジャイルに近いプロセスとも言えます。 副次的な効用として、自分とは異なる視点の指摘や知見の共有を通して、メンバー同士のリスペクトも高まったように思えます。 day2:発散・決定(アイデアを発散して決める) やったこと day2では、day1で共有した知識や背景を踏まえ、各々のメンバーがアイデアを出し合いました。 各々のアイデアを見つつ、最終的にどのようなソリューションが良いか決定するところまで進めました。 具体的には、制限時間をつけながら、各員が次の4つのワークを通して高速にアイデアを発散→収束まで行いました。 ライトニングデモ( 情報収集) アイディアノート(アイデア発散) クレイジー8(アイデア発散) ソリューションスケッチ(アイデア収束) ソリューションスケッチの展示の様子↓ 最後に、一人一人のソリューションスケッチをお互いに見つつ、どのソリューションで進めるのかを決定します。 良い効果3:機能要件をアクティブラーニングできる day2のワークは、day1でインプットしたプロジェクト背景や、技術制約、ユースケースを思い出しつつ、自分なりのアイデアを黙々と考えスケッチしていく時間です。 このように、デザインスプリントは、 知識のインプット→アウトプットを高速で行うことで、細かい仕様やユースケースまで記憶に定着できる アクティブラーニングのような仕組みになっています。 良い効果4:メンバーのプロダクトへのエンゲージメントを高める day1で長期的なミッションを再確認したおかげか、「あらためて自分はどういったプロダクトを育てているのかがわかって、モチベーションがあがりました」といったメンバーの声もありました。 また、day2は全員のアイデアを踏まえてソリューションを決定していくプロセスであるため、 エンジニアやCSも一緒にUIUXを作るという、プロダクト作りの上流から関わる環境を作り出せました。 そのため、プロダクトへの愛着というか、エンゲージメントも向上できたように思えます。 メンバーのプロダクトへのエンゲージメント強化は、良いプロダクトを作るための大事な条件だと考えています。 Figma, IncのCPOである山下祐樹さんは、プロダクトへの「理屈を超えた情熱」が「魔法のようなプロダクト」を生み出す、といったことを述べられています。 blog.recruit-productdesign.jp デザインスプリントは、メンバーのプロダクトへのエンゲージメントを向上させ、「理屈を超えた情熱」を生み出す装置にもなると期待できます。 BASE BANKのメンバー募集 多様なメンバーを交えて実施するデザインスプリントは、良いプロダクトを作るためだけでなく、チームビルドにも良い効果がありました。 このようにBASE BANKでは、職能を横断し、対話を中心としたプロダクト作りを大事にしています。 このチームで一緒に働きたい!と思った方はぜひ求人からご応募ください。 open.talentio.com
はじめに こんにちは、BASE BANK Division で資金調達サービス「 YELL BANK 」の開発を担当している Doarakko です。 今回は前職でチームリーダーを務めた後にメンバーとして BASE に入社し、再度チームリーダーを務めて感じている役割の変化について話したいと思います。 前職での役割 前職では PdM 1名、デザイナー1名、エンジニア5~6名のチームでエンジニアリーダーを務めていました。 リーダーになった際のチーム状況としては、イテレーション開発はしておらず PdM とエンジニアの間に私が入り、メンバーのタスク状況を見て脳内パズルでタスクにメンバーをアサインする形で開発を進めていました。 エンジニアの人数が5~6名でこのやり方をしていると、どうしてもリーダーの負荷(リーダーがボトルネックになる)やチームの属人性も高くなっていました。 そこで私が開発よりもプロダクト開発プロセスの改善に比重を置いた方が、中長期的に見てチームのアウトプットを最大化できると判断してリーダーとしての役割を変化させました。 SCRUM BOOT CAMP THE BOOK に大変お世話になりながら、スクラムのアプローチを段階的にチームに導入したことを覚えています。 最終的にはプロダクト開発プロセスの改善と PdM のサポートが主な役割で、エンジニアリーダーと言いつつほぼスクラムマスターになっていました。 スクラムについては、自費で認定スクラムマスターの研修を受けに行ってしまうくらい好きになりました。 現在の役割 現在は PdM 1名、デザイナー2名、PMM 1名、アナリスト2名、エンジニアが2名のチームで Engineering Program Manager(エンジニアリーダー)を務めています。 BASE BANK における Engineering Program Manager(以降 EPM)の詳細については、以下の記事を読んでいただければと思います。 一言で言うと、プロダクトのデリバリーとクオリティに責任を持っています。 参考: プロダクトのデリバリー、クオリティに責任を持つEngineering Program Managerという役割 YELL BANK チームでは、スクラムのアプローチをチームの状態に合わせて取り入れながらイテレーション開発を行っています。 入社した当初は前職での経験を活かしてプロダクト開発プロセスの改善に比重を置いていた時期もありましたが、現在は開発業務がメインとなっています。 変わったこと、変わらないこと BASE に入社してからコードを書く時間は圧倒的に多くなりました(コミット数だけで比較しても前職の3倍くらい)。 それはリーダーになった今も変わりません。 自然とそうなった部分ももちろんありますが、意識的に変えたことでもあります。 プロダクト開発の複雑性はチームのメンバー数に比例して高くなり、それに合わせてプロセスを改善して得られるものも多くなります。 実際に スクラムガイド にも「スクラムとは、複雑な問題に対応する適応型のソリューション」だと記されています。 YELL BANK チームではエンジニア数が少ないことと、プロダクトの意思決定を基本的にはチーム内で完結できるということもあり、プロダクト開発の複雑性はまだそこまで高くありません。 実際に「前のチームでやっていたけどこれはやる必要ないか」「この辺はライトにやろう」などと考えることがよくあります。 例えば 細かい計測はせずに、スプリント内に差し込みタスクがどれくらいあったかだけわかるようにする ストーリーポイントは使わずに T シャツサイズで見積もりをする 一部属人化を許容する ある程度プロセスを整えた後に、ここからは私個人で出せるアプトプットを大きくした方がチームのアウトプットも大きくなると判断して、開発業務への比重を大きくしました。 チームやプロダクトのフェーズが変わればリーダーに求められるものも変わるというのは、聞いてみれば当たり前の話ですが、実際に体験してその変化を身に沁みて実感しています。 ただベースにある、リーダーとしてチームのアウトプットを最大化させて事業価値の創出に貢献すると言う考え方は変わりません。 これから別のチームでリーダーを務めることになっても、この考え方は変わらないのかなと思っています。 有難いことにこういったブログを書いているうちに、新しいメンバーが2人入社することが決まりました。 メンバー数が増えることでまた自分に求められる役割も変わったり、よりチームの問題を「チームで」解決していくことが必要になっていきます。 この変化を楽しみながらこれからもプロダクト開発をしていこうと思います。
はじめに こんにちは。BASEのデータ分析チーム(Data Strategy Team)で不正対策を行ったり、機械学習モデルを触ったりしている竹内です。 先日チーム内の論文読み会でニューラルネットを用いた画像合成によるバーチャル試着技術というトピックに触れる機会があったので、その最近のトレンドについて改めてブログという形でまとめてみました。 バーチャル試着は画像生成モデルの実用的なユースケースの一つとして今現在データセットの拡充やアーキテクチャの検証が進んでいる分野の一つであり、個人的には非常にアツいトピックだと感じています。 バーチャル試着とは バーチャル試着(Virtual Try On)とは、ある人物がある衣服を着用した状態を画像や3Dモデルなどの情報をもとに仮想的に実現し、どのように見えるか可視化する技術のことです。 ネットショップの普及により、店頭に出向かずともPCやスマートフォンから簡単に多種多様なファッション商品を購入することができるようになって久しい昨今ですが、その一方でオンラインではどうしても購入前に試着することで見た目やサイズ感を確かめることができないという課題を抱えています。バーチャル試着を利用することで、直接店頭へ出向かずに着用した際のイメージを得ることができるため、購入者においては誤って購入してしまうリスクを、ショップにおいては返品のリスクを減らすことが可能になります。 また、ネットショップの商品ページにおいては、扱っている商品単体の画像だけでなく、ファッションモデルがそれを着用した際のイメージ画像もよく利用されています。しかしながら、日々変化するトレンドの中で、商品が多種多様化し、ショップの規模もさまざまある中で、すべての商品においてファッションモデルを利用したイメージ画像を用意することは難しい場合があります。これについてもバーチャル試着を活用することで、多様なファッションモデルがさまざまなポーズで着用したイメージ画像を簡単に用意することが可能となります。 ニューラルネットを用いたバーチャル試着技術 バーチャル試着の実現においては3Dモデルの利用やAR技術、身体計測専用のスーツの利用など、さまざまな手法が検証されていますが、中でも昨今のニューラルネットを活用した条件付き画像生成技術の進歩により、入出力に画像を使用した分野においては目覚ましい進歩を遂げています。 ARやボディスーツなどと比較して入出力に画像を使用する場合は、カメラなどのデバイスの操作やスーツの着用といった手間がなく、またさまざまなポーズに対して自然な見え方が検証できるという利点があります。 ニューラルネットを利用したバーチャル試着モデルのイメージ( 1 より作成) 画像生成モデルによるバーチャル試着の登場 ニューラルネットによる画像生成手法としては、長らくGANやVAEを利用したものが主流であり、バーチャル試着への応用についても当初はそれらの技術をベースとしたものが考えられていました。 2017年に発表されたCAGAN 2 という手法はその中の1つであり、その名の通りGANをベースとした手法です。 Generatorは人物画像とその人物が着用している服画像、合成対象の服画像の3つを入力として合成画像を出力し、Discriminatorは与えられた画像がデータセットからのサンプルなのか、あるいはGeneratorの出力なのかを識別します。 この時GeneratorはDiscriminatorに当てられないように出力し、Discriminatorは出力を正しく識別できるように学習を行います。 CAGANではGeneratorの出力を安定させるために2つの服画像をスワップさせながら2回Generatorに通すことで元の人物画像をどれだけ復元できるかをLossに含めている点が特徴的であり、一般的な条件付き画像生成と比較して出力の安定性を追求している点が伺えます。 スワップを利用したGeneratorの出力([^2]より) Discriminatorは正例と負例を正しく識別できるように学習する GANから拡散モデルへ 2021年あたりから従来のGANやVAEではなく拡散モデルをベースとした手法が台頭しはじめ、それ以降、条件付き画像生成モデルの学習の安定性や出力のクオリティは格段に上がりました。 バーチャル試着においてもその恩恵は大きく、拡散モデルを採用することによって格段に正確な画像を高い解像度で生成できるようになっています。 拡散モデルを使用したバーチャル技術に関する論文はいくつかありますが、今回はその中でも特徴的なTryOnDiffusion 3 とOOTDiffusion[^1]の2つを取り上げたいと思います。 先にCAGAN、TryOnDiffusion、OOTDiffusionによる出力例をそれぞれの論文内から抜粋し、比較しておきます。 後者2つが拡散モデルベースの出力となりますが、再現度や解像度の面で大きな改善が見られていることがわかります。 CAGANによる出力例(入力画像) CAGANによる出力例(出力画像) TryOnDiffusionによる出力例 OOTDiffusionによる出力例 TryOnDiffusion タイトル: TryOnDiffusion: A Tale of Two UNets arxivリンク: https://arxiv.org/abs/2306.08276 2023年にワシントン大学とGoogle Researchのメンバーによって発表された論文です。 TryOnDiffusionはParallel-UNetと呼ばれる2つのUNetを使用し、一方へはターゲットなる人物にノイズを付与した画像と元画像の服部分をマスクした画像をconcatしたもの、もう一方へは試着対象の服画像を入力し、ノイズを除去するプロセスを繰り返すことで、出力画像を1024×1024という高い解像度で生成することに成功しています。 服の画像単体ではなく、ターゲットとなる人物の画像と、試着対象の服を着た別の人物の画像の2つを入力として使用している点が特徴的です。 TryOnDiffusionのネットワークの全体図([^3]より) TryOnDiffusionでは2つのUNetの出力をcross-attentionを使用することで組み合わせています。(図の黄緑色のブロック) 1つのUNetにノイズ画像と服画像をconcatしたものを入力とする方法をとっていない理由として、服画像を人物画像にフィットさせる際形状を大きく歪める複雑な変形が必要となりますが、UNetで採用されている畳み込みとself-attentionのようなピクセル単位での強いバイアスがかかる機構はそれに適さないと言及されています。これについてはablation studyとして2つのアーキテクチャを比較した検証もなされていますが、単純なconcatと比較して細部のテクスチャにおいて違いが出ていることがわかります。 cross-attentionとconcatとの比較([^3]より) 1つのDiffusionモデルの学習には32基のTPU-v4を使用しており、データセットとしては同じ人物が同じ服を別のポーズで着た画像ペアを400万ペア使用しています。 バッチサイズ256で50万ステップ回すのにだいたい3日かかると記載されており、かなり大掛かりなモデルであることがわかります。 ちなみにこのTryOnDiffusionを使用したバーチャル試着システムは2023年の6月からプロダクトとしてリリースされており、 Google’s Shopping Graph と呼ばれるGoogleの保有している商品データセットの一部ファッション商品を対象に、スキントーンや体型の異なるさまざまなファッションモデルが着用したイメージを取得し、購入の参考にすることができます。(現在は米国限定のようです。) https://blog.google/products/shopping/ai-virtual-try-on-google-shopping/ また、このモデルについてはデータセットやモデルパラメータは公開されていません。 OOTDiffusion タイトル: OOTDiffusion: Outfitting Fusion based Latent Diffusion for Controllable Virtual Try-on arxivリンク: https://arxiv.org/abs/2403.01779 OOTDiffusionは中国の大手AI企業Xiao-iのリサーチチームによって比較的最近公開されたバーチャル試着モデルであり、LDMを使用することで計算コストを削減しながら出力のクオリティの高さを維持しつつ、トップスだけでなく、ボトムスやワンピースなど、さまざまなカテゴリに対応している点が特徴です。 ネットワークのアーキテクチャについてはTryOnDiffusionと同様に衣服部分をマスクした人物画像を入力とするUNetと服画像を入力とするUNetの2つを使用し、UNet内のself-attention層の前でconcatするOutfitting fusionと呼ばれる手法で2つのUNetを繋げています。 OOTDiffusionのアーキテクチャ([^1]より) 先ほどのTryOnDiffusionと大きく異なる点として、Stable Diffusionなどでも採用されているVAE encoderを使用して潜在空間上でノイズ除去を行うLatent Diffusionベースのアーキテクチャを採用しており、このため一般的なGPU一基で推論を動かすことができます。(さながらTryOnDiffusionのLDMバージョンといった感じでしょうか。)学習時のUNetの重みの初期値としてもStable Diffusion v1.5のものをそのまま使用していると記載されています。 また、全身に対応したバージョンにおいてはCLIPを使用しており、試着を行う部位に関して(”upper body”など)テキストでのガイドを入れることで、出力を安定化する工夫も入れられています。 OOTDiffusionについてはGithubでソースコードが、Hugging Face Hubでモデルパラメータが公開されているため、計算環境があればすぐに手元で検証することができます。(ライセンスはcc-by-nc-sa-4.0なので、そのまま商用利用はできない点は注意が必要です。) https://huggingface.co/levihsu/OOTDiffusion/tree/main/checkpoints 学習においては上半身限定のモデルにはオープンデータセットのVITON-HDを、全身に対応したモデルにはオープンデータセットのDress Codeを使用し、バッチサイズ64(高解像度のものは16)で36000ステップの学習をA100一基で行っています。 TryOnDiffusionと比較してもかなり軽量なモデルであることがわかります。 ちなみに、TryOnDiffusionとOOTDiffusionを含めた最近のニューラルネットベースのバーチャル試着モデルでは、ターゲットとなる人物の画像の服の部分をマスクする前処理を行うことがほぼスタンダード化しており、OOTDiffsuionでは姿勢推定モデルの openpose とセグメンテーションモデルの humanparsing の2つを組み合わせたパイプラインが利用されています。 バーチャル試着モデルに用いられるオープンデータセット 少し脇道に逸れますが、こうしたバーチャル試着モデルの学習やテストによく使用されているオープンデータセットについても触れておきます。 バーチャル試着モデルの性能の向上については、モデルアーキテクチャやアルゴリズムの改善と並行して高品質かつサイズの大きなデータセットの拡充も後押ししています。(そこまでメジャーとは言えないタスクの割には利用しやすいデータセットが複数存在するため、研究や検証のテーマとしては案外取り組みやすい印象です。) また、これらのデータセットについては基本的には研究用途でのみ使用できるライセンスが設定されています。 VITON-HD KAISTによって公開されているデータセットで、複数の論文でベンチマークとしてもよく使用されている印象です。 1024 x 768の高画質な人物画像と服画像のペアが、学習用が11647セット、テスト用が2032セット含まれています。 また、それぞれの人物画像に対してpose推定やdense推定など処理済みのデータも含まれています。 https://github.com/shadow2496/VITON-HD FashionTryOn 山東大学によって公開されているデータセットであり、VITON-HDより大規模なデータセットになります。 服画像と異なるポーズの人物画像2ポーズ分の3点を1セットとして28714セット含まれています。 https://fashiontryon.wixsite.com/fashiontryon DressCode イタリアのモデナ・レッジョ・エミリア大学とイタリアの大手EC企業YOOX社によって公開されているデータセットであり、バーチャル試着モデルのデータセットとしては最大規模のサイズのものとなります。また、データセットに含まれるファッション画像はトップスだけにとどまらず、ボトムスやアクセサリなど、さまざまなカテゴリーのものが含まれている点が特徴です。 OOTDiffusionの全身モデルの学習にも使用されています。 https://github.com/aimagelab/dress-code データセットの規模の比較( 4 より) 課題 上記の論文以外にも拡散モデルを利用したバーチャル試着を検証した論文はいくつかあり、いずれにおいても従来のモデルと比較してKIDなどの指標において高い数値を出すことに成功しており、定性的にもクオリティの高い出力を得ることができていますが、まだ改善の余地もあります。 上記の論文で課題として挙げられている点としては、 入力画像の背景が複雑な場合に出力にどのような影響があるか不明である。 人物画像と服の画像のカテゴリが異なる場合、例えばTシャツを着ている人物にワンピースを、ズボンを履いている人にスカートを合わせる場合は期待した出力が得られない場合がある。 服部分をマスクする際に人物の肌の情報(筋肉の状態やタトゥーなどの特徴)が欠損する。 といったものがあります。 1つ目に関しては、人物と背景を分けるセグメンテーションを前処理に挟むことで背景に対してある程度背景に頑健なパイプラインを組むこと自体は可能に思えます。 2つ目に関しては、データセットにそういったサンプルがないためであると考えられ、データセットのバリエーションを増やすことによってある程度改善できる可能性があると述べられています。 3つ目については、2つの論文で共通して挙げられている課題であり、こちらも前処理でセグメンテーションを行う範囲をより限定することができれば、ある程度改善できそうです。しかしながら長袖→半袖のような入出力を考える場合は情報が足りないため、その場合はそれを補うような入力を追加する必要がありそうです。 また、そもそも入出力に画像を利用している以上、オーバーサイズやタイトめなどといったサイズ感やシルエットについては正確な情報を反映しづらいという点があるというのは実際に動かしてみて私が実感した課題です。 まとめ ニューラルネットを使用したバーチャル試着技術について紹介しました。 画像生成においてバーチャル試着というユースケースについては、StableDiffusionなどでプロンプトからオリジナルの画像を生成する用途などと異なり、クエリとなる画像から期待される出力が非常に限定されるため、少しでも歪んでしまったり服の柄が変わってしまうだけで利用価値が大きく損なわれることになります。 逆に言えば、モデルの性能やデータセットのバリエーションの向上に合わせて一気にその実用性が高まっていくような分野でもあるため、今後の技術的な進歩や実際のサービスへ導入などへの期待が高まります。 最後となりますが、弊社では一緒に働いてくださる方を広く募集しております!ご興味のある方は下記のリンクからお気軽にご応募ください! https://binc.jp/jobs Xu, Yuhao, et al. "Ootdiffusion: Outfitting fusion based latent diffusion for controllable virtual try-on." arXiv preprint arXiv:2403.01779 (2024). https://arxiv.org/abs/2403.01779 ↩ Jetchev, Nikolay, and Urs Bergmann. "The conditional analogy gan: Swapping fashion articles on people images." Proceedings of the IEEE international conference on computer vision workshops . 2017. https://arxiv.org/abs/1709.04695 ↩ Zhu, Luyang, et al. "Tryondiffusion: A tale of two unets." Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition . 2023. https://arxiv.org/abs/2306.08276 ↩ https://github.com/aimagelab/dress-code ↩
ごあいさつ はじめましての人ははじめまして、こんにちは!BASE BANK Divisionのフロントエンドエンジニアのがっちゃん( @gatchan0807 )です。 今回は、ここ数ヶ月の間にOIDC(OpenID Connect)という技術を使った開発を複数行い、この技術の概観を理解することができたので、OIDCの技術概要に触れつつBASE BANKの中でどのように使ったのかをご紹介しようと思います。 OIDCとは何なのか このパートでは、まずOIDCという技術について概要を紹介します。いくつかのWebページに記載されていた内容を参考にしてまとめさせて頂いているので、記事の最後に参照元のリンクを記載しておきます。 また、OIDCをはじめとした認証・認可の仕組みには様々な用語があり、自分自身も「調べれば調べるほど知らない用語が増えて、どんどんわからなくなってきた…」という経験をしたので、それらを具体例を交えて箇条書きなども用いながらまとめています。もし、明らかに間違ったことを書いている場合はX(旧Twitter)などで適宜ご指摘いただけますと幸いです! OIDC(OpenID Connect)とは? OIDC(OpenID Connect)は OpenID Foundation が策定をしている、アイデンティティ情報を連携するためのプロトコルの一種です。 このプロトコルは、Webアプリケーション等で利用する場合はOAuth 2.0(Googleログインなどで使われている「認可」プロトコル)をベースに、アイデンティティ情報を持つサーバー(IDプロバイダ)とサービスを提供するアプリやWebサーバー(サービスプロバイダ)でやり取りする値の中身まで定義しており、「認証」に使えるプロトコルとして定義されています。 この「認証」プロトコルを使ってSSO(シングルサインオン)の機能を実現することが多く、2024年現在では様々なところでOIDCプロトコルに対応した認証機構が用意されています。 ここまでで「認証と認可」や「SSO(シングルサインオン)」など、いくつか専門用語が出てきているので、これらがどういうものなのかおさらいしていきましょう。 認証と認可の違い 認可 : ユーザーまたはサービスに、 データへのアクセスまたは特定の処理の実行を許可する こと 認証 : 誰かまたは何かが、 主張する通りの人物または物であるかどうかを検証し、特定する こと 出典: https://www.onelogin.com/learn/authentication-vs-authorization OAuth2.0では「認可」を行うための仕組み(認証を実装しようと思えば出来るが、技術仕様上は担保出来ないので非推奨)を定義しています。 例えば、OAuth2.0を使ったGoogleログインなどでは「Googleの画面でログイン→Googleの認可サーバーからアクセストークン発行→Googleのリソースサーバーにアクセストークンを渡してデータを取得」というフローでデータのやり取りが行われています。 ただ、発行されたアクセストークンには「誰のリソースにアクセスしていいか?」という情報しかない(そのアクセストークンを送ってきたのが誰なのかはわからない)ため、何らかの方法でアクセストークンを盗まれると、認可サーバー側で認可した人以外にリソースを奪取されてしまうことになります。 OIDCではこれを防ぐために、「IDトークン」という形の(暗号化・復号化の仕様まで定義された)トークンをやり取りすることで「やり取りをしている相手が誰(何)であるか」を識別し、それを元に適切な権限付与を行えるように技術仕様を定義しています。 [追記: 2024-05-02] 後日、X上にて @pinzolo 様よりご連絡をいただき、図の中の誤っていた部分(「⑤ IDトークンを送信」と記載していた部分)を「⑤ アクセストークンを送信」という形に修正しました! ご指摘いただき誠にありがとうございました! 記事内の図の話ですが、OIDC で UserInfo endpoint からユーザー情報を取得するときも access token を使います。ID Token は受け取って検証するだけで送信しないです。 https://t.co/Wz7sAxtFeZ — pinzolo (@pinzolo) 2024年5月2日 要求された End-User の Claim を取得するため, Clientは OpenID Connect Authentication を通して得られた Access Token を用いて UserInfo Endpoint に要求する. 引用元: https://openid-foundation-japan.github.io/openid-connect-core-1_0.ja.html#UserInfo SSOとは SSO(シングルサインオン)とは「1つのアカウントにログインすることで複数のサービスのログインが可能になる機能」のことです。この機能を実現するために、OIDCやSAML(後述)という技術・プロトコルを利用するという関係性です。 BASE内では OneLogin (クラウド型ID管理サービスの一つ)を使ったSSO環境を利用しており、Google Wokrspaceなど各種アカウントへのログインをセキュアに便利に利用できるように環境が構築されています。 SAMLとは SAML(Security Assertion Markup Language)は、XMLベースの認証情報を表現する方法の規格のことです。現在では、そのSAML(XML情報)を送受信して認証を行うルール・プロトコルまで含めてSAMLと表現されることが多いです。 SAML認証では、サービスプロバイダ側からIDプロバイダに対してSAML形式のXMLファイルをあらかじめ登録し、ID情報を「どこから入手するのか・どこに提供するのか」の連携を事前に取っておく形で認証が実現されています 現在主流のSAML 2.0は2005年に仕様が策定され、SSOの機能を作る際のデファクトスタンダードな仕様として使い続けられてきたため、世の中に非常に多くの文献・利用事例などがあります。 しかし、そもそも XMLのパースやそのパース後のデータを利用した通信フローの作成、XML自体の脆弱性の対応が必要だったりして、全体として難解になりがち で、仕様を理想通り実装できれば全く問題ない認証方式だが、 現実は実装に問題があって脆弱になってしまうということが起こりがち なものでした。 そのため、SAMLを代替できるようにOIDCが生まれ、利活用されてきている。という背景があります。 SAMLとOIDCの違うところ 以上のように、SAMLとOIDCは どちらもSSOに使われる技術であり、認証を実現するための技術であり、どちらもIDプロバイダとサービスプロバイダとクライアント(ユーザーの端末)が決められた手順で通信を行って認証する技術 です。 逆に、差分として以下の2点があり、今回BASE BANKでは「サービスプロバイダ側の実装が簡単になる」というメリットを享受するためにOIDCを使った認証・連携処理を作成しました OIDCはHTTPS通信でデータをやり取りし、JWTという(XMLよりも)単純な文字列をやり取りするため、サービスプロバイダ側の実装が簡単になりやすい OIDCでは、サービスプロバイダ側からIDプロバイダに対して希望する データのスコープ(範囲)をリクエストできることが仕様として存在 しており、クライアント(ユーザーの端末)に対してサービスプロバイダにどのデータが与えられるかを伝えることが容易に実現できる 今回BASE BANKで使ったところ ここまで、OIDCとそれに関連する技術・キーワードについて紹介をしてきましたが、ここからはその技術を実際どこで使ったの?というところを紹介していきます。 GitHub ActionsからAWSリソースにアクセスし、デプロイする 1つ目のユースケースは、 GitHub Actionsを使って、AWS上にある開発環境(ステージング環境とは別に、非エンジニアが動作確認する際やQAを行う時に利用する環境)に対してアプリケーションをデプロイする ワークフローを作成する際にOIDCでの認証を利用しました。 BASE BANKチームが主に開発を行っている YELL BANK (BASEのショップオーナーさん向けの資金調達機能)のバックエンドには、APIとして利用するアプリケーションが複数あります。 ざっくりとした技術構成に関しては、 BASE BANKチームの紹介資料 をご覧ください。 これまではステージング環境での確認で事足りていたため開発環境を使う機会が少なく、本番へのデプロイと同時に(本番との差分をなくすためのデプロイを)CI上で行うだけで問題なかったのですが、この環境をもっと活用していくために開発環境へのデプロイを自由なタイミングでもっと手軽に行えるようにしたい!というモチベーションからこの対応を行いました。 全体の作業の流れとしては、以下のように大きく3つのステップで実現できました。 AWS IAMでOIDC Providerを作成する(このProviderにロールを指定し、AWS リソースへのアクセス許可を行う) https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_providers_create_oidc.html GitHub Actionsのステップで aws-actions/configure-aws-credentials を使い、上記で作成したOIDC Providerを指定する https://github.com/aws-actions/configure-aws-credentials?tab=readme-ov-file#oidc GitHub Actionsのワークフローを workflow_dispatch から利用できるようにし、GitHub上のActionsタブから利用する(完成!) より詳しい解説はGitHub Actions公式の解説ページをご覧ください。 docs.github.com AWS IAMでOIDC Providerを作成する 今回はマネージメントコンソールからOIDC Provider作成する方法を解説します。( AWS CLI経由など他の作成方法はAWS公式ドキュメント をご確認ください) 以下のように、 GitHub公式の解説ページ に記載されているプロバイダのURL(AWS ⇒ GitHubへのリクエスト先なので、基本的にここはユーザー個別ではない)を設定し、サムプリントの取得の上ID Providerを作成してください。 ID Providerの作成後、IAMロールを割り当てることでAWSリソースにアクセス可能なOIDC Providerが出来上がります。 注意点としては、AWS IAMの管理単位として上述の「プロバイダのURL」に設定したURL単位で1つのIAMユーザーとして扱うため、1つのAWS環境に対してのGitHub ActionsからのOIDC経由アクセスは1つに集約されてしまい、GitHub Actionsのワークフロー / リポジトリごとに「このリソースへのアクセス権限だけ与える」ということは出来ない点だけご注意ください。 GitHub Actionsのワークフローの作成 今回は将来的な拡張も見据えて、以下のような形で workflow_dispatch の input として環境名を受け取れるようにしていますが、基本的には GitHub公式の解説ページ のGitHub Actionsのワークフロー設定を踏襲して実装しています env : dev_id : 123456789012 on : workflow_dispatch : inputs : env : description : "deploy env(現時点は dev のみ)" required : true type : choice default : "dev" options : - "dev" jobs : deploy : name : deploy runs-on : ubuntu-latest permissions : id-token : write contents : read actions : read steps : - uses : actions/checkout@v4 - name : Configure AWS Credentials uses : aws-actions/configure-aws-credentials@v4 with : # 作成したIAM Role名を指定する # see: https://github.com/aws-actions/configure-aws-credentials # 例) dev指定のときに env[format('{0}_id', inputs.env)] => dev_idを取り出す role-to-assume : arn:aws:iam::${{ env[format('{ 0 }_id', inputs.env)] }}:role/${{ inputs.env }}-oidc-provider aws-region : ap-northeast-1 (以降は、各ステップでデプロイに必要なAWS ECRへのコンテナのPushやAWS ECSクラスターへのプロビジョニングコマンドをaws cli経由で実行している) GitHub上のActionsタブから利用出来るように 上述のYAMLファイルをデフォルトブランチにマージすることで、Actionsタブから以下のように実行することが可能になります。 画面右上のRun workflowから実行時に利用するブランチと環境情報を選択できるので、これでデフォルトブランチ以外のブランチを開発環境に適用することもGUIからかんたんにできるようになりました。 社内向け管理画面でNextAuthを利用し、OneLoginを使ったSSOを実装する 2つ目のユースケースは、 新たに作成する社内向け管理画面のログイン機構にOneLoginを使ったSSOでの認証機構を用意するために、NextAuthでOIDCを利用 しました。 NextAuth とは、複雑な認証・認可の処理をラップして提供してくれるJavaScript向けライブラリのAuth.jsの派生ライブラリで、中でもNext.js用にチューニングされたものの名前です。 このNextAuthを使った社内向け管理画面自体はまだ完成していない状態ではありますが、PoCの段階でOIDCでのOneLoginとNext.js製アプリケーションとの連携が問題なく行えることを確認できて、このまま本番投入を行う予定のため、主になぜこの意思決定をしたかをご紹介します。 今回のOneLoginと社内向け管理画面のログイン機構では、OneLoginが提供しているAppの 「OpenID Connect (OIDC) Custom Connector」を利用してClient ID / Client Secrets / Issuer情報を発行 し、それらの情報を NextAuthのOneLogin Providerの形式 に合わせて利用する形を取っています。 このアーキテクチャでの実装(IDaaSやフレームワーク選定)をなぜ選択したのか?をまとめたADR(Architecture Decision Records)があるので、そこから内容をサマライズし箇条書きしたものを以下に記載しておきます なぜクラウド型ID管理サービス(認証IDaaS)はOneLoginを利用するのか? BASE内のSSO環境でOneLoginを使っている事例が複数あるため、それと合わせたSSO環境を利用すると認証、認可情報の管理を効率的に行えると考えたため なぜOIDCの実装でNextAuthを利用するのか? 今回、管理画面を作成するプロダクトのプロダクションコード側は既にNext.jsで実装されており、(フロントエンドメンバーの人数がチームに少ない事もあって)学習すべき技術を分散させないためにNext.jsを利用することにしたため Next.jsを利用する場合、ブラウザ上での実行なのかサーバー上での実行なのかがコード上から判別しづらく、OAuth 2.0(OIDC)の通信ステップをある程度隠蔽して、NextAuthのAPI経由で認証データを取得する方が全体像の理解がしやすいと考えたため なぜOneLoginとの接続方法はSAMLではなく、OIDCを利用するのか? 前述の解説パートの通り、OIDCはSAMLの代替になるようOAuth 2.0の仕様を拡張して定義された認証方法。SAMLに比べるとまだまだ導入事例は少ないが、直近はAWS、GitHub、Azure、GCP等様々な箇所の認証方式として利用されていて、2024年時点でSAMLではなくOIDCでの導入に踏み切っても、問題ないと判断できたため OneLoginからOIDC認証経由で取得できるデータ(claim)の種類も必要十分であることがわかり、取得可能なデータと言う面でもOIDCで問題ないと判断できたため このURL から確認できるJSONの claims_supported の値 その他、検討したが選択しなかったこと SDKにAuth0を使うパターン OneLoginと併用する場合、認証IDaaS(SSO提供サービス)が二重( Auth0 → OneLogin )になり、Auth0とOneLoginをSAMLで連携させないといけないため 社内でのAuth0の利用事例はなくゼロから探索をする形になる。そのコストを払うよりもOneLoginを使う方が効率的だと考えたため Auth0のSDKにNext.jsとExpress以外のものはなく、アプリケーションの実装フレームワークをNext.jsにする選択肢(Next.jsへのロックインを避ける方向)としても、特にNextAuthと比べた差分がなかったため NextAuthを使わず、OIDCの通信ステップをフルスクラッチするパターン Next.js上でフルスクラッチでOIDC(OAuth 2.0 + IDトークン)の認証フローを実装するのは、Next.jsがSSRとCSRどちらも活用してアプリケーションを作成するフレームワークである以上、コードの複雑性が高まりやすい。そのため、フルスクラッチ実装 + そのメンテナンスと、NextAuthライブラリのバージョンアップ等のメンテナンスコストを比較したときに後者のほうがコストが低いと考えたため 認証をID/Passwordでフルスクラッチするパターン 入退職者管理、セキュリティ脆弱性を産まない実装、適切なアクセスコントロールを実現するために、OneLoginのSSO基盤の上に乗せる形に比べてコストがかかりすぎると判断したため おわりに ここまで、OIDCという技術について関連キーワードも含めた紹介とBASE BANKチームの中でどのように利用したのかを紹介させていただきました。 今回ゼロからOIDCという技術を学びつつ、導入のメリット・デメリットなどを整理していましたが、非常に便利な技術で適宜活用していきたいなと思いました。 このように、新機能開発や新規事業などはもちろんのこと、フルサイクルエンジニアとして計測基盤を盤石にするための開発や開発体験の向上のための開発などなど…様々な開発が少人数で活発に行われているが故に、適切に調査・言語化することで技術選定を任せてもらうチャンスも多いBASE BANKチームにもし興味が湧いた方はぜひカジュアル面談などにご応募いただけると嬉しいです! gatchan0807としては、一緒にBASE BANKチームのフロントエンドを盛り上げてくれる方をとっても求めています! X(旧 Twitter) のDMやリプライなどでも問題ないので、お気軽にお声がけください〜! 参照したWebページ 最後に、この記事を書くにあたって参照させて頂いたページを紹介してこの記事を締めくくろうと思います。知識を公開情報にしてくださった先人たちに最大限の感謝をこの場でお伝え出来ればと思います。ありがとうございました! https://www.openid.or.jp/document/ https://openid.net/developers/how-connect-works/ https://www.onelogin.com/jp-ja/learn/oidc-vs-saml https://www.cloudgate.jp/glossary/saml.html https://boxil.jp/mag/a2950 https://admina.moneyforward.com/jp/blog/saml-sso https://solution.kamome-e.com/blog/archive/blog-auth-20221108/ https://logmi.jp/tech/articles/322829 https://img.logmi.jp/article_images/JCf94mRZseDVe6Dq2CiBU8.jpg https://www.slideshare.net/tkudo/openid-connect-devlove https://qiita.com/TakahikoKawasaki/items/8f0e422c7edd2d220e06
はじめに こんにちは、バックエンドエンジニアの@zawaです。 私は入社以来、1年ほどショップオリジナルの「メンバーシップ」(会員制度)を開設できる「メンバーシップApp」の開発に携わってきました。 少し前になりますが、2024年2月末にメンバーシップAppの特典交換機能をリリースしました。 リリース内容の詳細はぜひこちらをご覧ください! baseu.jp メンバーシップAppは、モジュラーモノリスのアーキテクチャ上に構築しており、モジュール内部ではドメイン駆動設計(以下、DDD)を採用しています。 先日公開された動画の中でも紹介していますので、ご興味がある方は是非ご覧ください。 【前編】クリーンアーキテクチャの柔軟性を生かしたメンバーシップAppの開発の道筋 - YouTube 【後編】クリーンアーキテクチャの柔軟性を生かしたメンバーシップAppの開発の道筋 - YouTube 本記事では、初めてDDDを採用したチームが直面した課題と、またそれらをどのように克服していったのかをお伝えしたいと思います。何か参考になることがあれば幸いです! プロジェクトの概要 メンバーシップAppの開発は、次の3段階でリリースし、1st~3rdまでの総期間は1.5年ほどかかりました。 1st:メンバーシップを開設できる機能 2nd:ショップオリジナルのポイントを貯められる機能 3rd:購入時に貯まるオリジナルポイントと、ショップで設定した特典を交換できる機能 領域を分けてコンフリクトしないようにしつつ、2チーム体制で開発を行っていました。 エンジニアだけでも15人前後は関わっており、かなり多くの人が関わっていたプロジェクトでした。 私は1stの途中からチームに参加し、主にショップオーナーさん向けの機能開発を担当してきました。 1st、2ndで得た学び 初めのうちは、チームでの輪読会や組織内の有識者への相談を通じて、徐々にDDDに関する理解を深めていきました。 2ndのリリース後の振り返りの中で、どうすればさらに改善できるかについて、具体的な振り返りを行いました。 データモデリングとドメインモデリングの誤解とその影響 まず、1st、2ndでは、データモデリングとドメインモデリングのそれぞれの目的を正しく理解できていなかったね、という話題が出ました。 ドメインモデリングではドメイン領域に焦点を当てて会話し、ドメイン領域への理解を深めることが重要ですが、私たちのチームはデータの永続化や具体的なデータ構造に関する議論に偏っていました。 事前にデータモデリングの勉強会を行い、テーブル構造を事前に検討した影響もあってか、エンティティや値オブジェクトを特定した後も、「このエンティティの永続化が必要か」「どのタイミングで永続化すべきか」「どのようなデータ構造が適切か」という永続化の観点が議論の中心になってしまい、ドメインの振る舞いやルールについて十分な検討を行う前にドメインモデルの実装に進んでしまいました。後になってから、永続化とドメインモデルは別々に考えるべきだった、ということに気づきました。 これによって、次のような実装になってしまい、オブジェクトの整合性も保ちづらく、保守性も低い上に理解しづらい実装になってしまいました…😢 ドメインルールや振る舞いについて深く考えることができなかった結果、本来ドメインモデルにあるべき実装がアプリケーション層やドメインサービスに漏れてしまうことがあった。 集約について議論していなかった結果、テーブルとRepositoryが1対1になっていたり、ロジックの置き場所に困ることがあった。 例として、メンバーシップの編集をする際のメイン画像の登録/削除ロジックは、アプリケーション層に次のように実装していました。(⚠️サンプルコードなので実際の実装とは大きく異なります) 当時は手探りの中、スピード感を持って実装していたので致し方ないのですが、本来ドメインモデル振る舞いの中で実行されるべきロジックが、アプリケーション層に漏れ出てしまったことで、テストのしやすさや保守性が損なわれていました。 /** * リクエストに画像URLが存在していないとき * ・ 既に画像が保存されている場合は削除する * ・ 画像が保存されてされていない場合、何もしない * * リクエストに画像URLが存在しているとき * ・ 既に保存されている画像があるとき * ・ 同じ場合、何もしない * ・ 異なる場合、古い画像を削除して新しい画像を保存する * ・ 画像が保存されていないとき、新しい画像を保存する */ // リクエストの画像URLを取得 $requestImageUrl = $request- > getImageUrl(); // データストアから、メンバーシップを取得 $membership = $this- > membershipRepository- > find($membershipId); // データストアから、登録済みのメイン画像URLを取得 $savedImageUrl = $this- > mainImageRepository- > find($membership- > getId()); if (is_null($requestImageUrl)) { if (!is_null($savedImageUrl)) { // 画像が保存されている場合、削除 $this- > s3ImageRepository- > delete($savedImageUrl); } // 画像が保存されていない場合、何もしない } else { if (!is_null($savedImageUrl)) { if (!$requestImageUrl- > equals($savedImageUrl)) { // 保存されている画像が異なる場合、古い画像を削除して新しい画像を保存 $this- > s3ImageRepository- > delete($savedImageUrl); $this- > s3ImageRepository- > save($requestImageUrl); $this- > mainImageRepository- > save($requestImageUrl); } // 同じ場合、何もしない } else { // 画像が保存されていない場合、新しい画像を保存 $this- > s3ImageRepository- > save($requestImageUrl); $this- > mainImageRepository- > save($requestImageUrl); } } // メンバーシップを保存 $this- > membershipRepository- > save($membership); モデリングへのフィードバック 実装したドメインモデルについて、使いづらさや保守性の観点での違和感を感じつつも、修正することができなかったことに関して、「途中で立ち止まる時間が欲しかった」という話題も出ました。 ドメインモデルを実装し、実際にユースケースから使ってみて、その結果をモデリングにフィードバックするサイクル回すことが重要なのは理解しながらも、実務の中で再ドメインモデリングをしようと言い出すことは一定のハードルがあることが振り返りの中でわかりました。 ドメインモデルは色々なユースケースから使われるので、再モデリングをする場合、認識を合わせたり、改修するコストが高くなるのではと感じてしまい、結果として修正するアクションができなかったのではないかと思われます。 3rdではどうなったか 2ndリリース後の全体振り返りでうまくいかなかった部分について振り返ることができ、3rdでは改善することができました! 3rdではデータモデリングとドメインモデリングを分けて考え、最初からドメイン領域に焦点を当てた設計をする動きができました。ユースケースをもとに、エンティティや値オブジェクトを探し出す作業、そしてドメインルールや振る舞い、集約についても深く考えることができたと思います。 これまでは、ドメインモデリング図はホワイトボードツールで作成をしていましたが、作成したモデリング図は明確な管理方法が決まっていたわけではなく、コードに落とし込んだ後は使い捨てるようなケースもありました。そのため、議論に参加していないと、どのような理由でどう変更されたかがとても追いづらい状況でした。 再モデリングを気軽にやりやすくするために、3rdではmermaidで書いてGit管理するようにしました。Git管理することで、変更履歴を追いやすくなり、大きな変更でなければ共有はPRで済むようになり、ドメインモデルの修正作業が以前よりも気軽に行えるようになりました。 メンバーシップ特典登録では、特典画像を登録することができます。画像登録は1stで実装したメンバーシップのメイン画像のドメインモデルを流用できれば良かったのですが、先ほどの例のとおり、ロジックがアプリケーション層に漏れ出しており、流用するのが難しい状態でした。そこで、再モデリングをし直して、リファクタをしました。 メンバーシップのメイン画像はメンバーシップと同じライフサイクルをもつため、メンバーシップ集約ルートとし、メイン画像はその集約の中に含めることにしました。 これにより、メンバーシップの編集ロジック内に、画像の登録/削除のロジックを閉じ込めることができ、アプリケーション層がとてもシンプルになりました🎉 // リクエストの画像ファイル名を取得 $requestImageFileName = $request- > getImageFileName(); // データストアから、メンバーシップ集約を取得 $membership = $this- > membershipRepository- > find($membershipId); // メンバーシップ集約が持つ、画像ファイル情報を取得 $savedImageFileName = $membership- > getMainImageFileName(); $membership- > edit( $request- > getName(), $request- > getDescription(), $requestImageFileName, ); if (!$membership- > isSameMainImageFileName($savedImageFileName)) { $this- > s3ImageRepository- > save($shopId, $savedImageFileName, $requestImageFileName); } // メンバーシップ集約を保存 $this- > membershipRepository- > save($membership); よいモデリングができると、複雑さなロジックをドメインモデルに閉じ込めることができるので、アプリケーション層では振る舞いを呼び出せばよく、とてもシンプルになる上に、責任が明確なので、とてもテストがしやすくなりました。試行錯誤してよいモデルができてからは実装速度が上がっていったように感じます! 一方で正解のないドメインモデリングにこだわりすぎてしまい、時間をかけ過ぎてしまっているかも?という感覚もありました。どこまで作り込むべきなのか、この辺りはとても塩梅が難しいところだなと感じました。 最後に 私自身、これまでの経験で、設計についてここまで深く考えたことはなかったのですが、このプロジェクトを通じて、チーム全体でDDDやOOPに対する理解が深まり、保守性の高いシステムの開発ができたのではないかと思います。 難しい挑戦ではありましたが、モチベーションの高いメンバーと一緒に理解を深めながら開発ができたことがとても良い経験となりました! また、スクラム開発を採用し、振り返りを重視したことで、1.5年にわたる長期プロジェクトの中でも、1st、2nd、3rdと各段階で以前の欠点を改善しながら前に進むことができたと思っています。 最後になりますが、BASEでは一緒に働くエンジニアを積極採用中です! 今回紹介したようなモジュラモノリスやドメイン駆動設計に少しでも興味を持っていただける方がいたら、ぜひご連絡ください! open.talentio.com
こんにちは。BASE BANKの02 ( @cocoeyes02 )です。 2024/04/13(土)に開催されたPHPカンファレンス小田原 2024に登壇してきました。今回の記事では登壇についてのコメントと、会場の様子についてお届けします! 今回のセッション LT最後のトリを務めました!もともと地元が小田原に近く、今回のカンファレンスでは 「小田原っこ」枠 での登壇となりました! speakerdeck.com PHP8.2 / 8.3の新機能である Random\Randomizer クラスについて、時間がゆるす限りコードや実行結果とあわせて、ひたすらユースケースを話しました! 今回のトークで、かなり Random\Randomizer クラスへの理解が深まりました。プロダクトコードやOSSライブラリで使用しているPHPのバージョンによっては、Random\Randomizer クラスを使った処理へと書き換えできないか、機会を伺ってみてもよいなと思いました! また、今回のLTでは、理解しやすさや納得しやすさを優先したため、日常的なユースケースをメインに扱いました。 扱っている業務次第では、プロダクトコード上で乱数処理を使用する機会はたくさんあると思います。ぜひスライドに載っている今回使用したリポジトリや、 PHP Playground のURLから、手を動かして理解を深めてみてください! 会場の様子 会場は小田原ならではの体験が多かったです! 各ブースコーナーに訪れると、小田原や小田原近辺のお菓子がもらえました。 また、PHPカンファレンス小田原のスポンサーブース以外にも、小田原市移住相談ブースがありました。 小田原市役所の方々が、小田原市に住む上で参考となる情報を様々な観点で教えてくれるブースでした!オープニングを聞いてから、一番最初に小田原市移住相談ブースに駆け込みました。 小田原市のブースには醤油せんべいが置いてあります🍘 #phpcon_odawara pic.twitter.com/2yEF2AApBU — PHPカンファレンス小田原 (@phpcon_odawara) 2024年4月13日 めっちゃ参考になった(ほくほく) #phpcon_odawara https://t.co/RABzGlur4b — 02 (@cocoeyes02) 2024年4月13日 また、スペシャルゲストとして、 小田原市観光PRキャラクターのうめまる が登場しました! LTで時間切れに鳴ったらドラを叩いたりしてくれました!LT中の02とうめまるとのツーショットです(このあと無事(?)時間切れでドラがなりました)。 02さんの方がでかそう #phpcon_odawara pic.twitter.com/Kv9A4mdPjb — しめじ/Kaga (@TAKA_0411) 2024年4月13日 最後に スタッフの方々には業務でお忙しいにも関わらず、多くの時間をカンファレンス準備へ注いでいただいたかと思います。この場を借りて御礼申し上げます。 小田原愛の溢れたユニークでとても素敵なカンファレンスでした!また来年も開催されたらぜひ参加したいです!ありがとうございました! 最後に、BASE では絶賛採用中です!下記リンクからぜひご覧ください! binc.jp