
Swift
イベント
マガジン
技術ブログ
はじめに こんにちは、ZOZOTOWN開発1部iOSブロックの @kitasuke です。 前回の記事「 ZOZOTOWN iOS のアーキテクチャとチームの進化 」では、MVCからMVVM、そしてMVVM + Repositoryへのアーキテクチャ進化を取り上げました。あわせて、レビュー文化をチームに根づかせてきた3年間も振り返っています。 ただ、アーキテクチャを文章で定義しても、書き手によって命名や責務分割はぶれが生じますし、AIに任せると過去の望ましくない実装パターンまで律儀に再現されます。 ドキュメントによる「努力目標」では、アーキテクチャは守りきれません。 そこで発想を逆にしました。アーキテクチャを「守るべきルール」ではなく、 構造化されたスキーマ として定義し、人間とAIの双方がそれに従うしかない形にします。Swiftの型システムがコンパイル時に不正を弾くのと同じ発想を、アーキテクチャのレイヤーにスキーマという形で持ち込みます。それが本記事で紹介する 「スキーマでアーキテクチャを縛る」アプローチ です。副産物として、設計からコードを自動生成するパイプラインも動いています。 目次 はじめに 目次 どんなスキーマを定義したのか architecture-guidelines.md — コンポーネントをスキーマで縛る architecture-templates.md — スキーマから Swift を導出するルール どうやって縛っているのか 画面ごとの設計を YAML で表現する /architectureと/codegen — 実際の運用 /architecture: 仕様書やデザインから YAML を起こす /codegen: YAMLからSwiftのコードを生成する 何が変わったのか AIの書くコードがレビューを通る水準になった レビューで「プロダクト品質」の話ができるようになった まとめ どんなスキーマを定義したのか 全体像はこうなっています。 仕様書 (Confluence) / デザイン (Figma) / 既存コード │ ▼ /architecture ┌─────────────────────┐ │ 設計 YAML │ ←── AI / Codegen 向け │ Human Doc (Markdown) │ ←── 人間向けレビュー資料 └─────────────────────┘ │ ▼(人間がレビュー・編集) │ ▼ /codegen Swift コード一式 ↑ 全工程でガイドラインとテンプレートが参照される 土台となっているのが、チームで整備した 2つのドキュメント です。 architecture-guidelines.md — 各コンポーネントのスキーマ(何が正しいか) architecture-templates.md — スキーマからSwiftを導出するテンプレート(どう書くか) architecture-guidelines.md — コンポーネントをスキーマで縛る 各コンポーネント(ViewModel、Repository、Translatorなど)を、型・依存・命名・必須ルール・禁止パターンなどのフィールドで厳密に定義しています。たとえばViewModelのスキーマは次のとおりです。 ### ViewModel - type : `@MainActor final class` - imports : [ Foundation, Combine ] - imports_forbidden : [ APIModule ] - depends_on : [ RepositoryProtocol, UIModelTranslator, DataModel, UIModel ] - nested_types : [ ViewState, Router ] - naming : { Feature } ViewModel - required : - ViewState enum で画面状態を管理(複数 Bool 禁止) - @Published private(set) で外部からの直接変更を防止 - 1 ユーザーアクション = 1 input メソッド(did{Verb}{Noun}) - forbidden : - キャッシュロジック(Repository の責務) - ログ送信の直接呼び出し(UseCase/別 Repository に分離) 自由に書ける余地を 意図的に潰している のがポイントです。ViewModelがAPIモジュールをimportした時点でアウトです。 @Published を private(set) にしなかった場合もアウトです。自己流のMVVM解釈を許さない設計になっています。 architecture-templates.md — スキーマから Swift を導出するルール スキーマだけではSwiftコードの具体的な書き方までは決まりません。命名規則、ファイルの生成順序、各レイヤーのSwiftコードテンプレートなどを、もう一段別のドキュメントで固めています。 ガイドラインがスキーマで、テンプレートが導出規則です。 この2つが揃うことで、アーキテクチャのスキーマから具体的なSwiftコードが一意で決まる状態になりました。 どうやって縛っているのか 人間・AI・ツールの全員が、同じスキーマで動くようになっています。順に見ていきます。 画面ごとの設計を YAML で表現する コンポーネントのスキーマが決まっても、画面ごとの実装は別物です。そこで、 画面ごとの設計を1枚のYAMLで記述 します。 feature : ProductList domain : Product api : - id : fetchProducts method : GET path : /products response : items : [ Product ] actions : - trigger : didAppear api : fetchProducts - trigger : didTapRetry api : fetchProducts condition : "state == .error" models : data : - name : Product fields : id : String name : String brandName : String price : Int imageURL : URL ui : - name : ProductListUIModel fields : nameText : String brandText : String priceText : String このYAMLは、ガイドラインが定めたスキーマの「値」にあたります。画面のAPI、アクション、データモデルが構造化されて並んでいるだけで、曖昧さの入り込む余地はありません。 /architecture と /codegen — 実際の運用 この縛りを日々の開発で実行しているのが2つのスラッシュコマンドです。 /architecture : 仕様書やデザインから YAML を起こす 重要なのは、このYAMLを人間がゼロから書いているわけではない という点です。Confluenceの仕様書やFigmaのデザインを入力にすると、 /architecture コマンドが設計YAMLと人間向けMarkdownの大部分を自動生成します。 人間の作業は「書く」ではなく「判断する」に寄っています。生成されたYAMLを読み、責務分割やエッジケースの扱いなど 設計判断が必要な箇所だけ に手を入れます。スキーマが縛ってくれているので、AIが起こしたYAMLも標準から外れた形にはなりません。 /codegen : YAMLからSwiftのコードを生成する レビューが終わったYAMLを /codegen に渡すと、Swiftコード一式が出力されます。具体的には、View / ViewModel / Repository / プロトコル / モック / ユニットテストの雛形 / 依存注入のコードです。 たとえば先ほどの ProductList.yaml のうち、以下の部分に注目します。 actions : - trigger : didAppear api : fetchProducts - trigger : didTapRetry api : fetchProducts condition : "state == .error" この部分を /codegen に流すと、ViewModelは次のように生成されます。 @MainActor final class ProductListViewModel : ObservableObject { enum ViewState { case loading case loaded(ProductListUIModel) case error(Error) } @Published private ( set ) var state : ViewState = .loading private let repository : ProductRepositoryProtocol func didAppear () async { await fetchProducts() } func didTapRetry () async { guard case .error = state else { return } await fetchProducts() } private func fetchProducts () async { state = .loading do { let products = try await repository.fetchProducts() state = .loaded(ProductListUIModelTranslator.translate(from : products )) } catch { state = .error(error) } } } ガイドラインで定義した制約が そのまま反映されている のが分かります。たとえば @MainActor final class 、 @Published private(set) 、ViewState enumでの状態管理、 did{Verb}{Noun} 命名規則などです。YAMLの actions はそのままViewModelのメソッドに、 condition はguard文に対応しています。コード生成は仕組みの主役ではなく、スキーマで縛った結果として得られる副産物です。 何が変わったのか AIの書くコードがレビューを通る水準になった スキーマで縛ったことで、実際にAIの出力が目に見えて安定しました。命名・配置・レイヤー構成がプロジェクト標準に揃い、ハルシネーションもほぼ消え、同じYAMLを何度通してもほぼ同じコードが出てきます。 AIの生成するコードは、そのままレビューを通る水準に達しました。 これが縛りの直接的な見返りです。 レビューで「プロダクト品質」の話ができるようになった コード品質(命名、配置、責務分割)はスキーマが自動的に揃えるので、レビューで議論する必要がなくなりました。その分、UXが成立しているか、エッジケースの仕様が妥当か、ビジネスゴールに沿っているか、といった プロダクトとしての品質 に時間を使えるようになっています。コードの良し悪しではなく、 プロダクトの良し悪し を議論できるようになったのは、狙い通りの大きな変化でした。 まとめ アーキテクチャは「努力目標」ではなく「スキーマ」で守ります。Swiftの型システムが不正を弾くのと同じ発想を、設計レイヤーにも持ち込みます。人間とAIを同じスキーマで動かすことで、チームのアーキテクチャを長く保てる状態を目指しています。 ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com
はじめに こんにちは、ZOZOTOWN開発本部でiOSエンジニアをしている續橋( @tsuzuki817 )です。 2026年4月13日〜14日に開催された try! Swift Tokyo 2026 にて、「GeoJSON×SwiftUI:地図を“美しく”描くための技術」というタイトルで20分のトークをしました。 speakerdeck.com www.youtube.com 本記事では、プロポーザルの準備から採択、トーク作成、社内での練習とフィードバック、そして登壇当日までの道のりをお伝えします。これからカンファレンスへの登壇を考えている方の参考になれば幸いです。 目次 はじめに 目次 try! Swift Tokyo とは ZOZOのiOSエンジニア全体でプロポーザルに挑む プロポーザルを考える会の開催 GPTを活用した「try! Swift プロポーザル コーチ」 採択 — LT枠から20分トークへ トーク作成 チーム内トーク練習とフィードバック スライドの改善 — 英語化とビジュアライズ ビジュアライズの強化 英語化 登壇当日 組織横断で登壇を支える意義 まとめ try! Swift Tokyo とは try! Swift Tokyo は、世界中からSwift開発者が集まる国際カンファレンスです。2026年は4月12日〜14日の3日間にわたって立川ステージガーデンで開催されました。4月12日がワークショップ、4月13日〜14日がカンファレンス本編という構成です。 トークの言語は自由で、AI翻訳による同時通訳が提供されています。多くのスピーカーが英語で発表する中、私はスライドを英語で作成し、発表自体はAI翻訳に任せて日本語で行いました。 ZOZOのiOSエンジニア全体でプロポーザルに挑む プロポーザルを考える会の開催 try! Swift Tokyo 2026のプロポーザル募集が告知されたタイミングで、ZOZOのiOSエンジニア全体に向けて 「プロポーザルを考える会」 を企画しました。 企画の背景には、いくつかの想いがありました。正直なところ、私自身もtry! Swiftへのプロポーザル提出は初挑戦で不安がありました。一人で世界的なカンファレンスに挑むのはハードルが高いと感じていました。だからこそ仲間を募り、みんなで一緒に挑戦したいと考えました。一人だと尻込みしてしまうことでも、みんなで「お祭り」のように取り組めば乗り越えられると思いました。そして、結果(採択)以上に、みんなで知見を出し合う「プロセス」そのものを大事にしたいと考えました。この活動を通じて、プロダクトの枠を超えた横のつながりを深めたいという想いもありました。 ZOZOTOWN、WEAR、FAANSなど複数のプロダクトチームから横断的に参加を募り、2026年1月7日に開催したところ、8名が参加しました。 会のアジェンダは以下のとおりです。 イントロ — 会の目的説明、try! Swift Tokyo 2026のスケジュール共有(締切1月末、採択2月中旬) 採択傾向の共有 — 過去セッションの分析 プロポーザル例の紹介 — 私のプロポーザル2案を紹介し、フィードバックを募集 ネタ出しブレスト — 各自のアイデアを出し合う まとめ & Next Action — 興味のあるネタの深掘り担当決め、次回開催について 「ネタがなくてもとりあえず参加して、みんなのネタを見てプロポーザルが閃くかもしれない」というスタンスで、飛び入り参加も歓迎としました。結果的に、この会をきっかけに、ZOZOTOWN・WEAR・FAANSの 3プロダクト横断で5名 がプロポーザルを提出できました。 GPTを活用した「try! Swift プロポーザル コーチ」 プロポーザルの質を高めるために、ChatGPTのカスタムGPT機能で 「try! Swiftプロポーザルコーチ」 を作成しました。 このコーチは、雑にネタを投げるとtry! Swiftに提出できる形へプロポーザルを整形してくれるものです。過去のtry! Swiftで採択されたプロポーザルの傾向や、効果的なプロポーザルの書き方の知見を組み込んでいます。 作成したコーチは、プロポーザルを考える会の場でも参加者に共有しました。自分のプロポーザルを磨くだけでなく、他のプロダクトチームのメンバーにも活用してもらうことで、全体のプロポーザルの質を底上げできました。ツールとして共有することで、個人の経験や知見に依存せず、誰でも一定水準のフィードバックを得られる仕組みになったのは大きな成果でした。 採択 — LT枠から20分トークへ プロポーザルは「GeoJSON×SwiftUI:地図を"美しく"描くためのサイズ設計と描画テク」というタイトルでLT枠として提出しました。 2月中旬、try! Swift運営チームから採択のメールが届きました。驚いたのは、 LT枠として提出していたにもかかわらず、20分のトーク枠での登壇を打診された ことです。運営からは「可能であれば20分のトークでお願いしたい」とのことで、二つ返事で承諾しました。 ZOZOTOWN、WEAR、FAANSの各チームから合わせて5名がプロポーザルを提出しましたが、採択されたのは私のみでした。それでも、組織横断の取り組みから「次こそは」という機運が生まれたことは大きな収穫でした。 トーク作成 採択が決まってからは、20分のトーク内容を作り込んでいきました。 テーマは、個人開発アプリ「旅行思い出マップ」で直面した、GeoJSONを使った地図描画の技術的な挑戦です。市町村レベルの地形に沿って写真を切り抜き、地図上にパズルのように配置する機能を実装しました。本トークでは、図法(投影法)の違いによる地図の歪みの解決方法を解説する内容としました。 まず、Claude Codeを使ってプロポーザルと実際のプロジェクトのコードから発表の流れを組み立てました。しかし、最初に生成された構成は同じ内容の重複や、話の順番の繋がりの悪さが目立ちました。細かく指示を出して何度も修正を重ね、ようやく納得のいく台本に仕上がりました。 台本が完成した後は、Claude Codeでベースのスライドを生成しました。ただ、生成されたスライドは好みに合わなかったため、Keynoteで自分好みにスライドを分割したり、画像を差し込んだりして手作業で仕上げていきました。 トークの構成は以下のとおりです。 イントロ & アプリ紹介 MapKitの限界と画像ベースの苦労(Before) GeoJSONとの出会い(転換点) 描画パイプライン全体像 GeoJSONパース 座標変換とMercator投影 SwiftUIでの描画 地図を"美しく"する工夫 まとめ チーム内トーク練習とフィードバック スライドの初版が完成した段階で、3月27日にチーム内でトーク練習会を実施しました。実際に20分の通し発表をし、メンバーからリアルタイムでフィードバックをもらいました。 フィードバックは以下のようなものでした。 GeoJSONの説明タイミング —「GeoJSONに触れてから1分くらい経っていたので、もう少し早めに説明へ入ったほうがいい」 技術的な説明の速度 —「GeoDataProviderやMKGeoJSONDecoder、MKGeoJSONFeatureのくだりが速くてあまり入ってこない。全体的な流れのイメージがあるといい」 ビジュアルの追加 —「地図の説明はビジュアルで見たい」「もうちょっと実際の地図との関連性がわかるといい」 Before-Afterの対比 —「プログラムと図(Before-After)をセットで見られるともっと良さそう」「プログラムのページをわかりやすくするだけでもっと良くなりそう」 コードの細かな指摘 — インデントやスラッシュの数など、スライド上のコード品質についても指摘をもらいました チームメンバーの率直なフィードバックのおかげで、説明の流れや視覚的なわかりやすさについて多くの改善点を発見できました。一人では気づけない「聴衆視点」の指摘は非常に貴重でした。 スライドの改善 — 英語化とビジュアライズ 練習会でのフィードバックを受けて、以下の改善をしました。 ビジュアライズの強化 フィードバックで特に多かった「視覚的にわかりにくい」という指摘に対応するため、以下を追加・改善しました。 Before-Afterの図をコードとセットで表示 描画パイプラインの全体像を図解 離島を含む地図描画のビジュアル例を追加 実際の地図との対比がわかるスクリーンショットを追加 ビジュアライズにはClaude Codeを活用しました。実際のGeoJSONデータを渡してSwiftUIのコードを生成してもらい、そこから画像を出力する形で対応しました。実データを使って図を描画できるため、スライド上の説明と実際の動作が一致した正確なビジュアルを効率よく用意できました。 英語化 try! Swift Tokyoは国際カンファレンスのため、スライドは英語で作成しました。発表自体はAI翻訳による同時通訳を活用し、日本語で行う方針としたため、日本語で作成したスライドを英語に翻訳する作業が必要でした。 英語化にはClaude Codeを活用し、作業を効率的に進めました。ただし、AIによる翻訳だけでは伝えたい感情やニュアンスを正確に表現しきれない部分がありました。そこで、チーム内で英語に強いメンバーの、らぷ( @laprasdrum )と小松( @tosh_3 )にレビューを依頼しました。2人には「ここはこういう意図で伝えたい」という部分の表現をかなり細かく指摘してもらい、機械的な翻訳では得られない自然で伝わる英語に仕上げられました。AIと人間のレビューを組み合わせることで、スライドの完成度を大きく引き上げられたと感じています。 登壇当日 4月11日のスライド提出締め切りを経て、4月12日のワークショップ、そして4月13日〜14日のカンファレンス本番を迎えました。 会場に着いて受付でスピーカーのプレートをもらいました! 会場は想像していたよりもかなり広く、とても迫力がありました。 歴代のtry! Swiftのポスターが飾られており、10周年のタイミングで参加できてとても光栄に思いました。 登壇終了後にステージから撮影した写真です。本番中は緊張してしまい、会場の方をほとんど見られていなかったのが反省点です。 登壇とAsk the Speakerを何とか終え、開放感からすぐにスポンサーブースを回りました。 可愛いお菓子もデプロイされていました! 組織横断で登壇を支える意義 今回の登壇を振り返ると、個人の努力だけでなく ZOZOのiOSエンジニア全体の支えがあったからこそ実現できた と強く感じます。 プロポーザル段階 : ZOZOTOWN・WEAR・FAANSの各チームから横断的にプロポーザルを考える会を開催し、互いのアイデアにフィードバックを送り合いました ツールの共有 : GPTを活用したプロポーザルコーチを作り、全員が活用できるようにしました トーク練習 : 社内でリハーサルを行い、聴衆視点からの具体的なフィードバックをもらえました 英語レビュー : 英語に強いメンバーがスライドの英語をレビューしてくれました カンファレンス登壇は個人の活動と思われがちですが、組織横断で取り組むことで、プロポーザルの質・トークの質ともに大きく向上します。また、たとえ今回採択されなかったメンバーも、この過程で得た経験は次のチャレンジに活きるはずです。 まとめ try! Swift Tokyo 2026での登壇は、プロポーザルの準備からトーク完成まで約3か月の道のりでした。この経験を通じて、組織横断で挑戦することの価値を改めて実感しました。 カンファレンスへの登壇を検討されている方は、ぜひチームを巻き込んでみてください。一人では出てこないアイデアやフィードバックが、必ず登壇の質を高めてくれるはずです。 ZOZOのiOSエンジニア一同、今後もカンファレンスへの登壇を組織横断で積極的に推進していきます。 ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com
こんにちは!株式会社LuupのiOSエンジニアのリョウです。 先日、try! Swift Tokyo 2026が開催され、Luupからは4名のiOSエンジニアが参加しました。 本記事では、各メンバーが特に注目したセッションについてご紹介します。 try! Swift try! SwiftはApple PlatformやSwiftに関するトピックを扱う国際カンファレンスです。 世界中のエンジニアが集まり、プレゼンテーションを聴いたり、スピーカーや参加者と交流できます。 スピーカーと1対1で話せるオフィスアワーの時間もあり、気になった点を直接聞くことができます。 今年も3日間にわたり、学
動画
該当するコンテンツが見つかりませんでした
















