(KO) PostgreSQL 클라이언트 프로토콜 — 섹션 개요
목차
이 섹션이 다루는 범위
섹션 제목: “이 섹션이 다루는 범위”이 서브카테고리는 PostgreSQL FE/BE 와이어 프로토콜의 백엔드 절반이다. TCP/Unix 소켓의 accept() 시점부터 완성된 SQL 명령이 파서로 진입하는 순간까지가 그 범위다. 세 가지 관심사가 있다.
- 와이어 프로토콜 자체 — 길이 접두사와 타입 태그를 붙이는 메시지 형식(
protocol.h의PqMsg_*바이트 코드), 그 메시지를 감싸는 버퍼드 I/O(libpq/pqcomm.c), 직렬화·역직렬화 헬퍼(libpq/pqformat.c), 그리고PostgresMain(tcop/postgres.c) 안의 정상 상태 메시지 루프. 루프는 메시지 하나를 읽어 첫 바이트로 분기하고(Q단순 질의,P/B/E확장 질의,X종료) 다시 돌아온다. 이것이 프로토콜의 운영 국면이다. - 연결 수립과 인증 — 루프 이전에 연결 하나가 딱 한 번 밟는 초기 경사면. 사용자와 데이터베이스를 담은 스타트업 패킷(
tcop/backend_startup.c파싱), 인증 방법을 고르는 HBA 룩업, 그리고 해당 방법을 실행하는libpq/auth.c의ClientAuthentication디스패치가 여기 있다. 현대적 기본값은 SASL 프레이밍 위의 SCRAM-SHA-256 챌린지-응답(auth-sasl.c+auth-scram.c)이다. - 전송 보안 — 스타트업 패킷보다 앞서 협상되는 선택적 암호화 계층. TLS(
be-secure.c+be-secure-openssl.c)와 GSSAPI 암호화(be-secure-gssapi.c)가 여기 해당하며, 각각 매직 협상 코드로 요청된다. PG17 이상에서는 ALPN으로 TLS를 직접 수립하는 경로도 열렸다.
명확한 경계. 이 섹션은 의도적으로 좁다. 파이프를 소유하지, 파이프 안을 흐르는 내용물을 소유하지 않는다.
- 상위 경계 (질의 파이프라인 쪽): 메시지 루프의 역할은 메시지 본문을 손에 쥐는 것으로 끝난다.
Q/P텍스트를 파스 트리로 바꾸는 일, 플래닝, 실행은 query-processing (postgres-overview-query-processing.md) 영역이다. 경계는 루프에서exec_simple_query/exec_parse_message로 넘어가는 호출 지점이다. - 하위/측면 경계 (서버 아키텍처 쪽): 루프를 누가 돌리는가 — postmaster가 연결마다
B_BACKEND를fork()하고BackendInitialize를 거쳐PostgresMain에 이르는 과정 — 는 server-architecture (postgres-overview-server-architecture.md) 소유다. 이 섹션은 fork된 소켓을 받아서 인증이 성공하면InitPostgres로 돌려준다. - 복제 서브프로토콜:
walsender의 COPY-both 스트리밍과START_REPLICATION명령 집합은 이 메시지 프레이밍을 재사용하지만, replication-ha (postgres-overview-replication-ha.md)에 기록된다. 이 섹션은 일반 클라이언트 경로만 다루고 연결 지점을 명시한다. - 프론트엔드
libpq클라이언트 라이브러리 (src/interfaces/libpq)는 이 프로토콜의 피어 구현이며 범위 밖이다. 이 트리는 백엔드를 분석한다. 공유 계약은protocol.h다.
핸드셰이크 스택
섹션 제목: “핸드셰이크 스택”모든 연결은 아래 직선형 스택을 정확히 한 번 올라간 뒤 메시지 루프에 자리 잡는다. 다이어그램의 각 구간은 그 구간을 소유하는 모듈 문서를 명시한다.
flowchart TB
SOCK["수락된 소켓<br/>(postmaster가 B_BACKEND를 fork함)<br/>— server-architecture 소유"]
subgraph TLSGSS["postgres-tls-gssapi.md"]
NEG["협상 요청 패킷<br/>SSLRequest / GSSENCRequest<br/>(ProcessSSLStartup)"]
ENC["암호화 계층 수립<br/>be_tls_open_server / secure_open_gssapi<br/>이후 모든 I/O를 secure_read / secure_write로 래핑"]
end
subgraph WIRE1["postgres-wire-protocol.md (수립 단계)"]
SUP["스타트업 패킷<br/>ProcessStartupPacket<br/>(사용자, 데이터베이스, GUC)"]
end
subgraph AUTH["postgres-authentication.md"]
HBA["HBA 룩업으로 인증 방법 결정<br/>(hba.c)"]
CA["ClientAuthentication 디스패치<br/>(auth.c)"]
SCRAM["SASL / SCRAM-SHA-256 교환<br/>CheckSASLAuth -> pg_be_scram_mech<br/>(auth-sasl.c, auth-scram.c)"]
end
HANDOFF["인증 성공<br/>-> InitPostgres / 백엔드 스타트업<br/>— server-architecture 소유"]
subgraph WIRE2["postgres-wire-protocol.md (정상 상태)"]
LOOP["PostgresMain 메시지 루프<br/>ReadCommand -> 첫 바이트로 분기<br/>Q 단순 / P,B,E 확장 / X 종료"]
FRAME["프레이밍 + 직렬화·역직렬화<br/>pqcomm.c (버퍼드 I/O)<br/>pqformat.c (PqMsg_* 코드)"]
end
PIPE["파싱된 메시지가 파서/실행기로 진입<br/>— query-processing 소유"]
SOCK --> NEG
NEG --> ENC
ENC --> SUP
NEG -. "암호화 미요청" .-> SUP
SUP --> HBA
HBA --> CA
CA --> SCRAM
SCRAM --> HANDOFF
HANDOFF --> LOOP
LOOP <--> FRAME
LOOP --> PIPE
다이어그램이 담고 있는 구조적 사실 두 가지를 짚어 두자.
- 암호화는 스타트업 패킷보다 먼저 협상된다. TLS를 원하는 클라이언트는
SSLRequest(메시지 타입 바이트 없이 길이+매직 코드만 담은 특수 패킷)를 보내고S/N응답 한 바이트를 기다린다. 그 뒤에야 실제 스타트업 패킷이 암호화된 채널 안으로 흐른다. GSSAPI 암호화도GSSENCRequest로 같은 방식으로 동작한다. PG17에서 추가된 다이렉트 TLS(ALPN)는 요청 바이트를 건너뛴다.backend_startup.c에서ProcessSSLStartup이ProcessStartupPacket보다 앞에 실행되는 이유가 바로 이것이다. - 클라이언트에서 서버로 오는 모든 인증 응답은 동일한 첫 바이트
'p'(PqMsg_PasswordMessage)를 쓴다. 평문 패스워드, SASL 초기 응답, GSS 토큰이 모두 같은 코드를 쓰는데(protocol.h는PqMsg_PasswordMessage,PqMsg_SASLInitialResponse,PqMsg_SASLResponse,PqMsg_GSSResponse를 동일 코드로 정의한다), 바이트가 아니라 인증 상태 기계가 어떤 응답인지 구분한다.
읽기 순서
섹션 제목: “읽기 순서”프로토콜 운영 국면을 먼저 읽고 초기 경사면을 나중에 읽는다. 인증과 TLS를 설명할 때 메시지 프레이밍 어휘를 전제하기 때문이다.
postgres-wire-protocol.md— 여기서 시작한다. 메시지 형식,PqMsg_*코드,pqcomm/pqformat,PostgresMain루프가 나머지 두 문서의 공통 어휘다. 스타트업 패킷도 이 문서 소유이므로 수립-루프 전환을 끝까지 볼 수 있다.postgres-authentication.md— 스타트업 패킷과 루프 사이에 자리한 인증 경사면. HBA 방법 선택,ClientAuthentication디스패치, SCRAM/SASL 챌린지-응답 교환(현대적 기본값),crypt.c검증자 처리.postgres-tls-gssapi.md— 마지막으로 그 아래에 있는 전송 계층. TLS/GSS 협상이 스타트업 패킷 이전의 교환이라는 점을 이해한 뒤 읽고, GSSAPI가 암호화와 인증 사이 경계를 흐리는 이유는 인증 문서를 읽은 뒤에 살펴본다.
세부 문서 요약
섹션 제목: “세부 문서 요약”전방 참조 — 아래 모듈 문서들은 계획 단계에 있으며, 요약은 예측적이다.
| 모듈 문서 | 한 줄 범위 |
|---|---|
postgres-wire-protocol.md | FE/BE 메시지 형식(protocol.h PqMsg_* 코드), pqcomm.c의 버퍼드 프레이밍, pqformat.c의 직렬화·역직렬화, 스타트업 패킷(backend_startup.c), tcop/postgres.c의 PostgresMain 단순-확장 질의 메시지 루프. |
postgres-authentication.md | auth.c의 HBA 주도 ClientAuthentication 디스패치, auth-sasl.c의 SASL 프레이밍(pg_be_sasl_mech)이 담는 SCRAM-SHA-256 교환(auth-scram.c), 패스워드 검증자 처리(crypt.c) — 채널 바인딩의 TLS 연결 포함. |
postgres-tls-gssapi.md | 스타트업 이전 암호화 협상과 secure_read/secure_write 추상화. OpenSSL 경유 TLS(be-secure.c, be-secure-openssl.c, README.SSL의 SSLRequest/다이렉트 ALPN 경로)와 GSSAPI 암호화(be-secure-gssapi.c, GSSENCRequest). |
인접 섹션
섹션 제목: “인접 섹션”postgres-overview-server-architecture.md— 양쪽 끝에서 직접 맞닿는 이웃이다.B_BACKEND를 만들어 내는 postmaster fork,BackendInitialize, 백엔드 수명 주기 안에서PostgresMain의 위치를 소유한다. 이 섹션은 fork된 소켓을 빌려와서 인증된 세션을InitPostgres로 돌려준다. 경계는 “메시지 루프 이전 vs 메시지 루프 안”이다.postgres-overview-query-processing.md— 메시지 루프가 먹여 살리는 섹션이다.ReadCommand가Q또는P/B/E메시지 본문을 반환하는 시점에 제어가 파싱→분석→재작성→플래닝→실행으로 넘어간다. 그 호출이 이 섹션의 상단 경계다.postgres-overview-replication-ha.md— 스트리밍 복제 서브프로토콜(walsenderCOPY-both,START_REPLICATION)에서 이 메시지 프레이밍을 그대로 재사용한다. 와이어 형식은 공유되지만, 명령 어휘와 walsender 루프는 그쪽에 있다.postgres-overview-base-infra.md— 프로토콜 계층이 세워지는 기반을 공급한다.pqformat의 뼈대인StringInfo버퍼, 메모리 컨텍스트, 그리고 와이어의ErrorResponse(E) 메시지로 올라오는elog/ereport오류 보고가 여기 있다.