한 끼에 탄수 50g을 넘기지 않으면 혈당이 거의 움직이지 않는다
기간: 2026-01-01 ~ 2026-04-10 (Apple Health 100일) 데이터: Health Data Bridge 로컬 스냅샷 분석 단위: 개별 식사 이벤트 (N=1, 탐색적)
한 줄
이 100일 동안 내 몸이 보여준 가장 선명한 규칙은 "식후 걷기"가 아니라 "한 끼 탄수 총량"이었다. 50g 이하 식사는 혈당이 거의 움직이지 않고, 100g을 넘기면 평균 45 mg/dL까지 튄다.
왜 이걸 찾게 됐나
원래 찾으려던 건 전혀 다른 것이었다. Apple Health 100일치를 훑어서 "식후 10분 걷기가 실제로 내 혈당 스파이크를 낮추는가"를 보려고 했다. 당시 가지고 있던 재료는 세 개였다.
- 36일치 CGM raw 로그 (2,637건, 2026-01-27 ~ 2026-04-05)
- 100일치 식사 raw 로그 (606건, FastingWorks 앱)
- 100일치 intraday step raw 로그 (14,103건)
모든 식사 이벤트에 대해 식사 시점 전후 30분의 혈당 baseline, 식후 90분 이내의 peak, 식후 0~30분 사이의 걸음 수를 계산했다. 이 세 값이 있으면 "걸은 식사 vs 안 걸은 식사"의 Δpeak 비교가 가능할 것이라 봤다.
원 가설이 죽은 이유
CGM 창 안에서 분석 가능한 식사는 396건 중 43건이었다. 나머지는 CGM 결측 기간에 있었다. 43건 중 사전 등록된 기준(식후 30분 이내 ≥500 걸음)을 만족한 식사는 2건이었다. 기준을 완화해 "식후 10~60분 사이 ≥200 걸음"으로 바꿔도 12건이었다.
더 결정적인 문제: walk=True 12건이 전부 2026-02-02 ~ 2026-02-09 단 한 주에 몰려 있었다. 즉 "걸은 식사 그룹"은 사실상 그 1주일의 식사 12개였다. 무엇을 매칭해도 이 주간 편향을 걷어낼 수 없었다.
그래서 원 가설은 "데이터 부족"이 아니라 "구조적 교란으로 영원히 검증 불가"로 끝났다.
진짜 신호가 드러난 순간
walk 플래그를 던지고 탄수화물 양 기준으로 같은 43건을 3분위로 나눴다. 결과는 즉시 읽혔다.
| 한 끼 탄수 | n | 중앙 Δpeak (mg/dL) | 중앙 TIR 70~140 (2시간) | 뜻 |
|---|---|---|---|---|
| < 50 g | 18 | +10.5 | 1.00 | 2시간 내내 70~140 안에 유지 |
| 50~100 g | 14 | +32.5 | 0.46 | 절반 이상 시간이 범위 밖 |
| ≥ 100 g | 6 | +45.25 | 0.50 | 큰 스파이크 |
- <50g 식사 18건은 TIR 중앙값이 1.00이었다. 즉 식사 직후 2시간 내내 혈당이 한 번도 140 mg/dL 위로 올라가지 않았다. Δpeak도 10 mg/dL 수준으로, 노이즈와 구분하기 어렵다.
- 50g을 넘기는 순간 TIR이 0.46으로 주저앉는다. 약 55%의 시간이 140 mg/dL 위에 있다는 뜻이다.
- 100g 이상 식사 6건은 Δpeak 중앙값 45.25 mg/dL. 세 배가 넘는 스파이크다.
Δpeak 증가 폭이 용량에 비례해 매끄럽게 커지는 dose-response 곡선이다. 이 선명도는 "걷기" 같은 부수 변수가 뚫고 올라올 수준이 아니었다.
이 결론이 특히 강한 이유
이 결론은 같은 43건의 식사에서 "걷기" 관점으로 보면 희미했지만, "탄수량" 관점으로 보면 뚜렷했다. 즉 동일한 데이터 안에서 두 가설을 직접 비교한 결과다. 걷기가 아니라 탄수량이 더 많은 분산을 설명한다.
또한 이 규칙은 Week 2에서 따로 발견한 "하루 총 탄수량과 다음 날 아침 HRV 사이에는 신호가 없다"는 결과와 모순되지 않는다. 이 둘을 합치면:
- 개별 식사 단위(수 시간): 탄수가 많을수록 혈당 스파이크가 커진다
- 하루 총량 단위(다음 날 아침): 하루 총 탄수는 HRV/RHR에 흔적을 남기지 않는다
내 몸은 급성 혈당 변동은 크게 겪지만, 그걸 밤 사이에 회복시켜 다음 날 아침엔 baseline으로 돌려놓는다. 두 진술이 동시에 참이다.
Sugar를 분리해 보면 — 두 번째 축이 드러난다
"50g 이하"는 탄수 총량 기준이다. 같은 43건의 식사에서 당(sugar) 절대량과 sugar / carbs 비율을 분리해 다시 돌려봤다. raw dietarySugar 347건이 meal 클러스터에 붙으며, 25건의 식사에서 탄수·당 둘 다 로그됐다.
Pearson 상관 (n=25)
| 변수 | vs Δpeak 상관계수 | 해석 |
|---|---|---|
| 탄수 총량 | +0.49 | 피크 높이의 1차 지배 변수 |
| 당 절대량 | +0.095 | 거의 0 — 피크 높이를 예측 못함 |
| 당 / 탄수 비율 | −0.37 | 오히려 약한 음의 상관 |
즉 피크 높이 관점에서 sugar는 carbs만큼 중요하지 않다. 당 비율이 음수 상관인 이유는 sugar 비율이 높은 식사(과일·유제품)가 일반적으로 탄수 총량 자체가 작기 때문이다.
같은 탄수 bucket 안에서 sugar로 쪼개면
50~100g 탄수 그룹을 저당 vs 고당으로 다시 나누면:
| 그룹 | n | sugar 중앙 | carbs 중앙 | Δpeak 중앙 | TIR 중앙 |
|---|---|---|---|---|---|
| 저당 (< 15 g) | 5 | 7.6 g | 90 g | +28.7 | 0.83 |
| 고당 (≥ 15 g) | 9 | 26.4 g | 72 g | +36.3 | 0.42 |
피크 높이는 +7.6 mg/dL만 올라가지만, TIR은 0.83 → 0.42로 반토막 이하로 떨어진다. 즉 같은 탄수량에서도 sugar가 많으면 피크가 훨씬 오래 유지된다.
실제 식사가 보여주는 장면
이 패턴은 음식 라벨을 같이 보면 훨씬 뚜렷하다.
Sugar 적은 고탄수 식사 — 의외로 평온
닭죽— c=90g, s=3g → Δpeak +2.2, TIR 0.83. 같은 탄수 bucket의 어떤 식사보다 낮은 스파이크.보양염소탕, 김치, 밥— c=91g, s=10g → Δpeak +22, TIR 1.00.
정제 starch + sugar 조합 — 가장 격하게 튀김
단팥 도너츠 + 포카리 스웨트— c=83g, s=58g → Δpeak +77.소바, 쯔유, 김치— c=180g, s=29g → Δpeak +67.해물순두부찌개, 불고기전골, 밥— c=136g, s=31g → Δpeak +89.5.
과일·유제품 단독 sugar — 놀랍게 안전
딸기, 그릭 요거트— c=39g, s=23g → Δpeak −3 (오히려 감소).사과— c=54g, s=40g → Δpeak +8.8.천혜향— c=36g, s=27g → Δpeak +13.7.
같은 20~40g의 sugar라도, 과일·요거트 형태는 fiber와 protein을 동반하므로 거의 튀지 않는다. 반면 액체 sugar(스포츠 드링크)나 정제 starch를 동반한 sugar(도너츠, 팥빵) 는 가장 큰 스파이크를 만든다.
개정된 공식 — 2축 모델
원래의 "50g 탄수 룰"은 피크 높이 관점에서는 여전히 맞다. 하지만 Sugar가 두 번째 축을 추가한다.
탄수 총량 = 피크 높이의 1차 지배 변수 (r = +0.49) 당 함량 (같은 탄수에서) = 피크 지속시간의 조절 변수 (TIR 0.83 → 0.42) 가장 위험한 조합: 정제 starch (밥·면·빵) + 액체/추가 sugar (음료·단팥·초코) 놀랍게 안전한 조합: fiber/protein을 동반한 자연 sugar (과일·요거트)
즉 한 줄 규칙은 이렇게 바뀐다:
"한 끼 탄수 50g 이하"는 여전히 핵심. 넘겨야 한다면 starch-dominant (쌀·면·빵) 식사에 sugar를 추가하지 않는 것이 다음으로 강한 지렛대다. 과일이나 무가당 요거트의 sugar는 걱정하지 말자.
한계
- N=1, 탐색적 관찰 분석. 실험적 통제가 아니다.
- n=43 식사 (탄수 분석), n=25 (탄수+sugar 동시 로그). 당 절대량 3분위는 4/15/6으로 작은 그룹.
- GI 정보 없음. "50g 탄수"의 품목(쌀밥 vs 콩류 vs 설탕)이 구분되지는 않지만, sugar 분리 분석이 일부 해상도를 회복한다.
- CGM 창 36일. 대부분의 sugar-logged 식사는 2월 초 1주일에 몰려 있어 계절·생활 편향 가능.
- 식사 클러스터링의 불확실성. 15분 창으로 raw 기록을 묶었지만, 한 끼가 두 클러스터로 쪼개졌을 가능성이 있다.
- Sugar null ≠ 0: sugar 기록이 없는 식사(주로 육류·해산물 중심)는 "0 sugar"가 아니라 "미기록"으로 취급되어 분석 대상에서 제외.
이 한계들은 "이 규칙이 틀렸을 수 있다"가 아니라 "이 규칙이 일반화되지 않는다"는 의미다. 내 몸에서 이 100일 동안 관찰된 패턴이며, 다른 사람에게도 같을 이유는 없다.
어떻게 써먹을까
가장 단순한 적용은 한 줄이다.
가능하면 한 끼 탄수를 50g 이하로 유지하자. 이게 안 될 때는 식사 크기를 100g 이하로라도 맞추자. 걷는 것보다 먹는 양이 더 강한 지렛대다.
50g은 구체적으로:
- 밥 한 공기: ~70g (초과)
- 밥 반 공기: ~35g
- 식빵 1장: ~15g
- 바나나 1개: ~27g
- 요거트 한 컵(무가당): ~10g
즉 "밥을 반 공기로 줄이는 것"이 이 규칙의 핵심 실천이다.
관련 문서
- 상세 도출 리포트:
data/week3/expC-results.md— 왜 원래 가설이 죽었는지, 탄수·sugar bucket 분석의 세부 수치, Week 2 결과와의 화해 - 분석 산출물:
data/week3/expC-results.json— 43개 meal 이벤트 전체와 bucket·상관 통계 - 분석 스크립트:
scripts/analyze_expC_cgm.py— meal clustering → glucose windowing → carb/sugar bucketing - HTML 렌더러:
scripts/build_one_pager.py— 이 문서를 one-pager HTML로 빌드
raw 데이터에 관해
이 분석이 사용한 raw 입력(dietaryEnergyConsumed, dietaryCarbohydrates, dietarySugar, dietaryFiber, dietaryProtein, dietaryFatTotal, bloodGlucose, stepCount, workout)은 개인 정보 분량이 커서 repo에 포함시키지 않았다. 재실행하려면 Health Data Bridge CLI로 2026-01-01 ~ 2026-04-10 구간을 다시 덤프해야 한다. 커맨드는 scripts/analyze_expC_cgm.py 상단 docstring 참조.