Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
5.6 KiB
5.6 KiB
로직 조각(logic chunk) 추출 설계 — 2026-09-16 구조 변경
결정
인덱스의 단위를 파서가 자른 unit(FORM/METHOD/FUNCTION/MODULE/이벤트) 에서 LLM 이 골라낸 로직 조각(logic chunk) 으로 바꾼다.
- 파서 unit 은 더 이상 인덱스 단위가 아니다. LLM 에게 코드를 나눠 보여주는 창(window) 이자, 조각의 위치를 설명하는 컨테이너 역할만 남는다.
- LLM 은 unit 코드를 읽고 업무적으로 의미 있는 로직 조각(특정 SQL, DB 갱신, BAPI 호출, 집계 LOOP, 검증 …)을 0개 이상 골라내 각각에 자연어 설명을 붙인다.
- 의미 없는 코드(선언, 초기화, ALV 필드카탈로그, 화면 속성 …)는 조각으로 만들지 않는다 → 인덱스에서 버려진다.
- 조각의 설명·키워드가 검색(chunk_fts)의 1차 대상이다.
왜 프로그램 전체가 아니라 unit 하나씩 보여주는가
| 관점 | 프로그램 전체 1회 | unit 창 + 프로그램 요약 문맥 (채택) |
|---|---|---|
| 긴 코드에서의 추출 품질 | 수천 줄에서 뒤쪽을 대충 봄 | 200~300줄 단위라 안정적 |
| 줄 번호 확정 | 어려움 | 창 안이라 매칭 쉬움 |
| 증분 비용 | 한 줄 수정에도 전체 재실행 | 바뀐 unit 만 |
| unit 을 가로지르는 로직 | 잡을 수 있음 | 프로그램 요약(main_flow) 이 담당 |
그래서 2단계로 간다.
- 프로그램 요약 — 구조 사실(이벤트 흐름, unit 목록, 테이블, 외부 호출, 텍스트 심볼, 이벤트 블록 코드)로
ProgramSummary를 만든다. 코드가 바뀌면(summary_status='stale') 다시 만든다. - unit 별 조각 추출 — 프로그램 요약 + unit 코드(줄번호 포함) + 파서 힌트(DB 접근·호출 줄)를 주고
UnitExtraction { unit_purpose_ko, chunks[] }를 받는다. 300줄을 넘는 unit 은 파서의sub_chunks(최상위 IF/LOOP 경계) 창으로 나눠 여러 번 호출한다.
사실은 파서가, 해석은 LLM 이 — 조각 단위에서의 적용
- 줄 번호: LLM 이 준
line_start/line_end는first_line(시작 줄 코드 원문)과 대조해 확정한다. 어긋나면 unit 안에서 그 줄을 찾아 보정하고, 못 찾으면 조각을 버린다(dropped). - 테이블/호출: 조각 코드 범위를 파서(
split_statements+extract_refs)로 다시 돌려tables_read/tables_write/calls를 채운다. LLM 이 쓴 값은 쓰지 않는다. - 해시: 조각 코드의 sha256 을
code_hash로 저장한다. unit 의 code_hash 가 같으면 재적재 시 조각을 보존한다.
스키마 (index/db.py)
logic_chunk(chunk_id PK = <unit_id>#C<seq>, program, include, unit_id, seq,
line_start, line_end, code_hash, kind, purpose_ko, purpose_en,
keywords_ko, keywords_en, sap_objects, tables_read, tables_write, calls (JSON),
confidence, prompt_version, extracted_at)
chunk_fts(chunk_id, program, purpose, keywords, objects, bigrams) -- FTS5
unit.summary_json = {purpose_ko(한 줄), chunk_count, covered_lines, coverage} -- 얇은 unit 색인
unit.summary_status = none | done | failed (done 이면서 chunk_count=0 = 의미 조각 없음)
program.summary_json = ProgramSummary, program.text_symbols_json
kind 어휘: sql_select, db_write, fm_call(BAPI/FM/RFC), aggregation(내부테이블 집계·가공),
validation(검증·권한), calculation, output(ALV·화면·파일·메일), interface, control_flow, other
검색 (query/tools.py)
search_logic(q)→ chunk_fts 검색 → 프로그램 단위로 묶어 반환(프로그램 요약 + 조각 목록).search_units/search_programs는 얇은 색인으로 유지 — 버려진 코드도 unit 이름·주석·한 줄 요약으로는 도달 가능.get_chunk(chunk_id)→ 메타 + 코드 원문.
정의부 — 조각을 붙여넣을 때 필요한 선언
조각 코드에는 로직만 둔다. 선언을 섞으면 조각의 뜻이 흐려지고 검색이 나빠진다.
대신 declaration 테이블에 선언 원문을 따로 모아 두고, 조각을 꺼낼 때 그 조각이 쓰는 선언을
의존까지 묶어 조립해 함께 준다 (get_chunk → declaration_code).
→ docs/definition-block-design.md
위키 (wiki_out)
- units/ 문서 생성 중단. 프로그램 문서 안에
## 로직 조각섹션(조각마다 H3, resource 줄 범위)으로 넣는다. → 1만 프로그램 × 수십 unit 파일 문제 해소. - OKF frontmatter 에
x-chunk-count추가.
평가 (eval)
- 질문 유형
logic추가:expected=[{program, line_from, line_to}]. 조각 검색 상위 10개 중 프로그램이 같고 줄 범위가 겹치면 적중.
남은 일 (구조 변경 뒤 10개 보강 과제와 연결)
2026-09-16 에 9건 반영 완료 — 판정·적용 내역은 docs/수정사항-적용.md.
- ✅ 조각 키워드·요약을 program_fts 에 반영(과제 1) —
index/loader.py:refresh_program_fts - ✅ 텍스트 심볼 FTS 반영(과제 3) —
index/db.py:text_symbol_phrases - ✅ 용어 사전 질의 확장(과제 4) —
query/expand.py(2단 검색) - ✅ 중복 조각 해시 묶기(과제 6) —
summarize/runner.py:clone_unit_chunks(줄 평행이동 포함) - ✅ 병렬 실행(과제 10) — 프롬프트 조립/호출/저장 3단 분리 + 429 백오프
- ✅ 엔티티 위키 + 계층 index.md(과제 8) —
wiki_out/entities.py - ⏸ 정답셋 확대(과제 7) — 남은 유일한 과제. 이게 없으면 위 검색 변경의 정밀도를 검증할 수 없다.
- ⏸ 프로세스 페이지(과제 8 후반) — 프로그램을 가로지르는 reduce 단계. 조각이 쌓인 뒤 판단.