Community코딩 & 개발github.com

pwquint24/org-babel-literate-tangle

Org Babel을 활용한 문헌적 프로그래밍(리터레이트 프로그래밍), 코드 추출(tangling), Noweb 매크로 확장, 배치 컴파일 및 설정 관리 가이드입니다.

org-babel-literate-tangle란 무엇인가요?

이 스킬은 Emacs의 Org Babel을 기반으로 한 문헌적 프로그래밍(Literate Programming)을 실현하는 방법을 종합적으로 안내합니다. 사용자는 하나의 Org 파일에 인간을 위한 설명(prose)과 기계가 실행할 코드 블록을 함께 작성하고, `:tangle` 헤더 인자를 통해 필요한 소스 코드 파일을 추출할 수 있습니다. 특히, Noweb 문법을 이용해 여러 코드 조각을 모듈식으로 조립하고, Org 테이블의 데이터를 코드에 인라인으로 주입하는 고급 기능을 제공합니다. 또한, 서브트리 수준에서의 타겟 파일 분리, 파이썬과 같은 공백 민감 언어를 위한 들여쓰기 처리, CI/CD 파이프라인에서 사용할 수 있는 헤드리스 배치 텡글링(batch tangling) 방법을 상세히 다룹니다. Emacs 환경에 의존적이지만 Makefile이나 CI 스크립트에서 `emacs --batch` 모드로 쉽게 통합할 수 있어, 문서와 코드가 항상 동기화된 상태를 유지하는 강력한 워크플로우를 구축할 수 있습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pwquint24/org-babel-agent-skills/tree/HEAD/skills/org-babel-literate-tangle

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Org Babel을 사용한 문헌적 프로그래밍과 텡글링

Org Babel은 도널드 크누스(Donald Knuth)의 문헌적 프로그래밍(Literate Programming) 패러다임을 구현한 것입니다. 코드 사이에 주석을 끼워 넣는 대신, 인간을 위한 설명(prose), 아키텍처 노트, 설계 이유를 작성하고 그 안에 실행 가능한 코드 블록을 포함시킵니다.

하나의 Org 파일은 두 가지 다른 출력물에 대한 최종 진실 공급원(single source of truth) 역할을 합니다.

  1. 위빙 (인간 문서): 노트북을 포맷된 HTML, LaTeX/PDF, 또는 Markdown으로 내보내 독자를 위한 문서를 만듭니다.
  2. 텡글링 (기계 실행): 컴파일러, 인터프리터, 배포 시스템을 위한 순수하고 실행 가능한 소스 코드 파일(.py, .sh, .c, .conf, .el)을 추출합니다.

1. 텡글링 기본: :tangle 헤더 인자

기본적으로 코드 블록은 텡글링되지 않습니다. :tangle 계열의 헤더 인자는 블록이 디스크에 어떻게, 어디로 추출될지를 지정합니다.

1.1 :tangle 인자 값

값동작
:tangle no (기본값)블록이 어떤 파일에도 기록되지 않습니다. (<<noweb>>를 통해 다른 블록 내부에 포함되는 것은 가능합니다.)
:tangle "path/to/file.py"블록 본문을 지정된 파일 경로(버퍼 디렉토리 기준 상대 경로 또는 절대 경로)에 직접 씁니다.
:tangle yesOrg 파일의 기본 이름과 언어의 표준 파일 확장자를 사용하여 파일로 텡글링합니다. (예: model.org -> model.py)

1.2 추가 텡글링 헤더 인자

  • :shebang "#!/usr/bin/env python3": 텡글링된 파일의 첫 번째 줄로 지정된 쉬뱅(shebang) 문자열을 앞에 추가합니다.
  • :tangle-mode (identity #o755): 생성된 파일에 파일 시스템 권한을 설정합니다 (예: #o755는 스크립트를 실행 가능하게 만듭니다).
  • :no-expand: 변수 할당(:var)이 텡글링된 코드에 인라인으로 포함되는 것을 방지합니다. 원시 블록 본문만 씁니다.
  • :mkdirp yes: 텡글 경로에 존재하지 않는 상위 디렉토리를 자동으로 생성합니다.

2. 텡글링 범위: 블록, 서브트리, 버퍼 수준

텡글링 인자는 프로젝트 전체에 깔끔하게 범위를 지정할 수 있습니다.

2.1 서브트리 수준 텡글링 (권장 패턴)

다른 제목(heading)들이 서로 다른 파일이나 모듈로 텡글링될 수 있습니다.

* 핵심 유틸리티
:PROPERTIES:
:header-args:python: :tangle src/utils.py :mkdirp yes
:END:

#+BEGIN_SRC python
  def slugify(text: str) -> str:
      return "-".join(text.lower().split())
#+END_SRC

* 데이터 처리 파이프라인
:PROPERTIES:
:header-args:python: :tangle src/pipeline.py :mkdirp yes
:END:

#+BEGIN_SRC python
  from utils import slugify

  def process_record(rec: dict) -> dict:
      rec["slug"] = slugify(rec["name"])
      return rec
#+END_SRC

2.2 버퍼 전체 텡글링 기본값

파일 상단에 설정합니다:

#+PROPERTY: header-args:python :tangle src/main.py

3. Noweb 문법: 모듈식 코드 조립

Noweb을 사용하면 더 큰 소스 파일을 더 작고 모듈식이며 설명하기 쉬운 조각들로 조립할 수 있습니다. <<block_name>>을 사용하여 한 코드 블록을 다른 블록 안에서 참조합니다.

3.1 Noweb 확장 활성화

Noweb은 기본적으로 비활성화되어 있습니다. :noweb 헤더 인자로 제어합니다.

:noweb 값Emacs에서 평가?디스크로 텡글?문서로 내보내기?
no (기본값)아니요아니요아니요
yes예예예
tangle아니요예아니요
strip-tangle예아니요 (참조 제거됨)예
no-export예예아니요
eval예아니요아니요

3.2 Noweb 예제: 문헌적 스크립트 구성

#+NAME: imports
#+BEGIN_SRC python :exports none
  import sys
  import argparse
  from pathlib import Path
#+END_SRC

#+NAME: argument-parser
#+BEGIN_SRC python :exports code
  parser = argparse.ArgumentParser(description="데이터셋 처리.")
  parser.add_argument("--input", required=True, type=Path, help="입력 CSV 경로")
  parser.add_argument("--threshold", default=0.5, type=float, help="점수 컷오프")
  args = parser.parse_args()
#+END_SRC

#+NAME: process-data
#+BEGIN_SRC python :exports code
  print(f"{args.input}에서 데이터 로딩 중...")
  # 처리 로직은 여기에
#+END_SRC

# 최종 실행 가능한 스크립트 조립:
#+NAME: main-cli
#+BEGIN_SRC python :tangle bin/run_pipeline.py :shebang "#!/usr/bin/env python3" :tangle-mode (identity #o755) :noweb yes :exports none
  <<imports>>

  def main():
      <<argument-parser>>
      <<process-data>>

  if __name__ == "__main__":
      main()
#+END_SRC

텡글링되면 bin/run_pipeline.py는 모든 조각이 적절히 배치되고 들여쓰기된 깔끔하고 실행 가능한 스크립트로 작성됩니다!

3.3 Noweb 접두사와 들여쓰기

  • Noweb은 들여쓰기를 존중합니다. def main(): 안에서 <<argument-parser>>가 4칸 들여쓰기되어 있으면 확장된 블록의 모든 줄도 4칸 들여쓰기됩니다.
  • 접두사 동작을 비활성화하려면: :noweb-prefix no.
  • 소스 코드 대신 블록 실행 결과를 삽입하려면 괄호를 추가하세요: <<compute_constant()>>

3.4 확장 디버깅

텡글링이나 실행 전에 Noweb 블록이 어떻게 확장될지 확인하려면:

  • 블록 안에 커서를 놓고 C-c C-v v (org-babel-expand-src-block)를 누릅니다.
  • Org는 모든 noweb 및 :var 치환 후의 정확한 코드를 보여주는 임시 버퍼를 엽니다.

4. 구성 및 데이터를 텡글링된 파일에 인라인 처리

Babel은 Org 테이블이나 제목 속성의 변수를 텡글링된 코드에 직접 인라인할 수 있습니다.

# Org 테이블에 저장된 구성:
#+NAME: server_config
| Key     | Value            |
|---------+------------------|
| host    | 10.0.1.25        |
| port    | 8080             |
| timeout | 30               |

# 텡글링된 구성 모듈:
#+BEGIN_SRC python :tangle config.py :var cfg=server_config :colnames yes
  HOST = cfg[0][1]
  PORT = int(cfg[1][1])
  TIMEOUT = int(cfg[2][1])
#+END_SRC

Babel이 텡글링된 코드에 변수 래퍼를 생성하는 것을 방지하려면 :no-expand를 전달하세요.


5. 들여쓰기 처리: 공백 민감 언어

Python이나 YAML과 같은 공백 민감 언어에서 Org의 자동 재들여쓰기는 문법을 깨뜨릴 수 있습니다.

Python 텡글링을 위한 중요 규칙:

org-src-preserve-indentation을 t로 설정하세요. t로 설정하면 Org는 내보내기나 텡글링 중에 들여쓰기를 제거하거나 추가하지 않습니다.

;; Emacs 설정에서:
(setq org-src-preserve-indentation t)

또는 블록별로 스위치 -i 사용:

#+BEGIN_SRC python -i :tangle script.py

6. 텡글링 실행 방법

6.1 Emacs 내에서 대화형으로

키바인딩명령어설명
C-c C-v t / C-c C-v C-torg-babel-tangle현재 버퍼의 모든 코드 블록을 텡글링합니다.
C-c C-v f / C-c C-v C-forg-babel-tangle-file디스크上的 Org 파일을 묻고 텡글링합니다.

6.2 텡글링된 파일에서 Org 파일로 탐색

텡글링될 때 Babel은 생성된 파일에 역링크 주석을 삽입합니다.

# [[file:~/project/notebook.org::*핵심 유틸리티][core-slugify]]
def slugify(text: str) -> str:
...
# core-slugify ends here

Emacs에서 생성된 파일을 열고 M-x org-babel-tangle-jump-to-org를 실행하면 소스 .org 문서의 정확한 제목과 블록으로 즉시 이동합니다!

6.3 헤드리스 명령줄 / CI / Make 배치 텡글링

Emacs GUI 창을 열지 않고 파일을 텡글링합니다 (빌드 스크립트, Makefile, 지속적 통합에 이상적).

# 단일 파일 텡글링:
emacs -Q --batch \
  --eval "(require 'org)" \
  --eval "(require 'ob-tangle)" \
  --eval '(org-babel-tangle-file "analysis.org")'

# 셸 루프나 Makefile에서 여러 파일 텡글링:
emacs -Q --batch --eval "
  (progn
    (require 'org)
    (require 'ob-tangle)
    (dolist (file command-line-args-left)
      (with-current-buffer (find-file-noselect file)
        (org-babel-tangle))))" *.org

7. 문헌적 설정 관리: init.org 패턴

Org Babel 문헌적 프로그래밍의 인기 있는 사용 사례는 Emacs 설정이나 시스템 닷파일(dotfiles)을 관리하는 것입니다.

~/.emacs.d/init.el에서:

;; Org Babel 문헌적 설정 부트스트랩
(require 'org)
(require 'ob-tangle)
(org-babel-load-file (expand-file-name "config.org" user-emacs-directory))

org-babel-load-file은 config.org가 마지막으로 config.el이 생성된 이후 수정되었는지 자동으로 확인하고, 필요한 경우 새 버전을 텡글링한 후 결과 .el 파일을 로드합니다.


8. 텡글링 프로젝트를 위한 요약 체크리스트

  1. 명시적 텡글링 경로: 명시적인 파일 이름을 사용하세요 (예: :tangle "src/core.py").
  2. 가독성을 위한 Noweb 사용: 복잡한 알고리즘을 논리적 단계(<<init-weights>>, <<forward-pass>>, <<backprop>>)로 나누어 이야기가 독자에게 자연스럽게 흘러가도록 하세요.
  3. 들여쓰기 유지: Python 코드의 경우 항상 org-src-preserve-indentation이 t인지 확인하세요.
  4. Make/CI로 자동화: 빌드 시스템에 헤드리스 emacs --batch 텡글링 단계를 포함시켜 생성된 소스 코드가 Org 문서와 동기화된 상태를 유지하도록 하세요.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

관련 스킬