AI 비교AI 찾기AI 뉴스AI 활용
회사 소개
개인정보처리방침이용약관FAQ문의하기문의하기
에이아이비 주식회사사업자정보
© 2026 AIB Inc.

개발자, 건강 챗봇 SQL 배제

개발자, 건강 챗봇 SQL 배제

DEV.to·2026년 8월 19일 (수)
  • •Matty Stratton은 Claude 건강 데이터 앱에서 6가지 스키마 함정이 오답을 만들자 직접 SQL 접근을 거부했다
  • •타입 지정 읽기 전용 도구는 부분 날짜, 운동 중복 집계, 0으로 채운 공백, 2.7x 에너지 균형 오류를 막는다
  • •9개 검증 질문의 총비용은 37 cents였고, 지연시간은 6.9초에서 16.8초까지 걸렸다
  • •Matty Stratton은 Claude 건강 데이터 앱에서 6가지 스키마 함정이 오답을 만들자 직접 SQL 접근을 거부했다
  • •타입 지정 읽기 전용 도구는 부분 날짜, 운동 중복 집계, 0으로 채운 공백, 2.7x 에너지 균형 오류를 막는다
  • •9개 검증 질문의 총비용은 37 cents였고, 지연시간은 6.9초에서 16.8초까지 걸렸다
  • •Matty Stratton은 Claude 건강 데이터 앱에서 6가지 스키마 함정이 오답을 만들자 직접 SQL 접근을 거부했다
  • •타입 지정 읽기 전용 도구는 부분 날짜, 운동 중복 집계, 0으로 채운 공백, 2.7x 에너지 균형 오류를 막는다
  • •9개 검증 질문의 총비용은 37 cents였고, 지연시간은 6.9초에서 16.8초까지 걸렸다
  • •Matty Stratton은 Claude 건강 데이터 앱에서 6가지 스키마 함정이 오답을 만들자 직접 SQL 접근을 거부했다
  • •타입 지정 읽기 전용 도구는 부분 날짜, 운동 중복 집계, 0으로 채운 공백, 2.7x 에너지 균형 오류를 막는다
  • •9개 검증 질문의 총비용은 37 cents였고, 지연시간은 6.9초에서 16.8초까지 걸렸다

Matty Stratton은 2026-08-17 자신만의 건강 데이터에 답하는 웹 앱을 구축한 기록을 공개했다. 이 앱은 코치 화면에는 결정론적 규칙을 쓰고, 질문 화면에는 Claude와 13개 읽기 전용 도구를 사용한다. 또한 정확히 1개 주소만 허용한 Google 로그인 뒤에 있으며, TimescaleDB 데이터베이스를 읽고, 기준값이 한 사람의 상황에 맞춰져 있어 의학적 조언은 아니다.

Stratton은 LLM에 직접 SQL 접근을 주는 흔한 “chat with your database” 방식을 거부했다. 그의 건강 데이터에는 이미 오답을 만든 6가지 함정이 있었기 때문이다. 오늘은 부분 날짜이고, 공백은 0이 아니며, Apple은 모든 Liftosaur 세션을 섀도 복사한다. `energy_balance`는 적자를 약 2.7x 과대평가하고, 단일 체중 측정은 잡음이며, `reps: 0`은 누락 데이터가 아니라 시도했지만 실패한 세트를 뜻한다.

가장 강한 사례는 `energy_balance`였다. 최근 30개 완료일 기준으로 평균 섭취량은 1,602 kcal, 소모량은 3,216으로 나타났고, 하루 순값은 −1,614였다. 이는 주당 3.2 lb 감량을 예측했지만 실제 체중계는 1.2를 보였다. Stratton은 6가지 함정을 모두 프롬프트에 넣으면 대부분 작동했다고 말했다. 다만 드문 오답도 정답과 같은 자신감 있는 형식으로 나타났기 때문에 “대부분의 경우”는 일관된 실패보다 더 위험했다.

앱은 지시에 기대지 않고 타입 지정 도구, 즉 모델에 노출된 사전 정의 함수로 그 실패 모드를 차단한다. 기간 쿼리는 `today_local()` 전에서 끝나고, 공백은 행이 없는 상태로 남으며, 어떤 도구도 Apple의 운동 화면에 접근하지 않는다. 또한 `energy_balance`는 항상 현실 검증값과 함께 반환된다. 시스템 프롬프트도 여전히 함정을 설명하지만, 쓰기 도구는 전혀 없어 프로그램 변경은 Liftosaur에, 매크로 목표는 MacroFactor에 남는다.

Stratton은 `list_metrics`가 81개 지표 중 38개만 포함한 `metric_catalog` 테이블을 읽으면서 또 다른 결함 있는 도구를 거의 배포할 뻔했다. 빠진 43개에는 오늘 업데이트된 3,865일치 걷기와 달리기 거리, 오른 층수, 걷기 심박수 평균, 걷기 속도, 보폭, 미량영양소 패널이 포함됐다. 실제 데이터베이스를 대상으로 한 임시 스크립트가 이 불일치를 드러냈다.

수정 뒤 쿼리는 `observations_daily`에서 출발했고, `LEFT JOIN`을 사용했으며, 카탈로그에 없는 지표도 숨기지 않고 `catalogued: false`와 null 단위로 표시했다. `EXPLAIN ANALYZE`는 전체 연속 집계에 대한 aggregate가 100ms를 충분히 밑돈다고 보여줬고, Stratton은 대화당 1번 호출되는 작업으로 받아들일 만하다고 봤다.

도구 출력도 도구 경계에서 부동소수점 값을 소수점 이하 2자리로 반올림하도록 바뀌었다. `1370.9033333354562` calories와 `187.9353333412348` protein_g 같은 원시 행은 거짓 정밀도와 토큰 비용을 만들었다. 공유 `json()` 헬퍼 안에서 반올림하자 7일 기간의 `get_nutrition` 페이로드 크기는 대략 3분의 1 줄었고, 90일 시계열에서는 더 많이 줄었다.

의도적으로 함정이 들어간 9개 질문을 커밋된 probe 스크립트로 실행한 결과, 모델은 때때로 구조를 넘어 유용한 추론을 더했다. VO2max를 상승세지만 “시사적이지 결론적이지는 않다”고 설명했고, 무게와 세트 수를 살펴 squat T1과 T2 작업을 구분했으며, 커버리지 수치를 읽은 뒤 21 nights의 수면 등급 매기기를 거부했다. Stratton은 지표 커버리지를 위해 추가한 `days365` 필드가 일반적인 데이터 충분성 게이트가 됐다고 말했다.

상관관계에 필요한 과거 사건이 없어 교차 영역 신호는 추가하지 않았다. 필터 없이 `stalling()`을 2,545 sets와 190 sessions에 실행하자 정확히 1건, 47.5lb로 2 sessions 이어진 triceps pushdown만 잡혔고, 이는 T3 tier filter가 무시해야 하는 사례였다. `overreaching()`을 2,409 days에 실행한 결과는 `ok` 2,344회, `unknown` 48회, `watch` 16회, 2022년 4월 25일 `act` 1회였다. 2024년 6월 이후에는 `ok`를 통과한 것이 없었다. 일관된 영양 기록은 7월 13일 시작돼 상관관계 분석에 쓸 수 있는 완료 주는 4주뿐이었다.

남은 검증 공백은 2가지였다. 질문 인터페이스가 브라우저에서 렌더링되지 않았고, 현재 `unknown`이 없어 실시간 `unknown` 신호 경로도 테스트되지 않았다. 그날 측정한 9개 probe에서 샘플 실행은 끝까지 6.9초에서 16.8초가 걸렸고, 첫 텍스트는 1.7초에서 10.1초 사이에 도착했다. 9개 질문의 총비용은 37 cents였으며, 질문별로 1.3 cents에서 9 cents였다. 캐시된 prefix는 시스템 프롬프트와 13개 도구 정의를 합쳐 7,069 tokens였고, 첫 턴 이후 `cacheWrite`는 0을 유지했으며, 2턴 질문은 prefix를 두 번 다시 읽어 14,138 cached tokens를 사용했다.

Matty Stratton은 2026-08-17 자신만의 건강 데이터에 답하는 웹 앱을 구축한 기록을 공개했다. 이 앱은 코치 화면에는 결정론적 규칙을 쓰고, 질문 화면에는 Claude와 13개 읽기 전용 도구를 사용한다. 또한 정확히 1개 주소만 허용한 Google 로그인 뒤에 있으며, TimescaleDB 데이터베이스를 읽고, 기준값이 한 사람의 상황에 맞춰져 있어 의학적 조언은 아니다.

Stratton은 LLM에 직접 SQL 접근을 주는 흔한 “chat with your database” 방식을 거부했다. 그의 건강 데이터에는 이미 오답을 만든 6가지 함정이 있었기 때문이다. 오늘은 부분 날짜이고, 공백은 0이 아니며, Apple은 모든 Liftosaur 세션을 섀도 복사한다. `energy_balance`는 적자를 약 2.7x 과대평가하고, 단일 체중 측정은 잡음이며, `reps: 0`은 누락 데이터가 아니라 시도했지만 실패한 세트를 뜻한다.

가장 강한 사례는 `energy_balance`였다. 최근 30개 완료일 기준으로 평균 섭취량은 1,602 kcal, 소모량은 3,216으로 나타났고, 하루 순값은 −1,614였다. 이는 주당 3.2 lb 감량을 예측했지만 실제 체중계는 1.2를 보였다. Stratton은 6가지 함정을 모두 프롬프트에 넣으면 대부분 작동했다고 말했다. 다만 드문 오답도 정답과 같은 자신감 있는 형식으로 나타났기 때문에 “대부분의 경우”는 일관된 실패보다 더 위험했다.

앱은 지시에 기대지 않고 타입 지정 도구, 즉 모델에 노출된 사전 정의 함수로 그 실패 모드를 차단한다. 기간 쿼리는 `today_local()` 전에서 끝나고, 공백은 행이 없는 상태로 남으며, 어떤 도구도 Apple의 운동 화면에 접근하지 않는다. 또한 `energy_balance`는 항상 현실 검증값과 함께 반환된다. 시스템 프롬프트도 여전히 함정을 설명하지만, 쓰기 도구는 전혀 없어 프로그램 변경은 Liftosaur에, 매크로 목표는 MacroFactor에 남는다.

Stratton은 `list_metrics`가 81개 지표 중 38개만 포함한 `metric_catalog` 테이블을 읽으면서 또 다른 결함 있는 도구를 거의 배포할 뻔했다. 빠진 43개에는 오늘 업데이트된 3,865일치 걷기와 달리기 거리, 오른 층수, 걷기 심박수 평균, 걷기 속도, 보폭, 미량영양소 패널이 포함됐다. 실제 데이터베이스를 대상으로 한 임시 스크립트가 이 불일치를 드러냈다.

수정 뒤 쿼리는 `observations_daily`에서 출발했고, `LEFT JOIN`을 사용했으며, 카탈로그에 없는 지표도 숨기지 않고 `catalogued: false`와 null 단위로 표시했다. `EXPLAIN ANALYZE`는 전체 연속 집계에 대한 aggregate가 100ms를 충분히 밑돈다고 보여줬고, Stratton은 대화당 1번 호출되는 작업으로 받아들일 만하다고 봤다.

도구 출력도 도구 경계에서 부동소수점 값을 소수점 이하 2자리로 반올림하도록 바뀌었다. `1370.9033333354562` calories와 `187.9353333412348` protein_g 같은 원시 행은 거짓 정밀도와 토큰 비용을 만들었다. 공유 `json()` 헬퍼 안에서 반올림하자 7일 기간의 `get_nutrition` 페이로드 크기는 대략 3분의 1 줄었고, 90일 시계열에서는 더 많이 줄었다.

의도적으로 함정이 들어간 9개 질문을 커밋된 probe 스크립트로 실행한 결과, 모델은 때때로 구조를 넘어 유용한 추론을 더했다. VO2max를 상승세지만 “시사적이지 결론적이지는 않다”고 설명했고, 무게와 세트 수를 살펴 squat T1과 T2 작업을 구분했으며, 커버리지 수치를 읽은 뒤 21 nights의 수면 등급 매기기를 거부했다. Stratton은 지표 커버리지를 위해 추가한 `days365` 필드가 일반적인 데이터 충분성 게이트가 됐다고 말했다.

상관관계에 필요한 과거 사건이 없어 교차 영역 신호는 추가하지 않았다. 필터 없이 `stalling()`을 2,545 sets와 190 sessions에 실행하자 정확히 1건, 47.5lb로 2 sessions 이어진 triceps pushdown만 잡혔고, 이는 T3 tier filter가 무시해야 하는 사례였다. `overreaching()`을 2,409 days에 실행한 결과는 `ok` 2,344회, `unknown` 48회, `watch` 16회, 2022년 4월 25일 `act` 1회였다. 2024년 6월 이후에는 `ok`를 통과한 것이 없었다. 일관된 영양 기록은 7월 13일 시작돼 상관관계 분석에 쓸 수 있는 완료 주는 4주뿐이었다.

남은 검증 공백은 2가지였다. 질문 인터페이스가 브라우저에서 렌더링되지 않았고, 현재 `unknown`이 없어 실시간 `unknown` 신호 경로도 테스트되지 않았다. 그날 측정한 9개 probe에서 샘플 실행은 끝까지 6.9초에서 16.8초가 걸렸고, 첫 텍스트는 1.7초에서 10.1초 사이에 도착했다. 9개 질문의 총비용은 37 cents였으며, 질문별로 1.3 cents에서 9 cents였다. 캐시된 prefix는 시스템 프롬프트와 13개 도구 정의를 합쳐 7,069 tokens였고, 첫 턴 이후 `cacheWrite`는 0을 유지했으며, 2턴 질문은 prefix를 두 번 다시 읽어 14,138 cached tokens를 사용했다.

원문 보기 (영어)·2026년 8월 17일
#llm#claude#sql#typed tools#timescaledb#health data#database#read only tools#cachewrite#vo2max