Monoxer Tech Blog

アプリストアのオーナーアカウントを共用アカウントに入れ替えた話

こんにちは!やまもと@テスト番長です。暑くて長い夏がようやく終わったと思ったら今年もあと残り3ヶ月、冷凍おせちをどこで買うか悩み始めた今日この頃です。

僕はモノグサでQM(Quality Management)チームのマネージャーを務めさせていただいております。今年、アプリストアのオーナーアカウントを共用アカウントに入れ替える作業をQAチームで行いましたのでその時の体験談をご紹介したいと思います。

経緯

MonoxerはAndroidとiOSの各プラットフォームに対応しており、それぞれのストアの管理者権限はCTOがオーナーとなっておりました。

組織が拡大するにつれ、ストアで発生する諸々の対応をCTOが逐一行うのは非効率的になっていました。

今後の事業展開を踏まえ、設定を変える手間がかさみそうなことから、今回アプリストアのオーナーアカウントの入れ替えを行うことになりました。

モノグサではサービスのリリース作業をQAチームで担当しており、ストア周りの設定に触れることも多いため、検討の結果QAマネージャーの私が移行作業の担当を引き受けることになりました。

iOSはオーナーを簡単に引き継ぐことのできる仕組みがあったのですが、Androidはオーナーを永続的なものと定義していて引き継がれることを前提としておらず、結果、アプリの譲渡と同じプロセスを踏む必要がありました。

(現在は会社組織の場合は個人アカウントで登録しないように注意書きがあるようです)

移行作業で色々と苦労がありましたので、同じような作業をする方がいらっしゃったら参考になるよう経験したことを書き残しておきたいと思います。

事前に調べたこと、決めたこと

アカウント移行で万が一サービス停止したら大問題ですので、移行の影響を綿密に調査して段取りを決めていかねばなりません。

情報収集の際に参考にしたサイトを以下に挙げます。(先人の方々に感謝です。)

・Zaim アプリの所有者権限を変更した際の苦労話 https://note.com/y_sumida/n/n91b0265c439a

・iOS/Androidアプリを譲渡またはアカウントを移行する方法 https://backapp.co.jp/blog/12099

調査が進むにつれ、色々と面倒な作業があることがわかりました。

iOSはAccount Holderを移譲すればOKで、割とシンプルでした。

問題はAndroidです。FAQを調べたところ、オーナー権限の譲渡は出来ないようでした。現行のデベロッパーアカウントは個人のアカウントで登録されており、他の用途でも使っているので共用に変えるわけにも行きません。

念の為サポートにも問い合わせしましたが、やはり譲渡手続きになるとのことで腹を括って準備を開始しました。

基本的に譲渡手続きであるため、移行できない情報(=譲渡の場合渡す必要のない情報)が幾つかあり、そのケアが必要かどうか整理する必要がありました。

また、デベロッパーIDが変わるため、登録してある箇所は全部入れ替える必要があります。

当該のヘルプを確認し、洗い出しを進めました(下記は2024年4月頃の情報です。最新情報はヘルプをご参照ください。)

  • 移行できる情報

    • アプリのユーザー、ダウンロードの統計情報、評価およびレビュー、コンテンツのレーティング、ストアの掲載情報
  • 移行できない情報や設定

    • 一括エクスポート レポート、売上レポート、収益レポート
      • この時点でストア課金が無く収益は見ていませんでした。
      • ここを考慮しないで済んだのはラッキーでした。
    • テスター グループなど
      • デベロッパー / テスターは最初から登録し直す必要があります。
  • 連携し直しになる統合サービス

    • Google アナリティクス
    • Google Developers Console プロジェクト
    • Firebase連携
    • FCM (Firebase Cloud Messaging)
      • Push通知で使っているため確認が必要でしたが、GCPのサポートに問い合わせた結果、対応不要でした。
  • Ad SDK の統合(AdMob を含む)
    • 未使用
  • managed Google Play ****限定公開アプリ
    • 該当せず
  • Google Play Developer API
    • 使用箇所があれば新しいデベロッパー IDに更新する必要あり

統合サービスへの影響を洗ううち、入れ替え時のラグが若干あるかもしれないことが気になり出し、影響度のヒアリングを行いました。アナリティクスなどが見れなくなって困ることがないか社内に確認を取りましたが、幸い数日程度のラグであれば問題ない状況でした。

切り替えに時間がかかるため、移行時期はビジネス上影響の出にくい時期を選ぶことにしました。

4月は新学期でMonoxerの導入作業が活発に行われているため、無用なトラブルを避けるために5月のGW以降に実施することになりました。

いざ移行開始

まずは移行先のアカウントを準備するところから始めます。

アカウントの管理方法、2段階認証の方法やネーミングも決めなくてはいけません。地味に手間なところです。

Android側の移行ではPlay Storeのデベロッパー名が一時的に変わるため、開始のタイミングでカスタマーサクセスチームを通じて全社に周知を行いました。

iOSアプリの移行手順

手順は以下の通りでした。

https://developer.apple.com/jp/support/account-holder-transfer/

  1. 受諾側アカウント(共用アカウント)の下準備
    1. メールアドレスを振り出してApple IDを取得
    2. 組織にデベロッパーとして招待する
    3. 本人確認を終わらせる
      1. ファクタ認証必須のため、電話番号も準備
  2. Account Holderの譲渡
    1. 現在のAccount Holder(CTO)が、受諾側アカウントを指定して譲渡手続きを行う
  3. Account Holderを受諾
    1. 受諾側アカウントに通知が来るので、契約を確認して同意する
      1. Account Holderになった旨の通知が届く
  4. サブスクリプションの更新設定
    1. 以前のAccount Holderが、サブスクリプションの自動更新をオフにする
    2. 新しいAccount Holderが、サブスクリプションに登録
      1. 有効期限の30日前から可能

概ね問題なく完了しました。

Androidアプリの移行手順

移行作業の開始を社内に宣言し、以下の手順を実施していきました。

  • 現在のデベロッパー名を「monoxer.com」→「monoxer.com(旧)」に変更
    • 移行先のアカウントを「monoxer.com」にするため、一時的にリネームしておく必要がありました。
    • 審査しているのか、反映まで2日ほどかかりました。
  • 移行先のアカウントでデベロッパー登録を行う(有料
    • デベロッパー登録には審査があり、完了までしばしリードタイムがあります。2023年ころに比べると、登録に必要な情報が増えているようでした。
    • D-U-N-S ナンバー
      • 入力する必要があり、情報を取得しました。
    • デベロッパーの連絡先登録
      • 確認の音声メッセージが会社番号に届く仕組みなのですが、早く終わらせたかったため 一時的に仮の番号で登録し、後日正式な番号に入れ替えました。
    • その他会社情報
      • 住所、ウェブサイト、メールアドレスなどが必要です。

ここまでで一旦移行先のアカウントが作成されました。アプリの配信や譲渡を受けられるような状態にするには、さらに追加で諸々の設定を進めていきます。

  • 本人確認
    • 会社設立証書、登記簿、税務署からの何らかの書類、納税証明書が必要
      • アップロードの容量制限が厳しく、今回使用した資料ではPDFをダウンサイズしておく必要がありました。
    • 確認書類に記載のある経営者が、身分証明書を送って登録する必要がありました。
  • Google Payments 販売アカウントを作成
    • Google Search Consoleで会社のウェブサイトを認証登録します
    • 案内に沿ってお支払いプロファイルを作成します
    • 銀行口座登録
      • 銀行口座を登録すると、確認用のデポジットが振り込まれます。
      • 経理に協力をお願いして確認を終えました。
  • 移行先のアカウントでテストアカウント、グループ等を作成し直す
    • 現行のアカウントと同じ内容で登録し直しました。
    • Googleからの連絡をMLにしてメンバーを招待すると良いようです。
  • GCPのサービスアカウントを招待する
    • 手元の環境ではユーザーとして登録すればOKでした。
  • レポートのダウンロード(念の為)
    • レポートは利用していないと聞いており対応不要なものでしたが、2024年分について落とせるものは落としておきました。

一連の設定が終わったらいよいよ移行リクエストです。

  • アプリの移行リクエストを送る
    • 元のアカウントと移行先アカウントの登録取引 ID を調べて元のアカウントからサポートに依頼します。
    • 新しいアカウントの準備が全部完了していないと、アプリの移行は行えません。

移行リクエストを送ってから2日程度でリクエストが処理されました。 移行後に一連の動作確認を行い、移行完了となりました。

  • 移行完了の確認
    • Play storeでアプリをダウンロード出来ること
    • push通知を送信出来ること
    • Firebaseで各種情報を閲覧可能なこと
    • アプリをアップデート出来ること(旧アカウントで作成したビルドを使いましたが、新アカウントでもビルドすべきでした。このあたりは後述します)

移行で躓いたポイント

移行中、幾つか躓いたポイントがあったので愚痴注意喚起しておきます。

想定外① Apple Developer Appの本人確認書類アップロード

iOS側の移行は概ね順調に進みましたが、一点困ったのが本人確認が運転免許証では通らず、パスポートを引っ張り出してやっと通ったことです。写りの問題なのかもしれませんが、もっと簡単に認証できると嬉しいところですね。

想定外② Google Play Consoleの移行先アカウントの本人確認

どうしても経営陣に作業依頼をせねばならず、使ったPDFが一発で通らなかったこともあり手間取りました。会社の書類と本人の確認と段階が分かれてるとありがたいなと思いました。

想定外③ Google Play Consoleのお支払いプロファイル

銀行のデポジット手続きは認識していたのですが、会社のウェブサイトをGoogle Search Consoleへ登録する必要があり、確認用のファイルをサイトにアップロードするのに少々時間を食いました。

そして作業漏れ発生

移行作業にはなんだかんだで1ヶ月程度かかり、一通り片付けてほっとしたところで作業漏れが判明しました。

Androidアプリの新しいバージョンのビルドをするところでCIが失敗、原因はGCPのサービスアカウントに対してmonoxerアプリのアクセス権限を付与出来ていなかったせいでした。

アプリ譲渡前の待ち時間に開発者アカウントを登録し直したため、その時点ではmonoxerアプリへの紐付けがまだ出来ておらず、作業漏れとなってしまいました。

GCPのサービスアカウントおよび開発メンバーのデベロッパーアカウントの紐付けを行い、すぐに復旧させることが出来ました。

最後に

こういう作業はふつう、インフラ系だったシニアなDevの方などが担当する作業で、QAがこの手の作業をすることは珍しいのではないでしょうか。慣れないところも多く、沢山の方の手助けをいただいてなんとか完了することが出来ました。 この記事が何かのご参考になれば幸いです。

モノグサQA募集中です

モノグサ株式会社では一緒に働く仲間を募集しています。 少しでも興味を持ってくださった方は、ぜひお話しましょう!

Monoxer Intern Report #19_数式正解判定アルゴリズムの実装

はじめに

モノグサ株式会社のソフトウェアエンジニアのインターンとして参加させていただいている堀毛晴輝です。 Intern Reportを書くのは2回目で、1回目の記事は こちらです。2022年夏のインターン終了後も、通年でインターンを継続させていただいています。

取り組んだこと

Monoxerでは学習者が数式を解答する形式の問題があります。

この形式では、学習者は数式を入力し解答します。しかし、この形式の問題では登録されている正解の数式と完全に一致しないと不正解となってしまっていました。 たとえば正解が  (x+2)(x+3) の問題では、  (x+3)(x+2) は不正解と判定されてしまっていました。

問題作成時に別解を登録することができるため、簡単な数式であれば考えられる別解を登録しておくことで解決できますが、複雑な数式になると考えうるすべての別解を登録するのはとても困難です。 「同値な数式を入力したのに、登録されている正解と一致しなかったために不正解となってしまう」というのは、 学習者にとってモチベーション低下につながってしまいます。また、Monoxerがユーザーの記憶を正しく判定できない、ということにもつながってしまうため、これを解消したいです。

以下、正解として登録した数式を「正解」、学習者が入力した数式を「解答」と呼びます。今回は正解に等号や不等号が含まれているものは対象としません。

数値的な一致判定

正解/解答の数式に対して、 x y などの変数についてそれぞれ同じ値を代入することを考えます。 こうすると、正解と解答の数式は( 0で割ったり平方根の中に負の数が入ったりなどしていないなら)それぞれ一つの実数値になります。 解答が正解と判定されるべき数式ならば、変数にどのような値を代入しても、この値は一致するはずです。

正解/解答の変数にランダムな変数を代入することを複数回行い、複数回全てでこの値が一致しているかで正誤判定をします。 先述した通り、 0 で割ったり平方根の中に負の数が入ったりしている時には評価ができないのですが、そのような時は正解と回答は共に評価できなくなるはずです。実際の実装ではランダム変数の代入を複数回行い、値が違ったりどちらか一方が評価できない時は不正解と判定し、最終的に評価した値が一致した回数が規定回数以上であれば正解と判定しています。 この判定は完全ではありませんが、実用上は十分な精度を持っていると考えています。

Monoxerでは数式をMathMLの形で扱っています(Monoxerで使われている MathML については こちら の記事が詳しいです)。

MathMLは木の構造をしています。この構造をうまく使い、式の値を求めます。例えば  3 ^ 2 + 1 をMathMLで表すと、

<math>
    <msup>
        <mn>3</mn>
        <mn>2</mn>
    </msup>
    <mo>+</mo>
    <mn>1</mn>
</math>

となります。この式を評価した値を求めることを考えます。 これは、下から順に各頂点の値を求めていくことを繰り返せば良いです。

 3 ^ 2 = 9 なので、

 9 + 1 = 10 なので、

一番上のmath要素の値が求めたい数式の値です! このように、「子要素から順に値を求めていく」ことを繰り返すことで、求めたい式の値を求めることができます。

競技プログラミング風に言うと、  \mathrm{dp[node]} := (\mathrm{node} を根とする部分木を評価した値) として、木DPをしているイメージです。

シンボル的な一致判定

「次の数式を因数分解せよ。  x ^ 2+5x+6 正解:  (x+2)(x+3)

この問題は、「因数分解せよ」という問題なので、解答として  (x+2)(x+3) (x+3)(x+2) は正解に、 x ^ 2+5x+6 は因数分解されていないので不正解となるべきです。 しかし、数値的な一致判定を用いると  x ^ 2+5x+6 は正解と判定されてしまいます。

そこで、「因数分解せよ」や「展開せよ」といった問題では、数値的な一致判定に加え、以下の条件:

  • 正解と解答に含まれる括弧の数が一致
  • 正解と解答に含まれる 各変数(mi要素)/各数字(mn要素)の個数が一致

を満たす時に正解と判定するようにしました。 これにより、

  •  (x+2)(x+3) には括弧が2組あるが、  x ^ 2+5x+6 には括弧が存在しないので不正解
  •  (x+2)(x+3) には括弧が2組あり、  x が2回、 2,3 が1回ずつある。  (x+3)(x+2) にも括弧が2組、$x$が2回、2,3が1回ずつあり、数値的な一致判定でも正解と判定されるため、正解

となり、「因数分解せよ」「展開せよ」といった問題でも想定通りに別解の判定を行うことができるようになりました。

採点方法の設定方法

具体的に、ユーザーは問題作成時に、採点方法を次の3つ:

  • 従来通り、正解と解答が完全に一致するかどうかで判定
  • 数値的な一致判定で判定
  • 数値的な一致判定とシンボル的な一致判定で判定

から選択できるようにしました。別解が考えられるような問題では数値的な一致判定を、「因数分解せよ」や「展開せよ」といった問題では数値的な一致判定とシンボル的な一致判定を選択することを想定しています。

工夫した箇所

特殊なケースの構文解析

数値評価を行うとき「下から順に値を求めていけばよい」と簡単に書きましたが、実はこれだけではうまくいきません。 たとえば  \sin ^ 2 xなどは、MathMLだと

<math>
    <msup>
        <mi>sin</mi>
        <mn>2</mn>
    </msup>
    <mi>x</mi>
</math>

と表現されます。これをそのまま数値評価しようとすると、 \sin ^ 2を計算しようとしてエラーになってしまいます。  \sin ^ 2 x = (\sin x) ^ 2 なので、数値評価を行う時に気をつけなければなりません。

評価不能な数式のvalidate

MonoxerではCSV形式でBookやMiniTestを作成できます。この時に採点方法を指定するのですが、 たとえば数値計算モードが設定されているのに正解の数式が数値評価できない数式だった時、それは作問ミスである可能性が高そうです。 そういった時に警告を出してあげることで、作問者がミスに気づくことができます。

数値計算モードが指定されたエントリの登録時に数値評価ができるかどうかをフロント側で判定し、できなかった場合は登録できないようにしました。

正解が順不同な時の正誤判定

たとえば 、

 60の約数を全て列挙してください。 正解:  1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60

という問題について、順序を入れ替えたものは全て正解としたいです。しかし、この場合順序の入れ替えは  12! = 479,001,600 個あり、これらを全て別解として登録することは非現実的です。 今までは答えが一意になるように問題文を工夫し、この問題では「昇順で解答してください」と問題文に入れることで対応していたのですが、順不同な時にもうまく動作するようにしました。

このような問題について、正解と解答の数式をそれぞれカンマで区切り、

  • 正解の個数と解答の個数が一致している
  • 正解と解答で、答えが一致するようなマッチングが存在する

時に正解となるようにしました。これにより、問題で「昇順で解答してください」のように解答方法を指定する必要がなくなりました。

感想

前回のインターンタスクではフロントエンドのみでしたが、今回のタスクでは

  • フロントエンド: 登録しようとしている数式がアプリで数値評価できるかどうかのチェック
  • バックエンド: 数式エントリの採点方法の情報を新たにデータベースに追加
  • アプリ(iOS/Android): 正誤判定ロジックの実装

と幅広く触ることができ、とても勉強になりました。

また、今回の実装をするにあたり、

  • 四則演算だけでなくルート、分数、冪乗などの記法を使ったMathMLを数値評価した時に、意図した計算順序で計算が行われているか
  • 評価不能と判定されるべき数式が、意図した理由で評価不能と判定されているか

などが正しく動作しているかを確認するためたくさんテストを書きました。 テストを書くことでバグがあることに気づいたということが何度もあったので、テストを書くことの重要さを身をもって体感することができました。 

数値評価の実装は木DPをしたり構文解析をしたりが必要で複雑な実装となってしまいましたが、 「どうしたら数式を意図した通りに解釈できるか」を考えるのが面白く、楽しみながらコードを書くことができました。

おわりに

モノグサ株式会社では一緒に働く仲間を募集しています。 少しでも興味を持ってくださった方は、ぜひお話しましょう! モノグサ株式会社の採用サイトです。モノグサは「記憶定着」をサポートする学習サービス「Monoxer」を運営する会社です。

careers.monoxer.com

Monoxer と組版: より良いコンテンツの表示を目指して

モノグサで Software Engineer として働いている杉江です。

Monoxer では、記憶対象が問題としてアプリ上で出題されます。その際に表示される問題文などのコンテンツが見やすく表示されることは重要です。今回は、一般的に知られているコンテンツ作成方式の種類を紹介し、また Monoxer での組版についてもお話しします。

コンテンツ作成方式の種類

電子書籍やブログ記事などのデジタルコンテンツは、デバイス上で文字や図表の集まりとして表示されます。文字や図表を画面上に配置する工程は「組版」と呼ばれます。

コンテンツ作成方式は大きく分けて「リフロー型」と「フィックス型」の 2 種類があります。組版の工程をどの段階で行うかが異なります。

リフロー型は、表示するデバイスの画面サイズや設定に合わせて、テキストやレイアウトが流動的に表示される方式です。この場合、コンテンツは文字列として保持されていて、閲覧するたびにデバイス側でレンダリングしてコンテンツを表示します。

フィックス型は、表示するデバイスの画面サイズや設定に関わらず、文字や図表などのレイアウトが固定される方式です。この場合、コンテンツは画像や PDF などの形で保持されていて、デバイス側では組版処理は行わずに単に表示だけを行います。

Monoxer と組版

従来の Monoxer における組版と、その問題点

これまでの Monoxer はリフロー型のみに対応しており、アプリ側でコンテンツのレイアウトを決めて表示していました。

なお、コンテンツには 1 枚の画像を「挿絵」として挿入でき、挿絵は常にコンテンツの最上部に、決められたサイズに収まるよう配置されます。図を使って表す必要がある要素が複数ある場合は、それらを 1 枚の画像に収めたうえで、「図の(ア)は○○であり〜」のように、各要素にラベルをつけて指し示す必要がありました。

例として連立方程式が含まれたコンテンツを考えてみます。連立方程式の部分を正確に表記するには、数式を挿絵にする必要があり、その際は以下のようにそれぞれの式に(ア)と(イ)というラベルをつけて指し示すことでコンテンツを作成できます。

数学のコンテンツ制作を検討していく中で、この仕様ではレイアウトの自由度が低く、表現上で限界が出るのではないかという懸念が生まれました。仕様に関する主な問題点は次のとおりです。

  • コンテンツに必要な図表を、1 枚の画像に収めることが難しい場合がある

    • 数学では図表を多用する単元もあります。このような単元で、問題を解くために必要な画像群を 1 枚に全て収めようとすると無理が出てくる場合があります。
  • 文と文の間に画像を挿入できず、学習体験として望ましくない状況になることがある

    • 画像は最上部に表示され、文と文の間に画像を挿入できません。先ほどの連立方程式の例では、(ア)や(イ)に対応する式を見るときに、コンテンツの最上部にある画像に再び注目する必要があるため、視線が不自然に上下してしまいます。もしも(ア)や(イ)が書かれている場所に式がそのまま書かれていれば、上から下へ流れにそって、より自然にコンテンツを読めるようになる可能性があります。

また、これらの問題は数学だけでなく、他の教科や分野でも起こりうる問題ではないかと考えました。

課題解決に向けた方針検討

これらの課題を解決するために、リフロー型の方式を維持してアプリ側を改修する方針と、フィックス型の方式にも対応する方針の 2 つを検討しました。

Monoxer には、今後もさまざまな教科や分野のコンテンツが搭載される可能性があります。そのため、レイアウトに関するコンテンツ作成者からの要望も多岐にわたると予想されます。現状の仕組みで対応できないコンテンツに直面するたびに、必要な条件を洗い出してアプリ側を改修し、リフロー型の方式のみで対応し続けることは工数的・技術的に困難であると考えました。

一方でフィックス型の方式では、コンテンツは後述するように画像であり、レイアウトに関する要望は画像側(コンテンツ側)で対処すればよくなります。アプリ側では、コンテンツである画像を適切に表示できれば十分です。レイアウトに関する個々の要望をコンテンツ作成者側に移譲できることが決め手となり、フィックス型の方式に対応する方針を採用しました。

フィックス型の導入

今回導入した方式では、コンテンツは画像として保持されており、コンテンツが縦に長い場合は縦にスクロールすることで全体を閲覧できます。

画像がそのままコンテンツになるため、コンテンツ作成者は文面を自由に作成できます。たとえば先ほどの連立方程式の問題であれば、「次の連立方程式を」から「答えは x = 3, y = 2 である。」まで、問題文全体が 1 枚の画像になるように画像を作成します。この方式であれば、文と文の間に数式を挿入できるため、上から下へ流れにそってコンテンツを読めるようになりました。

Monoxer がフィックス型のコンテンツを導入してよかった点は、主に以下が挙げられます。

  • 複雑なレイアウトにも柔軟に対応できる

    • コンテンツ全体が画像であるため、画像さえ用意すればどのようなレイアウトでも表現可能です。
    • もちろん、文と文の間に図表を入れたり、複数の図表を含めたりすることができます。
  • コンテンツのレイアウトに関する個々の要望を、アプリ側ではなくコンテンツ側で対処できる

    • 先に述べたように、リフロー型のみで対処するとアプリ開発がボトルネックになるうえ、個々の要望に対応しきれなくなることが予想されます。フィックス型に対応したことで、レイアウトの複雑さをコンテンツ側で対処できるようになったため、このような懸念を払拭できた点がよかったと考えています。
  • 組版に関する既存の資産を活用できる

    • 出版社やライターなどのコンテンツ作成者は、組版に関するツールやスキルをすでにお持ちであると考えています。また、組版結果を画像形式で出力することは一般的に行われています。今回導入した方式では、画像がそのままコンテンツになるため、Monoxer に搭載するコンテンツを作成するときに、組版に関するツールやスキルを活用しやすくなります。

今後の課題

今回の改修によって、まだすべてのコンテンツがカバーできたわけではありません。たとえば、縦書きのコンテンツが入力されたときは、縦方向のスクロールだけでは対応できないかもしれません。教科や分野に応じてより良い学習体験を実現できるように、今後もさまざまな方針を検討していきたいです。

まとめ

コンテンツの作成方式にはリフロー型とフィックス型があり、それぞれ異なる強みを持っています。 従来の Monoxer ではリフロー型にのみ対応しており、また画像は決まった位置にしか挿入できませんでした。フィックス型にも対応できるように改修したことで、文中に図表を挿入したり、複数の画像を挿入したりなど、より柔軟にコンテンツのレイアウトを決められるようになりました。

モノグサ株式会社では一緒に働く仲間を募集しています。
少しでも興味を持ってくださった方は、ぜひお話しましょう!
モノグサ株式会社の採用サイトです。モノグサは「記憶定着」をサポートする学習サービス「Monoxer」を運営する会社です。

careers.monoxer.com

JaSST `24 Tokyo参加レポート

こんにちは!モノグサでQAEをしている甲斐と申します。 2024年3月14日(木)、3月15日(金)に開催されたJaSST'24 Tokyoに弊社のQAEとTest Automation Engineerの6名で参加してきましたので、その感想をレポートします。

JaSSTとは

JaSSTはソフトウェアテスト技術振興協会(ASTER)が開催する、テスト技術力の向上と普及を目的としたソフトウェアテストシンポジウムです。2020年からはしばらくの間オンラインのみの開催でしたが、今年(2024年)からオンラインと現地でのハイブリッド開催となりました。 私は初日を現地で、2日目をオンラインで参加しました。現地の基調講演では会場の8割前後が埋まるくらい盛況でした。現地には現地の、オンラインにはオンラインの良さがあったので、ハイブリッド方式の開催がとてもよかったです。 現地で実際に講演者の声や空気を感じるのもよかったのですが、オンラインの特性を活用して例えばDiscordでわからない用語についてURLを貼ってくださる方がいたり、社内のSlackでその瞬間刺さった言葉の感想や各個人が課題に感じていて改善したいと思っていることを意見交換できたり、プロアクティブに講演を理解できる経験ができてよかったです。

社内Slackの様子

メイン会場の後ろにはスポンサーのブースがあり、あまりITのイメージがなかったChocozapさんがスポンサーとしてブースをされていてびっくりしました。私はアンケートに記入してロゴ入りグッズをいただきました、ありがとうございます!

タオルはけっこうな頻度で使わせていただいてます!

講演の感想

初めてJaSSTに参加したのですが、B3講演「QAエンジニアの〇〇UP!キャリア解剖で見える今どきの成長軸とは?」で言及されていた、「現場で得られるものは断片で、シンポジウムや勉強で断片を体系化する」という話がとても印象に残りました。 普段仕事の中であまり意識しておらず、自分のキャリアアップとはテストをうまくできることに終始していましたが、テストの作業はソフトウェアやサービスの先にいる顧客に満足のいく品質で届けるためという俯瞰的な視点が抜けていたなと感じています。

他にも社内ではこんな感想が出ました:

  • 両日オンライン参加だったが、社内slack実況もdiscordでのチャットも盛り上がっていたので楽しく過ごせた
  • 登壇者のトレンドとして、QAの存在価値(そもそも、なぜQAが必要なのか)をきちんと(どのような指標が満たされれば達成されるのか)定義しよう、という論調が多かった
  • 今回は全体的にQAは品質をリードする存在であると言う内容の話が多かった気がする
  • 勉強ではなく知識を得て使え、というお話がありましたがまずは知識を得る勉強が必要だと思いました。
  • プロセス改善を地道に進める話や品質の考え方のセッションが多くあり参考になった。

JaSST 2024 Tokyoの参加は、私たちモノグサのQAチームにとってとても有益な経験になりました。個人としてもチームとしても自分たちの仕事に対する視野が広がり、これから取り組んでいきたい課題に対する理解も深まったと感じています。次回も是非参加させていただきたいと思います!

JaSSTに参加された方は、各講演の録画が公開されてますのであらためて視聴してみてもいいかなと思います。JaSSTからの案内メールか、公式Discordの「総合案内」にURLがあります(URLは転載禁止のため案内だけにしております。)

Monoxer Intern Report #18_Webクライアントにおける数式入力手段の拡充

自己紹介

 2024 年春にモノグサで SWE としてインターンに参加しました、宮崎と申します。2024 年 3 月現在、慶應義塾大学理工学部の 1 年生です。

参加を決めた理由

 もともと春休みに大きな予定がなく、何かしらの春季インターンに参加することは考えていました。そんなとき、AtCoderJobs でモノグサの募集を見て、実際のサービスの開発に携われることに魅力を感じたこと、また AtCoder Beginner Contest や ICPC のスポンサーなどを通して会社について認知していたことから、応募を決めました。

取り組んだこと

 主に管理者用 Web クライアントでの Book 編集機能に関するタスクを担当しました。その中でもメインタスクとして、数式の入力手段の拡充に取り組みました。

メインタスクについて

 Monoxer では数学の問題を出題することができますが、そのためには自ずと数式を入力する機能が必要になります。Monoxer では MathML と簡易数式という 2 種類の数式入力手段をサポートしており、前者はマークアップ言語であり、後者は AsciiMath をベースとした記法となっています。

図1. MathML と簡易数式を記述する例

 図 1 からわかるように、MathML は文法が明確に定まっておりプログラム上では扱いやすい一方、タイプ量が多いことや人にとって読みづらいことからユーザにとって負担が大きいです。それに対して、簡易数式は直感的な記述ができるため、簡易数式を使える場面を増やすことが目標となっています。

 現状の Web クライアントにはとある問題があり、それは図 2 のように簡易数式で入力しても、一度保存して再度編集しようとすると MathML に変換されてしまうことです。

図2. 簡易数式が MathML に変換される例

 これは仕様であり、入力された数式のデータはすべて MathML に変換された上でデータベースに保存されていることに起因します。

 この問題を解消すべく、私は解答の入力欄に MathML と簡易数式を相互に変換するボタンを配置し、ユーザの操作により切り替えられるようにしました。

図3. MathML と簡易数式を切り替えるラジオボタン

実装について

 ここで、簡易数式 → MathML の変換は既にあるものを流用することができましたが、その逆である MathML → 簡易数式の変換は新たに実装する必要がありました。

 MathML はマークアップ言語のため木構造が成り立っており、深さ優先探索 (DFS) により容易に探索することができます。そこで私は「自らを根とする部分木に対する変換結果」を返す関数をつくり、再帰的に変換する実装としました。

図4. MathML を深さ優先探索により探索する例

 また、React を用いた UI の実装も担当しました。

インターンの感想

 今回参加したインターンシップではとても多くのことを学びました。その中でもいちばん大きなものが、チーム開発の流れです。たとえば製品に 1 つの変更を加えるだけでも、最初の要件定義や実装後のコードレビューなど、多くの段階を踏む必要があることを実感しました。さらに保守性を高めるため、読みやすいコードを書くことやテストを作成することなども初めての経験であり、重要な学びとなりました。

 コーディングの面では、TypeScript や React が完全に未経験の状態だったため、一から調べながら実装していましたが、そのような状態からこのような成果を出せたのは大きな成長であったと感じます。

 そして、働く環境はとても良かったです。ボードゲームの文化が端的な例ですが、それ以外にもあらゆる場面で伸び伸びと働ける雰囲気がありました。また、我々インターン生の考えも社内で真剣に扱ってもらえたことが嬉しく、印象に残っています。

 その反面大変だったこととしては、必要な知識を自分で手にいれる必要があったことが挙げられます。たとえば React は、公式のチュートリアルなども活用して習得していきました。もっとも、そのおかげでスキルをよりしっかりと身につけられたとも考えています。

 最後のまとめとなりますが、初めてのインターンであり製品の開発経験もなかった私がこのような成果を出せたことはとても貴重な経験であり、参加して良かったと感じています。私を支えてくださった社員の方々に深く感謝します。

Monoxer Intern Report #17_CSV Data Export機能の追加と改善

自己紹介

モノグサの春インターンに2ヶ月間参加した中尾です。春から立命館大学の学部3年生です。普段は技術書や技術記事を読んだりしています。今回は遠方からの参加ということで、最初と最後に1週間強ほどずつ出社し、他はリモートでの勤務となっていました。

参加を決めた理由

春のインターン生をAtCoderJobsで募集しているというポストをXでみた友人に教えてもらって存在を知りました。AtCoder自体は最近はやっていなかったのですが、半年ほど夢中で取り組んでいたので深い思い入れがありましたし、モノグサに関してもAtCoderをやっていた時に解説記事などでお世話になったけんちょんさんが入社したというポストを見たことがあったので、存在は知っていました。当時ちょうどインターンに参加したいと思って色々探していた私にはまさに渡りに船で、すぐに応募を決めました。モノグサのブログやインタビュー記事、ネットニュースなどを調べるにつれ、参加したいという思いは強まっていきました。そこで実際に面接を受けた結果、選考を通過することができ、参加することを決めました。

取り組んだこと

組織の管理者がユーザを管理するためのWeb管理ツールにある、CSV Data Export機能の追加や改善に取り組みました。 CSV Data Export機能とは、ユーザに関する情報をCSVファイル形式で出力できる機能です。ダウンロードしたCSVファイルをExcelに取り込んで、データを分析するために使用されます。現在は、一部の組織向けに限定で公開している機能です。 私が取り組んだ課題は主に3つあります。

記憶度の出力項目に所属クラス情報を追加する

課題背景

CSV Data Export機能に、ユーザの記憶度を出力できるものがあります。記憶度とは、学習するBookに対して、どのくらい記憶しているのかを表す指標です。組織の管理者は、情報が欲しいBookを選択して、組織に所属する各ユーザの選択されたBookに対する記憶度をCSVファイルとして出力することができます。 今まで、この機能に対して、各ユーザの「スクールID」「スクール名」「クラスID」「クラス名」などの所属クラスの情報が付属していませんでした。なので、所属クラスの情報を必要とする分析を行うためには、お客様自身で、出力したCSVファイルとユーザの所属クラスの情報を組み合わせる必要がありました。 また、「学習回数の出力」などの他の機能にはこれらのクラス情報が付属していたため、記憶度と他の機能の出力項目の違いをお客様に説明する必要もありました。 よって、この課題を解決することで、お客様の手間も省け、ビジネスチームがお客様に出力項目の違いを説明する必要もなくなります。

やったこと

フロントエンドの実装

「出力するCSVデータの項目」に所属クラス情報を追加しました。

記憶度の出力予約画面

バックエンドの実装

ユーザの「組織メンバーID」から所属クラス情報が取得できるMapを作成し、それを使って出力項目に追加していきました。

結果

実装箇所としてはあまり多くないのですが、ビジネスとしてはインパクトがあると考えられます。 記憶度の出力項目に所属クラスの情報が追加されたことで、お客様自身で所属クラスの情報を付与する手間がなくなりました。また、ビジネスチームも他の機能との出力項目の違いをお客様に説明する必要がなくなりました。

管理者週間アクティブ率を出力できるようにする

課題背景

管理者週間アクティブ率とは、1週間でWeb管理ツールを使用した管理者の割合を表すものです。塾現場では管理者を管理したいというニーズが高いため、この機能を追加することになりました。この機能は、Monoxerを導入した組織が、出力されたデータを基に管理者がきちんとWeb管理ツールを利用しているかを確認し、利用を促したりするために利用されます。

やったこと

フロントエンドの実装

「管理者アクティブ率の出力」というボタンを設置し、そこから出力予約画面に飛べるようにしました。

出力予約画面への遷移ボタン

出力予約画面では、集計する期間や集計対象を選択して、出力予約が行えるようにしました。Monoxerでは組織階層の下にスクール階層というものがあり、組織AにはスクールA, スクールB, スクールCがあるというようになっています。よって、集計対象としてスクールを選択することで、スクール単位での管理者のアクティブ率というのも出力できるようにしました。

出力予約画面

ちなみになぜ「出力」ではなく「出力予約」なのかというと、データの出力に時間がかかるからです。先ほど紹介した記憶度の出力だと、長い場合2時間半ほどかかるので、出力予約という形にして、CSVファイルが準備できたらダウンロードできるようにしています。

バックエンドの実装

こちらは2ステップあります。

  1. 出力予約リクエストの処理

    出力予約画面で選択されたパラメータを含むリクエストが飛んでくるので、それを処理します。任意の出力予約を処理するハンドラがあるので、そこに今回の機能の処理を追加する形になります。集計期間が意図された値か、集計対象が存在しているかなどをチェックして、OKであれば予約をDBに格納します。なぜDBに格納するかというと、CSVファイルの生成はバッチ処理で行う仕組みになっているためです。

  2. CSVファイルの生成

    こちらでは管理者のアクティブ率を計算するため必要なデータをDBから取得して、出力するデータを算出し、CSVファイルを生成します。 まず、管理者週間アクティブ率を計算するためには「組織の管理者一覧」と「対象期間の管理者のアクセスログ」が必要になるので、それらをDBから取得します。 次に、集計期間を1週間ごとに区切って、各期間でアクセスしていた管理者の数をカウントし、アクティブ率を計算します。 このようにして、「集計開始日」「集計終了日」「アクティブ率」をCSVデータとして出力します。

    以上が組織単位での管理者アクティブ率の出力方法です。スクール単位だともう少し処理が複雑になりますが、流れとしては同じです。

結果

管理者週間アクティブ率が出力できるようになったことで、Monoxerの利用実態についてデータに基づいた分析や利用の促進が可能になり、お客様の「組織の管理者を管理したい」というニーズを満たすことができました。

追加の実装箇所

実は、記憶度の出力項目に所属クラスの情報を追加する課題が終わった後に、大手のお客様が記憶度を出力しようとするとエラーになってしまう問題が発生しました。調査の結果、私が実装した箇所に不備があったことが発覚し、それを修正することで問題は解決しました。レビューはしっかりと行っていたのですが、それでも不備が入り込んでしまったことの原因として、CSVファイルを生成する関数にテストが存在しないことがありました。これらの関数は複雑な処理をしているため、レビューだけでバグを無くすのは困難です。よって、今回の管理者週間アクティブ率を出力する関数にはテストを追加することにしました。結果として不備が2つ見つかり、そのうちの1つは実際にアクティブ率の計算結果に影響を及ぼす可能性のあるものでした。このように、早期に不備に対応することができ、他のCSVファイル生成関数にもテストを追加する足がかりを作ることができたのは、地味ではありますが今回のインターンの中でも重要な成果であると思っています。

出力項目に属性情報を追加できるようにする

課題背景

属性情報とは、「学年」「出席番号」「校舎」「選択科目」など、組織で個別に設定できるユーザに関する情報のことです。現状では、これらをCSVファイルの項目に追加することができません。よって、これらの情報を用いて分析を行いたい場合は、お客様自身でCSVファイルとアカウント情報を組み合わせる必要があります。このような作業は二度手間です。また、そもそもCSVファイルを分析ではなく表のように扱いたい小規模な組織のお客様にとっては、完全に手作業で属性情報を付与していくことによってミスをしてしまう危険性もあります。 よって、この課題を解決することで、お客様の苦しみを解決することができます。

やったこと

Design Docの執筆

機能の要件を満たす上で、どの方針にどんなメリット、デメリットがあるのかを記述し、どれをなぜ採用したのか。不安要素は何で、それは実際に問題となるのか。などを記述しました。 例えば、属性選択のコンポーネントのデザインで以下の3つが良い方針として浮かび上がりました。

  • 画面スクロール
    • メリット
      • ページに比べて操作が楽
    • デメリット
      • 既存の基盤コンポーネントがなく、新たに実装する必要がある
      • デザインを工夫しないと、スクロールできることがわかりづらい
      • Web管理ツールのターゲットによっては、必ずしもスクロールが使いやすいデザインであるとは限らない

スクロールでの選択画面

  • ページネーション
    • メリット
      • 既存の基盤コンポーネントが使用できる
      • 操作方法がわかりやすい
      • デザインとして見栄えが良い
    • デメリット
      • ページ遷移の操作がやや面倒
      • 表示件数を増やすと、縦に伸びて画面を占有してしまう
      • 属性の追加は必須項目でないのに、画面の占有率が高く、存在感が大きい

ページネーションでの選択画面

  • Modal&ページネーション
    • メリット
      • 既存の基盤コンポーネントが使用できる
      • 操作方法がわかりやすい
      • 表示件数を増やしても予約画面には影響がない
    • デメリット
      • ページ遷移の操作がやや面倒
      • デザインとして単純なページネーションに比べて、見栄えが悪い

Modal&ページネーションでの選択画面

このように、それぞれの方法のメリットデメリットを検討し、結果としてModal&ページネーションを採用しました。特に単純なページネーションではなくModalを採用した理由としては、「属性の追加は必須項目でないのに、画面の占有率が高く、存在感が大きい」がクリティカルでした。 最初私はスクロールを推していましたが、「Web管理ツールのターゲットによっては、必ずしもスクロールが良いデザインであるとは限らない」というのは考えられておらず、人によって良いデザインは異なるかもしれないというのは私にとって深い学びになりました。

他にも、出力項目に属性を追加する必要があるのですが、無制限に追加できるようにするとデザインが崩れてしまう恐れがあります。よって、以下の2つの案を検討しました。

  • 選択数に制限を持たせる
    • メリット
      • 何が追加されるのか明確にわかる
    • デメリット
      • 制限を持たせることによって、お客様が不便に思うケースが生じる可能性がある
  • 「選択された属性情報」などの表現で代替
    • メリット
      • 選択数に制限がない
    • デメリット
      • 何が追加されるのかが明確に表現できない

これに関してはビジネス側とも連携をとって、どのくらいの選択数が必要かを確認しました。すると、5つあれば十分との回答がありました。また、選択数に制限を持たせることでCSVファイルのサイズも抑えられるので、この方針に決定しました。このように、ビジネスの都合だったり、付随する問題についても考慮して設計を行うのは面白いなと思いました。

フロントエンドの実装

予約画面で追加する属性を選択できるようにしました。 選択し直す際に選択している項目が上にくるようにしたり、検索ボタンをなくして入力するだけで動的に検索結果が表示されるようにするなど、お客様が使いやすいよう工夫しました。

出力予約画面での追加する属性の選択ボタン

追加する属性の選択Modal

バックエンドの実装

管理者週間アクティブ率の出力と流れとしては同じです。

  1. 出力予約リクエストの処理

    選択された属性の数が制限を超えていないか、選択された属性が本当にその組織に存在するのかなどをチェックします。OKであれば予約をDBに格納します。

  2. CSVファイルの生成

    選択された属性の情報、組織のメンバーに対する属性の値をDBから取得します。ユーザの「組織のメンバーID」から属性の値の配列が取得できるMapを作成し、それを使って出力項目に追加していきました。

結果

属性情報を出力項目に追加できるようになり、お客様が手作業で属性情報をCSVに付与する必要がなくなりました。これにより、簡単に属性情報を必要とする分析が可能になり、お客様の苦しみが解決されました!

インターンの感想

この2ヶ月間で、本当に様々なことを学ばせていただきました。開発の観点では、Design Docを書いて、実装をして、テストを書いて、レビューをいただいて修正するという開発の一連のプロセスを経験することができました。その経験を通して、レビューやテストの大切さ、設計をする上では様々なことを考慮しなければならないこと、どのようなコードを書くべきかなどを学ぶことができました。経験の観点では、実際に2ヶ月間チームの一員として働くことで、会社の雰囲気や仕事上のコミュニケーション、プロダクトに対してどのように人が関わっているかなど、仕事に対する具体的なイメージを持つことができました。また、開発をしていると設計や実装において意見がぶつかることがありますが、その時にきちんと自分の意見を伝え、相手の意図を汲み取って尊重し、お互いが気持ちよく合意を取れるように議論をするというのがとても大切だと思いましたし、そのような環境が構築できているモノグサは良い会社だなと思います。 このインターンを通して、エンジニアとしてとても成長できたと感じています。この経験を活かして、今後も成長できるように精進していきます。このような機会を提供してくださったモノグサの皆様に深く感謝を申し上げます。2ヶ月間ありがとうございました!

Monoxer Intern Report #16_文章分割確認ツールの開発

自己紹介

こんにちは。モノグサのソフトウェアエンジニアのインターンに参加した堤歩斗です。普段は東京都立大学でコンピュータサイエンスの学習をしています。モノグサでは1ヶ月半ほどインターンをしていました。 この記事ではインターンを振り返りモノグサで取り組んだことやインターン中のあれこれについて紹介したいと思います。

参加を決めた理由

モノグサを知ったのはICPC2022アジア横浜地区大会のスポンサーブースでお話を聞いたときでした。その他にもAtCoder上でモノグサプログラミングコンテストを開催していたり、CodeQUEENのスポンサーを務めるなど、モノグサは競技プログラミングに理解のある会社なのだなという印象を持っていました。 私は比較的長い期間で本格的な開発に携われるインターンに行ってみたいと思っていました。 そんな中、モノグサの春インターンを見つけました。モノグサのインターンは期間が1ヶ月以上と希望にマッチしており、大学の春休み期間に取り組むのにちょうど良いと思いました。さらに、応募の決め手となったのはAtCoderJobsでの要求ランクがC(AtCoderのレートが緑)でちょうど応募可能だったためです。競技プログラミングで得た機会を生かしてみようと思い応募しました。

取り組んだこと

色々なことに取り組みました。最初はiOSとAndroidのアプリ開発に触れました。そして最後にはwebフロントエンドからバックエンドの開発まで、幅広くフルスタックでの開発を体験できました。そんな中から今回はインターン中にメインで取り組んだテーマについて紹介します。

Monoxerでは、「文章記憶機能」を提供しています。文章記憶機能というのは以下のような機能で、

  • 試験勉強に必要な文章や歴史的に有名な詩、業務に必要なマニュアルやトークスクリプトなど、様々なシーンで記憶が必要な文章が存在しています。
  • モノグサでは、この「ミラーの法則」を参考にして、文章をチャンク(情報のかたまり)に分割したうえで、チャンクごとの記憶を促すための出題する機能を開発いたしました。

引用元:文章をチャンクに分割して記憶する「文章記憶機能」をリリース | Monoxer・解いて憶える記憶アプリ

今回私は文章記憶機能における問題作成時のチェックプロセスを自動化するツールの開発を行いました。

文章記憶機能では、覚えたい元の文章を分割することで問題を作成します。 今回自動化したいチェックプロセスというのは、元の文章を分割して出来た短い文章のブロック(図1のL1に相当)同士で類似したものがないかをチェックするというものです。

図1 文章記憶コンテンツの構造

なぜ、このようなチェックをする必要があったのでしょうか?それは類似したものがあった場合に問題の選択肢にそれらが同時に出現することがあるからです。(図2 似たような選択肢が出現するスクリーンショット)

図2 似たような選択肢が出現するスクリーンショット

このスクリーンショットでは「当社で確認し、」と「当社で確認した」という選択肢が同時に出現しています。この問題の正解は「当社で確認した」なのですが、「当社で確認し、」を選択しても良いように思えます。 このように似たような選択肢が出現すると、文章の内容を十分に記憶出来ているのに誤答と判定されてしまうという問題が発生します。

今回のケースではスクリーンショット中の「当社で確認し、」と「当社で確認した」のような表記揺れや文末の表現の違いがある文章を検出するだけでなく、「迅速に」と「素早く」といったような言い換え表現も検出したいという背景がありました。(図3 検出したい文章の例)

図3 検出したい文章の例

そこで、このチェックを自動で行うために、SentenceTransformerという自然言語処理ライブラリを用いました。

SentenceTransformerは、文などのテキストデータをベクトル表現に変換するためのライブラリです。SentenceTransformerのモデルは、文を入力として受け取り、固定長のベクトルにエンコードします。このベクトル表現を用いることで、文間の類似度を計算することが可能になります。すなわち、SentenceTransformerを用いると文レベルでの意味論的な情報を捉えることが出来ます。 *1

実際には単純にSentenceTransformerで文章の最小単位(図1のL1に相当)同士の類似度を計算するだけではなく、その文章を誤って選んだ場合にどうなるか?という部分を加味して判定するようにしました。具体的には、「正解の選択肢を選んだ場合に完成する元の文章」と「類似した誤答選択肢を選んだ場合に完成する類似した文章」の二つの類似度を計算することで、誤答選択肢として適切かどうかをより正確に判定できるようになりました。

また、このツールの使用者はエンジニアではなく社内のコンテンツを作成する方々になります。そのため、普段のコンテンツ作成で使用しているGoogle スプレッドシートからGUIでの操作が出来るようにしました。そこで、以下の2つを開発しました。

  • 類似度の計算処理等を実行するバックエンドAPI
  • APIを叩き、結果を視覚的に表示するGoogle スプレッドシートのアドオン

また、SentenceTransformerを使用するには、Pythonで提供されているライブラリを利用する必要があります。そのため、Pythonの実行環境が必要です。そこで今回はGCPのCloud Runへ新たにデプロイすることになりました。

Cloud Runはコンテナを直接実行できるマネージドな実行環境で、リクエストベースでの自動スケーリングが行われます。すなわち、リクエストがあった場合にのみ動作し、しばらくリクエストが無い場合にはスケールダウンされるということです。今回作成したいツールはコンスタントにリクエストがあるものではなく、コンテンツ作成の作業時という限られたタイミングでのみ使用できれば良いので、Cloud Runは最適な選択肢でした。さらに、Cloud Runではコンテナを直接実行できるので、実行環境の新規構築としては比較的簡単です。 *2

今回はインフラチームの方と連携しながら、必要な知識を学びつつ、Cloud Runのデプロイにかかるプロセスを習得しました。この過程で、Cloud Runの仕組み、コンテナ技術、GCPの基本操作など、クラウドインフラに関する幅広い知識が得られました。

また、SentenceTransformerを使用するに当たり、パフォーマンスと精度についても課題がありました。デプロイにおいては、これら二つの要素を最適化することが重要な挑戦となりました。応答時間と消費するリソースの改善を精度を犠牲にすることなく、実現する必要があります。そのために、モデルの軽量化やキャッシュの利用などを施しました。このプロセスを通じて、パフォーマンスと精度の間のバランスを取ることの難しさを学びました。

インターンの感想

今回のインターンでは本当に幅広い領域を扱わせていただきました。「どんな文章を検出するべきなのか」というプロダクト理解から、「デプロイやシステム構成」といったインフラ領域、さらにバックエンドとフロントエンドの一通りの実装などに取り組みました。その中で自分で考えた内容に対して様々な方面からレビューをいただき、一つの機能を完成させていくという一連のプロセスが体験できました。主体性を持って幅広い領域の開発を経験できたことは非常に興味深かったです。

さらに、本格的なコードレビューを受けてプロダクトに自身のPullRequestをマージするという経験は学生にはなかなか得られるものではなく、様々な学びがありました。また、PullRequestだけでなく、Design Docという開発にまつわる文書のレビューも社内から広く受けられるモノグサの文化に感心しました。

そして、モノグサでは非常に働きやすい環境が整っているなとも感じました。インターンの最初に支給されるPCのキーボード配列の希望調査があったときから、インターンを終える今日まで、社員のことを第一に考えていることを随所に感じました。

このインターン体験を通じて、幅広いスキルを身につけることができました。また、実務でのコードレビューやプロダクト開発の一端を担うなど、貴重な経験をさせていただき、成長できたと自負しています。技術的なスキルだけでなく、チームで働く重要性や、プロダクト開発の過程における細かな配慮を学ぶ機会もありました。最後に、この機会を提供してくださったモノグサの皆様に心から感謝を申し上げます。ありがとうございました。