> ## 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.

# Rust로 확장 만들기

> VillageSQL Rust SDK를 사용하여 안전한 Rust로 확장 함수를 작성하고, VEB 파일로 패키지화한 후 VillageSQL에 설치하는 방법을 알아보세요.

> [!NOTE]
>
> C++를 선호하는 경우 [C++로 확장 만들기](https://villagesql.com/docs/ko/extensions/build/create.md)에서 C++ SDK 워크스루를 참조하세요.

VillageSQL 확장은 `villagesql` 크레이트를 사용하여 Rust로 작성할 수 있습니다. SDK는 모든 FFI 마샬링을 처리하므로 일반적인 Rust 타입을 사용하여 작업할 수 있습니다. 서버가 로드 시 호출하는 C 엔트리 포인트는 `extension!` 매크로가 생성합니다.

## 사전 요구 사항

시작하기 전에 소스에서 VillageSQL을 빌드하세요 — `cargo vsql install`과 `cargo vsql test`는 서버의 빌드 트리를 사용합니다. 먼저 [소스에서 빌드](https://villagesql.com/docs/ko/8.4/stable/source.md) 가이드를 따르세요.

또한 다음이 필요합니다:

* **Rust 안정 도구 체인** — [rustup.rs](https://rustup.rs)에서 설치
* **Git** — SDK 및 확장 리포지토리를 클론하기 위해
* **cargo-vsql** — 확장 패키지화, 설치, 테스트를 위한 Cargo 하위 명령어
* **VillageSQL 빌드 디렉터리** — `cargo vsql install` 및 `cargo vsql test`를 위해 `VillageSQL_BUILD_DIR`을 서버 빌드 경로로 설정
* **기본적인 Rust 지식** — Cargo, 열거형, 패턴 매칭에 대한 익숙함

SDK 리포지토리에서 `cargo-vsql`을 설치합니다:

```bash theme={null}
git clone https://github.com/villagesql/vsql-rust-sdk
cd vsql-rust-sdk
cargo install --path cargo-vsql
```

사용 가능 여부를 확인합니다:

```bash theme={null}
cargo vsql --help
```

## 새 크레이트 생성

새로운 Rust 라이브러리 크레이트를 만들고 SDK를 추가합니다:

```bash theme={null}
cargo new --lib vsql_rot13
cd vsql_rot13
cargo add villagesql
```

그런 다음 `Cargo.toml`에서 크레이트 유형을 설정합니다:

```toml theme={null}
[lib]
crate-type = ["cdylib"]
```

`cdylib` 크레이트 유형은 Cargo에게 서버가 로드할 수 있는 공유 라이브러리(리눅스에서는 `.so`, 맥OS에서는 `.dylib`)를 생성하도록 지시합니다.

## 첫 번째 함수 작성

`src/lib.rs`를 완전한 확장으로 대체합니다:

```rust theme={null}
use villagesql::{InValue, VdfReturn};

fn rot13_impl(args: &[InValue]) -> VdfReturn {
    match args.first() {
        Some(InValue::String(s)) => VdfReturn::string(rot13(s)),
        Some(InValue::Null) | None => VdfReturn::null(),
        _ => VdfReturn::error("vsql_rot13: expected a STRING argument"),
    }
}

fn rot13(s: &str) -> String {
    s.chars()
        .map(|c| match c {
            'a'..='m' | 'A'..='M' => (c as u8 + 13) as char,
            'n'..='z' | 'N'..='Z' => (c as u8 - 13) as char,
            _ => c,
        })
        .collect()
}

villagesql::extension! {
    funcs: [
        villagesql::func!(rot13_impl, "vsql_rot13", [villagesql::Type::String] -> villagesql::Type::String),
    ]
}
```

`func!` 매크로는 `rot13_impl`을 SQL 이름 `vsql_rot13`과 `STRING -> STRING` 시그니처로 연결합니다.

함수 시그니처는 `fn(&[InValue]) -> VdfReturn`입니다. `InValue`는 서버가 전달하는 SQL 타입의 열거형입니다. `VdfReturn`은 반환 타입입니다. 값에 접근하기 전에 `args.first()`를 확인하여 NULL 경우와 잘못된 타입 경우를 처리하세요.

함수가 동일한 입력에 대해 항상 동일한 출력을 반환한다면 결정적(deterministic)으로 선언하세요 — 결정적 함수만 생성 열이나 `CHECK` 제약 조건에 사용할 수 있습니다:

```rust theme={null}
villagesql::func!(rot13_impl, "vsql_rot13", [villagesql::Type::String] -> villagesql::Type::String, deterministic: true)
```

## manifest.json 추가

크레이트 루트(`Cargo.toml`과 같은 위치)에 `manifest.json`을 생성합니다:

```json theme={null}
{
  "name": "vsql_rot13",
  "version": "0.1.0",
  "description": "ROT-13 encoding for VillageSQL",
  "author": "Your Name",
  "license": "GPL-2.0"
}
```

서버는 설치 시 이 파일을 읽습니다. `name` 필드는 `Cargo.toml`의 `[package]` 섹션에 있는 `name`과 `INSTALL EXTENSION`에 전달하는 값 모두와 일치해야 합니다.

## 빌드 및 설치

> [!NOTE]
>
> `cargo vsql package`, `cargo vsql install`, `cargo vsql test` 명령은 워크스페이스 루트가 아닌, 확장 디렉터리 내부(`Cargo.toml`과 `manifest.json`이 있는 위치)에서 실행하세요.

확장을 `.veb` 파일로 패키지화합니다:

```bash theme={null}
cargo vsql package
```

이로 인해 `dist/vsql_rot13.veb`가 생성됩니다. VEB를 직접 VillageSQL 빌드 디렉터리로 패키지화하고 복사하려면:

```bash theme={null}
export VillageSQL_BUILD_DIR=/path/to/villagesql/build
cargo vsql install
```

개발 중에 의존성을 로컬 체크아웃으로 패치하려면 `--config KEY=VALUE`를 전달하세요(반복 가능):

```bash theme={null}
cargo vsql install --config 'patch.crates-io.villagesql.path="/path/to/villagesql"'
```

VEB가 확장 디렉터리로 복사된 것을 확인할 수 있습니다. 존재하는지 확인합니다:

```bash theme={null}
ls "$VillageSQL_BUILD_DIR/veb_output_directory/"
# vsql_rot13.veb
```

> [!NOTE]
>
> **0.0.8-dev에서 변경됨.** `cargo vsql install`은 VEB를 `$VillageSQL_BUILD_DIR/lib/veb/`로 복사합니다.

## 테스트

`mysql-test/t/rot13_basic.test`에 테스트 파일을 작성합니다:

```sql theme={null}
INSTALL EXTENSION vsql_rot13;
SELECT vsql_rot13('Hello');
SELECT vsql_rot13('');
SELECT vsql_rot13(NULL);
UNINSTALL EXTENSION vsql_rot13;
```

예상 결과를 생성합니다:

```bash theme={null}
cargo vsql test --record
```

테스트 스위트를 실행합니다:

```bash theme={null}
cargo vsql test
```

함수의 동작을 수정한 후, 예상 결과를 업데이트하기 위해 `cargo vsql test --record`를 다시 실행하고, 확인하기 위해 `cargo vsql test`를 실행합니다.

## SQL에서 설치

VEB가 확장 디렉터리에 있으면 설치합니다:

```sql theme={null}
INSTALL EXTENSION vsql_rot13;
```

확인합니다:

```sql theme={null}
SELECT * FROM INFORMATION_SCHEMA.EXTENSIONS WHERE EXTENSION_NAME = 'vsql_rot13';
```

호출합니다:

```sql theme={null}
SELECT vsql_rot13('Hello, World!');
-- → Uryyb, Jbeyq!
```

## 다음 단계

이 안내서는 스칼라 함수 하나를 만듭니다. [vsql-rust-sdk](https://github.com/villagesql/vsql-rust-sdk) 저장소의 두 가지 예제는 집계와 가변 인자 지원을 다룹니다:

* [`examples/vsql_agg_sum`](https://github.com/villagesql/vsql-rust-sdk/tree/main/examples/vsql_agg_sum) — `agg_func!`로 `SUM`을 다시 구현한 집계 VDF로, 그룹별 누산기에 대해 별도의 `clear`, `accumulate`, `result` 콜백을 사용합니다.
* [`examples/vsql_varargs`](https://github.com/villagesql/vsql-rust-sdk/tree/main/examples/vsql_varargs) — `varargs_func!`로 만든 네 가지 가변 인자 함수: `str_join`(검증 있음, 상태 있음), `arg_count`(검증 없음, 상태 없음), `describe`(검증 있음, 상태 없음, INT/REAL/STRING 혼합 인수), `point_path`(사용자 정의 `point2d` 타입에 대한 가변 인자).

각 예제는 완전한 `Cargo.toml`, `manifest.json`, MTR 테스트를 포함합니다.

> [card] [Rust에서 사용자 정의 타입](https://villagesql.com/docs/ko/sdk/rust/custom-types.md)
>
> 이진 저장, 정렬, 해싱을 갖는 새 컬럼 타입 정의.

> [card] [Rust API 참조](https://villagesql.com/docs/ko/sdk/rust/api-reference.md)
>
> InValue, VdfReturn, extension!, func!, custom\_type! — 모든 필드.

> [card] [Rust에서의 미리보기 기능](https://villagesql.com/docs/ko/sdk/rust/preview-capabilities.md)
>
> requires: 목록을 통한 상태 변수, 시스템 변수, 백그라운드 스레드 워커,
> 키링 접근.

> [card] [C++ SDK (확장 만들기)](https://villagesql.com/docs/ko/extensions/build/create.md)
>
> C++ 경로 — 타입화된 래퍼, 빌더 API, CMake 설정.

> [card] [확장 아키텍처](https://villagesql.com/docs/ko/extensions/build/architecture.md)
>
> VEB 파일 로드, 라이프사이클 훅, 심볼 격리.

> [card] [네트워크 의존 확장 테스트](https://villagesql.com/docs/ko/sdk/cpp/testing-network.md)
>
> HTTP 서버나 외부 리스너를 생성하는 확장을 위한 MTR 포트 패턴 — Rust와 C++ 확장에 동일하게 적용됩니다.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.