# 026 — 선택형 Pure 피어 연결과 실제 비용 2026-09-24. Linux AArch64, GCC 14.2, Zig 0.15.2, OpenSSL 3.x. 첫 공개 체크포인트의 **중간 결과**다. 이 문서의 크기는 전체 용량 scalar 모듈을 사용한 첫 구현 기준이다. 이후 고정 정의 빌드의 비용 변화는 [027](027-fixed-native-capacity.md)에 기록했다. ## 구현한 경계 기존 `routed-layout.pure`를 준비한 같은 앱 인스턴스에 `pure-peer`가 입력·조회·저장·복원을 제출한다. 서버는 TCP 소켓에서 TLS 1.3을 수립한 뒤 길이가 명시된 작은 바이너리 메시지를 읽고, 기존 `PureNativeApp`과 실행 코어를 호출한다. HTTP 문자열 헤더·메서드·URL이나 SQL 저장소를 이 연결의 내부 형식으로 사용하지 않는다. 일반 Python `ssl` 클라이언트도 이 형식을 구현해 상태를 읽고 작업을 제출했다. 기존 평문 HTTP 경계도 별도로 유지한다. ```text 외부 TCP → TLS 1.3 → 선택형 peer.c/peer-wire.c → 같은 앱 작업 → 실행 코어 → scalar·저장 ``` 이것은 **앱 선택 호스트**다. `runtime.c`, scalar 모듈, 실행 전용 `pure-native`에는 소켓·TLS 형식이 들어가지 않는다. OpenSSL을 직접 구현하지 않고 검증 가능한 라이브러리로 사용한다. TLS에서 체인 검증과 이름 검증은 별도 확인이 필요하다. `SSL_get_verify_result()`의 성공 값만 으로 피어 인증서를 받았다고 판단하지 않으며 실제 인증서 존재도 검사한다. [OpenSSL 검증 결과](https://docs.openssl.org/3.5/man3/SSL_get_verify_result/), [호스트 이름 검증](https://docs.openssl.org/3.5/man3/SSL_set1_host/). 서버와 클라이언트 모두 CA·인증서·개인키를 지정하고 서로의 DNS 이름을 검증한다. TLS 1.3과 ALPN `pure/1`이 맞지 않으면 종료하며 평문으로 낮추지 않는다. 0-RTT는 사용하지 않는다. 부작용 있는 작업을 0-RTT에서 안전하게 재생할 수 있다고 가정하지 않는 선택이다. [TLS 1.3 RFC §8](https://www.rfc-editor.org/rfc/rfc8446.html#section-8), [OpenSSL ALPN](https://docs.openssl.org/3.3/man3/SSL_CTX_set_alpn_select_cb/). ## 이번 앱에 필요한 최소 메시지 TLS는 바이트 스트림이므로 각 메시지 앞에 2바이트 big-endian 길이를 둔다. 핸드셰이크 후 서버가 `PUR1` 4바이트, 작성 정의 SHA-256 32바이트, 상태 수 1바이트, 로컬/저장 버전 각 8바이트로 된 53바이트 hello를 보낸다. Pure 클라이언트는 정의가 다르면 작업 전에 거절한다. 일반 클라이언트는 필요에 맞게 이 식별자를 확인할 수 있다. | 메시지 | payload 길이 | 의미 | |---|---:|---| | 상태 조회 | 1 B | 현재 값과 버전. 작업 효과 없음 | | 저장·복원 | 9 B | 동작 1 B + 기대 로컬 버전 8 B | | 키·프레임·초기화 | 12 B | 동작·버전·입력·위상·대상 | | 수치 입력 | 20 B | 위 필드 + IEEE binary64 값 | | 포인터 입력 | 28 B | 위 필드 + 좌표 2개 | | 결과 | 26 + 상태 수 × 8 B | 명시적 결과 코드·버전·오류·held·숫자 상태 | 선택한 앱의 상태·입력 한도에 따라 요청은 최대 28 B, 결과는 최대 282 B다. 앱 내부 구조체, 포인터, 패딩을 직렬화하지 않는다. 필드 길이·바이트 순서·유한 숫자·입력 종류와 대상·상태 수를 확인한 뒤 실행한다. 슬롯 숫자는 **현재 준비 정의의 연결 인덱스**이며 범용 안정 ABI가 아니다. 이 때문에 정의의 identity를 세션 시작에 확인한다. 서버는 작업의 `expected revision`이 현재 로컬 버전과 다르면 상태를 바꾸지 않고 충돌을 돌려준다. 한 연결에서 동시에 대기하는 작업은 하나로 제한한다. 응답이 유실되면 성공 여부를 알 수 없으므로 클라이언트가 자동 재시도하지 않는다. 다시 연결해 상태·저장 버전을 읽어야 한다. 연결이 끊어지면 해당 연결이 누른 키와 포인터 입력을 해제·취소한다. ## 재현한 동작과 비용 [실행 결과](../../prototypes/workbench/results/2026-09-24-secure-peer/peer-check.json), [빌드 식별](../../prototypes/workbench/results/2026-09-24-secure-peer/build.json), [크기 원자료](../../prototypes/workbench/results/2026-09-24-secure-peer/size.txt). 테스트는 1일짜리 임시 CA·서버·클라이언트 인증서를 `/tmp`에 만들고 종료 시 삭제한다. 실제 비밀키를 저장소에 넣지 않는다. - 일반 Python TLS 클라이언트가 정의 hello와 현재 상태를 읽고, 버전 불일치 작업의 충돌과 상태 불변을 확인했다. 연결을 끊은 뒤 서버가 held 입력을 해제하는 것도 확인했다. - 불명 동작·과장된 길이의 프레임, 인증서 없음·잘못된 클라이언트 이름, 잘못된 서버 이름, ALPN 불일치를 거절했다. 인증을 끝낸 뒤 요청을 보내지 않는 클라이언트도 약 5초의 요청 기한 후 연결을 닫고, 다음 클라이언트가 같은 앱을 읽을 수 있었다. - Pure 클라이언트가 녹색 상자를 잡아 이동·놓고 저장했다. 새 서버 프로세스의 첫 상태가 `green.x=220`, `green.y=200`, 저장 버전 1, held 0임을 확인했다. - 기존 네이티브/Wasm 9개 작성물·156개 이벤트의 일치 검사가 일반·C 호스트 ASan/UBSan에서 통과했고, Workbench Node 회귀 검사 87개가 통과했다. 같은 피어 통합 시나리오도 C 호스트를 ASan/UBSan으로 계측한 실행물에서 통과했다. Zig 모듈과 OpenSSL 라이브러리까지 계측했다는 뜻은 아니다. 동일한 준비 정의에 대해 `-O2 -g`로 만든 실행 파일을 비교했다. `size`의 text는 ELF 섹션 합계이며 실제 상주 메모리와 다르다. stripped 파일 크기도 라이브러리 파일을 포함하지 않는다. | 범위 | 이 호스트에서 관찰한 값 | |---|---:| | 공통 실행 코어 아카이브 `text/data/bss`, `make check-core` | 5,932 / 0 / 0 B, 6 KiB 예산 통과 | | `runtime.c` 단일 오브젝트 `text`, 이 명령의 `cc -O2` | 5,012 B | | 기존 실행 전용 CLI `text`, stripped ELF | 62,827 B, 68,000 B | | 선택형 피어 실행물 `text`, stripped ELF | 75,969 B, 133,936 B | | 피어 실행물에 추가된 `text` | 13,142 B | | 피어 서버 유휴 VmRSS / 인증 연결 중 VmRSS | 7,904 / 8,480 KiB, 각각 한 번 관찰 | | 피어 실행물의 직접 동적 의존성 | OpenSSL `libssl.so.3`, `libcrypto.so.3`, libc 및 라이브러리 하위 의존성 | 이 피어 프로세스를 “8 MiB 이하 런타임”이라 일반화하지 않는다. 인증서·TLS 연결·동적 라이브러리·호스트 환경의 비용이 포함되며 동시 연결, 실제 부하, macOS에서는 아직 측정하지 않았다. 실행 전용 CLI는 OpenSSL을 링크하지 않는다. 이 분리가 마이크로 비용의 현재 증거다. ## 남은 한계와 다음 판단 서버는 단일 앱 인스턴스에서 한 피어씩 처리한다. DNS 조회와 동기 저장 효과는 현재 5초 네트워크 기한에 포함되지 않는다. 원격 정의 교체, 다중 작업·스트림, 느린 소비자의 장기 예산, 권한별 역할, 인증서 교체 운영, 실제 인터넷 장애·손실·재연결 정책은 미구현이다. 5초는 현재 프로토타입의 고정값이다. macOS Apple Silicon에서는 빌드·실행을 확인하지 못했다. TLS 1.3 위의 인증된 앱 작업 **정확성**을 확인했을 뿐 QUIC 수준 전송 특성이나 Kitex 수준 성능을 보이지 않았다. 추가 성능 실험은 유휴 숫자 반복이 아니라 같은 앱 작업·보안·완료 조건에서 실제 병목이 나타날 때 진행한다. 체크포인트에는 큰 작성물과 혼합 작업, 전체 피크 메모리·작업별 비용, 사용자 작성·배포 경로가 더 필요하다.