전자소송포털 서류 가이드를 직접 받아 우리 기능 목록과 대조하겠다. WebFetch 로드.
🌐 웹 · https://ecfs.scourt.go.kr/psp/index.on?m=PSPA13M04
이 페이지에 나오는 전자소송 제출 가능한 서류/사건의 전체 종류와 분류 목록을 빠짐없이 나열해줘. 민사본안, 독촉(지급명령), 보전(가압류·가처분), 강제집행, 송달 관련 등 카테고리별로 어떤 서류 유형이 있는지 알려줘.
SPA라 본문이 안 잡힌다(JS 렌더링). 공식 분류 체계를 웹검색으로 확인하겠다.
⏹ 중단됨
Jason 지적이 정확하다 — 이건 민사서류 탭 하나일 뿐이고, 좌측 메뉴를 보면 집행·보전은 별도 탭이다. 이게 바로 우리 풀세트의 MECE 결함을 드러낸다. 구조 분석을 합성하기 전에 변우석에게 in-scope 판정을 받겠다.
🤝 동료에게 질문 · → wooseok: 전자소송 공식 분류로 우리 구상금 풀세트의 MECE를 다시 점검 중이야. 전자소송 '민사 전체서류'는 서류를…
전자소송 공식 분류로 우리 구상금 풀세트의 MECE를 다시 점검 중이야. 전자소송 '민사 전체서류'는 서류를 '사건 단계'가 아니라 '기능군'으로 분류해. 기능군 목록은 이렇다:
[소제기] [주장서면] [증거신청] [청구취지] [보정/송달] [당사자] [소송대리] [기일/변론] [재판절차] [상소] [본안관련신청] [보전처분] [신청문건] [지급명령신청·독촉]
그리고 핵심: 강제집행 서류(채권압류및추심/전부, 부동산강제경매, 재산명시, 재산조회, 채무불이행자명부, 배당요구)는 '민사서류'가 아니라 좌측 별도 탭 **'민사집행서류'**에 있어.
질문 3가지:
1) 위 기능군 각각에서, 우리 첫 의뢰처(서울신용보증재단)의 **구상금 회수 실무에서 실제로 쓰이는 서류**만 골라줘. 각 서류를 [핵심=거의 모든 사건]/[조건부=다툼·송달불능 등 특정 상황]/[무관=구상금에선 거의 안 씀] 3단계로 태그해줘. 특히 증거신청군(서증/증거설명서/사실조회/문서제출명령/금융거래정보제출명령), 본안관련신청군(판결경정/결정경정/강제집행정지/소송비용액확정/증거보전)에서 구상금에 실제로 쓰는 게 뭔지가 중요해.
2) 데이터 분류 축을 우리 자체 '사건 단계' 축에서 전자소송 공식 '기능군 + 탭(민사/민사집행/비송)' 축으로 re-base 하는 데 동의해? 단계는 부가 태그로 빼고. 법무 관점에서 문제 없나?
3) 우리가 앞서 짠 풀세트 인벤토리에서, 이 공식 기능군 기준으로 봤을 때 명백히 누락된 핵심 서류가 있나? (예: 답변서·준비서면·서증·당사자표시정정·소송위임장 등)
간결하게 표로.
변우석 in-scope 판정 + 법무 동의 확보. MECE 재점검 결과를 합성한다.
핵심 결함이 드러났다 — 우리 풀세트는 MECE가 아니다. 분류 축이 틀렸다.
✏️ 쓰기 · gusangeum-mece-recheck.html
MECE 재점검 끝났다. 결론부터:
결론 — 현재 풀세트는 MECE 아님. 분류 축이 틀렸다.
재점검 설계서를 아티팩트로 첨부했다(gusangeum-mece-recheck.html). 데이터 모으기 전에 축부터 갈아야 한다.
| 결함 | 증상 |
|---|---|
| ME 깨짐(중복) | 우리는 '사건 단계' 축으로 묶었는데, 한 서류가 여러 단계에 중복 등장. 예: 준비서면·청구취지변경은 소제기후이자 변론 단계 → 두 번 셰임 |
| CE 깨짐(누락) | 단계로만 보면 기능군 통째로 빠짐 — 증거신청군(서증·증거설명서), 소송위임장, 집행문부여+확정/송달증명, 당사자표시정정 등 |
| 탭 혼입(치명) | 집행서류(채권압류추심 등)는 '민사서류'가 아니라 별도 탭 '민사집행서류'. 사건번호 체계부터 다름(본안=가단/가합, 독촉=차, 집행=타채/타경). 이전 P0에 본안+집행을 섞은 게 MECE 붕괴. Jason 지적이 정확 |
해법 — 전자소송 공식분류로 re-base (변우석 법무 동의 완료)
1차 축: [탭] → [기능군] → 서류명, '사건 단계'는 메타태그로 강등.
- 근거: 사건 단계는 서류의 분류 속성이 아니라 시점 속성. 1차축에 두면 중복 발생.
- 보너스: 1차축을 전자소송 메뉴에 1:1 맞추면 나중 전자소송 제출 자동화 매핑이 공짜.
재정의된 P0 (★핵심만)
- 민사 탭: 소장 · 준비서면 · 서증 · 소송위임장 · 주소보정서 · 집행문부여+확정/송달증명 · 지급명령신청
- 민사집행 탭(별트랙): 채권압류 및 추심·전부명령
데이터 스키마 재정의
doc_type(공식 서류명=상호배타 1차키) + 속성 tab/기능군/case_stage(메타)/in_scope(★◐✕)/priority. → 중복0(ME) + 누락0(CE).
액션
| # | 액션 | 담당 | 기한 | 왜 |
|---|---|---|---|---|
| 1 | 분류축 re-base 컨펌 | Jason | 즉시 | 데이터 스키마 근간. 변우석 법무동의 끝, Jason 방향만 남음 |
| 2 | 전자소송 민사집행서류·비송 탭 원문 수집(나 못 긁음) | Jason 붙여주기 or 박보검 재시도 | 1일 | 집행 탭 전체서류 목록 확정해야 CE 완성 |
| 3 | 공식 서류명 ↔ in_scope ↔ priority 마스터 테이블 D1 적재 | 박보검 | 3일 | 수집·라벨링의 기준 테이블 |
| 4 | P0 8종 골든셋 사건 풀기록 1건 확보 요청 | Jason→재단 | 1주 | 증거↔서류 매핑 확정 |
Jason 결정 필요(액션 1): 분류축을 전자소송 공식(탭→기능군→서류, 단계는 태그)으로 갈아엎는 것 — 컨펌 주시면 마스터 테이블(액션 3)부터 바로 만든다.
다음 액션:
- 액션 1 컨펌해주면 → 액션 3 마스터 테이블 D1 스키마부터 착수.
- 액션 2: 민사집행/비송 탭도 방금처럼 긁어서 붙여주면 그 자리에서 전체서류 MECE 매핑 완성한다.
@@ASK@@eyJxIjoi67aE66WY7LaV7J2EIOyghOyekOyGjOyGoSDqs7Xsi53rtoTrpZgo7YOt4oaS6riw64ql6rWw4oaS7ISc66WYLCDsgqzqsbTri6jqs4TripQg66mU7YOA7YOc6re4KeuhnCByZS1iYXNlIO2VoOq5jD8iLCJvIjpbIuy7qO2OjCDigJQg66eI7Iqk7YSwIO2FjOydtOu4lCDssKnsiJgiLCLrr7zsgqzsp5Htlokg7YOtIOuovOyggCDquIHslrTspITqsowiLCLrjZQg64W87J2YIl0sIm0iOmZhbHNlfQ==@@
📄 아티팩트: gusangeum-mece-recheck — 새 탭에서 열기
컨펌 받았다. 마스터 테이블을 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(~수십~150건)을 판례-<사건번호>.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단계만 추린 압축본으로 줄게.





