AI 출력을 저장하기 전에 검토 단계를 모델링하는 방법
요약
AI가 생성한 제안을 최종 기록으로 저장할 때, 데이터의 무결성을 유지하는 모델링 접근 방식이 중요합니다. 특히 '분석'과 '식사' 같은 개념적 경계를 명확히 분리하여, 사용자가 검토하고 확인하기 전까지는 임시적인 해석 상태를 유지해야 합니다.
핵심 포인트
- AI 제안을 저장된 기록으로 변환할 때 분석(Analysis)과 식사(Meal)의 역할을 분리하세요.
- 사용자 편집 및 확인 과정을 거치기 전에는 데이터가 영구적으로 변경되어서는 안 됩니다.
- 데이터 무결성을 위해 '불변 조건'을 명시하고, 수정 사항에 대한 추적 가능성(traceability)을 확보해야 합니다.
AI 응답은 식사를 식별하고 영양값을 제안할 수 있습니다. 하지만 이 응답만으로는 제품 결정이 해결되지 않습니다. 즉, 사용자가 다이어리에 어떤 정보를 기록하길 원하는가 하는 문제입니다.
응답을 저장된 식사로 즉시 처리하게 되면, 사용자가 음식을 확인하거나 양을 점검하기 전에 일일 총합계가 성공적인 모델 요청에 의해 변경될 수 있습니다. 나중에 추가되는 검토 화면으로는 데이터 모델이 이미 잃어버린 구분을 복구할 수 없습니다.
FoodWarz의 도메인 어휘는 **분석(analysis)**과 **식사(meal)**를 분리합니다. 분석은 검토 가능한 해석입니다. 식사는 사용자가 기록하기로 선택한 양, 영양 및 출처 정보를 포함하는 저장된 다이어리 스냅샷입니다. 이 게시물에서는 그 경계를 사용하여 생성된 제안을 지속적인 기록으로 변환하는 다른 제품에도 적용될 수 있는 작은 모델링 접근 방식을 설명합니다.
각 객체에 하나의 역할 부여하기
다음 TypeScript 코드는 FoodWarz의 실제 스키마가 아닌 예시적 초안입니다. 식별자, 유효성 검사 및 저장 세부 사항은 의도적으로 생략되었습니다.
type Nutrition = Readonly<{
calories: number | null;
protein: number | null;
...
유용한 부분은 분리된 이름들입니다. SavedMeal을 받는 함수가 단순히 둘 다 칼로리를 포함한다는 이유만으로 AnalysisResult도 받아서는 안 됩니다. 프로덕션 경계에는 런타임 유효성 검사도 필요합니다. 타입만으로는 클라이언트 요청이 유효한지 또는 사용자가 이를 확인했는지 여부를 확립할 수 없습니다.
간소화된 흐름은 다음과 같습니다:
Analysis 완료 → 검토 초안 열기
사용자 편집 → 초안 업데이트
사용자 확인 → 식사 유효성 검사 및 영속화
...
초안은 폐기될 수도 있습니다. 이 또한 분석의 일반적인 결과로 남아 있어야 하며, 새로운 섭취 음식 기록을 생성해서는 안 됩니다.
UI 이벤트 연결 전에 불변 조건 작성하기
이러한 불변 조건들은 이벤트 핸들러를 검토하기 쉽게 만듭니다:
UI 이벤트 연결 전에 불변 조건 작성하기
이러한 불변 조건들은 이벤트 핸들러를 검토하기 쉽게 만듭니다:
| Event | Expected effect | Boundary to preserve |
|---|---|---|
| Analysis completes | A suggestion becomes available for review | Analysis completion alone does not add consumed food |
| ... |
스냅샷 규칙은 놓치기 쉽습니다. 예를 들어, 카탈로그 항목이 내일 수정되었다고 가정해 봅시다. 만약 어제 일기가 현재 카탈로그 행과 결합하여 영양 정보를 읽는다면, 일기 편집 없이도 어제의 총량이 변경될 수 있습니다. 검토된 영양 정보는 기록(historical record)에 저장하고 추적 가능성(traceability)을 위해 출처 참조를 유지해야 합니다.
기존 식사에 대한 의도적인 수정은 별도의 사용자 행동입니다. 스냅샷을 유지한다고 해서 소유자가 실수를 수정하는 것을 막는다는 의미는 아닙니다.
수정 증거 보관하기
FoodWarz의 저장된 식사 계약(saved-meal contract)은 원래 분석과 검토된 추정치를 구분합니다. 수정 사항은 분석 컨텍스트에 대한 링크를 유지하면서 사용자 수정 값으로 표현될 수 있습니다. 이는 구체적인 디버깅 질문을 지원합니다: 시스템이 무엇을 제안했고, 실제로 무엇이 저장되었는가?
겉보기에 그럴듯한 칼로리 총량만으로는 불충분한 증거입니다. 양(amount), 단위(unit), 영양 기반(nutrition basis)이 함께 중요합니다. 100그램당 값은 섭취된 부분의 총량과는 다른 의미를 갖습니다. 출처와 불확실성(uncertainty) 또한 일기로 전환되는 과정에서도 살아남아야 합니다.
이는 경계(boundary)에서 검증하기 위한 계약입니다. 모든 상위 스트림 해석(upstream interpretation)이 정확하다는 증거가 아니며, 검토가 추정치를 정확한 측정값으로 바꾸지는 않습니다.
역사를 변경할 수 있는 전환 테스트하기
유용한 회귀 시나리오(regression scenarios)는 사람이 취할 수 있는 행동에서 시작됩니다:
- 분석을 완료하고, 검토를 닫은 후, 식사가 추가되지 않았는지 확인합니다.
- 검토 중에 양을 변경하고, 저장된 스냅샷에 검토된 결과가 포함되어 있는지 확인합니다.
- 재사용 가능한 출처 기록(reusable source record)을 변경하고, 기존 식사가 기록된 영양 정보를 유지하는지 확인합니다.
- 계획된 요리를 생성하거나 편집하고, 일반적인 식사(ordinary meal)가 저장될 때까지 섭취 총량이 변하지 않는지 확인합니다.
이러한 시나리오들은 내부 헬퍼 함수의 이름보다는 관찰 가능한 의미를 확인합니다. 이는 이 모델을 위한 제안된 커버리지이며, 실제 운영 테스트 실행 보고서는 아닙니다.
FoodWarz 다이어리 개요는 이 엔지니어링 노트의 사용자 인터페이스(user-facing) 컨텍스트를 보여줍니다. 모델링 교훈은 제안이 언제 기록(record)이 되는지 결정하고, 그 결정을 타입(types), 유효성 검사(validation), 상태 전이(state transitions)에서 명시적으로 만드는 것입니다.
공개 고지: FoodWarz 팀에 의해 게시되었습니다. 이 문서는 프로젝트의 도메인 문서와 선택된 코드 계약을 사용하여 AI 지원으로 작성되었습니다. 위의 코드는 예시적입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기