데이터 사이언스 프로젝트에 Repomix를 사용해 보았습니다. 22,000 KB 파일이 생성되어 직접 도구를 만들었습니다.
요약
Repomix와 같은 기존 코드 패키징 도구가 데이터 사이언스 프로젝트의 대용량 CSV, SQL 덤프, 바이너리 파일을 처리할 때 발생하는 토큰 낭비 문제를 분석합니다. 이를 해결하기 위해 데이터 유형별 맞춤형 전략을 사용하는 data2prompt 도구 개발 과정을 소개합니다.
핵심 포인트
- 기존 도구는 데이터 프로젝트의 대용량 파일을 무분별하게 텍스트로 변환하여 LLM 과부하 유발
- CSV는 전체 행 대신 스마트 샘플링을 통해 구조와 대표성만 전달 필요
- SQL은 데이터 행 대신 스키마(CREATE TABLE) 위주로 추출해야 효율적
- Jupyter Notebook 내 base64 이미지 데이터는 LLM에게 불필요한 노이즈임
- data2prompt는 파일 유형별 맞춤형 전략으로 토큰 효율성을 극대화함
몇 달 전, 한 친구가 Repomix와 code2prompt라는 두 가지 도구를 보여주었습니다. 아이디어는 간단했습니다. 프로젝트 폴더를 지정하면 도구가 모든 것을 하나의 파일로 패키징하고, 사용자는 이를 LLM (Large Language Model)에 붙여넣어 전체 코드베이스에 대해 한 번에 질문할 수 있다는 것이었습니다. 친구의 순수 Python 프로젝트들에는 이 도구들이 아주 잘 작동했습니다.
당시 저는 데이터 분석 프로젝트를 진행 중이었습니다. 차원(dimension) 및 사실(fact) CSV 파일, SQL 덤프(dump), 몇몇 Power BI 파일, 그리고 ML (Machine Learning) 모델이 포함된 Jupyter Notebook들이 있었습니다. 여기에 Repomix를 실행했더니 22,085 KB의 출력 파일이 생성되었습니다. code2prompt는 9,304 KB를 생성했습니다. 둘 중 하나를 Claude에 붙여넣으려 시도해 보았지만, 즉시 과부하가 걸려 작동을 멈췄습니다.
그래서 파일 안에 실제로 무엇이 들어있는지 확인하기 위해 파일을 열어보았습니다. 그리고 제가 발견한 것이 바로 문제의 근원이었습니다.
데이터 프로젝트에서 이 도구들이 놓치고 있는 점
Repomix와 code2prompt는 코드(code) 저장소를 위해 만들어졌습니다. 이들은 모든 파일을 읽고, 모든 파일을 쏟아낸다는 단순한 원칙에 따라 작동합니다. 프로젝트가 Python 스크립트와 설정 파일들로 구성되어 있다면 잘 작동합니다. 하지만 제 프로젝트처럼 구성되어 있다면 완전히 무너집니다.
파일 크기를 부풀린 원인은 다음과 같습니다.
가공되지 않은 CSV 덤프. 저의 Fact_Sales.csv에는 수만 개의 행이 있었습니다. 도구는 그 모든 행을 다 쏟아냈습니다. LLM은 50,000개의 판매 데이터 행을 필요로 하지 않습니다. 구조와 대표성 있는 샘플이 필요할 뿐입니다.
끝도 없는 SQL INSERT 문. 저의 Superstore.sql 파일에는 모든 테이블에 대한 모든 INSERT INTO 문을 포함한 전체 데이터베이스 덤프가 들어있었습니다. LLM에게 실제로 필요한 것은 스키마(schema), 즉 CREATE TABLE 블록입니다. 데이터 행들은 대부분 노이즈(noise)에 불과합니다.
base64 이미지가 포함된 노트북 출력. Jupyter Notebook은 셀 출력 내용을 .ipynb 파일 내부의 JSON으로 저장합니다. 셀이 matplotlib 차트를 생성하면, 그 차트는 notebook 내부의 base64 인코딩된 이미지 문자열로 저장됩니다. 단 하나의 차트 출력만으로도 LLM이 전혀 사용할 수 없는 50,000자 이상의 base64 쓰레기 데이터가 될 수 있습니다.
텍스트로 읽힌 바이너리 파일 (Binary files read as text). 저의 .pbix (Power BI) 파일들은 바이너리 형식입니다. 기존 도구들은 이 파일들을 텍스트로 읽으려 시도했고, 그 결과 정보는 전혀 제공하지 못하면서 토큰만 소비하는 손상된 쓰레기 데이터를 생성했습니다.
이러한 문제들을 이해하는 도구가 없었습니다. 그래서 3개월간의 개발 끝에 — 솔직히 말씀드리면 저는 개발자가 아닌 데이터 사이언티스트이기에 AI의 도움을 매우 많이 받았습니다 — data2prompt를 출시했습니다.
data2prompt가 차별화되는 점
핵심 아이디어는 데이터 프로젝트의 각 파일 유형마다 일반적인 "읽고 쏟아붓기 (read and dump)" 방식이 아닌, 각기 다른 전략이 필요하다는 것입니다.
CSV 및 Excel: 스마트 샘플링 (Smart Sampling)
모든 행을 쏟아붓는 대신, data2prompt는 무작위 샘플을 추출합니다:
df = df.sample(sample_size, random_state=seed)
기본값은 15행이며, --csv-sample-size로 설정할 수 있습니다. 결정적으로 이는 파일의 앞부분이나 뒷부분을 가져오는 것이 아니라, 고정된 시드(seed)를 사용한 무작위 (random) 샘플링입니다. 무작위 샘플링은 LLM에게 데이터셋 전체에 걸친 값의 다양성을 더 대표성 있게 보여줍니다. 시드(기본값 42)를 사용함으로써 실행 시마다 동일한 출력을 재현할 수 있습니다.
출력 결과는 LLM에게 자신이 무엇을 보고 있는지 정확히 알려줍니다:
-- [Sample - Random 15 rows] --
| order_id | customer_name | sales | profit |
|----------|--------------|--------|--------|
...
Excel 파일의 경우, 각 시트(sheet)를 독립적으로 샘플링합니다. 파서(parser)는 시각적인 대시보드(차트, 이미지만 있는 경우)로만 구성된 시트를 감지하여, 빈 테이블을 생성하는 대신 해당 내용을 기록합니다.
SQL 파일: 스키마 보존 및 데이터 샘플링
이 파서를 제대로 구현하는 것이 가장 어려웠습니다. SQL 덤프(dump) 파일은 일반적으로 스키마를 정의하는 CREATE TABLE 블록이 나오고, 그 뒤를 이어 데이터를 로드하는 수백 또는 수천 개의 INSERT INTO 문이 따르는 패턴을 보입니다.
data2prompt는 한 줄씩 읽으며 각 부분에 서로 다른 로직을 적용합니다:
# 항상 스키마를 보존합니다
if "CREATE TABLE" in line_upper:
flush_buffer()
...
INSERT 행이 담긴 버퍼에 도달하면, 이를 무작위로 샘플링합니다:
rest_indices = sorted(rng.sample(range(1, len(table_data_buffer)), sample_size - 1))
sampled_rows = [first_line] + [table_data_buffer[idx] for idx in rest_indices]
첫 번째 줄(INSERT 헤더)은 항상 보존됩니다. 나머지는 원래 순서대로 무작위 샘플링된 데이터입니다. LLM은 모든 테이블의 전체 스키마 (Schema)와 대표적인 데이터 샘플을 받게 되며, 이는 LLM이 데이터베이스를 이해하는 데 정확히 필요한 정보입니다.
Jupyter Notebooks: 소스 코드만 추출
노트북 셀 (Notebook cells)은 소스 코드 (Source code), 실행 횟수 (Execution count), 그리고 출력값 (Outputs)이라는 세 가지 요소를 저장합니다. 파일 크기를 부풀리는 주범은 바로 출력값입니다. 출력값에는 출력된 데이터프레임 (Dataframes), base64 형식의 matplotlib 차트, 에러 트레이스백 (Error tracebacks) 등이 포함됩니다.
data2prompt는 모든 셀의 소스 코드는 유지하되 출력값은 완전히 제거합니다. 8MB에 달하던 JSON 형식의 노트북이 깔끔한 코드 셀 시퀀스로 변환됩니다. 또한 파서 (Parser)는 비정상적으로 긴 줄을 잘라내며(Truncation), 출력값이 실제로 유용한 텍스트인 경우에도 설정 가능한 라인 제한에 따라 출력 블록의 크기를 제한합니다.
XML 형식의 경우, 각 셀은 다음과 같이 구조화된 블록이 됩니다:
<cell path="ML/Q1/Q1.ipynb" index="3" type="code">
<content>
model = XGBRegressor(n_estimators=100, learning_rate=0.1)
...
바이너리 파일 (Binary Files): 목록만 표시, 내용은 읽지 않음
.pbix, .parquet, .pkl, .db, .sqlite, .feather, .h5 — 이 파일들은 디렉토리 트리 (Directory tree)에 모두 나열되어 LLM이 파일의 존재를 알 수 있게 하지만, 내용은 완전히 건너뜁니다. 컨텍스트 윈도우 (Context window)를 소모하는 쓰레기 바이트 (Garbage bytes)가 발생하지 않습니다.
두 가지 출력 형식: Markdown과 XML
data2prompt는 --format markdown (기본값)과 --format xml을 모두 지원합니다.
XML 형식은 Anthropic이 XML 스타일의 태그가 LLM의 어텐션 (Attention)과 파싱 (Parsing) 성능을 향상시킨다는 연구 결과를 발표한 이후에 추가되었습니다. 전체 프로젝트는 다음과 같이 구조화된 계층 구조로 감싸집니다:
<codebase name="superstore-analysis">
<metadata>
<generated_on>2025-05-31 09:00</generated_on>
...
벤치마크 (Benchmark)
동일한 프로젝트, 동일한 파일, 세 가지 도구:
| 도구 (Tool) | 출력 크기 (Output Size) |
|---|---|
| Repomix | 22,085 KB |
| ... |
동일한 데이터 집약적 (data-heavy) 프로젝트에서 Repomix 대비 98.9%, code2prompt 대비 97.4%의 감소율을 기록하면서도, 스키마 (schemas), 샘플링된 데이터 (sampled data), 노트북 로직 (notebook logic), 파일 트리 (file tree)와 같이 구조적으로 유용한 모든 정보는 그대로 보존했습니다.
이러한 극적인 감소는 특히 프로젝트의 유형 때문에 발생합니다. 순수 Python 프로젝트라면 격차가 훨씬 작았을 것입니다. 바로 이 점이 핵심입니다. 이 도구는 코드 프로젝트가 아닌 데이터 프로젝트를 위해 만들어졌습니다.
설치 및 사용법 (Installation and Usage)
# 설치 (Install)
pip install data2prompt
...
기본 사용법 — 프로젝트 디렉토리 내부에서 실행하세요:
# 기본값: Markdown 출력
data2prompt
...
출력 파일 (기본값: PROMPT.md 또는 PROMPT.xml)은 Claude, ChatGPT, Gemini 또는 컨텍스트 창 (context window)이 큰 모든 LLM에 직접 붙여넣을 준비가 되어 있습니다.
또한 프로젝트 루트에 .data2promptignore 파일을 생성하여 — .gitignore와 동일한 구문 사용 — 특정 파일이나 패턴을 영구적으로 제외할 수 있습니다.
대상 사용자 (Who This Is For)
data2prompt는 다음과 같은 작업을 수행하는 데이터 사이언티스트 (data scientists), 데이터 분석가 (data analysts), 데이터 엔지니어 (data engineers)를 위해 특별히 설계되었습니다:
- CSV/Excel 데이터 파일
- SQL 데이터베이스 덤프 (database dumps)
- Jupyter 노트북 (Jupyter notebooks)
- Power BI 또는 기타 바이너리 분석 파일 (binary analytics files)
- 코드와 데이터가 혼합된 프로젝트
만약 당신의 프로젝트가 데이터 파일이 없는 순수 Python 스크립트라면, Repomix나 code2prompt로도 충분할 것입니다. 하지만 당신의 프로젝트가 실제 데이터 사이언스 워크플로우 (data science workflow)와 조금이라도 닮아 있다면, data2prompt를 사용해 보세요.
GitHub: https://github.com/arianmokhtariha/data2prompt
PyPI: https://pypi.org/project/data2prompt
SQL 파서 (parser)가 어떻게 작동하는지, 혹은 왜 헤드/테일 (head/tail) 기반의 무작위 샘플링 (random sampling)을 사용하는지 등에 대한 질문이 있다면 댓글로 남겨주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기