Files
ABAP-Indexing/docs/logic-chunk-design.md

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단계로 간다.

  1. 프로그램 요약 — 구조 사실(이벤트 흐름, unit 목록, 테이블, 외부 호출, 텍스트 심볼, 이벤트 블록 코드)로 ProgramSummary 를 만든다. 코드가 바뀌면(summary_status='stale') 다시 만든다.
  2. unit 별 조각 추출 — 프로그램 요약 + unit 코드(줄번호 포함) + 파서 힌트(DB 접근·호출 줄)를 주고 UnitExtraction { unit_purpose_ko, chunks[] } 를 받는다. 300줄을 넘는 unit 은 파서의 sub_chunks(최상위 IF/LOOP 경계) 창으로 나눠 여러 번 호출한다.

사실은 파서가, 해석은 LLM 이 — 조각 단위에서의 적용

  • 줄 번호: LLM 이 준 line_start/line_endfirst_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_chunkdeclaration_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 단계. 조각이 쌓인 뒤 판단.