Native AOT에 관한 두 가지 이야기

Native AOT에 관련된 내용을 요즈음 계속 살펴보면서 알게 된 내용 두 가지를 정리해봤습니다.

Native Export를 만들긴 했는데 C 언어 개발자에게는 어떻게 이야기하지?

Native AOT가 드디어 크로스 컴파일에 관한 부분을 제외하면 완성형에 가깝게 되었습니다. 정말 감격스러운 일이죠! 다만 생각해보니, 바이너리만 만들었지 실제로 C 언어 개발자에게 어떻게 전달해야 하는지가 missing link라는 것을 나중에 깨달았습니다. 애석하게도 C# 코드에서 어떤 식으로 시그니처를 잡았는지 설명하는 것은 C 개발자 입장에서는 전혀 도움이 안되는 정보입니다.

다행히 공식 기능은 아니지만, 자동으로 C 언어용 헤더 파일을 만들어주는 추가 패키지가 있었습니다. 바로 Dnne 패키지를 사용하는 것입니다.

이 패키지를 이용해서 Native AOT로 퍼블리싱하면, Windows, Linux, macOS용 C 컴파일러에 모두 대응되는 dnne.h 헤더와 해당 프로젝트용 .h 헤더와 .c 파일까지 같이 만들어줍니다. native 디렉터리 안에서는 DLL로 빌드한 경우 .dll 파일과 .lib (혹은 플랫폼별 정적 라이브러리) 파일을 제공하므로 이것을 가져다 사용하시면 되겠습니다.

이 기능은 정적 라이브러리를 빌드하는 경우에도 동일하게 구현되므로 정적/동적 라이브러리 여부나 OS 종류, CPU 아키텍처에 상관없이 일관성있는 지원을 받을 수 있습니다. 이를 통해 C#을 사용하면서도 직접 네이티브 프로그래밍을 할 수 있는 완전한 기술 스택을 갖추게 됩니다.

정적 라이브러리로 만들어진 Native AOT 바이너리에 관한 제한 사항

닷넷으로 네이티브 바이너리를 만들어낼 수 있게 된 것이 극히 최근의 일인지라 아마 여기까지 도달하는 경우는 흔치 않을 것 같습니다만, 아쉽게도 정적 라이브러리로 링킹하는 경우 AppDomain, 가비지 컬렉터, 그리고 닷넷 측 Native AOT 심볼이 겹치는 관계로 닷넷으로 만든 Native AOT를 정적 링크하는 경우는 같은 방식으로 만들어진 정적 라이브러리 단 1개만 링킹이 가능하다는 큰 제약 사항이 있습니다. (물론 다른 방식으로 만들어진 정적 라이브러리의 링킹은 아무 지장 없습니다.)

사실 이는 내장 런타임을 정적 링크 방식으로 연결하려 할 때 벌어지는 내장 런타임의 다이아몬드 의존성 문제 (여러 라이브러리가 동일한 런타임의 독립적인 복사본을 각각 포함하여 심볼이 충돌하는 문제) 에 딱 걸린 부분이고, Go와 Rust에서도 비슷한 문제가 있는 것으로 알려져 있습니다.

그렇다고는 하더라도, Native AOT로의 대장정에 마침표를 찍은 기분이라 너무 좋습니다. :blush:

6개의 좋아요

덤으로, AOT 기능을 고려해서 충실히 대비하셨다면 이제 아래 커밋과 같은 형태로 C 언어용 동적/정적 라이브러리 프로젝트를 별도로 추가하는 것도 충분히 가능합니다.

pythonnet 특유의 불친절함에 질려서 Native AOT 지원까지 고려해서 만든 새로운 파이썬 래퍼인 dotnetpy가 Native AOT를 지원하도록 되어있는 덕분에, 여기까지 쉽게 올 수 있었습니다.

그래서 닷넷을 전혀 설치하지 않은 PC에서 이 라이브러리 파일 하나만 가지고 venv, uv 혹은 파이썬 런타임과 직결해서 C, C++, Rust 등의 여러 프로그래밍 언어가 이 라이브러리를 참조하는 Lingua Franca 모델을 구현할 수 있지 않을까? 하는 재미있는 상상을 해봤습니다. :smiley: (물론 테스트는 더 해봐야 합니다. ㅎㅎ)

3개의 좋아요

그리고 또 다른 실질적인 예시 하나를 더 추가했습니다.

NativeSdk Tech Demo · GitHub

2개의 좋아요

뭔가 연구를 하면 언리얼이나 유니티 같은 게임 엔진에서 닷넷 서버를 호출할때 호출부를 만들어줘야 할 때가 있는데 그럴 때도 써먹을 수 있을 듯합니다