ARK-1139: 데이터 플랫폼 리뉴얼¶
Jira: ARK-1139 | 상태: In Progress | 담당: 백재현 | 설계 보고서: data-platform-design.vercel.app
최종 업데이트: 2026-03-27
문제의식 — 왜 지금 바꿔야 하는가¶
현재 Data Platform의 설계는 "AI가 먼저 제안하고 사람이 고른다" 는 가정 위에 세워졌다. 하지만 실제 사용 패턴을 보면 이 가정이 틀렸음을 알 수 있다.
1. 자동 제안(Proposal)의 함정¶
데이터 소스를 연결하면 Agent가 자동으로 proposal을 생성한다. 얼핏 편리해 보이지만 사용자의 의도가 시스템 안으로 들어가는 입구 자체가 없다.
흐름 비교
사용자가 원하는 것: "이 DB의 거래 테이블로 월별 매출 추이 CM을 만들고 싶다"
현재 시스템: Agent가 자동으로 여러 proposal 생성 → 사용자가 그 중에서 선택 → 원하는 게 없으면 다시 요청
Agent가 먼저 추측하고, 사용자는 그 추측에 반응하는 수동적인 위치에 놓인다. 협업이 아니라 correction의 반복이 된다.
2. "Source가 주인공"인 구조의 경직성¶
현재 구조 Source → Proposals (1:N) 은 Source를 중심에 두지만, 실제 작업 단위와 맞지 않는다.
현재 구조는 "설계서(proposal)"를 "실행 단위(pipeline)"로 오용하고 있다.
- 같은 Source에서 변환 로직이 다른 CM 2개를 만들고 싶다면? → 독립 Pipeline 2개가 있어야 한다
- Pipeline을 일시정지하거나 재실행하고 싶다면? → Proposal에는 상태 개념이 없다
- Pipeline 실행 이력을 추적하고 싶다면? → Proposal은 설계서지 실행 단위가 아니다
3. Schedule이 잘못된 곳에 묶여 있다¶
Schedule의 본질적인 의미는 "이 데이터 소스를 언제 갱신할 것인가" 다. Proposal을 선택했냐 안 했냐는 Schedule과 무관해야 한다.
올바른 모델: Dataset 단위로 schedule 설정 → 갱신 시 연결된 Pipeline 자동 트리거
4. 파일 업로드 부재 — 사용 케이스의 절반을 놓치고 있다¶
DB 커넥션만 지원하면 실제 사용자가 활용하는 데이터의 상당 부분을 커버할 수 없다.
- 리서치 하우스의 리포트 데이터 (CSV)
- 특수 데이터 벤더의 커스텀 포맷
- 팀 내부에서 직접 가공한 데이터셋
파일만 있으면 CM을 만들 수 있어야 한다. 이 능력이 없으면 플랫폼의 접근성 자체가 제한된다.
5. 팀 사일로 — 좋은 데이터가 팀 안에 갇힌다¶
각 팀이 만든 Content Model이 팀 경계 안에 갇혀 있다. A팀이 공들여 만든 고품질 CM이 있어도 B팀은 그 존재조차 모른다.
데이터도 코드처럼 재사용될 수 있어야 한다. 검증된 CM은 팀 간에 공유·구독되어 중복 작업을 없애야 한다.
AS-IS vs TO-BE¶
| 관점 | AS-IS | TO-BE |
|---|---|---|
| 워크플로우 | Scan → Propose → Select → Extract | User intent → Agent 협업 → Preview → Production |
| 구조 | 1 Source → N Proposals | 1 Pipeline = 1 Dataset (1:1) |
| 실행 단위 | Proposal (설계서) | Pipeline (실행 단위) |
| Schedule 귀속 | Proposal에 1:1 | Dataset 단위 → Pipeline 자동 트리거 |
| 파일 지원 | DB 커넥션만 | DB + 파일 업로드 (CSV/Parquet/JSON/Excel) |
| Agent 역할 | 자동 제안 생성 | 사용자 피드백 기반 CM 초안 반복 생성 |
| 팀 간 공유 | 불가 | Catalog Marketplace (구독 모델) |
구현 진행 현황¶
브랜치:
wogus/ARK-1139| 마지막 확인: 2026-03-27
진행 상태¶
| 레포 | 커밋 | PR | 변경 내용 | 상태 |
|---|---|---|---|---|
arkraft-api |
107606a |
#441 | vendors 테이블, vendor→connector, ConnectorType enum, test 엔드포인트, artifacts, AI descriptions, spec docs, OAuth 전파 | ✅ PR 생성 |
arkraft-web |
27e22149 |
#437 | Source/Dataset 서브탭 분리, Proposals UI 제거, AI descriptions 표시, DOCS 탭, artifacts 탭, TEST 버튼 | ✅ PR 생성 |
arkraft-agent-data |
6d64468 |
#106 | PostgreSQL schema 버그 수정, AI descriptions (Claude SDK), spec docs S3 로드, artifacts 디렉토리, 이벤트 로깅 | ✅ PR 생성 |
[arkraft-api] POST /data/sources/{id}/test — 연결 테스트 엔드포인트¶
PR: #441
데이터 소스 저장 전/후 연결 가능 여부를 확인하는 엔드포인트 추가.
UI에서는 SourceDetail 헤더에 TEST 버튼이 위치하며, 결과 뱃지가 버튼 좌측에 표시된다.
[arkraft-api] source_docs_prefix + artifacts 엔드포인트¶
무엇을 바꿨나:
DataS3Paths.source_docs_prefix헬퍼: spec 문서(xlsx/xls 등)가 저장되는 S3 경로 생성GET /data/sources/{id}/artifacts: 워크스페이스 전체 파일 조회 (scan_manifest.json 항목만이 아닌 전체)
scan_manifest.json 지원: scan 실행 후 생성되는 scan_manifest.json을 통해 artifacts 목록 파싱 가능. 단, artifacts 엔드포인트는 manifest 항목에 한정하지 않고 워크스페이스 전체를 반환한다.
[arkraft-api] AI descriptions 스키마 응답 포함¶
무엇을 바꿨나:
- 스키마 API 응답(
GET /data/sources/{id}/schema)에 AI 생성 descriptions 포함 - DB/테이블/컬럼 레벨의 descriptions가 agent scan 후 S3에 저장되어 있으면 함께 반환
{
"tables": [{
"name": "transactions",
"description": "일별 주식 거래 내역 테이블 (AI 생성)",
"columns": [{
"name": "amount",
"description": "거래 금액 (KRW 단위, AI 생성)"
}]
}]
}
[arkraft-api] USE_OAUTH / OAuth 토큰 data agent 전파¶
data agent 컨테이너 실행 시 환경변수로 USE_OAUTH 플래그와 OAuth 액세스 토큰을 주입. agent 내부에서 Claude API 호출 시 Bedrock 직접 호출 대신 OAuth 경유 방식으로 전환 가능.
[arkraft-api] spec 문서 허용 확장자 확장¶
| 이전 | 이후 추가 |
|---|---|
.pdf, .txt, .md |
.xlsx, .xls, .xlsm, .xlsb |
spec 문서란 데이터 소스의 컬럼 정의서, 데이터 명세서 등 agent가 description 생성 시 참고하는 문서다.
[arkraft-api] vendors 테이블 신규, connector 리네임¶
PR: #441
무엇을 바꿨나:
data_sources.vendor (VARCHAR)→data_sources.connector (ConnectorType enum, NOT NULL)data_sources.source_type컬럼 완전 제거vendors테이블 신규 생성 (team-scoped,team_id IS NULL= 전팀 공용)data_sources.vendor_id,data_sets.vendor_idFK 추가ConnectorTypeStrEnum: postgresql/mysql/mariadb/s3/glue_catalog/rest_api/ftp/sftpCONNECTOR_CATEGORY맵 추가,DataSourceResponse.category필드 노출- Migration:
e5b0031e15ee_add_vendors_connector_enum.py(autogenerated)
왜 바꿨나 (ADR-5, ADR-6): 아래 ADR 섹션 참조
[arkraft-web] Sources → Source/Dataset 서브탭 분리¶
PR: #437
무엇을 바꿨나:
변경 전:
/data/sources → DataSourcesClient (Source 목록 + ProposalSection)
SubNav에 Data 섹션 드롭다운
변경 후:
/data/sources → redirect → /data/sources/source
/data/sources/source → Source 목록 (TertiaryNav: Source | Dataset)
/data/sources/dataset → Dataset 목록 (신규 라우트)
SubNav: Data 섹션에서 서브메뉴 숨김 (TertiaryNav로 이관)
DataSourcesClient: ProposalSection 제거, container resize 동적 계산
SourceDetail: Schema 탭 flex layout 수정, 헤더 단일 행 컴팩트 레이아웃
드래그 resize 성능 최적화 (rAF 쓰로틀)¶
드래그 중 setState 호출을 제거하고, requestAnimationFrame으로 쓰로틀된 DOM 직접 조작으로 전환했다.
문제: mousemove 이벤트는 초당 수백 번 발생한다. 매번 setPanelHeight 호출 → React re-render → 버벅임.
1차 개선 (이전): DOM 직접 조작 (panelRef.current.style.height)으로 re-render 제거.
2차 개선 (이번): requestAnimationFrame으로 프레임당 1회로 추가 쓰로틀.
const rafRef = useRef<number | null>(null);
function onMove(ev: MouseEvent) {
if (!dragRef.current) return;
const clientY = ev.clientY;
if (rafRef.current !== null) return; // 이미 rAF 예약됨 → 스킵
rafRef.current = requestAnimationFrame(() => {
rafRef.current = null;
if (!dragRef.current || !panelRef.current) return;
const delta = dragRef.current.startY - clientY;
// ... 높이 계산
panelRef.current.style.height = `${next}px`;
});
}
function onUp() {
if (rafRef.current !== null) {
cancelAnimationFrame(rafRef.current); // 미처리 rAF 취소
rafRef.current = null;
}
const finalH = panelRef.current.clientHeight;
setPanelHeight(finalH); // mouseup 시에만 state 동기화
}
| 단계 | 방식 | 효과 |
|---|---|---|
| AS-IS | mousemove → setState |
re-render 연속 발생, 버벅임 |
| 1차 개선 | DOM 직접 조작 | re-render 제거 |
| 2차 개선 (현재) | rAF 쓰로틀 + DOM 조작 | 프레임당 1회 제한, 60fps 보장 |
resize handle에 select-none 추가
드래그 중 텍스트 선택이 발생하는 문제도 함께 수정. resize handle div에 select-none 클래스 추가.
SourceDetail 헤더 레이아웃 컴팩트화¶
변경 전: 2행 레이아웃 (소스명+상태 / 메타정보 / 버튼)으로 헤더 높이가 컸다.
변경 후: 단일 flex items-center 행으로 통합 — 소스명, ScanChip, 메타정보(truncate), 버튼 순서로 좌→우 배치.
// 변경 전: py-4, 2행 구조
<div className="shrink-0 border-b border-neutral-800 px-5 py-4">
<div className="flex items-start justify-between mb-3">
<div>
<h2 className="text-[15px] ...">...</h2>
<p className="text-[12px] ...">...</p>
</div>
<div className="flex items-center gap-2 shrink-0">버튼들</div>
</div>
</div>
// 변경 후: py-2, 단일 행
<div className="shrink-0 border-b border-neutral-800 px-5 py-2">
<div className="flex items-center gap-2 mb-2">
<h2 className="text-[13px] ... shrink-0">소스명</h2>
<ScanChip />
<p className="text-[11px] ... min-w-0 truncate">메타정보</p>
<div className="flex items-center gap-2 shrink-0 ml-auto">버튼들</div>
</div>
</div>
flowchart TD
direction TB
A[/data/sources] -->|redirect| B[/data/sources/source]
subgraph TertiaryNav["TertiaryNav (Sources 진입 시)"]
direction TB
B[Source 탭]
C[Dataset 탭]
end
B --> D[Source 목록 UI]
C --> E[Dataset 목록 UI]
미결 질문 — Web
/data/sources/dataset페이지는 현재 어떤 상태인가요? 빈 placeholder인가요, 아니면 기존 Dataset 목록 UI가 이미 있나요?ProposalSection을 UI에서 완전히 제거한 건가요, 아니면 점진적 제거의 첫 단계인가요? 기존selected상태의 proposal 데이터는 어떻게 접근하나요?
[arkraft-web] AI descriptions 표시 + DOCS 탭 + artifacts 탭¶
PR: #437
AI descriptions 표시¶
스키마 뷰(SchemaTreeView)에 AI 생성 descriptions 렌더링 추가.
initialTable prop으로 초기 선택 테이블 지정 가능 (URL 파라미터 연동 등에 활용).
<SchemaTreeView
sourceId={sourceId}
initialTable="transactions" // AI description 포함 응답으로부터 하이라이트
/>
DOCS 탭 — spec 문서 관리 UI¶
spec 문서를 업로드/조회하는 탭 신규 추가.
| 기능 | 구현 |
|---|---|
| 문서 목록 조회 | 업로드 존 위에 기존 문서 목록 표시 |
| 파일 업로드 | 클릭 + drag & drop 모두 지원 |
| 허용 확장자 | .xlsx, .xls, .xlsm, .xlsb, .pdf, .txt, .md |
drag & drop 구현 포인트:
- onDragOver → e.preventDefault() + setDragOver(true)
- onDrop → e.dataTransfer.files 처리
- onDragLeave → setDragOver(false)
- 업로드 직후 presigned URL 요청 → S3 직접 PUT (double JSON.stringify 버그 수정 포함)
artifacts 탭 — scan 산출물 파일 브라우저¶
scan 완료 후 생성되는 워크스페이스 파일들을 탐색하는 탭.
GET /data/sources/{id}/artifacts API를 사용하며, manifest 항목에 한정하지 않고 전체 파일 목록을 표시.
TEST 버튼 레이아웃 이동¶
| 이전 | 이후 |
|---|---|
| 하단 버튼 영역 | SourceDetail 헤더 우측 |
연결 테스트 결과 뱃지(✅ 연결됨 / ❌ 실패)가 TEST 버튼 좌측에 인라인 표시.
[arkraft-agent-data] AI descriptions + S3 artifacts 구조 개선¶
PR: #106
AI descriptions — DB/테이블/컬럼 설명 자동 생성¶
scan 완료 후 Claude Agent SDK를 이용해 DB 전체 구조에 대한 자연어 설명을 자동 생성한다.
인증 분기:
if USE_OAUTH:
# Claude Agent SDK + OAuth 토큰 (arkraft-api가 주입)
client = AnthropicBedrock(access_token=os.environ["OAUTH_TOKEN"])
else:
# Claude Agent SDK + Bedrock IAM (기존 방식)
client = AnthropicBedrock()
Bedrock 직접 호출(boto3.client("bedrock-runtime")) → Claude Agent SDK로 전환. 구조화된 출력(tool_use 블록)으로 DB/테이블/컬럼 descriptions를 한 번에 생성.
spec docs 활용:
source_docs_prefix 하위 S3 파일들을 로드하여 description 생성 프롬프트에 주입.
예: transactions_spec.xlsx가 있으면 컬럼 정의서를 참고해 더 정확한 description 생성.
spec_docs = load_spec_docs_from_s3(source_docs_prefix)
prompt = f"""
DB Schema:
{schema_json}
Reference Documents:
{spec_docs_text}
Generate descriptions for each table and column.
"""
S3 artifacts 디렉토리 구조¶
scan 실행 결과물을 기능별 prefix로 분리 저장:
s3://arkraft-{env}/data-sources/{source_id}/workspace/
├── schema.json # 전체 스키마 (테이블/컬럼 목록)
├── descriptions.json # AI 생성 descriptions
├── scan_manifest.json # 산출물 목록 (파일명, 크기, 생성시각)
└── artifacts/
├── sample_data/ # 각 테이블 샘플 데이터
└── stats/ # 컬럼별 통계
이벤트 로깅¶
agent 실행 중 LLM 이벤트를 구조화된 로그로 기록:
| 이벤트 타입 | 로그 내용 |
|---|---|
thinking |
extended thinking 블록 텍스트 |
text |
일반 텍스트 응답 |
tool_use |
도구 호출명 + 입력 파라미터 |
PostgreSQL schema 범위 버그 수정¶
# 변경 전: public schema 고정
schema_filter = "schema_name = 'public'"
# 변경 후: 시스템 schema 제외 전체 탐색 (MySQL/MariaDB와 동일 방식)
excluded = ['information_schema', 'pg_catalog', 'pg_toast']
# + pg_temp_*, pg_toast_* 패턴 제외
핵심 도메인 구조¶
flowchart TD
direction TB
subgraph Source["Source Layer"]
direction TB
S1[RDS Connection]
S2[Cloud Warehouse]
S3[File Upload]
end
subgraph Dataset["Dataset"]
direction TB
D1[spec 정의]
D2[schedule/cron]
end
subgraph Pipeline["Pipeline Layer"]
direction TB
P1[1 Pipeline = 1 Dataset]
P2[Agent 피드백 루프]
P3[CM 생성]
end
subgraph Catalog["Catalog Layer"]
direction TB
C1[CatalogEntry]
C2[Marketplace 구독]
end
Source --> Dataset --> Pipeline --> Catalog
도메인별 설계¶
Source¶
- RDS Connection / Cloud Warehouse / File Upload 통합
- vendor는 Source에 귀속 (RDS/Warehouse만 해당)
- File Upload: S3 presigned URL, CSV/Parquet/JSON/Excel, 크기 제한 없음
Dataset¶
- Source 하위 소속
- vendor는 Source로부터 자동 상속
- spec 메타정보 보유 (하단 ARK-1149 참조)
- Dataset 단위로 schedule(cron) 설정
- Dataset 갱신 시 연결된 Pipeline 자동 트리거
Pipeline¶
- 1 Pipeline = 1 Dataset (엄격한 1:1)
- vendor는 Dataset.vendor 자동 참조 (직접 설정 불필요)
- 인터랙션: 채팅 아님 — Agent가 CM 초안 생성 → 사용자 피드백 → 반복
- 1 Pipeline → N Content Model(CM) 생성 가능
Content Model (CM)¶
- Pipeline에서 생산되는 개별 데이터 산출물
- 상태:
building→preview→scheduled→running→paused - 결과는 CatalogEntry로 연결
Catalog¶
- CM 생산 결과물 집합소
is_public플래그로 Marketplace 공개 여부 결정CatalogSubscription으로 팀 간 구독
핵심 설계 결정 (ADR)¶
ADR-1: Pipeline과 Dataset을 1:1로 제한¶
결정: 1 Pipeline = 1 Dataset (N:1 금지)
이유:
- Pipeline은 Dataset의 schema와 긴밀하게 결합된다 (transform definition이 schema 기반)
- Dataset schema가 바뀌면 Pipeline의 transform도 재검토가 필요
- 1:1 제약이 있으면 Dataset 변경의 영향 범위가 명확해진다
- 같은 Dataset으로 다른 변환이 필요하면 → Pipeline을 새로 만들면 된다 (명시적)
ADR-2: Schedule을 Dataset에 귀속¶
결정: Schedule은 Dataset 단위로 설정, Pipeline을 자동 트리거
이유:
- Schedule의 의미론적 주체는 "데이터 소스의 갱신 주기"이지 "어떤 변환을 선택했나"가 아님
- Dataset이 갱신되면 연결된 모든 Pipeline이 트리거되어야 함 (데이터 일관성)
- Pipeline 레벨에서 수동 트리거도 가능 (유연성 확보)
ADR-3: Agent 인터랙션을 구조화된 피드백 루프로¶
결정: 채팅 UI 대신 "CM 초안 → 피드백 입력 → 재생성" 루프
이유:
- 채팅은 이력 관리가 어렵고 "어느 버전의 CM인가"를 추적하기 어렵다
- 구조화된 피드백은 각 수정 사항이
PipelineFeedback레코드로 저장됨 - 특정 시점으로 롤백하거나 다른 피드백으로 재시도 가능
- Agent 입장에서도 명확한 diff 기반 수정이 더 정확하다
ADR-4: 파일 업로드는 S3 presigned URL¶
결정: 파일 업로드는 S3 presigned URL 방식, 크기 제한 없음
이유:
- API 서버를 통한 파일 프록시는 대용량 파일에서 병목이 됨
- Presigned URL은 클라이언트 → S3 직접 업로드로 서버 부하 없음
- 금융 데이터의 특성상 대용량 파일이 많아 크기 제한을 두지 않음
ADR-5: Source 연결 방식 필드명을 connector로 통일¶
결정: engine / vendor (문자열) 대신 connector 단일 필드 사용
배경:
초기 설계에서는 engine (postgresql, mysql 등 DB 엔진명)과 vendor (데이터 제공사) 두 개념이 혼재했다. DB가 아닌 소스(S3, REST API, FTP/SFTP)가 추가되면서 engine이라는 이름 자체가 어색해졌다.
| 후보 | 문제점 |
|---|---|
engine |
S3, REST API에 "엔진"은 의미 없음 |
vendor |
별도 VendorModel 엔티티로 분리됨 (아래 ADR-6) — 중복/혼란 |
connector |
모든 소스 유형에 자연스럽게 적용 가능 |
결정:
data_sources.vendor→data_sources.connector(컬럼명 변경)source_type컬럼 제거 —connector값에서 카테고리 파생 가능connector타입:ConnectorTypeStrEnum (DB 레벨 non-native enum)
connector → 카테고리 매핑:
CONNECTOR_CATEGORY = {
"postgresql": "database",
"mysql": "database",
"mariadb": "database",
"s3": "object_storage",
"glue_catalog": "object_storage",
"rest_api": "api",
"ftp": "ftp",
"sftp": "ftp",
}
영향 범위: data_sources 테이블 + 이를 참조하는 모든 서비스, 스키마, 테스트
ADR-6: Vendor를 별도 엔티티(vendors 테이블)로 분리¶
결정: vendor(데이터 제공사)를 문자열이 아닌 독립 엔티티로 관리
배경:
- 데이터 소스(Source)는 연결 방법(
connector)을 가지지만, 그 데이터의 출처(FnGuide, Bloomberg, 내부 생성)는 다른 개념 - Dataset은 Source 없이 직접 생성될 수도 있어 vendor 정보를 Dataset에도 독립적으로 지정해야 할 필요가 생김
- Source의 vendor를 Dataset이 단순 상속하는 방식만으로는 "출처 불명" Dataset을 표현할 수 없음
설계:
CREATE TABLE vendors (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL, -- "FnGuide", "Bloomberg", "Internal"
code VARCHAR(100) UNIQUE NOT NULL, -- "fnguide", "bloomberg", "internal"
description TEXT,
team_id UUID, -- NULL이면 글로벌, 값이 있으면 팀 전용
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ
);
ALTER TABLE data_sources ADD COLUMN vendor_id UUID REFERENCES vendors(id);
ALTER TABLE data_sets ADD COLUMN vendor_id UUID REFERENCES vendors(id);
규칙:
team_id IS NULL: 전팀 공용 vendor (e.g., FnGuide, Bloomberg)team_id IS NOT NULL: 특정 팀 전용 vendor- vendors는 CRUD API로 팀이 직접 생성/관리 (
POST /data/vendors)
결과: 파일 Dataset의 vendor 지정 방식 미결 사항 해소 (→ data_sets.vendor_id 직접 지정)
DB 스키마 구현 현황¶
Migration:
e5b0031e15ee_add_vendors_connector_enum.py(autogenerated, branch:wogus/ARK-1139)
vendors 테이블 (신규)¶
CREATE TABLE vendors (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
code VARCHAR(100) NOT NULL UNIQUE,
description TEXT,
team_id UUID,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX ix_vendors_team_id ON vendors(team_id);
data_sources 변경사항¶
| AS-IS | TO-BE | 변경 유형 |
|---|---|---|
vendor VARCHAR(255) |
connector ConnectorType NOT NULL |
리네임 + Enum 타입 |
source_type VARCHAR(50) |
(제거) | 컬럼 삭제 |
| (없음) | vendor_id UUID REFERENCES vendors(id) |
FK 추가 |
data_sets 변경사항¶
| AS-IS | TO-BE | 변경 유형 |
|---|---|---|
| (없음) | vendor_id UUID REFERENCES vendors(id) |
FK 추가 |
Alembic 마이그레이션 체인¶
source_type 파생
source_type 컬럼은 제거됐으나, 카테고리가 필요한 경우
CONNECTOR_CATEGORY[source.connector]로 파생한다. (DataSourceResponse.category로 노출)
Sub-tasks¶
| 이슈 | 제목 | 상태 |
|---|---|---|
| ARK-1149 | Dataset spec 정의 및 파일 업로드 검증 파이프라인 도입 | Backlog |
ARK-1149: Dataset spec 정의 및 검증 파이프라인¶
문제¶
현재 파일 업로드 시마다 LLM Full Pipeline이 실행된다:
데이터 형상을 매번 추론해야 하므로 비효율적이고, 기존 Dataset과의 형상 일치 여부 검증이 없다.
설계 방향¶
Dataset = 데이터 파일들 + 그 파일들이 따라야 할 spec
Dataset spec 구조¶
{
"columns": [{"name": "date", "type": "date"}, ...],
"time_axis": {"column": "date", "format": "%Y-%m-%d", "frequency": "daily"},
"entity_axis": {"column": "ticker"},
"value_columns": ["close", "volume"],
"cm_name": "kr_stock_price_daily",
"delivery_lag": 1
}
spec 정의 시점¶
| Dataset 생성 경로 | spec 정의 시점 | 출처 |
|---|---|---|
| Source(RDB) → Dataset | Dataset 생성 시 | trial 결과 spec.json 승계 |
| 첫 파일 업로드 | 첫 업로드 Full Pipeline 완료 후 | 생성된 spec.json 저장 |
업로드 파이프라인 분기 변경¶
flowchart TD
direction TB
A[파일 업로드 confirm]
A --> B{Dataset에 spec 있음?}
B -->|없음 - 첫 업로드| C[Full Pipeline<br>detect_normalize → spec 생성 → 저장]
B -->|있음| D[검증 모드<br>spec 형상 검증]
D -->|통과| E[transform + register]
D -->|실패| F[에러 리포트 반환]
검증 스텝 (신규)¶
- 컬럼명/타입 일치 여부
- time_axis, entity_axis 존재 여부
- 타입 호환성 (e.g., date 컬럼이 실제로 파싱 가능한지)
영향 범위¶
| 레포 | 변경 내용 |
|---|---|
arkraft-api |
Dataset 모델 spec 컬럼 추가, migration, upload 서비스 분기 변경 |
arkraft-agent-data |
검증 스텝 구현 |
arkraft-web |
Dataset 상세 UI에 spec 메타 표시 |
마이그레이션 고려사항¶
| AS-IS | TO-BE | 비고 |
|---|---|---|
data_sources.vendor |
data_sources.connector |
ConnectorType enum으로 전환 완료 |
data_sources.source_type |
(제거) | category 필드로 API 응답에서 파생 |
dataset_proposals |
datasets + pipelines |
1 proposal → 1 dataset + 1 pipeline (미구현) |
proposal.schedule |
dataset.cron_schedule |
schedule 귀속 이동 (미구현) |
| — | vendors |
신규 완료 (ADR-6) |
| — | content_models |
미구현 |
| — | catalog_entries |
미구현 |
마이그레이션 원칙
- 기존
selected상태의 proposal만 pipeline으로 이관 (unselected는 아카이브) - 이관 전 충분한 검증 기간 필요 (기존 API 병행 운영)
미결 사항¶
설계 미결¶
- ~~파일 Dataset의 vendor 지정 방식~~ →
data_sets.vendor_idFK로 직접 지정 (ADR-6) - ~~spec 문서 S3 업로드 및 agent 연동~~ →
source_docs_prefix+ DOCS 탭 + agent S3 로드로 완성 - ~~AI descriptions 스키마 API 노출~~ →
GET /data/sources/{id}/schema응답에 포함 - Agent tool use 접근 범위 (읽기 전용 vs 쓰기)
- Catalog Marketplace 접근 제어 (추후)
- 기존 데이터 마이그레이션 전략
- Vendor CRUD API (
POST /data/vendors,GET /data/vendors) 구현 - Dataset 상세 UI에 spec 메타 표시 (ARK-1149)
- Pipeline 모델 구현 및 Proposal 이관