[Rust 공식문서 한국어 정리] 58. Rust FFI 모범 사례 가이드
[Rust 공식문서 한국어 정리] 58. Rust FFI 모범 사례 가이드
원문 제목: FFI — The Rustonomicon
작성자: The Rust Language Team
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📌 1. 서론 — 이 문서가 다루는 내용
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
이 문서는 Rust가 외부 코드와 상호작용할 때 안전하고 견고한 FFI 설계를 위한 모범 사례를 제시합니다.
C ABI 호환성, 메모리 관리 책임 분리, 패닉 경계, 그리고 객체 생명주기 관리를 다룹니다.
안전한 래퍼(sys 크레이트와 safe 크레이트 분리), 널 포인터 처리, 그리고 콜백 안전성을 중심으로 설명합니다.
FFI는 Rust의 안전성 경계를 넘어서는 영역이므로, 계약(contract)을 명시하고 위반을 방지하는 패턴이 핵심입니다.
네이티브 라이브러리를 감싸거나, Rust를 다른 언어의 플러그인으로 제공하는 개발자에게 필수적입니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔑 2. 핵심 개념 4가지
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
① sys/safe 분리: raw FFI 바인딩(sys)과 안전한 래퍼(safe)를 별도 크레이트로 분리합니다.
② Contract: unsafe 함수의 전제조건과 보증을 문서에 명시하여 호출자가 준수하도록 합니다.
③ Panic Boundary: FFI 경계에서 panic이 외부로 전파되지 않도록 catch_unwind로 차단합니다.
④ RAII: 외부에서 할당한 리소스는 Rust의 Drop 트레이트로 관리하여 메모리 누수를 방지합니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📖 3. 주요 내용 상세
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FFI 설계의 첫 번째 원칙은 sys와 safe 크레이트의 분리입니다.
-sys 크레이트는 bindgen이나 수동 선언으로 C API를 raw하게 매핑합니다.
-safe 크레이트는 -sys를 감싸고, 소유권과 수명을 관리하며, Option>로 null을 명시적으로 처리합니다.
이 구조는 unsafe 영역을 최소화하고, 사용자에게 안전한 API를 제공합니다.
메모리 관리의 책임 소재는 반드시 문서화해야 합니다.
Rust가 할당한 메모리를 C가 해제하거나, 그 반대의 경우가 발생하면 이중 해제나 누수가 발생합니다.
Box::into_raw와 Box::from_raw를 쌍으로 사용하거나, C의 malloc/free와 Rust의 alloc을 혼용하지 않도록 합니다.
FFI 함수는 #[no_mangle]과 extern "C"로 노출하며, panic 전파를 차단해야 합니다.
std::panic::catch_unwind로 FFI 핸들러 낸부를 감싸고, panic 발생 시 정의된 에러 코드를 반환합니다.
panic이 C 코드로 전파되면 undefined behavior가 발생할 수 있습니다.
콜백 패턴에서의 안전성은 특히 어렵습니다.
Rust 클로저를 C 콜백으로 전달할 때는 수명이 종료되지 않도록 보장하고, Send/Sync 요구사항을 명시합니다.
콜백 등록 시 수명이 충분히 긴 참조를 사용하거나, 전역 상태 대신 명시적인 컨텍스트 포인터를 전달합니다.
타입 매핑에서는 libc와 std::os::raw 타입을 사용하여 플랫폼 독립성을 확보합니다.
#[repr(C)]로 구조체 레이아웃을 고정하고, 복잡한 타입은 opaque 포인터로 처리합니다.
C의 문자열은 CStr이나 CString으로 변환하고, UTF-8 가정을 명시적으로 검증합니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🛠 4. 실전 활용
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
네이티브 라이브러리를 감쌀 때는 반드시 -sys와 safe 크레이트를 분리 설계합니다.
FFI 함수 낸부에서 catch_unwind로 panic을 차단하고, 에러 코드로 변환합니다.
C에서 전달된 포인터는 NonNull로 검증하고, RAII 래퍼로 수명을 관리합니다.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ 5. 정리
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FFI는 Rust의 안전 경계를 넘어서는 위험하지만 불가피한 영역입니다.
sys/safe 분리, 명시적 계약, panic 차단, RAII가 안전한 FFI의 4대 기둥입니다.
가능한 한 자동 바인딩 도구를 사용하고, 수동 FFI는 최소한의 경계에서만 다루세요.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔗 출처 링크
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
원문: https://doc.rust-lang.org/nomicon/ffi.html
FFI Best Practices: https://doc.rust-lang.org/nomicon/ffi.html
#Rust #FFI #BestPractices #Unsafe #Interop #MemorySafety #번역

오뉴노노 님의 최근 댓글
ㅋㅋㅋㅋㅋ 2019 01.14 잘 읽었습니다 2018 12.30 포인트가 없어서 아직 시작을 못하고있는데요! 글은 잘 읽었습니다! 포인트 쌓고 도전할거에요 2018 12.30