> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 확장과 ABI의 동작 방식

> 이 페이지는 VillageSQL 확장 ABI를 다룹니다. 서버가 소유하는 것, 확장이 소유하는 것, 그리고 그 구분이 크래시 복구, 복제, 복원, 스키마 작업 전반에서 어떻게 작동하는지 설명합니다.

VillageSQL 확장 프레임워크(VEF)는 MySQL 서버 코드의 지정된 위치에서 확장 코드를 호출합니다. 확장의 출력에 발생하는 모든 것 — 크래시 복구, 복제, 스키마 작업, 백업 — 은 서버가 내장 열 유형을 처리하는 방식과 동일하게 처리됩니다. 이 문서는 그 경계 — VEF가 하는 일, 확장이 하는 일, 그리고 그 결과로 만들어진 시스템이 운영 환경에서 어떻게 동작하는지 — 를 설명합니다.

이 페이지 전반의 예제는 [vsql-uuid](https://github.com/villagesql/vsql-uuid) 확장을 사용하여 데이터가 어떻게 흐르는지 설명합니다.

## ABI 경계

VillageSQL 확장은 바이너리 인터페이스(ABI)를 통해 서버와 상호작용하며, 확장과 서버 사이에 소유권이 명확하게 분리되어 있습니다.

**서버가 소유하는 것:**

* 저장소: InnoDB는 바이트를 읽고 쓰지만, 그것을 해석하지는 않습니다
* 스키마: 열 유형 메타데이터와 각 유형을 등록한 확장 정보는 VillageSQL 시스템 테이블에 저장되며 재시작 후에도 유지됩니다
* 복구, 복제, 백업: 이것들은 다른 내장 열 유형과 마찬가지로 원시 바이트에 대해 작동합니다
* 확장 등록: 이름, 버전, 함수/유형 등록은 시작 시 VillageSQL 시스템 테이블에서 다시 로드됩니다

**확장이 소유하는 것:**

* 바이너리 형식: `from_string` 인코딩 함수가 디스크에 무엇이 기록되는지 정의하며, `to_string`은 출력 시 그것을 다시 읽어들입니다
* 비즈니스 규칙: 검증, 비교, 해싱, 오류 처리
* 상태: 확장은 서버가 확장을 위해 저장하는 바이트 외에는 아무것도 유지하지 않습니다

전체 바이너리 인터페이스 — 구조체, 함수 포인터 typedef, 프로토콜 버전 관리 — 는 서버 저장소의 [`villagesql/sdk/include/villagesql/abi/types.h`](https://github.com/villagesql/villagesql-server/blob/main/villagesql/sdk/include/villagesql/abi/types.h)를 참조하세요.

## 사용자 정의 유형이 저장되는 방식

(vsql-uuid의 예처럼) 열을 `UUID`로 선언하면, 서버는 행마다 고정 길이의 원시 바이트 블록을 저장합니다. 사람이 읽을 수 있는 형태 — 예를 들어 `d7d665f3-bb13-4c2f-b10f-d2126eb40cba` — 는 경계에서만 존재합니다: `from_string`은 쓰기 시 그것을 바이너리로 인코딩하고, `to_string`은 읽기 시 그것을 다시 디코딩합니다. 그 사이의 모든 것 — 저장소, 리두 로그, 크래시 복구, 바이너리 로그 — 은 그 바이트를 해석하지 않고 작동합니다.

## 크래시 복구

확장은 서버 재시작 시 자동으로 다시 로드됩니다 — 수동 개입이 필요하지 않습니다. `INFORMATION_SCHEMA.EXTENSION_REGISTRATION`을 통해 이를 확인할 수 있으며, 재시작 후에도 이전과 동일한 등록 항목이 표시됩니다.

행 데이터는 InnoDB의 일반적인 크래시 복구를 통해 보존됩니다. 확장의 바이너리 형식은 결코 특별하게 취급되지 않습니다 — InnoDB는 UUID 열을 `VARBINARY` 열과 다르지 않게 처리합니다.

## 바이너리 로그 형식

행 형식 복제(기본값)에서 사용자 정의 유형 값은 바이너리 로그에 원시 바이너리로 전달됩니다. 재인코딩 단계는 없습니다: binlog를 기록할 때 확장의 `from_string`은 호출되지 않으며, `to_string`은 클라이언트가 값을 다시 읽을 때만 호출됩니다.

UUID 열에 대한 행 수준 바이너리 로그 항목은 다음과 같습니다:

```
### INSERT INTO `abi_test`.`t1`
### SET
###   @1='\xd7\xd6\x65\xf3\xbb\x13\x4c\x2f\xb1\x0f\xd2\x12\x6e\xb4\x0c\xba'
###   @2='alpha'
```

그 16개의 원시 바이트는 바이너리 로그를 통해 변경되지 않은 채 흐릅니다. 확장이 설치된 소비자는 `to_string`을 통해 그것을 읽을 수 있는 값으로 디코딩할 수 있습니다. 확장이 없는 소비자 — 외부 CDC 파이프라인이나 binlog 리더 — 는 원시 바이트만 봅니다.

## 복원

VillageSQL 서버를 복원하는 것은 크래시 복구와 동일한 방식으로 작동합니다: 서버가 시작되고, 확장 등록 정보를 읽고, 각 확장을 자동으로 로드합니다. 확장 유형 열에 대한 특별한 처리는 필요하지 않습니다 — 원시 바이트는 백업 안에 있으며, 확장은 필요할 때 그것을 디코딩합니다.

확장은 데이터베이스 내부에 저장되지 않습니다 — 확장은 디스크의 `veb_dir`에 `.veb` 파일로 존재합니다. 복원된 인스턴스에서 서버가 시작될 때 VEB 파일이 없으면, 시작이 `VEB file not found`와 함께 중단됩니다. `.veb_expansion_cache`는 `.veb` 자체를 대체하지 않습니다. 확장을 배포할 때, 사용자에게 데이터 디렉터리와 함께 모든 백업이나 서버 마이그레이션에 `veb_dir`을 포함해야 한다는 점을 반드시 알려주세요.

## 스키마 작업

확장 유형 열이 있는 테이블에 대한 `ALTER TABLE`은 내장 유형에 대해서와 정확히 동일하게 동작합니다. 서버는 스키마 메타데이터에서 열의 확장 바인딩을 추적하며, 그 바인딩은 테이블 재구성 후에도 유지됩니다. vsql-uuid `id` 열이 있는 테이블에 다른 열을 추가하거나 수정해도 UUID 데이터는 그대로 유지됩니다.
