LLM에게 JSON을 학습시키는 건 노이즈일까?

Dorong·2026년 4월 28일

AI

목록 보기
3/4

최근 자연어 입력을 구조화된 객체로 변환하는 태스크를 설계하면서 이런 고민을 했다.

예를 들어 사용자가 이렇게 입력한다고 하자.

“지난달 마케팅팀에서 작성한 캠페인 기획서 찾아줘”

이 질의를 검색 파이프라인이 바로 사용할 수 있도록 아래와 같은 구조로 변환하고 싶다.

{
  "keywords": ["캠페인", "기획서"],
  "category": "마케팅",
  "project": null,
  "date_range": {
    "start": "2024-03",
    "end": "2024-03"
  },
  "intent": "document_search"
}

여기서 고민은 이것이다.

“어차피 Structured Output이나 function calling으로 JSON 형식은 강제할 수 있는데, PEFT 데이터의 assistant 출력까지 JSON으로 학습시키는 게 맞을까?”

중괄호, 대괄호, 쉼표, 따옴표 같은 문법 토큰이 불필요한 노이즈가 되지는 않을까?


내가 내린 결론부터 말하면 PEFT 학습 타깃은 실제 서비스에서 사용할 JSON 구조와 동일하게 두는 편이 낫다.
다만 목적은 “JSON 문법을 학습시키는 것”이 아니라, “자연어 입력을 올바른 구조적 의미 단위로 매핑하는 것”이어야 한다.

Structured Output이 잘하는 것은 형식 제약이다.

예를 들어:

  • 반드시 keywords는 배열이어야 한다.
  • intent는 정해진 enum 중 하나여야 한다.
  • 필수 필드는 빠지면 안 된다.
  • schema에 없는 필드는 나오면 안 된다.
  • JSON 문법이 깨지면 안 된다.

이런 것들은 Structured Output이 강하게 보장할 수 있다.

하지만 Structured Output이 해결하지 못하는 것도 있다.

예를 들어 사용자가 “지난달 개발팀 로그인 오류 문서 찾아줘”라고 했을 때, 모델이 아래처럼 출력할 수 있다.

{
  "keywords": ["로그인", "오류"],
  "category": "디자인",
  "project": null,
  "date_range": {
    "start": null,
    "end": null
  },
  "intent": "summary_request"
}

이 JSON은 형식적으로는 맞다.
하지만 의미적으로는 틀렸다.

Structured Output은 JSON schema를 맞추는 장치이지, 사용자의 의도를 항상 정확히 해석해주는 장치는 아니다.

그래서 역할을 나누어 봐야 한다.

Structured Output은 형식을 보장한다.
PEFT는 의미 매핑의 정확도를 높인다.

즉, PEFT가 배워야 하는 것은 이런 것이다.

  • “찾아줘”는 보통 document_search
  • “정리해줘”는 보통 summary_request
  • “지난달”은 기준일에 따라 날짜 범위로 정규화
  • “개발팀”은 category로 매핑
  • “로그인 오류 문서”에서는 로그인, 오류, 문서 같은 검색 키워드 추출
  • 언급되지 않은 필드는 null
  • 프로젝트명과 일반 명사를 구분

이 관점에서 보면 JSON의 괄호와 쉼표가 완전히 비용이 없는 것은 아니다.
학습 시 assistant 출력 토큰에 loss를 걸면 구조 토큰도 loss 계산에 포함되고, 전체 토큰 중 실제 의미값이 차지하는 비율은 낮아질 수 있다. completion-only loss masking을 쓰더라도 assistant 출력 내부의 {, }, [, ], ,, key 이름 같은 토큰 비중은 남는다.

다만 이 비용이 실제 성능을 유의미하게 떨어뜨린다고 단정하기는 어렵고, 운영 schema와 학습 타깃을 맞추는 train-serve consistency의 이점이 더 크다고 보는 편이 현실적이다.
즉, “JSON 문법 토큰은 완전히 무의미하다”가 아니라, “약간의 비용은 있지만 핵심 문제는 아니며, 운영 형식과 정렬되는 이점이 더 크다”에 가깝다.

만약 학습 데이터를 자연어 설명형으로 만들면 어떨까?

예를 들어:

“키워드는 캠페인, 기획서이고 카테고리는 마케팅입니다. 프로젝트는 없습니다. 의도는 문서 검색입니다.”

이 방식도 가능하다.
하지만 실제 서비스에서는 결국 JSON 객체가 필요하다. 그러면 모델은 학습 때는 자연어 설명을 보고, 추론 때는 JSON schema에 맞춰 출력해야 한다. 학습 분포와 운영 분포가 어긋난다.

또한 자연어 설명은 표현이 쉽게 흔들린다.

  • 프로젝트 없음
  • 프로젝트 미지정
  • project는 null
  • 해당 없음
  • 별도 프로젝트 없음

사람에게는 같은 뜻이지만, 모델 학습 관점에서는 불필요한 변형이다.

물론 입력의 다양한 표현을 학습하는 것은 중요하다.
사용자는 “프로젝트 없어”, “관련 프로젝트는 모르겠어”, “그냥 마케팅 자료 찾아줘”처럼 여러 방식으로 말할 수 있고, 이런 입력 다양성은 robustness에 도움이 된다. 하지만 입력 다양성과 출력 정규화는 별도 문제다. 이 태스크에서는 입력은 다양하게 받되, 출력은 canonical한 형태로 고정하는 편이 낫다.

반대로 JSON 출력은 정답 표현을 canonical하게 고정할 수 있다.

{"keywords":["캠페인","기획서"],"category":"마케팅","project":null,"date_range":{"start":"2024-03","end":"2024-03"},"intent":"document_search"}

이런 compact JSON 형태로 key order, null 표현, enum 값을 고정하면 학습 신호가 더 명확해진다.

물론 주의할 점도 있다.

JSON 형식만 잘 맞추는 모델을 만들면 안 된다.
중요한 것은 필드값의 의미적 정확도다.

따라서 이런 태스크의 평가 지표는 단순 JSON validity로 끝나면 안 된다.

최소한 아래를 봐야 한다.

  • keywords 추출 F1
  • category exact match
  • project exact match
  • date_range exact match
  • intent exact match
  • 전체 객체 exact match
  • downstream 검색 성능: Recall@k, Precision@k, MRR, nDCG

특히 검색 파이프라인에서는 잘못된 hard filter가 recall을 크게 망칠 수 있다.

예를 들어 category를 잘못 예측해서 디자인으로 고정해버리면, 실제 정답이 있는 개발 문서가 검색 후보에서 사라질 수 있다.

그래서 구조화된 질의 객체를 검색에 사용할 때는 다음과 같은 방어선이 필요하다.

  1. Structured Output으로 schema-valid JSON 생성
  2. 애플리케이션 레벨 validation 수행
  3. 날짜, 카테고리, 프로젝트명은 taxonomy와 포맷 검증
  4. 확신이 낮은 필드는 hard filter가 아니라 soft boost로 사용
  5. 결과가 너무 적으면 filter relaxation 수행
  6. 원문 질의도 vector search에 함께 사용

정리하면 이렇다.

LLM에게 JSON을 학습시키는 것은 단순히 중괄호와 쉼표를 학습시키는 일이 아니다.
자연어 질의를 검색, 추천, 자동화, 워크플로우 시스템이 소비할 수 있는 구조적 의미 표현으로 변환하는 작업이다.

Structured Output은 형식의 안정성을 준다.
PEFT는 도메인별 의미 해석의 정확도를 높인다.

JSON 구조 토큰에는 학습 비용이 일부 있지만, 실제 운영에서 JSON을 사용할 계획이라면 PEFT 데이터도 운영 schema와 동일한 JSON 구조로 만드는 것이 더 자연스럽다.

중요한 것은 JSON을 예쁘게 생성하는 모델이 아니라,
schema 안에 들어갈 값을 정확히 판단하는 모델을 만드는 것이다.

profile
AI R&D와 웹/앱개발 욕심쟁이 멀티 플레이🐖

0개의 댓글