AI JSON 응답이 흔들릴 때 sanitize 계층 만들기
AI 리포트가 화면에서 기대하는 형태와 다르게 돌아올 때, 응답 계약과 정규화 계층으로 제품을 지킨 기록입니다.
Code notes
코드에서 확인한 구현 포인트
배포 기준 2026.05.03
관련 파일
apps/web/lib/ai-report.tsapps/web/app/api/reports/[sessionId]/route.tsapps/web/lib/recommendations.ts구현 메모
AI 응답은 response_format으로 JSON 객체를 요구하지만, 서버에서 다시 sanitizeAiPayload를 거쳐 필드와 문장을 정규화한다.
내부 사진 reference나 화면에 노출되면 어색한 값은 사용자 문장에서 제거해 제품 문장으로 다듬는다.
AI 호출이나 파싱이 실패해도 기본 리포트 구조를 반환할 수 있도록 fallback을 둔다.
AI 응답은 문장보다 계약이 먼저다
피부 리포트 화면은 oneLiner, resultBadge, keyFindings, focus, actions, warnings 같은 정해진 필드를 기대한다. 그런데 AI 응답은 프롬프트를 잘 써도 가끔 필드가 빠지거나, 기대한 배열 대신 문장이 들어오거나, 내부 참조명을 그대로 말하는 식으로 흔들릴 수 있다.
이 문제는 단순히 프롬프트를 더 강하게 쓰는 것으로 끝나지 않았다. 화면이 AI 응답을 그대로 믿지 않도록, 서버에서 한 번 더 제품이 이해하는 형태로 정리하는 계층이 필요했다.
response_format과 sanitize를 같이 둔 이유
먼저 AI 호출에서는 JSON 객체 응답을 요구했다. 하지만 JSON으로 온다고 해서 모든 값이 안전한 것은 아니다. 그래서 응답을 파싱한 뒤 sanitizeAiPayload에서 badge, focus, finding, action 같은 필드를 정규화했다.
예를 들어 화면에 보여주면 어색한 사진 reference나 내부 라벨은 사용자 문장에 남지 않도록 걸러냈다. AI는 분석을 돕지만, 최종 사용자 경험의 책임은 앱이 가져야 하기 때문이다.
실패해도 리포트는 열려야 한다
AI 호출이나 파싱이 실패할 때 리포트 전체가 무너지는 것은 좋지 않다. 사용자는 분석을 기다렸고, 최소한 기본 결과와 다음 행동은 받아야 한다.
그래서 서버는 AI payload가 비어 있거나 일부 필드가 이상해도 기본 구조를 만들어 반환할 수 있게 했다. 완벽한 AI 문장보다 중요한 것은 화면이 깨지지 않는 안정적인 리포트 흐름이었다.
남겨둔 원칙
AI 기능은 ‘잘 나올 때’보다 ‘이상하게 나올 때’의 처리가 제품 품질을 결정한다. 프롬프트, 응답 포맷, sanitize, fallback을 한 묶음으로 봐야 한다.
이후 AI 기능을 추가할 때도 화면이 직접 AI 응답에 기대지 않고, 서버가 한 번 제품 언어로 번역해주는 구조를 유지하기로 했다.
Keep reading
다른 글 이어서 보기
AI Debugging
2026.05.03
8 min read
모바일 AI 분석이 멈춘 것처럼 보이던 문제
사진 촬영, 업로드, 분석 요청이 이어지는 모바일 AI 흐름에서 타임아웃과 재시도 기준을 나눈 기록입니다.
AI Debugging
2026.03.22
8 min read
주간 AI 리포트가 빈말이 되지 않게 fallback 만들기
주간 리포트에 충분한 데이터가 없거나 AI 생성이 실패해도 사용자에게 의미 있는 요약을 보여주기 위한 방어 로직입니다.
AI Debugging
2026.03.14
7 min read
AI 리포트 캐시가 오래된 모델 결과를 붙잡던 문제
중복 호출을 줄이기 위한 AI 캐시가 모델 변경과 충돌하지 않도록 provider, model, payload 저장 기준을 점검한 기록입니다.