[{"data":1,"prerenderedAt":657},["ShallowReactive",2],{"detailvacation2026-app":3,"$fi5b0cf3IrCOdIKBu5eoEUy_yn7IDY3qPLoCF_Pjnkss":257,"$f7OovQEBIkf3flPSO65XgVqn1FRUlN7OLmCu_FYFaAPE":284,"works":492},{"id":4,"createdAt":5,"updatedAt":6,"publishedAt":7,"revisedAt":6,"title":8,"tag":9,"recommended_articles":30,"eyecatch":122,"heading_list":29,"summary":126,"content2":127,"description":128,"related_articles":129,"recruit":14,"cta_title":254,"cta_text":255,"cta_url":256,"is_html":14,"is_migration":14},"vacation2026-app","2026-08-14T02:25:28.575Z","2026-09-24T03:25:59.639Z","2026-09-24T03:25:42.801Z","AIで作ったプロトタイプを実用化。「AIプロトタイプ壁打ち」で社員旅行アプリを開発",[10,15,19,23],{"id":11,"createdAt":12,"updatedAt":12,"publishedAt":12,"revisedAt":12,"name":13,"top":14},"ai","2025-10-20T05:29:45.387Z","AI",false,{"id":16,"createdAt":17,"updatedAt":17,"publishedAt":17,"revisedAt":17,"name":18,"top":14},"company-trip","2024-03-15T05:38:37.920Z","社員旅行",{"id":20,"createdAt":21,"updatedAt":21,"publishedAt":21,"revisedAt":21,"name":22,"top":14},"internal-project","2025-02-03T17:24:30.251Z","社内案件",{"id":24,"createdAt":25,"updatedAt":26,"publishedAt":25,"revisedAt":27,"name":28,"top":29},"promotion","2023-07-13T11:19:32.620Z","2023-08-09T08:38:30.413Z","2023-08-09T07:10:47.562Z","PR",true,[31,70,102],{"id":32,"createdAt":33,"updatedAt":34,"publishedAt":35,"revisedAt":35,"title":36,"tag":37,"recommended_articles":47,"eyecatch":54,"heading_list":29,"content2":58,"description":59,"related_articles":60,"recruit":14,"cta_title":68,"cta_text":69,"is_html":14,"is_migration":14},"custom-reservation-system","2026-08-24T05:53:29.501Z","2026-09-07T04:01:25.896Z","2026-09-07T03:51:13.114Z","3つの事例で見るフルカスタムの予約システム",[38,40,42,44,45],{"id":39},"infrastructure",{"id":41},"security",{"id":43},"backend",{"id":24},{"id":46},"tech",[48,50,52],{"id":49},"claude-code-perl-typescript-migration",{"id":51},"nazotoki",{"id":53},"noel2025",{"url":55,"height":56,"width":57},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F089ad5ed4cfa415983677dc8044d462a\u002Fcustom-reservation-system.png",941,1672,"\u003Cp>弊社ではこれまで、\u003Cstrong>施設の体験プログラムやイベントなど、さまざまな予約システムを開発\u003C\u002Fstrong>してきました。同じ予約システムでも、何を予約するのか、誰が管理するのかによって、求められる仕組みは変わります。\u003Cbr>\u003Cbr>今回は\u003Cstrong>特徴の異なる 3 つの事例から、個別の要望をどのように形にしたのか\u003C\u002Fstrong>を紹介します。\u003C\u002Fp>\u003Ch2 id=\"hdb941c213f\">体験型施設：現場の声からつくった管理画面\u003C\u002Fh2>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F0f46d438819249fe8af52687f5c34686\u002Fworkshop-admin.png.png\" alt=\"\" width=\"1672\" height=\"941\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>1 つ目は、\u003Cstrong>施設内で行われる体験型ワークショップの予約システム\u003C\u002Fstrong>です。利用者は会員登録後、Webサイトから希望する日時を予約できます。\u003C\u002Fp>\u003Cp>利用者向けの予約機能に加え、スタッフ側の管理機能も充実させました。学校などの団体から電話で受けた予約をその場で登録できるほか、団体利用に伴う駐車場や来館の予約も管理画面上で扱えます。\u003C\u002Fp>\u003Cp>リニューアルで特に重視したのが、\u003Cstrong>日々予約対応を行うスタッフの使いやすさ\u003C\u002Fstrong>です。管理画面のデザインと実装にあたり、\u003Cstrong>カスタマーサポートの担当者へヒアリングを実施\u003C\u002Fstrong>。従来のシステムで使いづらかった点だけでなく、変えずに残してほしい部分も確認し、実際の業務の流れに沿って画面や操作を調整しました。\u003C\u002Fp>\u003Cp>管理画面には、\u003Cstrong>予約した参加者を当日のテーブルへ割り当てる機能\u003C\u002Fstrong>も備えています。人数やグループ構成を見ながら、画面上で各テーブルへ配置できる仕組みです。年齢や参加者の組み合わせといった、\u003Cstrong>ワークショップ独自の予約条件にも対応\u003C\u002Fstrong>しています。\u003C\u002Fp>\u003Cp>現場へのヒアリングをもとに、独自の予約条件や当日の運用まで一つの管理画面に落とし込める点は、\u003Cstrong>フルスクラッチ開発の強み\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Ch2 id=\"h6ccc823773\">大規模イベント：アクセス集中を見越した設計\u003C\u002Fh2>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fc8b5f984b7dc48429bce076a01fb1b9b\u002Fhigh-traffic-event.png.png\" alt=\"\" width=\"1672\" height=\"941\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>2 つ目は、\u003Cstrong>予約開始と同時に多くの申し込みが集まり、短時間で枠が埋まる大規模イベント\u003C\u002Fstrong>の事例です。最大の課題は、大量のアクセスを受け止めながら、\u003Cstrong>定員を超える予約を発生させないこと\u003C\u002Fstrong>でした。\u003C\u002Fp>\u003Cp>そのため、システムとインフラの両面から構成を検討。入口となるページは、アクセスのたびに処理が発生しない静的な構成にし、予約処理でロックする範囲も限定。\u003Cstrong>短時間に負荷が集中することを前提に設計\u003C\u002Fstrong>しています。\u003Cbr>\u003Cbr>予約には LINE ログインによる認証が必要です。認証を挟むことで利用者ごとの操作に時間差が生まれ、結果としてアクセスがある程度分散することも見込んでいます。一方で、\u003Cstrong>ログインを終えた時点ですでに満席となる状況を避けられる\u003C\u002Fstrong>よう、予約の流れも調整しました。\u003C\u002Fp>\u003Cp>受付開始前には、多くの利用者が同時に操作しても、用意した枠数を超えて予約が成立しないかを繰り返しテストしています。\u003C\u002Fp>\u003Cp>予約後は参加者ごとに QR コードを発行し、当日はスタッフがスマートフォンで読み取って入場を確認できます。多数の来場者を円滑に受け入れるため、\u003Cstrong>QR コードを使ったチケットのもぎり機能\u003C\u002Fstrong>まで独自に実装しました。\u003C\u002Fp>\u003Cp>アクセス集中への対策だけでなく、予約の受付から当日の入場まで、イベントの規模と運用に合わせて一から設計した事例です。\u003C\u002Fp>\u003Ch2 id=\"h2f3457306f\">有料イベント：Shopifyと連携した有料イベントの予約システム\u003C\u002Fh2>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fd65eac0757c244d0b5e25922e0a0bb97\u002Fecommerce-reservation-integration.png.png\" alt=\"\" width=\"1672\" height=\"941\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>3 つ目は、\u003Cstrong>EC サイトを運営するクライアント向けに開発した、有料イベントの予約システム\u003C\u002Fstrong>です。当初は一つのイベント向けに開発したものでしたが、\u003Cstrong>現在は複数のプログラムにも展開\u003C\u002Fstrong>されています。\u003C\u002Fp>\u003Cp>既存の EC サイトでは、 \u003Ca href=\"https:\u002F\u002Fwww.shopify.com\u002Fjp\" target=\"_blank\" rel=\"noopener noreferrer\">Shopify\u003C\u002Fa> が使われていました。そこで、イベント予約の機能を \u003Cstrong>Shopify のアプリとして開発\u003C\u002Fstrong>。既存の会員情報や決済機能をそのまま利用できるため、参加者は別のサービスでアカウントを作ったり、支払い情報を登録したりする必要がありません。\u003C\u002Fp>\u003Cp>運営側も、商品の販売とイベントの予約を同じ Shopify の管理画面から確認できます。参加経験などイベントごとに必要な情報を取得できるよう、\u003Cstrong>独自のアンケート機能\u003C\u002Fstrong>を追加。\u003Cstrong>以前利用していた外部サービスの予約データについても、過去の履歴を引き継げるよう移行をサポート\u003C\u002Fstrong>しました。\u003C\u002Fp>\u003Cp>実装にあたっては、\u003Cstrong>Shopify が備える多様な機能との整合性も考慮\u003C\u002Fstrong>しています。クーポンなどを利用した場合も予約を正しく処理できるよう、API の組み合わせを一つずつ検証。Shopify 側で扱う情報と、独自に保持する予約データを切り分けました。\u003C\u002Fp>\u003Cp>Shopify の既存機能を活かしながら、イベント運営に必要な予約機能を加えています。\u003C\u002Fp>\u003Ch2 id=\"h65a80d5aa6\">予約システムの開発・改善をご相談ください\u003C\u002Fh2>\u003Cp>予約システムを設計する際は、申し込みを受け付ける画面だけでなく、管理業務や当日の運用まで考える必要があります。\u003C\u002Fp>\u003Cp>弊社では、\u003Cstrong>利用者向けの予約画面、管理画面の UI、バックエンド、インフラ、外部サービスとの連携\u003C\u002Fstrong>まで、案件に応じて設計・開発しています。\u003Cbr>アクセスが集中するシステムには、\u003Cstrong>キャンペーン開発で培った負荷対策の知見\u003C\u002Fstrong>を活かして設計します。\u003C\u002Fp>\u003Cp>\u003Cstrong>システム全体の新規開発やリニューアルに限らず、一部機能の改修にも対応可能\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>\u003Cstrong>「既存の予約サービスでは運用に合わない」「管理業務の一部が手作業で残っている」「現在の EC サイトや会員基盤を活かしたい」\u003C\u002Fstrong>など、予約に関する課題があれば、\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>お問い合わせフォーム\u003C\u002Fstrong>\u003C\u002Fa>からご相談ください。\u003C\u002Fp>","S2 Factoryがフルカスタムで開発した予約システムを3つの事例から紹介。カップヌードルミュージアムの管理画面、大規模イベントのアクセス対策、山と道のShopify連携など、要件に合わせた設計・実装の工夫をまとめました。",[61,62,64,66],{"id":49},{"id":63},"ai-generated-campaign-site",{"id":65},"bird-classification-2",{"id":67},"design-project-1","予約システムの開発・リニューアルをご検討の方へ","既存サービスでは運用に合わない、管理業務に手作業が残っている、ECサイトや会員基盤と連携したい。予約システムに関する課題をお聞かせください。新規開発から既存システムの見直しまで、要件に合わせて対応します。",{"id":49,"createdAt":71,"updatedAt":72,"publishedAt":73,"revisedAt":72,"title":74,"tag":75,"recommended_articles":82,"eyecatch":86,"heading_list":14,"content2":88,"description":89,"related_articles":90,"recruit":14,"cta_url":101,"is_html":14,"is_migration":14},"2026-05-29T08:21:55.189Z","2026-09-01T05:43:45.290Z","2026-06-02T01:45:24.758Z","テストがない 10 万行の Perl システムを、Claude Code で TypeScript へ書き換えた話",[76,77,79,80,81],{"id":11},{"id":78},"typescript",{"id":43},{"id":46},{"id":24},[83,84,85],{"id":67},{"id":63},{"id":65},{"url":87,"height":56,"width":57},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F1632b87e5aaa4944a854ccc430cdb89e\u002F%E3%82%A2%E3%82%A4%E3%82%AD%E3%83%A3%E3%83%83%E3%83%81.png","\u003Ch2 id=\"h586b90d155\">「AI が書いたコード、読んでますか？」\u003C\u002Fh2>\u003Cp>最近よく見かけるこの議論に、正直に答えます。\u003C\u002Fp>\u003Cp>\u003Cstrong>全部は読んでいません。10 万行、読みきれません。\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>これは無責任に聞こえるかもしれません。「AI が書いたコードの 80% は負債だ」という研究もありますし、「理解していないコードをリリースするな」という意見はもっともだと思います。\u003C\u002Fp>\u003Cp>ただ、10 万行のコードを1行ずつ目で追って品質を担保するのは、\u003Cstrong>現実的に難しい\u003C\u002Fstrong>ですよね。人間が書いたコードでも、全行レビューはしていないはずです。\u003C\u002Fp>\u003Cp>じゃあどうしたか。\u003C\u002Fp>\u003Cp>\u003Cstrong>読む代わりに、検証する仕組みを作りました。 AI に書かせたコードを、AIに検証させ続ける\u003C\u002Fstrong>。24 時間、何百ラウンドも、バグが出なくなるまで。読んで理解する代わりに、正しさを証明する。\u003C\u002Fp>\u003Cp>この記事は、その話です。\u003C\u002Fp>\u003Ch2 id=\"h90ca2bc41d\">前提：テストがほぼない\u003C\u002Fh2>\u003Cp>私が担当しているのは、ある企業の EC サイトのバックエンドです。\u003C\u002Fp>\u003Cp>\u003Ca href=\"https:\u002F\u002Fwww.perl.org\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">Perl\u003C\u002Fa> で書かれていて、10 年以上動いています。認証、注文、決済、予約、LINE連携、クーポン。\u003Cstrong>API のエンドポイントは 133 個\u003C\u002Fstrong>あります。\u003C\u002Fp>\u003Cp>そしてこのコードベースには、\u003Cstrong>まともな自動テストがほぼありませんでした。\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>初めてソースを開いたときのことは覚えています。10 年分のビジネスロジックがぎっしり詰まっていて、でもそれを検証する手段が何もない。仕様書もない。何かを変えたとき、壊れたかどうかを知る方法がない。よくこれで 10 年動いてきたなと、率直に思いました。\u003C\u002Fp>\u003Cp>\u003Cstrong>これを \u003C\u002Fstrong>\u003Ca href=\"https:\u002F\u002Fwww.typescriptlang.org\u002Fja\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>TypeScript\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> に書き換えろ、というのが今回のミッション\u003C\u002Fstrong>でした。\u003C\u002Fp>\u003Ch2 id=\"h460484bf92\">普通にやったら詰みます\u003C\u002Fh2>\u003Cp>テストのないコードの移植は、ソフトウェアエンジニアリングでも最悪の部類に入る仕事です。\u003C\u002Fp>\u003Cp>教科書的にやるなら、まず既存の Perl コードにテストを書きます。挙動を固めてから、TypeScript で書き直す。でも 10 年分のコードにテストを書く工数は、移植そのものと同じかそれ以上かかります。しかも、Perl の挙動をちゃんと理解してテストに落とせる人材は限られています。\u003C\u002Fp>\u003Cp>詰んでます。\u003C\u002Fp>\u003Ch2 id=\"h4677704352\">Claude Code に「書かせる」のは1週間で終わりました\u003C\u002Fh2>\u003Cp>Claude Code には、\u003Cstrong>カスタムスラッシュコマンド\u003C\u002Fstrong>という機能があります。\u003Cstrong>自分でコマンドを定義して、繰り返し使える仕組み\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>私はまず \u003Ccode>\u002Fmigrate-endpoint\u003C\u002Fcode> というコマンドを作りました。\u003C\u002Fp>\u003Cp>Perl のコントローラのファイルパスを渡すと、Claude Code が関連するモデルやエンティティ、DB スキーマまで全部読みに行って、TypeScript の実装コードとテストを一気に生成してくれます。\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F285f776615bd4583a5177b8d1c440a90\u002Fmigrate-endpoint-flow.png\" alt=\"\" width=\"1448\" height=\"1086\">\u003C\u002Ffigure>\u003Cp>\u003Cstrong>テストがないなら、テストごと作ればいい。\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>この割り切りで、\u003Cstrong>移植前にテストを書くという工程を丸ごとスキップ\u003C\u002Fstrong>できました。\u003C\u002Fp>\u003Cp>133 エンドポイント、約 10 万行。実装が終わるまで、約 1 週間でした。最初のエンドポイントが動いたときは「本当にこれでいけるのか？」という気持ちが正直ありましたが、\u003Cstrong>2 つ目、3 つ目と進むうちに、コマンドの精度がどんどん上がっていく\u003C\u002Fstrong>のがわかりました。\u003C\u002Fp>\u003Ch2 id=\"h1a681fd8e2\">でも「書けた」は「正しい」じゃない\u003C\u002Fh2>\u003Cp>1 週間で 10 万行。数字だけ見ればすごいです。\u003C\u002Fp>\u003Cp>でも、テストのほぼない Perl から移植したコードです。\u003Cstrong>「動くけど微妙に違う」コードが量産されている可能性\u003C\u002Fstrong>は大いにあります。\u003C\u002Fp>\u003Cp>Perl は未定義値を空文字やゼロとして黙って処理します。TypeScript ではそうはいきません。タイムゾーンの扱いも違う。数値と文字列の暗黙変換もある。こういう差異は、普通のテストでは見つかりません。\u003C\u002Fp>\u003Cp>そこで、これも仕組みで解決することにしました。\u003C\u002Fp>\u003Ch2 id=\"h7480bb35d9\">パリティ監査という仕組みを作りました\u003C\u002Fh2>\u003Cp>もう 1 つのカスタムコマンド、\u003Ccode>\u002Fparity-audit\u003C\u002Fcode> を作りました。\u003C\u002Fp>\u003Cp>やることはシンプルです。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>Perl のコードと TypeScript のコードを突き合わせて、挙動の差異を見つける\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>差異があればバグとして修正し、テストを追加する\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>このコマンドを実行すると、\u003Cstrong>1 ラウンドで 20 の AI エージェントが並列に起動\u003C\u002Fstrong>し、それぞれが違う切り口でコードを調べていきます。\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fe1d8b1dc72f44fcf9f367d8dc3b852b9\u002Fparity-audit-flow.png\" alt=\"\" width=\"1447\" height=\"1087\">\u003C\u002Ffigure>\u003Cp>あるエージェントはエンドポイント単位で、リクエストからレスポンスまでのコードパスを 1 行ずつ比較しています。別のエージェントは DB アクセス層を見ていて、クエリの条件やソート順、NULL の扱いをチェックしています。\u003C\u002Fp>\u003Cp>決済まわりを専門で見るエージェントもいます。税計算、クーポン適用、支払いステータス。1 円でもズレたらアウトの領域です。認証・セッション管理を集中的に検証するエージェントもいて、ログインや SSO、MFA といったセキュリティに直結する処理を重点的に見ます。\u003C\u002Fp>\u003Cp>日時処理、暗号化、バーコード生成といった「言語が変わると挙動が変わりやすい」ユーティリティも、専用のエージェントが横断的にチェックしています。\u003C\u002Fp>\u003Cp>これだけの観点を人間が毎回カバーするのは、まず無理だと思います。\u003C\u002Fp>\u003Ch2 id=\"h9def901947\">「10回連続クリーン」になるまで止めません\u003C\u002Fh2>\u003Cp>パリティ監査には、1 つ\u003Cstrong>ルール\u003C\u002Fstrong>を課しました。\u003C\u002Fp>\u003Cp>\u003Cstrong>連続10回、差異ゼロが出るまで回し続ける。\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>1ラウンドでもバグが見つかったら、カウンタはゼロに戻ります。修正して、また最初から。10 回連続でクリーンになって、初めて「OK」です。\u003C\u002Fp>\u003Cp>このコマンドを夜間も含めて走らせ続けました。\u003C\u002Fp>\u003Cp>\u003Cstrong>2.5 ヶ月間。\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2 id=\"h29bb0ce50d\">監査 379 ラウンド、800件以上のバグを修正\u003C\u002Fh2>\u003Cp>結果として、\u003Cstrong>379 ラウンドの監査を回し、800 件以上のバグ\u003C\u002Fstrong>を見つけて直しました。\u003C\u002Fp>\u003Cp>最初のほうはラウンドごとにバグが山のように出てきて、正直なところ気が遠くなりました。でも修正を重ねるうちに、だんだんクリーンなラウンドが増えてきます。連続クリーンが 5 回、6 回と伸びていくのを見ているときは、ちょっとした達成感がありました。\u003C\u002Fp>\u003Cp>中には、\u003Cstrong>移植元の Perl 側に何年も潜んでいたバグが見つかったケースも\u003C\u002Fstrong>ありました。テストがなかったから、誰も気づかなかったバグです。\u003Cstrong>パリティ監査がなければ、そのまま TypeScript 側にも引き継がれていた\u003C\u002Fstrong>でしょう。\u003C\u002Fp>\u003Ch2 id=\"h3884ede80a\">これで何が変わったか\u003C\u002Fh2>\u003Cp>移植前と移植後で、テストの状況は一変しました。\u003C\u002Fp>\u003Cp>\u003Cstrong>移植後のテストは 1,419 件。\u003C\u002Fstrong> しかも全部パスしています。移植プロジェクトとしてだけでなく、テスト資産の構築としても大きな成果だと思っています。\u003C\u002Fp>\u003Cp>そして、1,419 件のテストがあるということは、ここからのリファクタリングが容易になるということでもあります。\u003Cstrong>テストがなかった頃は怖くて触れなかったコードを、安心して改善できる。\u003C\u002Fstrong>移植がゴールではなく、ここからがスタートです。\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Ffaaa3c46c0cf4ac6b95524e19d81e50c\u002Fmigration-audit-results.png\" alt=\"\" width=\"1448\" height=\"1086\">\u003C\u002Ffigure>\u003Ch2 id=\"h49ccabfba5\">そして、人間の手で確かめました\u003C\u002Fh2>\u003Cp>\u003Cstrong>最後に、フロントエンドとつないで E2E テスト\u003C\u002Fstrong>をしました。\u003C\u002Fp>\u003Cp>これは人間が手で動かすテストです。実際のブラウザで、実際の画面を操作して、注文を入れて、決済して、予約して。AI ではなく、人間の目と手で確かめました。\u003C\u002Fp>\u003Cp>\u003Cstrong>不具合は見つかりませんでした。\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>10 万行。テストがほぼない状態からの移植。AI が書いて、AI が検証して、最後に人間が触って、壊れていなかった。\u003C\u002Fp>\u003Cp>正直、自分でもちょっと信じられませんでした。\u003C\u002Fp>\u003Ch2 id=\"h42e2556fbc\">Claude Codeの使い方として伝えたいこと\u003C\u002Fh2>\u003Cp>この経験を通じて、Claude Code の使い方について 3 つのことがわかりました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>カスタムコマンドで「仕組み」にする\u003C\u002Fstrong>\u003Cul>\u003Cli>属人的な「上手いプロンプトの書き方」ではなく、誰でも実行できるコマンドとして定義します。これで品質が人に依存しなくなります。\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Ca href=\"http:\u002F\u002FCLAUDE.md\">\u003Cstrong>CLAUDE.md\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> に知識を貯める\u003C\u002Fstrong>\u003Cul>\u003Cli>プロジェクト固有のルール（アーキテクチャ、命名規則、エラーコードなど）を CLAUDE.md ファイルに書いておきます。セッションが変わっても、Claude Code はこれを読んでくれます。移植が進むほどこのファイルが育ち、後半フェーズほど手戻りが減りました。\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>品質保証を「計算資源」の問題にする\u003C\u002Fstrong>\u003Cul>\u003Cli>1 ラウンド 20 エージェント × 379 ラウンド。この物量の検証を人間がやるのは無理です。でもコマンドにして 24 時間回せば、品質保証は工数の問題ではなく計算資源の問題になります。\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003Ch2 id=\"h5b6299b788\">「読んでない」のその先へ\u003C\u002Fh2>\u003Cp>冒頭に戻ります。\u003C\u002Fp>\u003Cp>\u003Cstrong>AI が書いたコード、読んでますか？\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>私の答えは変わりません。全部は読んでいません。でも、全部検証しました。20 エージェント並列で、379 ラウンド、800 件のバグを潰して、最後に人間の手で E2E テストして、不具合ゼロ。\u003C\u002Fp>\u003Cp>もちろん、コードを読んで理解すること自体の価値を否定するつもりはありません。ただ、「読む」以外にも品質を担保する手段はあるはずです。\u003C\u002Fp>\u003Cp>\u003Cstrong>読むか読まないかではなく、正しさをどう証明するか。\u003C\u002Fstrong> その仕組みを設計できるかどうかが、AI 時代のエンジニアリングで問われることなんじゃないかと思っています。\u003C\u002Fp>\u003Ch2 id=\"hc96909f29a\">この 3 ヶ月は長いのか\u003C\u002Fh2>\u003Cp>AI コーディングの事例として、「数時間でアプリを作った」「週末で完成した」といった話をよく見かけます。それと比べると、3 ヶ月という数字は地味に映るかもしれません。\u003C\u002Fp>\u003Cp>でも、考えてみてください。\u003Cstrong>テストのほぼない 10 万行のプロダクションコードを、133 エンドポイントの挙動を 1 つも壊さずに別言語へ移植\u003C\u002Fstrong>する。普通にやったら 1 年はかかるプロジェクトです。見積もりの段階で「現実的じゃない」と却下されてもおかしくない。\u003C\u002Fp>\u003Cp>\u003Cstrong>それを 3 ヶ月で、しかも人間の E2E テストで不具合ゼロという品質で完遂\u003C\u002Fstrong>できました。\u003C\u002Fp>\u003Cp>同じような課題を抱えている方は、少なくないと思います。テストのないレガシーシステム、移植したいけど踏み切れない、人手も時間も足りない。今回のアプローチは、そうしたプロジェクトにも十分に適用できると考えています。\u003C\u002Fp>\u003Cp>\u003Cstrong>レガシーシステムの移行でお困りの方がいらっしゃれば、ぜひご相談ください。\u003C\u002Fstrong>\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Chr>\u003Cp>\u003Cspan style=\"color: #6c6c6c\">注記：本記事で紹介した \u003C\u002Fspan>\u003Ccode>\u002Fmigrate-endpoint\u003C\u002Fcode>\u003Cspan style=\"color: #6c6c6c\">、\u003C\u002Fspan>\u003Ccode>\u002Fparity-audit\u003C\u002Fcode>\u003Cspan style=\"color: #6c6c6c\"> は Claude Code のカスタムスラッシュコマンド機能で構築したものです。\u003C\u002Fspan>\u003C\u002Fp>","テストがほぼない10万行のPerl製ECバックエンドを、Claude Codeを使ってTypeScriptへ移植。カスタムコマンドによる実装生成とパリティ監査で、379ラウンドの検証、800件以上のバグ修正、1,419件のテスト構築まで行った取り組みを紹介します。",[91,92,94,95,97,99],{"id":63},{"id":93},"event-ai-agent",{"id":65},{"id":96},"edge-ai",{"id":98},"ux-certification-basics",{"id":100},"figma-plugin","https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fshader-basics\u002F",{"id":63,"createdAt":103,"updatedAt":104,"publishedAt":105,"revisedAt":104,"title":106,"tag":107,"recommended_articles":111,"eyecatch":116,"heading_list":29,"content2":120,"related_articles":121,"recruit":14,"is_html":14,"is_migration":14},"2025-12-18T04:44:24.111Z","2026-09-01T05:32:07.516Z","2026-01-14T08:48:50.112Z","生成 AI を活用したコンテンツ生成キャンペーンサイトの制作事例",[108,109,110],{"id":24},{"id":11},{"id":46},[112,113,115],{"id":49},{"id":114},"birdwatch-camera",{"id":67},{"url":117,"height":118,"width":119},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F127f63b9fa8b47eb93d3f6d7c53fe605\u002Fwebsite.png",2000,4000,"\u003Cp>近年、広告・キャンペーン領域では、生成 AI を活用したユーザー参加型コンテンツが増えています。\u003Cbr>\u003Cstrong>ユーザーの入力をもとにコンテンツを生成し、その結果を画像として保存したり、SNS でシェアしたりできる仕組み\u003C\u002Fstrong>は、体験性と拡散性の両面を備えた手法です。\u003C\u002Fp>\u003Cp>具体的な案件名は出しませんが、今回は弊社で制作した\u003Cstrong>「生成 AI を利用したコンテンツ生成キャンペーンサイト」\u003C\u002Fstrong>について、どのような構成で、どんな実装を行ったのかを紹介したいと思います。\u003C\u002Fp>\u003Ch2 id=\"h9707d3a59a\">概要\u003C\u002Fh2>\u003Cp>今回紹介するのは、生成 AI を活用したコンテンツ生成型のキャンペーンサイトです。\u003Cbr>ユーザーが任意の文章を入力すると、その内容をもとに\u003Cstrong>架空の四字熟語を生成し、さらにその四字熟語を配置したデザイン画像を自動で生成\u003C\u002Fstrong>します。\u003C\u002Fp>\u003Cp>生成された画像は、サイト上でそのまま閲覧できるだけでなく、SNS へのシェアや、ユーザーの端末への保存にも対応しています。\u003Cbr>診断コンテンツのように気軽に参加でき、生成結果をそのままアウトプットとして扱える構成です。\u003C\u002Fp>\u003Col>\u003Cli>\u003Cstrong>ユーザーが文章を入力\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>文章をもとに架空の四字熟語を生成\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>生成された四字熟語を使って画像を生成\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>生成結果を表示・保存・シェア\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Fol>\u003Ch2 id=\"hb8b4f4df49\">生成 AI による四字熟語生成とチェック機構\u003C\u002Fh2>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fda95ca0e974c4a9ebd9a5692781467ac\u002Fcheck.png\" alt=\"\" width=\"1024\" height=\"595\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>ユーザーが入力した文章をもとに、\u003Cstrong>架空の四字熟語を生成する部分には、生成 AI の API を利用\u003C\u002Fstrong>しています。入力されたテキストの内容を踏まえ、意味的に成立する四字熟語が生成されます。\u003C\u002Fp>\u003Cp>ただし、キャンペーン用途として公開する以上、生成結果をそのまま無条件に表示するわけにはいきません。なので、生成結果に対していくつかの\u003Cstrong>チェック機構\u003C\u002Fstrong>を実装しています。\u003C\u002Fp>\u003Cp>具体的には、\u003Cstrong>プロンプトによる制御\u003C\u002Fstrong>に加え、あらかじめ用意した \u003Cstrong>NG 漢字リストを用いたチェック\u003C\u002Fstrong>を行っています。\u003Cbr>生成された四字熟語にネガティブな意味合いを持つ漢字や、不適切と判断される文字が含まれていた場合は、その結果を採用せず、\u003Cstrong>再度生成処理を行う\u003C\u002Fstrong>仕組みです。\u003C\u002Fp>\u003Cp>\u003Cstrong>プロンプトにすべてを依存せず、後段でチェックを行う構成とすることで、実運用を想定した安定した生成フローを実現\u003C\u002Fstrong>しています。\u003C\u002Fp>\u003Ch2 id=\"h05a3315797\">四字熟語を使った画像生成\u003C\u002Fh2>\u003Cp>生成された四字熟語は、そのままテキストとして表示するのではなく、\u003Cstrong>あらかじめ用意したデザインをもとに、画像として出力\u003C\u002Fstrong>しています。\u003C\u002Fp>\u003Cp>\u003Cstrong>画像生成にあたっては、いわゆる生成 AI による画像生成は使用していません。\u003C\u002Fstrong>\u003Cbr>文字の配置やサイズ、色、背景とのバランスなどは、事前に設計したデザインルールをもとに、\u003Cstrong>画像編集ライブラリを用いて動的に生成\u003C\u002Fstrong>しています。\u003C\u002Fp>\u003Cp>四字熟語は内容によって文字の印象やバランスが変わるため、単純に文字を載せるだけでは、見た目にばらつきが出てしまいます。\u003Cbr>そこで文字数や構成を考慮しながら、配置やスタイルを調整する処理を行い、\u003Cstrong>どの生成結果でも一定のビジュアルクオリティを保てるように\u003C\u002Fstrong>しています。\u003C\u002Fp>\u003Cp>\u003Cstrong>生成 AI は四字熟語を作る部分にのみ使用し、画像表現そのものは、これまでの Web 制作やビジュアル制作で培ってきた手法を用いて制御\u003C\u002Fstrong>しています。\u003C\u002Fp>\u003Ch2 id=\"h543fa3266b\">キャンペーン用途を想定したインフラ設計と安定稼働\u003C\u002Fh2>\u003Cp>本コンテンツでは、生成AIによる処理や画像生成を行うため、ユーザーの操作に対して即時に結果を返すことが難しい場面があります。\u003Cbr>さらに\u003Cstrong>キャンペーンサイトの場合、SNS での拡散などをきっかけに、短時間でアクセスが集中するケース\u003C\u002Fstrong>も想定されます。\u003C\u002Fp>\u003Cp>そのため、生成処理を含むバックエンドを \u003Ca href=\"https:\u002F\u002Faws.amazon.com\u002Fjp\u002Fpm\u002Flambda\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>AWS Lambda\u003C\u002Fstrong>\u003C\u002Fa> 上に構築し、同時アクセスが発生しても処理が滞りにくい構成を採用しました。\u003Cbr>アクセス数の増減に応じて自動的にスケールすることで、キャンペーン期間中も安定した動作を維持できるようにしています。\u003C\u002Fp>\u003Ch2 id=\"ha214098e44\">まとめ\u003C\u002Fh2>\u003Cp>今回は、「生成AIを利用したコンテンツ生成キャンペーンサイト」の一例を紹介しました。\u003Cbr>\u003Cbr>ユーザー参加型のコンテンツでは、\u003Cstrong>生成 AI の使いどころと制御、そして安定して運用できる構成が重要\u003C\u002Fstrong>になります。\u003Cbr>弊社では、こうした点を踏まえた制作をこれまで複数手がけてきました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>毎ドラ部 AI ソングメーカー\u003C\u002Fstrong>\u003Cbr>ユーザーが撮影した写真をアップロードすると、AI により歌詞が自動生成され、\u003Cbr>オリジナルのテーマソングとして楽しめるコンテンツです。\u003Cbr>同時に、写真からジャケットイラストも自動生成されます。\u003Cbr>（弊社は Web システム開発・インフラ構築を担当）\u003Cp>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fwork\u002Fdetail\u002Fgeorgia-song-maker\" data-iframely-url=\"https:\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fwork%2Fdetail%2Fgeorgia-song-maker&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"https:\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Cp>\u003Cbr>\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cstrong>毎ドラ部 AI イラストメーカー\u003C\u002Fstrong>\u003Cbr>ユーザーが撮影した写真を人気イラストレーター風のタッチに AI で変換し、生成されたイラストを日本全国のマップ上に投稿・共有できるキャンペーンサイトです。\u003Cbr>（弊社はテクニカルディレクション、Web 制作、システム開発、インフラ構築を担当）\u003Cp>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fwork\u002Fdetail\u002Fgeorgia\" data-iframely-url=\"https:\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fwork%2Fdetail%2Fgeorgia&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"https:\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cbr>\u003Cstrong>「生成AIを活用したコンテンツ制作」\u003C\u002Fstrong>についてご相談があれば、ぜひお気軽にお問い合わせください。\u003Cbr>これまでの知見をもとに、企画段階からの設計・制作・安定稼働までお手伝いします。\u003C\u002Fp>",[],{"url":123,"height":124,"width":125},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F76171c49363646cc86698d5e2043af98\u002Fai-prototype-walltalk-eyecatch-revised-v3.png",900,1600,"\u003Cul>\u003Cli>\u003Cstrong>Claude Codeで作った社員旅行用アプリを題材に、新サービス「AIプロトタイプ壁打ち」を社内で検証\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>技術構成やバックエンド、デザインについて相談し、参加者全員が使えるWebアプリへ改修\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>実際の社員旅行で運用し、利用後のアンケートから良かった点や改善点を振り返った\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>","\u003Cp>\u003Cstrong>2 年ぶりの社員旅行\u003C\u002Fstrong>で長崎に行きました。\u003Cstrong>前回は、写真を投稿してミッションを達成していく専用アプリを制作\u003C\u002Fstrong>しましたが、今回も社員旅行に合わせて新しい Web アプリを用意することに。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fvacation2024-missions\u002F\" data-iframely-url=\"https:\u002F\u002Fiframely.net\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fblog%2Fvacation2024-missions%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"https:\u002F\u002Fiframely.net\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Cp>\u003Cbr>今回はこのアプリを題材に、\u003Cstrong>弊社で始める新サービス「AIプロトタイプ壁打ち」\u003C\u002Fstrong>を社内で検証しました。\u003Cstrong>普段は広報を担当し、開発を専門としていない私がクライアント役\u003C\u002Fstrong>となって Claude で作ったプロトタイプを持ち込み、\u003Cstrong>エンジニアとアートディレクターの支援\u003C\u002Fstrong>を実際に受けながら、社員旅行で使えるアプリへ仕上げました。\u003C\u002Fp>\u003Cp>本記事では、AIプロトタイプ壁打ちの流れと、アプリが完成するまでの過程を紹介します。\u003C\u002Fp>\u003Ch2 id=\"he7c7cc39d9\">「AIプロトタイプ壁打ち」とは\u003C\u002Fh2>\u003Cfigure>\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\u002Fai-prototype-consultation\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F52c6db9bdf6049a4bb90d0c68acb48ff\u002Fai-proto01.png\" alt=\"AIプロトタイプ壁打ちとは\" width=\"1440\" height=\"1124\">\u003C\u002Fa>\u003C\u002Ffigure>\u003Cp>\u003Cbr>\u003Ca href=\"https:\u002F\u002Fclaude.ai\u002Fnew\" target=\"_blank\" rel=\"noopener noreferrer\">Claude\u003C\u002Fa> のようなツールを使えば、専門的な知識が十分になくても、画面や基本的な動きを備えたプロトタイプを作れます。ただ、それを\u003Cstrong>公開し、実際に人に使ってもらう\u003C\u002Fstrong>となると、見た目を整えるだけでは済みません。\u003C\u002Fp>\u003Cp>入力したデータはどこに保存するのか。利用者以外から見えないようにするにはどうすればよいのか。必要な機能を実現するには、どのサービスを組み合わせればよいのか。AI に聞けば実装方法は返ってきますが、\u003Cstrong>その内容が適切かどうかを判断するには専門的な知識が必要\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>「AIプロトタイプ壁打ち」は、AIで作ったプロトタイプをもとに、実現したいことや利用する場面をヒアリングし、\u003Cstrong>技術、デザイン、使いやすさ、セキュリティなどの観点から、実用化までに必要なことを整理するサービス\u003C\u002Fstrong>です。\u003Cbr>\u003Cbr>まだ要件が固まっていない段階でも、\u003Cstrong>「このまま進めて大丈夫か」「次に何をすればよいか」\u003C\u002Fstrong>といったところから相談できます。\u003C\u002Fp>\u003Ch3 id=\"haebd317835\">今回は「月額顧問：ライト」に相当\u003C\u002Fh3>\u003Cp>AIプロトタイプ壁打ちには、支援内容に応じて次の 3 つのプランがあります。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\u002Fai-prototype-consultation\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F4b0fc4fae6c94e05b52d4250d9a328b8\u002Fai-proto02.png\" alt=\"プランの紹介\" width=\"1440\" height=\"1124\">\u003C\u002Fa>\u003C\u002Ffigure>\u003Cul>\u003Cli>\u003Cstrong>単発セッション：\u003C\u002Fstrong> ヒアリング、90 分のセッション、簡易レポート\u003C\u002Fli>\u003Cli>\u003Cstrong>月額顧問・ライト：\u003C\u002Fstrong> Slack での随時相談、隔週 1 回のセッション\u003C\u002Fli>\u003Cli>\u003Cstrong>月額顧問・スタンダード：\u003C\u002Fstrong> Slack での随時相談、週 1 回のセッション\u003C\u002Fli>\u003C\u002Ful>\u003Cp>今回はこのうち、\u003Cstrong>「月額顧問：ライト」に相当する内容\u003C\u002Fstrong>で社内検証を実施しました。\u003C\u002Fp>\u003Cp>\u003Cstrong>実際のクライアントとのやり取りを想定した上で、技術担当者もデザイナーもいない企業の担当者\u003C\u002Fstrong>として、私がクライアント役を務めました。支援を担当したのは、弊社のエンジニアとアートディレクターです。\u003C\u002Fp>\u003Cp>初回の壁打ちだけでなく、技術構成の提案、開発環境やバックエンドの土台づくり、その後の Slack やミーティングでの相談、デザインレビューまで、\u003Cstrong>アプリの完成に向けて継続的にサポートを受ける形\u003C\u002Fstrong>で進めました。\u003C\u002Fp>\u003Ch2 id=\"hcc630d9979\">社員旅行用アプリのプロトタイプを作る\u003C\u002Fh2>\u003Ch3 id=\"h12af5505b6\">作りたかったもの\u003C\u002Fh3>\u003Cp>社員旅行用アプリには、集合時間や座席表などをまとめた旅のしおりに加えて、旅行をより楽しむための機能も取り入れることにしました。\u003C\u002Fp>\u003Cp>前回のアプリでは、写真を投稿しながらミッションを達成し、共通の話題や目標をつくることで、\u003Cstrong>自由行動中にも一体感が生まれる\u003C\u002Fstrong>ようにしました。今回も目的は変えず、別のアプローチを試すことに。\u003C\u002Fp>\u003Cp>そこで参考にしたのが、写真を共有し、1 日の記録を動画で振り返れる \u003Ca href=\"https:\u002F\u002Fsetlog.kr\u002F\">\u003Cstrong>setlog\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> \u003C\u002Fstrong>です。この体験をベースに、\u003Cstrong>それぞれの場所で過ごす様子を共有し、あとから1日の旅を動画で振り返れるアプリ\u003C\u002Fstrong>を目指しました。\u003C\u002Fp>\u003Ch3 id=\"he5ce4354bb\">まずは 4 つの画面を作成\u003C\u002Fh3>\u003Cp>作りたいもののイメージを Claude に伝え、まずは次の 4 画面を作成しました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>スケジュール：\u003C\u002Fstrong> 旅行のスケジュールや座席表を確認する\u003C\u002Fli>\u003Cli>\u003Cstrong>投稿：\u003C\u002Fstrong> 参加者が投稿した写真を見る\u003C\u002Fli>\u003Cli>\u003Cstrong>マップ：\u003C\u002Fstrong> 自分や参加者の現在地、観光スポットを表示する\u003C\u002Fli>\u003Cli>\u003Cstrong>メンバー：\u003C\u002Fstrong> 参加者の一覧を確認する\u003C\u002Fli>\u003C\u002Ful>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fd45697594aa148ff8ad30323ea4f43ed\u002Fbefore.png\" alt=\"\" width=\"1312\" height=\"1199\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>Claude に指示しながら調整を重ねるうちに、画面を切り替えたり、サンプルの投稿やメンバー情報を表示したりできるようになりました。保存はされませんが、モーダルが開いて投稿することもできます。一見すると、\u003Cstrong>あとは見た目を整えれば、そのまま使えそうな状態\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>このプロトタイプを持って、最初の壁打ちに臨みました。\u003C\u002Fp>\u003Ch2 id=\"hbd1f209a2e\">プロトタイプを持ち込んで相談\u003C\u002Fh2>\u003Cp>相談にあたって共有したのは、Claude で作ったプロトタイプと、アプリの概要や必要な機能をまとめたガイドラインです。\u003C\u002Fp>\u003Cp>初回のセッションは、\u003Cstrong>Zoom を使ったオンラインミーティング形式\u003C\u002Fstrong>で実施。当日はプロトタイプの画面を共有し、実際に操作しながら、各画面の狙いや実現したいことを説明しました。\u003C\u002Fp>\u003Cp>この時点で、目指すアプリの方向性は決まっていましたが、\u003Cstrong>Claude にどのような指示を出せば実現できるのか、必要な技術やサービスをどう組み合わせればよいのかはわからない状態\u003C\u002Fstrong>でした。\u003C\u002Fp>\u003Ch3 id=\"hb4096d20ef\">今回相談したこと\u003C\u002Fh3>\u003Cp>主な相談内容は次のとおりです。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>旅行らしい楽しさのあるデザインにしたい\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>マップ上に観光スポットを分かりやすく表示したい\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>投稿された写真を時間帯ごとにまとめたい\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>決まった時間に投稿を促す通知を送りたい\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>社員だけが利用できるログインを用意したい\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>社員旅行の 3 日間を中心に使うため、運用費をできるだけかけずに実現したい\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>機能やデザインだけでなく、利用人数や期間、費用面も含めて相談しました。\u003C\u002Fp>\u003Cp>質問への回答に加えて、画面を見て気づいた課題や、開発を進めるうえで確認すべき点についても意見をもらいました。要望をそのまま形にするのが難しい場合には、\u003Cstrong>何を実現したいのかを確認しながら、別の方法を一緒に考えてもらえた\u003C\u002Fstrong>のも助かった点です。\u003C\u002Fp>\u003Ch3 id=\"h61e292a9e2\">初回の相談で整理したこと\u003C\u002Fh3>\u003Cp>初回のセッションで整理した内容のうち、特に大きかったのが、マップの表現方法と、複数人で利用するためのバックエンドです。\u003C\u002Fp>\u003Ch4 id=\"hf7860d2c20\">\u003Cbr>\u003Cstrong>マップは実際の地図をベースに\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>当初は、地図全体をイラストで表現したいと考えていました。しかし、位置や縮尺を正確に合わせる必要があり、制作の負担も大きくなります。\u003C\u002Fp>\u003Cp>そこで、\u003Cstrong>実際の地図を使い、観光スポットのマーカーをイラストにする方向\u003C\u002Fstrong>で進めることになりました。\u003C\u002Fp>\u003Ch4 id=\"h9b3b2ddb50\">\u003Cbr>\u003Cstrong>複数人で使うにはバックエンドが必要\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>この時点では、投稿データをブラウザ内に保存していたため、内容を確認できるのは自分の端末だけでした。\u003C\u002Fp>\u003Cp>参加者全員で利用するには、次のような準備が必要です。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>投稿データを共有するためのデータベース\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>写真や動画を保存するためのストレージ\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>社員だけが利用できるようにする認証\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>アプリを公開するための環境\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>一見すると使えそうな画面ができていても、実際に複数人で利用するには、\u003Cstrong>データの保存や共有、ログインなどを担うバックエンド\u003C\u002Fstrong>が欠かせません。\u003C\u002Fp>\u003Cp>このほか、\u003Cstrong>通知の実現方法や利用できるサービス、費用を抑えるための条件\u003C\u002Fstrong>なども確認しました。初回のセッションで整理した内容をもとに、\u003Cstrong>後日、具体的な技術構成と完成までのロードマップを提案\u003C\u002Fstrong>してもらいました。\u003C\u002Fp>\u003Ch2 id=\"h9d87693828\">提案をもとに開発の土台を整える\u003C\u002Fh2>\u003Cp>社員旅行の参加人数や 3 日間という利用期間、投稿される写真の枚数を踏まえ、アプリの公開とデータ保存には主に次のサービスを組み合わせることになりました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>GitHub\u003C\u002Fstrong>\u003C\u002Fa>：ソースコードを管理し、Vercel と連携する\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fvercel.com\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>Vercel\u003C\u002Fstrong>\u003C\u002Fa>：アプリを公開し、データの送受信やログインなどの API を動かす\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fneon.com\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>Neon\u003C\u002Fstrong>\u003C\u002Fa>：メンバーや投稿、リアクションなどのデータを保存する\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fcloudinary.com\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>Cloudinary\u003C\u002Fstrong>\u003C\u002Fa>：写真や動画を保存し、サイズや形式の変換、配信を行う\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>GitHubへ変更を反映すると、Vercelを通じてアプリが自動的に更新\u003C\u002Fstrong>されます。\u003Cstrong>投稿された文字情報やリアクションは Neon\u003C\u002Fstrong> へ、\u003Cstrong>写真や生成した動画は Cloudinary へ保存\u003C\u002Fstrong>する構成です。\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fafd12931a8d84c8e90f297cdcfbd60a6\u002Fai-prototype-system-architecture.png\" alt=\"\" width=\"1600\" height=\"830\">\u003C\u002Ffigure>\u003Cp>利用するサービスが決まったあと、各アカウントを作成し、案内を受けながら設定を進めました。\u003Cbr>GitHub と Vercel を連携した公開環境、Neon のデータベース、Cloudinary へ写真を送る API は、壁打ちを担当したエンジニアが構築。\u003Cbr>\u003Cbr>こうして、Claude で機能を追加できる状態から開発を引き継ぎました。\u003C\u002Fp>\u003Ch3 id=\"hdf69f15fb8\">想定される使用量も確認\u003C\u002Fh3>\u003Cp>無料枠で運用できるかを判断するため、Neon のデータ量と Cloudinary の画像保存量を中心に試算してもらいました。\u003C\u002Fp>\u003Cp>想定したのは、参加者 30 人が 1 人 50 枚ずつ投稿する、合計 1,500 枚です。写真をそのままCloudinaryへ保存すると約 6GB になりますが、アップロード時にサイズや画質を調整すれば、\u003Cstrong>1 枚あたり 300〜500KB、全体で最大約 750MB \u003C\u002Fstrong>まで抑えられます。\u003C\u002Fp>\u003Cp>Neon に保存するメンバーや投稿などの文字情報は、約 1 MB を想定しています。今回の人数と利用期間であれば、\u003Cstrong>提案時の無料枠で運用できる見込み\u003C\u002Fstrong>となりました。\u003C\u002Fp>\u003Cp>ただし、Cloudinary では保存容量だけでなく、画像や動画の変換、配信などでもクレジットを消費します。そのため、実装後も利用状況を確認しながら運用することが前提です。\u003Cbr>無料プランの内容や利用条件は変更される場合があります。最新の情報は、\u003Ca href=\"https:\u002F\u002Fneon.com\u002Fdocs\u002Fintroduction\u002Fplans\" target=\"_blank\" rel=\"noopener noreferrer\">Neon\u003C\u002Fa> と \u003Ca href=\"https:\u002F\u002Fcloudinary.com\u002Fpricing\" target=\"_blank\" rel=\"noopener noreferrer\">Cloudinary\u003C\u002Fa> の公式ページをご確認ください。\u003C\u002Fp>\u003Cp>自分では、どのサービスを選び、どう組み合わせれば実現できるのか判断できなかったのが、利用規模や費用を踏まえた構成を提示してもらい、実現可能だと確認できたことが大きな助けになりました。\u003C\u002Fp>\u003Ch2 id=\"h1b99dc3e31\">相談しながら機能を実装\u003C\u002Fh2>\u003Cp>引き継ぎ後は、提案された構成をもとに、引き続き Claude で開発を進めました。\u003C\u002Fp>\u003Cp>初期のプロトタイプでは、サンプルの投稿やメンバー情報を表示していました。これを Neon や Cloudinary、Vercel 上の API とつなぎ、\u003Cstrong>参加者が投稿した写真やリアクションを全員で共有できる状態\u003C\u002Fstrong>へ変えていきます。\u003C\u002Fp>\u003Cp>実装中にエラーが起きたときは、まず Claudeと 試行錯誤。それでも解決できないことや、実装方法を判断できない点は Slack で相談し、必要に応じて Zoom などで画面を共有しました。\u003C\u002Fp>\u003Ch3 id=\"hcabe9ba610\">開発途中で課題と方向を確認\u003C\u002Fh3>\u003Cp>開発が進んだところで、実装できた機能と作業中に出てきた課題を共有しました。\u003C\u002Fp>\u003Cp>この時点では、メンバー情報の変更が反映されない、ローカル環境でログインを確認できない、マップの画像表示に時間がかかるといった問題が発生していました。エンジニアに原因や確認方法を教えてもらい、データベースの扱い方や開発環境の整え方、\u003Ca href=\"https:\u002F\u002Fdevelopers.google.com\u002Fmaps?hl=ja\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>Google Maps API\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> への切り替え\u003C\u002Fstrong>について相談しました。\u003C\u002Fp>\u003Cp>デザインについても、旅行らしい楽しさと画面全体の統一感を両立させる方法を相談。参考画像を使って方向を伝える方法に加えて、\u003Cstrong>色や文字、余白などのルールを Markdown にまとめ、AI への指示に利用する Design.md\u003C\u002Fstrong> についてレクチャーしてもらいました。\u003C\u002Fp>\u003Cp>ここで整理した内容を Claude への指示に落とし込み、マップや通知、動画などの実装を進めました。\u003C\u002Fp>\u003Ch3 id=\"h3826854768\">仮置きのマップをGoogle Mapsへ\u003C\u002Fh3>\u003Cp>開発中のミーティングで整理した内容をもとに、プロトタイプで使っていた無料のマップライブラリから、Google Maps API へ切り替えました。\u003C\u002Fp>\u003Cp>Google Cloud の API キーと Map ID は自分で用意し、教えてもらった設定方法を Claude へ伝えて実装。初回の壁打ちで決めた\u003Cstrong>「実際の地図にイラストのマーカーを配置する」という方針\u003C\u002Fstrong>を、実際の画面へ反映していきました。\u003C\u002Fp>\u003Cp>観光スポットだけでなく、投稿された場所や、位置情報の共有を選んだ参加者もマップ上に表示。完成前のレビューでは、地図を引いたときに近くの投稿をまとめるマーカークラスタリングや、投稿場所を示す写真アイコンの大きさについてもアドバイスを受けました。\u003C\u002Fp>\u003Cp>観光スポットのイラストマーカーは ChatGPT で作成し、Claude を使ってアプリへ組み込んでいます。\u003C\u002Fp>\u003Ch3 id=\"hd32293748f\">通知を送る方法を使い分ける\u003C\u002Fh3>\u003Cp>旅行中に写真を投稿してもらうため、\u003Cstrong>約 1 時間ごとに通知\u003C\u002Fstrong>を送り、通知から投稿画面を開けるようにしました。\u003C\u002Fp>\u003Cp>開発時の Vercel の Hobby プランでは、Cron 機能を利用できる頻度が 1 日 1 回まででした。そこで、\u003Ca href=\"https:\u002F\u002Fcron-job.org\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">投稿を促す通知には外部サービスの cron-job.org\u003C\u002Fa>  を利用し、決まった時間に Vercel 上の通知用 API を呼び出す構成にしています。\u003C\u002Fp>\u003Cp>通知を送る時間は、初日と 2 日目が 9 時から 21 時まで、最終日は 9 時から 17 時まで。無料枠を利用しながら、必要な頻度で通知できる方法を選びました。\u003C\u002Fp>\u003Ch3 id=\"hcb6efaa4d9\">動画生成はClaudeと試行錯誤\u003C\u002Fh3>\u003Cp>もう一つ実装したかったのが、\u003Cstrong>1 日の投稿をまとめた動画\u003C\u002Fstrong>です。\u003Cstrong>Cloudinary の動画変換機能\u003C\u002Fstrong>を使い、投稿された写真をつなぎ合わせてダイジェスト動画を生成しました。\u003C\u002Fp>\u003Cp>単純に写真を順番に並べるのではなく、「みんなの動画」には次のようなルールを設けています。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>同じ時間帯では、同じ人の写真を 1 枚まで使用する\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>同じ時間帯から 1 〜4 枚を選び、複数枚の場合はコラージュにする\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>使用する写真の組み合わせを参加者ごとに変える\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>最後に、その日のベストショットを表示する\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>縦横比の異なる写真をどう配置するのか、コラージュを何枚で構成するのか、写真ごとの表示時間をどうそろえるのか\u003C\u002Fstrong>など、実装には細かな調整が必要でした。動画が表示されない、長さがそろわないといった問題が起きるたびに、状況を Claude へ伝えて修正を繰り返しました。\u003C\u002Fp>\u003Cp>当初は、自分の投稿だけをまとめた「自分の動画」も用意し、参加者が何度でも作り直せる仕様にしていたのですが、動画を生成するたびに Cloudinary のクレジットを消費します。開発中のテストですでに一定量を使用していたこともあり、このままでは旅行中に上限へ達する心配もありました。\u003C\u002Fp>\u003Cp>自分の投稿だけを振り返るより、参加者全員の写真をまとめた方が、別々に行動した時間も含めて\u003Cstrong>「みんなで旅行した」感覚\u003C\u002Fstrong>が伝わります。そこで、「自分の動画」は最終版から外し、「みんなの動画」のみに絞りました。\u003C\u002Fp>\u003Cp>\u003Cstrong>「みんなの動画」は、夜間処理を 1 日 1 回実行して参加者ごとに生成し、翌日に表示\u003C\u002Fstrong>します。一度決まった写真の組み合わせを再利用することで、同じ動画が何度も生成されないようにしました。\u003C\u002Fp>\u003Ch3 id=\"h897e363f98\">完成前にアプリ全体をレビュー\u003C\u002Fh3>\u003Cp>主要な機能がそろった段階で、エンジニアとアートディレクターによる\u003Cstrong>全体レビューを実施\u003C\u002Fstrong>しました。\u003C\u002Fp>\u003Cp>レビューの対象は、機能が想定どおり動くかだけではありません。\u003Cstrong>画面ごとの役割が伝わるか、アプリ全体のトーンが揃っているか\u003C\u002Fstrong>まで確認します。\u003C\u002Fp>\u003Cp>特に見直したのが、\u003Cstrong>ページごとの情報の見せ方\u003C\u002Fstrong>です。投稿画面とメンバー詳細は似た構成になっていたため、それぞれの目的に合わせて分けることに。色の明るさや装飾、文言も整え、必要な機能は残しながら、事務的だった印象をやわらげていきました。\u003C\u002Fp>\u003Cp>レビューによって修正すべき点が明確になり、Claude への指示にも落とし込みやすくなりました。指摘された内容を反映し、修正版を Slack で確認してもらいながら、社員旅行で使う最終版へ仕上げました。\u003C\u002Fp>\u003Ch2 id=\"h47cdf6c7a6\">完成した社員旅行アプリ\u003C\u002Fh2>\u003Cp>こうして、最初はサンプル情報を表示するだけだった 4 つの画面が、\u003Cstrong>参加者全員で使えるアプリ\u003C\u002Fstrong>になりました。\u003Cbr>ブラウザ上で動く Web アプリですが、旅行中は iOS・Android ともにホーム画面へ追加し、\u003Cstrong>アプリアイコンから起動\u003C\u002Fstrong>してもらいました。\u003Cbr>\u003Cbr>最終版は、\u003Cstrong>長崎の海をイメージした青を基調に、イラストやキャラクターを取り入れた明るいデザインで統一\u003C\u002Fstrong>しています。ここからは、完成した各画面と機能を紹介します。\u003C\u002Fp>\u003Ch3 id=\"hd14ad94190\">社員だけが使えるログイン画面\u003C\u002Fh3>\u003Cp>\u003Cstrong>社員共通の合言葉を入力し、参加者一覧から自分の名前を選んでログイン\u003C\u002Fstrong>します。\u003Cbr>合言葉はサーバー側で確認し、一度ログインすると状態が保存されるため、次回からは入力しなくても大丈夫です。\u003C\u002Fp>\u003Cp>ヘッダーには、\u003Cstrong>弊社の公式キャラクター「Sくん」「2ちゃん」「Fさん」\u003C\u002Fstrong>が、眼鏡橋で記念撮影を楽しむ様子を描いたイラストを配置しました。長崎らしい風景と社員旅行の楽しさが伝わるよう、ChatGPT へ構図や修正内容を伝えながら作成したものです。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F87a4953447474bb781362ae4fce11107\u002Flogin.png?w=500&amp;h=750\" alt=\"ログイン画面\" width=\"500\" height=\"750\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>ちなみに初回ログイン時には、通知と位置情報共有について確認します。どちらも任意で、許可しなくてもアプリを利用できます。\u003Cbr>設定はメンバー画面の自分のページから、いつでも変更可能です。\u003C\u002Fp>\u003Ch3 id=\"h3c7140a5ae\">旅行中に必要な情報をまとめたスケジュール画面\u003C\u002Fh3>\u003Cp>\u003Cstrong>この画面を見れば、旅行中に必要な情報をひととおり確認できる\u003C\u002Fstrong>よう、2泊3日の予定を日ごとにまとめました。集合時間や移動予定に加えて、バスや食事の座席表も掲載。座席表は画像を拡大して確認できます。\u003C\u002Fp>\u003Cp>観光スポットの項目を開くと、見どころや公式サイトへのリンクを表示。さらに、端末の日付と時刻に合わせて現在の予定を自動で判定し、\u003Cstrong>進行中の項目がひと目でわかるようにハイライト\u003C\u002Fstrong>しています。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fd7401ede6b5e42fb854e7d8936b333b6\u002Fschedule.png?w=1500&amp;h=1582\" alt=\"スケジュール\" width=\"1500\" height=\"1582\">\u003C\u002Ffigure>\u003Ch3 id=\"hcae8a62685\">写真を投稿して共有\u003C\u002Fh3>\u003Cp>投稿画面では、\u003Cstrong>一度に最大 4 枚の写真を選び、タイトルやコメント、場所を付けて投稿\u003C\u002Fstrong>できます。投稿された写真は投稿時刻に沿って並び、ほかの参加者は\u003Cstrong>絵文字でリアクション\u003C\u002Fstrong>できます。\u003C\u002Fp>\u003Cp>写真には\u003Cstrong>ポラロイドのような白い余白\u003C\u002Fstrong>を設け、\u003Cstrong>壁に貼った写真のように少しずつ角度\u003C\u002Fstrong>を変えて表示。タイトルを付けると、\u003Cstrong>タイトルステッカーとして写真の上に重なります\u003C\u002Fstrong>。一般的な SNS とは少し違う見せ方で、旅の思い出を眺める楽しさを加えています。\u003C\u002Fp>\u003Cp>投稿時には、あらかじめ登録した観光スポットの一覧から場所を選び、写真と紐づけることも可能です。位置情報の共有を許可している場合は、投稿時に取得した位置情報も記録され、関連する写真をマップから確認できます。\u003Cbr>\u003Cbr>\u003Cstrong>その日に最も多くのリアクションを集めた投稿は、ベストショット\u003C\u002Fstrong>に選出されます。\u003Cbr>\u003Cbr>さらに決まった時間に届く通知から投稿画面を開けるほか、投稿ボタンを画面下部に固定し、旅行中でもすぐに写真を共有できるようにしました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F88f0526c70504b89badf298a3ccb7b18\u002Fpost.png?w=4000&amp;h=2571\" alt=\"投稿画面\" width=\"4000\" height=\"2571\">\u003C\u002Ffigure>\u003Ch4 id=\"h207542fc58\">\u003Cbr>\u003Cstrong>1日の旅を動画で振り返る\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>翌朝になると、前日に参加者全員が投稿した写真から、1日を振り返る「みんなの動画」が自動で作られます。\u003C\u002Fp>\u003Cp>動画に使う写真は、1時間ごとに区切って選びます。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>同じ時間帯では、同じ人の写真を1枚まで使用する\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>各時間帯から1〜4枚を選び、複数枚の場合はコラージュにする\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>写真の組み合わせを、動画を見る参加者ごとに変える\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>最後に、その日のベストショットを掲載する\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>全員が同じ動画を見るのではなく、それぞれ少しずつ異なる1日を振り返れる仕組みです。自由行動で別々の場所にいた時間も、参加者全員の写真を通して一つの旅として楽しめるようにしました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F65ac247b5619498db43e38dca1e1109d\u002Fvideo.png?w=4000&amp;h=2354\" alt=\"みんなの動画\" width=\"4000\" height=\"2354\">\u003C\u002Ffigure>\u003Ch3 id=\"h6d4cb5b2d8\">観光スポットと投稿をマップ上で結びつける\u003C\u002Fh3>\u003Cp>マップ画面は、\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>観光スポットを探す\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>投稿された写真を場所から見る\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>位置情報を共有している参加者を確認する\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>といった使い方ができます。\u003C\u002Fp>\u003Cp>2 日目の自由行動に先立って参加者へ行き先を聞き、訪れる可能性のある観光地をあらかじめ登録。それぞれの特徴を取り入れた\u003Cstrong>イラスト\u003C\u002Fstrong>をChatGPTで作り、マーカーとして配置しました。\u003Cbr>実際の地図を使いながらも、旅行アプリらしい楽しさを感じられるようにしています。\u003C\u002Fp>\u003Cp>観光スポットのマーカーを開くと、場所の紹介と、そこに紐づいた投稿をまとめて確認できるほか、スポットを選ばずに投稿した写真も、投稿時に取得した位置情報をもとにカメラアイコンで地図へ反映。近い場所に投稿が集まっている場合は一つのマーカーにまとめ、地図を拡大すると個別に見られます。\u003C\u002Fp>\u003Cp>位置情報を共有している参加者は、本人のアイコンで現在地を確認できます。共有は任意で、自分のページからいつでも切り替えられます。自由行動中でも、ほかの参加者がどこで何をしているのかを、場所と写真の両方から知ることができ、行動を共にしていなくとも\u003Cstrong>みんなで旅行してるような気持ち\u003C\u002Fstrong>になれるようにしました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F8a340711b9c24e4da007d77dfd3ced6e\u002Fmap.png?w=1500&amp;h=1395\" alt=\"マップ画面\" width=\"1500\" height=\"1395\">\u003C\u002Ffigure>\u003Ch3 id=\"h12c1f37458\">メンバーごとに旅の写真を振り返る\u003C\u002Fh3>\u003Cp>メンバー画面では、\u003Cstrong>参加者を投稿数の多い順に並べ、投稿数と上位3名のメダルを掲載\u003C\u002Fstrong>しました。\u003C\u002Fp>\u003Cp>メンバーを選ぶと、その人が投稿した写真が 3 列の\u003Cstrong>グリッド\u003C\u002Fstrong>に並びます。複数枚をまとめた投稿には印を付け、開くと一枚ずつ確認できるようにしました。\u003Cbr>投稿画面が旅全体の出来事を追う場所であるのに対し、メンバー詳細は\u003Cstrong>一人ひとりの視点から旅行を振り返る画面\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>自分のページからは、投稿のタイトルやコメントの編集、写真の削除も可能です。初回に設定した通知と位置情報共有も、ここから変更できます。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F691b94f9996e470ca20954cd1e1ce9a3\u002Fmember.png?w=4000&amp;h=2577\" alt=\"メンバー画面\" width=\"4000\" height=\"2577\">\u003C\u002Ffigure>\u003Ch2 id=\"h93eaa93a02\">社員旅行で実際に使ってみた\u003C\u002Fh2>\u003Cp>完成したアプリは、2 泊 3 日の社員旅行で実際に使用しました。\u003Cstrong>3 日間で投稿された写真は合計 377 枚。初日は 112 枚、自由行動の 2 日目は 218 枚、最終日は 47 枚\u003C\u002Fstrong>でした。最終日は旅行日程そのものが短く、疲れもたまっていたためか、利用は少なめです。\u003C\u002Fp>\u003Cp>最も投稿が集まった 2 日目には、参加者がそれぞれの場所で過ごす様子を写真で共有しました。\u003Cbr>\u003Cstrong>マップを見て近くにいることに気づき、一緒に食事へ行った参加者\u003C\u002Fstrong>もいたようです。\u003Cbr>\u003Cbr>別々に行動していても、写真や場所を通して互いの様子が伝わり、目指していた\u003Cstrong>自由行動中の一体感\u003C\u002Fstrong>につながったと思います。\u003C\u002Fp>\u003Ch3 id=\"hcc66d73f16\">アンケートで好評だったこと\u003C\u002Fh3>\u003Cp>旅行後のアンケートでは、全体として満足度は高く、良かった点として次のような意見が寄せられました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>アプリを開けば、旅行中に必要な情報を確認できる\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>スケジュールがまとまっていて、旅のしおりとして使いやすい\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>自由行動中に、ほかの参加者の様子を写真で見られる\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>投稿へ気軽にリアクションできる\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>1 日の写真を、翌日に動画で振り返れる\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>タイトルやコメントと写真の組み合わせを楽しめる\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>デザインがよく、操作も分かりやすい\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>予定の確認だけでなく、参加者同士で旅の出来事を共有し、あとから振り返るところまで一つのアプリで体験できた点が評価されました。\u003C\u002Fp>\u003Ch3 id=\"hde3fd539b6\">改善点や次回に向けて\u003C\u002Fh3>\u003Cp>一方で、実際に使ったからこそ見えた改善点もあります。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>画面の読み込み：\u003C\u002Fstrong> 投稿画面を開くたびに読み込みが発生するため、キャッシュを保持してほしい\u003C\u002Fli>\u003Cli>\u003Cstrong>写真を共有する場所：\u003C\u002Fstrong> Slackの写真共有チャンネルと役割が重なり、どちらへ投稿するか迷う場面があった\u003C\u002Fli>\u003Cli>\u003Cstrong>投稿画面の見せ方：\u003C\u002Fstrong> 投稿数ランキングやメダルは目的が伝わりにくく、ベストショットを上部に固定したことで、最新の投稿を追いづらい\u003C\u002Fli>\u003C\u002Ful>\u003Cp>また、\u003Cstrong>次回も社員旅行用のアプリを作る場合のアイデア\u003C\u002Fstrong>として、次のような機能が挙がりました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>集合時間の変更などをアプリから一斉に知らせる\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>自由行動の予定や食事の参加者を事前に募集する\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>行きたい場所や買いたいお土産を共有する\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>近くにいる参加者を知らせる\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>アプリ内でチャットする\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>投稿した写真を社内の共有ドライブへ保存する\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>旅行先で使えるARフォトフレームを用意する\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>いずれも参加者から寄せられたアイデアです。\u003Cbr>どれを取り入れるかは未定ですが、今回見つかった改善点とあわせて、今後のアプリづくりに活かしたいと思います。\u003C\u002Fp>\u003Ch2 id=\"hee7b126aff\">AIで作ったプロトタイプを実用化するには\u003C\u002Fh2>\u003Cp>AIを使えば、開発の専門知識がなくても、画面や基本的な動きを備えたプロトタイプを作れます。だからといって、\u003Cstrong>そのまま公開して使えるわけではありません\u003C\u002Fstrong>。\u003C\u002Fp>\u003Cp>Web上にどのように公開するのか。入力されたデータや画像をどこへ保存するのか。バックエンドには何が必要なのか。誰がアクセスできるようにするのか。\u003Cstrong>実用化にあたっては、セキュリティや費用、公開後の運用まで含めて検討\u003C\u002Fstrong>する必要があります。\u003C\u002Fp>\u003Cp>デザインについても、画面を作るだけでなく、それぞれの役割や情報の優先順位、操作の流れを整理し、アプリ全体の見せ方を整えなければなりません。\u003C\u002Fp>\u003Cp>\u003Cstrong>「AIプロトタイプ壁打ち」では、プロトタイプと利用条件を確認しながら、公開・運用までに必要なことを技術とデザインの両面から整理\u003C\u002Fstrong>します。\u003C\u002Fp>\u003Ch3 id=\"hff055326e9\">まだ形になっていなくても相談できます\u003C\u002Fh3>\u003Cul>\u003Cli>\u003Cstrong>AIで試作したものの、次に何をすればよいか分からない\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>作ったものをどのように公開すればよいか分からない\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>データの保存方法やバックエンドの構成に不安がある\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>セキュリティや公開後の運用について確認したい\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>技術的に実現できるのか、費用がどのくらいかかるのか知りたい\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>画面は作れたものの、使いやすさやデザインにまとまりがない\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>要件が固まっていなくても、プロトタイプが途中でも構いません。作りたいものや現在困っていることから、\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\u002Fai-prototype-consultation\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>お気軽にご相談ください。\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\u002Fai-prototype-consultation\u002F\" data-iframely-url=\"https:\u002F\u002Fiframely.net\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fcontact%2Fai-prototype-consultation%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"https:\u002F\u002Fiframely.net\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>","Claude Codeで作った社員旅行用アプリを題材に、新サービス「AIプロトタイプ壁打ち」を社内で検証。技術構成やデザインの相談から、実装、旅行当日の利用、振り返りまでを紹介します。",[130,153,175,194,213,235],{"id":131,"createdAt":132,"updatedAt":133,"publishedAt":134,"revisedAt":133,"title":135,"tag":136,"recommended_articles":146,"eyecatch":147,"heading_list":29,"content2":151,"related_articles":152,"recruit":14,"is_html":14,"is_migration":14},"vacation2024-missions","2024-10-30T17:05:37.788Z","2025-06-12T07:40:58.029Z","2024-11-27T07:40:58.000Z","社員旅行向けの Web アプリを開発してみた",[137,138,139,140,141,143,145],{"id":16},{"id":24},{"id":46},{"id":43},{"id":142},"frontend",{"id":144},"design",{"id":20},[],{"url":148,"height":149,"width":150},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Faac0d1a67524433c8a5670d06077cc7d\u002F%E4%B8%80%E8%A6%A7.png",768,1366,"\u003Ch2 id=\"hd2c91c24e4\">経緯\u003C\u002Fh2>\u003Cp>\u003Cstrong>2024年7月、社員旅行が実施\u003C\u002Fstrong>されることになり、せっかくの機会を\u003Cstrong>広報として活用できないか\u003C\u002Fstrong>と議論を重ねました。\u003C\u002Fp>\u003Ch2 id=\"h0b0d08b338\">企画\u003C\u002Fh2>\u003Cp>真っ先に\u003Cstrong>「何かシステムを作ってみようか？」\u003C\u002Fstrong>という案が浮上。\u003C\u002Fp>\u003Cp>「社員旅行のためだけにシステムを作るなんて大変では？」と思われるかもしれませんが、\u003Cstrong>システム開発は弊社の得意分野\u003C\u002Fstrong>です。\u003Cbr>だからこそイメージも付きやすく、また、利用するユーザー規模が少ないので、いくらでも楽のできる方法も思いつきます\u003Cstrong>。\u003C\u002Fstrong>実は意外と手軽な選択肢でした。\u003C\u002Fp>\u003Cp>システムの方向性を考えた際には、次の点を念頭に置きました。\u003C\u002Fp>\u003Cul>\u003Cli>旅程的に自由時間も多く、ある程度のグループはあるものの基本的にはバラバラに動くこともあり、何もないと社員旅行感が生まれないかも\u003C\u002Fli>\u003Cli>家族参加されるスタッフも多いことから、幅広い年齢層が楽しめる内容が良い\u003C\u002Fli>\u003C\u002Ful>\u003Cp>こうした要素を踏まえて、\u003Cstrong>写真投稿でミッションを達成していく「スタンプラリー」型のSNS\u003C\u002Fstrong>を作成することに決定。\u003Cstrong>2 泊 3 日の社員旅行のためだけに、フルスクラッチでSNSを構築する\u003C\u002Fstrong>ことになりました。\u003C\u002Fp>\u003Ch2 id=\"h4db3ec6501\">設計\u003C\u002Fh2>\u003Ch3 id=\"ha8f355181f\">画面をざっくり洗い出す\u003C\u002Fh3>\u003Cp>言い出しっぺでもある、\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Finterview-3\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>テクニカルディレクターの takano\u003C\u002Fstrong>\u003C\u002Fa> がざっと洗い出しました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Finterview-3\u002F\" data-iframely-url=\"\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fblog%2Finterview-3%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Cp>\u003Cbr>\u003Cstrong>以下は実際のメモ内容です\u003C\u002Fstrong>。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>タイムライン\u003C\u002Fstrong>\u003Cul>\u003Cli>インスタっぽく？TikTokっぽく？\u003C\u002Fli>\u003Cli>「これ以降は既読」が欲しい\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>ミッションリスト\u003C\u002Fstrong>\u003Cul>\u003Cli>すべて\u003C\u002Fli>\u003Cli>達成済み\u003C\u002Fli>\u003Cli>未達成\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>ミッション詳細\u003C\u002Fstrong>\u003Cul>\u003Cli>登録ボタン\u003Cul>\u003Cli>新規\u003C\u002Fli>\u003Cli>追加\u003C\u002Fli>\u003Cli>変更\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>他の人の状況と登録写真\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>メンバーリスト\u003C\u002Fstrong>\u003Cul>\u003Cli>アイコン\u003C\u002Fli>\u003Cli>アカウント名\u003C\u002Fli>\u003Cli>スコア\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>メンバー詳細\u003C\u002Fstrong>\u003Cul>\u003Cli>スコア\u003C\u002Fli>\u003Cli>ミッションの状況と登録写真\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>既視感のあるシステムなので、メモ程度の簡単な整理でも頭の中で全体のイメージができあがりました。\u003Cbr>ここから具体的にシステム設計に進みます。\u003C\u002Fp>\u003Ch3 id=\"h82b60cc132\">実装方針\u003C\u002Fh3>\u003Cp>システムの設計に取り掛かる前に、まずは全体の方向性や構成を考えることから始めました。\u003C\u002Fp>\u003Cp>今回のプロジェクトでは、基本的に takano が一人で全て作り切ることを前提に進めることにしました。\u003Cbr>普段はバックエンドエンジニアとしての業務が中心ですが、Android のネイティブアプリや Flutter を使ったハイブリッドアプリの開発経験もあるため、選択肢は少ないながらもいくつか考えられます。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"h5dc0967264\">\u003Cstrong>フロントエンド\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>\u003Cstrong>ネイティブアプリでは、スタッフにアプリをインストールしてもらう手間が発生\u003C\u002Fstrong>し、手軽に利用してもらえないと判断したため、選択肢から外しました。\u003Cbr>そこで、\u003Cstrong>Webアプリケーションとして開発\u003C\u002Fstrong>する方向に決め、以下の選択肢を検討しました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ca href=\"https:\u002F\u002Fja.react.dev\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>React\u003C\u002Fstrong>\u003C\u002Fa>  \u003Cul>\u003Cli>社内のフロントエンドエンジニアが主に使用しているため、習得すれば今後の業務にも役立つ可能性が高い\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.jetbrains.com\u002Fja-jp\u002Fkotlin-multiplatform\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Kotlin Multiplatform \u003C\u002Fstrong>\u003C\u002Fa>\u003Cul>\u003Cli>Android開発者として馴染みがあり、個人的に興味もある分野\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fflutter.dev\u002Fmulti-platform\u002Fweb\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Flutter on the Web \u003C\u002Fstrong>\u003C\u002Fa>\u003Cul>\u003Cli>これまでネイティブアプリ開発で使ってきた経験があり、Flutter そのものへの好感度が高い\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>ただし、今回のプロジェクトは短期間での完成が求められるため、React の習得には十分な時間が確保できないと判断。また、Kotlin Multiplatform は現時点ではまだ時期尚早だと考え、消去法で \u003Cstrong>Flutter を選択\u003C\u002Fstrong>しました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fflutter.dev\u002Fmulti-platform\u002Fweb\" data-iframely-url=\"\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fflutter.dev%2Fmulti-platform%2Fweb&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Ch4 id=\"ha2cc149486\">\u003Cbr>\u003Cstrong>バックエンド\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>フロントエンドで Flutter を使おうと考えた時点で、バックエンドには自然と \u003Ca href=\"https:\u002F\u002Ffirebase.google.com\u002F?hl=ja\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Firebase\u003C\u002Fstrong>\u003C\u002Fa> を使おうと考えていました。\u003Cbr>\u003Cbr>フロントエンドの実装に注力したかったこともあり、バックエンドの構築に時間をかけられないと判断。また、以前からしっかり Firestore を利用したサービスを作ってみたいという思いもあり、Firebase を採用することにしました(普段は \u003Ca href=\"https:\u002F\u002Faws.amazon.com\u002Fjp\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">AWS\u003C\u002Fa> を使用しているため、\u003Ca href=\"https:\u002F\u002Faws.amazon.com\u002Fjp\u002Flambda\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">Lambda\u003C\u002Fa>、\u003Ca href=\"https:\u002F\u002Faws.amazon.com\u002Fjp\u002Fdynamodb\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">DynamoDB\u003C\u002Fa>、\u003Ca href=\"https:\u002F\u002Faws.amazon.com\u002Fjp\u002Fs3\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">S3\u003C\u002Fa> でも同様に迅速に作成可能だったとは思いますが、今回はあえて Firebase を選びました)。\u003C\u002Fp>\u003Cp>写真投稿機能を提供するにあたり、認証は必須だと考え、\u003Ca href=\"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fauth?hl=ja\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Firebase Authentication\u003C\u002Fstrong>\u003C\u002Fa> を採用。\u003Cbr>データストアには \u003Ca href=\"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Ffirestore?hl=ja\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Cloud Firestore\u003C\u002Fstrong>\u003C\u002Fa> を使用し、データベース設計もメモ書き程度にまとめて構想しました。\u003C\u002Fp>\u003Cp>こちらが実際のメモ内容です。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>ミッション\u003C\u002Fstrong>\u003Cul>\u003Cli>ID\u003C\u002Fli>\u003Cli>タイトル\u003C\u002Fli>\u003Cli>説明文\u003C\u002Fli>\u003Cli>ポイント\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>メンバー\u003C\u002Fstrong>\u003Cul>\u003Cli>ID\u003C\u002Fli>\u003Cli>ステータスとかいる？\u003C\u002Fli>\u003Cli>アカウント名\u003C\u002Fli>\u003Cli>合計ポイント\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>ポスト\u003C\u002Fstrong>\u003Cul>\u003Cli>ID\u003C\u002Fli>\u003Cli>時間\u003C\u002Fli>\u003Cli>メンバーID\u003C\u002Fli>\u003Cli>ミッションID\u003C\u002Fli>\u003Cli>画像 base64 ？ cloud storage 使ってみる？\u003C\u002Fli>\u003Cli>写真コメント\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>洗い出してみることで、データの持ち方が次第にイメージできるようになります。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"he949583e15\">\u003Cstrong>コメント機能の検討\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>\u003Cstrong>「他者の投稿にコメントできた方が良いだろう」「リアクションしたくなる場面があるだろう」\u003C\u002Fstrong>との考えから、コメント機能の実装を検討。しかし、長年の経験から「そこまで手を広げると間に合わないのでは？」という警告が頭をよぎり、\u003Cstrong>既存のシステムを活用する方針\u003C\u002Fstrong>に。\u003C\u002Fp>\u003Cp>弊社では日頃から\u003Cstrong>コミュニケーションツールとして Slack を利用\u003C\u002Fstrong>しており、\u003Cstrong>社員旅行中の連絡にも Slack が想定\u003C\u002Fstrong>されていました。\u003Cbr>\u003Cbr>そこで、\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>写真を投稿すると、 Bot 経由で Slack にも投稿される仕組みを導入し、これを通知機能として活用\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>Slack 上の投稿に対して、リアクションやコメントをつけることで、コメント機能の代替とする\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>これにより、システムの開発範囲を抑えつつ、必要な機能を補完する形で Slack を活用することを決定しました。\u003C\u002Fp>\u003Ch3 id=\"h46fc9b640d\">プロトタイプ開発\u003C\u002Fh3>\u003Cp>概ねの設計が終わったところで、まずはざっとプロトタイプを作成します。\u003C\u002Fp>\u003Cp>今回、このタイミングでプロトタイプを作成した目的は\u003Cstrong>「デザイナーに機能を伝えるため」\u003C\u002Fstrong>でした。\u003Cbr>慣れないワイヤーフレームを書くより、実際に動く形で見せる方が早いと判断したからです。\u003Cbr>\u003Cbr>このタイミングでプロトタイプをなんとなくでも作成しておくことで、以下のようなポイントを洗い出すことができました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>残りの作業量の把握\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>実現が難しい機能の別案検討\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>本実装前に調査が必要な事項の明確化\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>これにより、今後の作業に対する見通しが立ち、安心感を持って進めることができるようになりました。\u003Cbr>\u003Cbr>プロトタイプの仕様としては、UI は Flutter の Widget をそのまま使用し、装飾は一切なし。\u003Cbr>バックエンドはしっかり構築し、 \u003Ca href=\"https:\u002F\u002Friverpod.dev\u002Fja\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Riverpod\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> を使って状態管理を行いながら Firebase と接続\u003C\u002Fstrong>。モックではなく、\u003Cstrong>データ連携が可能な状態になっており、写真の投稿も\u003C\u002Fstrong>\u003Ca href=\"https:\u002F\u002Fcloud.google.com\u002Fstorage?hl=ja\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Cloud Storage\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> に保存して閲覧できるところまでは実装\u003C\u002Fstrong>しました。\u003Cbr>\u003Cbr>このプロトタイプを基に、次にデザインを社内のデザイナーに依頼します。\u003Cbr>ただし、相手も他の案件を抱えており、どの程度の時間がかかるかわからなかったので、ここまではかなり駆け足で進めました。\u003Cstrong>企画立案からプロトタイプ開発完了まで約 2 週間\u003C\u002Fstrong>ほどです。\u003C\u002Fp>\u003Ch3 id=\"hb570a6676d\">デザイン\u003C\u002Fh3>\u003Cp>アプリのデザインは、\u003Cstrong>社内デザイナーの \u003C\u002Fstrong>\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Finterview-5\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>matsue\u003C\u002Fstrong>\u003C\u002Fa> が手掛けました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Finterview-5\u002F\" data-iframely-url=\"\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fblog%2Finterview-5%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Cp>\u003Cbr>社内案件ならではの自由度を活かし、プロトタイプを通じて実際に触れながら、細部まで丁寧に作り上げていきました。デザインには多くの工夫と遊び心が盛り込まれています。\u003Cbr>ここでは、\u003Cstrong>社員旅行アプリに込めた意図やデザインのポイント\u003C\u002Fstrong>についてご紹介します。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"hfa14ac7259\">\u003Cstrong>テーマ\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>\u003Cstrong>今回のテーマは「シンプルで見やすく、そして楽しく！」\u003C\u002Fstrong>。\u003Cbr>\u003Cbr>\u003Cstrong>配色は北海道の自然をイメージ\u003C\u002Fstrong>しました。広がる青空を彷彿とさせる彩度の高い青をメインに、草原を思わせる緑をアクセントカラーに採用。これにより、清々しく爽やかな雰囲気をデザインに取り入れています。\u003Cbr>\u003Cstrong>S2 のブランドカラー(ピンク、黄色、紺、黄緑)では普段使用しない色味をあえて採用し、旅行らしい新鮮さと特別感を演出\u003C\u002Fstrong>しました。\u003Cbr>\u003Cbr>\u003Cstrong>フォント\u003C\u002Fstrong>についても\u003Cstrong>テーマに合わせて選定\u003C\u002Fstrong>しています。\u003Cbr>スケジュール画面では、丸みがあり視認性の高い \u003Ca href=\"https:\u002F\u002Ffonts.google.com\u002Fspecimen\u002FZen+Maru+Gothic\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Zen Maru Gothic\u003C\u002Fstrong>\u003C\u002Fa> を採用し、読みやすさを重視。\u003Cbr>一方で、ミッション画面には遊び心を取り入れるため、ゲームらしい雰囲気が漂う \u003Ca href=\"https:\u002F\u002Ffonts.google.com\u002Fspecimen\u002FDela+Gothic+One\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>Dela Gothic One\u003C\u002Fstrong>\u003C\u002Fa> を使用しました。いずれも日本語対応フォントの中から、テーマに合うユニークな書体を選びました。\u003C\u002Fp>\u003Cp>また、デザインのアクセントとして、\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fs2-character\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>S2 のオリジナルキャラクター\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong>を随所に大胆に使用\u003C\u002Fstrong>しています。社員旅行という遊び心あふれるテーマに合わせ、親しみやすく楽しい雰囲気を感じられる仕上がりになりました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"h6936b451cc\">\u003Cstrong>スケジュール機能\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>当初の構成にはなかった\u003Cstrong>「スケジュール」機能\u003C\u002Fstrong>をデザインに加えました。\u003Cbr>\u003Cbr>北海道出身の社員から目的地や北海道に関する情報を聞き、注意事項や各スポットでできるアクティビティ、場所の簡単な説明などを写真付きで記載しました。次の目的地をイメージしやすいよう構成を工夫しています。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"hfce69b5a73\">\u003Cstrong>ミッション画面\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>社員旅行アプリの\u003Cstrong>目玉の一つが「ミッション機能」\u003C\u002Fstrong>。\u003Cbr>この機能は、\u003Cstrong>参加者が旅行中に様々なアクティビティを楽しみながら写真を投稿し、ミッションを達成することでポイントを獲得できる仕組み\u003C\u002Fstrong>です。\u003Cbr>\u003Cbr>ミッションの目的は、\u003Cstrong>「全員が共有できる体験」を作り出すこと\u003C\u002Fstrong>。例えば、2日目は丸一日自由時間、初日の夜もそれぞれが自由に過ごせる時間があり、個人で行動する場面が多くなる状況でした。そんな中、ミッションを通じて共通の話題や目標を持つことで、一体感を生み出す狙いがあります。\u003Cbr>\u003Cbr>ミッションは、社員旅行前にチームでアイデアを出し合って決定。\u003Cbr>例えば「〇〇の写真を撮る」「地元の名物を食べる」といった課題に加え、社員の写真を撮影するというミッションも加えました。これにより、ポイント獲得だけでなく、\u003Cstrong>自然と社員同士の交流が生まれ、思い出として写真に残る仕組み\u003C\u002Fstrong>を意識しました。\u003Cbr>\u003Cbr>さらに、ポイントを獲得するだけではなく、何度も投稿したくなるよう、投稿そのものが楽しめるデザインを目指しています。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F4d1420c6286c498a85b2cc0e6dc734ce\u002F%E5%AE%8C%E6%88%90-3.png?w=450&amp;h=975\" alt=\"ミッション画面\" width=\"450\" height=\"975\">\u003C\u002Ffigure>\u003Ch2 id=\"h04aefaf859\">開発\u003C\u002Fh2>\u003Ch3 id=\"h5c4db552d5\">UI 開発\u003C\u002Fh3>\u003Cp>デザインも決まったので本格的に実装を進めていきます。\u003Cbr>\u003Cstrong>今回の開発では「デザイナーにあまり負担をかけたくない」という方針を大前提\u003C\u002Fstrong>とし、できるだけ実装側で解決できるよう工夫しました。これにより、デザインの修正や調整にかかる手間を減らしつつ、スムーズな開発を目指しました。\u003C\u002Fp>\u003Cp>基本的には淡々と実装していくのみですが、特に工夫した点や注力した箇所についていくつかご紹介します。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"h8cd10f94c9\">\u003Cstrong>地味に面倒なヘッダー、フッターのカーブ\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fc5adbcc7a69a45ed8c4653019731091e\u002F%E3%82%AB%E3%83%BC%E3%83%96.png?w=250&amp;h=543\" alt=\"カーブ\" width=\"250\" height=\"543\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>\u003Cbr>Figma では Rectangle と Elipse を重ねて書いたようで、私には上手く扱うスキルがありません。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fae6e440113ac487080be4b20c1b3283e\u002F%E9%96%8B%E7%99%BA%E7%94%BB%E9%9D%A2.png?w=650&amp;h=239\" alt=\"開発画面\" width=\"650\" height=\"239\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>\u003C\u002Fp>\u003Cp>「別の方法で描いてもらう」「SVG で書き出してもらう」といった選択肢もありましたが、\u003Cstrong>実装してみること自体が経験になるし、楽しめそう\u003C\u002Fstrong>だと思ったので、コードで書いてみることにしました。\u003C\u002Fp>\u003Cp>\u003Cstrong>ヘッダー\u003C\u002Fstrong>\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-dart\">AppBar(\n    shape: const HeaderAppBarShape(),\n    :\n);\n\nclass HeaderAppBarShape extends ContinuousRectangleBorder {\n  const HeaderAppBarShape();\n  final bottomPadding = 12.0;\n\n  @override\n  Path getOuterPath(Rect rect, {TextDirection? textDirection}) {\n    var path = Path();\n    path.moveTo(0, 0);\n    path.lineTo(0, rect.height - bottomPadding);\n\n    path.quadraticBezierTo(\n        rect.width \u002F 2,\n        rect.height - 50,\n        rect.width,\n        rect.height - bottomPadding\n    );\n    path.lineTo(rect.width, 0);\n    path.lineTo(0, 0);\n    path.close();\n\n    return path;\n  }\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cbr>\u003Cstrong>フッター\u003C\u002Fstrong>\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-dart\">ClipPath(\n    clipper: BottomNavigationBackgroundClipper(),\n    :\n);\n\nclass BottomNavigationBackgroundClipper extends CustomClipper&lt;Path&gt; {\n  final topPadding = 12.0;\n\n  @override\n  getClip(Size size) {\n    var path = Path();\n    path.moveTo(0, topPadding);\n    path.quadraticBezierTo(size.width \u002F 2, 60, size.width, topPadding);\n\n    path.lineTo(size.width, size.height);\n    path.lineTo(0, size.height);\n    path.lineTo(0, topPadding);\n    path.close();\n    return path;\n  }\n\n  @override\n  bool shouldReclip(BottomNavigationBackgroundClipper oldClipper) =&gt; false;\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>改めて見るとかなり雑ですが、これで実現できました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"hc55027b20a\">\u003Cstrong>スケジュール表記\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>よく見かけるタイプのUIですが、いざ実装となるとどう組み立てるか一瞬考えさせられます。\u003Cbr>さらに、スケジュールはギリギリまで変更が入る可能性があるため、\u003Cstrong>変更に対応しやすい形で設計\u003C\u002Fstrong>する必要がありました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F9e133d2e6f544563b1b60581406d639b\u002F%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB.png?w=350&amp;h=458\" alt=\"スケジュール\" width=\"350\" height=\"458\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>よく見ると 9:20～9:30 の間隔と 9:30～10:00 の間隔が違うのでこれも考慮しつつ、MEMO のように長文が入る場合は、デバイスの幅によって高さ(行数)が変化するため、左に走る縦線も右側の要素の高さに合わせて自動で伸びるようにしたいと考えました。\u003C\u002Fp>\u003Cp>こうした点を踏まえ、基本的には \u003Cstrong>Table\u003C\u002Fstrong> を活用しつつ、各パーツを関数化して編集が容易な形で実装を進めました。\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-dart\">Table(\n    defaultColumnWidth: const IntrinsicColumnWidth(),\n    columnWidths: const {\n      2: FlexColumnWidth(1),\n    },\n    children: [\n      scheduleTimeStart(&quot;9:20&quot;, &quot;ホテルのロビーに集合&quot;),\n      scheduleSpacer(24),\n      scheduleTime(&quot;9:30&quot;, &quot;ホテル出発&quot;),\n      scheduleSpacer(40),\n      scheduleTime(&quot;10:00 - 11:00&quot;, &quot;観光２&quot;),\n      scheduleSpacer(24),\n      scheduleContents([\n        scheduleContentTitleWithLink(&quot;場外市場&quot;, &quot;https:\u002F\u002Fwww.jyogaishijyo.com\u002F&quot;),\n        const SizedBox(height: 16),\n        Text(&quot;個性いっぱいの60店舗！&quot;, style: CustomTextStyles.scheduleBody),\n        const SizedBox(height: 32),\n        const ScheduleTag(title: &quot;MEMO&quot;),\n        const SizedBox(height: 16),\n        Text(\n            &quot;&quot;&quot;ツアーというほど時間もないですが海産物を買い漁ったりしてみてください\n食事を狙うのもあり（混み具合をよく見てね）（あとすぐ昼食だよ）&quot;&quot;&quot;,\n            style: CustomTextStyles.scheduleBody,\n        ),\n      ]),\n      scheduleSpacer(40),\n      scheduleTime(&quot;11:30 - 13:15&quot;, &quot;お昼と観光３&quot;),\n      :\n    ],\n);\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cbr>関数の中身は例えばこんな感じです。\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-dart\">TableRow scheduleTime(String time, String title, {RichText? richText}) {\n  return TableRow(\n    children: [\n      TableCell(\n        verticalAlignment: TableCellVerticalAlignment.fill,\n        child: Stack(\n          alignment: Alignment.center,\n          children: [\n            Positioned(\n              top: 0,\n              bottom: 0,\n              child: Container(\n                width: 4,\n                color: CustomColors.scheduleBar,\n              ),\n            ),\n            Positioned(\n              top: 4,\n              child: Container(\n                width: 16,\n                height: 16,\n                decoration: const ShapeDecoration(\n                  color: CustomColors.scheduleDot,\n                  shape: OvalBorder(),\n                ),\n              ),\n            ),\n          ],\n        ),\n      ),\n      const SizedBox(width: 8),\n      Row(\n        crossAxisAlignment: CrossAxisAlignment.start,\n        children: [\n          Text(time, style: CustomTextStyles.scheduleTime),\n          const SizedBox(width: 16),\n          richText ?? Text(title, style: CustomTextStyles.scheduleTimeTitle),\n        ],\n      ),\n    ],\n  );\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"hb7426e2514\">システム開発\u003C\u002Fh3>\u003Ch4 id=\"hc3bd5f627a\">\u003Cstrong>Firestore\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>最終的に、以下のような形で \u003Cstrong>Entity\u003C\u002Fstrong> を定義し、Firestore に保存しています。\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-dart\">\u002F\u002F ミッション情報\nclass Mission {\n  final String id;\n  final String title;    \u002F\u002F 撮影するお題\n  final String category; \u002F\u002F カテゴリー名(&quot;FOOD&quot;, &quot;PLACE&quot; など)\n  final int point;       \u002F\u002F 達成時の獲得ポイント数\n  final int sortKey;     \u002F\u002F 並び替え用のキー\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-dart\">\u002F\u002F メンバー情報\nclass Member {\n  final String id;\n  final String accountName;             \u002F\u002F アカウント名(表示名)\n  final int totalPoint;                 \u002F\u002F 総獲得ポイント数\n  final Map&lt;String, int&gt; categoryPoint; \u002F\u002F 各カテゴリーごとの獲得ポイント数\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>ユーザーアクションによってのみポイントが変動するため、都度集計するのではなく、増減値を直接保持する形にしました。\u003Cbr>\u003Cbr>各カテゴリーごとにランキングを集計して表示するために、\u003Ccode>categoryPoint\u003C\u002Fcode> を設けています。\u003Cbr>\u003Ccode>totalPoint\u003C\u002Fcode> の増減に合わせて \u003Ccode>categoryPoint\u003C\u002Fcode> も編集する設計にしました(後から考えると \u003Ccode>categoryPoint\u003C\u002Fcode> だけで全体のポイントも表現できるため、\u003Ccode>totalPoint\u003C\u002Fcode> は不要だったかもしれません)。\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-dart\">\u002F\u002F メンバーごとのミッション達成状況\ntypedef MemberMission = Map&lt;String, int?&gt;;\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>投稿の削除が可能であり、同じミッションに複数回投稿できる仕様のため、以下の設計を採用しています。\u003C\u002Fp>\u003Cul>\u003Cli>各メンバーごとに、そのミッションに対して\u003Cstrong>何回投稿しているか\u003C\u002Fstrong>をカウント\u003C\u002Fli>\u003Cli>カウントの変化に応じてポイントを増減\u003Cul>\u003Cli>\u003Cstrong>0 ⇨ 1\u003C\u002Fstrong> に変化した際：ポイントを増加\u003C\u002Fli>\u003Cli>\u003Cstrong>1 ⇨ 0\u003C\u002Fstrong> に変化した際：ポイントを減少\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>このカウントは、ミッションの達成状況（フラグ）としても利用\u003C\u002Fli>\u003C\u002Ful>\u003Cpre>\u003Ccode class=\"language-dart\">\u002F\u002F 投稿情報\nclass Post {\n  final String id;\n\n  final String memberId;        \u002F\u002F 投稿したメンバーのID\n  final String accountName;     \u002F\u002F 投稿したメンバーの表示名\n\n  final String missionId;       \u002F\u002F 投稿対象のミッションID\n  final String title;           \u002F\u002F 投稿対象のミッションのお題名\n  final String category;        \u002F\u002F 投稿対象のミッションのカテゴリー名\n  final int point;              \u002F\u002F 投稿対象のミッションの達成時の獲得ポイント\n\n  final DateTime createdAt;     \u002F\u002F 投稿日時（タイムラインでのソートキーになる）\n  final List&lt;PostImage&gt; images; \u002F\u002F 画像の情報\n  final String comment;         \u002F\u002F 画像に対する投稿者のコメント\n  final String? slackTs;        \u002F\u002F 紐づいた Slack の timestamp\n}\n\n\u002F\u002F 投稿画像情報\nclass PostImage {\n  final String mainUrl;         \u002F\u002F メイン画像の公開URL\n  final String thumbnailUrl;    \u002F\u002F サムネイル画像の公開URL\n  final String path;            \u002F\u002F Cloud Storage のパス\n  final int width;              \u002F\u002F 画像の幅\n  final int height;             \u002F\u002F 画像の高さ\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>前半はすべて Mission と Member の値をコピーしています。\u003C\u002Fp>\u003Cp>今回のシステムでは、利用開始後にアカウント名やミッション情報が編集されることはありません。そのため、投稿情報を表示するたびに他のコレクションを参照するよりも、\u003Cstrong>必要なデータをコピーして保持する方が、高速かつシンプル\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>画像データは \u003Cstrong>Cloud Storage\u003C\u002Fstrong> に保存し、以下の工夫を取り入れました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>パフォーマンス最適化\u003C\u002Fstrong>\u003Cbr>ダウンロード用の URL を発行し、投稿データに格納することで、画像取得を効率化\u003C\u002Fli>\u003Cli>\u003Cstrong>認証への配慮\u003C\u002Fstrong>\u003Cbr>認証機能を利用していますが、発行される URL は推測が難しい形式のため、セキュリティ面も問題ないと判断\u003C\u002Fli>\u003C\u002Ful>\u003Cp>さらに、投稿データには \u003Cstrong>width\u003C\u002Fstrong> と \u003Cstrong>height\u003C\u002Fstrong> を保持する設計に。\u003Cbr>画像のアスペクト比を元に、読み込み中のプレースホルダー表示で正確なサイズを確保できます。これにより、画面がガタガタすることなく、スムーズなレイアウトが実現します。\u003C\u002Fp>\u003Cp>\u003Ccode>slackTs\u003C\u002Fcode> は、うっかり投稿すべきでない写真を選択してしまった場合、投稿後に削除しても Slack 上に残る問題が発生する可能性がありました。\u003Cbr>そこで、Slack の投稿時に得られるタイムスタンプを記録し、\u003Cstrong>投稿が削除された際には Slack 上の投稿も連動して削除\u003C\u002Fstrong>するように実装しました。\u003Cbr>\u003Cbr>これらの設計により、投稿の表示速度、画像の読み込み体験、そして Slack 連携の安全性と利便性を高めることができました。\u003C\u002Fp>\u003Cp>ちなみにルールは想像の通りですが、\u003C\u002Fp>\u003Cp>\u003Cstrong>Firestore\u003C\u002Fstrong>\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-javascript\">rules_version = &apos;2&apos;;\n\nservice cloud.firestore {\n  match \u002Fdatabases\u002F{database}\u002Fdocuments {\n  \tfunction requireS2FDomain() {\n  \t\treturn request.auth != null &amp;&amp; request.auth.token.email.matches(&apos;.*@s2factory[.]co[.]jp$&apos;);\n    }\n    \n    match \u002Fmember_mission\u002F{userId} {\n      allow write: if requireS2FDomain() &amp;&amp; request.auth.uid == userId;\n      allow read: if requireS2FDomain();\n    }\n    match \u002Fmembers\u002F{userId} {\n      allow write: if requireS2FDomain() &amp;&amp; request.auth.uid == userId;\n      allow read: if requireS2FDomain();\n    }\n    match \u002Fmissions\u002F{document=**} {\n      allow write: if false;\n      allow read: if requireS2FDomain();\n    }\n    match \u002Fposts\u002F{document=**} {\n      allow update, delete: if requireS2FDomain() &amp;&amp; resource.data.memberId == request.auth.uid;\n      allow read, create: if requireS2FDomain();\n    }\n  }\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Cbr>\u003Cstrong>Storage\u003C\u002Fstrong>\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-javascript\">rules_version = &apos;2&apos;;\n\nservice firebase.storage {\n  match \u002Fb\u002F{bucket}\u002Fo {\n  \tfunction requireS2FDomain() {\n  \t\treturn request.auth != null &amp;&amp; request.auth.token.email.matches(&apos;.*@s2factory[.]co[.]jp$&apos;);\n    }\n    \n    match \u002F{userId}\u002F{allPaths=**} {\n      allow write: if requireS2FDomain() &amp;&amp; request.auth.uid == userId;\n      allow read: if requireS2FDomain();\n    }\n  }\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003Ccode>requireS2FDomain\u003C\u002Fcode> によって、\u003Cstrong>特定ドメインのメールアドレスを持つ認証済みアカウントのみアクセスを許可\u003C\u002Fstrong>。\u003C\u002Fp>\u003Cp>\u003Ca href=\"https:\u002F\u002Fworkspace.google.com\u002Fintl\u002Fja\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">Google Workspace\u003C\u002Fa> を利用して特定のドメインで絞り込む方法も考えられますが、今回は Workspace を使っていない組織でも同様のことが実現できるか試す意図もあり、別の形で実装しました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"h5052bae7d3\">\u003Cstrong>投稿時の処理フロー\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>最も肝となる投稿時の流れは以下の通りです。\u003C\u002Fp>\u003Col>\u003Cli>ログイン状態のチェック\u003C\u002Fli>\u003Cli>写真のアップロード(複数)\u003Col>\u003Cli>画像の幅と高さを取得\u003C\u002Fli>\u003Cli>メインサイズとサムネイルサイズに縮小\u003C\u002Fli>\u003Cli>それぞれ Cloud Storage へアップロード\u003C\u002Fli>\u003Cli>ダウンロードURLの取得\u003C\u002Fli>\u003C\u002Fol>\u003C\u002Fli>\u003Cli>MemberMission を取得し投稿済みかどうかをチェック\u003C\u002Fli>\u003Cli>未投稿であれば Member の totalPoint と categoryPoint を加算\u003C\u002Fli>\u003Cli>MemberMission を更新\u003C\u002Fli>\u003Cli>Post を作成\u003C\u002Fli>\u003C\u002Fol>\u003Cp>処理が重くなりがちな部分には \u003Ccode>Future\u003C\u002Fcode> を使用し、並列化して処理時間を短縮。ユーザーが待てる範囲の速度を維持しました。\u003Cbr>3～6 の Firestore への書き込みはトランザクション処理を利用して一貫性を確保。初めての利用でしたが、実装がシンプルで非常に使いやすいと感じました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Ch4 id=\"h2e856c9f6a\">\u003Cstrong>Slack への投稿\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>Slack への投稿はそれほど難しくありませんが、アクセストークンを付与したリクエストを行う必要があります。\u003Cbr>社内で使うものなので、フロントエンドにアクセストークンを持たせても問題ないのですが、\u003Cstrong>普段からセキュリティには注意を払っているため、たとえ社内向けのアプリでもそれは気持ち悪く感じてしまいます。\u003C\u002Fstrong>\u003Cbr>\u003Cbr>しかし、\u003Cstrong>バックエンドを実装しないというポリシーで開発を進めてきた\u003C\u002Fstrong>ため、アクセストークンをどこに隠蔽するかを検討。\u003Cbr>考えた末、以下のようにプロキシを利用することにしました。\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-shell\"># Slack API\nSetEnvIf Request_URI &quot;^\u002Fslack-notification\u002F&quot; IS_SLACK\nRequestHeader SET host &quot;slack.com&quot; env=IS_SLACK\nRequestHeader SET authorization &quot;Bearer xoxb-*******&quot; env=IS_SLACK\nRewriteRule ^slack-notification\u002F(.*) https:\u002F\u002Fslack.com\u002Fapi\u002F$1 [P,L]\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>社内の認証で保護されたサーバー上で運用しているため、不正なアクセスができない構造になっています。\u003Cbr>この方法でアクセストークンを安全に隠蔽しつつ、Slack への投稿機能を実現しました。\u003C\u002Fp>\u003Ch2 id=\"hde965b176a\">完成\u003C\u002Fh2>\u003Cp>完成したものがこちらです。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fc7b9740bfa854cbdb96fe92a8779cf50\u002F%E5%AE%8C%E6%88%90-1.png?w=450&amp;h=975\" alt=\"スケジュール画面\" width=\"450\" height=\"975\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F4d1420c6286c498a85b2cc0e6dc734ce\u002F%E5%AE%8C%E6%88%90-3.png?w=450&amp;h=975\" alt=\"ミッション\" width=\"450\" height=\"975\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fa4d91f5859e44699b470d67def9420f5\u002F%E5%AE%8C%E6%88%90-4.png?w=450&amp;h=975\" alt=\"ミッション\" width=\"450\" height=\"975\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F448baf19bffb4b59bcc68698921bdea5\u002F%E5%AE%8C%E6%88%90-2.png?w=450&amp;h=975\" alt=\"タイムライン\" width=\"450\" height=\"975\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F71b1da2da1614a95a6ae46c0d4a0c09e\u002F%E5%AE%8C%E6%88%90-5.png?w=450&amp;h=975\" alt=\"メンバー\" width=\"450\" height=\"975\">\u003C\u002Ffigure>\u003Ch2 id=\"ha214098e44\">まとめ\u003C\u002Fh2>\u003Cp>みんな楽しんでくれたようで、\u003Cstrong>評判は上々\u003C\u002Fstrong>でした。 \u003Cbr>\u003Cbr>最終日には、ミッションの獲得ポイントを集計し、\u003Cstrong>上位3名を表彰\u003C\u002Fstrong>。\u003Cstrong>カテゴリーごとのランキングトップと総合得点トップの参加者に景品を授与\u003C\u002Fstrong>し、社員旅行を締めくくりました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Ffec90573c3104638ba5a8a3cf930a1bb\u002F%E6%9C%A8%E5%BD%AB%E3%82%8A%E3%81%AE%E7%86%8A.jpeg?w=650&amp;h=447\" alt=\"賞品の木彫りの熊\" width=\"650\" height=\"447\">\u003Cfigcaption>賞品の木彫りの熊\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003Cbr>サービスは旅行後も残しておき、参加者からは\u003Cstrong>「思い出を振り返ったり、家族に旅行の話をするときに便利だった」\u003C\u002Fstrong>といった声も寄せられました。\u003C\u002Fp>\u003Cp>普段の業務では、利用者の顔が直接見えない場面での開発が多い中、今回は\u003Cstrong>「自分が作ったものを便利に楽しく使ってもらう」というモノづくりの醍醐味を久しぶりに実感\u003C\u002Fstrong>でき、やってよかったと感じています。\u003C\u002Fp>\u003Cp>ちなみに、\u003Cstrong>Google Cloud のインフラ費用は、開発・テスト期間も含めて税込 15 円\u003C\u002Fstrong>(工夫の甲斐あってか、想像以上に安く済みました)。\u003Cbr>一方で、バックエンドを実装しない方針にこだわりすぎた結果、無理をした部分もあり、その影響でいくつかのバグが発生してしまいました。次回は方針を少し緩め、バックエンドを取り入れることも検討しようと思います。\u003Cbr>\u003Cbr>また、自分も参加者として旅行に参加する中で、出先での改修が難しい場面も多く、変更が発生しそうな部分については、\u003Cstrong>あらかじめ CMS を用意しておくべきだったというのが反省\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>今回は、開発スピードを重視し、デザイン以外は一人で手掛けるという制約のもとで進めたため、内容的にはプロダクト品質には程遠いものでしたが、それでも何かの参考になれば幸いです。\u003Cbr>\u003Cbr>\u003Cstrong>また、こうしたアプリの開発に興味がある方やご相談をご希望の方は、ぜひお気軽に\u003C\u002Fstrong>\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>\u003Cu>お問い合わせ\u003C\u002Fu>\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong>ください。私たちが全力でサポートいたします。\u003C\u002Fstrong>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002F\" data-iframely-url=\"\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fcontact&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>",[],{"id":154,"createdAt":155,"updatedAt":156,"publishedAt":157,"revisedAt":156,"title":158,"tag":159,"recommended_articles":168,"eyecatch":169,"heading_list":29,"content2":173,"related_articles":174,"recruit":14,"is_html":14,"is_migration":14},"vacation2024","2024-10-30T17:22:07.115Z","2025-06-12T07:54:13.094Z","2024-11-29T07:40:52.000Z","社員旅行 2024",[160,161,162,164,166],{"id":16},{"id":24},{"id":163},"character",{"id":165},"application",{"id":167},"look-back",[],{"url":170,"height":171,"width":172},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F360670743a444d118b437053c36ddacd\u002Fryo-nagisa-SbZ9uF-830w-unsplash.jpg",3024,4032,"\u003Cp>木枯らしが吹き、冬の足音がすぐそこまで近づいてまいりました。\u003Cbr>寒さが厳しくなる折、どうぞご自愛くださいませ。\u003Cbr>\u003Cbr>\u003Cbr>2024年も、いよいよ終わりが近づいてまいりました。\u003Cbr>様々な出来事があった一年ですが、弊社では昨年に続き、\u003Cstrong>社員旅行を実施\u003C\u002Fstrong>することができました。\u003Cbr>\u003Cstrong>前回は宮古島\u003C\u002Fstrong>でしたが、\u003Cstrong>今年は趣向を変え、雄大な自然と美食を楽しむ「北海道」\u003C\u002Fstrong>へ。\u003Cbr>\u003Cbr>昨年は初めての開催ということもあり、準備段階で苦労した部分も多くありましたが、今回はその反省を活かしてスムーズな計画を目指しました。\u003Cbr>前回との比較や改善点も交えながら、今年の社員旅行を振り返ってみたいと思います。\u003C\u002Fp>\u003Cp>\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fvacation2023\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>前回の社員旅行の様子はこちら。\u003C\u002Fstrong>\u003Cbr>\u003C\u002Fa>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fvacation2023\u002F\" data-iframely-url=\"\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fblog%2Fvacation2023%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Ch2 id=\"h9707d3a59a\">概要\u003C\u002Fh2>\u003Cp>今年の社員旅行は、リフレッシュと交流を目的に\u003Cstrong>北海道・札幌で実施\u003C\u002Fstrong>しました。\u003Cbr>2 泊 3 日の行程には、東京・大阪から総勢約20名以上が参加。今年初参加の新入社員も多く、和気あいあいとした雰囲気でスタートしました。\u003Cbr>\u003Cbr>全体の予定としては、\u003Cstrong>初日と最終日に全員で楽しめるよう簡単なツアー\u003C\u002Fstrong>を取り入れつつ、\u003Cstrong>2 日目は全員自由行動\u003C\u002Fstrong>の時間を設けることで、それぞれが北海道の魅力を満喫できる構成に。\u003Cbr>また、連絡には Slack を使用し、\u003Cstrong>新たな取り組みとして社員旅行専用アプリを導入\u003C\u002Fstrong>。旅行の楽しみをさらに広げる工夫も加えました。\u003C\u002Fp>\u003Ch2 id=\"he6d4e69bd8\">スケジュール\u003C\u002Fh2>\u003Cp>スケジュールは以下の通り。\u003Cbr>1 日目と最終日は、全員で楽しめるアクティビティを中心に計画しました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>1 日目\u003C\u002Fstrong>\u003Cul>\u003Cli>\u003Cstrong>朝\u003C\u002Fstrong>：羽田空港または伊丹空港に集合\u003C\u002Fli>\u003Cli>\u003Cstrong>昼過ぎ\u003C\u002Fstrong>：新千歳空港到着\u003C\u002Fli>\u003Cli>\u003Cstrong>バスツアー開始\u003C\u002Fstrong>：バスガイドさんと合流、ツアー出発\u003Cul>\u003Cli>\u003Cstrong>えこりん村\u003C\u002Fstrong>：昼食バイキング\u003C\u002Fli>\u003Cli>\u003Cstrong>エスコンフィールド\u003C\u002Fstrong>：観光\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>夕方\u003C\u002Fstrong>：ホテル到着、荷物を置いて夕食会場へ\u003C\u002Fli>\u003Cli>\u003Cstrong>夜\u003C\u002Fstrong>：すすきので地元料理を堪能\u003C\u002Fli>\u003Cli>\u003Cstrong>夕食後\u003C\u002Fstrong>：解散、自由行動\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>2 日目\u003C\u002Fstrong>\u003Cul>\u003Cli>\u003Cstrong>完全自由行動\u003C\u002Fstrong>\u003Cul>\u003Cli>それぞれが自由に観光やグルメを楽しむ\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>3 日目\u003C\u002Fstrong>\u003Cul>\u003Cli>\u003Cstrong>朝\u003C\u002Fstrong>：ホテルロビーに集合、各自チェックアウト\u003C\u002Fli>\u003Cli>\u003Cstrong>午前\u003C\u002Fstrong>：バスで場外市場へ\u003Cul>\u003Cli>市場で買い物\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>昼\u003C\u002Fstrong>：サッポロビール園でジンギスカン昼食\u003C\u002Fli>\u003Cli>\u003Cstrong>午後\u003C\u002Fstrong>：新千歳空港へ移動\u003C\u002Fli>\u003Cli>\u003Cstrong>順次\u003C\u002Fstrong>：各自フライトで帰路へ\u003C\u002Fli>\u003Cli>\u003Cstrong>到着後\u003C\u002Fstrong>：自由解散\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>2 日目は完全に自由時間。各自が思い思いの時間を過ごしました。\u003Cbr>\u003Cbr>一人で早朝から出発し、\u003Cstrong>一日かけて札幌と宗谷岬を往復した社員\u003C\u002Fstrong>もいれば、数人でレンタカーを借りて富良野のラベンダー畑を訪れたグループや、温泉でリラックスするグループも。また、市内散策を選び、札幌のカフェや地元グルメを堪能する社員も多く、自由な時間の中でそれぞれが北海道の魅力を満喫していました。\u003Cbr>\u003Cbr>さらに、\u003Ca href=\"https:\u002F\u002Fwww.banei-keiba.or.jp\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">ばんえい競馬\u003C\u002Fa>を観戦しに行った社員や、飛行機を使って函館まで足を伸ばした社員もおり、自由行動ならではの多様な楽しみ方が見られて面白かったです。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F4c9692bd0aa549b48cd7138e512136f1\u002F%E7%A4%BE%E5%93%A1%E6%97%85%E8%A1%8C%E4%BD%8D%E7%BD%AE%E5%85%B1%E6%9C%89.png?w=250&amp;h=556\" alt=\"位置情報共有\" width=\"250\" height=\"556\">\u003C\u002Ffigure>\u003Cp>また、\u003Cstrong>Googleの位置共有機能\u003C\u002Fstrong>を利用し、\u003Cstrong>参加者が北海道中を自由に巡っている様子をリアルタイムで確認\u003C\u002Fstrong>できるように。それぞれが訪れた場所やルートが共有され、北海道の広大さを実感することができました。\u003C\u002Fp>\u003Ch2 id=\"hc135c55324\">社員旅行アプリ\u003C\u002Fh2>\u003Cp>今年の社員旅行では、\u003Cstrong>社員旅行専用のアプリを開発し活用\u003C\u002Fstrong>しました。このアプリは、スケジュールの確認や写真投稿のタイムライン、コメント機能を通じて、情報共有や交流を促進するために作られたものです。その中でも、\u003Cstrong>目玉となったのが「ミッション機能」\u003C\u002Fstrong>でした。\u003C\u002Fp>\u003Ch4 id=\"hbdf1bf3d5d\">\u003Cstrong>アプリの主な機能\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cul>\u003Cli>\u003Cstrong>スケジュール確認\u003C\u002Fstrong>：旅行中の行程や集合場所、時間などをリアルタイムでチェック可能。\u003C\u002Fli>\u003Cli>\u003Cstrong>タイムラインとコメント機能\u003C\u002Fstrong>：社員が写真を投稿し、それにコメントし合うことで、旅行中の交流をオンラインでも広げる仕組み。\u003C\u002Fli>\u003Cli>\u003Cstrong>ミッション機能\u003C\u002Fstrong>：旅行中に設定された課題を達成し、写真投稿や得点を競う仕組み。ミッションの詳細や進捗状況もアプリ内で確認可能。\u003C\u002Fli>\u003Cli>\u003Cstrong>ミッション状況の可視化\u003C\u002Fstrong>：ミッションの得点状況を随時確認でき、参加者間での盛り上がりをサポート。\u003C\u002Fli>\u003C\u002Ful>\u003Cp>このアプリは、スケジュール管理や情報共有をスムーズにするだけでなく、\u003Cstrong>社員間の交流を自然に生み出すツール\u003C\u002Fstrong>として大きな役割を果たしました。\u003Cbr>\u003Cbr>中でもミッション機能は、観光や食事を楽しみながら課題をクリアし、写真を投稿して得点を競う仕組みで、多くの社員が楽しんで参加していました。Slackとはまた違った形でつながりを感じられる点が好評で、旅行全体をさらに盛り上げるきっかけになったと思います。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F4d1420c6286c498a85b2cc0e6dc734ce\u002F%E5%AE%8C%E6%88%90-3.png?w=450&amp;h=975\" alt=\"ミッション\" width=\"450\" height=\"975\">\u003Cfigcaption>食事・場所・キャラ・S2・その他の5つのカテゴリを用意。難易度によって獲得ポイントが変わる。\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003Cbr>\u003Cstrong>最終日には、ミッションの得点状況をもとに表彰が行われ、上位 3 名に木彫りのくまを贈呈\u003C\u002Fstrong>しました。表彰式は、ただの結果発表にとどまらず、旅行を通じて生まれたエピソードをみんなで共有する楽しいひとときにもなりました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Ffec90573c3104638ba5a8a3cf930a1bb\u002F%E6%9C%A8%E5%BD%AB%E3%82%8A%E3%81%AE%E7%86%8A.jpeg?w=650&amp;h=447\" alt=\"木彫りの熊\" width=\"650\" height=\"447\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>このアプリの導入によって、旅行は観光や自由行動だけでなく、\u003Cstrong>全員で共有できる特別な体験\u003C\u002Fstrong>へと進化したのではないでしょうか。\u003Cbr>\u003Cstrong>開発の背景や詳細については、こちらの記事で詳しく解説\u003C\u002Fstrong>しています。ぜひご覧ください。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fvacation2024-missions\u002F\" data-iframely-url=\"\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fblog%2Fvacation2024-missions%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Cp>\u003Cbr>\u003Cstrong>また、こうしたアプリの開発に興味がある方やご相談をご希望の方は、ぜひお気軽に\u003C\u002Fstrong>\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>お問い合わせ\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong>ください。私たちが全力でサポートいたします！\u003Cbr>\u003C\u002Fstrong>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002F\" data-iframely-url=\"\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fcontact&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Ch2 id=\"h767a9b8c78\">昨年との違い\u003C\u002Fh2>\u003Cp>今回の社員旅行は、前回の経験を活かして計画を進めた結果、準備段階からスムーズに進行することができたのではないでしょうか。\u003Cbr>\u003Cbr>\u003Cstrong>前回は、突然 2 ヶ月以内に社員旅行を決行することに\u003C\u002Fstrong>なり、行き先や旅行会社の手配を急ピッチで進める必要がありました。\u003Cbr>そのうえ、\u003Cstrong>参加者全員が「一人一部屋で宿泊」という希望\u003C\u002Fstrong>があり、限られた時間の中で条件を満たす宿泊先を探すのに、非常に難儀したのを覚えています。\u003Cbr>\u003Cbr>なんとか宮古島のリゾートホテルに空きを見つけ、予約にこぎつけましたが、そこに至るまでに多くの時間と労力を要しました。しかし、苦労はそれだけでは終わりません。\u003Cbr>\u003Cbr>さらに、行き先が決まった後も、\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>参加者情報の収集\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>部屋割り\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>食事のアレルギー確認\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>アクティビティの計画\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>レンタカーの手配\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>など、短期間で数多くの準備をこなさなければならず、慌ただしい計画となりました。\u003Cbr>\u003Cbr>今回は、昨年のデータやノウハウを活用したことで、参加者情報の収集や宿泊先の手配がかなり効率化されたと思います。\u003Cbr>また、何と言っても\u003Cstrong>前回はほとんど一人で企画を進めていたような状態\u003C\u002Fstrong>だったため大変でしたが、\u003Cstrong>今年はチームを組み、定期的にミーティングを行いながら役割を分担して進められた\u003C\u002Fstrong>ことが大きな違いでした。この体制のおかげで、昨年よりも負担が軽減され、準備段階からスムーズに進行することができました。\u003C\u002Fp>\u003Ch3 id=\"h5ac8a4307d\">クリアカード\u003C\u002Fh3>\u003Cp>また、\u003Cstrong>去年の宮古島では社員旅行中の記念撮影用にアクリルスタンドを制作\u003C\u002Fstrong>し、スタッフ全員に配りましたが、\u003Cstrong>今年はクリアカード\u003C\u002Fstrong>を作りました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Ff1cdb512bdca4bd99379aa9d2468f88a\u002F%E3%82%AF%E3%83%AA%E3%82%A2%E3%82%AB%E3%83%BC%E3%83%89.jpg?w=650&amp;h=650\" alt=\"クリアカード全 8 種類\" width=\"650\" height=\"650\">\u003Cfigcaption>クリアカード全8種類\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003Cbr>クリアカードは\u003Cstrong>全部で 8 種類\u003C\u002Fstrong>あり、\u003Cstrong>どれが当たるかわからないように銀紙で包装\u003C\u002Fstrong>されてあります。\u003Cbr>スタッフには 3 枚ずつ配布され、写真撮影用として使うだけでなく、社員同士でカードを交換し合うなどの交流のきっかけにもなりました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F4dc76db1c0814e5b8481f04cca9040bc\u002F%E3%82%AF%E3%83%AA%E3%82%A2%E3%82%AB%E3%83%BC%E3%83%89%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9.JPG?w=650&amp;h=650\" alt=\"クリアカードの使い方\" width=\"650\" height=\"650\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fa6009dcda7c54cfb97a8f22c23ec8cf4\u002F%E3%82%B0%E3%83%83%E3%82%BA%E3%82%B3%E3%83%BC%E3%83%8A%E3%83%BC.jpg?w=650&amp;h=514\" alt=\"グッズコーナー\" width=\"650\" height=\"514\">\u003Cfigcaption>社内の一角にあるグッズコーナー。かなりバリエーションが増えてきました。\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Ch2 id=\"ha214098e44\">まとめ\u003C\u002Fh2>\u003Cp>今回の社員旅行は、「リフレッシュ」と「社員間の交流を深める」という目的をしっかりと果たすことができた 2 泊 3 日でした。自由行動が多いスケジュールの中でも、旅行専用アプリやミッション機能を活用することで、社員同士のつながりを感じられる機会が多くありました。\u003C\u002Fp>\u003Cp>\u003Cstrong>弊社では、社員の約 8 割がリモートワーク\u003C\u002Fstrong>をしており、普段は直接顔を合わせる機会が少ない中、今回の旅行は貴重な交流の場となりました。\u003Cbr>参加者からは、\u003Cstrong>「普段話せない社員と交流できた」「久々にリフレッシュできた」\u003C\u002Fstrong>といった感想が寄せられ、特に新入社員にとっては、会社の雰囲気に馴染む良い機会になったようです。\u003C\u002Fp>\u003Cp>また、\u003Cstrong>今回導入した旅行専用アプリは非常に好評\u003C\u002Fstrong>でした。スケジュールや写真投稿のタイムライン、ミッション機能などが旅行中の楽しみを広げるだけでなく、\u003Cstrong>旅行後も閲覧できるようにしたことで、「家族や友人に社員旅行の話をする際に役立った」\u003C\u002Fstrong>といった声も寄せられました。\u003Cbr>\u003Cbr>今後も、このような取り組みを続けながら、旅行に限らず、日々の業務においても新しいチャレンジや発見を積極的に取り入れ、さらに成長できるよう努めていきたいと思います。\u003Cbr>社員旅行で得られた経験が、業務にも前向きな姿勢や新しい発想をもたらしてくれることを期待しています。\u003C\u002Fp>",[],{"id":176,"createdAt":177,"updatedAt":178,"publishedAt":178,"revisedAt":178,"title":179,"tag":180,"recommended_articles":187,"eyecatch":188,"heading_list":14,"content2":192,"related_articles":193,"recruit":29,"is_html":14,"is_migration":14},"vacation2023","2024-03-12T07:44:34.099Z","2025-04-23T06:51:16.526Z","社員旅行に行ってきました！",[181,182,183,184,185],{"id":24},{"id":163},{"id":167},{"id":16},{"id":186},"event",[],{"url":189,"height":190,"width":191},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fb3525caaf6a946109797b5618e5558ef\u002Fvacation2023-1.JPG.png",488,650,"\u003Cp>寒暖定まらぬこの頃ですが、皆様いかがお過ごしでしょうか。\u003Cbr>年度末を控え何かと慌ただしくなりがちですが、どうかご自愛ください。\u003Cbr>\u003Cbr>\u003Cbr>さて、弊社は先日の3月6日で創業18年目を迎えたのですが、なんと昨年、\u003Cstrong>長年の目標であった社員旅行を決行\u003C\u002Fstrong>しました。\u003Cbr>\u003Cstrong>新しいオフィスへの引っ越しと合わせて、新たなスタートを切る良い機会\u003C\u002Fstrong>になったと思います。\u003Cbr>\u003Cbr>\u003Cstrong>行き先は宮古島\u003C\u002Fstrong>。\u003Cbr>太陽の光がきらめき、青い海と白い砂浜が織りなすまさに楽園。\u003Cbr>初めこそ少し雨が降っていましたが、その後はずっと快晴で最高でした。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F58b1b3496ac04da9ae5cc49de822443d\u002FIMG_1960.png\" alt=\"空港\" width=\"650\" height=\"488\">\u003Cfigcaption>空港に到着してすぐは雨が降っていたのですが、すぐに晴れ間が見えました。\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fad32f2725f824ab99e48fd051e331074\u002Fvacation2023-1.JPG\" alt=\"S2旗\" width=\"650\" height=\"488\">\u003Cfigcaption>社員旅行のために作ったS2旗\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fd232e326dcc047cc9fb4bc38c2c1853b\u002F20230826_094430.jpg\" alt=\"海\" width=\"650\" height=\"488\">\u003Cfigcaption>青い空、白い砂浜\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fff7f491f02e74967ba196bdc70bebb44\u002FIMG_2002.png\" alt=\"海とアクスタ\" width=\"650\" height=\"867\">\u003Cfigcaption>アクスタで思い出作り\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Feed17cd3bf4f4adc851fb34bfc6ef76e\u002FIMG_2039.png\" alt=\"夜の海\" width=\"650\" height=\"488\">\u003Cfigcaption>夜の海\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003Cbr>\u003Cstrong>参加人数は総勢28人\u003C\u002Fstrong>。\u003Cbr>\u003Cstrong>夕食以外の時間は基本的に自由行動\u003C\u002Fstrong>とし、数人で島を観光するグループや、レンタカーを借りて一人でドライブする人、ダイビングやカヤック、パラセーリングなどのアクティビティを楽しむ人など、それぞれが自由に過ごしました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F55c3a84b3b2a490a938e8d92bf33991d\u002F20230826_092305.jpg\" alt=\"\" width=\"650\" height=\"488\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fc7f723c8f41841bebc145df1ef446d35\u002F370477365_309873201698295_2329863843918874474_n.jpg?w=650&amp;h=487\" alt=\"パラセーリング\" width=\"650\" height=\"487\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>具体的な行程は以下の通り。\u003Cbr>\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>1日目\u003C\u002Fstrong>\u003Cul>\u003Cli>早朝羽田空港に集合\u003C\u002Fli>\u003Cli>昼過ぎに宮古島到着\u003C\u002Fli>\u003Cli>バスで観光しながらホテルへ移動\u003Cul>\u003Cli>神社\u003C\u002Fli>\u003Cli>ビーチ\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>夕食まで自由行動\u003C\u002Fli>\u003Cli>夕食後自由行動\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>2日目\u003C\u002Fstrong>\u003Cul>\u003Cli>夕食まで自由行動\u003C\u002Fli>\u003Cli>夕食後自由行動\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>3日目\u003C\u002Fstrong>\u003Cul>\u003Cli>お土産タイム\u003C\u002Fli>\u003Cli>バスツアー\u003Cul>\u003Cli>海中公園見学\u003C\u002Fli>\u003Cli>昼食\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>宮古空港から羽田へ\u003C\u002Fli>\u003Cli>解散\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>羽田空港が集合・解散地点でしたが、\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fmigration\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cstrong>全国に散らばるリモート勤務の社員たち\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong>は、それぞれの地域から直接目的地に\u003C\u002Fstrong>集まりました。\u003Cbr>\u003Cbr>2泊3日の社員旅行、後で感想を聞いたところ、\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>とてもいいリフレッシュになった\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>普段できない体験ができた\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>毎年やってほしい\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>というように社員全員、とても満足度が高かったそうなので、実施して本当によかったと思います。\u003Cbr>\u003Cbr>\u003Cbr>実は、\u003Cstrong>社員旅行に行くことが決まってから2ヶ月以内に出発\u003C\u002Fstrong>という、かなり急ピッチで計画を練った裏側などもあり結構大変だったのですが、それはまた別で苦労話と反省として紹介できればと考えています。\u003Cbr>皆様が社員旅行を計画する際には参考になる部分もあると思いますので、ぜひご覧になってみてください。\u003Cstrong>乞うご期待\u003C\u002Fstrong>です。\u003Cbr>\u003Cbr>そしてなんと、去年の評判が良かったので、\u003Cstrong>今年も社員旅行を実施予定\u003C\u002Fstrong>です。\u003Cbr>現在、プロジェクトチームが中心になって計画を立てています。\u003Cbr>\u003Cbr>まだ行き先が確定したわけではありませんが、\u003Cstrong>今年は北海道\u003C\u002Fstrong>に行くつもりです。\u003Cbr>またブログで報告したいと思います！\u003Cbr>\u003C\u002Fp>",[],{"id":49,"createdAt":71,"updatedAt":72,"publishedAt":73,"revisedAt":72,"title":74,"tag":195,"recommended_articles":201,"eyecatch":205,"heading_list":14,"content2":88,"description":89,"related_articles":206,"recruit":14,"cta_url":101,"is_html":14,"is_migration":14},[196,197,198,199,200],{"id":11},{"id":78},{"id":43},{"id":46},{"id":24},[202,203,204],{"id":67},{"id":63},{"id":65},{"url":87,"height":56,"width":57},[207,208,209,210,211,212],{"id":63},{"id":93},{"id":65},{"id":96},{"id":98},{"id":100},{"id":93,"createdAt":214,"updatedAt":215,"publishedAt":216,"revisedAt":215,"title":217,"tag":218,"recommended_articles":228,"eyecatch":229,"heading_list":29,"content2":232,"description":233,"related_articles":234,"recruit":14,"is_html":14,"is_migration":14},"2026-01-16T04:00:35.807Z","2026-05-11T08:28:29.550Z","2026-01-28T07:13:03.163Z","AI エージェントを社内で試して見えてきたこと",[219,220,222,223,224,226],{"id":11},{"id":221},"workshop",{"id":186},{"id":46},{"id":225},"study",{"id":227},"tea",[],{"url":230,"height":119,"width":231},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F1f7ae268ef684c979b3aef3b51d183a4\u002Fevent.jpg",6000,"\u003Cp>2 年間ほぼ毎日同じ時間に同じチョコザップに通い続けているのですが、いろんな人が来なくなりました。\u003C\u002Fp>\u003Cp>この記事は、社内イベント「\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Ftea\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cu>お茶会\u003C\u002Fu>\u003C\u002Fa>」での発表内容をもとにまとめたものです。\u003Cbr>今回は弊社の maya が、\u003Cstrong>社内で実施した「event-ai-agent」\u003C\u002Fstrong>の取り組みをもとに、\u003Cstrong>「AI エージェント」\u003C\u002Fstrong>について話しました。\u003C\u002Fp>\u003Chr>\u003Cp>\u003Cbr>最近、AI の話題の中で\u003Cstrong>「AI エージェント」\u003C\u002Fstrong>という言葉を目にする機会が増えてきました。\u003Cbr>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffeatures\u002Fcopilot?locale=ja\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub Copilot\u003C\u002Fa> のような補完型 AI や \u003Ca href=\"https:\u002F\u002Fchatgpt.com\u002Fja-JP\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">ChatGPT\u003C\u002Fa> のようなチャット型 AI とは異なり、\u003Cstrong>指示を与えると自律的にコードを書き、タスクを進めていくタイプの AI\u003C\u002Fstrong> で、\u003Ca href=\"https:\u002F\u002Fdevin.ai\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">Devin\u003C\u002Fa> や \u003Ca href=\"https:\u002F\u002Fclaude.com\u002Fproduct\u002Foverview\" target=\"_blank\" rel=\"noopener noreferrer\">Claude Code\u003C\u002Fa> などが有名です。\u003C\u002Fp>\u003Cp>こうした AI は、便利そうに感じる一方で、実際にどこまで任せられるのか、どんな場面で使えるのかは、触ってみないと分からない部分が多いのも事実です。\u003C\u002Fp>\u003Cp>S2 には、コードを書くこと自体が好きだったり、自分でやったほうが速いと感じる人が多くいます。また、自社に権利のないデータや取り扱いに注意が必要な情報を扱う仕事が多いこともあり、\u003Cstrong>AI に任せることに対して慎重な感覚\u003C\u002Fstrong>を持っている人も少なくありません。\u003Cbr>\u003Cbr>それでも今後、エージェント型 AI は広まっていくと考えられ、うまく使えれば作業の工数を抑えられる可能性もあります。そこで\u003Cstrong>「社内で AI エージェントをちゃんと使ってみる時間を作れないか」\u003C\u002Fstrong>という話が社内で持ち上がりました。\u003C\u002Fp>\u003Cp>こうして立ち上がったのが、\u003Cstrong>1 か月間にわたって取り組んだ社内企画「event-ai-agent」\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Ch2 id=\"he4fe40370a\">AI エージェントとは\u003C\u002Fh2>\u003Cp>まずは、今回の企画の前提となる AI エージェントについて整理しておきます。\u003Cbr>\u003Cbr>ChatGPT のようなチャット型 AI は、チャットでやり取りした内容に対して、その場で回答を返す AI です。質問に答えたり、相談に応じたりといった使い方が中心になります。\u003C\u002Fp>\u003Cp>対して AI エージェントは、\u003Cstrong>目標を与えると、その達成に向けて自律的に行動する AI \u003C\u002Fstrong>です。人が細かく手順を指示しなくても、状況を判断しながら処理を進め、コードを書いたりシステムに手を入れたりしながら、\u003Cstrong>複数の工程を含むタスクを一連の流れとして完了\u003C\u002Fstrong>させます。\u003C\u002Fp>\u003Cp>AI エージェントの主な特徴は、次のとおりです。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>自律性(Autonomy)\u003C\u002Fstrong>\u003Cbr>人の指示を逐一待たずに、自分で判断して行動できる\u003C\u002Fli>\u003Cli>\u003Cstrong>目標指向(Goal-oriented)\u003C\u002Fstrong>\u003Cbr>与えられた目標を達成するために計画を立てる\u003C\u002Fli>\u003Cli>\u003Cstrong>環境認識(Perception)\u003C\u002Fstrong>\u003Cbr>周囲の状況やデータを認識・理解する\u003C\u002Fli>\u003Cli>\u003Cstrong>行動実行(Action)\u003C\u002Fstrong>\u003Cbr>ツールや API を使って実際に作業を行う\u003C\u002Fli>\u003Cli>\u003Cstrong>学習能力(Learning)\u003C\u002Fstrong>\u003Cbr>経験から学び、振る舞いを改善していく\u003C\u002Fli>\u003C\u002Ful>\u003Ch3 id=\"h0c83bdc0b0\">AI エージェントができること\u003C\u002Fh3>\u003Cp>AI エージェントは、さまざまな役割を担うことができます。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>カスタマーサポートエージェント\u003C\u002Fstrong>\u003Cbr>顧客の質問に対応し、問題解決までを行う\u003C\u002Fli>\u003Cli>\u003Cstrong>データ分析エージェント\u003C\u002Fstrong>\u003Cbr>データを収集・分析し、レポートを作成する\u003C\u002Fli>\u003Cli>\u003Cstrong>コーディングエージェント\u003C\u002Fstrong>\u003Cbr>プログラムを書いたり、バグを修正したりする\u003C\u002Fli>\u003Cli>\u003Cstrong>タスク管理エージェント\u003C\u002Fstrong>\u003Cbr>スケジュールを管理し、リマインダーを送る\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>MCP(Model Context Protocol)\u003C\u002Fstrong> を利用することで、\u003Cstrong>外部のツールやサービスと連携した処理も可能\u003C\u002Fstrong>です。\u003Cbr>例えば、\u003Ca href=\"https:\u002F\u002Fwww.figma.com\u002Fja-jp\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">Figma\u003C\u002Fa> の MCP を読み込ませてデザインデータを参照したり、Gmail と連携してメールを送信したりといったこともできます。\u003C\u002Fp>\u003Ch2 id=\"h7907b76c82\">event-ai-agent\u003C\u002Fh2>\u003Cp>event-ai-agent は、\u003Cstrong>社内で AI エージェントを一定期間実際に使い、その使いどころや制約を確認するために行った取り組み\u003C\u002Fstrong>です。\u003Cbr>個人で断続的に試すのではなく、\u003Cstrong>期間を区切り、参加者同士で状況を共有\u003C\u002Fstrong>しながら進める形にしました。参加は希望制とし、関心のあるメンバーがそれぞれのペースで取り組めるようにしています。\u003C\u002Fp>\u003Cp>概要は以下のとおりです。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>実施期間\u003C\u002Fstrong>：約 1 か月\u003C\u002Fli>\u003Cli>\u003Cstrong>使用ツール\u003C\u002Fstrong>：\u003Ca href=\"https:\u002F\u002Fclaude.ai\u002Flogin\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>Claude Code\u003C\u002Fstrong>\u003C\u002Fa>\u003Cul>\u003Cli>検証は、社内で用意したサンドボックス環境(EC2)上で実施\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>進め方\u003C\u002Fstrong>\u003Cul>\u003Cli>期間中、各自で AI エージェントを使った検証を実施\u003C\u002Fli>\u003Cli>Slack 上の専用チャンネルで、検証内容や気づいたことを随時共有\u003C\u002Fli>\u003Cli>\u003Cstrong>週 1 回・30 分の共有会をオンラインで開催\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>期間内に 1 日、オフラインで集まり集中的に検証\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>オフラインでの集中検証日には、次のレギュレーション\u003C\u002Fstrong>を設けました。\u003C\u002Fp>\u003Cul>\u003Cli>人が行うのは AI エージェントへの指示出しのみ\u003C\u002Fli>\u003Cli>ソースコードを人が直接書くことは禁止\u003C\u002Fli>\u003Cli>指示用のテキストファイル作成は可\u003C\u002Fli>\u003C\u002Ful>\u003Cp>また、本企画で設定していた\u003Cstrong>目的\u003C\u002Fstrong>は次の 3 点です。\u003C\u002Fp>\u003Cul>\u003Cli>エージェント型 AI にふれるきっかけを作る\u003C\u002Fli>\u003Cli>できること・できないことを経験として知る\u003C\u002Fli>\u003Cli>今後の案件に活用できそうな可能性を探る\u003C\u002Fli>\u003C\u002Ful>\u003Ch2 id=\"h55d45458f2\">事例紹介\u003C\u002Fh2>\u003Cp>それでは、期間中に参加者が試してみた事例について紹介します。\u003C\u002Fp>\u003Ch3 id=\"h3b8cb5ca5b\">事例 1：API 仕様書を渡してフロントエンドを作らせてみる\u003C\u002Fh3>\u003Cp>この事例では、\u003Cstrong>AI エージェントにどのような情報を渡せば、どこまでアウトプットできるのか\u003C\u002Fstrong>を意識して試してみました。\u003C\u002Fp>\u003Cp>API 仕様書を入力として渡し、「この仕様をもとにフロントエンドを作ってほしい」と指示しました。AI エージェントに依頼した内容は次のとおりです。\u003C\u002Fp>\u003Cul>\u003Cli>作業用のブランチを作成する  \u003C\u002Fli>\u003Cli>簡単な API を実装する  \u003C\u002Fli>\u003Cli>実装後に動作確認を行う  \u003C\u002Fli>\u003Cli>README を作成する  \u003C\u002Fli>\u003Cli>.gitignore を設定する  \u003C\u002Fli>\u003Cli>成果物を commit し、リポジトリに push する  \u003C\u002Fli>\u003C\u002Ful>\u003Cp>実装手順の分解や、Git 操作を含めた作業はすべて AI エージェントが行っています。\u003Cbr>その結果、生成されたのが下のアプリケーションです。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F706b8cb607f84b058316d5782a0b380b\u002F%E4%BA%8B%E4%BE%8B-1.png?w=1000&amp;h=639\" alt=\"生成されたフロントエンド\" width=\"1000\" height=\"639\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>仕様書という限られた情報からでも、フロントエンドの形を容易に作れることがわかります。\u003C\u002Fp>\u003Ch3 id=\"h1f5ee5b46a\">事例 2：Auth0 のエクスポートデータを変換するプログラム\u003C\u002Fh3>\u003Cp>\u003Cstrong>Auth0 からエクスポートしたデータを ion 形式に変換するプログラム\u003C\u002Fstrong>の作成を AI エージェントに任せました。\u003Cbr>変換処理の実装に加えて、\u003Cstrong>テストデータの作成までまとめて行ってくれた\u003C\u002Fstrong>点は便利に感じられました。\u003Cbr>\u003Cbr>一方で、最初に生成されたプログラムではパフォーマンス面に問題があり、特に処理の中で \u003Ca href=\"https:\u002F\u002Fja.wikipedia.org\u002Fwiki\u002FJq_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E)\" target=\"_blank\" rel=\"noopener noreferrer\">jq\u003C\u002Fa> の呼び出し回数が非常に多い点が気になりました。\u003C\u002Fp>\u003Cp>改善方法を指示することで、より良いプログラムにはなりましたが、\u003Cstrong>現状のまま実案件で使うのは難しそう\u003C\u002Fstrong>に感じてしまいました。\u003C\u002Fp>\u003Ch3 id=\"h69e5e36448\">事例 3：古いメモデータの移行を手伝ってもらう\u003C\u002Fh3>\u003Cp>業務とは直接関係ないものの、日常的に発生しがちな作業として、古いメモデータの移行を AI エージェントに任せてみた事例です。\u003C\u002Fp>\u003Cp>\u003Cstrong>かんたん Markdown 形式で保存していたメモデータを、Markdown ファイルとして整理・変換する作業\u003C\u002Fstrong>を行っています。変換処理はまとめて AI エージェントに指示しました。\u003C\u002Fp>\u003Cp>その結果、\u003Cstrong>全体の大部分は問題なく変換\u003C\u002Fstrong>され、実用上は十分な精度で移行できました。特に、\u003Cstrong>ファイル名の正規化(NFD から NFC への変換)についても、指示だけで対応できた点は印象的\u003C\u002Fstrong>でした。正規化の考え方自体も、この過程で把握することができています。\u003C\u002Fp>\u003Cp>しかし、\u003Cstrong>画像の埋め込み部分については正しくパースできないケース\u003C\u002Fstrong>があり、いくつかのファイルは手動での確認が必要でした。\u003C\u002Fp>\u003Ch3 id=\"h8158e69e7a\">事例 4：積読管理\u003C\u002Fh3>\u003Cp>積読本を管理するための簡単な Web アプリ。\u003Cbr>\u003Cstrong>本棚のように本が並ぶ UI\u003C\u002Fstrong> にしたい、という指示を出したところ、\u003Cstrong>レイアウトや見た目も含めて実装\u003C\u002Fstrong>されています。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F85cc7f4396fd4e29b5c69939d3218942\u002F%E7%A9%8D%E8%AA%AD%E7%AE%A1%E7%90%86.png?w=1000&amp;h=808\" alt=\"積読管理\" width=\"1000\" height=\"808\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>途中一度動かなくなってしまい、その際、AI エージェントがかなりの勢いでソースコード全体を確認し始めたため少し不安になりましたが、2 回ほど修正を重ねることで最終的には正常に動作する状態になりました。\u003C\u002Fp>\u003Ch3 id=\"hab78e183bc\">事例 5：競馬レース予想アプリ\u003C\u002Fh3>\u003Cp>競馬のレース条件を入力すると、AI が予想結果を生成するアプリです。\u003C\u002Fp>\u003Cp>レースの種類や距離、出走頭数を入力し、あわせて各馬の名前を登録したうえで「レースを登録」すると、\u003Cstrong>AI が予想\u003C\u002Fstrong>を行います。\u003Cbr>単勝・複勝といった基本的な馬券に加え、三連単や三連複など、頭数や順序によって成立条件が変わる馬券についても、\u003Cstrong>あらかじめルールを伝えたうえで結果を出す構成\u003C\u002Fstrong>になっています。\u003C\u002Fp>\u003Cp>予想を実行すると、\u003Cstrong>UI 上で馬が走る簡単なアニメーションが表示\u003C\u002Fstrong>され、その後に予想結果が表示されます。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Ff43390b16e574027a75bf6ab2d8c2646\u002F%E4%BA%88%E6%83%B3%E7%94%BB%E9%9D%A2.png?w=1000&amp;h=809\" alt=\"入力と結果画面\" width=\"1000\" height=\"809\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F1a2c9e8778004d0fb0b7f57fe5995b2e\u002F%E3%83%AC%E3%83%BC%E3%82%B9%E4%B8%AD.png?w=1000&amp;h=655\" alt=\"レース中\" width=\"1000\" height=\"655\">\u003C\u002Ffigure>\u003Ch2 id=\"h450f1919de\">オフライン会について\u003C\u002Fh2>\u003Cp>オフライン会では、\u003Cstrong>X を模倣したアプリ\u003C\u002Fstrong>を作る取り組みを行いました。\u003Cbr>やっていいのは \u003Cstrong>AI エージェントへの指示出しのみ\u003C\u002Fstrong>とし、フロントエンド・バックエンドを含むコードはすべて Claude Code に書かせる、というレギュレーションを設けています。\u003C\u002Fp>\u003Cp>参加者それぞれが自分の環境で AI エージェントに指示を出し、完成したものを持ち寄って見せ合いました。\u003Cstrong>一発の指示でどこまで書かせられるかが重要なポイントとなり、細かい修正を重ねるのは難しい\u003C\u002Fstrong>と感じる場面もありました。\u003C\u002Fp>\u003Cp>私が作ったものはこちら。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fe95d1594116a43b6b2d76a0a56c62312\u002F%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E7%94%BB%E9%9D%A2.png?w=1000&amp;h=659\" alt=\"ログイン画面\" width=\"1000\" height=\"659\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F390ced090a264df1b98fecdaa62d38bd\u002F%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%A9%E3%82%A4%E3%83%B3.png?w=1000&amp;h=665\" alt=\"タイムライン\" width=\"1000\" height=\"665\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>ファンタジーなデザインで、と伝えたところ、この見た目になりました。\u003Cbr>投稿や削除に加えて、フォロー・アンフォロー、プロフィール編集、検索機能まで、\u003Cstrong>必要な機能は一通りちゃんと実装\u003C\u002Fstrong>されています。\u003C\u002Fp>\u003Ch2 id=\"h40eb6b6976\">AI エージェントと S2 の今後\u003C\u002Fh2>\u003Cp>今回利用していた \u003Ca href=\"https:\u002F\u002Fclaude.com\u002Fja-jp\u002Fpricing\" target=\"_blank\" rel=\"noopener noreferrer\">Clauded の Max プラン\u003C\u002Fa>については、上限まで使い切る参加者はいませんでした。\u003Cbr>今後は、\u003Cstrong>API キーを各人に発行し、使用量を把握しながら運用していく\u003C\u002Fstrong>つもりです。従量課金ではありますが、事前チャージ制のため、コスト面では比較的管理しやすいと考えています。\u003C\u002Fp>\u003Cp>また、全体向けに AI エージェント利用時の\u003Cstrong>ガイドラインを作成\u003C\u002Fstrong>し、\u003Cstrong>セキュリティや取り扱いのルールを整理\u003C\u002Fstrong>していこうと思っています。\u003C\u002Fp>\u003Ch2 id=\"ha214098e44\">まとめ\u003C\u002Fh2>\u003Cp>event-ai-agent を通して、AI エージェントを実務に近い形で試すことができました。\u003C\u002Fp>\u003Cp>当初は\u003Cstrong>「まずは触ってみるきっかけを作る」ことを主な目的\u003C\u002Fstrong>としていましたが、実際に使ってみる中で、\u003Cstrong>想像以上に実用的\u003C\u002Fstrong>だと感じました。\u003Cbr>\u003Cstrong>定例や共有の場を設けたことで、「どう使っていけそうか」を継続的に話せた点も良かった\u003C\u002Fstrong>と思います。週 1 回の定例後に、Slack チャンネルでのやり取りが活発になる様子も見られました。\u003C\u002Fp>\u003Cp>ですが、できるだけセキュアに使うための環境づくりやガイドライン整備については、思っていた以上に手間がかかることもわかりました。\u003C\u002Fp>\u003Cp>\u003Cstrong>自分でコードを書かなくても、フロントエンドからバックエンドまで含めて、実際に動くものが一通りそろうのは大きな利点\u003C\u002Fstrong>だと感じています。ただし、まったく新しい仕組みを一から作るのは難しそうで、一般的によくある構成やパターンを持つものほど相性が良い、という印象もあります。\u003C\u002Fp>\u003Cp>今回の参加者は普段からプログラミングを書いている人ばかりでしたが、必ずしもそうでない人でも、日本語で指示を整理して伝えることで、さまざまなものが作れる可能性を感じました。\u003C\u002Fp>\u003Cp>今後は、社内でより多くの立場の人にも実際に使ってみてほしいと思っています。\u003C\u002Fp>","AIエージェントを社内で1か月検証した取り組み「event-ai-agent」をもとに、実際に試した事例や、使ってみて見えてきたことをまとめています。",[],{"id":65,"createdAt":236,"updatedAt":237,"publishedAt":238,"revisedAt":237,"title":239,"tag":240,"recommended_articles":246,"eyecatch":247,"heading_list":29,"content2":251,"description":252,"related_articles":253,"recruit":14,"is_html":14,"is_migration":14},"2025-12-01T09:52:57.341Z","2026-05-11T08:30:00.447Z","2025-12-03T08:40:57.702Z","モデルとデータを見直して、Bird Classification の精度を改善した話",[241,242,243,244],{"id":227},{"id":20},{"id":46},{"id":245},"deeplearning",[],{"url":248,"height":249,"width":250},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fbe7e9e0b19c24a2987a7dc6a4429996c\u002F%E3%83%A4%E3%83%9E%E3%82%AC%E3%83%A9.png",1356,2213,"\u003Cp>迷惑メールが多すぎます。\u003C\u002Fp>\u003Cp>この記事は、社内イベント「\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Ftea\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cu>お茶会\u003C\u002Fu>\u003C\u002Fa>」での発表内容をもとにまとめたものです。\u003Cbr>今回は弊社の arakawa が「\u003Cstrong>Bird Classification の精度改善」\u003C\u002Fstrong>について話しました。\u003C\u002Fp>\u003Chr>\u003Cp>\u003Cbr>\u003Cstrong>社内で制作した鳥類分類のデモアプリ\u003C\u002Fstrong>「\u003Ca href=\"https:\u002F\u002Flab.s2factory.co.jp\u002Fbird-classification\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>Bird Classification\u003C\u002Fstrong>\u003C\u002Fa>」の精度を、日頃からちょこちょこ試しています。\u003C\u002Fp>\u003Cp>ある日、ネットで拾った\u003Ca href=\"https:\u002F\u002Fwww.google.com\u002Fsearch?q=%E3%83%A4%E3%83%9E%E3%82%AC%E3%83%A9&amp;oq=%E3%83%A4%E3%83%9E%E3%82%AC%E3%83%A9&amp;gs_lcrp=EgZjaHJvbWUyCQgAEEUYORiABDIGCAEQRRg7MgcIAhAAGIAEMgcIAxAAGIAEMgcIBBAAGIAEMgcIBRAAGIAEMgcIBhAAGIAEMgYIBxBFGDzSAQcyMTNqMGo0qAIAsAIB&amp;sourceid=chrome&amp;ie=UTF-8\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>ヤマガラ\u003C\u002Fstrong>\u003C\u002Fa>の写真を、試しに Bird Classification に読み込ませてみました。\u003Cbr>どう見てもヤマガラの写真だったので当然正しく判定されると思っていたのですが、返ってきた結果はまさかの\u003Ca href=\"https:\u002F\u002Fwww.google.com\u002Fsearch?q=%E3%82%B8%E3%83%A7%E3%82%A6%E3%83%93%E3%82%BF%E3%82%AD&amp;oq=%E3%82%B8%E3%83%A7%E3%82%A6%E3%83%93%E3%82%BF%E3%82%AD&amp;gs_lcrp=EgZjaHJvbWUyDggAEEUYORhDGIAEGIoFMgcIARAAGIAEMgoIAhAAGLEDGIAEMgwIAxAAGEMYgAQYigUyBwgEEAAYgAQyBwgFEAAYgAQyBwgGEAAYgAQyDAgHEAAYQxiABBiKBTIHCAgQABiABDIHCAkQABiABNIBBzMwM2owajmoAgCwAgA&amp;sourceid=chrome&amp;ie=UTF-8\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>ジョウビタキ♂\u003C\u002Fstrong>\u003C\u002Fa>。\u003C\u002Fp>\u003Cp>確かに、角度によってはジョウビタキ(特にオス)もお腹が橙色で、頭部に黒い柄があるので、一部分の特徴だけを捉えると似て見えることもあります。とはいえ、背中の色味や全体のシルエットまで含めて判断すれば、\u003Cstrong>両者は明らかに別の鳥\u003C\u002Fstrong>です。\u003Cbr>\u003Cbr>それを\u003Cstrong>判定できなかったことに、正直ショックを受けました\u003C\u002Fstrong>。\u003Cbr>そして、この事件をきっかけに「\u003Cstrong>どうにかして分類の精度をもっと上げたい\u003C\u002Fstrong>」と思うようになりました。\u003C\u002Fp>\u003Ch2 id=\"hebf6f58cc3\">Bird Classification とは\u003C\u002Fh2>\u003Cp>Bird Classification は、\u003Cstrong>ニューラルネット\u003C\u002Fstrong>を利用した技術検証プロジェクトとして、社内で開発した\u003Cstrong>野鳥画像の分類アプリ\u003C\u002Fstrong>です。\u003Cbr>\u003Cbr>私が個人的に撮影してきた写真の中から、\u003Cstrong>6,310 枚・77 種の画像を学習データ\u003C\u002Fstrong>としており、ブラウザ上で写真をアップロードすることで、鳥の種類を推定することができます。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Ca href=\"https:\u002F\u002Flab.s2factory.co.jp\u002Fbird-classification\u002F\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F57349a3a663e43c6bb5c242d2c7757f2\u002F2021-12-bird-classification.s2factory.co_.jp_.png?w=1200&amp;h=772\" alt=\"Bird Classification\" width=\"1200\" height=\"772\">\u003C\u002Fa>\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F5bed6d9e5c0f4c5490e5cda46ab56403\u002F2021-12-bird-classification.s2factory.co_.jp_-2.png?w=1200&amp;h=715\" alt=\"Bird Classification\" width=\"1200\" height=\"715\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fdbbe98b347b149899d9f6b5643afdb0e\u002F2021-12-bird-classification.s2factory.co_.jp_-3.png?w=1200&amp;h=715\" alt=\"Bird Classification\" width=\"1200\" height=\"715\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>Bird Classification について、詳しくはこちらの記事をご覧ください。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fneural-network-2\u002F\" data-iframely-url=\"https:\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fblog%2Fneural-network-2%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"https:\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Cp>\u003C\u002Fp>\u003Cdiv class=\"iframely-embed\">\u003Cdiv class=\"iframely-responsive\" style=\"height: 140px; padding-bottom: 0;\">\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fbird-classification\u002F\" data-iframely-url=\"https:\u002F\u002Fcdn.iframe.ly\u002Fapi\u002Fiframe?card=small&amp;url=https%3A%2F%2Fwww.s2factory.co.jp%2Fblog%2Fbird-classification%2F&amp;key=c271a3ec77ff4aa44d5948170dd74161\">\u003C\u002Fa>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cscript async src=\"https:\u002F\u002Fcdn.iframe.ly\u002Fembed.js\" charset=\"utf-8\">\u003C\u002Fscript>\u003Ch2 id=\"he15b39bd7e\">ニューラルネットによる画像分類\u003C\u002Fh2>\u003Cp>ニューラルネットの精度を上げる方法を考える前に、まずはニューラルネットによる画像分類がどのように動いているのかを簡単におさらいしておきましょう。\u003C\u002Fp>\u003Cp>\u003Cstrong>ニューラルネット\u003C\u002Fstrong>は、\u003Cstrong>ニューロン\u003C\u002Fstrong>と呼ばれる\u003Cstrong>多入力一出力の非線形関数を、層状に束ねて結線したもの\u003C\u002Fstrong>です。\u003Cbr>ニューロンの内部には\u003Cstrong>重み\u003C\u002Fstrong>と呼ばれるパラメーターがあり、入力値に応じて計算を行い、出力を次のニューロンへ渡していきます。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F78b3fa88d8ae45f3acec469f15962b12\u002F%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%AB%E3%83%8D%E3%83%83%E3%83%88.png?w=650&amp;h=304\" alt=\"ニューラルネット\" width=\"650\" height=\"304\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>ニューロンの結線方法は、やたらに繋げばいいわけではありません。\u003Cbr>\u003Cstrong>層の数や結線の仕方を工夫する必要\u003C\u002Fstrong>があり、こうした\u003Cstrong>構成全体(コンフィギュレーション)をモデル\u003C\u002Fstrong>と呼びます。\u003C\u002Fp>\u003Cp>画像分類の場合は、\u003Cstrong>画像のビットマップデータ(224×224ピクセル)\u003C\u002Fstrong>を入力し、ネットワークの各層を順に通るなかで特徴が取り出されていきます。\u003Cbr>最終的な出力層は、\u003Cstrong>分類対象ごとにニューロンを用意しておき、その中で最も大きい値となったものを判定結果として扱う仕組み\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>ニューラルネットが正しい判定をできるようにするには、\u003Cstrong>学習\u003C\u002Fstrong>が必要です。学習では、\u003Cstrong>データを与えたときの出力と正解との誤差\u003C\u002Fstrong>をもとに、\u003Ca href=\"https:\u002F\u002Fja.wikipedia.org\u002Fwiki\u002F%E3%83%90%E3%83%83%E3%82%AF%E3%83%97%E3%83%AD%E3%83%91%E3%82%B2%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>バックプロパゲーション\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong>というアルゴリズム\u003C\u002Fstrong>で各ニューロンのパラメーター(重み)を修正していきます。\u003Cbr>この更新を繰り返すことで、ネットワークが徐々に正しい出力に近づくようになるのです。\u003C\u002Fp>\u003Ch3 id=\"h37e1cf7a69\">学習のさせ方\u003C\u002Fh3>\u003Cp>ニューラルネットで画像分類を行うときは、まず\u003Cstrong>学習用データの一覧表\u003C\u002Fstrong>を作る必要があります。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F36b1f16f1fea4815858a93f19d65faec\u002F%E4%B8%80%E8%A6%A7%E8%A1%A8.png?w=450&amp;h=455\" alt=\"学習データの一覧表\" width=\"450\" height=\"455\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>この一覧表づくりが意外と手間で、\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>ファイル名\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>正解の種類\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>画像を正方形に切り出すときの位置(中央・左など。今回補助的に入れたもの)\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>といった情報を、ひとつひとつ書いてまとめていきます。\u003Cbr>\u003Cbr>学習に使うデータはすべてを使うのではなく、\u003Cstrong>だいたい 2 割程度を評価用データとして残しておく\u003C\u002Fstrong>のが一般的です。\u003Cbr>ちなみに評価用データは、\u003Cstrong>学習には絶対に使ってはいけません\u003C\u002Fstrong>。これは「学習で見たことがない画像で正しく判断できるか」を確かめるためです。\u003C\u002Fp>\u003Cp>学習の流れはシンプルで、\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>学習用データを使ってニューラルネットのパラメーターを更新\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>1 エポック（学習の1巡）が終わるごとに、評価用データで正答率を計算する\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>これを繰り返します。\u003Cbr>\u003Cstrong>すべてのエポックの中で最も正答率が高かった時点の重みを、最終的な結果\u003C\u002Fstrong>とします。\u003C\u002Fp>\u003Ch3 id=\"h2f4fb49eaa\">実際の学習で見えてきた課題\u003C\u002Fh3>\u003Cp>実際に Bird Classification のデータで学習を回してみると、いくつか気になる点が出てきました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fb93d44943eac44c6b2da667bd38db66a\u002F%E7%94%BB%E5%83%8F%E4%B8%80%E8%A6%A7.png?w=1000&amp;h=568\" alt=\"種類と画像の一覧\" width=\"1000\" height=\"568\">\u003Cfigcaption>種類と画像の一覧\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003Cbr>まず、今回の誤判定の原因になった\u003Cstrong>ヤマガラの学習枚数が 15 枚\u003C\u002Fstrong>しかなかったことです。\u003Cbr>これではさすがに厳しい面もありますが、とはいえ何とかして判定できるようにしたいところ。\u003C\u002Fp>\u003Cp>さらに、全体の\u003Cstrong>6,310枚\u003C\u002Fstrong>という枚数も、画像分類のタスクとしては多いとは言えません。\u003Cbr>少ないデータをなんとか補うために、\u003Cstrong>別のデータセットで事前に学習された重みを使ってスタートするファインチューニング\u003C\u002Fstrong>の手法(少ない枚数でも成果が出やすい方法)をとりましたが、それでも限界がありました。\u003C\u002Fp>\u003Cp>25 エポック学習させた結果、\u003Cstrong>学習用データに対する正答率は順調に上がる\u003C\u002Fstrong>ものの、評価用データの正答率は点線のあたりで頭打ちになり、なかなか伸びていきませんでした。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Ffd98da61a59d4681929002cd9a7c53ca\u002F%E5%AD%A6%E7%BF%92%E7%B5%90%E6%9E%9C.png?w=700&amp;h=463\" alt=\"結果\" width=\"700\" height=\"463\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>これは学習が進むほど、\u003Cstrong>モデルが「写真そのものを覚えてしまっている」状態(過学習)\u003C\u002Fstrong>になってしまい、本来重要である「未知の画像」に対して良い結果が出せなくなっていたためです。\u003C\u002Fp>\u003Ch2 id=\"h15458c1c2e\">精度を上げるには\u003C\u002Fh2>\u003Cp>分類の精度を上げる方法は大きく分けて次の二つが考えられます。\u003C\u002Fp>\u003Col>\u003Cli>\u003Cstrong>学習させるデータを増やす\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>モデルそのものを高性能なものに置き換える\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Fol>\u003Cp>最も確実なのは 1 の「データを増やす」方法ですが、これは撮影・整理・一覧化を含めてとにかく手間がかかります。\u003Cbr>現実的にはかなりしんどく、すぐには対応できません。\u003C\u002Fp>\u003Cp>一方で 2 の「モデルを置き換える」方法は、計算機を動かして学習を回すだけで試せるため、比較的取り組みやすい手段です。\u003C\u002Fp>\u003Cp>今回はこの\u003Cstrong>モデルを高性能なものへ置き換える\u003C\u002Fstrong>アプローチを試してみることにしました。\u003C\u002Fp>\u003Ch3 id=\"he65e60ad85\">試したモデルとその結果\u003C\u002Fh3>\u003Cp>\u003Cstrong>従来の Bird Classification で使っていたモデル\u003C\u002Fstrong> はGoogle が公開している \u003Cstrong>EfficientNet\u003C\u002Fstrong> でした。\u003Cbr>事前学習済みデータとして \u003Cstrong>efficientnet-b7\u003C\u002Fstrong> を使用しており、そのサイズは \u003Cstrong>257,621,231 byte\u003C\u002Fstrong> とかなり大きなモデルです。\u003C\u002Fp>\u003Cp>今回はこの従来モデルの精度を超えることを目標に、\u003Ca href=\"https:\u002F\u002Ftimm.fast.ai\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>timm\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> に登録されているさまざまなモデルを試してみる\u003C\u002Fstrong>ことにしました。timm とは幅広い画像分類モデルがまとまっており、比較検証が非常にしやすいライブラリです。\u003C\u002Fp>\u003Cp>今回試したのは以下のモデルです。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>EfficientNet V2\u003C\u002Fstrong>\u003Cul>\u003Cli>efficientnetv2_rw_m.agc_in1k\u003C\u002Fli>\u003Cli>efficientnetv2_rw_s.ra2_in1k\u003C\u002Fli>\u003Cli>tf_efficientnetv2_l.in21k_ft_in1k\u003C\u002Fli>\u003Cli>tf_efficientnetv2_m.in21k_ft_in1k\u003C\u002Fli>\u003Cli>tf_efficientnetv2_xl.in21k_ft_in1k\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>CoAtNet\u003C\u002Fstrong>\u003Cul>\u003Cli>coatnet_0_rw_224.sw_in1k\u003C\u002Fli>\u003Cli>coatnet_rmlp_2_rw_224.sw_in12k_ft_in1k\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003Cli>\u003Cstrong>MambaOut\u003C\u002Fstrong>\u003Cul>\u003Cli>mambaout_femto.in1k\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>ここ数年は、従来の「\u003Ca href=\"https:\u002F\u002Fja.wikipedia.org\u002Fwiki\u002F%E7%95%B3%E3%81%BF%E8%BE%BC%E3%81%BF%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%AB%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF\" target=\"_blank\" rel=\"noopener noreferrer\">畳み込みニューラルネット(CNN)\u003C\u002Fa>」だけでなく、\u003Ca href=\"https:\u002F\u002Fja.wikipedia.org\u002Fwiki\u002F%E5%A4%A7%E8%A6%8F%E6%A8%A1%E8%A8%80%E8%AA%9E%E3%83%A2%E3%83%87%E3%83%AB\" target=\"_blank\" rel=\"noopener noreferrer\">LLM\u003C\u002Fa> の流れから派生した\u003Cstrong>より大規模なニューラルネット\u003C\u002Fstrong>の性能が非常に高く、\u003Cstrong>その系統に属するのが\u003C\u002Fstrong> \u003Cstrong>CoAtNet\u003C\u002Fstrong> です。\u003Cbr>CoAtNet は\u003Ca href=\"https:\u002F\u002Fja.wikipedia.org\u002Fwiki\u002F%E7%95%B3%E3%81%BF%E8%BE%BC%E3%81%BF\" target=\"_blank\" rel=\"noopener noreferrer\">畳み込み\u003C\u002Fa>と\u003Ca href=\"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FVision_transformer\" target=\"_blank\" rel=\"noopener noreferrer\">ビジョントランスフォーマー\u003C\u002Fa>を組み合わせたハイブリッド構造になっており、今回も大きな期待を持って試しました。\u003C\u002Fp>\u003Cp>しかし、これらのモデルを使っても \u003Cstrong>未知のデータで精度が伸び悩み\u003C\u002Fstrong>、正答率が \u003Cstrong>95% を超えるところまで届かず\u003C\u002Fstrong>。\u003C\u002Fp>\u003Ch3 id=\"hd746411c2a\">もう一度 EfficientNet を試してみることに\u003C\u002Fh3>\u003Cp>そこで、一度原点に戻り\u003Cstrong>EfficientNet を再度試す\u003C\u002Fstrong>方針をとりました。\u003Cbr>ただし今回は、従来とは異なる事前学習データを使っています。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>事前学習データ\u003C\u002Fstrong>：efficientnet_el.ra_in1k\u003C\u002Fli>\u003Cli>\u003Cstrong>モデルサイズ\u003C\u002Fstrong>：従来の約 1\u002F7（37,203,003 byte）\u003C\u002Fli>\u003Cli>\u003Cstrong>入力サイズ\u003C\u002Fstrong>：256×256 pixel\u003C\u002Fli>\u003C\u002Ful>\u003Cp>この構成で学習させたところ、\u003Cstrong>正答率 96.13%\u003C\u002Fstrong> \u003Cstrong>という今までで最高の結果\u003C\u002Fstrong>を得ることができました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F4f6d7114596841f79aaadbc2687c3a0b\u002F%E7%B5%90%E6%9E%9C.png?w=700&amp;h=474\" alt=\"結果\" width=\"700\" height=\"474\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>そして問題の\u003Cstrong>ヤマガラ\u003C\u002Fstrong>を判定してみたところ、今度は\u003Cstrong>しっかり正しく分類できました。\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch3 id=\"h85eea43db3\">もっと精度を上げたい\u003C\u002Fh3>\u003Cp>こうなると欲が出てきます。\u003Cstrong>もっと精度を上げたい\u003C\u002Fstrong>。\u003C\u002Fp>\u003Cp>そこで、2021 年 6 月以降に撮り溜めていた \u003Cstrong>2,281 枚\u003C\u002Fstrong> の写真を使って、\u003Cstrong>“学習データを増やす”\u003C\u002Fstrong> \u003Cstrong>方向で再挑戦\u003C\u002Fstrong>することに。\u003Cbr>追加分すべてにラベル付けを行い、一覧表も作り直しています。\u003Cbr>\u003Cbr>その結果、\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>種類は従来より 11 種増加\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>ヤマガラの枚数は 15 枚 → 29 枚に増加\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fc3aefe7897184cd385739032cb67bf0c\u002F%E4%B8%80%E8%A6%A7%E8%A1%A8%E6%94%B9.png?w=1000&amp;h=605\" alt=\"一覧表追加分\" width=\"1000\" height=\"605\">\u003Cfigcaption>緑色の行が今回追加した部分\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003Cbr>データ量としては十分に増え、「これなら精度も上がるだろう」と期待したのですが、\u003Cstrong>学習させてみると、正答率は 93.03% に下がる結果に。\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>なぜこんなことが起きたのかを考えたところ、「\u003Cstrong>種が増えたせいで、相対的に 1 種類あたりのデータ量が不足したのではないか？\u003C\u002Fstrong>」という可能性が見えてきました。\u003C\u002Fp>\u003Cp>そこで、\u003Cstrong>泣く泣く新しく増やした11種をいったん外し(画像枚数も8,431 枚に)\u003C\u002Fstrong>、従来と同じ種構成に戻して学習をやり直したところ、\u003Cstrong>正答率は 96.8% に到達し、これまでで最高の数字になりました。\u003C\u002Fstrong>\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F93bf4379794949a09afcd30a1f027497\u002F%E6%9C%80%E7%B5%82%E7%9A%84%E3%81%AA%E4%B8%80%E8%A6%A7%E8%A1%A8.png?w=1000&amp;h=544\" alt=\"最終的な一覧表\" width=\"1000\" height=\"544\">\u003C\u002Ffigure>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F05ecf6aefffe4c25b593783379979e0c\u002F%E6%9C%80%E7%B5%82%E7%B5%90%E6%9E%9C.png?w=700&amp;h=469\" alt=\"最終結果\" width=\"700\" height=\"469\">\u003C\u002Ffigure>\u003Ch2 id=\"ha214098e44\">まとめ\u003C\u002Fh2>\u003Cp>今回のアップデートでは、モデルの差し替えやデータ量の調整など、いくつかの検証を重ねながら Bird Classification の精度改善に取り組みました。\u003C\u002Fp>\u003Cp>思ったように精度が伸びないケースもあれば、条件を変えた途端にうまくいく場面もあり、\u003Cstrong>単純に「最新モデルに変えれば精度が上がる」という話でもない\u003C\u002Fstrong>ことが確認できました。\u003C\u002Fp>\u003Cp>また、\u003Cstrong>データを増やしたからといって必ず性能が向上するわけではなく、種数や構成とのバランスが意外と影響する\u003C\u002Fstrong>、という点も今回の作業で改めて実感したところです。\u003C\u002Fp>\u003Cp>最終的には 96% 台まで精度が向上し、課題になっていた種も正しく分類できるようになりましたが、それ以上に、条件を変えながら確かめていく中で、結果が動くポイントがいくつか見えてきました。\u003C\u002Fp>\u003Cp>こうした検証は、Bird Classification に限らず、今後なにか画像分類を試すときにも役に立つはずです。\u003Cbr>条件を少しずつ変えながら試していくプロセス自体に、得られるものが多いことを再確認する機会になりました。\u003C\u002Fp>\u003Cp>引き続き、こうした検証の積み重ねを通して、よりよい仕組みやサービスづくりにつなげていきたいと思います。\u003C\u002Fp>\u003Ch2 id=\"hed1b589b7c\">今回の取り組みが活かせる場面\u003C\u002Fh2>\u003Cp>精度改善のプロセスやモデルは、Bird Classification 以外の場面にも応用できます。\u003C\u002Fp>\u003Cp>たとえば、 \u003Cstrong>弊社の野鳥特化モデル\u003C\u002Fstrong>を使って、\u003Cstrong>Web 上の野鳥図鑑に自動識別の機能を追加するといったことも可能\u003C\u002Fstrong>です。\u003Cbr>また、同程度の学習データが揃えられるのであれば、\u003Cstrong>対象を野鳥以外に置き換えて再学習させることも\u003C\u002Fstrong>できます。\u003C\u002Fp>\u003Cp>一方で、独自モデルをサーバーで運用する場合はインフラコストが発生するため、要件によっては\u003Cstrong>ネイティブアプリ化して\u003C\u002Fstrong>\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fedge-ai\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>エッジ AI\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> で動かす構成\u003C\u002Fstrong>も選択肢に入ります。利用環境や目的に合わせて、最適な動かし方を設計できます。\u003C\u002Fp>\u003Cp>分類機能の導入やモデル活用をご検討の際は、今回得た知見も踏まえてご相談をお受けできますので、まずはお気軽に\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>お問い合わせ\u003C\u002Fstrong>\u003C\u002Fa>ください。\u003C\u002Fp>","野鳥分類アプリ「Bird Classification」の精度改善に向けて、モデル比較やデータ構成の見直しを実施。誤判定の原因分析から、EfficientNet を用いた再学習、学習データ追加による変化まで、実際の検証プロセスをまとめました。",[],"AIプロトタイプ壁打ちのご相談はこちら","AIでプロトタイプを作ったものの、バックエンドやインフラ、セキュリティ、デザインなどに不安がある方へ。要件が固まっていない段階でも、現在困っていることや実現したいことからご相談いただけます。","https:\u002F\u002Fwww.s2factory.co.jp\u002Fcontact\u002Fai-prototype-consultation\u002F",{"contents":258,"totalCount":281,"offset":282,"limit":283},[259,261,271],{"id":32,"eyecatch":260,"publishedAt":35,"createdAt":33,"title":36,"is_html":14,"content2":58},{"url":55,"height":56,"width":57},{"id":262,"eyecatch":263,"publishedAt":267,"createdAt":268,"title":269,"is_html":14,"content2":270},"manhole-card",{"url":264,"height":265,"width":266},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F468c5e350f7c40f7b7a76fd33fa25a5b\u002Fmanhole.png",910,1728,"2026-09-01T06:24:08.870Z","2026-08-26T04:32:26.387Z","マンホールカードとは？見方や集め方、楽しみ方を紹介","\u003Cp>この記事は、社内イベント「\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Ftea\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cu>お茶会\u003C\u002Fu>\u003C\u002Fa>」での発表内容をもとにまとめたものです。\u003Cbr>今回は、弊社の \u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Finterview-3\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">takano\u003C\u002Fa> が「マンホールカード」について発表しました。\u003C\u002Fp>\u003Chr>\u003Cp>\u003C\u002Fp>\u003Cp>本格的なコレクターというわけではありませんが、出かけた先で見つけた\u003Cstrong>マンホールカード\u003C\u002Fstrong>を少しずつ集めています。\u003Cbr>手元のマンホールカードを見ながら、\u003Cstrong>カードの見方や集め方、楽しみ方\u003C\u002Fstrong>を紹介したいと思います。\u003C\u002Fp>\u003Ch2 id=\"hc49a14f474\">ダムや橋を題材にしたインフラカード\u003C\u002Fh2>\u003Cp>全国各地では、ダムや橋、トンネルなどのインフラを題材にしたカードが発行されています。\u003Cbr>これらは総称して「インフラカード」と呼ばれますが、\u003Cstrong>ひとつの団体による統一シリーズではなく、発行元や配布方法はさまざま\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Cp>\u003Cstrong>インフラカードの元祖といえるのが、ダムカード。\u003C\u002Fstrong> 国土交通省と独立行政法人水資源機構が管理するダムで2007年に配布が始まり、その後、題材はさまざまなインフラへ広がっていきました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>ダムカード\u003C\u002Fstrong>：各地のダムを写真やデータとともに紹介\u003C\u002Fli>\u003Cli>\u003Cstrong>橋カード\u003C\u002Fstrong>：橋の構造や特徴、周辺の情報などを掲載\u003C\u002Fli>\u003Cli>\u003Cstrong>トンネルカード\u003C\u002Fstrong>：トンネルの概要や工事の記録などを紹介\u003C\u002Fli>\u003Cli>\u003Cstrong>砂防カード\u003C\u002Fstrong>：砂防堰堤をはじめ、土砂災害から地域を守る施設を紹介\u003C\u002Fli>\u003C\u002Ful>\u003Cp>ダムカードには、\u003Cstrong>周年やイベントに合わせて発行される限定版\u003C\u002Fstrong>もあり、配布終了後には入手しにくい\u003Cstrong>「レアカード」\u003C\u002Fstrong>になることもあります。\u003Cbr>私も最初はダムカードを集めており、記念カードも手に入れました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F2585951c82da42c28ce21be31abbbd4d\u002Fdamcard.jpg?w=600&amp;h=800\" alt=\"ダムカード\" width=\"600\" height=\"800\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>ただ、ダムカードは原則としてダムを訪れた人に、管理事務所や周辺施設で配布されるものです。公共交通では訪れにくい場所もあり、そのぶん手に入れたときの達成感はありますが、そもそもダムを訪れる機会が少なく、なかなか枚数は増えませんでした。\u003C\u002Fp>\u003Cp>そうしているうちに、イベントで\u003Cstrong>マンホールカード\u003C\u002Fstrong>の存在を知り、こちらも集めてみることにしました。\u003C\u002Fp>\u003Ch2 id=\"h7dd9eacda3\">マンホールカードとは\u003C\u002Fh2>\u003Cp>マンホールカードは、\u003Ca href=\"https:\u002F\u002Fwww.gk-p.jp\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>下水道広報プラットホーム(GKP)\u003C\u002Fstrong>\u003C\u002Fa>が企画・監修し、マンホール蓋を管理する地方公共団体と共同で発行しているカードです。デザインマンホールを入口に、\u003Cstrong>下水道の役割や大切さへ関心を持ってもらうことを目的\u003C\u002Fstrong>としています。\u003C\u002Fp>\u003Cp>\u003Cstrong>2016 年 4 月に第 1 弾 30 種が登場し、2026 年 8 月時点で累計 1,311 種類が発行\u003C\u002Fstrong>されています。各自治体が指定する役所や観光案内所、下水道関連施設などで、\u003Cstrong>原則として一人一枚、無料\u003C\u002Fstrong>でもらえます。\u003C\u002Fp>\u003Cp>ダムカードと比べて街中で配布されているものが多く、\u003Cstrong>旅や街歩きのついでに集めやすいのも特徴\u003C\u002Fstrong>です。\u003C\u002Fp>\u003Ch3 id=\"he6c39239dd\">マンホールカードの見方\u003C\u002Fh3>\u003Cp>マンホールカードは全国共通のフォーマットで作られており、\u003Cstrong>表面にはマンホール蓋と設置場所の情報、裏面にはデザインの背景や配布情報\u003C\u002Fstrong>がまとめられています。\u003Cbr>実際のカードを見ながら、記載されている内容を確認してみましょう。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fbc2f52f3f9f24ccebb04f3235face788\u002Fmaehashi.png\" alt=\"前橋市のマンホールカード\" width=\"1000\" height=\"698\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>\u003Cstrong>表面に記載されている情報\u003C\u002Fstrong>\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>マンホール蓋の写真\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>発行した自治体名\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>緯度・経度\u003C\u002Fstrong>：写真のマンホール蓋が実際に設置されている場所\u003C\u002Fli>\u003Cli>\u003Cstrong>ピクトグラム\u003C\u002Fstrong>：自然や歴史、文化など、デザインの題材を表すマーク\u003C\u002Fli>\u003Cli>\u003Cstrong>デザイン管理ナンバーとコレクションナンバー\u003C\u002Fstrong>：自治体やデザインを識別し、カードを整理するための番号\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cbr>\u003Cstrong>裏面に記載されている情報\u003C\u002Fstrong>\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>デザインの由来\u003C\u002Fstrong>：描かれている名所や歴史、文化、特産品などが紹介されている\u003C\u002Fli>\u003Cli>\u003Cstrong>設置開始年\u003C\u002Fstrong>：そのデザインのマンホール蓋が設置され始めた年\u003C\u002Fli>\u003Cli>\u003Cstrong>製造管理ナンバー\u003C\u002Fstrong>：カードの導入年月、修正回数、製造ロットを示す番号。末尾が「001」のものは初期ロット\u003C\u002Fli>\u003Cli>\u003Cstrong>配布場所とQRコード\u003C\u002Fstrong>：カードを受け取れる施設と、自治体の関連ページへアクセスできるQRコード\u003C\u002Fli>\u003C\u002Ful>\u003Cp>初期ロットを目当てに集める楽しみ方もあるそうですが、私は番号にはあまりこだわらず、デザインや訪れた場所との思い出を楽しんでいます。\u003C\u002Fp>\u003Ch2 id=\"h6d76565e2d\">手元のマンホールカードを見てみる\u003C\u002Fh2>\u003Cp>ここからは、私が集めたカードの中から、相模原市と小田原市、北広島市の 3 枚を見てみます。\u003C\u002Fp>\u003Cp>\u003Cbr>\u003Cstrong>相模原市｜はやぶさ2\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>小惑星探査機「\u003Ca href=\"https:\u002F\u002Fwww.hayabusa2.jaxa.jp\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">はやぶさ2\u003C\u002Fa>」を題材にしたカードです。\u003Cstrong>マンホール蓋は淵野辺駅前\u003C\u002Fstrong>にあり、カードはJAXA相模原キャンパスの向かいにある\u003Ca href=\"https:\u002F\u002Fsagamiharacitymuseum.jp\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">相模原市立博物館\u003C\u002Fa>で受け取りました。博物館を訪れた際、たまたま配布されていることを知って手に入れた一枚です。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F4f2a4e90a4b042aaa4f2dab5d2fde7e5\u002Fsagamihara.png\" alt=\"相模原市のマンホールカード\" width=\"1000\" height=\"711\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>\u003Cstrong>小田原市｜小田原城\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>小田原城や城下町の風景が描かれています。実物の\u003Cstrong>マンホール蓋は小田原城址公園内\u003C\u002Fstrong>にあり、カードの配布場所は少し離れた\u003Ca href=\"https:\u002F\u002Fwww.city.odawara.kanagawa.jp\u002Ffield\u002Findustry\u002Furban\u002Fnariwai.html\" target=\"_blank\" rel=\"noopener noreferrer\">小田原宿なりわい交流館\u003C\u002Fa>でした。\u003Cbr>版画のような絵柄が蓋の凹凸で表現されており、イラストをはめ込んだタイプとは違う、マンホールらしいデザインが個人的に気に入っています。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002Fe2454e65c6774014b96a8e5409a4e349\u002Fodawara.png\" alt=\"小田原市のマンホールカード\" width=\"1000\" height=\"705\">\u003C\u002Ffigure>\u003Cp>\u003Cbr>\u003Cstrong>北広島市｜北海道ボールパークFビレッジ\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>北海道ボールパークFビレッジを題材にしたカードです。\u003Cbr>Fビレッジを訪れた際に、施設内の「HUB HOKKAIDO SELECT SHOP」で配布されていることを知り、受け取りました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cfigure>\u003Cimg src=\"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F995729ded86742c8a7ee8e743e248b20\u002Fkitahiroshima.png\" alt=\"北海道北広島市のマンホールカード\" width=\"1000\" height=\"704\">\u003C\u002Ffigure>\u003Ch2 id=\"hfaecbbb682\">マンホールカードの魅力と楽しみ方\u003C\u002Fh2>\u003Cp>デザインマンホールには、名所や特産品、歴史など、その土地を象徴するものが描かれています。アニメやキャラクターを題材にしたものもあり、まさに\u003Cstrong>ご当地感の極み\u003C\u002Fstrong>。\u003Cbr>円形の蓋に地域らしさを落とし込んだ構図や、鋳造の凹凸、彩色も見どころです。\u003C\u002Fp>\u003Cp>最近では、ポケモンが描かれたマンホール蓋「\u003Ca href=\"https:\u002F\u002Flocal.pokemon.jp\u002Fmanhole\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>ポケふた\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong>」\u003C\u002Fstrong>が全国各地に設置されているほか、実在するマンホールを題材にした漫画『\u003Ca href=\"https:\u002F\u002Fwww.shogakukan.co.jp\u002Fbooks\u002F09143565\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>マンホール戦記アオイ\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong>』\u003C\u002Fstrong>も刊行され、楽しみ方はカード以外にも広がっています。\u003C\u002Fp>\u003Cp>カードを集め始めると、出かけた先でも足元のデザインが気になるようになります。街歩きの途中でデザインマンホールを見つけると、少しうれしくなるものです。\u003Cbr>気に入ったデザインや訪れた場所のカードだけでも楽しめるので、出かけた先で配布案内を見かけたら、よかったら集めてみてください。\u003C\u002Fp>",{"id":272,"eyecatch":273,"publishedAt":277,"createdAt":278,"title":279,"is_html":14,"content2":280},"dx-library-puzzle-game",{"url":274,"height":275,"width":276},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002F0eb919b93c74437dbd287ab903d9ea2c\u002F8fe79ab758cb41b6871dee5591cfdbf5\u002Fdx-library-puzzle-game.jpg",1688,3000,"2026-08-13T05:33:03.675Z","2026-08-11T05:15:55.477Z","C++とDXライブラリで落ちものパズルゲームを作っている話","\u003Cp>ハーゲンダッツのCMに出たいです。\u003C\u002Fp>\u003Cp>この記事は、社内イベント「\u003Ca href=\"https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Ftea\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">お茶会\u003C\u002Fa>」での発表内容をもとにまとめたものです。\u003Cbr>今回は、弊社の wataru が、\u003Cstrong>DXライブラリを使って作っている落ちものパズルゲーム\u003C\u002Fstrong>について発表しました。\u003C\u002Fp>\u003Chr>\u003Cp>\u003Cbr>普段はバックエンドのシステム開発をしているのですが、最近は息抜きに、普段あまり触れることのない UI やゲームの実装を試しながら、高校時代に作った落ちものパズルゲームを少しずつ作り直しています。\u003Cbr>というわけで今回は、\u003Cstrong>現在の実装状況をはじめ、DX ライブラリを使った描画・入力処理や、今後試してみたいこと\u003C\u002Fstrong>について紹介したいと思います。\u003C\u002Fp>\u003Ch2 id=\"h0574876bfe\">落ちものパズルゲームを作り直す\u003C\u002Fh2>\u003Cp>高校生の頃、コンピュータ部の出し物として文化祭に展示しようと、\u003Ca href=\"https:\u002F\u002Fja.cppreference.com\u002Fc\" target=\"_blank\" rel=\"noopener noreferrer\">C 言語\u003C\u002Fa>と \u003Ca href=\"https:\u002F\u002Fdxlib.xsrv.jp\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>DX ライブラリ\u003C\u002Fstrong>\u003C\u002Fa>を使って\u003Cstrong>落ちものパズルゲーム\u003C\u002Fstrong>を作り始めました。\u003Cbr>文化祭には間に合わなかったものの、その後も少しずつコードを修正。最終的には、一通り遊べる状態まで完成させました。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cdiv style=\"left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;\">\u003Ciframe src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002Fik9MOwHc4VE?rel=0\" style=\"top: 0; left: 0; width: 100%; height: 100%; position: absolute; border: 0;\" allowfullscreen scrolling=\"no\" allow=\"accelerometer *; clipboard-write *; encrypted-media *; gyroscope *; picture-in-picture *; web-share *;\" referrerpolicy=\"strict-origin\">\u003C\u002Fiframe>\u003C\u002Fdiv>\u003Cp>\u003Cbr>その後は長らく触っていませんでしたが、最近、\u003Cstrong>ブロックの形状や回転状態を以前より整理して定義\u003C\u002Fstrong>できそうだと思い、久しぶりに作り直してみることにしました。\u003Cbr>現在は当時のコードを改修するのではなく、一から書き直しています。\u003C\u002Fp>\u003Ch2 id=\"hb404b0ecc8\">DX ライブラリを使ったゲームの実装\u003C\u002Fh2>\u003Ch3 id=\"hb913cd443e\">現在の実装状況\u003C\u002Fh3>\u003Cp>現在は基本的な操作や処理を実装し、\u003Cstrong>ひとまず遊べる状態\u003C\u002Fstrong>まで進んでいます。\u003C\u002Fp>\u003Cp>実装できているのは、主に次の機能です。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>ピースの移動\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>ピースの回転\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>落下と固定\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>次に出てくるピースの表示\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>まだ作り直し始めたばかりなので、\u003Cstrong>操作中のピースが意図しない形に変わったり、正しく回転しなかったりするバグ\u003C\u002Fstrong>も残っています。\u003Cbr>今は、こうしたバグを直しながら基本動作を整えているところです。\u003Cbr>\u003Cbr>\u003C\u002Fp>\u003Cdiv style=\"left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;\">\u003Ciframe src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002FfelBQ7YJbVc?rel=0\" style=\"top: 0; left: 0; width: 100%; height: 100%; position: absolute; border: 0;\" allowfullscreen scrolling=\"no\" allow=\"accelerometer *; clipboard-write *; encrypted-media *; gyroscope *; picture-in-picture *; web-share *;\" referrerpolicy=\"strict-origin\">\u003C\u002Fiframe>\u003C\u002Fdiv>\u003Ch3 id=\"ha78b91dcfe\">DX ライブラリとは\u003C\u002Fh3>\u003Cp>\u003Ca href=\"https:\u002F\u002Fdxlib.xsrv.jp\u002F\">\u003Cstrong>DX ライブラリ\u003C\u002Fstrong>\u003C\u002Fa>は、\u003Ca href=\"https:\u002F\u002Fja.wikipedia.org\u002Fwiki\u002FMicrosoft_DirectX\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>DirectX\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> や Windows に関する複雑な処理を、比較的簡単な関数で扱えるようにした \u003C\u002Fstrong>\u003Ca href=\"https:\u002F\u002Fja.wikipedia.org\u002Fwiki\u002FC%2B%2B\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cstrong>C++\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> 用のゲームライブラリ\u003C\u002Fstrong>です。C++ 用ではありますが、C 言語の知識を使って開発できます。\u003C\u002Fp>\u003Cp>Windows には、画像や 3DCG、音声などを扱うための DirectX という API 群があります。DirectX の開発キットをそのまま使う場合、さまざまな設定や複雑なコードが必要です。DX ライブラリを利用することで、こうした処理を簡略化し、ゲーム本体の実装に集中しやすくなります。\u003C\u002Fp>\u003Cp>DX ライブラリは 2001 年に公開され、現在も更新が続いています。Windows のほか、Android・iOS 向けのライブラリも配布されており、Nintendo Switch、PlayStation 4、PlayStation Vita にも対応しています。\u003C\u002Fp>\u003Cp>\u003Cspan style=\"color: #838383\">※ 家庭用ゲーム機向けの利用には、各プラットフォームとの契約や「\u003C\u002Fspan>\u003Ca href=\"https:\u002F\u002Fplaydoujin.mediascape.co.jp\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">\u003Cspan style=\"color: #838383\">Play,Doujin!\u003C\u002Fspan>\u003C\u002Fa>\u003Cspan style=\"color: #838383\">」への参加など所定の手続きが必要です。詳しくは、\u003C\u002Fspan>\u003Ca href=\"https:\u002F\u002Fdxlib.xsrv.jp\u002Fdxswitch.html?utm_source=chatgpt.com\" target=\"_new\">\u003Cspan style=\"color: #838383\">こちら\u003C\u002Fspan>\u003C\u002Fa>\u003Cspan style=\"color: #838383\">をご覧ください。\u003C\u002Fspan>\u003C\u002Fp>\u003Cp>扱える機能も幅広く、主なものだけでも次のような機能があります。\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Cth colspan=\"1\" rowspan=\"1\">\u003Cp>分類\u003C\u002Fp>\u003C\u002Fth>\u003Cth colspan=\"1\" rowspan=\"1\">\u003Cp>主な機能\u003C\u002Fp>\u003C\u002Fth>\u003C\u002Ftr>\u003Ctr>\u003Ctd colspan=\"1\" rowspan=\"1\">\u003Cp>描画\u003C\u002Fp>\u003C\u002Ftd>\u003Ctd colspan=\"1\" rowspan=\"1\">\u003Cp>線や図形、画像、文字、3D モデルなどの表示\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd colspan=\"1\" rowspan=\"1\">\u003Cp>画面\u003C\u002Fp>\u003C\u002Ftd>\u003Ctd colspan=\"1\" rowspan=\"1\">\u003Cp>解像度やウィンドウモード、描画先の設定\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd colspan=\"1\" rowspan=\"1\">\u003Cp>入力\u003C\u002Fp>\u003C\u002Ftd>\u003Ctd colspan=\"1\" rowspan=\"1\">\u003Cp>\u003Ccode>GetJoypadInputState\u003C\u002Fcode>を使った、キーボードやゲームパッドの入力状態の取得\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd colspan=\"1\" rowspan=\"1\">\u003Cp>音声・動画\u003C\u002Fp>\u003C\u002Ftd>\u003Ctd colspan=\"1\" rowspan=\"1\">\u003Cp>効果音や BGM、動画の再生\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>公式サイトには、各関数の使い方を確認できる\u003Ca href=\"https:\u002F\u002Fdxlib.xsrv.jp\u002Fdxfunc.html\" target=\"_blank\" rel=\"noopener noreferrer\">関数リファレンス\u003C\u002Fa>や\u003Ca href=\"https:\u002F\u002Fdxlib.xsrv.jp\u002Fdxprogram.html\" target=\"_blank\" rel=\"noopener noreferrer\">サンプルプログラム\u003C\u002Fa>も用意されています。\u003C\u002Fp>\u003Ch3 id=\"h41dffbbfc1\">今回のゲームでの実装\u003C\u002Fh3>\u003Cp>DX ライブラリには多くの機能がありますが、今回のゲームで主に使っているのは、\u003Cstrong>画面表示と入力\u003C\u002Fstrong>に関する機能です。\u003C\u002Fp>\u003Cp>主な処理は次のとおり。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>画面の設定：\u003C\u002Fstrong> \u003Ccode>SetGraphMode\u003C\u002Fcode>で解像度や色数を指定。あわせて、ウィンドウモードで起動するよう設定\u003C\u002Fli>\u003Cli>\u003Cstrong>入力の取得：\u003C\u002Fstrong> キーボードやゲームパッドの入力を受け取り、ピースの操作に利用\u003C\u002Fli>\u003Cli>\u003Cstrong>画像の読み込み：\u003C\u002Fstrong> \u003Ccode>LoadDivGraph\u003C\u002Fcode>で1枚の画像を複数に分割して読み込む\u003C\u002Fli>\u003Cli>\u003Cstrong>画面の更新：\u003C\u002Fstrong> 裏画面に描画した内容を\u003Ccode>ScreenFlip\u003C\u002Fcode>で表画面に反映\u003C\u002Fli>\u003C\u002Ful>\u003Ch4 id=\"h01e5d42029\">\u003Cbr>\u003Cstrong>ブロック画像の読み込みと描画\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>ブロックの描画には、\u003Ccode>LoadDivGraph\u003C\u002Fcode>を使用しています。これは、複数のブロックをまとめた1枚の画像を、指定したサイズと数に分割して読み込むための関数です。\u003C\u002Fp>\u003Cp>分割した画像は、それぞれ\u003Cstrong>グラフィックハンドルと呼ばれる識別子で管理\u003C\u002Fstrong>されます。描画時には現在のピースに対応する画像を指定し、形状データに沿って繰り返し表示することで、画面上にピースを描いています。画像を表示する処理は、各クラスから呼び出す構成です。\u003C\u002Fp>\u003Ch4 id=\"h284fed8d12\">\u003Cbr>\u003Cstrong>裏画面を使ってちらつきを防ぐ\u003C\u002Fstrong>\u003C\u002Fh4>\u003Cp>画面の描画には、\u003Cstrong>ダブルバッファリング\u003C\u002Fstrong>という方法を使っています。\u003C\u002Fp>\u003Cp>まず、\u003Ccode>SetDrawScreen\u003C\u002Fcode>で描画先を裏画面に設定します。必要な描画が終わったところで\u003Ccode>ScreenFlip\u003C\u002Fcode>を実行し、\u003Cstrong>裏画面の内容を表画面へまとめて反映\u003C\u002Fstrong>します。\u003Cbr>この方法によって描画途中の状態が表示されることを防ぎ、画面のちらつきを抑えています。\u003C\u002Fp>\u003Ch3 id=\"h090ff28f5a\">作りながら見直していること\u003C\u002Fh3>\u003Cp>今回は、ピースやフィールドをクラスに分け、\u003Cstrong>データと処理の役割\u003C\u002Fstrong>を意識しながらコードを書いています。\u003Cbr>移動や回転までは比較的スムーズに進みましたが、落下や固定の処理を加えると、次のような部分が複雑になってきました。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>状態判定に使うフラグ\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>クラス間で受け渡す配列データ\u003C\u002Fstrong>\u003C\u002Fli>\u003Cli>\u003Cstrong>ピースのデータを書き換えるタイミング\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>前述のバグも、配列に格納したピースのデータが、どこかで書き換わっていることが原因のようです。\u003Cbr>現在はバグの原因を追いながら、クラスの役割やデータの受け渡し方を少しずつ整理しています。今後の機能も追加しやすい形にしていくつもりです。\u003C\u002Fp>\u003Ch2 id=\"h88738c86b4\">これから追加してみたい機能\u003C\u002Fh2>\u003Cp>まずは、消したライン数に応じてレベルが上がり、落下速度も速くなっていく基本モードを完成させる予定です。\u003Cbr>\u003Cstrong>SE や BGM も追加\u003C\u002Fstrong>したいと考えています。\u003C\u002Fp>\u003Cp>その後は、\u003Cstrong>遊び方の異なる複数のモード\u003C\u002Fstrong>を実装したいと考えています。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>タイムアタック：\u003C\u002Fstrong> 一定のレベルへ到達するまでの時間を計測する\u003C\u002Fli>\u003Cli>\u003Cstrong>対戦：\u003C\u002Fstrong> 1 台の PC で 2 人が同時に遊び、消したラインを相手へ送り合う\u003C\u002Fli>\u003Cli>\u003Cstrong>レース：\u003C\u002Fstrong> 一定のレベルへ先に到達したプレイヤーが勝利する。LAP などのレース要素も検討中\u003C\u002Fli>\u003C\u002Ful>\u003Cp>いずれは\u003Cstrong>ネットワーク対戦\u003C\u002Fstrong>にも挑戦してみたいと思っています。リアルタイムで進行するゲームでは\u003Cstrong>通信の遅延が発生するため、それを目立たせない方法\u003C\u002Fstrong>も考えてみたいところです。\u003C\u002Fp>\u003Cp>さらに余裕があれば、\u003Cstrong>ブラウザや Linux でも動かせるように\u003C\u002Fstrong>してみたいです。別の環境へ展開するには、ゲームの進行を管理するロジックと、画面の描画や入力を処理する部分を分けておかなければなりません。\u003C\u002Fp>\u003Cp>まずは Windows 版を作りながら、ピースのデータ構造や状態の持たせ方を整理し、ほかの環境にも移しやすい形にしていく予定です。\u003C\u002Fp>\u003Ch2 id=\"ha214098e44\">まとめ\u003C\u002Fh2>\u003Cp>今回は、空いた時間に少しずつ作っている落ちものパズルゲームの現在の様子を紹介しました。\u003C\u002Fp>\u003Cp>DX ライブラリを使って、描画や入力、ダブルバッファリングなどを自分で実装していくなかで、\u003Cstrong>ゲームが動くまでの流れ\u003C\u002Fstrong>もあらためて確認できました。\u003C\u002Fp>\u003Cp>まだ制作途中ですが、これからも息抜きとして少しずつ手を加え、まずは皆さんに遊んでもらえる状態まで仕上げたいと思っています。このゲームがひと段落したら、次はシューティングゲームにも挑戦してみたいです。\u003C\u002Fp>",178,0,3,{"contents":285,"totalCount":490,"offset":282,"limit":491},[286,287,289,292,295,296,298,301,304,307,310,313,314,317,320,323,324,327,330,332,335,338,341,343,346,349,352,354,356,359,362,365,367,369,371,374,377,380,382,385,388,391,394,397,400,403,406,409,412,415,418,420,422,425,427,430,432,435,437,440,443,446,449,452,455,458,461,464,467,469,472,475,478,481,484,487],{"id":11,"name":13},{"id":221,"name":288},"ワークショップ",{"id":290,"name":291},"tool","ツール",{"id":293,"name":294},"office","オフィス",{"id":20,"name":22},{"id":186,"name":297},"イベント",{"id":299,"name":300},"iot","IoT",{"id":302,"name":303},"art","アート",{"id":305,"name":306},"moving","引越し",{"id":308,"name":309},"picture","映像",{"id":311,"name":312},"plant","植物",{"id":16,"name":18},{"id":315,"name":316},"health","健康",{"id":318,"name":319},"exercise","運動",{"id":321,"name":322},"bicycle-club","自転車部",{"id":24,"name":28},{"id":325,"name":326},"interview","Interview",{"id":328,"name":329},"recruiting","採用",{"id":227,"name":331},"お茶会",{"id":333,"name":334},"history","歴史",{"id":336,"name":337},"life","生活",{"id":339,"name":340},"club","部活動",{"id":163,"name":342},"キャラクター",{"id":344,"name":345},"food","食",{"id":347,"name":348},"math","数学",{"id":350,"name":351},"alcohol","酒",{"id":39,"name":353},"インフラ",{"id":165,"name":355},"アプリ",{"id":357,"name":358},"parenting","子育て",{"id":360,"name":361},"data","通信",{"id":363,"name":364},"migration","地方移住",{"id":41,"name":366},"セキュリティ",{"id":368,"name":368},"esports",{"id":167,"name":370},"振り返り",{"id":372,"name":373},"animal","動物",{"id":375,"name":376},"css","CSS",{"id":378,"name":379},"game","ゲーム",{"id":78,"name":381},"TypeScript",{"id":383,"name":384},"management","マネジメント",{"id":386,"name":387},"remote-work","リモートワーク",{"id":389,"name":390},"frame-work","フレームワーク",{"id":392,"name":393},"music","音楽",{"id":395,"name":396},"money","お金",{"id":398,"name":399},"covid-19","コロナ",{"id":401,"name":402},"railway","鉄道",{"id":404,"name":405},"agriculture","農業",{"id":407,"name":408},"hobby","趣味",{"id":410,"name":411},"certification","資格",{"id":413,"name":414},"personal-computer","PC",{"id":416,"name":417},"welfare","福利厚生",{"id":46,"name":419},"技術",{"id":225,"name":421},"勉強",{"id":423,"name":424},"mental-health","メンタルヘルス",{"id":142,"name":426},"フロントエンド",{"id":428,"name":429},"pilates","ピラティス",{"id":43,"name":431},"バックエンド",{"id":433,"name":434},"tunnel","トンネル",{"id":144,"name":436},"デザイン",{"id":438,"name":439},"sports","スポーツ",{"id":441,"name":442},"online","オンライン",{"id":444,"name":445},"internship","インターンシップ",{"id":447,"name":448},"animation","アニメーション",{"id":450,"name":451},"virtual-reality","VR",{"id":453,"name":454},"ssl","SSL",{"id":456,"name":457},"perl","Perl",{"id":459,"name":460},"operating-system","OS",{"id":462,"name":463},"ios","iOS",{"id":465,"name":466},"google","Google",{"id":245,"name":468},"DeepLearning",{"id":470,"name":471},"aws","AWS",{"id":473,"name":474},"apple","Apple",{"id":476,"name":477},"api","API",{"id":479,"name":480},"3-d","3D",{"id":482,"name":483},"school","学校",{"id":485,"name":486},"blender","Blender",{"id":488,"name":489},"android","Android",76,200,{"contents":493,"totalCount":283,"offset":282,"limit":283},[494,547,612],{"id":495,"createdAt":496,"updatedAt":497,"publishedAt":498,"revisedAt":497,"title":499,"category":500,"thumbnail":509,"image":512,"content":521,"keyword":522,"client":537,"team":538,"url":542,"release":543,"status":544,"top":14,"blog":29,"service":546},"phpj-noel-2025","2025-12-15T06:18:04.117Z","2026-08-04T09:31:48.003Z","2026-03-05T04:15:03.177Z","PIERRE HERMÉ PARIS | NOËL 2025",[501,506],{"id":502,"createdAt":503,"updatedAt":504,"publishedAt":503,"revisedAt":503,"name":505},"web","2024-03-22T05:33:05.262Z","2024-06-24T23:16:42.692Z","ウェブ制作",{"id":144,"createdAt":507,"updatedAt":507,"publishedAt":507,"revisedAt":507,"name":508},"2024-03-22T05:34:30.127Z","デザイン＆ディレクション",{"url":510,"height":124,"width":511},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002F47e7b069013a45b8b6e931ec132bd272\u002Fthumb.png",1200,[513,517,519],{"url":514,"height":515,"width":516},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002F43a703ebe8d7467aac2c995378cb081e\u002F1.png",1800,2400,{"url":518,"height":515,"width":516},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002F6aed2d670822422696329a5cb3a6877f\u002F2.png",{"url":520,"height":515,"width":516},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002Fb691d73151a94dcf9d60a6f8af436eac\u002F3.png","\u003Cp>昨年に続き、ホリデーシーズン限定の『NOËL 2025』スペシャルサイトを、\u003Cstrong>デザインとフロントエンドで担当\u003C\u002Fstrong>しました。\u003Cbr>\u003Cbr>\u003Cstrong>「深海(アビス)」をテーマ\u003C\u002Fstrong>に、鮮やかな青から徐々に暗く沈んでいくグラデーションで、海の中を潜っていくような体験を表現。泡や珊瑚、砂などのモチーフを取り入れ、ページ全体で海中の世界を感じられる構成に仕上げました。\u003Cbr>\u003Cbr>砂や泡の表現にはWebGLとGPGPUを用い、数万単位のパーティクルをGPUで並列処理することで滑らかな動作を実現。一部テキストは3D描画で演出しながら、DOM上にも同内容を配置し、表現とSEOの両立を図りました。\u003Cbr>また、Safariなどブラウザ差異による負荷を考慮し、SVGからCanvasへ置き換えるなど最適化を実施。視覚的な印象を保ちながら、各環境で安定して動作するよう設計しています。\u003Cbr>\u003Cbr>\u003Cstrong>デザインと実装の両面から、制作の背景やポイントについてブログで詳しく解説\u003C\u002Fstrong>しています。\u003C\u002Fp>",[523,527,532],{"id":524,"createdAt":525,"updatedAt":526,"publishedAt":525,"revisedAt":526,"name":426,"filter":29,"page":29},"ice0h9h9ap","2024-06-28T01:14:44.830Z","2025-01-15T07:40:01.729Z",{"id":528,"createdAt":529,"updatedAt":530,"publishedAt":529,"revisedAt":530,"name":531,"filter":29,"page":29},"6ncqc37v7nzq","2024-06-28T01:14:12.293Z","2025-01-15T07:39:08.437Z","デザインプロジェクト",{"id":533,"createdAt":534,"updatedAt":535,"publishedAt":534,"revisedAt":535,"name":536,"filter":29,"page":29},"ztrz9np70v","2024-06-28T01:14:41.050Z","2025-01-15T07:40:30.428Z","コンセプトメイキング"," PH PARIS JAPON 株式会社",[539],{"fieldId":540,"title":541},"teamField","S2ファクトリー","https:\u002F\u002Fwww.s2factory.co.jp\u002Fblog\u002Fnoel2025\u002F","2025.10.17",[545],"公開中",[436],{"id":548,"createdAt":549,"updatedAt":550,"publishedAt":549,"revisedAt":550,"title":551,"category":552,"thumbnail":559,"image":563,"content":568,"keyword":569,"client":551,"team":584,"url":607,"release":608,"status":609,"statusText":610,"top":29,"blog":29,"service":611},"tamabi","2024-06-28T01:58:38.788Z","2025-05-27T03:25:42.261Z","多摩美術大学",[553,554],{"id":502,"createdAt":503,"updatedAt":504,"publishedAt":503,"revisedAt":503,"name":505},{"id":555,"createdAt":556,"updatedAt":557,"publishedAt":556,"revisedAt":556,"name":558},"system","2024-03-22T05:33:52.708Z","2024-06-24T23:16:53.739Z","システム開発",{"url":560,"height":561,"width":562},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002Fdea8e004e627415c80bf7b8d622bb4b9\u002Ftamabi-thumbnail-1.png",456,600,[564],{"url":565,"height":566,"width":567},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002Fa000f3cedf5d474d83c5b70e8c11db4e\u002Ftamabi-other-1.png",1305,1740,"\u003Cp>「多摩美術大学」ウェブサイトリニューアルのお手伝いをさせていただきました。\u003Cbr>\u003Cbr>サイトのコンテンツを大幅に整理し、運用効率を考慮した再利用しやすく組み合わせやすいUIコンポーネントを構築。また多くの方に利用していただけるようにアクセシビリティの向上にも注力しました。\u003Cbr>インフラは、従来のオンプレミスとクラウドが混在していた環境から、AWS への段階的な移行を進めており、今後の完全移行に向けた準備も進行中です。 \u003Cbr>\u003Cbr>弊社は、フロントエンドとバックエンドの実装、インフラ構築を担当しました。\u003C\u002Fp>",[570,574,578,583],{"id":571,"createdAt":572,"updatedAt":573,"publishedAt":572,"revisedAt":573,"name":471,"filter":29,"page":29},"uftrxsmd0v72","2024-06-28T01:14:13.671Z","2025-01-15T07:39:25.538Z",{"id":575,"createdAt":576,"updatedAt":576,"publishedAt":576,"revisedAt":576,"name":577,"filter":14,"page":14},"yctx9hzd4","2024-06-28T01:14:33.743Z","Lambda",{"id":579,"createdAt":580,"updatedAt":581,"publishedAt":580,"revisedAt":581,"name":582,"filter":29,"page":29},"u84cy0fbzno","2024-06-28T01:14:39.521Z","2025-01-15T07:40:41.433Z","Cloud",{"id":524,"createdAt":525,"updatedAt":526,"publishedAt":525,"revisedAt":526,"name":426,"filter":29,"page":29},[585,588,591,594,597,600,603,606],{"fieldId":540,"title":586,"link":587},"萩原 俊矢","https:\u002F\u002Fshunyahagiwara.com\u002F#\u002Fworks",{"fieldId":540,"title":589,"link":590},"GrandBase Inc.","https:\u002F\u002Fwww.grandbase.jp\u002F",{"fieldId":540,"title":592,"link":593},"DSCL Inc.","https:\u002F\u002Fdscl.jp\u002F",{"fieldId":540,"title":595,"link":596},"株式会社トラフィックス","https:\u002F\u002Ftraffics.jp\u002F",{"fieldId":540,"title":598,"link":599},"株式会社カンバセーションズ","https:\u002F\u002Fqonversations.jp\u002F",{"fieldId":540,"title":601,"link":602},"Measurements Inc.","https:\u002F\u002Fwww.measurements.co.jp\u002F",{"fieldId":540,"title":604,"link":605},"tha ltd.","https:\u002F\u002Ftha.jp\u002F",{"fieldId":540,"title":541},"https:\u002F\u002Fwww.tamabi.ac.jp\u002F","2024.4.4",[545],null,[505],{"id":613,"createdAt":614,"updatedAt":615,"publishedAt":614,"revisedAt":615,"title":616,"category":617,"thumbnail":619,"image":621,"content":630,"keyword":631,"client":604,"team":647,"url":653,"release":654,"status":655,"statusText":610,"top":14,"blog":29,"service":656},"humanity","2024-06-28T01:56:51.507Z","2025-05-27T03:26:34.287Z","HUMANITY",[618],{"id":555,"createdAt":556,"updatedAt":557,"publishedAt":556,"revisedAt":556,"name":558},{"url":620,"height":561,"width":562},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002F740adb4e02c54fee97d12025df5f16a0\u002Fhumanity-thumbnail-1.png",[622,624,626,628],{"url":623,"height":566,"width":567},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002F2a10b034854d40e789d38ac33e0a3c4e\u002Fhumanity-other-1.png",{"url":625,"height":566,"width":567},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002F1091c52a97f745e5a3fc105bd0e542dc\u002Fhumanity-other-2.png",{"url":627,"height":566,"width":567},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002F613c8c836fff40119e9f85097262399d\u002Fhumanity-other-3.png",{"url":629,"height":566,"width":567},"https:\u002F\u002Fimages.microcms-assets.io\u002Fassets\u002Fd6dcb8ec530642e7a9b0d0c0a93bf874\u002F3a9dfb8cce0d4ec887ead3d3998be04c\u002Fhumanity-other-4.png","\u003Cp>『HUMANITY』は、インターフェース／ビジュアルデザイナーの中村勇吾氏とゲームクリエイター水口哲也氏のタッグによって制作された PlayStation 5(PS VR2対応)、PlayStation 4(PS VR対応)、Steam(PC用VR対応)用アクションパズルゲームです。\u003Cbr>\u003Cbr>プレイヤーは柴犬を操作して、自我を失った人類を導きゴールを目指します。\u003Cbr>メインのストーリーモードには 90 以上のステージを収録。さらに「STAGE CREATOR」では、自分だけのオリジナルステージを作って全世界のプレイヤーにシェアが可能です。また「USER STAGES」では、他のプレイヤーがシェアしたステージが公開され、カスタムのプレイリストや、タグを使用して検索し、お気に入りのステージを発見・チャレンジできます。\u003Cbr>\u003Cbr>弊社はゲームのコミュニティ機能のバックエンドと管理ツールの作成、インフラを担当しました。\u003C\u002Fp>",[632,637,642,643],{"id":633,"createdAt":634,"updatedAt":635,"publishedAt":634,"revisedAt":635,"name":636,"filter":29,"page":29},"fg8e4c9nl","2024-06-28T01:14:04.517Z","2025-01-15T07:36:58.970Z","CMS",{"id":638,"createdAt":639,"updatedAt":640,"publishedAt":639,"revisedAt":640,"name":641,"filter":29,"page":29},"p6qgoo2k9vl9","2024-06-28T01:14:06.759Z","2025-01-15T07:37:22.466Z","大規模データ",{"id":579,"createdAt":580,"updatedAt":581,"publishedAt":580,"revisedAt":581,"name":582,"filter":29,"page":29},{"id":644,"createdAt":645,"updatedAt":646,"publishedAt":645,"revisedAt":646,"name":379,"filter":29,"page":29},"pxnv6cy2u","2024-06-28T01:14:45.570Z","2025-01-15T07:39:54.004Z",[648,651,652],{"fieldId":540,"title":649,"link":650},"Enhance","https:\u002F\u002Fenhance-experience.com\u002Fja\u002F",{"fieldId":540,"title":604,"link":605},{"fieldId":540,"title":541},"https:\u002F\u002Fhumanity.game\u002Fja\u002F","2023.5.16",[545],[558],1790220504841]