LLMs를 마침내 강제로 완벽한 JSON 반환하게 만든 방법 (2025 Edition) — 해킹도, Regex도 없이, 깔끔한 출력만
Source: Dev.to

LLM JSON 출력의 문제점
실제 애플리케이션에서 LLM을 사용해 본 적이 있다면 — 특히 LangChain + TypeScript와 함께라면 — 다음과 같은 좌절감을 겪어봤을 것입니다:
- 깨진 JSON
- JSON 주변에 불필요한 텍스트가 포함됨
- 무작위 “창의적인” 출력
- 프로덕션에서 파서가 폭발함
저는 Next.js, LangChain, Supabase Vector Store, Pusher 등을 사용해 AI 앱, RAG 챗봇, SaaS 플랫폼을 구축하면서 이 모든 문제를 직접 겪었습니다. 엄격한 JSON 구조를 강제하기 위해 다양한 프롬프트 트릭을 시도했죠:
- “유효한 JSON만 반환하세요.”
- 엄격한 지시사항 및 금지/허용 규칙 추가
- 정규식으로 정리
- 후처리 파이프라인
어느 것도 신뢰할 수 있게 동작하지 않았습니다.
프롬프트만으로는 충분하지 않은 이유
프롬프트만으로는 유효한 JSON을 보장할 수 없습니다. LLM은 일관된 포맷 규칙을 따르도록 설계되지 않았기 때문에 프롬프트 엔지니어링에만 의존하면 결과가 불안정합니다.
2025년 솔루션: LangChain .withStructuredOutput() + Zod
프로덕션 수준의 해결책은 LangChain의 withStructuredOutput() 메서드와 Zod 스키마를 결합하는 것입니다. 이를 통해 모델이 다음을 반환하도록 강제합니다:
- 100 % 유효한 JSON
- 완전한 타입 지정 데이터
- 스키마에 안전한 응답
- 불필요한 텍스트나 포맷 문제 없음
다음 제공자와도 동작합니다:
- Google Gemini
- OpenAI (GPT‑4o, o‑mini)
- Groq (Llama 3.1)
- Anthropic Claude
배울 내용
.withStructuredOutput()가 내부적으로 어떻게 동작하는지- 단계별 Next.js 16 + TypeScript 구현 방법
- 적절한 오류 처리를 포함한 API 라우트
- 엄격한 출력 검증을 위한 Zod 스키마
- shadcn/ui를 활용한 깔끔한 UI 예시
- 이 방법이 기존 해킹 방식보다 더 빠르고, 저렴하며, 신뢰할 수 있는 이유
전체 가이드
🔗 LangChain과 TypeScript로 완벽한 JSON 응답을 강제하는 방법 (2025 Edition)