자동화: 일정에 따라 전달되는 내 데이터
Marrow는 원하는 주기로, 휴대폰에서 직접, 원하는 URL에 건강 데이터 파일을 POST할 수 있어요. 이 페이지는 레퍼런스예요. 설정 방법, 각 페이로드의 모양, 그리고 이를 받는 수신기를 만드는 방법을 담았어요.
n8n, Zapier, Make, Home Assistant, Google Sheets, InfluxDB용 설정 예시는 연결에 준비되어 있어요.
Marrow 가이드 전체: MCP · 셀프 호스팅 미러 · 자동화 · 파일 · 지원
자동화란?
내보내기, 자동에 저장된 작업이에요. 데이터 종류 하나, 형식 하나, 날짜 범위 하나, URL 하나, 주기 하나로 이루어져요. Marrow는 검증된 저장소에서 파일을 만들어, 앱이 닫혀 있어도 동기화가 끝날 때마다, 그리고 백그라운드 새로고침 때 주기가 지났다면 URL로 POST해요. 우리 서버를 거치는 것은 없어요. 휴대폰이 내 엔드포인트와 직접 통신해요.
설정하는 방법
- 내보내기 탭, 자동: 켠 다음 새로운 자동화를 탭하세요. 도구의 페이지(연결의 n8n, Zapier, Home Assistant 등)에서 만들면 자동화에 그 도구의 이름이 붙고, 각 항목 옆에 그 도구가 거기에 무엇을 원하는지 안내가 나와요.
- 주소: POST할 https URL이에요. 헤더: 수신기가 필요로 하는 것(
Authorization베어러 토큰,X-Gitlab-Token등 무엇이든). 도구에 필요 없는 경우 헤더 추가는 옵션 더 보기에 있어요. - 데이터: 건강 지표, 운동, 근력 운동 기록, 영양 일기, 증상 및 기분을 JSON이나 CSV로 보내요. 자동화 하나는 한 종류만 보내므로 원하는 종류마다 하나씩 만드세요. 켜져 있는 자동화는 각각 연결 하나로 계산돼요. 무료는 한 번에 연결 1개, Marrow Pro는 최대 10개까지 켤 수 있고, AI와 서버도 포함돼요.
- 주기: 몇 분, 몇 시간 또는 며칠마다. 날짜 범위, 집계 방식, 타임아웃은 옵션 더 보기에 있어요.
- 지금 실행은 첫 페이로드를 보내서, 일정을 기다리기 전에 수신기를 확인할 수 있어요.
날짜 범위
- 마지막 실행 이후(기본값): 마지막 성공한 실행 이후의 모든 데이터에서 이틀을 겹쳐서 보내요. HealthKit은 하루가 끝난 뒤에도 그날의 데이터를 계속 채우기 때문에, 겹치는 구간에서 최근에 끝난 날들을 다시 보내요. 내 쪽에서 지표와 날짜별로 최신 값을 유지하면 반복 전송은 문제가 되지 않아요. 한동안 꺼져 있던 수신기는 처음 성공하는 실행에서 놓친 모든 날을 받아요.
- 오늘, 최근 7 / 30 / 90일, 최근 1년: 고정된 이동 구간으로, 실행할 때마다 전체를 다시 보내요. 변경분보다 스스로 복구되는 스냅숏이 좋다면 이쪽을 고르세요.
페이로드 형태
건강 지표 (일일 합계, JSON)
Health Auto Export의 지표와 같은 구조예요(name, units, data(qty 포함)로 이루어진 metrics 목록). 그 앱용으로 만든 수신기도 조금만 고치면 돼요. 여기서 날짜는 타임스탬프가 아니라 일 단위이고, 아래 운동과 근력 페이로드는 Marrow 고유 형식이에요. 값은 units에 적힌 저장 단위(kg, m, mL, degC, kcal, count)로 와요. 심박수는 하루의 Avg, Min, Max를 bpm으로, 수면은 단계가 포함된 밤별 기록을 시간 단위로 보내요. 야드파운드법이 필요하면 받는 쪽에서 변환하세요.
{"data": {"metrics": [
{"name": "body_mass", "units": "kg",
"data": [{"date": "2026-09-11", "qty": 81.3}]},
{"name": "step_count", "units": "count",
"data": [{"date": "2026-09-11", "qty": 8746}]},
{"name": "heart_rate", "units": "bpm",
"data": [{"date": "2026-09-11", "Avg": 71, "Min": 52, "Max": 148}]},
{"name": "sleep_analysis", "units": "h",
"data": [{"date": "2026-09-11", "totalSleep": 7.2, "asleep": 7.2, "deep": 1.1, "rem": 1.6, "core": 4.3, "awake": 0.2,
"sleepStart": "2026-09-10 23:36:00 -0400", "sleepEnd": "2026-09-11 07:02:00 -0400"}]}
]}}
원본 샘플(원본 샘플 그룹)은 일일 합계 대신 모든 샘플을 시작 시간과 끝 시간과 함께 보내요. CSV 지표는 파일 페이지에 설명된 넓은 표로 와요.
운동
{"data": {"workouts": [
{"activity": "Running", "start": "2026-09-11T18:43:41Z", "end": "2026-09-11T19:13:53Z",
"duration_min": 30.2, "kcal": 512, "distance_mi": 3.06, "avg_hr": 174, "source": "Apple Watch"}
]}}
근력 운동 기록
모든 본 세트(워밍업은 제외)와 운동별 진행 상황, 근육군별 볼륨이 들어가요. 무게는 설정, 단위에서 고른 단위예요. 어떤 단위인지는 unit 필드에 나와요. 각 세트의 set_type은 work, failure, drop 중 하나이고, 여유 반복 횟수를 기록했다면 rir도 들어가요. set_credits는 근육군에 반영된 세트 수이고, 한 운동이 여러 근육군에 쓰이면 소수로 나눠요.
{"data": {"unit": "lb",
"sets": [{"time": "2026-09-11T17:02:00Z", "session": "Push day", "exercise": "Bench Press",
"set": 1, "weight": 185, "reps": 8, "est_1rm": 229.6, "set_type": "work"}],
"exercises": [{"exercise": "Bench Press", "best_est_1rm": 229.6,
"sessions": [{"date": "2026-09-11T17:02:00Z", "sets": 3, "top_weight": 185, "top_reps": 8, "est_1rm": 229.6, "volume": 3885}]}],
"muscle_groups": [{"group": "Chest", "volume": 3108.0, "set_credits": 2.4}]
}}
영양 일기
{"data": {"days": [
{"day": "2026-09-11", "entries": [
{"meal": "breakfast", "name": "Oatmeal", "grams": 250, "kcal": 300,
"protein_g": 10, "carbs_g": 54, "fat_g": 5, "logged_at": "2026-09-11T12:10:00Z",
"nutrients": {"dietary_fiber": 8.0, "dietary_sugar": 1.2}}
]}
]}}
수신기 만들기
HTTPS POST를 받고 2xx로 응답하는 곳이라면 어디든 돼요. 웹훅 서비스, 서버리스 함수, 홈 서버의 스크립트 모두 가능해요. 세 가지 규칙을 지키면 튼튼해져요:
- 마지막 값이 우선이에요. 값을 (지표, 날짜) 또는 항목 자체의 식별자를 키로 저장하고, 같은 키가 다시 오면 덮어쓰세요. 구간은 일부러 겹치게 되어 있어요.
- 원본 본문을 먼저 보관하세요. 그다음에 파싱하세요. 파서 버그 때문에 데이터를 잃는 일은 없어야 해요.
- 빨리 응답하세요. Marrow는 설정한 타임아웃(기본 60초)까지 기다리고, 그 시간이 지나면 실행을 실패로 표시해요. 실패한 실행은 다음 주기에 마지막으로 성공한 구간부터 다시 시도해요.
모든 POST를 보관하는 열두 줄짜리 Python 수신기:
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
class H(BaseHTTPRequestHandler):
def do_POST(self):
body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
with open(f"marrow-{int(time.time())}.json", "wb") as f:
f.write(body)
self.send_response(200)
self.end_headers()
HTTPServer(("0.0.0.0", 8798), H).serve_forever()
HTTPS 뒤에 두고(Cloudflare Tunnel, Tailscale Funnel 또는 아무 리버스 프록시) 자동화가 그곳을 가리키게 하세요. 파일 폴더보다 질의할 수 있는 사본이 필요하다면 셀프 호스팅 미러가 이미 만들어진 그 수신기예요.
알아 두면 좋은 점
- 자동화는 iOS가 앱 실행을 허용할 때만 실행돼요. 동기화 커밋 후, 포그라운드 새로고침 때, 백그라운드 새로고침 중에요. 하루 종일 잠겨 있는 휴대폰은 다음에 잠금을 풀 때 보내요. 마지막 실행 이후 구간이 그 사이를 채워 줘요.
- 모든 실행은 자동화의 활동 기록(옵션 더 보기)에 결과와 함께 남아서, URL이 잘못 설정되었을 때 서버뿐 아니라 앱에서도 볼 수 있어요.
- 자동화를 복제하면 헤더를 다른 종류에 재사용할 수 있어요.
문제 해결
지금 실행으로 테스트하세요. 그 아래 한 줄이 무슨 일이 있었는지 알려 주고, 옵션 더 보기, 활동 기록에 최근 30번의 실행이 같은 한 줄로 남아요. 확인하는 동안 실행할 때마다 알림을 받으려면 실행 시 알림(옵션 더 보기)을 켜세요.
| Marrow에 표시되는 내용 | 해결 방법 |
|---|---|
12 diary entries 같은, 전송한 내용의 요약 | 전달됨: 수신기가 2xx로 응답했어요. 수신기 쪽에 아무것도 보이지 않으면 아래 마지막 행을 확인하세요. |
Server answered 401 또는 403 | 수신기가 헤더를 요구하거나 추가한 헤더가 잘못되었어요. 이름과 값을 확인하세요. Bearer와 그 뒤의 공백도 포함해서요. |
Server answered 404 | 주소가 잘못되었거나 수신기가 응답하지 않아요. n8n에서는 Production URL을 쓰고 워크플로를 활성화하세요. 끝에 경로가 빠졌는지 확인하세요. |
Server answered 405 | 이 주소는 POST를 받지 않아요. 들어오는 데이터를 받도록 만든 엔드포인트를 가리키게 하세요. |
Server answered 413 | 페이로드가 수신기에 비해 너무 커요. 날짜 범위를 줄이거나 지표 수를 줄이거나, 원본 샘플 대신 일일 합계를 고르세요. |
Server answered 500 또는 다른 5xx | 수신기가 처리하다가 실패했어요. 수신기의 로그를 보세요. 원본 본문을 먼저 보관한 다음 파싱하세요. |
| 요청한 시간이 초과되었습니다 | 수신기가 타임아웃보다 오래 걸렸어요. 먼저 응답하고 나중에 작업하거나, 옵션 더 보기의 타임아웃을 늘리세요(최대 300초). |
| App Transport Security 정책에서는 보안 연결을 사용해야 합니다 | 인터넷에서 일반 http 주소를 쓰고 있어요. https를 사용하세요. iOS는 내 네트워크 안에서만 Marrow가 일반 http를 쓰도록 허용해요. |
| 지정한 호스트 이름의 서버를 찾을 수 없습니다 | 주소에 오타가 있거나 내 집 네트워크에서만 아는 이름이에요. 휴대폰의 Safari에서 확인해 보세요. |
No valid URL - set an https endpoint first | 주소가 비어 있거나 https://(내 네트워크에서는 http://)로 시작하지 않아요. |
Nothing to export in this range | 날짜 범위에 해당 종류의 데이터가 없어요. 옵션 더 보기에서 더 긴 범위를 고르거나 먼저 무언가를 기록하세요. |
- 전달됐다고 나오는데 아무것도 도착하지 않아요. 일부 수신기는 데이터를 버리면서도 200으로 응답해요. Home Assistant는 웹훅 ID가 틀리면 그렇게 하고, Apps Script 레시피는
?key=가 틀리면 그렇게 해요. Zapier와 Make는 편집기에서 샘플을 불러오기 전까지 아무것도 보여 주지 않아요. 수신기의 기록이나 로그를 확인하세요. - 실행이 늦거나 아예 되지 않아요. 백그라운드 실행 시점은 iOS가 정해요. 동기화 후, Marrow를 열 때, 백그라운드 새로고침 중에요. Marrow의 백그라운드 앱 새로 고침을 켜 두세요(설정, 일반, 백그라운드 앱 새로 고침). 저전력 모드에서는 백그라운드 실행이 보류되고, 계속 잠겨 있는 휴대폰은 다음에 잠금을 풀 때 보내요. 마지막 실행 이후는 성공하는 다음 실행에서 따라잡아요.
- 집 네트워크의 수신기. Marrow가 닿으려면 로컬 네트워크 접근이 필요해요: 설정, 개인정보 보호 및 보안, 로컬 네트워크. Marrow를 연 채로 지금 실행을 한 번 탭하면 iOS가 물어봐요. 백그라운드에서는 답하기 전까지 iOS가 묻지도 않고 거부해요.
- 앱을 위로 쓸어서 종료했어요. 앱 전환기에서 Marrow를 위로 쓸어 종료하면, 다시 열기 전까지 iOS가 백그라운드에서 깨우지 않을 수 있어요.
- 같은 날이 두 번 도착해요. 일부러 그래요. 마지막 실행 이후는 Apple Health가 계속 채우는 최근 이틀을 다시 보내요. 지표와 날짜별로 최신 값을 유지하세요.
- 켜지지 않아요. 켜진 자동화는 각각 연결 하나로 계산돼요. 무료는 한 번에 연결 1개, Marrow Pro는 최대 10개예요. AI, 서버, 자동화를 모두 합쳐서요. 다른 하나를 먼저 끄세요.
- 단위가 이상해 보여요. 지표는
units에 적힌 저장 단위(kg, m, mL, degC, kcal)로 도착해요. 근력 세트는 설정, 단위를 따르고, 어느 단위인지는unit필드에 나와요.
도구별 해결 방법은 각 도구의 페이지에 있어요: n8n, Zapier, Make, Home Assistant, Google Sheets, InfluxDB, 원하는 URL.