
풀마라톤 러너가 만든, Garmin Export를 AI 분석으로 연결하는 정규화 OSS
요약
Garmin의 러닝 데이터를 AI 분석에 용이하도록 정규화해주는 오픈소스 도구(OSS)를 소개합니다. 복잡한 데이터 구조를 일관된 형태로 변환하여 반복적인 전처리 과정을 줄이고 데이터 기반의 장기적인 분석을 가능하게 합니다.
핵심 포인트
- Garmin 에스포트 데이터를 AI 분석용으로 정규화하는 Python 기반 OSS
- JSON, FIT 등 다양한 데이터 형식을 일관된 구조로 변환
- 데이터 결측치 및 관계 명시를 통해 AI 분석의 신뢰도 향상
- CLI 기반의 일괄 정규화(run-all) 기능 제공

저는 풀마라톤을 달리고 있습니다.
서브 3:15를 달성했으며, 현재는 서브 3를 목표로 러닝을 계속하고 있습니다. Garmin에는 매일의 주행 기록이나 페이스, 심박수, 랩(Lap) 등 오랜 기간의 데이터가 축적되어 있습니다.
이것들을 AI와 함께 되돌아보려 하자, 분석 자체를 시작하기 전에 매번 비슷한 준비가 필요하다는 것을 깨달았습니다.
Garmin의 에스포트(Export) 데이터를 준비한다
→ 파일 구성을 조사한다
→ 읽는 방법을 생각한다
...
정말로 하고 싶은 것은 자신의 러닝을 되돌아보는 것입니다.
그래서 Garmin Account Data Export(Garmin 계정 데이터 에스포트)를 한 번 정리해 두면 반복해서 사용할 수 있는 형태로 만들고, 이후의 분석에 재사용할 수 있는 OSS를 만들었습니다.
Garmin Running Data Normalizer (Garmin 러닝 데이터 정규화 도구) 입니다.
- GitHub: https://github.com/tsubotti63/garmin-running-data-normalizer
- PyPI: https://pypi.org/project/garmin-running-data-normalizer/
현재 안정 버전은 v1.2.0 입니다.
이 기사에서는 이후 이 도구를 「정규화 도구」, 처리 자체를 「정규화 처리」라고 부릅니다.
왜 Garmin의 에스포트 데이터를 매번 그대로 AI에게 전달하지 않는가
이 에스포트 데이터에는 여러 데이터군, JSON, FIT, 압축 파일 등이 포함되어 있으며, 게다가 각각이 나타내는 1건의 의미가 다릅니다.
- Activity는 1회의 운동
- FIT Session은 FIT 내의 1개 운동 기록
- FIT Lap은 그 안의 랩(Lap)
- Gear는 슈즈 등의 장비
- Personal Record는 자기 기록
그때그때 임시로 하는 전처리(Pre-processing)로는 어떤 파일을 사용할지, 열 이름(Column name)이나 단위, 결측치(Missing value) 처리, 데이터 간의 연결 방법, 집계의 분모, 어디까지를 사실로 다룰 것인지——이러한 것들이 분석할 때마다 바뀌어 버립니다.
AI 모델이나 대화 내용이 바뀌면 전제 조건까지 바뀌는 경우도 있습니다. 같은 질문을 하고 있다고 생각해도, 같은 조건의 데이터에서 시작하지 않은 것입니다. 이래서는 장기적인 비교나 사후 검토가 어려워집니다.
한 번 정규화하고, 그 후에는 같은 데이터를 반복해서 사용
정규화 도구의 기본적인 흐름은 다음과 같습니다.
Garmin 에스포트 데이터
↓
로컬 환경에서 일괄 정규화
...
CLI에서는 이 일괄 정규화 명령을 run-all이라고 부릅니다. 목적은 단순히 JSON이나 FIT를 CSV로 변환하는 것이 아니라, 분석하는 사용자나 AI가 "무엇이 처리되었는지", "어떤 관계가 명시적으로 확인되었는지", "무엇이 결손/미결제 상태인지", "무엇을 결론으로 삼아서는 안 되는지"를 확인할 수 있는 상태로 만드는 것입니다.
Garmin 계정이 없어도 지금 바로 테스트 가능
실제 Garmin 데이터가 없어도 동작 확인용 합성 데이터로 테스트할 수 있습니다.
필요한 Python 버전은 3.11 이상입니다.
git clone https://github.com/tsubotti63/garmin-running-data-normalizer.git
cd garmin-running-data-normalizer
python3 -m venv .venv
...
명령어 이름에는 run-all이 포함되어 있지만, 수행하는 것은 일괄 정규화 처리입니다. 이 동작 확인에서는 실제 Garmin 데이터를 사용하지 않습니다.
실제 Garmin 데이터를 사용하는 경우는 다음 순서가 됩니다.
-
위의 합성 데이터로 설치와 동작을 확인한다
-
Garmin 공식 사이트에서 Account Data Export를 취득한다
-
다운로드한 외부 ZIP 파일을 보관하고, 그 ZIP만 압축 해제한 폴더를 입력값으로 한다 (ZIP 자체를
--input에 직접 지정하지 않는다) -
처음에는 1회분 에스포트를 정규화한다
-
run_summary.json을 확인하고,START_HERE.md를 읽는다 -
AI 분석으로 진행한다
-
동작 확인용 퀵 스타트: https://github.com/tsubotti63/garmin-running-data-normalizer/blob/main/docs/product_quick_start.md
-
실제 데이터용 도입 가이드: https://github.com/tsubotti63/garmin-running-data-normalizer/blob/main/docs/getting_started_from_garmin_export.md
이후부터는 이 정규화 도구가 어떤 개념으로 만들어졌는지에 대한 이야기입니다.
정규화 후에 「무엇을 보면 좋은가」도 출력한다
일괄 정규화가 완료되면, 정규화 데이터와 더불어 사용자용 및 AI·툴용 안내가 생성됩니다.
사용자용으로는 START_HERE.md나 DATASET_INVENTORY.md가 있으며, AI나 툴용으로는 ANALYSIS_CONTEXT.json이나 SCHEMA_CATALOG.json 같은 파일이 있습니다. run_summary.json은 처리가 완료되었음을 확인하기 위한 파일로, 먼저 이곳을 확인한 뒤 START_HERE.md를 읽고 분석으로 진행합니다.
여기서 말하는 「AI가 다루기 쉬운 상태」란, 분석에 필요한 전제와 규칙이 갖춰진 상태를 의미합니다. AI의 답변이 반드시 옳다는 의미는 아닙니다. 분석할 때는 「관측된 사실」, 「계산 결과」, 「해석의 후보」, 「모르는 것」의 4가지를 나누어 생각하며, 최종 판단은 이용하는 사용자 스스로가 수행합니다.
어디까지 근거를 확보하고 있는가
전처리를 대신해 주는 도구인 만큼, 「정말로 신뢰해도 되는 정규화인가」는 궁금한 부분일 것입니다. 여기서는 세 가지 설계 판단과 그 근거를 짧게 정리합니다.
비슷하다고 해서 연결하지 않는다. Garmin 데이터에서는 비슷한 시각이나 거리를 가진 기록이 있더라도, 동일한 Activity라고 단정할 수 있는 것은 아닙니다. 과거 한 사용자의 실제 데이터 검증(v1.1.1 시점)에서는 3,464건의 Activity와 FIT의 관계를 명시적인 근거를 통해 확인한 반면, 4건의 Activity와 1건의 대상 FIT Session은 추측으로 연결하지 않고 미결 상태로 남겨두었습니다. 「거의 전부 성공했다」는 점수가 아니라, 어디까지 근거가 닿아 있는지를 보여주는 경계선입니다 (자세한 내용은 검증 사례 CS-002).
장기간의 실제 데이터에서도 처리 결과와 재현성을 확인하고 있다. 일괄 정규화와 AI로 분석용 데이터를 인계하는 기능에 대해, 약 11.1년 분량·Activities 3,468건·FIT Sessions 3,684건·FIT Laps 37,432건의 한 사용자 실제 데이터로 대규모 검증을 수행했습니다 (v1.1.1 시점). 결과는 일부 성공을 나타내는 PARTIAL_SUCCESS로, 검출된 FIT 중 20건에 불완전한 해석 상태가 있었으나 추측으로 복구하지 않고 나중에 확인할 수 있는 형태로 남겨두었습니다. 동일한 입력과 동일한 공개 패키지로 3회 실행했을 때, 3회 모두 출력이 바이트 단위로 일치함을 확인했습니다. 다만 이는 한 사용자·한 환경에서의 검증이며, 모든 환경에서 동일한 결과가 나온다는 주장은 아닙니다 (CS-001).
보이지 않게 된 데이터를 멋대로 「삭제되었다」고 취급하지 않는다. Garmin의 에스포트(Export) 데이터를 여러 번 가져오면, 이전 에스포트에는 있었던 기록이 이후의 에스포트에서는 보이지 않을 수 있습니다.
이후의 에스포트에서 보이지 않음 != 삭제되었다는 증거
최신 에스포트만을 완전한 교체 대상으로 취급하면, 이전에 확인했던 이력을 잃어버릴 수 있습니다. v1.2.0에서는 이 문제에 대응하는 임의 기능으로서 **복수 에스포트 축적 기능 (Snapshot Accumulation, 이후 「축적 기능」)**을 추가했습니다. 동일한 Garmin 계정의 완전한 에스포트를 변경되지 않는 원본으로 등록하고, 결손이나 값의 상태 (존재하지 않음·비어 있음·과거 값을 유지함 등 7가지 상태)를 구분하면서, 여러 회차분을 통합한 정본(正本) 데이터를 재구축합니다.
하나의 Garmin 계정에서 반복적으로 취득한 4개의 완전한 에스포트(4개의 독립된 데이터군이 아님)로 검증하였으며, 확인된 범위 내에서는 6가지 모든 2개 조합 비교·24가지 모든 등록 순서·13건 모든 장애 복구 시나리오를 통과하였고, 원본 데이터의 변경은 0건이었습니다. 모든 결손을 반드시 회복한다거나, 어떤 순서에서도 반드시 같아진다는 주장은 아닙니다 (CS-007).
AI에게 넘기기 전에, 어디까지 공유할지 결정한다
Garmin의 익스포트 (Export) 데이터나 정규화 후의 모든 출력에는 개인정보 및 상세한 러닝 정보——어떤 신발로 얼마나 달렸는지, 정확한 위치와 일시, 심박수까지——가 포함됩니다. 따라서 기본적으로는 로컬 환경 또는 본인이 신뢰할 수 있는 환경에서의 분석을 권장합니다. 모든 출력을 "AI가 ZIP 파일을 읽을 수 있으니까"라는 이유만으로 외부 서비스에 전달하는 것은 상정하고 있지 않습니다.
월 단위의 활동 (Activity) 양이나 횟수만으로 충분한 경우에는, 임의 기능으로서 외부 공유용 최소 데이터 팩 (External-safe Pack) 을 analysis/external_safe_handoff.zip으로 생성할 수 있습니다. 정규화 도구 본체에서는 신발 등의 기어 (Gear) 정보도 포함하여 유지하지만, 외부 공유용 팩에서는 ID, 파일 경로, 메모, 위치 정보, 정확한 일시, 심박수, 신발 정보, FIT 파일의 상세 내용 등은 포함하지 않습니다. 공유하는 정보를 줄이는 것일 뿐, 어떤 서비스에 전달하더라도 자동으로 안전해지는 것은 아니며, 이용하는 서비스의 계약 플랜이나 보관 기간, 학습 이용 여부는 사용자 스스로 확인해야 합니다.
- AI Analysis Quick Start: https://github.com/tsubotti63/garmin-running-data-normalizer/blob/main/docs/ai_analysis_quick_start.md
어떤 분석부터 시작할 것인가
처음에는 하나의 기술적인 질문으로 범위를 좁히는 것이 안전합니다.
- 월간·주간 경향: 운동 횟수, 거리, 시간, 결측 건수 -
- 페이스와 심박수의 관계: 관측 가능한 범위 내에서의 차이 (원인은 단정하지 않음) -
- 연습 지속성과 복귀 패턴: 운동 기록이 없는 기간, 재개 후의 연습량 (이유는 추측하지 않음) -
- 데이터 품질 그 자체: 각 데이터 군의 유무, 경고, 미해결 범위
이 OSS는 연습 메뉴를 자동으로 결정하는 AI 코치가 아닙니다. 의료 진단, 부상 평가, 피로 및 컨디션의 단정, 연습 메뉴 지시, 인과관계의 단정은 이 제품이 제공하는 범위를 벗어납니다.
현재 대응 상황
| 환경 | 현재의 위치 설정 |
|---|---|
| macOS | 개발자 본인이 동작 확인 완료 |
| ... |
Windows를 대상에서 제외하고 있는 것은 아닙니다. 합성 데이터 (Synthetic Data)를 사용한 동작 확인 결과나, 가이드에서 혼란스러웠던 부분을 개인 데이터를 포함하지 않고 Support로 보고해 주시면 도움이 됩니다.
- AI 분석 시작하기: https://github.com/tsubotti63/garmin-running-data-normalizer/blob/main/docs/ai_analysis_quick_start.md
- 자주 묻는 질문 (FAQ): https://github.com/tsubotti63/garmin-running-data-normalizer/blob/main/docs/faq.md
향후 검토 사항
현재의 v1.2.0 이후로는 다음과 같은 전개를 검토하고 있습니다. 다만, 이들은 모두 현재의 일괄 정규화에서 제공 중인 기능이 아니며, 제공 시기나 순서를 약속하는 것은 아닙니다.
- 웰니스/메트릭스 (Wellness/Metrics) 계열: 수면, HRV, 건강 상태에는 라이브러리 레벨의 구현이 있으나, 현재의 정식 일괄 정규화 대상은 아닙니다. 일괄 정규화에 포함할 수 있을지를 향후 평가할 예정입니다. -
- Open-Meteo 대응 및 GUI화: 향후 검토 후보입니다. 현재 Repository의 공개 문서에서 구체적으로 명시된 것은, Open-Meteo를 프라이버시 및 이용 조건 등을 포함하여 별도로 확인한다는 방침까지입니다. GUI를 포함한 버전 번호, 제공 시기, 구현 순서는 확정되지 않았습니다.
앞으로 기사에서 자세히 다룰 내용
이번에는 제품 전체를 알리기 위한 요약이었습니다. 다음 회차부터는 이번에 간략히 언급한 부분들을 개별적으로 깊이 있게 다룰 예정입니다.
- 이후의 익스포트로 인해 보이지 않게 된 기록으로부터 이력을 보호하는 축적 기능
- 일괄 정규화, 품질 확인, 감사용 정보, 데이터의 출처 및 처리 이력
- AI로 분석 데이터를 인계하는 메커니즘과 공유 범위를 결정하는 방법
- 데이터 간의 관계와 "모르는 것을 남겨두는" 설계
- 합성 데이터를 사용한 분석 예시와 검증 사례 (Case Study)
- AI Collaboration Platform을 사용한 OSS 개발 운영
주역은 Garmin Running Data Normalizer입니다. 6번째인 AI Collaboration Platform은 이 OSS를 어떻게 설계, 리뷰, 공개하고 있는지를 설명하는 보조적인 위치로 설정합니다.
요약
Garmin Running Data Normalizer가 목표로 하는 것은,
Garmin 데이터를 단 한 번 안정적인 형태로 정규화하여, 사용자와 AI가 동일한 검증된 데이터를 사용해 반복적으로 분석할 수 있도록 하는 것입니다.
관계가 불분명한 데이터나 불완전한 FIT 파일은 그럴듯한 추측으로 채우지 않고, 나중에 확인할 수 있는 형태로 남겨둡니다. AI에는 계산과 정리를 도와달라고 요청하되, 공유 범위와 해석에 대한 최종 판단은 사용자 스스로 수행합니다.
동일한 과제를 느끼고 있는 Garmin 사용자, 러너, Python 사용자분들은 우선 위의 합성 데이터(Synthetic Data)를 통한 동작 확인부터 시도해 보시기 바랍니다. 다음 기사도 이 계정을 통해 공개할 예정입니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기