にゅーとぴあ

気が向いたら書きます。

MIXIのインターンに参加しました

5月中旬から6月中旬までの1ヶ月間、MIXIの就業型インターンシップ"Dive into MIXI”に参加しました!

きっかけ

2年前に参加した「Git Challenge」というイベントをきっかけに、MIXIという会社に興味を持ちました。それ以降も、新卒研修のスライドをまとめた記事を見たり、mixi2を始めたりと、会社の名前を目にする機会が多くありました。

そうした中で、実際の業務に携わることができる長期の就業型インターンシップが、私の得意とするフロントエンドエンジニアという職種で募集されていることを知り、応募を決めました。

ミニモとは

インターンではminimo事業部のweb1チームという部署に配属されました。

minimoはサロンスタッフを直接予約できるサービスで、スマホアプリやWebページから利用することができます。他のサロン系予約サービスと異なり、サロンではなくサロンスタッフを予約できる点や、練習用のモデルが「0円メニュー」として数多く掲載されている点などが特徴です。

なかでもWebは検索エンジンから検索してきた新しいユーザーとの接触機会を増やすという意味で、重要な意味を持っています。web1チームではSEOの改善を主なミッションとしながら、総合的にユーザーの体験を良くする施策を考えることで、検索結果における順位の向上やminimoで予約をしてもらうユーザーを増やすことを目的としています。

minimoは6月1日、ブランドロゴの変更を伴うリブランディングを行いました。今回ちょうど、ミニモ自体が大きな盛り上がりを見せているタイミングで参加することができたため、とても良かったです。

prtimes.jp

期間中やったこと

今回、minimoではおもにWebフロントエンドのタスクを担当しました。1ヶ月の期間中で34件のPull Requestをマージし、すべてリリースまで持っていくことができました!

「ミニモとは」ページの改善

minimodel.jp

このページはミニモを知らないユーザーが多く訪れます。しかし、改善前のページの内容はコンテンツが少なく、またアプリへの動線しかないものでした。

インターン参加後最初に着手したこのタスクでは、改善済みのデザインをデザイナーさんからFigmaでいただき、それを忠実に再現していく作業を行いました。

普段はUIも含めて、自分で実装をしながらデザインを考えているため、厳密な再現をする経験が少なかったのですが、これは簡単なことのように見えて思いの外難しかったです。何回かセルフチェックをしていてもline-heightの設定が漏れていたり、paddingの大きさがズレていたりして、レビューリクエストと修正を往復していました。修正の過程で「スクリーンショットをFigmaデザインに重ねると分かりやすい」というアドバイスをいただき、それから実践してみたのですが、それからはラリーの回数が減ったように感じます。

お客様の傾向を表示

掲載詳細と呼ばれるページに、来店するお客様はどの年代や性別が多いのかを分かりやすく可視化するグラフを表示する実装を行いました。

Figmaで「来店したお客様の傾向」のUIデザインを表示したスクリーンショット。左は「男性」選択時で、男性が全体のお客様に占める割合と年齢層別のグラフが表示されている。右はデータが少ない状態のデザインで、グラフの代わりに「データが足りていません」というメッセージが表示されている
「お客様の傾向」のFigmaデザイン

このグラフはモバイルアプリではすでに実装されていたものの、Webにはない機能だったため、バックエンドでWebのためのエンドポイントを実装するところから担当しました。

ミニモのバックエンドではアプリ用のエンドポイントにJSON-RPCを、Web用のエンドポイントにREST APIを使用しており、受け取ったリクエストをもとに、それぞれのハンドラーが共通のドメインサービスを呼び出す構成になっています。そのため、ロジック部分はアプリの実装を流用できますが、handler層については新しく実装する必要がありました。

さらに、アプリとWebでは掲載詳細ページを表示される条件が異なります。アプリではデータを返さないケースでも、Webではデータを返す必要がある場合があったため、この差異についても確認しながら実装しました。

つぎにフロントエンドの実装です。今回はラジオボタンで属性を切り替えた際にインジケーターをアニメーションさせて欲しい、とのことだったので、シンプルにspanタグで実装し、CSSでtransitionを設定するだけにしています。

ミニモのサロン詳細ページに表示される「来店したお客様の傾向」セクション。総合・女性・男性を切り替えるラジオボタンがあり、年齢層別の横棒グラフで18〜22歳が32%、23〜27歳が41%、28〜34歳が22%などの割合を表示している
デスクトップで「来店したお客様の傾向」を表示

直前割や割引前価格の表示

掲載者カードと呼ばれるUIにおいて、現在の価格しか表示されていない状態から、割引に関連する情報を表示するよう改善するというタスクです。

ミニモでは「直前割」という仕組みがあり、掲載者は当日予約をする利用者に対して割引料金を設定することができます。また、これ以外にも「割引価格」を設定したり、セール状態を設定したりすることが可能で、これらの状態をUIに反映させるようにしました。

こちらもアプリではすでに実装されている機能のため、デザインは基本的にアプリに揃える形で実装しました。

価格表示部分のデザインがパターンごとに並んだ比較表。定価のみ・セール割引・割引あり・当日割引などの状態ごとに、アプリでの表示、WEBの現状、新パターンのUIを並べて比較している。現状のWEBでは割引や当日割引が表示されていないことが確認でき、新パターンで取り消し線付きの元価格表示や『本日来店で¥9,000』などの表示に対応するデザインが示されている
価格表示の種類

アクセシビリティ改善

ここまでの内容はインターン期間用のタスクとして渡していただいたものですが、これ以外にも自分で直せそうな箇所を探し、Pull Requestを出していました。

まず、私自身が関心の高い領域であるWebアクセシビリティの観点から改善できそうな点を探し、いくつか取り組みました。

ラベルがなく、アイコンだけが表示されている箇所があると、支援技術を使ってアクセスしているユーザーには何のメニューであるかが分かりません。このようなUIでは隣にラベルを表示するか、aria-label属性を使って何を意味するラベルであるかを伝えてあげる必要があります。

ミニモのヘッダーには「閲覧履歴」や「マイページ」へ遷移できるリンクが存在しますが、これはアイコンのみで構成されているリンク要素でした。そのため画像のようにリンクタグに対してaria-label=”閲覧履歴”を設定することで、アクセシビリティツリーにも反映されるよう改善しました。

Chromeの開発者ツールでミニモのWebページをiPhone SEサイズで表示し、右側でAccessibilityパネルを開いて表示している様子。Webページヘッダー内のアイコンだけで構成されたリンク要素を選択し、aria-labelで設定した「閲覧履歴」がアクセシブルネームとして認識されていることを確認している
ヘッダーのアイコンにaria-labelが設定されている

掲載者の評価では5つ星中の評価値が表示されるUIとなっていますが、ここではラベルとして「4.8」のような数字は表示されるものの、隣にあるアイコンが何を意味するものなのか説明がないため、何の値であるかが分からないという問題がありました。この実装についてはWCAG 2.2のテクニック集 G196 画像のグループにある一つの画像に、そのグループのすべての画像を説明するテキストによる代替を提供する を参考に、アイコンとラベル両方を含む親要素に対し、「5つ星中4.8点」のような代替テキストを設定しました。

Chrome開発者ツールのAccessibilityパネルで検索結果の星評価部分を検証している画面。ratingStarのdiv要素にaria-labelで「5つ星中4.8点」が設定され、アクセシブルネームとして認識されていることを確認している
掲載者カードの星アイコンを含む要素にaria-labelが設定されている

環境設定で視差効果を減らす設定をしているユーザーに対して、アニメーションを減らす改善も行いました。ただ、ローディングスピナーや継続的なアニメーションなどは、デザインの変更が生まれてしまうため、今回はanimationで実装されている箇所については対応をスキップし、一旦transitionで実装されているもののみ対応しました。

:root {
  --transition-time: 0.3s;

  @media (prefers-reduced-motion: reduce) {
    --transition-time: 0s;
  }
} 

開発環境改善

CSSのfont-weightはnormalかboldに統一するというチームルールが存在しましたが、それを担保するためのリンタが設定されておらず、既存コードにも600や700といった数値指定が混在している状況でした。そのため、Stylelintでfont-weight-notationdeclaration-property-value-disallowed-listという2つのルールを設定し、期待した値のみを取れるよう改善しました。

GitHubのプルリクエスト『font-weightの値を制限 #7269』で差分を表示している。SCSSファイルでfont-weight: 700をfont-weight: boldに置き換える変更と、.stylelintrc.jsにfont-weight-notationルールとdeclaration-property-value-disallowed-listルールで数値指定を禁止する設定を追加している
font-weightの値を制限するためのPull Requestにおける差分

devDependencies に含まれていた yaml-loader の使用状況を調査したところ、更新頻度の低い3つのYAMLファイルの読み込みにのみ使用されていることが判明しました。

これらのYAMLファイルの型を扱うために json-schema-to-typescript が、Viteでのインポート解決のために @modyfi/vite-plugin-yaml があわせて導入されていましたが、3つのYAMLファイルをTypeScriptオブジェクトとして直接管理することで、これら3パッケージをすべて依存関係から除去できることが分かったため、リファクタリングを実施しました。

YAMLが採用された背景としては、非エンジニアでも編集しやすいファイル形式であることが理由だったようです。一方で、コーディングエージェントの普及により編集のハードルが下がってきていることや、実際にはほとんど更新されないファイルになったこともあり、私のほうで今回の変更を行うことになりました。

GitHubのプルリクエスト『refactor: yaml-loaderを削除 #7295』の概要画面。yaml-loaderが3ファイルでのみ使用されていたため、YAMLをTypeScriptに置き換えて依存を削除した旨が記載されている
yaml-loaderを削除するためのPull Request

このほか、プロジェクト内の不要なコードを検出するツールであるKnipを導入しました。CIへ導入するところまでは期間中に間に合いませんでしたが、一部の不要な依存関係やファイル、エクスポートなどを削除することができました。

MIXIで感じたこと

チームの雰囲気

私が配属されたweb1チームではスクラムを取り入れていて、2週間を1スプリントとしていたため、1ヶ月のインターン期間では都合2回のスプリントを経験しました。スプリントプランニングで各自が実施するタスクを検討し、毎日の朝会やバックログメンテナンス会などで進捗を確認しつつ進めていきますが、それでも間に合わなかったり、逆に時間が大幅に余ってしまうことはあり、工数見積もりの難しさを感じました。

ミーティングや普段の会話に参加しながら感じたのは、施策へのビジネス的な観点です。大きな施策を行うときは基本的にABテストを行い、数字に明確な改善が見られれば全展開したり、他ページへも導入したりという流れで進めていました。この他、毎日の朝会で予約数やアプリダウンロード数の推移を見ながら、どの施策がどのように影響しているのかを考察しているのが印象的でした。今回のチームがSEOに特化した施策を担当していたというのも大きいですが、エンジニアの立場にある職種の人たちがここまで数値を見ながら実装に取り組むというやり方は私にとって新鮮で、面白かったです。

リモートワーク

勤務は月曜日から木曜日の週4日で行っていて、そのほとんどの日で出社していました。とはいえチームメンバーはリモートで勤務している方が多く、週に1回程度出社されている方が多かったです。また、メンバーの中には地方に住んでいる方もいらっしゃり、場所にとらわれない柔軟な働き方が浸透していることを実感しました。

mixi.co.jp

ミニモではoViceを使ってオンラインでのコミュニケーションをとっています。ミーティングはGoogle Meetですが、リモートワーク中の作業や、月曜日の朝にある事業部全体のミーティング「ウィークリーチェックイン」ではoViceを使っていました。ウィークリーチェックインでは司会者が最後の枠で5分のLTを行うことになっており、期間中私も1回発表させていただきました。

オフィス

35階の社食には1グラム1円のデリがあり、毎日メニューが変わります。ランチのタイミングでは普段話さないミニモの別チームの方や、同期のインターン生などとお話することができました。

黒い机の上に、黒い使い捨て容器に入ったお弁当が縦向きで置かれている。時計回りに、ポテトサラダとドレッシングのかかったサラダ、タレのかかった鶏肉、豚の角煮と青菜、白ご飯、焼きそば、が仕切りごとに盛られている。右上にはMIXIのロゴが入った紙コップが置かれている
デリのごはん

オフィスでは定期的に全社向けのイベントが開催されていて、チームではこれに合わせて全員共通の出社日を設定していました。特に健康系のイベントが多く、私も月1回の「ベジチェック」や年1回の「カラダ測定フェス」に参加させていただきました。大学生になってから食生活が悪化する一方だったので、これを機に見直していきたいところです。

むすびにかえて

1ヶ月という短い間でしたが、MIXIでの働き方を肌で感じることができました。

ミニモはリリースの頻度も高く、期間中私自身も何度かリリース作業を経験させていただきました。学生のうちはリアルタイムにユーザーが存在するサービスの開発に携わる機会がまず限られているので、就業型インターンシップという形で実務を経験できたことは貴重な経験になりました。

チームメンバーの皆さんや人事の方、1on1をしてくださった方など、たくさんの社員さんにお世話になりました。ありがとうございました!