Slide 1

Slide 1 text

© 2024 Wantedly, Inc. ウォンテッドリーにおける モバイルアプリ開発 iOSDC Japan 2024 ウォンテッドリー株式会社

Slide 2

Slide 2 text

© 2024 Wantedly, Inc. 自己紹介 @swiz_ard @kubode @yuya_h_x @yuya-h-29

Slide 3

Slide 3 text

© 2024 Wantedly, Inc. Introduction ▍会社概要 ウォンテッドリー株式会社 仲 暁子 2010年5月 104人 究極の適材適所により、シゴトでココロオドルひとをふやす 東京都港区白金台 5-12-7 MG白金台ビル4F CEO 設立 ミッション 社員数 本社住所

Slide 4

Slide 4 text

© 2024 Wantedly, Inc. “シゴトでココロオドル”とは? 私たちは“シゴトでココロオドル ”人を増やし(プロダクト)、 私たち自身も“シゴトでココロオドル ”状態で あり続けることを目指します。 没頭することで成果を出し、成果によって成長を実感すること ミッションやカルチャーなどに共感できる組織 の、自律的に意思決定できる環境で、簡単す ぎず、難しすぎない適度な挑戦によりフロー状 態となり、仕事に没頭できている状態 没頭した結果、 新しい価値といった成果を生み出す 一定の成果をあげられたことに対して、 成長を実感できる About Wantedly シゴトでココロオドル状態とは? 没頭 1 成果 2 成長実感 3

Slide 5

Slide 5 text

© 2024 Wantedly, Inc. 人々が仕事に夢中になるためのユニークな価値を提供 Business サービス提供価値 Wantedlyの提供価値 Employee Engagement Recruiting Recruitment Marketing 認知形成・興味喚起・応募 定着・活躍 Blog、SNS、動画、PR 詳細情報提供、イベント コミュニケーション、 チームマネジメント、福利厚生 選考・内定・承諾 日程調整、候補者管理、 進捗把握、データ分析 

Slide 6

Slide 6 text

© 2024 Wantedly, Inc. Agenda ウォンテッドリーのモバイル開発チームの取り組み紹介 ● チーム ● 技術

Slide 7

Slide 7 text

© 2024 Wantedly, Inc. モバイル開発チーム

Slide 8

Slide 8 text

© 2024 Wantedly, Inc. モバイルチーム 開発メンバー 久保出 Tech Lead 林 iOSリード エンジニア 原田 iOS エンジニア 業務委託メンバー iOS エンジニア Android エンジニア

Slide 9

Slide 9 text

© 2024 Wantedly, Inc. スクラム開発 ● 1週間単位のスプリント 金曜日 ● デイリースクラム ● 開発 ● スプリントレビュー ● レトロスペクティブ 月曜日 ● プランニング ● 開発 火曜日〜木曜日 ● デイリースクラム ● 開発

Slide 10

Slide 10 text

© 2024 Wantedly, Inc. グロースサイクル 2. 施策アイディア 発見した課題の施策アイディアを考え る 1. 課題発見 プロダクトの改善や成長に つながる課題を見つける 3. 実装 施策アイディアを基に 新機能の実装や修正を行う 5. 分析 施策で狙った目的が達成で きたかを検証する 4. リリース

Slide 11

Slide 11 text

© 2024 Wantedly, Inc. 技術軸での取り組み ● モバイルお茶会 ○ 毎週30分の勉強会 ● 負債返済日 ○ 月に丸一日使って負債返済 https://docs.wantedly.dev/fields/dev-process/fusai-hensai-bi

Slide 12

Slide 12 text

© 2024 Wantedly, Inc. チームビルディング ● 相互理解のワークショップ ● 毎週の1 on 1 ● 新入社員研修 ● クラブ活動

Slide 13

Slide 13 text

© 2024 Wantedly, Inc. 技術

Slide 14

Slide 14 text

© 2024 Wantedly, Inc. Kotlin Multiplatform (KMP) https://www.jetbrains.com/kotlin-multiplatform/

Slide 15

Slide 15 text

© 2024 Wantedly, Inc. Kotlin Multiplatform (KMP) https://www.jetbrains.com/kotlin-multiplatform/

Slide 16

Slide 16 text

© 2024 Wantedly, Inc. KMPの実例 Visit iOSアプリのアーキテクチャ Kotlin Multiplatform

Slide 17

Slide 17 text

© 2024 Wantedly, Inc. KMPの実例 Visit iOSアプリのアーキテクチャ Reactor ● 独自の単方向データフローアーキテクチャ ● ViewModelのようなもの データフロー

Slide 18

Slide 18 text

© 2024 Wantedly, Inc. KMPの実例 1. 自由入力された居住地をステートとして持つ 2. サーバー通信を行い、居住地データを登録する オンボーディングで 居住地を入力する画面

Slide 19

Slide 19 text

© 2024 Wantedly, Inc. KMPの実例 Reactor class OnboardingLocationEditReactor internal constructor( private val updateLocationUseCase: UpdateLocationUseCase, ) : BaseReactor(State()) { data class State( val location: String = "", val submissionStatus: SubmissionStatus = SubmissionStatus.Pending, ) sealed class Action { data class UpdateLocation(val location: String) : Action() data object Submit : Action() } } ● 居住地入力のロジックを担う

Slide 20

Slide 20 text

© 2024 Wantedly, Inc. SwiftUIとKMPの連携 public struct OnboardingLocationView: View { public typealias Reactor = AnySwiftUIReactor< OnboardingLocationEditReactor.Action, OnboardingLocationEditReactor.State, KotlinUnit > @EnvironmentObject private var reactor: Reactor private var locationText: Binding { Binding(    get: { reactor.state.location }, set: { newValue in reactor.send(OnboardingLocationEditReactor.ActionUpdateLocation(location: newValue)) }) } public var body: some View { VStack { /* UIのコード */ Button { reactor.send(OnboardingLocationEditReactor.ActionSubmit()) } label: { ... } } } }

Slide 21

Slide 21 text

© 2024 Wantedly, Inc. SwiftUIとKMPの連携 Binding( get: { reactor.state.location }, set: { newValue in reactor.send(OnboardingLocationEditReactor.ActionUpdateLocation(location: newValue)) }) Button { reactor.send(OnboardingLocationEditReactor.ActionSubmit()) } label: { ... }

Slide 22

Slide 22 text

© 2024 Wantedly, Inc. KMPの良い点と課題

Slide 23

Slide 23 text

© 2024 Wantedly, Inc. 良い点 ● ビジネスロジックの共有ができ、仕様が統一される ○ プレゼンテーションロジック(ReactorやViewModel) ○ ネットワークレイヤー ○ エラーハンドリング ● モバイルプラットフォーム全体で考えたときの開発生産性向上 ○ 1つのコードベースでiOS / Android へ同じ体験を提供できる

Slide 24

Slide 24 text

© 2024 Wantedly, Inc. 課題 iOSエンジニアの開発体験 1. コードの定義元に直接飛べない 2. KMPの実装を取り込むまでに時間がかかる 3. Kotlin → Swiftへの変換に慣れる必要がある

Slide 25

Slide 25 text

© 2024 Wantedly, Inc. バイナリをXCFrameworkとして配布している 2. KMPの実装を取り込むまでに時間がかかる Swift Package Manager XCFramework Repo: Visit iOS Kotlin Multiplatform Repo: Visit App Shared

Slide 26

Slide 26 text

© 2024 Wantedly, Inc. KMPの変更をiOS側に取り込む手順 2. KMPの実装を取り込むまでに時間がかかる Kotlin Multiplatform 1. PR作成し、CIを実施 2. PRをマージ 3. KMPの変更を含んだ PRが作成される 4. PRをマージ Repo: Visit App Shared Repo: Visit iOS Swift Package Manager XCFramework

Slide 27

Slide 27 text

© 2024 Wantedly, Inc. 3. Kotlin → Swiftへの変換に慣れる必要がある Sealed Classをenum へ変換する例 sealed class SubmissionStatus { data object Pending : SubmissionStatus() data object Submitting : SubmissionStatus() data object Succeeded : SubmissionStatus() data class Failed(val error: Exception) : SubmissionStatus() } ネットワークリクエストの状態を表す

Slide 28

Slide 28 text

© 2024 Wantedly, Inc. extension OnboardingLocationEditReactor.SubmissionStatus { public enum Pattern { case pending   // 一部省略 case failed(error: KotlinException) } public func asSwiftEnum() -> Pattern? { switch self { case self as OnboardingLocationEditReactor.SubmissionStatusPending: return .pending // 一部省略 case let failed as OnboardingLocationEditReactor.SubmissionStatusFailed: return .failed(error: failed.error) default: assertionFailure("not supported") return nil } } } 3. Kotlin → Swiftへの変換に慣れる必要がある

Slide 29

Slide 29 text

© 2024 Wantedly, Inc. 改善案と展望 KMPを触るiOSエンジニアの 開発者体験向上 https://touchlab.co/kmp-teams-use-source 1. コードの定義元に直接飛べない ○ Xcode-Kotlin Pluginの導入 2. KMPの実装を取り込むまでに時間がかかる ○ GitPortalの導入 3. Kotlin → Swiftへの変換に慣れる必要がある ○ SKIEの導入

Slide 30

Slide 30 text

© 2024 Wantedly, Inc. まとめ

Slide 31

Slide 31 text

© 2024 Wantedly, Inc. まとめ ● ウォンテッドリーのモバイル開発を紹介 ○ 開発の流れ ○ 文化 ○ チームづくり ○ 利用技術と課題

Slide 32

Slide 32 text

© 2024 Wantedly, Inc. We Are Hiring!