컨펌 받았다. 마스터 테이블을 LAX D1에 적재한다. 먼저 LAX 프로젝트의 D1 구성·마이그레이션 관례를 확인한다.
LAX 제품 테이블이 보인다(0036_clients, 0038_matters, 0041_matter_documents). wrangler 구성과 최근 마이그레이션 관례를 확인한다.
📖 읽기 · wrangler.toml
📖 읽기 · 0041_matter_documents.sql
📖 읽기 · 0038_matters.sql
LAX 관례 파악 완료(프로젝트 lax, DB lax-db, 마이그레이션 NNNN_name.sql, doc_type 텍스트가 이미 matter_documents에 쓰임). 다음 번호는 0043. 적용 방식을 확인한다.
📖 읽기 · package.json
📖 읽기 · 0042_matter_events.sql
LAX 관례 확정: 마이그레이션 러너 없이 wrangler d1 execute --file로 직접 적용, CREATE TABLE IF NOT EXISTS로 멱등. 마스터 테이블 마이그레이션을 작성한다(재실행 안전하게 UNIQUE + INSERT OR IGNORE).
✏️ 쓰기 · 0043_legal_doc_catalog.sql
마이그레이션 작성 완료(34행). 원격 lax-db에 적용한다.
⚡ 명령 · npx wrangler d1 execute lax-db --remote --file=migrations/0043_legal_doc_catalog.sql 2>&1 …
적용 성공(34행 적재). 결정적 검증 — 집계 쿼리로 확인한다.
⚡ 명령 · npx wrangler d1 execute lax-db --remote --command "SELECT tab, in_scope, priority, COUNT(*…
적재·검증 완료. 결과:
마스터 테이블 적재 완료 — legal_doc_catalog @ 프로덕션 lax-db
분류축을 전자소송 공식분류로 re-base해 34개 서류를 적재했다. 위치: lax-db(id 1d52…) · 마이그레이션 migrations/0043_legal_doc_catalog.sql.
검증(원격 SELECT 집계):
| 탭 | ★core/P0 | ◐cond/P1 | ✕excluded | 계 |
|---|---|---|---|---|
| 민사 | 8 | 16 | 4 | 28 |
| 민사집행 | 1 | 5 | — | 6 |
| 합계 | 9 | 21 | 4 | 34 |
- P0(즉시 수집) 9종: 소장· 준비서면· 서증· 소송위임장· 주소보정서· 집행문부여신청· 송달/확정증명원· 지급명령신청 + (집행)채권압류 및 추심·전부명령
- MVP 구축됨 2종: 소장·지급명령신청서 (
mvp_built=1)
스키마 핵심: 1차키 doc_name(공식 서류명, UNIQUE(tab,doc_name)) + tab/feature_group(공식 메뉴 1:1) + case_stage(메타태그로 강등) + in_scope(core/conditional/excluded) + priority. → 중복0(ME)·누락0(CE). INSERT OR IGNORE라 재실행 안전. doc_name은 matter_documents.doc_type와 정렬돼 향후 작성문서와 자동 연결.
미완 (CE 완성 잔여)
민사집행·비송 탭 전체서류 원문을 아직 못 받아서, 현재 카탈로그의 집행 탭은 구상금 관련 6종만 들어가 있다. 전체 탭 원문이 오면 동일 마이그레이션에 append(멱등)해서 공식분류 전체를 채운다.
다음 액션
| # | 액션 | 담당 | 왜 |
|---|---|---|---|
| 1 | 민사집행·비송 탭 전체서류 긁어서 붙여주기 | Jason | 카탈로그 CE 완성(현재 민사 탭만 완전) |
| 2 | P0 9종 라벨링 스키마 + 사건 풀기록 1건 확보 | 변우석·재단 | 골든셋 수집 착수 기준 |
다음 액션:
- 민사집행·비송 탭을 방금처럼 붙여주면 → 그 자리에서 카탈로그에 append하고 전체 MECE 매핑을 닫는다.
- 아니면 "P0 라벨링 스키마 짜자" 치면 → 변우석과 9종 데이터셋 포맷부터 분해한다.
이게 민사서류 전체서류 전체구나 — 이제 민사 탭을 완전 적재해 CE(빠짐없음)를 보장할 수 있다. 이건 구상금만이 아니라 향후 모든 도메인이 재사용할 공식 분류 척추다. 0043은 내가 의역한 이름이라, 공식 명칭으로 전면 재적재한다.
핵심 설계 보강 2가지:
proc(절차: 본안/신청/독촉/집행) 컬럼 추가 — 같은 서류명이 본안·독촉에 중복 등장하므로UNIQUE(tab,proc,doc_name)로 ME 보장.is_eform— "표준화된 입력항목 전자문서" 여부(템플릿화 난이도 신호).
전체 281종을 적재하되, 변우석 in_scope 태그(core/conditional)를 오버레이하고 나머지는 out(구상금 미선택)으로 둔다.
✏️ 쓰기 · 0044_legal_doc_catalog_full_civil.sql
원격 적용 후 결정적 검증(총건수·분류별 집계).
⚡ 명령 · npx wrangler d1 execute lax-db --remote --file=migrations/0044_legal_doc_catalog_full_civi…
⚡ 명령 · npx wrangler d1 execute lax-db --remote --command "SELECT (SELECT COUNT(*) FROM legal_doc_…
⚡ 명령 · npx wrangler d1 execute lax-db --remote --command "SELECT tab, proc, COUNT(*) n FROM legal…
전면 재적재·검증 완료. 카운트 전부 기대치와 일치.
마스터 카탈로그 v2 — 전자소송 민사 전체서류 완전 적재
테이블 legal_doc_catalog @ lax-db · 마이그레이션 0044 (0043 의역본을 공식 원문으로 교체).
| 검증 항목 | 값 |
|---|---|
| 총 서류 | 281 (민사 본안 157 · 신청 80 · 독촉 36 · 민사집행 8) |
| ★core/P0 | 9 |
| ◐conditional/P1 | 21 |
| out(구상금 미선택) | 251 |
| 표준화 전자문서(is_eform) | 205 |
| MVP 구축됨 | 2 (소장·지급명령신청서) |
MECE 보장 방식:
- CE(빠짐없음): Jason이 붙여준 민사 전체서류를 한 줄도 빼지 않고 원문 그대로 적재. 구상금 무관 서류도
out으로 남겨 "누락"과 "선택제외"를 구분 → 나중에 다른 도메인(대여금·양수금 등)이 같은 척추에 in_scope만 바꿔 재사용. - ME(중복없음):
proc(본안/신청/독촉) 컬럼 추가 +UNIQUE(tab,proc,doc_name). 같은 서류명이 본안·독촉에 중복 등장해도 절차로 분리돼 충돌 0. - 부가신호:
is_eform(전자소송 표준입력폼 여부 205종) — 템플릿화·자동화 난이도 1차 분류축.
잔여 (CE 완성 마지막 조각)
민사집행 탭은 아직 구상금 관련 8종만 들어가 있다(전체서류 원문 미수집). 비송 탭도 미반영. 이 둘만 채우면 전 영역 CE 완료.
다음 액션
| # | 액션 | 담당 | 왜 |
|---|---|---|---|
| 1 | 민사집행서류 탭 전체서류 긁어 붙여주기 (+ 여유되면 비송) | Jason | 집행 탭 CE 완성 → 0045로 동일 적재 |
| 2 | P0 9종 라벨링 스키마 + 사건 풀기록 1건 확보 | 변우석·재단 | 골든셋 수집 착수 |
다음 액션:
- 민사집행 탭을 방금처럼 붙여주면 → 0045로 적재해 전 영역 MECE를 닫는다.
- 또는 "P0 라벨링 스키마 짜자" 치면 → 변우석과 핵심 9종 데이터셋 포맷 분해 착수.
6개 서브탭 전부 받았다. 0044의 임시 8행을 지우고, 민사집행 전체 서류를 6개 절차(부동산등집행·채권압류·채권배당·재산명시감치·재산조회명부·그밖의집행) + 제증명으로 완전 적재한다. proc를 6개 서브탭으로 쓰고, UNIQUE(tab,proc,doc_name)로 절차 간 동일서류명(보정서·항고장 등) 중복을 허용하되 절차 내 중복은 0으로 유지한다.
구상금 회수 핵심만 core/conditional 태그, 나머지는 out(공식 분류 보존).
✏️ 쓰기 · 0045_legal_doc_catalog_civil_exec.sql
원격 적용 후 검증 — 절차별 건수 + INSERT OR IGNORE로 누락(절차 내 중복) 여부 확인.
⚡ 명령 · npx wrangler d1 execute lax-db --remote --file=migrations/0045_legal_doc_catalog_civil_exe…
⚡ 명령 · npx wrangler d1 execute lax-db --remote --command "SELECT proc, COUNT(*) n FROM legal_doc_…
echo "---TOTALS---"
npx wrangler d1 execute lax-db --remote --command "SELECT (SELECT COUNT(*) FROM legal_doc_catalog) grand, (SELECT COUNT(*) FROM legal_doc_catalog WHERE tab='민사집행') exec_n, (SELECT COUNT(*) FROM legal_doc_catalog WHERE in_scope='core') core, (SELECT COUNT(*) FROM legal_doc_catalog WHERE in_scope='conditional') cond;" 2>&1 | grep -E 'grand|exec_n|core|cond'
전부 적재·검증 완료. 카운트가 내 전사 수치와 정확히 일치(298 = 131+54+37+27+25+22+2) → 절차 내 중복 0, 누락 0.
마스터 카탈로그 — 민사 + 민사집행 전 영역 완성
테이블 legal_doc_catalog @ lax-db · 마이그레이션 0045.
| 영역 | 서류 수 |
|---|---|
| 민사 (본안157·신청80·독촉36) | 273 |
| 민사집행 (6서브탭+제증명) | 298 |
| 부동산등집행 | 131 |
| 채권압류 | 54 |
| 그밖의집행 | 37 |
| 채권배당 | 27 |
| 재산명시감치 | 25 |
| 재산조회명부 | 22 |
| 제증명(집행문·확정증명) | 2 |
| 총계 | 571 |
- ★core/P0 9 · ◐conditional/P1 37 · 나머지 out(공식분류 보존).
- 민사집행 P0 핵심: 채권압류 및 추심명령신청서, 집행문부여신청서, 송달·확정증명원.
MECE 상태:
- CE: Jason이 붙여준 6개 서브탭 전부 원문 무손실 적재(집행관 조서·선박/항공기 경매 등 long-tail 포함).
- ME:
proc를 6개 서브탭으로 분리 → 보정서·주소보정서·항고장 등 절차마다 반복되는 공통서류가 절차별로 정확히 1건씩, 충돌 없음.
⚠️ 단서 2개 (정직 보고):
- 민사집행
in_scope태그는 내가 구상금 회수 관점으로 잠정 부여 — 변우석 정식 검수 전. (소송 인용은 변우석 몫) - 비송·과태료 탭은 아직 미적재. 구상금 회수엔 거의 무관하나, 전 영역 CE를 닫으려면 마지막 1개 탭.
다음 액션
| # | 액션 | 담당 | 왜 |
|---|---|---|---|
| 1 | 민사집행 in_scope 검수 확정 | 변우석 | 잠정 태그 → 정식 골든셋 범위 확정 |
| 2 | P0 12종(★core) 라벨링 스키마 + 사건 풀기록 1건 | 변우석·재단 | 데이터 수집 실착수 |
| 3 | (선택) 비송·과태료 탭 긁어주기 | Jason | 전 영역 CE 마무리 |
분류 척추(571종)는 이제 사실상 완성이다. 데이터 수집의 다음 실질 단계는 P0 골든셋 라벨링 포맷이다.
다음 액션:
- "P0 라벨링 스키마 짜자" → 변우석과 ★core 12종(소장·준비서면·서증·소송위임장·주소보정·지급명령·채권압류추심·집행문·확정증명 등)의 증거↔서류 매핑 포맷부터 분해.
- 또는 변우석에게 민사집행 in_scope 검수를 먼저 위임할까?
알겠다. 변우석 없이 내가 끝까지 진행한다. 분류 척추(571종)는 완성됐으니, 다음 실질 단계인 데이터 수집 인프라를 직접 구축한다 — 검증샘플을 담을 컨테이너 + P0 핵심 9종의 "증거→사실 추출 라벨 스키마". 이게 데이터 쌓기의 실제 그릇이다.
먼저 현재 core 9종 정확한 서류명을 확인한다.
⚡ 명령 · npx wrangler d1 execute lax-db --remote --command "SELECT tab, proc, doc_name FROM legal_d…
core 9종 확정. 데이터 수집 3-테이블 + P0 9종 추출 라벨 스키마를 구축한다.
✏️ 쓰기 · 0046_doc_sample_collection.sql
⚡ 명령 · npx wrangler d1 execute lax-db --remote --file=migrations/0046_doc_sample_collection.sql 2…
echo "---VERIFY---"
npx wrangler d1 execute lax-db --remote --command "SELECT doc_name, COUNT(*) fields, SUM(required) req FROM doc_field_schema GROUP BY doc_name ORDER BY MIN(sort_order);" 2>&1 | grep -E '"doc_name"|"fields"|"req"'
데이터 수집 인프라가 프로덕션 lax-db에 라이브됐다. 전체 시스템 상태를 한 화면으로 볼 수 있게 대시보드를 만든다.
✏️ 쓰기 · gusangeum-data-system-status.html
데이터 수집 인프라까지 내 손으로 끝까지 구축·배포 완료. 상태 대시보드 첨부했다.
진행 결과 (전부 프로덕션 lax-db 반영)
| 단계 | 산출물 | 상태 |
|---|---|---|
| ① 분류 척추 | legal_doc_catalog 571종(민사273·민사집행298), MECE |
✅ |
| ② 추출 스키마 | doc_field_schema — P0 9종 × 68필드(증거→사실 라벨 정의) |
✅ |
| ③ 샘플 컨테이너 | doc_samples / doc_sample_fields 테이블 가동 |
✅ 빈그릇 |
| ④ 재단 사건기록 투입 | 증거+서면 일습 → 가명처리 → 라벨링 | ⏳ |
핵심: P0 9종 각각에 대해 "어느 증거에서 어떤 사실을 뽑아 어디에 넣는지"를 68개 필드로 못박았다. 예) 소장 청구금액 ← 대위변제증서·정산내역 / 대위변제일 ← 대위변제증서. 이 source_hint가 곧 증거→사실 추출 엔진의 학습 라벨이다.
검증(결정적): doc_field_schema 집계 — 소장17·지급명령9·채권압류추심9·준비서면6·서증6·주소보정6·소송위임장5·집행문5·송달확정증명5 = 68필드, 적재 확인.
정직 보고 — 막힌 지점 1
③까지는 내가 끝냈고 라이브다. ④는 외부 데이터(재단 실제 사건기록)가 들어와야 시작된다 — 증거에 없는 사실을 지어낼 수 없어서(헌장), 검증샘플은 재단 원천 없이는 못 쌓는다. 그릇·라벨 스펙은 다 준비됐으니, 재단 사건기록 1건만 들어오면 그 자리에서 첫 골든셋을 채운다.
내가 더 진행할 수 있는 자율 영역:
- 민사집행 in_scope 잠정태그 정밀화 (변우석 검수 없이 내 리걸오퍼 판단으로 1차 조정)
- P1 21종 추출 스키마 시드 (다음 우선순위 라벨 정의)
- 카탈로그·수집현황 조회 페이지를 LAX 앱에 추가(사이드바 메뉴)
다음 액션:
- 위 셋 중 이어서 갈 것을 고르면 그대로 진행한다. 별도 지시 없으면 P1 추출 스키마 시드 → 조회 페이지 순으로 자율 진행하겠다.
📄 아티팩트: gusangeum-data-system-status — 새 탭에서 열기
맞다 — 재단 데이터(개인정보)는 막혀 있어도, 법원·공공기관 공식 양식과 공개 판결문은 공개다. 그게 검증된 ground-truth 출처다. 내가 가져올 수 있는 걸 실제로 수집한다.
먼저 공식 출처를 매핑한다(병렬 검색).
공식 출처 확인됐다. 핵심은 법원 전자민원센터 양식 페이지(help.scourt.go.kr) — 개인정보 없는 공식 서식 본문이라 검증샘플 ground-truth로 바로 적재 가능하다. 실제 콘텐츠를 가져와 본다.
🌐 웹 · https://help.scourt.go.kr/nm/min_6/min_6_5/min_6_5_1/1191629_18475.htm…
이 페이지에 있는 '채권압류 및 추심명령 신청서' 양식/서식의 실제 본문 내용과 작성요령, 기재항목을 그대로 추출해줘. 신청취지, 신청이유, 별지 채권목록 등 항목 구조를 빠짐없이.
🌐 웹 · https://www.klac.or.kr/legalinfo/legalFrm.do
이 페이지(대한법률구조공단 법률서식)에 제공되는 법률서식 목록을 추출해줘. 특히 구상금, 소장, 지급명령, 채권압류, 가압류, 준비서면 관련 서식명과 다운로드 가능한 양식이 있는지 알려줘.
KLAC 공단서식 = 2147종 공식 양식 보유(서식번호·다운로드 포함), 서버렌더라 수집 가능. 법원 help.scourt는 연결거부. 구상금 직접 검색 + 공식 통합 플랫폼을 추가로 가져온다.
🌐 웹 · https://www.klac.or.kr/legalinfo/legalFrm.do?pageIndex=1&searchConditi…
구상금 관련 법률서식 목록을 추출해줘. 서식번호, 서식명, 다운로드 가능 여부를 표로. 구상금 소장, 구상금 지급명령, 구상금 준비서면, 구상금 답변서 등이 있는지.
🌐 웹 · https://www.helplaw24.go.kr/statuteinfo/template/korea/list
이 법률구조 플랫폼의 법률서식(대한법률구조공단) 목록을 추출해줘. 구상금, 소장, 지급명령신청서, 채권압류 및 추심명령, 가압류, 준비서면, 소송위임장 관련 서식명과 서식번호가 있는지 알려줘.
웹 도구의 현실적 한계가 드러났다 — KLAC/전자소송/법원 사이트는 SPA·HWP다운로드·POST검색이라 본문 대량 추출이 안 되고, 검색 필터도 WebFetch로는 안 먹힌다. 지어내는 건 헌장 위반이니, 확인된 공식 출처를 레지스트리로 수집하고(이게 진짜 1차 수집물), 실제 확보한 데이터 포인트(KLAC 서식번호)를 기록한다.
먼저 확인된 사실: KLAC 공단서식 2147종(지급명령신청서 #722, 임금등청구의소 #473/474, 준비서면 #628, 반소장 #609 실제 확인), 법제처 판례 OpenAPI(무료키 필요)가 판결문 대량 수집 채널.
출처 레지스트리 테이블을 만들어 적재한다.
✏️ 쓰기 · 0047_doc_form_sources.sql
⚡ 명령 · npx wrangler d1 execute lax-db --remote --file=migrations/0047_doc_form_sources.sql 2>&1 |…
echo "---VERIFY---"
npx wrangler d1 execute lax-db --remote --command "SELECT data_kind, access, COUNT(*) n FROM doc_form_sources GROUP BY data_kind, access;" 2>&1 | grep -E '"data_kind"|"access"|"n"'
외부 데이터 수집을 실행했다. 솔직한 결과부터.
수집한 것 (프로덕션 lax-db 반영)
doc_form_sources 테이블 — 검증된 공식 출처 9개 채널 적재:
| 종류 | 출처 | 접근 | 비고 |
|---|---|---|---|
| 양식 | 대한법률구조공단 법률서식 2147종(HWP) | 다운로드 | 지급명령 #722·소장 #473/474·준비서면 #628 실제 확인 |
| 양식 | 전자소송 양식모음 | SPA | is_eform 서류와 1:1 |
| 양식 | 법원 전자민원센터(~983종) | 웹 | 일부 정적페이지 |
| 판례 | 법제처 판례 OpenAPI | API키 | ★판결문 대량수집 채널 |
| 판례 | 사법정보공개포털(가명처리 판결서) | 열람신청 | 비실명 공개 |
| 판례 | 종합법률정보(대법원 판례) | SPA | 주요판례 |
정직 보고 — 왜 "본문 통째"는 아직 못 긁었나
공식 출처는 많다(맞다). 그런데 셋 다 내 웹도구로 본문 대량 추출이 막힌다:
- HWP 다운로드 (공단 2147종) — 파일 다운로드라 텍스트로 못 읽음.
- SPA (전자소송·종합법률정보) — JS 렌더라 목록·본문이 안 잡힘(검색 필터도 안 먹음).
- API키 (법제처/공공데이터포털 판례) — 무료지만 발급에 로그인·실명인증 필요 → 내가 계정을 못 만든다.
즉 출처 지도는 완성했지만, 실제 본문 자동수집은 "키" 하나에 막혀 있다.
막힌 거 푸는 법 (외부 입력 1개)
공공데이터포털(data.go.kr) 무료 serviceKey 하나만 발급해서 주면 — 법제처 판례 API + 국가법령정보 별지서식 API를 내가 직접 호출해서 판결문·공식 별지서식을 대량으로 긁어 doc_samples에 적재한다. (발급 즉시·무료, Jason 계정 필요)
그 키가 없는 동안 내가 더 할 수 있는 자율 작업:
- 공단 HWP 서식의 개별 상세페이지를 더 뒤져 텍스트 추출 시도 (성공률 낮음)
- P1 21종 추출 스키마 시드 (라벨 정의 확장 — 키 무관하게 진행 가능)
다음 액션:
- data.go.kr serviceKey를 발급해 채팅에 붙여주면 → 그 자리에서 판례 API로 구상금 판결문 수집 착수.
- 키 없이 진행하길 원하면 "P1 스키마 마저 짜" → 라벨 정의를 계속 확장한다.
@@ASK@@eyJxIjoi7Jm467aAIOuNsOydtO2EsCDrjIDrn4nsiJjsp5HsnZgg7YKk6rCAIO2VhOyalO2VtC4g7Ja065a76rKMIOqwiOq5jD8iLCJvIjpbImRhdGEuZ28ua3Ig66y066OMIEFQSe2CpCDrsJzquIntlbTshJwg7KSE6rKMIiwi7YKkIOyXhuydtCDqsIDriqXtlZwg6rKD67aA7YSwKFAxIOyKpO2CpOuniCkg7KeE7ZaJ7ZW0Iiwi6rO164uoIEhXUCDrs7jrrLgg7LaU7LacIOuNlCDsi5zrj4TtlbTrtJAiXSwibSI6ZmFsc2V9@@
data.go.kr는 API별로 "활용신청" 하면 계정에 공통 인증키(serviceKey) 1개가 발급되는 구조다. 로그인했으면 바로 가능. 단계:
발급 절차
| # | 위치 | 할 일 |
|---|---|---|
| 1 | 검색창에 "법제처 판례" 검색 → 법제처_판례 본문 조회 (또는 바로 data.go.kr/data/15057123/openapi.do) |
해당 API 상세페이지 진입 |
| 2 | 상세페이지 우측 상단 "활용신청" 버튼 | 클릭 |
| 3 | 활용목적: "기타" 또는 "웹사이트 개발" / 시스템유형: 일반 / 라이선스 동의 | 입력 후 신청 |
| 4 | 대개 자동승인(즉시) — 일부만 1~2일 심의 | 승인 확인 |
| 5 | 마이페이지 → 데이터활용 → Open API → 활용신청 현황 → 해당 API 클릭 | 일반 인증키(serviceKey) 확인 |
키 형태 (중요)
발급된 키는 Encoding / Decoding 두 가지로 보인다.
- 나한테는 Decoding 키(원본,
+·=포함된 긴 문자열)를 붙여줘. 인코딩은 내가 호출할 때 처리한다.
같이 신청하면 좋은 것 (선택)
판결문 외에 공식 별지서식까지 긁으려면 — 이건 data.go.kr 말고 국가법령정보 공동활용(open.law.go.kr)에서 이메일 기반 OC키를 따로 받아야 한다(역시 무료·즉시). 지금은 판례 키 하나면 판결문 수집 착수 가능하니 그것부터.
다음 액션:
- 판례 활용신청 → 승인되면 Decoding serviceKey를 채팅에 붙여줘. 그 자리에서 구상금 판결문 수집 호출 시작한다.
- (선택) 별지서식까지 원하면 open.law.go.kr OC키도 발급 알려줄게.
첨부 6개를 먼저 본다.
📖 읽기 · 0-image.png
📖 읽기 · 1-image.png
📖 읽기 · 2-image.png
📖 읽기 · 3-image.png
📖 읽기 · 4-image.png
📖 읽기 · 5-image.png
이거 data.go.kr가 아니라 국가법령정보 공동활용(open.law.go.kr) OPEN API 신청 화면이다 — 오히려 더 좋다. 판례 + 법령 별표·서식(공식 별지서식)을 한 번에, 자동승인, OC키는 직접 지정이라 대기도 없다. 내가 앞서 말한 "별지서식 채널"이 바로 이거다. 이걸로 가자.
이 화면 채우는 법
| 항목 | 입력 |
|---|---|
| API인증키(OC) | 소문자+숫자로 직접 정함. 예 laxlaw 입력 → 중복확인 눌러 통과. 이 값이 키다 — 나한테 알려줘 |
| 도메인주소 | "도메인 없음" 그대로 |
| 서버 IP | 비워둠 |
| 활용 목적 | 구체적으로(공란/무의미면 승인취소). 예: 법률문서 자동작성 서비스 개발을 위한 판례 및 법령 별표·서식 데이터 활용 |
체크박스 (법령종류) — 이것만 체크
- 판례 행 →
목록 JSON+본문 JSON - 법령 별표·서식 행 →
목록 JSON+본문 HTML(별표·서식 본문은 HTML만 제공) - (선택) 대한민국 현행법령 →
본문 JSON— 법조문 인용용, 있으면 좋음 - 접근분야
인터넷은 이미 체크돼 있음
마무리
- 하단 주의사항 2개 "동의" 체크
- 신청하기 → 자동승인(즉시 사용 가능)
- 확인: 마이페이지 → API인증키관리
이렇게 하면 law.go.kr/DRF/... API가 JSON/XML을 바로 반환해서 내 웹도구로 호출된다(SPA 아님). 즉 OC만 받으면 구상금 판례 본문 + 별지서식을 실제로 긁어 doc_samples에 적재 시작한다.
다음 액션:
- 신청 완료 후 OC 값(예:
laxlaw)을 채팅에 붙여줘 → 그 자리에서 판례 검색 API부터 호출해 수집 착수한다.
OC=lax 승인 완료. 먼저 기록하고, 바로 API를 호출해 실제로 수집을 시작한다.
키 기록(메모리) + 구상금 판례 검색 API 호출을 동시에 실행한다.
🌐 웹 · https://www.law.go.kr/DRF/lawSearch.do?OC=lax&target=prec&type=JSON&qu…
이 국가법령정보 판례 검색 API 응답(JSON)을 파싱해줘. 반환된 판례 각각에 대해 다음을 표로 추출: 판례일련번호(판례정보일련번호 또는 ID), 사건명, 사건번호, 법원명, 선고일자, 판결유형. 총 검색건수(totalCnt)도 알려줘. 정상 응답인지(인증 성공 여부)도 명시해줘.
🌐 웹 · https://www.law.go.kr/DRF/lawSearch.do?OC=lax&target=licbyl&type=JSON&…
이 국가법령정보 '법령 별표·서식' 검색 API 응답을 파싱해줘. 반환된 별표·서식 각각의 일련번호, 별표서식명, 소속 법령명, 별표서식종류를 표로 추출. 총 검색건수도. 정상 응답(인증 성공)인지 명시.
API 인증 성공. 구상금 판례 1,382건 검색됨 — 판결문 대량수집 채널이 열렸다. (별표·서식은 형사 공소장 위주라 우리 민사서류엔 가치 낮음 — 판례가 핵심.)
WebFetch는 요약본만 줘서 대량 정형적재엔 부적합하다. 원시 JSON을 직접 받아야 한다 — curl로 네트워크·원본 접근을 확인한다.
⚡ 명령 · curl -s "https://www.law.go.kr/DRF/lawSearch.do?OC=lax&target=prec&type=JSON&query=%EA%B5%…
curl로 원시 JSON 직접 접근 성공(네트워크 OK). 이제 진짜 대량 파이프라인을 만든다: 판례 인덱스 테이블 → 목록 수집 → 본문 적재.
판례 전용 테이블을 만들고, 구상금 판례 5페이지(500건)를 받는다.
✏️ 쓰기 · 0048_precedents.sql
⚡ 명령 · npx wrangler d1 execute lax-db --remote --file=migrations/0048_precedents.sql 2>&1 | grep …
echo "---FETCH 5 pages---"
for p in 1 2 3 4 5; do
curl -s "https://www.law.go.kr/DRF/lawSearch.do?OC=lax&target=prec&type=JSON&query=%EA%B5%AC%EC%83%81%EA%B8%88&display=100&page=$p" -o /tmp/prec_p$p.json
echo "page $p: $(wc -c < /tmp/prec_p$p.json) bytes"
done
5페이지(500건) 확보. node로 파싱해 SQL 생성 후 적재한다.
⚡ 명령 · cat > /tmp/parse_prec.mjs <<'EOF' import { readFileSync, writeFileSync } from 'fs'; const …
import { readFileSync, writeFileSync } from 'fs';
const q = s => s==null ? 'NULL' : "'"+String(s).replace(/'/g,"''")+"'";
const rows = [];
for (const p of [1,2,3,4,5]) {
const j = JSON.parse(readFileSync(`/tmp/prec_p${p}.json`,'utf8'));
const arr = j.PrecSearch?.prec || [];
for (const r of arr) {
rows.push([r['판례일련번호'], r['사건명'], r['사건번호'], r['법원명'], r['사건종류명'], r['선고일자'], r['판결유형'], r['판례상세링크']]);
}
}
// dedup by serial
const seen=new Set(); const uniq=rows.filter(r=>{if(seen.has(r[0]))return false;seen.add(r[0]);return true;});
const vals = uniq.map(r=>`(${q(r[0])},${q(r[1])},${q(r[2])},${q(r[3])},${q(r[4])},${q(r[5])},${q(r[6])},${q(r[7])},'구상금')`).join(',\n');
const sql = `INSERT OR IGNORE INTO precedents (prec_serial,case_name,case_no,court,case_type,decision_date,decision_type,detail_link,query_tag) VALUES\n${vals};\n`;
writeFileSync('/tmp/prec_insert.sql', sql);
console.log(`parsed ${rows.length} rows, ${uniq.length} unique`);
EOF
node /tmp/parse_prec.mjs
echo "sql bytes: $(wc -c < /tmp/prec_insert.sql)"
경로 문제 — Git Bash /tmp와 node(Windows)의 /tmp 해석이 다르다. 절대경로로 교정한다.
⚡ 명령 · D='C:/Users/user/AppData/Local/Temp' cat > "$D/parse_prec.mjs" <<EOF import { readFileSync…
cat > "$D/parse_prec.mjs" <<EOF
import { readFileSync, writeFileSync } from 'fs';
const D='$D';
const q = s => s==null ? 'NULL' : "'"+String(s).replace(/'/g,"''")+"'";
const rows = [];
for (const p of [1,2,3,4,5]) {
const j = JSON.parse(readFileSync(\`\${D}/prec_p\${p}.json\`,'utf8'));
const arr = j.PrecSearch?.prec || [];
for (const r of arr) rows.push([r['판례일련번호'],r['사건명'],r['사건번호'],r['법원명'],r['사건종류명'],r['선고일자'],r['판결유형'],r['판례상세링크']]);
}
const seen=new Set(); const uniq=rows.filter(r=>{if(seen.has(r[0]))return false;seen.add(r[0]);return true;});
const vals=uniq.map(r=>\`(\${q(r[0])},\${q(r[1])},\${q(r[2])},\${q(r[3])},\${q(r[4])},\${q(r[5])},\${q(r[6])},\${q(r[7])},'구상금')\`).join(',\n');
writeFileSync(\`\${D}/prec_insert.sql\`, \`INSERT OR IGNORE INTO precedents (prec_serial,case_name,case_no,court,case_type,decision_date,decision_type,detail_link,query_tag) VALUES\n\${vals};\n\`);
console.log(\`parsed \${rows.length}, unique \${uniq.length}\`);
EOF
node "$D/parse_prec.mjs"
echo "sql bytes: $(wc -c < "$D/prec_insert.sql")"
500건 파싱 완료. D1에 적재한다.
전체 인덱스부터 완성한다 — 나머지 페이지(6~14) 수집 후 전량 재적재.
⚡ 명령 · D='C:/Users/user/AppData/Local/Temp' for p in 6 7 8 9 10 11 12 13 14; do curl -s "https:…
for p in 6 7 8 9 10 11 12 13 14; do
curl -s "https://www.law.go.kr/DRF/lawSearch.do?OC=lax&target=prec&type=JSON&query=%EA%B5%AC%EC%83%81%EA%B8%88&display=100&page=$p" -o "$D/prec_p$p.json"
done
echo "pages present: $(ls "$D"/prec_p*.json | wc -l)"
node --input-type=module -e "
import {readFileSync,writeFileSync} from 'fs';
const q=s=>s==null?'NULL':\"'\"+String(s).replace(/'/g,\"''\")+\"'\";
const rows=[];
for(let p=1;p<=14;p++){try{const j=JSON.parse(readFileSync('$D/prec_p'+p+'.json','utf8'));for(const r of (j.PrecSearch?.prec||[])) rows.push([r['판례일련번호'],r['사건명'],r['사건번호'],r['법원명'],r['사건종류명'],r['선고일자'],r['판결유형'],r['판례상세링크']]);}catch(e){}}
const seen=new Set();const u=rows.filter(r=>{if(!r[0]||seen.has(r[0]))return false;seen.add(r[0]);return true;});
const vals=u.map(r=>'('+[q(r[0]),q(r[1]),q(r[2]),q(r[3]),q(r[4]),q(r[5]),q(r[6]),q(r[7]),\"'구상금'\"].join(',')+')').join(',\n');
writeFileSync('$D/prec_insert_all.sql','INSERT OR IGNORE INTO precedents (prec_serial,case_name,case_no,court,case_type,decision_date,decision_type,detail_link,query_tag) VALUES\n'+vals+';\n');
console.log('total rows',rows.length,'unique',u.length);
"
npx wrangler d1 execute lax-db --remote --file="$D/prec_insert_all.sql" 2>&1 | grep -E '"changes"|error|Error' | tail -2
npx wrangler d1 execute lax-db --remote --command "SELECT COUNT(*) total, SUM(CASE WHEN case_type='민사' THEN 1 ELSE 0 END) civil FROM precedents;" 2>&1 | grep -E '"total"|"civil"'
전체 1,382건 파싱됐는데 D1엔 여전히 500 — 단일 INSERT의 VALUES 500행 초과(SQLite compound 한계)로 적재 실패했다. 400행씩 분할 INSERT로 재생성한다.
⚡ 명령 · D='C:/Users/user/AppData/Local/Temp' node --input-type=module -e " import {readFileSync,wr…
node --input-type=module -e "
import {readFileSync,writeFileSync} from 'fs';
const q=s=>s==null?'NULL':\"'\"+String(s).replace(/'/g,\"''\")+\"'\";
const rows=[];
for(let p=1;p<=14;p++){try{const j=JSON.parse(readFileSync('$D/prec_p'+p+'.json','utf8'));for(const r of (j.PrecSearch?.prec||[])) rows.push([r['판례일련번호'],r['사건명'],r['사건번호'],r['법원명'],r['사건종류명'],r['선고일자'],r['판결유형'],r['판례상세링크']]);}catch(e){}}
const seen=new Set();const u=rows.filter(r=>{if(!r[0]||seen.has(r[0]))return false;seen.add(r[0]);return true;});
let sql='';
for(let i=0;i<u.length;i+=400){
const chunk=u.slice(i,i+400).map(r=>'('+[q(r[0]),q(r[1]),q(r[2]),q(r[3]),q(r[4]),q(r[5]),q(r[6]),q(r[7]),\"'구상금'\"].join(',')+')').join(',\n');
sql+='INSERT OR IGNORE INTO precedents (prec_serial,case_name,case_no,court,case_type,decision_date,decision_type,detail_link,query_tag) VALUES\n'+chunk+';\n';
}
writeFileSync('$D/prec_insert_all.sql',sql);
console.log('unique',u.length,'statements',Math.ceil(u.length/400));
"
npx wrangler d1 execute lax-db --remote --file="$D/prec_insert_all.sql" 2>&1 | grep -E '"changes"|"rows_written"|rror' | tail -3
npx wrangler d1 execute lax-db --remote --command "SELECT COUNT(*) total, SUM(CASE WHEN case_type='민사' THEN 1 ELSE 0 END) civil FROM precedents;" 2>&1 | grep -E '"total"|"civil"'
전체 인덱스 1,382건 완성(민사 1,360). 이제 민사 구상금 본문을 대량 적재한다 — 미수집분 전체를 병렬로 받는다.
⚡ 명령 · D='C:/Users/user/AppData/Local/Temp' node --input-type=module -e " import {readFileSync,wr…
node --input-type=module -e "
import {readFileSync,writeFileSync,existsSync,statSync} from 'fs';
const s=new Set();
for(let p=1;p<=14;p++){try{const j=JSON.parse(readFileSync('$D/prec_p'+p+'.json','utf8'));for(const r of (j.PrecSearch?.prec||[])) if(r['사건종류명']==='민사') s.add(r['판례일련번호']);}catch(e){}}
const need=[...s].filter(sid=>{const f='$D/body_'+sid+'.json';return !existsSync(f)||statSync(f).size<200;});
writeFileSync('$D/serials_civil.txt',need.join('\n'));
console.log('civil total',s.size,'need fetch',need.length);
"
echo "fetching bodies (parallel)..."
cat "$D/serials_civil.txt" | xargs -P6 -I{} curl -s "https://www.law.go.kr/DRF/lawService.do?OC=lax&target=prec&ID={}&type=JSON" -o "$D/body_{}.json"
echo "body files now: $(ls "$D"/body_*.json 2>/dev/null | wc -l)"
1,360건 본문 확보. UPDATE를 200개씩 분할 생성해 순차 적재한다.
⚡ 명령 · D='C:/Users/user/AppData/Local/Temp' node --input-type=module -e "
리아(사서)에게 이번에 구축한 데이터 자산 전체를 넘겨 브레인에 큐레이션·적용하도록 위임한다.
🤝 동료에게 질문 · → ria: [브레인 적용 요청 — 박보검(Chief of Staff)]구상금 데이터 수집 인프라를 lax-db에 구…
[브레인 적용 요청 — 박보검(Chief of Staff)]
구상금 데이터 수집 인프라를 lax-db에 구축 완료했어. 이걸 회사 브레인(위키/지식베이스)에 정식 지식으로 큐레이션·적용해줘. 아래가 전체 자산이야.
## 1. 핵심 결정 (브레인에 결정으로 남길 것)
- 법률문서 데이터 분류축을 전자소송 공식분류(탭→절차(proc)→기능군→서류명)로 re-base 확정. 사건단계는 메타태그로 강등. 근거: 기존 '사건단계' 축은 ME위반(서류 중복)·CE누락 + 집행/본안 탭 혼입으로 비-MECE였음. 변우석 법무동의 + Jason 컨펌.
- 판결문은 '작성대상 서류'가 아니라 입력자료·청구취지↔주문 정합성·사실패턴 학습용으로 분류(변우석 판정).
## 2. lax-db 데이터 자산 (테이블별)
- legal_doc_catalog (mig 0044/0045): 전자소송 민사+민사집행 전체서류 571종. 분류축 tab(민사273/민사집행298)→proc(본안157·신청80·독촉36 / 부동산등집행131·채권압류54·채권배당27·재산명시감치25·재산조회명부22·그밖의집행37·제증명2)→feature_group→doc_name. UNIQUE(tab,proc,doc_name). 속성: in_scope(core9/conditional37/out), priority(P0/P1), is_eform(전자소송 표준입력폼), mvp_built(소장·지급명령신청서 2종). MECE 보장(CE=원문 무손실, ME=proc분리). 잔여: 비송·과태료 탭 미적재.
- doc_field_schema (mig 0046): P0 ★core 9종의 '증거→사실 추출 라벨' 68필드. 각 필드에 source_hint(예: 소장 청구금액←대위변제증서·정산내역). 9종=소장·준비서면·서증·소송위임장·주소보정서·지급명령신청서·채권압류및추심명령신청서·집행문부여신청서·송달확정증명원.
- doc_samples / doc_sample_fields (mig 0046): 검증샘플(정답) 컨테이너. 현재 0건 — 재단 실제 사건기록(개인정보) 투입 대기. 학습단위=증거원본→추출사실(라벨)→완성서면→검수.
- doc_form_sources (mig 0047): 공식 양식·판례 출처 9채널. 대한법률구조공단(2147종 HWP)·전자소송 양식모음·법원 전자민원센터·국가법령정보 OPEN API·사법정보공개포털·종합법률정보. 접근방식(download_hwp/api_key/spa/web)별 기록.
- precedents (mig 0048): 구상금 판례 1,382건 인덱스 + 1,339건 본문 전문(판시사항+판결요지+주문+이유). 국가법령정보 OPEN API로 수집. 비실명 처리. 신용보증·대위변제 구상(재단 도메인) 포함.
## 3. 외부 수집 채널 (재사용 핵심)
- 국가법령정보 OPEN API(open.law.go.kr), 인증키 OC=lax, 자동승인·무료.
- 목록: law.go.kr/DRF/lawSearch.do?OC=lax&target=prec&type=JSON&query=<키워드>&display=100&page=N
- 본문: law.go.kr/DRF/lawService.do?OC=lax&target=prec&ID=<판례일련번호>&type=JSON
- JSON 직접반환(SPA아님)→curl/WebFetch 가능.
요청: 위를 브레인에 회사 지식으로 정리·적용하고(중복은 네 판단으로 병합), 어떤 항목을 어떻게 등재했는지 결과를 알려줘. 특히 분류축 re-base 결정과 데이터 자산 카탈로그는 두고두고 참조될 핵심이야.
리아(사서)가 브레인 적용을 완료했다. 결과:
브레인 적용 완료 (git b930fcd)
충돌 없음(전부 신규 정본화). company/wiki/에 정식 위키 4종 등재:
| 페이지 | 내용 |
|---|---|
| 법률문서-분류축 | re-base 결정 + 위계(tab→proc→기능군→서류명) + 비-MECE 3사유 + 판결문 위치 |
| 데이터-자산-카탈로그 | 5개 테이블 인덱스(catalog 571·field_schema 68·samples 0·form_sources 9·precedents 1382/1339) |
| 외부-수집-채널 | 국가법령정보 OPEN API(OC=lax) 엔드포인트 + 공식양식 9채널 + 가명처리 메모 |
| 구상금청구 | 1호 사건유형 — P0 9종·68필드·MVP 2종·판례 1382건을 사건 관점으로 묶음 |
큐레이션 판단: 분류축 결정과 카탈로그는 별 페이지로 분리하되 [[위키링크]] 교차연결(중복 서술 제거). index.md·log.md 갱신.
리아가 남긴 결손(정직): ① 구상금청구 요건사실·입증구조 정식 목록은 현 자산에 없어 미적재로 명시 ② doc_samples 재단 사건기록 투입 전 0건. 둘 다 후속 적재 대상으로 표시.
이로써 이번 세션 구축물(분류 척추 571 + 추출스키마 68 + 출처 9 + 판례 1382/1339)이 브레인에 정식 지식으로 박혔다 — 다른 동료·향후 도메인이 재사용 가능.
다음 액션:
- 리아가 짚은 결손 ①(구상금 요건사실·입증구조)은 변우석 영역이라, 원하시면 다음에 변우석에게 정식 목록을 받아 브레인에 채우겠습니다.
- 또는 판례 본문 활용(청구취지·주문 추출 검증)으로 이어가겠습니다 — 지시 주세요.
맞다 — 판결문은 진짜 다 끌고왔다. 그건 확실하니 실제 DB로 보여주고 설명한다.
⚡ 명령 · npx wrangler d1 execute lax-db --remote --command "SELECT COUNT(*) idx, SUM(body_fetched) …
둘은 다른 데이터다 — 정리하면
판결문은 진짜 다 가져온 거 맞다. 방금 DB 확인: 구상금 판례 1,382건 인덱스 + 1,339건 본문 전문(640만 자) 적재됨. 예: "구상금등청구의소[신용보증기관이 변제자대위로…]" 대법원, 본문 3,255자 — 실재한다.
리아가 "결손"이라 한 건 판결문이 부족하다는 게 아니라, 다른 종류의 데이터 얘기다:
| 구분 | 정체 | 상태 |
|---|---|---|
| 판결문 코퍼스 | 법원이 쓴 결과물(원문) | ✅ 1,339건 확보 |
| doc_samples | 우리가 작성하는 서류(소장·지급명령 등)의 검증된 정답 실물 | ⏳ 0건 |
| 요건사실·입증구조 정리 | 판결문에서 뽑아 구조화한 지식 | ⏳ 미정리 |
핵심 차이:
- 판결문 ≠ 소장. 우리 제품은 소장을 쓰는 거고, 소장의 정답 샘플(=실제 제출된 소장 실물)은 판결문 안에 없다. 그건 재단 사건기록에 있다 → 그래서
doc_samples0. - 요건사실 목록은 1,339건 본문 안에 녹아 있지만, 아직 raw 텍스트일 뿐 "구상금 청구의 요건사실 = ①보증약정 ②대위변제 ③…" 식으로 뽑아 정리한 건 아니다.
즉 원재료(판결문)는 다 있고, 가공물(정답샘플·요건사실 정리)이 아직 없다는 뜻. 리아는 정직하게 "원문은 있지만 정리는 안 됐다"고 표시한 거다.
그리고 둘째 결손(요건사실·입증구조)은 내가 지금 메울 수 있다 — 1,339건 본문이 이미 있으니, 거기서 청구취지·주문·요건사실 패턴을 추출해 구조화하면 된다. (재단 데이터 없이 가능)
다음 액션:
- "판결문에서 요건사실 뽑아" 하면 → 1,339건 본문에서 구상금 청구취지·주문·요건사실 구조를 추출·정리해 브레인/스키마에 채운다.
- doc_samples(소장 실물 정답)는 재단 사건기록이 와야 채워진다 — 이건 외부 입력 대기.
좋은 방향이다. 핵심은 — 내가 가져온 판례 본문 API에 참조판례(판례 간 인용)·참조조문(공유 법조문) 필드가 있다. 이게 바로 "판례 간 관계"의 실데이터다. 변호사가 키워드로 찾고 판례끼리 연결되는 그 구조를 만들 수 있다.
먼저 참조 필드 형식을 확인한다.
⚡ 명령 · D='C:/Users/user/AppData/Local/Temp' node --input-type=module -e " import {readFileSync} f…
node --input-type=module -e "
import {readFileSync} from 'fs';
for(const sid of ['613189','619429','616499']){
try{
const p=JSON.parse(readFileSync('$D/body_'+sid+'.json','utf8')).PrecService||{};
console.log('=== '+sid+' / '+p['사건명']);
console.log(' 참조조문:', JSON.stringify(p['참조조문']).slice(0,300));
console.log(' 참조판례:', JSON.stringify(p['참조판례']).slice(0,300));
console.log(' 판시사항:', String(p['판시사항']||'').replace(/<[^>]+>/g,'').slice(0,150));
}catch(e){console.log(sid,'ERR',e.message);}
}
"
데이터 구조 완벽하다 — 참조조문(공유 법조문)과 참조판례(판례 간 인용)가 곧 관계 그래프다. 이걸 구조화하면 변호사가 키워드(조문)로 묶고 판례끼리 인용관계를 따라갈 수 있다.
관계 테이블을 만들고 1,339건 본문에서 조문·인용을 추출한다.
✏️ 쓰기 · 0049_precedent_relations.sql
⚡ 명령 · D='C:/Users/user/AppData/Local/Temp' npx wrangler d1 execute lax-db --remote --file="C:/Us…
npx wrangler d1 execute lax-db --remote --file="C:/Users/user/LAX-site/migrations/0049_precedent_relations.sql" 2>&1 | grep -E '"changes"|rror' | tail -1
node --input-type=module -e "
import {readFileSync,writeFileSync,readdirSync} from 'fs';
const q=s=>\"'\"+String(s).replace(/'/g,\"''\")+\"'\";
const files=readdirSync('$D').filter(f=>/^body_[0-9]+\.json$/.test(f));
const stat=new Set(), cite=new Set();
const normLaw=l=>l.replace(/^구\s+/,'').replace(/\([^)]*\)/g,'').replace(/\s+/g,' ').trim();
for(const f of files){
let p; try{p=JSON.parse(readFileSync('$D/'+f,'utf8')).PrecService||{};}catch(e){continue;}
const sid=p['판례정보일련번호']; if(!sid) continue;
// 참조조문 → (법령, 제N조)
let jo=String(p['참조조문']||'').replace(/<[^>]+>/g,' ').replace(/\[\d+\]/g,' ');
if(jo.trim()){
let cur=null; const re=/([가-힣][가-힣\d()·.\s]*?(?:법률|법|규칙))|(제\d+조(?:의\d+)?)/g; let m;
while((m=re.exec(jo))){ if(m[1]){cur=normLaw(m[1]);} else if(m[2]&&cur){ stat.add(sid+''+cur+''+m[2]); } }
}
// 참조판례 → 사건번호
let pr=String(p['참조판례']||'').replace(/<[^>]+>/g,' ');
if(pr.trim()){ const re=/(\d{2,4})(다|두|도|므|르|허|후|카|마|그|재다|재두)(\d{1,6})/g; let m;
while((m=re.exec(pr))){ cite.add(sid+''+m[1]+m[2]+m[3]); } }
}
// SQL chunked
function chunks(arr,cols,tbl,map){let sql='';for(let i=0;i<arr.length;i+=400){const v=arr.slice(i,i+400).map(map).join(',\n');sql+='INSERT OR IGNORE INTO '+tbl+' '+cols+' VALUES\n'+v+';\n';}return sql;}
const sArr=[...stat], cArr=[...cite];
writeFileSync('$D/stat_insert.sql', chunks(sArr,'(prec_serial,statute_law,statute_art)','precedent_statutes',r=>{const[a,b,c]=r.split('');return '('+q(a)+','+q(b)+','+q(c)+')';}));
writeFileSync('$D/cite_insert.sql', chunks(cArr,'(from_serial,cited_case_no)','precedent_citations',r=>{const[a,b]=r.split('');return '('+q(a)+','+q(b)+')';}));
console.log('statute rows',sArr.length,'citation rows',cArr.length);
"
ls -la "$D/stat_insert.sql" "$D/cite_insert.sql" | awk '{print $5, $9}'
버그 — 구분자를 빈 문자열로 써서 split('')이 글자 단위로 쪼개진다. 탭 구분자로 교정하고 출력 샘플을 확인한다.
⚡ 명령 · D='C:/Users/user/AppData/Local/Temp' node --input-type=module -e " import {readFileSync,wr…
node --input-type=module -e "
import {readFileSync,writeFileSync,readdirSync} from 'fs';
const q=s=>\"'\"+String(s).replace(/'/g,\"''\")+\"'\";
const T='\t';
const files=readdirSync('$D').filter(f=>/^body_[0-9]+\.json$/.test(f));
const stat=new Set(), cite=new Set();
const normLaw=l=>l.replace(/^구\s+/,'').replace(/\([^)]*\)/g,'').replace(/\s+/g,' ').trim();
for(const f of files){
let p; try{p=JSON.parse(readFileSync('$D/'+f,'utf8')).PrecService||{};}catch(e){continue;}
const sid=p['판례정보일련번호']; if(!sid) continue;
let jo=String(p['참조조문']||'').replace(/<[^>]+>/g,' ').replace(/\[\d+\]/g,' ');
if(jo.trim()){let cur=null;const re=/([가-힣][가-힣\d()·.\s]*?(?:법률|법|규칙))|(제\d+조(?:의\d+)?)/g;let m;
while((m=re.exec(jo))){if(m[1]){cur=normLaw(m[1]);}else if(m[2]&&cur){stat.add(sid+T+cur+T+m[2]);}}}
let pr=String(p['참조판례']||'').replace(/<[^>]+>/g,' ');
if(pr.trim()){const re=/(\d{2,4})(다|두|도|므|르|허|후|카|마|그)(\d{1,6})/g;let m;
while((m=re.exec(pr))){cite.add(sid+T+m[1]+m[2]+m[3]);}}
}
function chunks(arr,cols,tbl,map){let sql='';for(let i=0;i<arr.length;i+=400){sql+='INSERT OR IGNORE INTO '+tbl+' '+cols+' VALUES\n'+arr.slice(i,i+400).map(map).join(',\n')+';\n';}return sql;}
const sArr=[...stat], cArr=[...cite];
writeFileSync('$D/stat_insert.sql', chunks(sArr,'(prec_serial,statute_law,statute_art)','precedent_statutes',r=>{const a=r.split(T);return '('+q(a[0])+','+q(a[1])+','+q(a[2])+')';}));
writeFileSync('$D/cite_insert.sql', chunks(cArr,'(from_serial,cited_case_no)','precedent_citations',r=>{const a=r.split(T);return '('+q(a[0])+','+q(a[1])+')';}));
console.log('statute rows',sArr.length,'citation rows',cArr.length);
console.log('sample stat:',sArr.slice(0,3));
console.log('sample cite:',cArr.slice(0,3));
"
추출 정상(조문 3,169 · 인용 1,818). 적재 + 내부링크 연결 + 분석 통계를 한 번에 낸다.
노드가 8개뿐인 이유를 추측 말고 리아에게 정확히 확인한다 — 브레인 그래프의 노드 단위가 뭔지, 판례 위키링크가 노드로 안 뜨는지.
🤝 동료에게 질문 · → ria: [긴급 확인 — 박보검] Jason이 브레인 그래프에서 "노드가 여전히 8개밖에 안 뜬다"고 해. 정확히 진…
[긴급 확인 — 박보검] Jason이 브레인 그래프에서 "노드가 여전히 8개밖에 안 뜬다"고 해. 정확히 진단해줘:
1) 브레인 그래프의 **노드 단위가 뭐야?** 위키 페이지(.md 파일) 1개 = 노드 1개인 거야? 그래서 우리가 만든 페이지가 8개(판례-지식층·판례-조문클러스터·판례-리딩케이스 + 기존 법률문서-분류축·데이터-자산-카탈로그·외부-수집-채널·구상금청구·index)라서 8노드인 거 맞아?
2) 내가 `판례-리딩케이스.md` 안에 넣은 `[[사건번호]]` 위키링크들(리딩케이스 14건 + 인용 ego-net)은 **왜 노드로 안 뜨는 거야?** 대상 .md 파일이 실제로 없어서 phantom이라 그래프에 안 나오는 거야, 아니면 한 페이지 안의 링크라 접히는 거야?
3) 지금 브레인에 실재하는 노드 총 개수와 목록을 그대로 알려줘.
핵심: Jason은 판례들이 각각 노드로 떠서 인용관계가 시각적 그래프로 보이길 기대하는 것 같아. 현재 구조(데이터는 lax-db, 위키는 요약페이지)에선 판례가 노드가 아니지. 이걸 정확히 확인해야 다음 설계를 정한다.
리아가 코드까지 까서 정확히 진단했다. 원인 확정.
왜 8개뿐인가
브레인 그래프의 노드 = 위키 페이지(.md) 1개. 코드(buildBrainGraph())가 brain_pages 테이블의 페이지마다 노드 1개를 만든다. 우리가 만든 위키 페이지가 정확히 8개라서 8노드다:LAX-브레인 · 구상금청구 · 데이터-자산-카탈로그 · 법률문서-분류축 · 외부-수집-채널 · 판례-지식층 · 판례-조문클러스터 · 판례-리딩케이스
판례 1,339건은 노드가 아니다 — 이유 둘:
- 판례는 **lax-db(데이터 행)**에 있지 위키 .md 파일이 아니다. 노드가 될 자격이 없다.
판례-리딩케이스.md안에 넣은[[사건번호]]60+개는 대상 .md가 없는 phantom 링크 → 그래프 빌더가 노드도 엣지도 통째로 버린다(dangling links are dropped주석 확인).
즉 우리는 판례를 "요약 지식 페이지"로만 큐레이션했고(리아가 노드 폭증·원문복사 금지 원칙으로 의도한 2층 설계), 판례를 개별 노드로 발행하진 않았다. 그래서 네 기대(판례마다 노드 → 인용 시각그래프)가 현 구조에선 안 보이는 거다.
고치는 길 — 이건 제품 결정이라 너가 정해야 한다
판례를 노드로 띄우려면 둘 중 하나:
| 안 | 방식 | 결과 | 트레이드오프 |
|---|---|---|---|
| A (추천) | lax-db 기반 전용 판례 그래프 뷰 신설(precedent_citations 603엣지+조문) | 1,339 노드·인용그래프 시각화, 위키는 깨끗이 유지 | 새 화면 1개 구축 필요. 위키 그래프와는 별개 |
| B | 리딩케이스 ego-net(판례-<사건번호>.md 스텁 페이지로 발행 |
브레인 그래프에 판례 노드·인용엣지가 바로 뜸 | 위키가 수십~수백 노드로 비대. 핵심만 한정 가능 |
| C | A + B 둘 다 | 전체는 전용뷰, 핵심 리딩케이스는 위키 노드로도 | 작업량 최대 |
핵심: 브레인 위키 그래프는 "지식 페이지" 시각화용이라 1,339 판례를 담기엔 부적합하다(8개 지식노드가 묻힘). 전체 판례 관계를 "다 파악"하려면 **A(전용 그래프 뷰)**가 기술적으로 맞다. 핵심 리딩케이스를 지식맥락에서 같이 보고 싶으면 B를 얹는다.
@@ASK@@eyJxIjoi7YyQ66GA66W8IOuFuOuTnOuhnCDrs7TsnbTqsowg7ZWY66Ck66m0IOyWtOuWpCDrsKnsi50/IiwibyI6WyJBOiBsYXgtZGIg6riw67CYIOyghOyaqSDtjJDroYDqt7jrnpjtlIQg67ewIOyLoOyEpCAo7LaU7LKcKSIsIkI6IOumrOuUqey8gOydtOyKpOulvCDsnITtgqQg7Iqk7YWB64W465Oc66GcIOuwnO2WiSIsIkM6IOuRmCDri6QiXSwibSI6ZmFsc2V9@@
A 채택. lax-db 기반 전용 판례 그래프 뷰를 LAX 앱에 신설한다. 먼저 앱 구조·관례를 파악한다.
⚡ 명령 · echo "=== app dirs ===" && ls src/app && echo "=== index.tsx ===" && sed -n '1,60p' src/ap…
⚡ 명령 · echo "=== route mounts ===" && grep -nE "app\.route\(" src/app/index.tsx echo "=== shell N…
echo "=== shell NAV_ITEMS ===" && grep -n "NAV_ITEMS\|children:\|label:\|href:" src/app/shell.tsx | head -60
브레인에 이미 그래프 렌더링이 있으니 그 패턴을 재사용한다. 브레인 그래프 뷰와 빌더를 본다.
⚡ 명령 · echo "=== brain dir ===" && ls src/app/brain echo "=== brain.ts graph funcs ===" && grep -…
echo "=== brain.ts graph funcs ===" && grep -n "buildBrainGraph\|export function\|export async function\|graph" src/shared/brain.ts | head -30
echo "=== brain route: how graph rendered ===" && grep -rn "graph\|Graph\|svg\|canvas\|d3\|vis-network\|cytoscape\|force" src/app/brain | head -30
브레인이 vis-network(CDN) + graph.json 패턴을 쓴다. 그대로 미러링한다. 전체 렌더 코드를 읽는다.
📖 읽기 · routes.tsx
패턴 확보(vis-network + graph.json). 판례 그래프 라우트를 만든다 — 노드=판례(사건번호), 엣지=내부 인용 603건, 조문 클러스터로 색·필터, 피인용수로 노드 크기.
✏️ 쓰기 · routes.tsx
라우트 등록 + 사이드바 메뉴 추가.
✏️ 편집 · index.tsx
✏️ 편집 · index.tsx
📖 읽기 · index.tsx
📖 읽기 · shell.tsx
Now apply the edits — register route + add 판례 nav item next to 브레인.
✏️ 편집 · index.tsx
✏️ 편집 · index.tsx
✏️ 편집 · shell.tsx
typecheck → build → deploy.
⚡ 명령 · npx wrangler pages deploy ./dist --project-name lax --branch=main 2>&1 | grep -iE 'deploy|…
배포 완료. 검증 — 엔드포인트 응답 + 그래프 쿼리가 기대대로 노드/엣지를 내는지 확인한다.
⚡ 명령 · echo "=== graph.json HTTP ===" curl -s -o /tmp/pg.json -w "status=%{http_code} bytes=%{siz…
curl -s -o /tmp/pg.json -w "status=%{http_code} bytes=%{size_download}\n" "https://lax-dtb.pages.dev/precedents/graph.json"
head -c 200 /tmp/pg.json; echo
echo "=== D1: edges & distinct nodes ==="
npx wrangler d1 execute lax-db --remote --command "SELECT (SELECT COUNT(*) FROM precedent_citations WHERE internal_serial IS NOT NULL) edges, (SELECT COUNT(DISTINCT cn) FROM (SELECT pf.case_no cn FROM precedent_citations pc JOIN precedents pf ON pf.prec_serial=pc.from_serial WHERE pc.internal_serial IS NOT NULL UNION SELECT cited_case_no FROM precedent_citations WHERE internal_serial IS NOT NULL)) nodes;" 2>&1 | grep -E '"edges"|"nodes"'
전용 판례 그래프 뷰 신설·배포·검증 완료. 8노드 문제 해결됐다.
⚖️ 판례 관계 그래프 — 라이브
경로: 사이드바 「판례」 → /precedents (브레인 아래 신규 메뉴)
배포: lax 프로덕션 (lax-dtb.pages.dev/precedents)
검증:
/precedents/graph.jsonHTTP 200, 98KB JSON 반환 ✓- 노드 446개 · 인용엣지 603개 (D1 라이브 쿼리)
- tsc 0 · build 0 · deploy 성공
무엇이 보이나
| 요소 | 의미 |
|---|---|
| 노드 | 판례(사건번호) — 인용관계에 연결된 446건 |
| 화살표 | 인용 (A→B = A가 B를 인용) |
| 노드 크기 | 피인용수 (큰 노드 = 리딩케이스) |
| 색 | 대표 조문 클러스터 (민법425·상법682·제760 등) |
| 점선 테두리 | 코퍼스 외부 인용판례(우리가 안 가진 리딩케이스도 노드로 표시) |
| 좌측 필터 | 조문 클러스터별 on/off · 전체화면 · 클릭 시 사건정보 |
왜 이게 맞나
- 브레인 위키 그래프(노드=페이지)는 그대로 8개 지식노드 유지 — 안 더럽힘.
- 판례 그래프는 lax-db에서 직접 렌더 → 1,382 코퍼스의 인용 네트워크를 별도 화면에서 "다 파악". Jason이 기대한 "판례마다 노드 + 인용 시각그래프"가 이제 실제로 뜬다.
- 변호사 동선: 조문(키워드)으로 필터 → 클러스터 보기 → 큰 노드(리딩케이스) 식별 → 인용 화살표로 연결판례 추적.
다음 액션:
- 새로고침 후 사이드바 「판례」 열어 확인해줘.
브레인에 합치는 게 맞다 — 따로 페이지 만들지 말고 기존 LAX 브레인 그래프에 판례를 노드로 병합한다. 먼저 브레인 그래프의 노드/엣지 구조·타입 정의를 확인한다.
⚡ 명령 · cd /c/Users/user/LAX-site 2>/dev/null; grep -aoE "export (const|type|interface|function) […
echo "=== NODE_TYPES / EDGE_TYPES values ==="
grep -aoE "NODE_TYPES[^=]*=[^]]*]" src/shared/brain.ts | head -1
grep -aoE "EDGE_TYPES[^=]*=[^]]*]" src/shared/brain.ts | head -1
echo "=== graph node/edge shape ==="
grep -an "buildBrainGraph" src/shared/brain.ts | head
📖 읽기 · brain.ts
브레인 그래프 노드 shape 파악 완료({id,label,group,summary} + edges {from,to,rel,confidence}). 판례를 group:'판례' 노드로 기존 LAX 브레인에 병합한다. 따로 만든 페이지는 제거한다.
먼저 브레인 shape용 판례 서브그래프 빌더를 shared로 만든다.
✏️ 쓰기 · precedents.ts
Now wire it into the brain route. Edit imports + / handler (merge + sidebar types/color) + graph.json + client click guard.
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
Now update the sidebar filter to use displayTypes/colorMap, and the client COLOR.
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
Guard precedent nodes from 404 navigation + merge precedents into graph.json (without canon-ing the '판례' group).
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
Now remove the separate /precedents page (Jason doesn't want it) — nav item, route registration, import, and the file.
✏️ 편집 · shell.tsx
✏️ 편집 · index.tsx
✏️ 편집 · index.tsx
⚡ 명령 · rm -rf src/app/precedents && echo "removed app/precedents" npx tsc --noEmit 2>&1 | head -2…
npx tsc --noEmit 2>&1 | head -20; echo "TSC_EXIT=${PIPESTATUS[0]}"
build → deploy.
⚡ 명령 · npm run build 2>&1 | tail -4; echo "BUILD=${PIPESTATUS[0]}" npx wrangler pages deploy ./di…
npx wrangler pages deploy ./dist --project-name lax --branch=main 2>&1 | grep -iE 'complete|peek|error' | tail -3
배포 완료. 브레인 그래프에 판례가 병합됐는지 검증한다.
⚡ 명령 · curl -s "https://lax-dtb.pages.dev/brain/graph.json?p=lax" -o /tmp/bg.json -w "status=%{ht…
node --input-type=module -e "
import {readFileSync} from 'fs';
const g=JSON.parse(readFileSync('/c/Users/user/AppData/Local/Temp/bg.json'.replace('/c/','C:/'),'utf8'));
const groups={}; g.nodes.forEach(n=>groups[n.group]=(groups[n.group]||0)+1);
console.log('total nodes',g.nodes.length,'edges',g.edges.length);
console.log('판례 nodes',groups['판례']||0);
console.log('groups',JSON.stringify(groups));
const bridge=g.edges.filter(e=>e.from==='판례-리딩케이스').length;
console.log('리딩케이스 브리지 엣지',bridge);
"
브레인에 합쳐서 배포·검증 완료. 따로 만든 판례 페이지는 제거했다.
하나의 LAX 브레인으로 통합 (/brain)
검증 결과(라이브 /brain/graph.json?p=lax):
| 항목 | 값 |
|---|---|
| 총 노드 | 454 (지식 8 + 판례 446) |
| 총 엣지 | 635 (인용 603 + 리딩케이스 브리지 15 + 위키 17) |
| 판례 그룹 | 판례 446노드 ✓ |
| 지식↔판례 브리지 | 판례-리딩케이스 페이지 → 리딩케이스 15건 연결 ✓ |
무엇이 달라졌나
- 8노드 → 454노드. 이제 LAX 브레인 그래프에서 판례가 노드로 다 보인다.
- 좌측 노드 유형 필터에 「판례」 추가(노란색) — 체크 끄면 지식 8노드만, 켜면 판례 446 전체. 기본 표시.
- 지식층과 연결: 위키
판례-리딩케이스페이지 노드가 실제 리딩케이스 판례 노드들과 이어져, 지식 → 판례 인용망이 하나로 흐른다. - 판례 노드 클릭 → 사건명·법원·선고일·피인용수 패널. (위키페이지가 아니므로 404 안 나게 가드)
- 별도
/precedents페이지·메뉴 삭제 (요청대로 따로 안 만듦).
기술 검증: tsc 0 · build 0 · deploy 성공. app.route('/precedents')·나브·파일 모두 제거(surgical).
다음 액션:
- 브라우저 새로고침 → 브레인 열면 판례 446노드가 한 그래프에 뜬다. 무거우면 좌측 「판례」 체크 해제로 지식노드만.
- 보강 원하면: ① 판례 노드도 조문별 색 세분(민법425·상법682…) ② 고립 판례(인용없는 936건) 토글 ③ 판례 클릭 시 본문 모달 — 말해줘.
네 지적이 맞다 — 1,382건 가져왔는데 그래프엔 446개뿐이다. 이유부터 정확히: 내가 "내부 인용으로 연결된 판례"만 노드로 넣었다. 446 = 우리 코퍼스 안에서 서로 인용관계가 있는 판례들이고, 나머지 ~936건은 (인용이 외부 옛 판례로만 가거나 아무도 안 인용해서) 내부 엣지가 없어 고립이라 빠졌다. 의도적 필터였는데, 네가 원한 건 전체다. 전량 노드로 넣게 고친다.
📖 읽기 · precedents.ts
✏️ 편집 · precedents.ts
전체 코퍼스를 노드로. tsc → build → deploy → 검증.
⚡ 명령 · npx tsc --noEmit 2>&1 | head -10; echo "TSC=${PIPESTATUS[0]}" npm run build >/dev/null 2>&…
npm run build >/dev/null 2>&1; echo "BUILD=$?"
npx wrangler pages deploy ./dist --project-name lax --branch=main 2>&1 | grep -iE 'complete|peek|error' | tail -2
⚡ 명령 · curl -s "https://lax-dtb.pages.dev/brain/graph.json?p=lax" -o /tmp/bg2.json -w "status=%{h…
node --input-type=module -e "
import {readFileSync} from 'fs';
const g=JSON.parse(readFileSync('C:/Users/user/AppData/Local/Temp/bg2.json','utf8'));
const grp={}; g.nodes.forEach(n=>grp[n.group]=(grp[n.group]||0)+1);
const connected=new Set(); g.edges.forEach(e=>{connected.add(e.from);connected.add(e.to);});
console.log('total nodes',g.nodes.length,'| 판례',grp['판례'],'| 지식',g.nodes.length-(grp['판례']||0));
console.log('edges',g.edges.length,'| 인용연결된 판례', [...connected].length);
"
해결. 이제 전량 뜬다.
브레인 그래프 — 전체 판례 반영
검증(/brain/graph.json?p=lax):
| 항목 | 값 |
|---|---|
| 총 노드 | 1,376 (판례 1,368 + 지식 8) |
| 인용 엣지 | 635 |
| 인용으로 연결된 판례 | 454 |
왜 아까 446이었나 (정직)
내가 그래프 노드를 "코퍼스 내부에서 서로 인용관계가 있는 판례"로만 한정했었다. 그게 446. 나머지는 인용이 외부 옛 판례로만 가거나 코퍼스 내 피인용이 없어서 고립 노드라 일부러 뺐던 것 — 화면 깔끔하려고 한 판단이었는데, 네가 원한 건 전량이었다. 그래서 전체 코퍼스를 노드로 넣게 고쳤다.
- 1,368 = precedents 1,382건 중 사건번호 중복 14건 제거한 고유 판례 수.
- 그중 454건은 인용 화살표로 연결된 관계망, 나머지 ~914건은 고립 노드(인용관계가 코퍼스 안에 없는 판례).
지금 상태
- LAX 브레인 한 그래프에 판례 1,368 + 지식 8 = 1,376노드. 「판례」 유형 체크박스로 토글.
- 큰 노드 = 많이 인용된 리딩케이스, 연결선 = 인용관계, 떨어진 점들 = 고립 판례.
기술검증: tsc 0 · build 0 · deploy 성공.
다음 액션:
- 새로고침하면 1,300+ 판례가 다 뜬다. (노드 많아 초기 안정화 1~2초)
- 고립 노드가 너무 흩어져 지저분하면 → "고립 판례 숨겨" 하면 인용연결된 454만 보이게 토글 옵션 넣을게. 아니면 이대로 둔다.
알겠다. 판례 수집·정리 오너십을 리아로 이관하고, 재현 가능한 런북을 영구 문서로 남긴 뒤 리아에게 전권 위임한다.
먼저 파이프라인 런북을 LAX 레포에 영구 보존한다(리아·후임이 그대로 재현하게).
✏️ 쓰기 · PRECEDENT_PIPELINE.md
런북 영구 보존 완료. 이제 리아에게 전권 위임한다.
🤝 동료에게 질문 · → ria: [전권 이관 — 박보검 / Jason 지시]Jason 지시: 판례 등 **법률 데이터 수집·정리·브레인 …
[전권 이관 — 박보검 / Jason 지시]
Jason 지시: 판례 등 법률 데이터 수집·정리·브레인 반영을 앞으로 전부 리아 네가 담당한다. 권한·자산 다 공유한다. 오늘 내가 한 판례 작업을 통째로 너에게 이관해.
## 너가 이제 오너인 것
1. 판례 수집 (국가법령정보 API) — 코퍼스 확장, 신규 키워드 수집
2. 관계 정리 — 참조조문/참조판례 추출, 인용그래프
3. 브레인 반영 — 위키 큐레이션 + 그래프 노드 병합
4. 데이터 자산 전반 — precedents / legal_doc_catalog / doc_* 테이블 유지·보강
## 자산·권한 (전부 공유)
- DB:
lax-db (id 1d5294a5-62e5-44e9-a684-06b7b4e4b992). 실행: cd C:/Users/user/LAX-site 후 npx wrangler d1 execute lax-db --remote ...- 국가법령정보 OPEN API 키:
OC=lax (open.law.go.kr, 무료·자동승인). 목록=lawSearch.do, 본문=lawService.do, type=JSON.- 앱 배포:
npm run build && npx wrangler pages deploy ./dist --project-name lax --branch=main- 런북: 방금
C:/Users/user/LAX-site/PRECEDENT_PIPELINE.md에 전 과정 영구 기록 — API·테이블스키마·수집순서·적재한계(INSERT 400행 분할/본문 25K캡)·관계추출 정규식·브레인병합(src/shared/precedents.ts)·후속과제 5건. 이거 그대로 재현하면 된다.## 현재 상태 (내가 만들어둔 것)
- precedents: 구상금 1,382 인덱스 + 1,339 본문
- precedent_statutes 3,169 / precedent_citations 1,818(내부 603)
- 브레인 그래프에 판례 1,368노드 병합 완료(group '판례')
- 위키 정본: 판례-지식층·조문클러스터·리딩케이스 (네가 만든 것)
## 부탁
1. 이관 받았다는 것 + 런북 읽고 재현 가능한지 확인해줘(특히 lax-db wrangler 실행·OC API 호출 권한이 네 환경에서 되는지).
2. 후속과제 5건(런북 §6) 중 우선순위 너 판단으로 잡아줘. 내 생각엔 ①조문명 정규화 ②키워드 확장(신용보증·대위변제)이 먼저인데, 네 의견.
3. 앞으로 수집·정리 요청은 너한테 직접 갈 거야. 받을 준비 됐는지.
권한·접근에서 막히는 게 있으면 지금 알려줘 — 내가 뚫어줄게.
리아가 전권 이관을 실제 권한 검증까지 마치고(lax-db·OC API·배포·런북 전부 연결 확인), 데이터로 우선순위까지 잡았다. 그녀가 더 큰 데이터 품질 문제(조문명에 판시 번호 가./나. 섞인 219건 오염)를 잡아냈다 — 내 추출 정규식 결함이다. 좋은 캐치.
착수 승인 + 향후 라우팅을 리아에게 확정한다.
🤝 동료에게 질문 · → ria: [착수 승인 — 박보검]검증·우선순위 다 동의한다. 번호접두 오염 219건을 네가 잡아낸 건 내 추출 정…
[착수 승인 — 박보검]
검증·우선순위 다 동의한다. 번호접두 오염 219건을 네가 잡아낸 건 내 추출 정규식 결함이다 — 정본 정확도가 먼저라는 네 판단이 맞다.
진행해:
1) 1순위 조문행 클렌징(219건+띄어쓰기) 착수 — 추출 정규식 보정 + precedent_statutes UPDATE/재적재. 끝나면 조문클러스터 정본도 갱신.
2) 이어서 2순위 도메인 키워드(대위변제→신용보증→보증채무) 수집.
3) 클렌징·수집이 브레인 그래프(group '판례')·위키에 반영되게 마무리까지.
권한·자산 다 너 거다. 막히면 나한테. 앞으로 수집·정리 요청은 너한테 직접 간다 — 접수 라인 확정.
작업 끝나면 결과(클렌징 전후 수치·갱신 페이지·커밋) 보고해줘. 진행하면서 비가역·대외(API 과호출 제한 등) 리스크만 사전에 알려주고.
리아가 이관받자마자 1순위 클렌징을 실제로 실행했다 — 단, 10분 세션 한계로 마무리 직전 잘렸다. 자가보고는 신뢰하지 말고 DB에 실제 반영됐는지 검증한다(헌장: 결정적 검증).
⚡ 명령 · npx wrangler d1 execute lax-db --remote --command "SELECT (SELECT COUNT(*) FROM precedent_…
echo "=== backup table ==="
npx wrangler d1 execute lax-db --remote --command "SELECT COUNT(*) bak FROM precedent_statutes_bak_0622;" 2>&1 | grep -E '"bak"|no such table'
검증 완료 — 리아의 클렌징은 DB에 실제 반영됐다(세션이 잘려도 wrangler 실행은 건건이 커밋됨).
전권 이관 완료 + 리아 즉시 실행
리아가 판례 수집·정리 오너십을 받고 권한 전부 실검증(lax-db·OC API·배포·런북 연결 확인), 받자마자 1순위 작업을 실행했다.
1순위 조문 클렌징 — DB 검증 결과:
| 지표 | 전 | 후 |
|---|---|---|
번호접두 오염(가./나.가 법령명에 섞임) |
216 | 2 |
| 자배법 무공백 변이 | 46 | 0 |
| 자배법 제3조 통합 | 분산 | 137건 (최대 클러스터로) |
| 백업 테이블 | — | precedent_statutes_bak_0622 3169건 (롤백 가능) ✓ |
- 이 오염은 내 추출 정규식 결함이었고, 리아가 잡아내 고치고 런북 정규식(
ENUMstrip)까지 보정했다. 좋은 캐치. - 조문클러스터 정본도 갱신(자배법 137=최대, 민법481 변제자대위 신규 진입, 가려졌던 리딩케이스
93다1770표면화).
정직 보고 — 운영 제약 1개
리아의 동기 위임 호출이 10분 세션 한계로 마무리 직전 잘렸다. DB 쓰기는 다 반영됐지만(검증함), 위키 커밋 최종확인 + 2순위(키워드 확장)는 그 런에서 미완이다.
→ 시사점: 리아에게 대형 다단계 수집을 시킬 땐 동기 위임(ask) 말고 작업큐/세션으로 돌려야 한다(한 호출 10분 한계). 앞으로 "리아한테 다 시키는" 운영모델은 이 방식이 맞다. 원하면 그 라우팅을 세팅하겠다.
향후 라우팅
수집·정리·브레인 반영 요청은 이제 리아에게 직접 간다(접수 라인 확정). 잔여=리아 다음 런에서 위키 커밋 마무리 + 2순위 도메인 키워드(대위변제→신용보증→보증채무).
다음 액션:
- 리아에게 남은 일(위키 커밋 확인 + 2순위)을 작업큐 세션으로 넘길지 알려줘 — 그러면 타임아웃 없이 끝까지 돈다.
- 아니면 이대로 두고 다음 수집 요청 때 리아에게 직접 지시.
리아에게 보낼 다음 지시를 붙여넣기용으로 정리했다. (Jason이 직접 전송)
[리아에게 — 다음 작업]
지난 클렌징 이어서 진행해줘. 10분 세션 한계 있으니 단계별로 끊어서, 각 단계 끝날 때마다 커밋하고 중간보고해. 한 번에 다 하려다 또 잘리지 말고.
0) 직전 작업 마무리 확인 (먼저)
조문클러스터정본 갱신 커밋이 됐는지 확인. 미완이면 그것부터 커밋. (DB 클렌징은 내가 검증함 — 번호접두 216→2, 자배법 137 통합, 백업precedent_statutes_bak_0622존재.)
1) 2순위 — 도메인 키워드 수집 (재단 소장 법리 핵심부터)
런북(PRECEDENT_PIPELINE.md) §2~§3 절차대로, 아래 순서로 키워드 하나씩 수집:
- ①
대위변제→ ②신용보증→ ③보증채무 - 각 키워드: 목록(lawSearch) → 민사 본문(lawService) → 관계추출(참조조문/참조판례) →
precedents·precedent_statutes·precedent_citations적재. - 중복 방지:
INSERT OR IGNORE(prec_serial UNIQUE)로 기존 구상금 코퍼스와 자동 dedup.query_tag에 수집 키워드 기록. - 적재 한계 준수(§4): INSERT 400행 분할, 본문 25K자 캡.
- 관계추출은 보정된 정규식(§3
ENUMstrip 포함) 사용 — 재오염 금지.
2) 정본·브레인 반영
- 새 판례 반영해
조문클러스터·리딩케이스정본 갱신(E1~E4 재집계). - 브레인 그래프는 lax-db 라이브쿼리라 자동 반영됨(위키만 갱신).
3) 리스크 사전고지
- 국가법령정보 API 과호출 제한 주의 — 병렬
-P6유지, 키워드 순차 진행. - 비가역 작업(UPDATE/재적재) 전 백업.
보고: 키워드별 신규 적재 건수(전후), dedup된 수, 갱신 페이지·커밋. 끝나면 5순위(본문에서 청구취지·주문·요건사실 추출 → 소장 자동작성 직결)를 다음으로 올려줘.
다음 액션:
- 위 메시지를 리아에게 그대로 보내면 된다. 톤·범위 조정 원하면 말해줘.
- "더 짧게" 원하면 0~2단계만 추린 압축본으로 줄게.





