
Rust와 Haskell 사이의 다리를 놓다
요즘 시스템 프로그래밍 쪽에서 Rust가 워낙 강세잖아요. 메모리 안전성과 성능을 동시에 잡았다는 평가를 받으면서 새 라이브러리들이 계속 Rust로 쓰여지고 있죠. 그런데 함수형 프로그래밍을 좋아하는 사람들이 쓰는 Haskell 입장에서는 이 좋은 Rust 라이브러리들을 활용하기가 쉽지 않았어요. 두 언어가 메모리 모델도, 타입 시스템도, 실행 방식도 다르거든요.
그래서 등장한 게 바로 Hsrs(Haskell-Rust)라는 도구예요. Rust 크레이트(라이브러리)를 보고 자동으로 Haskell에서 쓸 수 있는 바인딩 코드를 만들어주는 생성기입니다. 그것도 그냥 만들어주는 게 아니라, 타입 안전성을 지키면서 만들어준다는 게 핵심이에요.
FFI가 왜 이렇게 어려운가
FFI(Foreign Function Interface, 외부 언어 함수 호출 인터페이스)라는 게 있어요. 한 언어에서 다른 언어로 짠 코드를 부르는 다리 역할을 하죠. 예전부터 Haskell도 C 코드를 부르는 FFI는 잘 지원했어요. 그런데 문제는 Rust 코드를 직접 부를 수는 없다는 거예요. 그래서 보통 Rust 코드를 C ABI(애플리케이션 바이너리 인터페이스, 컴파일된 코드가 서로 통신하는 규약)로 노출시킨 다음, Haskell에서 그걸 C 함수처럼 부르는 우회 방식을 써야 했어요.
이게 왜 귀찮냐면, 일단 Rust 쪽에서 extern "C" 함수를 일일이 작성해줘야 하고, 복잡한 타입(예: Vec<String>, Option<T>, 트레이트 객체 같은 것들)은 C로 표현할 수가 없으니 단순화해서 넘겨야 해요. 그러면서 메모리 소유권 문제도 신경 써야 하죠. Rust에서 만든 객체를 Haskell이 들고 있다가 잘못된 시점에 해제하면 바로 크래시예요. 또 Haskell 쪽에서는 그 C 함수를 foreign import ccall로 다시 선언해주고, 타입 변환 코드도 짜야 해요. 한 함수 부르려고 양쪽에 보일러플레이트가 잔뜩 생기는 거죠.
Hsrs가 하는 일
Hsrs는 이 지긋지긋한 작업을 자동화해줘요. Rust 크레이트의 API를 분석해서, Rust 쪽 래퍼 코드와 Haskell 쪽 바인딩 코드를 동시에 생성해요. 사용자는 어떤 함수와 타입을 노출할지 선언만 하면 되고, 나머지 변환 로직은 도구가 알아서 만들어줘요.
핵심은 "타입 안전"이라는 부분이에요. 단순히 모든 걸 Ptr이나 raw 포인터로 던지는 게 아니라, Rust의 타입을 최대한 Haskell의 타입 시스템으로 옮겨와요. 예를 들어 Rust의 Result<T, E>는 Haskell의 Either E T로 매핑하고, Option<T>는 Maybe T로 옮기는 식이죠. 두 언어 다 강한 타입 시스템을 자랑하는데, 그 강점을 양쪽 모두에서 살리겠다는 거예요.
메모리 관리도 신경 썼어요. Rust 객체를 Haskell에서 들고 있을 때는 ForeignPtr로 감싸서 GC(가비지 컬렉터)가 적절한 시점에 Rust의 drop을 호출하도록 연결해줘요. 이렇게 하면 메모리 누수도, 이중 해제도 막을 수 있죠.
비슷한 시도들과 비교하면
언어 간 바인딩 자동 생성 도구는 새로운 개념이 아니에요. 가장 유명한 건 SWIG인데, C/C++ 라이브러리를 여러 스크립트 언어(Python, Ruby, Lua 등)에서 쓸 수 있게 해주는 거대한 도구죠. bindgen은 반대로 Rust에서 C 헤더를 읽어 Rust 바인딩을 만드는 도구고요. cbindgen은 Rust에서 C 헤더를 생성해주죠.
Hsrs는 이 흐름의 "Rust → Haskell" 버전이에요. 특이한 건 두 언어 다 함수형/대수적 타입 시스템을 갖고 있어서, 단순히 C ABI를 거치는 게 아니라 타입 의미를 보존하면서 옮길 수 있다는 점이에요. 비슷한 시도로는 Python에서 Rust를 쓰는 PyO3, JavaScript에서 Rust를 쓰는 wasm-bindgen, Ruby에서 Rust를 쓰는 Magnus 같은 게 있어요. 다 각 언어 생태계에 맞게 Rust를 끌어다 쓰는 방향이죠.
한국 개발자에게 주는 시사점
솔직히 Haskell을 실무에 쓰는 한국 회사는 손에 꼽아요. 그래서 Hsrs를 당장 업무에 쓸 분은 많지 않을 거예요. 하지만 "언어 간 바인딩을 어떻게 자동화하는가"라는 문제 자체는 모든 개발자에게 의미가 있어요.
예를 들어 여러분이 Node.js나 Python 프로젝트에서 "이 특정 부분만 Rust로 다시 짜서 성능을 올리고 싶다"는 상황을 만난다면, NAPI-RS나 PyO3 같은 도구를 쓰게 될 거예요. 그때 Hsrs 같은 프로젝트의 설계를 미리 봐두면 "아, 이런 식으로 메모리를 관리하는구나", "이런 타입 매핑은 이렇게 풀어내는구나" 하는 감이 생겨요.
또 한국에서도 시스템 프로그래밍에 Rust를 쓰는 회사가 늘고 있어요. 카카오, 네이버, 토스 같은 곳에서 부분적으로 도입 중이죠. 기존 코드베이스(Java, Kotlin, Go 등)와 Rust를 연결하는 일이 점점 많아질 텐데, 그때 이런 "바인딩 생성기" 패턴이 큰 도움이 될 거예요.
마무리
Hsrs는 작아 보이지만, "서로 다른 언어 생태계를 어떻게 안전하게 잇는가"라는 큰 질문에 한 가지 답을 제시하는 프로젝트예요. 여러분이라면 현재 쓰는 언어와 Rust 사이에 다리를 놓고 싶은 부분이 있나요? 어떤 종류의 라이브러리를 끌어다 쓰고 싶으세요?
🔗 출처: Hacker News
"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"
실제 수강생 후기- 비전공자도 6개월이면 첫 수익
- 20년 경력 개발자 직강
- 자동화 프로그램 + 소스코드 제공