로디 · 문서

02/ 04

RAG 1 · 무엇을 넣고, 어떻게 전달할까 — Dataset

Owen Lee · 이원빈완성 원고

로디는 법령·조례의 기준을 RAG에 준비하고, 현재 공고와 문의처는 웹에서 확인하도록 기획했습니다. 이 글에서는 수집한 자료의 범위와, 그 자료를 청킹 에이전트에 전달하기 전 형식을 비교한 결과를 설명합니다.

청킹 에이전트는 RAG 구축 파이프라인에서 문서를 검색용 조각으로 나누는 자동화된 에이전트입니다. 자세한 동작은 뒤의 구축 파이프라인 글에서 설명합니다.

1. 법령의 기준과 현재 공고를 나눠 준비했습니다

“이 지원을 저도 받을 수 있나요?”라는 질문에는 자격 조건과 지금 신청할 수 있는지가 함께 담겨 있습니다. 두 내용을 확인하려면 자료의 역할을 나눌 필요가 있었습니다.

  • RAG에 준비할 기준 자료: 법령과 조례에서 자격·적용 범위·예외를 찾습니다. 관련 원문을 모델에 전달해 답변의 근거로 사용합니다.
  • 웹에서 확인할 변동 정보: 현재 운영 중인 사업, 모집·신청 기간, 기관 위치와 연락처를 찾습니다. 해당 지자체나 운영 기관의 최신 안내를 우선 확인합니다.
복지 지원 질문에서 RAG의 법령·자격 조건과 웹의 최신 공고·문의처를 함께 확인하는 흐름
복지 지원 질문에서 RAG의 법령·자격 조건과 웹의 최신 공고·문의처를 함께 확인하는 흐름원본 크기로 보기

예를 들어 생활비 지원 상담에서는 관련 제도의 조건을 먼저 찾고, 거주 지역의 현재 공고와 문의처를 확인하는 흐름을 구상했습니다. 기준 자료를 미리 준비하면 공식 원문과 해설, 오래된 공고를 매번 가려내는 일을 줄일 수 있습니다. 법령도 개정되므로 자료를 갱신하고, 답변에 적용할 지역·시점·조건을 확인해야 합니다.

비교 대상: 법령 7건과 조례 4건

로디의 상담 범위에는 연금·복지와 함께 고령자 고용, 근로·퇴직 문제도 포함돼 있습니다. 프로젝트의 질문 예시에도 나이를 이유로 한 채용 거절과 퇴직금을 받지 못한 상황이 등장합니다. 아래 자료는 이런 상담 주제와 연결됩니다.

  • 연금·복지 — 법령 2건: 기초연금법, 노인복지법.
  • 고용·근로·퇴직 — 법령 5건: 고용보험법, 고령자고용법, 근로기준법, 근로자퇴직급여 보장법, 최저임금법.
  • 지역별 고령자 경비원·공동주택 노동자 — 조례 4건: 부산 수영구, 울산, 인천, 전주 관련 조례. 초기 RAG 실험을 위한 기본 예시 문서로 사용했습니다.

자료 확장은 뒤에서 다룰 자동화된 RAG 구축 파이프라인을 활용하는 방향으로 잡았습니다. 초기 실험에서 개념이 검증되면, 새로운 법령과 조례를 같은 구축 절차로 처리해 지식 기반을 넓힐 수 있습니다.

이 글에서는 위 11건의 API 본문 응답을 재수집해 형식별 토큰 수를 비교했습니다. 비교 범위는 각 응답의 전체 내용이며, 서비스 전체의 데이터 구성을 평가한 실험은 아닙니다.

2. 이름으로 검색하고, 식별자로 원문을 받았습니다

자료는 법제처 국가법령정보 공동활용 API에서 수집했습니다. 법령 이름으로 목록을 검색한 뒤, 결과에 포함된 식별자로 본문을 조회했습니다. 응답의 이름과 식별자가 요청한 자료와 일치하는지도 확인했습니다.

기초연금법을 검색해 법령 ID를 얻고 본문 JSON을 요청하는 국가법령정보 API 흐름
기초연금법을 검색해 법령 ID를 얻고 본문 JSON을 요청하는 국가법령정보 API 흐름원본 크기로 보기

기초연금법의 경우 검색 결과에서 법령ID 012045를 얻었습니다. 이 ID로 받은 본문에는 소관부처인 보건복지부와 실제 조문이 들어 있었습니다. 법령과 조례는 응답 구조가 달라 각각의 기본정보와 조문 위치를 확인했고, 조례에서는 지자체 이름도 확인했습니다.

3. 전체 응답에서는 Compact JSON이 가장 짧았습니다

청킹 에이전트에 원문을 전달할 때는 본문 외에도 반복되는 필드명과 들여쓰기가 입력 토큰을 차지합니다. 그래서 같은 내용을 유지하면서 전달 형식만 바꿔도 입력을 줄일 수 있는지 비교했습니다.

11건 모두 Compact JSON이 가장 짧았습니다. 전체 입력은 319,597토큰에서 271,299토큰으로 15.11% 감소했습니다. TOON은 292,669토큰으로 8.43% 줄었지만, Compact JSON보다는 길었습니다.

비교한 형식은 API 원본인 Original, 들여쓰기를 정리한 Pretty JSON, 공백을 줄인 Compact JSON, 반복 구조를 다른 문법으로 표현한 TOON입니다. 아래 표는 같은 토크나이저로 각 응답 전체를 측정한 결과입니다.

11건의 형식별 토큰 비교

셀: 토큰 수 (원본 대비 변화율). ↓ 감소 · ↑ 증가. 초록색은 해당 문서에서 가장 짧은 형식입니다. 긴 문서명은 표 안에서 줄여 적었습니다.

문서OriginalPrettyCompactTOON
고용보험법85,35085,483(↑0.16%)73,150(↓14.29%)78,522(↓8.00%)
고령자고용법22,18622,256(↑0.32%)18,456(↓16.81%)20,129(↓9.27%)
근로기준법62,25362,358(↑0.17%)52,960(↓14.93%)57,118(↓8.25%)
퇴직급여 보장법40,34840,401(↑0.13%)33,906(↓15.97%)36,813(↓8.76%)
최저임금법16,33316,395(↑0.38%)13,646(↓16.45%)15,072(↓7.72%)
기초연금법23,82323,883(↑0.25%)20,493(↓13.98%)21,916(↓8.00%)
노인복지법59,31259,462(↑0.25%)50,038(↓15.64%)53,843(↓9.22%)
부산 수영구 경비원 조례4,1744,126(↓1.15%)3,722(↓10.83%)3,873(↓7.21%)
울산 경비원 조례1,4331,421(↓0.84%)1,188(↓17.10%)1,315(↓8.23%)
인천 경비원 조례1,5641,563(↓0.06%)1,316(↓15.86%)1,451(↓7.23%)
전주 관리노동자 조례2,8212,783(↓1.35%)2,424(↓14.07%)2,617(↓7.23%)
합계319,597320,131(↑0.17%)271,299(↓15.11%)292,669(↓8.43%)

변화율 = (해당 형식 토큰 / Original 토큰 − 1) × 100. 합계의 변화율은 문서별 토큰을 더한 뒤 계산했습니다.

Pretty JSON은 사람이 읽기 위한 들여쓰기 때문에 원본보다 길어지는 경우도 있었습니다. 원문을 더 보기 좋게 정렬하는 일과 모델에 전달할 토큰을 줄이는 일은 결과가 달랐습니다.

4. TOON은 같은 필드가 반복될 때 유리했습니다

기초연금법 제2조의 호 배열에서는 TOON이 Compact JSON보다 8토큰(3.39%) 짧았습니다. 네 항목이 모두 호번호·호내용 필드를 공유하는 구조입니다.

Compact JSON은 항목마다 이 필드명을 반복합니다. TOON은 굵게 표시한 헤더에 배열 길이와 필드명을 한 번만 적고, 각 행에는 값만 나열합니다.

Compact JSONTOON
{"호":[{"호번호":"1.","호내용":"1. \"기초연금 수급권(受給權)\"이란 이 법에 따른 기초연금을 받을 권리를 말한다."},{"호번호":"2.","호내용":"2. \"기초연금 수급권자\"란 기초연금 수급권을 가진 사람을 말한다."},{"호번호":"3.","호내용":"3. \"기초연금 수급자\"란 이 법에 따라 기초연금을 지급받고 있는 사람을 말한다."},{"호번호":"4.","호내용":"4. \"소득인정액\"이란 본인 및 배우자의 소득평가액과 재산의 소득환산액을 합산한 금액을 말한다. 이 경우 소득평가액과 재산의 소득환산액을 산정하는 소득 및 재산의 범위는 대통령령으로 정하고, 소득평가액과 재산의 소득환산액의 구체적인 산정방법은 보건복지부령으로 정한다."}]}
"호"[4]{"호번호","호내용"}:
  1.,"1. \"기초연금 수급권(受給權)\"이란 이 법에 따른 기초연금을 받을 권리를 말한다."
  2.,"2. \"기초연금 수급권자\"란 기초연금 수급권을 가진 사람을 말한다."
  3.,"3. \"기초연금 수급자\"란 이 법에 따라 기초연금을 지급받고 있는 사람을 말한다."
  4.,"4. \"소득인정액\"이란 본인 및 배우자의 소득평가액과 재산의 소득환산액을 합산한 금액을 말한다. 이 경우 소득평가액과 재산의 소득환산액을 산정하는 소득 및 재산의 범위는 대통령령으로 정하고, 소득평가액과 재산의 소득환산액의 구체적인 산정방법은 보건복지부령으로 정한다."
236토큰228토큰 · Compact 대비 3.39% 감소

공식 문서의 TOON보다 다른 형식이 유리한 경우에서는 중첩이 깊거나 구조가 불규칙하면 Compact JSON이 더 짧을 수 있다고 설명합니다. 일부 항목만 구조가 같은 배열은 절감 폭이 작아 기존 JSON을 유지하는 편을 권합니다. 단순한 표는 CSV가 더 작습니다. 처리 속도가 중요하다면 토큰 수와 별개로 실제 모델에서 실행 시간도 비교해야 합니다.

이번 법령 전체 응답에도 중첩된 항목과 서로 다른 조문 구조가 섞여 있었습니다. 전체를 전달할 때는 Compact JSON이 유리했고, 같은 필드가 반복되는 검색 결과나 도구 응답에는 TOON을 후보로 남겼습니다.

이번 작업은 자료 수집과 전달 형식 비교까지입니다. 다음 글에서는 문서를 어떤 청크로 나누고, 검색 구조와 관계 후보를 어떻게 만들고 검토하는지 설명합니다.

재현 방법과 작성 근거

원본의 모든 필드를 포함해 변환한 뒤, 값·타입·배열 순서가 같은지 검사했습니다. 11건 모두 원본과 일치했습니다. 이 결과는 전달 문자열의 토큰 수 비교이며, API 과금·청킹 정확도·임베딩 비용·검색 품질은 별도 측정 대상입니다.

API 요청·변환·검증 방법 보기

법령 요청. 목록 검색에는 OC(API 인증값), target=law, type=JSON, query(법령명)를 보냅니다. 응답의 LawSearch.law에서 이름·ID·일련번호·본문 링크를 확인합니다. 본문은 lawService.do에 ID 또는 MST를 전달해 조회합니다.

응답 구조. 법령의 기본정보는 법령.기본정보, 조문은 법령.조문.조문단위에 있습니다. 장 제목도 섞여 있어 조문여부를 확인합니다. 조례는 target=ordin으로 요청하며, LawService 아래의 자치법규기본정보와 조문.조를 읽습니다. 식별자는 ID 또는 자치법규 일련번호인 MST를 사용합니다.

변환. 응답마다 파일 하나를 저장했습니다. Original은 받은 텍스트, Pretty는 JSON.stringify(value, null, 2), Compact는 JSON.stringify(value)입니다. TOON은 @toon-format/toon 4.1.1의 encode(value, {indentSize: 2, delimiter: ","})로 만들었습니다.

검증과 측정. Pretty와 Compact는 JSON.parse, TOON은 strict decode로 다시 읽어 원본과 대조했습니다. 토큰은 tiktoken 0.13.0의 o200k_harmony 인코딩과 encode_ordinary()로 셌습니다. 법령 ID·시행일을 검색 조건용 필드로 정규화하는 작업은 이 형식 비교와 별개입니다.

같은 객체의 표현 예시. 아래는 기초연금법 응답의 소관부처 객체입니다. Compact JSON은 보건복지부와 코드 문자열 1352000을 유지하면서 문자열 바깥의 공백과 개행을 없앱니다.

형식 / 처리동일한 소관부처 객체의 실제 표현
Original · 응답의 해당 구간 그대로
{
            "content": "보건복지부",
            "소관부처코드": "1352000"
        }
Pretty · JSON.stringify(value, null, 2)
{
  "content": "보건복지부",
  "소관부처코드": "1352000"
}
Compact · JSON.stringify(value)
{"content":"보건복지부","소관부처코드":"1352000"}
TOON · @toon-format/toon encode(value)
content: 보건복지부
"소관부처코드": "1352000"

예시 토큰 수: Original 28 · Pretty 27 · Compact 20 · TOON 21. 소관부처 객체와 제2조 배열은 구조를 설명하기 위한 부분 예시이며, 11건의 합계에 다시 더하지 않았습니다. 표 안의 자동 줄바꿈과 관계없이 실제 변환 문자열을 측정했습니다.

TOON의 쉼표·탭·파이프 구분자도 비교했습니다. 쉼표 설정이 가장 짧았지만, 전체 11건의 Compact JSON보다는 7.88% 길었습니다.