Overview
プロジェクト概要
歩数・睡眠・食事などの健康データを一元管理し、ユーザーが日々の状態を把握して、継続的な生活習慣の改善につなげるスマートフォンアプリです。健康データを「記録する」だけでなく、「理解し、行動に活かす」ことを目的に設計しました。中核の体験は「今日の健康状態を短時間で把握でき、次に取る行動が分かること」です。ホーム画面に主要指標を集約し、必要なユーザーだけが詳細画面へ進める情報設計にしています。
iOSはSwift・SwiftUI・HealthKit、AndroidはKotlin・Jetpack Compose・Health Connectのネイティブアプリとして作り、OS固有の健康データの権限とバックグラウンド動作を直接制御しています。バックエンドはAWS(API Gateway・Lambda・Cognito・DynamoDB)のREST APIで分離し、OpenAPIで契約を管理しました。当社が1名の体制で、要件整理、設計、実装、テスト、リリース準備、改善対応を一貫して担当しています。
※ 製品名は記載していません。掲載している画面とデータは、説明用に再構成したイメージです。
- 分類
- 健康管理・生活習慣トラッキング用スマートフォンアプリ
- 対応プラットフォーム
- iOS/Android(ネイティブアプリ)
- 体制
- 1名
- 規模
- 主要画面 5画面 / 主要API 10系統
- 主な利用者
- 健康管理を始めたい社会人、運動不足を感じる人、睡眠・食生活を振り返りたい人
- 業種
- ヘルスケア
- ロール
- 要件整理 / 設計 / iOS・Androidアプリ実装 / API・データ設計 / テスト / リリース準備 / 改善対応
- 技術
- Swift / SwiftUI / HealthKit / Kotlin / Jetpack Compose / Health Connect / AWS(API Gateway / Lambda / Cognito / DynamoDB) / OpenAPI / Firebase Crashlytics / Analytics
01 — 週単位の振り返り
一日では見えない変化を、一週間で見る
単日の数値だけでは、生活リズムの変化は分かりません。そこで、歩数・睡眠・水分などの日次の値に加えて、週単位の推移と目標達成率を提示する画面を設けました。週次の振り返りでは、平均値、前週比、目標を達成した日数、継続状況を表示します。活動量の画面では日・週・月のグラフで歩数と歩行距離を確認でき、睡眠の画面では就寝・起床時刻と週単位の傾向を確認できます。
- 歩数・睡眠・目標達成の週単位の推移
- 平均値・前週比・目標達成日数を表示
- 日・週・月の切り替えでグラフを表示
- 歩数・睡眠・水分などの目標値を設定
開発中の課題と解決
日付の境界とタイムゾーンを、データモデルで扱う
- 課題
- 健康データは日付単位で取得・集計することが中心です。日付をまたぐ睡眠や、端末のタイムゾーンの違いを考慮しないと、記録が誤った日に集計されてしまいます。
- 解決
- イベントの時刻は標準時刻で保存し、日次集計のときにユーザーのタイムゾーンを適用する設計にしました。日付をまたぐ睡眠は、適切な対象日に集計します。歩数・睡眠の生データと日次集計値を分けて持ち、集計の再計算と監査をできるようにしています。
02 — データの正確さ
記録は、正しくつながってこそ意味がある
歩数はスマートフォンとスマートウォッチの両方から取得されることがあり、そのまま足すと二重に計上されます。そこで、OSの健康データAPIから取得した記録を、種類・単位・開始/終了時刻・タイムゾーン・取得元をそろえた共通の形式に整え、取得元IDや時間範囲で重複を判定してから保存します。画面には、取得元ごとの内訳、データの状態、最終同期時刻を表示し、「重複を排除して集計済み」かどうかが分かるようにしました。
- 取得元ごとの内訳を表示し、重複を排除して集計
- 種類・単位・時刻・取得元を共通形式に正規化
- 最終同期時刻と同期の状態を表示
- 未連携・未許可・未取得・同期失敗を別の状態で管理
開発中の課題と解決
「データが無い」と「0」を区別する
- 課題
- 歩数0歩は有効な計測値である可能性がある一方、アクセス権限がない場合やデータソースが空の場合は別の状態です。両者を同じ「0」として表示すると、ユーザーが誤解します。
- 解決
- 値が取得できていない状態を0として扱わず、画面では「0」「未取得」「同期中」「同期エラー」を区別して表示します。データには、未連携・未許可・未取得・同期失敗を別の状態として持たせました。
03 — 権限とプライバシー
健康データは、必要なものだけ
健康データへのアクセスは、歩数・睡眠などの目的ごとに個別に許可を求めます。初期設定では、利用目的とプライバシー情報、必要な権限を案内してから許可を求めます。許可されていないデータは取得せず、権限の状態が変わったときは再確認します。健康データの連携を許可しなくても、食事・水分の手動記録は使えます。アクセスが拒否されたときは、理由と設定画面への導線を表示します。
- 目的ごとに健康データの権限を要求
- 利用目的とプライバシー情報を先に案内
- 権限を拒否しても手動記録で利用可能
- アカウント削除・連携解除時の削除対象を定義
開発中の課題と解決
分析やログに、健康情報を含めない
- 課題
- クラッシュの調査や利用状況の分析は欠かせませんが、そこに健康状態の値が含まれると、機微な情報が不要に外部へ出てしまいます。
- 解決
- クラッシュレポートや分析イベントには、睡眠時間、歩数、食事内容などの値を含めない設計にしました。健康情報、アクセストークン、食品入力などの機微情報は、ログへ不用意に出力しません。分析は、利用状況の把握に必要な最小限のイベントに限定しています。
04 — 品質と運用
リリースしてからも、安定して使える品質へ
リリース前には、iOS・Androidの実機で、ホーム表示、HealthKit/Health Connectとの連携、通信切断からの復帰、端末再起動後の同期などを確認します。重複のないデータ、権限を拒否したときの動作、同期エラーの再試行、オフライン時の挙動もテストの対象です。リリース後は、アプリのクラッシュ率、APIエラー率、応答時間、同期失敗率などを、OS別・アプリのバージョン別に監視し、異常の発生箇所を切り分けられるようにしました。
- iOS・Androidの実機でのリリース前確認
- 単体・API結合・OS連携・UI・セキュリティ・回帰テスト
- クラッシュ率・APIエラー率・同期失敗率をOS別・バージョン別に監視
- 障害・利用指標をもとに改善バックログを管理
開発中の課題と解決
再送や複数の取得元で、記録を二重にしない
- 課題
- 通信の切断や再試行で、同じ健康データが何度もサーバーへ送られることがあります。そのまま保存すると、同じ記録が二重に登録されます。
- 解決
- 健康データの同期は再送される前提で設計し、取得元ID、対象時間、同期キーや冪等性キーを用いて、同一データの二重登録を防ぎます。前回の同期位置や更新時刻を管理し、失敗したときは安全に再試行します。
Scope
担当範囲
当社は1名の体制で、設計からリリース後の改善までを一貫して担当しています。
| 工程 | 担当 |
|---|---|
| 要件整理 | ユーザー課題・シナリオ・優先順位・受け入れ条件の整理(要件一覧、ユーザーストーリー、バックログ) |
| 基本・詳細設計 | 画面遷移、データモデル、API契約、エラー処理、権限設計(画面仕様、API仕様、データ設計、状態遷移) |
| 実装 | iOS、Android、API、データ保存、監視設定 |
| テスト | 単体、結合、UI、実機、回帰テスト |
| リリース | ビルド、ストア提出、設定確認、リリース判定 |
| 改善 | 障害調査、利用指標の確認、UX改善、バックログ更新 |
Architecture
使用技術・システム構成
- iOSアプリ
- Swift / SwiftUI / HealthKit
- Androidアプリ
- Kotlin / Jetpack Compose / Health Connect
- 共通API
- REST / OpenAPI / API Gateway。認証検証、リクエスト検証、APIバージョン管理、ルーティング
- アプリケーション処理
- AWS Lambda。健康記録保存、日次集計、目標管理、食事記録処理
- 認証
- Amazon Cognito。ユーザー認証、トークン発行・検証
- データ保存
- Amazon DynamoDB。ユーザー情報、健康記録、食事ログ、目標、同期状態
- 監視・分析
- Firebase Crashlytics/Analytics(アプリ) / AWS CloudWatch(API)
- 開発・運用
- GitHub / GitHub Actions / Jira / Figma / Slack
主な技術の選定理由
ネイティブ実装(Swift/Kotlin)
OS固有の健康データの権限とバックグラウンド動作を、直接制御するためです。HealthKit・Health Connectとの連携を、それぞれのOSの作法に合わせて実装しました。
REST API+OpenAPI
バックエンドをアプリから分離し、アプリのバージョンに依存しない契約を管理するためです。エンドポイント、スキーマ、エラー形式を明示し、変更時は互換性を確認します。
API Gateway/Lambda/DynamoDB
小さな機能単位でAPIを分割できるためです。DynamoDBのキーは、ユーザー単位・対象日単位・記録時刻順という主要なアクセスパターンに合わせて設計しました。
Firebase Crashlytics/Analytics
クラッシュの再現調査と利用状況の分析のためです。分析イベントには、個人の健康状態を含めません。
Process
開発の進め方
- 1
機能単位のブランチを作成し、変更内容を小さなプルリクエストに分割します。
- 2
マージ前に、ビルド、静的チェック、ユニットテストをGitHub Actionsで実行します。
- 3
コミットメッセージとプルリクエストに、変更目的、テスト内容、影響範囲を記載します。
- 4
環境変数・秘密情報はソースコードに直書きせず、適切なシークレット管理を利用します。
- 5
リリース前に、変更一覧、データ移行の有無、ロールバック手順、監視項目を確認します。
- 6
基本機能の安定性を優先し、利用状況とデータ品質を確認しながら、段階的に機能を追加する方針です。
Quality & Security
品質・セキュリティ・運用
データ最小化・同意
機能の提供に必要な健康データだけを取得し、不要な属性は収集しません。歩数・睡眠などの権限は目的別に要求し、拒否・解除時の挙動を定義しました。
通信・認証・認可
通信はTLSで保護し、トークンや秘密情報をURLに含めません。サーバー側でトークンを検証し、ユーザーIDの特定とリソースの所有者チェックを行います。
保存データとログ
AWSの保存時暗号化を利用し、アクセス権限を最小化します。健康情報やアクセストークンなどの機微情報は、ログへ出力しません。
データ削除
アカウント削除の際は、プロフィール、健康記録、食事記録、目標、同期状態を対象として処理します。
品質の目標
ホーム画面の表示はキャッシュ済みデータで1.5秒以内、主要APIの応答時間はp95で500ms以内、クラッシュフリーセッション率は99.5%以上を目標として定めました。
健康に関する表示
表示は一般的な生活習慣の振り返りを目的とし、診断や治療の代替として誤認させない設計にしています。
Results
成果
iOS・Androidの健康データ基盤と連携し、歩数・睡眠・食事・水分摂取を一元管理する健康管理アプリです。5つの主要画面、健康記録と目標を中心とするデータモデル、REST API、AWSのバックエンド、クラッシュ・利用状況の監視を組み合わせ、日々の状態把握から生活習慣の振り返りまでを支援します。
- ホーム画面で、当日の歩数・睡眠・食事・水分と目標達成率を1画面で確認できるようにしました。
- 週単位の推移と目標達成状況から、生活習慣を振り返れるようにしました。
- 取得元・記録時刻・同期状態を管理し、重複計上や欠損を検知できるデータ設計にしました。
- 健康データの権限を目的別に扱い、許可しなくても手動記録で使える設計にしました。
FAQ
技術面のよくあるご質問
- Q. 歩数が0のときと、データが取れていないときは、区別できますか?
- 区別します。歩数0歩は有効な計測値の可能性がある一方、アクセス権限がない場合やデータソースが空の場合は別の状態として扱い、画面では「0」「未取得」「同期中」「同期エラー」を分けて表示します。
- Q. 健康データへのアクセスを許可しなくても使えますか?
- 使えます。権限を拒否しても利用可能な機能へアクセスでき、理由と設定画面への導線を表示したうえで、手動記録などを続けられます。
- Q. 同期が何度も送られると、記録が二重になりませんか?
- なりません。同期は再送される前提で設計し、取得元ID、対象時間、同期キーや冪等性キーを用いて、同一データの二重登録を防ぎます。
- Q. 健康状態の診断に使えますか?
- 使えません。健康に関する表示は一般的な生活習慣の振り返りを目的とし、診断や治療の代替として誤認させない設計です。
Tech Stack
