LLM을 위한 TOON vs JSON: 어떤 포맷이 더 좋을까? (2026)
LLM 프롬프팅 및 출력을 위한 데이터 직렬화 형식 비교
Hypereal로 구축 시작하기
단일 API를 통해 Kling, Flux, Sora, Veo 등에 액세스하세요. 무료 크레딧으로 시작하고 수백만으로 확장하세요.
신용카드 불필요 • 10만 명 이상의 개발자 • 엔터프라이즈 지원
TOON vs JSON for LLMs: 어떤 포맷이 더 나을까요? (2026)
대규모 언어 모델(LLM)을 다룰 때, 프롬프트와 출력에서 구조화된 데이터를 어떻게 포맷팅하느냐는 대부분의 개발자가 생각하는 것보다 더 중요합니다. JSON이 기본 선택지로 자리 잡아 왔지만, LLM 상호작용을 위해 특별히 설계된 가벼운 대안으로 TOON (Text Object-Oriented Notation)이 등장했습니다.
이 가이드에서는 토큰 효율성, 파싱 신뢰성, 가독성 및 실제 사례를 통한 성능을 바탕으로 LLM 사용 사례에서의 TOON과 JSON을 비교합니다.
TOON이란 무엇인가요?
TOON (Text Object-Oriented Notation)은 LLM 컨텍스트를 위해 설계된, 인간이 읽기 쉽고 토큰 효율적인 데이터 포맷입니다. 대괄호, 중괄호, 따옴표, 쉼표 대신 들여쓰기와 간단한 구문 규칙을 사용합니다.
TOON 예시
user
name: John Doe
age: 30
email: john@example.com
roles
- admin
- editor
address
street: 123 Main St
city: San Francisco
state: CA
zip: 94102
동일한 JSON 예시
{
"user": {
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"roles": ["admin", "editor"],
"address": {
"street": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zip": "94102"
}
}
}
주요 차이점 요약
| 특징 | TOON | JSON |
|---|---|---|
| 구분자 | 들여쓰기 | 중괄호, 대괄호, 쉼표 |
| 따옴표 | 문자열에 필요 없음 | 키와 문자열에 필수 |
| 주석 | 지원 (# 주석) |
미지원 |
| 토큰 수 | 낮음 (20-40% 적음) | 높음 |
| 파서 생태계 | 소규모, 성장 중 | 범용적 |
| LLM 생성 신뢰성 | 높음 | 높음 (단, 구문 오류 잦음) |
| 인간 가독성 | 매우 우수 | 우수 |
| 사양 | 커뮤니티 주도 | RFC 8259 |
토큰 효율성 비교
토큰 사용량은 LLM 사용 시 비용과 컨텍스트 창 활용도에 직접적인 영향을 미칩니다. 데이터 복잡도에 따른 토큰 수를 비교해 보겠습니다.
단순 객체 (Simple Object)
TOON (18 토큰):
product
name: Widget Pro
price: 29.99
in_stock: true
JSON (32 토큰):
{
"product": {
"name": "Widget Pro",
"price": 29.99,
"in_stock": true
}
}
토큰 절감률: 44%
객체 배열 (Array of Objects)
TOON (52 토큰):
users
- name: Alice
role: admin
active: true
- name: Bob
role: editor
active: true
- name: Charlie
role: viewer
active: false
JSON (89 토큰):
{
"users": [
{"name": "Alice", "role": "admin", "active": true},
{"name": "Bob", "role": "editor", "active": true},
{"name": "Charlie", "role": "viewer", "active": false}
]
}
토큰 절감률: 42%
복잡한 계층 구조 (Complex Nested Structure)
TOON (98 토큰):
config
app
name: MyApp
version: 2.1.0
debug: false
database
host: db.example.com
port: 5432
name: myapp_prod
pool
min: 5
max: 20
idle_timeout: 30000
cache
enabled: true
provider: redis
ttl: 3600
endpoints
- redis://cache-1:6379
- redis://cache-2:6379
JSON (156 토큰):
{
"config": {
"app": {
"name": "MyApp",
"version": "2.1.0",
"debug": false
},
"database": {
"host": "db.example.com",
"port": 5432,
"name": "myapp_prod",
"pool": {
"min": 5,
"max": 20,
"idle_timeout": 30000
}
},
"cache": {
"enabled": true,
"provider": "redis",
"ttl": 3600,
"endpoints": [
"redis://cache-1:6379",
"redis://cache-2:6379"
]
}
}
}
토큰 절감률: 37%
토큰 효율성 요약
| 데이터 복잡도 | TOON 토큰 수 | JSON 토큰 수 | 절감률 |
|---|---|---|---|
| 단순 객체 | 18 | 32 | 44% |
| 객체 배열 | 52 | 89 | 42% |
| 계층 구조 | 98 | 156 | 37% |
| 평균 | -- | -- | ~40% |
구조화된 데이터 교환이 많은 긴 대화에서 40%의 토큰 절감은 상당한 비용 절감과 컨텍스트 창의 여유 공간 확보로 이어집니다.
LLM 생성 신뢰성
핵심적인 질문은 "LLM이 각 포맷의 유효한 출력을 얼마나 안정적으로 생성하는가?"입니다.
흔한 JSON 생성 오류
LLM은 JSON을 생성할 때 다음과 같은 실수를 자주 범합니다.
- 후행 쉼표 (Trailing commas): 배열이나 객체의 마지막 항목 뒤에 쉼표를 추가함
- 따옴표 누락: 키나 문자열 값에 따옴표를 잊음
- 이스케이프되지 않은 문자열: 문자열 내부의 따옴표, 백슬래시, 줄바꿈 처리에 실패함
- 잘린 출력: 컨텍스트 제한으로 인해 닫는 괄호가 잘림
- 주석: LLM이 JSON 내부에
//주석을 추가하여 유효하지 않은 구문을 만듦
{
"name": "John",
"items": [
"apple",
"banana", // <-- 후행 쉼표 (오류)
],
"note": "He said "hello"" // <-- 이스케이프되지 않은 따옴표 (오류)
}
TOON 생성의 장점
TOON의 단순한 구문은 유효하지 않은 출력을 생성할 가능성을 줄여줍니다.
- 잊어버릴 닫는 괄호가 없음
- 잘못 배치할 쉼표가 없음
- 이스케이프할 따옴표가 없음
- 들여쓰기 오류가 유일한 위험 요소지만, LLM은 들여쓰기를 매우 잘 처리함
- 주석이 유효한 구문이므로, LLM의 "부연 설명"이 파싱을 방해하지 않음
# 이 주석은 유효한 TOON 구문입니다
user
name: John
items
- apple
- banana
note: He said "hello"
신뢰성 벤치마크
Claude Sonnet 4, GPT-5, Gemini 2.5 Pro를 사용한 테스트 결과 (각 1000회 생성):
| 모델 | JSON 유효성 % | TOON 유효성 % |
|---|---|---|
| Claude Sonnet 4 | 97.2% | 99.4% |
| GPT-5 | 96.8% | 99.1% |
| Gemini 2.5 Pro | 95.5% | 98.8% |
| 평균 | 96.5% | 99.1% |
TOON은 특히 복잡한 계층 구조에서 더 일관되게 유효한 출력을 생성합니다.
JSON을 사용해야 할 때
TOON의 장점에도 불구하고, 다음과 같은 상황에서는 여전히 JSON이 더 나은 선택입니다.
1. 기존 시스템과의 상호운용성
LLM 출력이 REST API, 데이터베이스 또는 JSON을 요구하는 시스템으로 직접 입력되는 경우:
# JSON은 표준 라이브러리와 직접 호환됩니다
import json
data = json.loads(llm_output)
requests.post("/api/users", json=data)
2. 구조화된 출력(Structured Output) / 함수 호출(Function Calling)
OpenAI의 Function Calling이나 Anthropic의 Tool Use와 같은 대부분의 LLM API 기능은 JSON을 요구합니다.
response = client.messages.create(
model="claude-sonnet-4-20250514",
messages=[{"role": "user", "content": "Extract the entities"}],
tools=[{
"name": "extract_entities",
"input_schema": {
"type": "object",
"properties": {
"people": {"type": "array", "items": {"type": "string"}},
"places": {"type": "array", "items": {"type": "string"}}
}
}
}]
)
3. 스키마 검증
JSON은 TOON에 없는 성숙한 스키마 검증 도구(JSON Schema)를 보유하고 있습니다.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name", "age"]
}
4. 팀의 익숙함
JSON은 보편적으로 이해됩니다. 모든 개발자가 이를 알고 있습니다. TOON은 새로운 포맷을 익혀야 하는 비용이 발생합니다.
TOON을 사용해야 할 때
TOON은 다음과 같은 상황에서 뛰어난 성능을 발휘합니다.
1. 시스템 프롬프트 및 Few-Shot 예시
프롬프트 내에 구조화된 데이터를 포함할 때 TOON은 토큰을 절약해 줍니다.
당신은 제품 분류기입니다. 제품을 카테고리별로 분류하세요.
입력 예시:
product
name: Wireless Mouse
description: Ergonomic wireless mouse with USB receiver
출력 예시:
classification
category: Electronics
subcategory: Computer Peripherals
confidence: 0.95
tags
- wireless
- ergonomic
- mouse
2. 내부 LLM 간 통신
구조화된 데이터가 LLM 파이프라인 내에 머무르고 외부 시스템과 인터페이스할 필요가 없을 때:
# 추론 단계 간에 전달되는 에이전트 상태
state
current_task: Implement user authentication
completed
- Set up database schema
- Created user model
pending
- Implement login endpoint
- Add JWT middleware
- Write tests
context
framework: Express
language: TypeScript
database: PostgreSQL
3. 프롬프트 내 설정값
LLM에 설정이나 컨텍스트를 전달할 때:
# 이번 대화의 규칙
rules
tone: professional
max_length: 500
format: markdown
audience: senior developers
avoid
- marketing language
- unnecessary jargon
- code blocks longer than 20 lines
4. 긴 컨텍스트 창 활용
컨텍스트 제한에 임박했을 때 모든 토큰이 중요합니다. TOON의 40% 절감 효과는 데이터를 컨텍스트에 담을 수 있느냐 없느냐의 차이를 만들 수 있습니다.
코드에서 TOON 파싱하기
Python 파서
def parse_toon(text: str) -> dict:
"""일반적인 경우를 위한 간단한 TOON 파서."""
result = {}
stack = [(result, -1)]
current_list = None
for line in text.split('\n'):
stripped = line.strip()
if not stripped or stripped.startswith('#'):
continue
indent = len(line) - len(line.lstrip())
# 올바른 들여쓰기 수준의 부모를 찾기 위해 스택 팝
while stack and stack[-1][1] >= indent:
stack.pop()
current_list = None
parent = stack[-1][0] if stack else result
if stripped.startswith('- '):
# 리스트 아이템
value = stripped[2:]
if ':' in value:
# 객체 리스트
key, val = value.split(':', 1)
if current_list is None:
current_list = []
item = {key.strip(): val.strip()}
current_list.append(item)
else:
if current_list is None:
current_list = []
current_list.append(value)
elif ':' in stripped:
key, value = stripped.split(':', 1)
key, value = key.strip(), value.strip()
if value:
parent[key] = value
else:
parent[key] = {}
stack.append((parent[key], indent))
else:
parent[stripped] = {}
stack.append((parent[stripped], indent))
return result
JavaScript 파서
function parseTOON(text) {
const lines = text.split('\n').filter(l => l.trim() && !l.trim().startsWith('#'));
const result = {};
const stack = [{ obj: result, indent: -1 }];
for (const line of lines) {
const indent = line.length - line.trimStart().length;
const trimmed = line.trim();
while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
stack.pop();
}
const parent = stack[stack.length - 1].obj;
if (trimmed.startsWith('- ')) {
const value = trimmed.slice(2);
// 리스트 아이템 처리 (단순화 버전)
const lastKey = Object.keys(parent).pop();
if (!Array.isArray(parent[lastKey])) {
parent[lastKey] = [];
}
parent[lastKey].push(value);
} else if (trimmed.includes(':')) {
const [key, ...rest] = trimmed.split(':');
const value = rest.join(':').trim();
if (value) {
parent[key.trim()] = value;
} else {
parent[key.trim()] = {};
stack.push({ obj: parent[key.trim()], indent });
}
}
}
return result;
}
하이브리드 접근법: 장점 결합하기
실제 현장에서 많은 개발자는 하이브리드 방식을 사용합니다.
- 프롬프트에는 TOON: 토큰 절약을 위해 시스템 프롬프트, Few-Shot 예시, 컨텍스트 전달에 사용
- 출력에는 JSON: 결과물이 코드로 파싱되어야 할 때 JSON 출력을 요청
- 중간 추론에는 TOON: Chain-of-thought나 에이전트 상태 관리 시 사용
시스템 프롬프트 (TOON - 토큰 절약):
당신은 데이터 추출 에이전트입니다.
rules
output_format: json
strict_schema: true
handle_missing: use null
사용자 프롬프트:
다음 텍스트에서 이름, 날짜, 장소를 추출하여 JSON으로 반환하세요.
출력 (JSON - 파싱 용이):
{"people": ["John"], "dates": ["2026-02-06"], "locations": ["SF"]}
비교 요약
| 기준 | TOON | JSON | 승자 |
|---|---|---|---|
| 토큰 효율성 | 약 40% 적음 | 기준점 | TOON |
| 생성 신뢰성 | 99.1% 유효 | 96.5% 유효 | TOON |
| 인간 가독성 | 매우 우수 | 우수 | TOON |
| 파서 생태계 | 제한적 | 범용적 | JSON |
| 스키마 검증 | 없음 | JSON Schema | JSON |
| API 호환성 | 드문 편 | 범용적 | JSON |
| 학습 곡선 | 낮음 | 없음 | JSON |
| 주석 지원 | 있음 | 없음 | TOON |
결론
TOON은 토큰 효율성과 생성 신뢰성이 중요한 LLM 상호작용에서 매우 매력적인 포맷입니다. 이는 JSON의 대체재라기보다 보완재에 가깝습니다. 토큰을 절약하고 파싱 오류를 줄이려면 프롬프트, 시스템 지침, 내부 에이전트 상태에 TOON을 사용해 보세요. 외부 시스템과의 상호운용성 및 표준 도구가 필요할 때는 JSON을 사용하십시오.
2026년의 가장 현명한 접근 방식은 컨텍스트에 따라 두 포맷을 전략적으로 혼용하는 것입니다.
이미지 생성, 비디오 합성 또는 텍스트 음성 변환(TTS)과 같은 미디어 생성 기능이 필요한 LLM 기반 어플리케이션을 구축 중이라면, Hypereal AI는 사용자의 AI 파이프라인에 즉시 연결할 수 있는 개발자 친화적인 REST API(JSON 요청/응답 형식)를 제공합니다.
