논문 chunking 실험기 (RAG나 LLM wiki 등을 위한 준비 과정)

📝 한줄 요약

LLM Wiki에 논문 29편을 넣은 뒤, 검색과 OpenViking 연결을 준비하려고 먼저 chunking trial을 했다. 처음엔 “마크다운 섹션 제목 기준으로 자르면 되겠지”에 가까웠지만, 리뷰 논문·일반 원저·H2 중제목만 줄줄이 나열된 구조·OCR 논문을 거치며 규칙이 바뀌었다. 최종적으로는 출판사별 전용 파서를 만들지 않고, strict anchor(엄격한 기준 중제목 판정) + methods/results 같은 단계 제목 흡수(sibling absorb) + H3 soft split 조합을 채택했다.


🎯 이런 분들이 참고하실 수 있어요

  • 논문 PDF나 마크다운 원문을 LLM Wiki, RAG, 검색 시스템에 넣고 싶은 분

  • 문서를 “어디서 잘라야 검색이 잘 되는지” 고민하는 분


😫 문제 상황: 논문을 통째로 넣으면 검색이 뭉개진다

LLM Wiki의 정본 원문 레이어에는 시험용 논문 29편이 들어가 있었다. 다음 단계는 이 원문 위에 검색 가능한 retrieval layer를 얹는 것이었다. 여기서 retrieval layer란, 사용자가 질문했을 때 관련 논문 조각을 다시 찾아오는 검색·회수 계층을 말한다.

그런데 논문을 통째로 검색 대상으로 넣으면 결과가 너무 크고 흐릿해진다. 반대로 너무 잘게 자르면 문맥이 사라진다. 그래서 먼저 해야 할 일은 논문을 적당한 의미 단위로 나누는 것이었다.

이 작업에서 그 의미 단위를 chunk라고 불렀다. chunk는 검색이나 임베딩에 넣기 위해 문서를 나눈 조각이다. 예를 들어 논문 전체가 아니라 “Methods 중 MRI scanning 부분”만 하나의 chunk가 될 수 있다.


🔎 먼저 용어부터 짚기

이번 실험을 이해하려면 네 가지 용어만 알면 된다.

H2, H3

H2와 H3는 마크다운 문서의 섹션 제목 단계다. 이 글에서는 H2를 중제목, H3를 소제목처럼 설명한다.

## Materials and Methods   ← H2 중제목
### Patient cohort         ← H3 소제목
### MRI scanning           ← H3 소제목

H2는 큰 장 제목이고, H3는 그 아래 소제목이다. 논문을 마크다운으로 바꾸면 이런 제목 계층을 기준으로 본문을 나눌 수 있다.

다만 실제 추출 결과에서는 이 계층이 항상 예쁘게 유지되지 않았다. 출판사마다 HTML 구조가 다르고, PDF를 OCR로 뽑는 방식도 달라서, 소제목이어야 할 항목까지 전부 H2 중제목으로 나오는 경우가 있었다. 이 글에서는 그런 상태를 H2 중제목만 줄줄이 나열된 구조라고 부른다.

IMRaD

IMRaD는 많은 학술 논문에서 쓰는 기본 구조다.

  • Introduction

  • Methods

  • Results

  • Discussion

원저 논문은 대체로 이 구조를 따르지만, 리뷰 논문이나 가이드라인 논문은 꼭 그렇지 않다.

휴리스틱

휴리스틱은 완벽한 정답 규칙이 아니라, 여러 케이스에서 대체로 잘 작동하는 실용적 판단 규칙이다. 이번 작업에서는 “출판사별 전용 파서를 만들지 않고도, 대부분의 논문 구조를 버티는 규칙”을 찾는 것이 목표였다.

기준 중제목(anchor), regex, 흡수(absorb)

이번 chunker에서는 Methods, Results처럼 뒤따르는 소제목들을 묶어줄 수 있는 제목을 기준 중제목(anchor)이라고 봤다. 예를 들어 Methods가 기준 중제목이면, 그 뒤에 나오는 Patient cohort, MRI scanning 같은 항목은 Methods 아래 내용으로 묶일 수 있다.

이 기준 중제목을 찾을 때는 regex(정규표현식)를 썼다. regex는 글자 패턴을 찾는 규칙이다. 여기서는 “이 제목이 정확히 MethodsMaterials and Methods 같은 기준 중제목인가?”를 판정하는 데 썼다.

예를 들어 이런 식이다.

제목이 "Materials and Methods"이면 → 기준 중제목으로 인정
제목이 "MRI scanning"이면 → methods 관련 제목으로 분류할 수는 있지만, 기준 중제목으로는 인정하지 않음

그리고 어떤 논문은 소제목이 H3가 아니라 같은 단계의 H2 중제목으로 펼쳐져 있었다. 이때 Patient cohort, MRI scanning 같은 다음 H2들을 앞의 Methods 아래로 묶어주는 과정을 흡수(absorb)라고 불렀다.


🛠️ 사용한 도구와 역할

  • LLM Wiki 정본 원문 레이어: 논문 원문이 들어 있는 기준 자료 저장소

  • Python chunker script: 논문 마크다운을 chunk로 나누는 스크립트


🔧 작업 과정

1. 기본 방침: H2는 hard split, H3는 soft split

처음 채택한 기본 규칙은 단순했다.

  • H1/H2는 무조건 큰 분리점으로 본다.

  • H3는 부모 H2의 크기에 따라 나눌 수도 있고 합칠 수도 있다.

  • 목표 chunk 크기는 500–800 words.

  • 1200 words는 넘기지 않는 hard max로 본다.

  • section_type은 intro, methods, results, discussion, conclusion, meta, figure_caption, other로 분류한다.

  • 단, 모든 섹션을 억지로 IMRaD에 끼워 넣지 않는다.

마지막 규칙이 중요했다. 리뷰 논문이나 가이드라인 논문은 애초에 Methods/Results 구조가 아닐 수 있다. 이런 논문을 억지로 methodsresults로 분류하면 검색 결과가 오히려 거짓으로 정돈된다.

그래서 other가 많이 나오는 것을 실패로만 보지 않았다. 문서 구조가 실제로 그렇다면 other로 남기는 쪽이 더 안전했다.


2. 첫 trial: 리뷰 논문은 IMRaD에 억지로 맞추면 안 된다

첫 trial은 리뷰/가이드라인 성격의 논문이었다. 이 논문은 일반 원저처럼 Introduction, Methods, Results, Discussion이 깔끔하게 나뉘지 않았다.

처음 결과에서는 other가 많이 나왔다. 숫자만 보면 분류가 덜 된 것처럼 보일 수 있다. 하지만 이 논문은 애초에 IMRaD 구조가 아니었다. 따라서 “모든 것을 Methods/Results로 강제 매핑하지 않는다”는 기존 결정과 잘 맞았다.

이 trial에서 얻은 결론은 이랬다.

리뷰 논문에서 other는 실패 신호가 아닐 수 있다. 문서가 실제로 IMRaD 구조가 아니라면, 억지 분류보다 보수적 분류가 낫다.


3. 두 번째 trial: 일반 IMRaD 논문에서는 긴 Methods/Results를 잘라야 했다

다음은 H3 계층이 잘 살아 있는 일반 IMRaD 논문이었다. 여기서는 Abstract, Introduction, Methods, Results, Discussion, Conclusion 매핑이 깔끔했다.

하지만 새로운 문제가 나왔다. Methods와 Results가 하나의 chunk로는 너무 컸다.

  • Methods가 1000 words 이상

  • Results도 1000 words 이상

  • Discussion도 목표치보다 큼

검색 결과로 돌아왔을 때 사람이 읽기엔 너무 큰 덩어리였다.

여기서 사용자는 “method 등이 길어지면 적절히 자르고 싶다”고 방향을 줬다. 그래서 H3 soft split을 강화했다.

채택한 규칙은 이렇다.

H2 섹션이 800 words를 넘고 H3 하위 제목이 있으면, H3 단위로 나눈다. 단, section_type은 부모 H2에서 상속한다.

예를 들어 Methods 아래의 Patient cohort, Image acquisition, Statistical analysis 같은 H3는 각각 chunk가 되지만, 모두 methods 성격을 유지한다.

이 규칙 덕분에 큰 Methods/Results를 검색 가능한 크기로 나눌 수 있었다.


4. 세 번째 trial: H2 중제목만 줄줄이 나열된 구조가 나왔다

세 번째 논문에서 더 까다로운 문제가 나왔다. 보통은 Methods라는 H2 중제목 아래에 Patient cohort, MRI scanning 같은 H3 소제목이 들어가길 기대한다. 그런데 어떤 논문은 소제목이어야 할 항목까지 전부 H2 중제목으로 나열돼 있었다.

예를 들면 이런 식이다.

## Materials and methods   ← H2 중제목
## Patient cohort          ← 사실상 소제목인데 H2로 나옴
## MRI scanning            ← 사실상 소제목인데 H2로 나옴
## FDG-PET/CT reading      ← 사실상 소제목인데 H2로 나옴
## Statistical analysis    ← 사실상 소제목인데 H2로 나옴

사람이 보면 Patient cohortMRI scanning은 당연히 Methods의 하위 내용이다. 하지만 마크다운 구조만 보면 모두 같은 H2 중제목이다. 그러면 chunker는 Patient cohort를 Methods의 하위 항목으로 보지 못하고 other로 분류할 수 있다.

이런 구조가 나온 이유는 chunker 하나의 문제가 아니었다. 논문 원문은 출판사마다 HTML 구조가 다르고, PDF에서 OCR로 텍스트를 뽑는 방식도 다르다. 그래서 같은 논문 섹션이라도 어떤 파일에서는 H2/H3 계층이 살아 있고, 어떤 파일에서는 중제목만 줄줄이 펼쳐진 형태로 들어왔다. 이건 파이프라인의 한계점이기도 했다.

가장 깔끔한 해결책은 추출 과정에서 출판사별 HTML parser나 OCR 후처리 규칙을 정교하게 만드는 것이다. 하지만 그 작업은 시간이 많이 들고, 섹션 처리만 붙잡고 있으면 쉽게 번아웃이 올 수 있었다. 그래서 이번 단계에서는 추출기를 완벽하게 고치기보다, chunker 쪽에서 여러 heading 패턴을 버티는 휴리스틱을 먼저 두고, 세밀한 파싱 보정은 나중에 차차 고치기로 했다.

여기서 목표가 바뀌었다.

출판사별 전용 파서 없이, chunker 안에서 여러 heading 패턴을 견디는 휴리스틱을 만들자.


5. 첫 흡수 규칙은 좋아 보였지만, 리뷰 논문에서 폭주했다

처음 만든 해결책은 같은 단계 제목 흡수(sibling absorb)였다.

아이디어는 간단했다.

  1. Materials and Methods 같은 기준 중제목 H2를 찾는다.

  2. 그 다음에 나오는 H2들이 새로운 기준 중제목이 아니라면, 앞의 기준 중제목 아래로 흡수한다.

  3. 흡수된 항목은 부모 section_type을 상속한다.

이렇게 하면 H2 중제목만 줄줄이 나열된 논문에서 Patient cohort, MRI scanning, Statistical analysis를 모두 Methods로 묶을 수 있다.

하지만 바로 부작용이 나왔다.

H2 나열형 원저에는 도움이 됐지만, 리뷰 논문에서는 Introduction이 뒤의 여러 항목을 너무 많이 흡수했다. Pathology와 본문 항목들이 Introduction 아래로 들어가면서 의미가 무너졌다.

여기서 AI는 study_type 같은 frontmatter 정보를 보고 리뷰 논문이면 absorb를 끄는 복잡한 분기를 제안하려 했다. 하지만 사용자는 이 방향을 바로 받아들이지 않았다.

그건 별론데. 일단 흡수 결과 보여줘.

이 redirection이 중요했다. 복잡한 조건을 추가하기 전에, 실제로 무엇이 흡수됐는지 먼저 보자는 뜻이었다.

결과를 보고 나니 더 단순한 규칙이 나왔다.


6. 최종 채택: methods/results만 같은 단계 제목 흡수(sibling absorb) 허용

최종적으로 채택한 핵심 규칙은 이거였다.

ABSORB_ANCHOR_TYPES = {"methods", "results"}

즉, Introduction, Discussion, Conclusion도 section_type으로 분류할 수는 있다. 하지만 같은 단계의 H2 중제목을 흡수할 수 있는 기준 중제목 역할은 Methods와 Results로 제한했다.

이유는 단순하다.

  • H2 나열형 문제가 실제로 많이 생기는 곳은 Methods와 Results다.

  • Introduction이 같은 단계 제목을 흡수하면 리뷰 논문에서 폭주하기 쉽다.

  • Discussion과 Conclusion도 범위가 넓어져 의미가 흐려질 수 있다.

여기에 두 가지 안전장치도 같이 붙였다.

  • strict anchor regex(엄격한 기준 중제목 판정): Methods, Materials and Methods, Results처럼 standalone IMRaD 라벨만 기준 중제목으로 인정한다.

  • cap: 최대 8개 같은 단계 제목, 최대 2500 words까지만 흡수한다.

여기서 중요한 설계 판단은 regex를 둘로 나눈 것이다. regex는 제목 안의 단어 패턴을 보고 “이 제목을 어떻게 해석할지” 정하는 규칙이다.

  • section 분류 regex: heading에 cohort, scan, analysis 같은 단어가 있으면 methods로 분류할 수 있게 넓게 본다.

  • 기준 중제목 판정 regex: Methods, Materials and Methods, Results처럼 정말 뒤의 항목을 묶어줄 수 있는 제목인지 엄격하게 본다.

이 둘을 분리하지 않으면 문제가 생긴다. 분류 regex가 적극적일수록 기준 중제목도 너무 많이 잡히고, 그러면 흡수 구조가 흐트러진다.

이번 trial의 핵심 깨달음은 이것이었다.

분류는 넓게 하되, 흡수의 기준점은 좁게 잡아야 한다.

휴리스틱은 실제로 이런 모양이었다

본문에는 전체 코드를 넣지 않고, 핵심 판단만 축약하면 이렇다.

# 1) heading을 section_type으로 분류하는 규칙은 넓게 둔다.
# 예: cohort, imaging, scan, analysis 같은 단어가 있으면 methods로 볼 수 있다.
SECTION_PATTERNS = {
    "methods": r"method|materials and|patients and|cohort|imaging|scan|analysis",
    "results": r"result|finding|outcome|performance",
    "discussion": r"discuss|interpretation|implication",
    "meta": r"abstract|references|funding|conflict|acknowledg",
}

# 2) 하지만 같은 단계 제목을 흡수할 기준 중제목은 훨씬 좁게 본다.
# 'MRI scanning'은 methods로 분류될 수는 있지만, 기준 중제목이 되면 안 된다.
ANCHOR_STRICT = {
    "methods": r"^(materials and methods|methods|study design)$",
    "results": r"^(results|findings)$",
}

# 3) 흡수는 methods/results에서만 허용한다.
# Introduction까지 흡수하게 두면 review 논문에서 본문 전체가 딸려 들어갈 수 있다.
ABSORB_ANCHOR_TYPES = {"methods", "results"}
ABSORB_MAX_SIBLINGS = 8
ABSORB_MAX_WORDS = 2500

실제 흐름은 이런 식이다.

for section in H2_sections:
    anchor_type = classify_anchor_strict(section.heading)  # 엄격한 기준 중제목 판정

    if anchor_type in {"methods", "results"}:
        # 다음 H2들이 새로운 strict anchor(기준 중제목)가 아니라면
        # 현재 Methods/Results 아래 children으로 흡수한다.
        while next_section_is_not_strict_anchor():
            if too_many_siblings() or too_many_words():
                break
            absorb_as_child(section, next_section)
    else:
        # Introduction, Discussion, Conclusion은 분류는 하되
        # 같은 단계 제목 흡수는 하지 않는다.
        keep_as_independent_section(section)

예를 들어 이런 H2 나열형 입력이 있으면:

## Materials and methods
## Patient cohort
## MRI scanning
## Statistical analysis
## Results

최종적으로는 이렇게 해석한다.

Methods chunk group
├─ Materials and methods
├─ Patient cohort        # methods로 흡수
├─ MRI scanning          # methods로 흡수
└─ Statistical analysis  # methods로 흡수

Results chunk group
└─ Results               # 새 기준 중제목이라서 여기서 흡수 중단

반대로 리뷰 논문에서 이런 구조가 나오면:

## Introduction
## Pathology
## FIGO staging
## Treatment principles

Introduction은 기준 중제목처럼 보일 수 있어도 같은 단계 제목 흡수 대상이 아니다. 그래서 뒤 섹션을 전부 Introduction 아래로 끌고 가지 않는다.

Introduction       # 독립
Pathology          # 독립, 필요하면 other
FIGO staging       # 독립, 필요하면 other
Treatment principles # 독립, 필요하면 other

이게 최종 휴리스틱의 핵심이었다. 넓게 분류하되, 구조를 바꾸는 흡수는 좁게 허용한다.


7. 네 번째 trial: OCR 논문은 본문은 괜찮고 표지 노이즈는 v1로 미뤘다

마지막으로 OCR 기반 논문도 확인했다. OCR은 PDF 이미지를 텍스트로 읽어낸 결과라, 표지·저자·ORCID·Correspondence 같은 노이즈가 섞일 수 있다.

trial 결과, 본문 IMRaD 섹션은 잘 매핑됐다. Methods, Results, Discussion, tables는 검색에 쓸 수 있는 chunk로 나뉘었다.

다만 짧은 표지 메타 정보가 other chunk로 몇 개 남았다. 예를 들면 Correspondence나 ORCID 같은 항목이다. 일부 차이는 raw 추출이 깔끔하지 않아 생긴 노이즈성 chunk로 볼 수 있었다. 그래서 chunker 규칙만이 아니라, raw 추출 품질도 chunk 결과에 직접 영향을 준다는 점이 드러났다.

이걸 바로 제거하는 drop 휴리스틱을 넣을 수도 있겠지만 우선은 Chunking 후 추후 FTS/BM25 등이 잘 먹히는지 보고 싶어서 우선 보류.


📊 trial 결과 요약

최종 section_type 분포

여기서 section_type은 검색할 때 “이 chunk가 Methods인지, Results인지, 메타 정보인지, 아니면 분류하지 않는 other인지”를 알려주는 필드다.

citekey

total

intro

methods

results

discussion

conclusion

meta

figure_caption

other

berek2023

25

1

0

1

1

0

3

0

19

bezzi2026

14

1

5

5

1

1

1

0

0

fasmer2023

20

1

7

6

1

1

3

0

1

liu2019

12

0

1

4

1

0

1

0

5

합계

71

3

13

16

4

2

8

0

25

이 표에서 중요한 점은 두 가지다.

첫째, 일반 원저 논문에서는 methodsresults가 실제로 잘 살아났다. 특히 H2 중제목만 줄줄이 나열된 구조였던 fasmer에서도 methods 7개, results 6개가 잡혔다. 같은 단계 제목 흡수(sibling absorb) 휴리스틱이 의도대로 작동한 것이다.

둘째, review/guideline 성격의 berek는 other가 19개로 많다. 하지만 이건 무조건 실패가 아니다. 이 논문은 IMRaD 구조가 아니므로, 본문을 억지로 Methods/Results에 끼워 넣지 않은 결과다. 다만 OCR/raw 추출 노이즈가 섞이면 other가 더 늘 수 있으므로, v1에서는 작은 노이즈 chunk를 구분하는 보강이 필요하다.


✅ 최종 채택한 chunking 방식

이번 trial 이후 Step 1.1 기준으로 확정된 chunking spec은 다음과 같다.

항목

채택한 방식

큰 분리 기준

H1/H2 hard split

작은 분리 기준

H3 soft split

크기 기준

target 500–800 words, soft split 800 words, hard max 1200 words

section_type

intro / methods / results / discussion / conclusion / meta / figure_caption / other

기준 중제목 판정

strict regex로 standalone IMRaD 제목만 인정

같은 단계 제목 흡수(sibling absorb)

methods/results 기준 중제목만 허용

absorb 안전장치

최대 8개 같은 단계 제목, 최대 2500 words

리뷰 논문 처리

IMRaD 강제 매핑 금지, other 허용

OCR/raw 노이즈

v1 보강으로 이월

doc metadata

title, journal, year, doi, pmid를 모든 chunk에 복사

한 문장으로 줄이면 이렇다.

H2로 크게 자르고, 너무 큰 H2는 H3로 나누며, H2 중제목만 줄줄이 나열된 논문에서는 Methods/Results 아래 같은 단계 제목만 제한적으로 흡수한다.


💬 한계점

  • 위 규칙은 작성자가 html 혹은 ocr에서 뽑아낸 마크다운 구조에 대한 의존도가 높으므로, 작성자가 아닌 다른 사람이 추출한 .md 파일에서 똑같이 작동하지 않을 수 있음.

  • 각자의 데이터에서 구조를 파악하고 어떻게 나눌 수 있을지 더 고민이 필요함.

1
1개의 답글
밀어주고 끌어주는

온·오프라인 AI 스터디

AI로 어디까지 할 수 있는지
직접 확인하실 분만 신청하세요.