콘텐츠로 이동

(KO) PostgreSQL 확장성 — 섹션 개요

목차

이 문서는 확장성 서브카테고리의 라우터다. 이 서브카테고리가 다루는 플러그 포인트들은, 모아 놓고 보면, PostgreSQL 코드베이스가 지금 같은 모양인 이유 그 자체다. 확장성은 부가 기능이 아니다. 코어는 처음부터 고정된 간접 지점들 위에 세워졌고, 서드파티 코드는 엔진을 패치하지 않고 그 지점에 꽂힌다. 플러그 포인트의 형태는 한결같다 — 콜백 struct이거나, 코어가 정해진 자리에서 확인하는 함수 포인터 전역 변수다. 확장 기능은 공유 라이브러리를 올리고, 구조체를 채우거나 전역 변수를 설정하고, 등록한다.

이 서브카테고리가 소유하는 플러그 포인트는 다섯 가지다.

  • 외부 데이터 래퍼(FDW)FdwRoutine 콜백 구조체(fdwapi.h)와 카탈로그 배관(foreign/foreign.c, commands/foreigncmds.c). 다른 시스템에 있는 데이터를 마치 로컬 테이블처럼 질의 플래닝·스캔·수정할 수 있게 한다.
  • 확장 기능CREATE EXTENSION 패키징 시스템(commands/extension.c). 컨트롤 파일, 버전 스크립트, 의존성 해결, pg_extension 북키핑이 합쳐져 SQL 묶음 + 공유 라이브러리를 하나의 설치·삭제 가능한 단위로 묶는다.
  • 훅 전역 변수 — 엔진 곳곳에 흩어진 함수 포인터 전역 변수들(planner_hook, ExecutorStart_hook, ProcessUtility_hook, shmem_request_hook / shmem_startup_hook 등). 로드된 모듈이 이 변수를 설정하면 플래닝·실행·유틸리티 명령 디스패치·공유 메모리 예약 단계를 가로챌 수 있다.
  • 절차형 언어 + SPILANGUAGE plpgsql 함수가 pg_language.lanplcallfoid에서 콜 핸들러(pl_handler.c)로 디스패치되는 경로, 그리고 그 핸들러가 서버 프로그래밍 인터페이스(executor/spi.c)로 SQL 엔진에 재진입하는 경로.
  • 커스텀 스캔 제공자CustomScanMethods / CustomPathMethods / CustomExecMethods 삼중 구조체(nodes/extensible.h, executor/nodeCustom.c). 확장 기능이 플래너의 경로 탐색과 실행기의 노드 트리에 자신만의 플랜 노드를 주입할 수 있게 한다.

명확한 경계 — 이 서브카테고리가 넘기는 것들. 아래 세 플러그 포인트는 패턴상 동일하지만(등록된 콜백 구조체), 더 깊은 서브시스템에 속하기 때문에 다른 곳이 소유한다.

  • 테이블 및 인덱스 접근 방법(TableAmRoutine, IndexAmRoutine)은 스토리지 계층의 플러그 포인트로, storage-engine이 소유한다(postgres-table-am.md, postgres-index-am.md). FDW는 쿼리 시점의, 커스텀 스캔은 플래너 시점의 테이블 AM 유사체다.
  • 커스텀 WAL 리소스 매니저(RegisterCustomRmgr)는 WAL의 자기 서술적 레코드 집합을 확장하는 포인트로, txn-recovery가 소유한다(postgres-wal-records-rmgr.md).
  • 백그라운드 워커(RegisterBackgroundWorker)는 프로세스 모델의 플러그 포인트로, server-architecture가 소유한다(postgres-background-workers.md). PL이나 병렬 질의는 이 프레임워크의 소유자가 아니라 클라이언트다.

아키텍처 개요의 축 7은 일곱 개의 플러그 포인트를 모아 이름을 붙인다. 이 라우터는 그 가운데 사용자 대면 확장 표면에 해당하는 다섯 개를 다루고, 나머지 셋을 해당 섹션으로 넘긴다. 메커니즘은 코어에 있고, 구현은 대부분 contrib다. contrib/postgres_fdw, pg_stat_statements(planner_hook + 공유 메모리 사용자), 트리 내 인덱스 AM은 모두 이 패턴의 사례다 — 그러나 contrib/는 이 트리의 범위 밖이다. 이 문서들은 코어 메커니즘을 분석하고, contrib 모듈은 표준 사례를 이름으로 언급하는 것에 그친다.

기반 구조: 하나의 패턴, 많은 플러그 포인트

섹션 제목: “기반 구조: 하나의 패턴, 많은 플러그 포인트”

이 서브카테고리의 모든 플러그 포인트는, 코어가 정해진 자리에서 확장 기능이 설정한 간접 지점을 확인하는 구조다. 아래 다이어그램은 이 서브카테고리가 소유하는 다섯 개의 사용자 대면 표면(실선)과 인접 서브카테고리로 넘기는 세 개(점선)를 묶어 보여 준다.

flowchart TB
  CORE["PostgreSQL 코어<br/>(정해진 자리에서 각 간접 지점을 확인)"]

  subgraph OWNED["이 서브카테고리가 소유하는 플러그 포인트"]
    direction TB
    FDW["외부 데이터 래퍼<br/>FdwRoutine<br/>postgres-fdw.md"]
    EXT["확장 기능 패키징<br/>CREATE EXTENSION / 컨트롤 파일<br/>postgres-extensions.md"]
    HOOK["훅 전역 변수<br/>planner / ExecutorStart /<br/>ProcessUtility / shmem_*<br/>postgres-hooks.md"]
    PL["절차형 언어<br/>pg_language -> 콜 핸들러<br/>postgres-plpgsql.md"]
    SPI["서버 프로그래밍 인터페이스<br/>SPI_connect / SPI_execute<br/>postgres-spi.md"]
    CS["커스텀 스캔 제공자<br/>CustomScanMethods<br/>postgres-custom-scan.md"]
  end

  subgraph HANDOFF["같은 패턴, 인접 서브카테고리 소유"]
    direction TB
    TAM["테이블 / 인덱스 AM<br/>(storage-engine)"]
    RMGR["커스텀 WAL rmgr<br/>(txn-recovery)"]
    BGW["백그라운드 워커<br/>(server-architecture)"]
  end

  CORE --> FDW
  CORE --> EXT
  CORE --> HOOK
  CORE --> PL
  CORE --> CS
  PL --> SPI

  CORE -.-> TAM
  CORE -.-> RMGR
  CORE -.-> BGW

  EXT -. "패키징 + 로드" .-> FDW
  EXT -. "패키징 + 로드" .-> PL
  EXT -. "패키징 + 로드" .-> CS

이 다이어그램에서 구조적으로 중요한 관계가 두 가지 있다.

  • CREATE EXTENSION은 패키징 계층이지, 플러그 포인트 자체가 아니다. 다른 표면들이 확장 기능이 무엇을 제공하는지를 나타낸다면, postgres-extensions.md는 그것이 어떻게 전달되고, 버전이 매겨지고, 추적되는지를 다룬다. FDW, PL, 커스텀 스캔 제공자는 보통 확장 기능으로 배포된다.
  • PL과 SPI는 한 번의 왕복을 이루는 두 절반이다. PL 콜 핸들러는 엔진이 확장 코드로 진입하는 경로이고, SPI는 그 확장 코드가 SQL을 실행하기 위해 엔진으로 재진입하는 경로다. SPI는 PL 외에도 트리거·규칙 시스템·C 함수가 모두 사용하기 때문에 별도 문서로 분리했지만, 두 문서는 함께 읽는 것이 자연스럽다.

앞 문서를 뒤 문서가 참조하는 순서로 배열했다.

  1. postgres-hooks.md — 여기서 시작한다. 훅 전역 변수 패턴은 이 서브카테고리 전체 명제의 가장 단순한 사례다(함수 포인터를 설정하면 코어가 정해진 자리에서 호출한다). 다른 문서들이 “등록된 간접 지점”이라고 말할 때 참조하는 기준이 된다.
  2. postgres-extensions.md — 나머지를 전달하고 로드하는 패키징 시스템. FDW, PL, 커스텀 스캔의 구체적 플러그 포인트를 읽기 전에 먼저 읽는다.
  3. postgres-fdw.md — 가장 풍부한 콜백 구조체(FdwRoutine)이자, “패치 없이 쿼리 경로를 확장”하는 방식을 가장 명확하게 보여 주는 사례. query-processing 서브카테고리의 플래너/실행기 문서와 짝을 이룬다.
  4. postgres-custom-scan.md — 플래너와 실행기 양쪽을 모두 건드리는 플러그 포인트. FDW를 읽은 뒤 읽으면 좋다. “스캔 주입”이라는 같은 문제를 한 단계 낮은 수준(외부 테이블 추상화가 아닌 원시 플랜 노드)에서 푼다.
  5. postgres-plpgsql.md — 표준 절차형 언어 구현과 pg_language 디스패치 경로.
  6. postgres-spi.md — PL·트리거·규칙·C 함수가 엔진 내부에서 SQL을 실행할 때 공통으로 사용하는 재진입 API. 서버 사이드 코드 메커니즘이 공유하는 이음새를 다루므로 마지막에 읽는다.

아래는 전방 참조다. 해당 모듈 문서가 아직 존재하지 않을 수 있으며, 요약은 예측적이다.

모듈 문서범위 한 줄 요약
postgres-fdw.md코어 내 외부 데이터 래퍼 메커니즘: FdwRoutine 콜백 구조체(GetForeignRelSizeGetForeignPathsIterateForeignScan, 수정 콜백 포함), GetFdwRoutineForRelation / GetFdwRoutineByRelId가 외부 테이블에서 래퍼 핸들러를 찾는 방법(그리고 GetFdwRoutine이 그 핸들러를 호출해 구조체를 얻는 과정), foreigncmds.c의 서버/사용자 매핑/외부 테이블 DDL — contrib/postgres_fdw는 표준 사례로만 언급.
postgres-extensions.mdCREATE EXTENSION 패키징 시스템: 컨트롤 파일(read_extension_control_file), 버전 업그레이드 스크립트, 의존성 해결 및 CASCADE(CreateExtensionInternal), 확장 기능을 하나의 설치·버전 관리·삭제 단위로 만드는 pg_extension / pg_depend 북키핑.
postgres-hooks.md함수 포인터 훅 전역 변수: planner_hook, ExecutorStart_hook(및 나머지 실행기 훅), ProcessUtility_hook, 세그먼트 크기 확정 전에 공유 메모리를 예약할 때 확장 기능이 반드시 사용해야 하는 shmem_request_hook / shmem_startup_hook 쌍 — 체이닝 규칙(이전 포인터를 저장한 뒤 그 포인터로 호출)과 고정된 호출 지점.
postgres-plpgsql.md참조 절차형 언어: pg_language.lanplcallfoid에서 plpgsql_call_handler / plpgsql_inline_handler / plpgsql_validator로의 디스패치, 함수 바디를 PL 트리로 컴파일(pl_comp.c), 실행(pl_exec.c) — SPI를 통한 엔진 재진입 포함.
postgres-spi.md서버 프로그래밍 인터페이스: SPI_connect / SPI_execute / SPI_prepare / SPI_cursor_open, 외부 트랜잭션 안에서 서버 사이드 코드가 SQL을 안전하게 실행할 수 있게 하는 SPI 메모리 컨텍스트와 스냅샷 관리, 그리고 이에 의존하는 클라이언트들(PL, 트리거, 규칙 시스템, C 함수).
postgres-custom-scan.md커스텀 스캔 제공자 인터페이스: CustomPathMethods / CustomScanMethods / CustomExecMethods 삼중 구조체(extensible.h), 제공자가 플래너의 경로 목록에 CustomPath를 주입하는 방법과 실행기가 ExecInitCustomScan / ExecCustomScan(nodeCustom.c)으로 이를 인스턴스화하는 방법, 플랜 직렬화를 위한 RegisterCustomScanMethods.

확장성은 독립된 서브시스템이 아니라 횡단적 표면이기 때문에, 이 서브카테고리는 네 곳과 맞닿아 있다.

  • storage-engine(postgres-overview-storage-engine.md) — 테이블/인덱스 AM 플러그 포인트(TableAmRoutine, IndexAmRoutine)를 소유한다. FDW와 커스텀 스캔은 테이블 AM의 쿼리 시점 친척이다. AM 문서를 읽으면 등록된 콜백 패턴의 가장 깊은 사례를 볼 수 있다.
  • query-processing(postgres-overview-query-processing.md) — FDW, 커스텀 스캔, planner_hook / ExecutorStart_hook 플러그 포인트가 걸리는 플래너와 실행기를 소유한다. 훅과 커스텀 스캔은 거기서 설명되는 경로 탐색·노드 트리 메커니즘이 있어야만 의미가 생긴다.
  • txn-recovery(postgres-overview-txn-recovery.md) — 커스텀 WAL 리소스 매니저(RegisterCustomRmgr)를 소유한다. 내구성 계층에서 같은 패턴이 나타나는 사례다.
  • server-architecture(postgres-overview-server-architecture.md) — 백그라운드 워커 프레임워크(RegisterBackgroundWorker)와 shmem_request_hook이 예약하는 공유 메모리 기반을 소유한다. PL이나 병렬 질의 확장 기능은 이 두 가지의 클라이언트다.