Google Health API는 개발자가 Fitbit 사용자 데이터를 쿼리할 수 있도록 처음부터 빌드된 새로운 API입니다. 이번 업데이트는 단순한 업데이트가 아니라 앱이 안전하고 안정적이며 향후 건강 기술 발전에 대비할 수 있도록 하는 전략적 조치입니다. 이 API는 앱 등록을 위한 새로운 콘솔, Google OAuth 2.0 지원, 새로운 데이터 유형, 새로운 엔드포인트 스키마, 새로운 응답 형식을 지원합니다.
이 가이드는 개발자가 기존 Fitbit Web API 앱을 새로운 Google Health API로 이전하는 데 도움이 되도록 설계되었습니다.
마이그레이션해야 하는 이유
Google Health API 사용의 이점은 다음과 같습니다.
- 보안 강화: Google의 보안 권장사항을 준수하여 Google의 보안, 개인 정보 보호, ID 표준을 따릅니다.
- 일관성: 데이터 형식, 시간대, 측정 단위, 오류 처리의 기존 불일치를 없애 개발자 환경을 더 직관적으로 만듭니다.
- 확장성 및 미래 대비: 향후 요구사항을 충족하도록 확장할 수 있도록 설계되었으며 gRPC와 같은 최신 프로토콜을 지원합니다.
앱 등록
모든 Google Health API 앱은 모든 Google 앱을 관리하는 중앙 허브 역할을 하는 Google Cloud 콘솔을 사용하여 등록해야 합니다.
앱을 등록하는 방법은 시작하기의 단계를 따르세요. 앱을 등록할 때 확인할 수 있는 차이점은 다음과 같습니다.
| Fitbit Web API | Google Health API | |
| 공개 링크 | https://dev.fitbit.com/apps | https://console.cloud.google.com |
| 새 앱 추가 | 새 앱 등록을 누릅니다. |
|
| 기본 정보 | 작성해야 할 입력란:
|
작성해야 할 입력란:
|
| 애플리케이션 유형 | 개발자는 다음을 선택해야 합니다.
|
|
| 클라이언트 ID | 애플리케이션 설정이 저장될 때 등록됨 | 별도로 등록됨 |
| 액세스 유형 | 읽기 및 쓰기 액세스는 앱 수준에서 제어됩니다. | 읽기 및 쓰기 액세스는 범위 수준에서 제어됩니다. |
| 추가 URL |
|
|
OAuth 구현
Google Health API 앱은 Google OAuth2 클라이언트 라이브러리만 지원합니다. 널리 사용되는 프레임워크에 클라이언트 라이브러리를 사용할 수 있어 OAuth 2.0을 더 간단하게 구현할 수 있습니다. Google OAuth2 라이브러리와 오픈소스 OAuth2 라이브러리의 차이점은 다음과 같습니다.
| Fitbit Web API | Google Health API | |
| OAuth2 라이브러리 지원 | 오픈소스 | Google OAuth2 클라이언트 라이브러리 |
| 작동 방식 | 플랫폼 간에 일관되지 않음 | 여러 플랫폼에서 일관성 유지 |
| 승인 URL | https://www.fitbit.com/oauth2/authorize | https://accounts.google.com/o/oauth2/v2/auth |
| 토큰 URL | https://api.fitbit.com/oauth2/token | https://oauth2.googleapis.com/token |
| Access Token Lifetime(액세스 토큰 수명) | 8시간 | 1시간 |
| 액세스 토큰 크기 | 1,024바이트 | 2,048바이트 |
| 토큰 갱신 | 갱신 토큰은 승인 코드 부여 플로우를 사용할 때 생성됩니다. 사용자당 하나의 갱신 토큰만 생성할 수 있습니다. 토큰은 만료되지 않으며 한 번만 사용할 수 있습니다. | 갱신 토큰을 생성하려면 승인 문자열에 쿼리 매개변수 'access_type=offline'이 포함되어야 합니다. 단일 사용자에 대해 여러 개의 갱신 토큰을 만들 수 있습니다. 갱신 토큰은 시간 기반일 수 있습니다. 6개월 동안 사용되지 않았거나, 사용자가 시간 기반 액세스 권한을 부여했거나, 앱이 '테스트' 모드인 경우 만료됩니다. 자세한 내용은 갱신 토큰 만료를 참고하세요. |
| 토큰 응답 | JSON 응답에는 다음이 포함됩니다.
|
JSON 응답에는 다음이 포함됩니다.
사용자 ID를 가져오려면 users.getIdentity 엔드포인트를 사용하세요. |
사용자 재인증 (필수 재동의)
앱에서 다른 OAuth 라이브러리를 사용하므로 Fitbit 사용자는 새 통합에 다시 동의해야 합니다. 액세스 토큰과 갱신 토큰을 Google Health API로 전송하여 작동시킬 수는 없습니다.
범위
Google Health API 범위를 사용하도록 승인 요청을 업데이트해야 합니다. 범위는 앱이 읽기 또는 쓰기 작업을 지원하는지 여부를 정의합니다. 앱에 필요하지 않은 범위를 사용하지 마세요. 앱의 디자인이 변경되면 나중에 언제든지 범위를 추가할 수 있습니다.
Google Health API 범위는 https://www.googleapis.com/auth/googlehealth.{scope}로 시작하는 HTTP URL입니다. 예를 들어 https://www.googleapis.com/auth/googlehealth.activity_and_fitness입니다.
범위 매핑
Fitbit Web API 범위가 Google Health API 범위에 매핑되는 방식은 다음과 같습니다.
| Fitbit Web API 범위 | Google Health API 범위 |
|---|---|
| 활동 | .activity_and_fitness .activity_and_fitness.readonly |
| cardio_fitness | .activity_and_fitness .activity_and_fitness.readonly |
| 심박수 | .health_metrics_and_measurements .health_metrics_and_measurements.readonly |
| 위치 | .location.readonly |
| 영양 | .nutrition .nutrition.readonly |
| oxygen_saturation | .health_metrics_and_measurements .health_metrics_and_measurements.readonly |
| 프로필 | .profile .profile.readonly |
| respiratory_rate | .health_metrics_and_measurements .health_metrics_and_measurements.readonly |
| 설정 | .settings .settings.readonly |
| sleep | .sleep .sleep.readonly |
| 기온 | .health_metrics_and_measurements .health_metrics_and_measurements.readonly |
| 무게 | .health_metrics_and_measurements .health_metrics_and_measurements.readonly |
데이터 유형
다음은 Google Health API 데이터 유형과 Fitbit Web API에 매핑되는 방식의 목록입니다.
| Fitbit Web API 데이터 유형 | Google Health API 데이터 유형 엔드포인트 ID |
|---|---|
| 액티브존 미닛 | 액티브존 미닛active-zone-minutes
|
| 사용자의 활동 수준 변경사항을 포함합니다. | 활동 수준activity-level
|
| 고도 | 고도altitude
|
| 체지방 | 체지방body-fat
|
각 심박수 구간의 caloriesOut |
심박수 구간의 칼로리calories-in-heart-rate-zone
|
| HRV 요약 | 일일 심박 변이도daily-heart-rate-variability
|
| SpO2 요약 | 일일 산소 포화도daily-oxygen-saturation
|
| 안정 시 심박수 | 일일 안정 시 심박수daily-resting-heart-rate
|
| 피부 온도 | 일일 수면 온도 파생daily-sleep-temperature-derivations
|
| 거리 | 거리distance
|
| 기록된 활동 | 운동exercise
|
| 층수 | 층수floors
|
| 심박수 | 심박수heart-rate
|
| HRV 일중 | 심박 변이도heart-rate-variability
|
| SpO2 일중 | 산소 포화도oxygen-saturation
|
| 사용자가 러닝할 때의 VO2 Max 값 | 러닝 최대 산소 소비량run-vo2-max
|
| 활동 시계열(분) - 활동량 부족 | 활동이 없는 시간sedentary-period
|
| 수면 | 수면sleep
|
| 단계 | 단계steps
|
활동 caloriesOut개 |
총 칼로리total-calories
|
| 최대 산소 소비량 값 | 최대 산소 소비량vo2-max
|
| 무게 | 가중치weight
|
엔드포인트
REST 엔드포인트는 모든 데이터 유형에 일관된 구문을 채택합니다.
- 서비스 엔드포인트: 기본 HTTP URL이 https://health.googleapis.com으로 변경됩니다.
- 엔드포인트 구문: Google Health API는 지원되는 대부분의 데이터 유형에서 사용할 수 있는 제한된 수의 엔드포인트를 지원합니다. 이렇게 하면 모든 데이터 유형에 일관된 구문이 제공되고 엔드포인트를 더 쉽게 사용할 수 있습니다.
- 사용자 식별자: 엔드포인트 구문에서 사용자 ID 또는 me를 지정해야 합니다. me를 사용하는 경우 사용자 ID는 액세스 토큰에서 추론됩니다.
예: 다음은 Google Health API를 사용하여 호출된 GET 프로필 엔드포인트의 예입니다.
GET https://health.googleapis.com/v4/users/me/profile
엔드포인트 매핑
사용 가능한 데이터 유형과 지원되는 API 메서드의 목록은 데이터 유형 가용성 표를 참고하세요.
| Fitbit Web API 엔드포인트 유형 | Google Health API |
| 단일 일의 데이터를 요청하는 GET (로그 | 요약 | 일일 요약) | windowSize = 1일인 dailyRollup 메서드 |
| 세부 데이터를 요청하는 경우 GET (일중) | list 메서드 |
| 날짜 또는 간격별 GET (시계열) | 날짜 범위를 포함하는 rollUp 또는 dailyRollUp 메서드 |
| GET (로그 목록) | list 메서드 |
| 로그 생성 및 업데이트 | patch 메서드 |
| 로그 삭제 | batchDelete 메서드 |
| 프로필 가져오기 | users.getProfile은 사용자의 특정 정보를 반환합니다.
users.getSettings는 사용자의 단위와 시간대를 반환합니다. |
| 프로필 업데이트 | users.updateProfile은 사용자의 특정 정보를 수정합니다.
users.updateSettings은 사용자의 단위와 시간대를 수정합니다. |
| 사용자 ID 가져오기 | users.getIdentity는 사용자의 Fitbit 기존 및 Google 사용자 ID를 반환합니다. |
사용자 이전
Fitbit Web API에서 Google Health API로 이전하는 것은 기술 업데이트 이상의 의미가 있습니다. OAuth 라이브러리가 변경되어 사용자가 새 통합에 다시 동의해야 합니다. 액세스 토큰과 갱신 토큰을 Google Health API로 전송하여 작동하도록 할 수는 없습니다. 마이그레이션 중에 사용자 리텐션을 지원하기 위해 성공적인 마이그레이션을 위한 몇 가지 기술적 및 전략적 제안사항을 소개합니다.
이중 라이브러리 전략
Fitbit Web API와 Google Health API는 서로 다른 OAuth2 라이브러리를 사용하므로 코드베이스에 두 라이브러리가 모두 있는 '브리징' 기간을 관리해야 합니다.
병렬 승인 관리
- 클라이언트 캡슐화: '건강 서비스'의 추상화 레이어 또는 인터페이스를 만듭니다. 이렇게 하면 앱의 나머지 부분에서 특정 사용자에 대해 활성화된 라이브러리 (Fitbit OAuth와 Google OAuth)를 알지 못해도 데이터를 요청할 수 있습니다.
- 데이터베이스 스키마 업데이트:
oauth_type플래그를 포함하도록 사용자 테이블을 업데이트합니다. 예를 들어 Fitbit OAuth에는fitbit를 사용하고 Google OAuth에는google를 사용합니다.- 신규 사용자: Google Health API 및 Google OAuth 라이브러리가 기본값입니다.
oauth_type를google로 설정합니다. - 기존 사용자: 재동의 흐름을 완료할 때까지 Fitbit Web API를 유지합니다.
oauth_type를fitbit로 설정합니다.
- 신규 사용자: Google Health API 및 Google OAuth 라이브러리가 기본값입니다.
'단계별' 재동의 절차
강제 로그아웃 대신 증분 승인 방식을 사용하세요.
- Fitbit 오픈소스 토큰 감지: Fitbit Web API 사용자가 앱을 열면 '서비스 업데이트' 알림을 트리거합니다.
- Google OAuth 흐름 실행: 사용자가 '업데이트'를 클릭하면 Google OAuth2 라이브러리 흐름을 시작합니다.
- 바꾸기 및 취소: Google OAuth 토큰을 수신하면 사용자 프로필에 저장하고
oauth_type을fitbit에서google로 업데이트하고 (가능한 경우) 이전fitbit토큰을 프로그래매틱 방식으로 취소하여 사용자의 보안 프로필을 정리합니다.
사용자 유지율 극대화
재동의는 고객 이탈의 '위험 지대'입니다. 사용자가 앱을 포기하지 않도록 하려면 다음 UX 권장사항을 따르세요.
'가치 우선' 커뮤니케이션
'API가 업데이트되었습니다'로 시작하지 마세요. 새로운 Google 지원 시스템의 이점을 강조하세요.
- 보안 강화: Google의 업계 최고 수준의 계정 보호 및 2FA를 언급합니다.
- 안정성: 동기화 시간이 단축되고 데이터 연결이 더 안정적입니다.
- 기능 게이팅: 새 기능과 데이터 유형을 사용하려면 업데이트가 필요하다고 사용자에게 부드럽게 알립니다.
스마트 타이밍
- 가치가 높은 작업 방해 금지: 사용자가 운동 중이거나 음식 기록을 하는 중에 동의 다시 받기 화면을 트리거하지 마세요.
- '푸시' 단계: 처음 30일 동안은 닫을 수 있는 배너를 사용합니다.
- '강제 종료' 단계: 공식 Fitbit Web API 지원 중단 기한과 일치하도록 몇 주간 경고한 후에만 재동의를 필수사항으로 만듭니다.
이전 흐름 비교
이전 흐름과 새 흐름을 시각적으로 명확하게 구분하면 개발자가 로직이 분기되는 위치를 이해하는 데 도움이 됩니다.
| 기능 | Fitbit Web API (기존) | Google Health API (Google-Identity) |
| 인증 라이브러리 | 표준 오픈소스 | Google ID 서비스 (GIS) / Google 인증 |
| 사용자 계정 | Fitbit 기존 사용자 인증 정보 | Google 계정 |
| 토큰 유형 | Fitbit 전용 액세스 / 새로고침 | Google에서 발급한 액세스/새로고침 토큰 |
| 범위 관리 | 광범위한 권한 | 세분화된 / 증분 권한 |
계정 이전의 미묘한 차이 처리
Fitbit 문서에 따르면 계정을 Google로 이전하는 사용자는 일반적으로 서드 파티 연결을 즉시 잃지 않지만 API 버전을 변경하는 것은 개발자 측 요구사항입니다.
- 토큰 유효성 확인: 백그라운드 작업자를 사용하여 Fitbit 토큰이 '승인되지 않음' 오류로 실패하는지 확인합니다. 이는 사용자가 계정을 이전했지만 앱이 이를 따라가지 못했음을 나타낼 수 있습니다.
- 그레이스풀 실패: Fitbit OAuth 호출이 실패하면 새 Google OAuth 흐름을 구체적으로 사용하는 맞춤 'Fitbit 다시 연결' 페이지로 사용자를 리디렉션합니다.
코드 예
기존 Fitbit Web API에서 Google Health API로 이전하려면 일반 OAuth2 라이브러리에서 Google Auth 라이브러리로 이동해야 합니다. 다음은 이 '이중 라이브러리' 상태를 처리하기 위한 아키텍처 제안과 JavaScript로 작성된 의사 코드 구현입니다.
1. '미들웨어 스위치'
모든 사용자를 한 번에 이전할 수 없으므로 백엔드에서 데이터베이스에 저장된 사용자의 현재 apiVersion에 따라 사용할 라이브러리를 결정해야 합니다.
구현
const { OAuth2Client } = require('google-auth-library');
const FitbitV1Strategy = require('fitbit-oauth2-library').Strategy;
// 1. Initialize the Google Health API Client
const GHAClient = new OAuth2Client(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
process.env.REDIRECT_URI
);
// 2. Create a Unified Fetcher
async function fetchSteps(user) {
if (user.apiVersion === 4) {
// ---- GOOGLE OAUTH LIBRARY LOGIC ----
GHAClient.setCredentials({ refresh_token: user.refreshToken });
const url = 'GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints';
const res = await GHAClient.request({ url });
return res.data;
} else {
// ---- FITBIT WEB API LEGACY LOGIC ----
// Use your existing Fitbit open-source library logic here
return callLegacyV1Api(user.accessToken);
}
}
2. UX 흐름 마이그레이션
보관을 극대화하려면 '중단 후 업그레이드' 패턴을 사용하세요. 이렇게 하면 사용자가 앱에 이미 참여할 때까지 다시 로그인하지 않아도 됩니다.
리디렉션 로직
Fitbit Web API 사용자가 특정 기능을 사용하면 마이그레이션을 트리거합니다.
app.get('/dashboard', async (req, res) => {
const user = await db.users.find(req.user.id);
if (user.apiVersion === 1) {
// Render a "soft" migration page explaining the Google transition
return res.render('migrate-to-google', {
title: "Keep your data syncing",
message: "Fitbit is moving to Google accounts. Re-connect now to stay updated."
});
}
const data = await fetchSteps(user);
res.render('dashboard', { data });
});
3. 주요 기술 전환
JavaScript 이전 스크립트를 작성할 때는 다음 차이점에 유의하세요.
| 기능 | Fitbit Web API (기존) | Google Health API (Google-Identity) |
| 토큰 엔드포인트 | https://api.fitbit.com/oauth2/token | https://oauth2.googleapis.com/token |
| 인증 라이브러리 | 표준 오픈소스 | Google 인증 |
| 범위 | 활동 | https://www.googleapis.com/auth/googlehealth.activity_and_fitness |
| 사용자 ID | /oauth2/token 응답에서 반환된 Fitbit 인코딩 ID | users.getIdentity 엔드포인트에서 반환된 사용자 ID |
4. 유지 체크리스트
- 세션 지속성: Google Health API access_token이 성공적으로 확인되고 데이터베이스에 저장될 때까지 사용자의 이전 Fitbit Web API 세션을 삭제하지 마세요.
- 자동 취소: Google Health API 이전이 완료되면 POST 요청을 사용하여 기존 Fitbit 취소 엔드포인트(https://api.fitbit.com/oauth2/revoke)를 사용합니다. 이렇게 하면 사용자의 Fitbit 설정에 '중복' 앱 권한이 표시되지 않습니다.
- 오류 처리: Fitbit 호출에서 401 Unauthorized가 반환되면 오류 메시지를 표시하는 대신 Google OAuth 흐름으로 자동 리디렉션합니다.