요약
Embedded Swift로 운영체제 없이 QEMU에서 부팅해 글자를 주고받는 최소 커널을 만들었습니다.
개발자 앙토냉이 운영체제 없이 프로그램이 돌려면 무엇이 필요한지 배우려고 시작한 실험입니다. 10년쯤 전 비슷한 시도를 했던 그는 이번에 Swift로 64비트 ARM 커널을 만들어 애플 실리콘 맥의 QEMU에서 돌렸습니다.
왜 중요한가
- 앱 개발 언어로 알려진 Swift를 베어메탈(운영체제 없이 하드웨어에서 바로 도는 환경)에도 쓸 수 있음을 보여 줍니다.
- 다만 정식 배포판 컴파일러에는 Embedded Swift 표준 라이브러리가 없어 아직은 개발 스냅샷이 필요합니다.
핵심 내용
- 어셈블리 진입점이 0번 코어만 깨워 스택을 잡은 뒤 Swift로 쓴 kernel_main 함수를 부릅니다.
- C 라이브러리가 없어서 print에 필요한 putchar와 memmove를 직접 구현했습니다.
- 입출력은 QEMU virt 보드의 PL011 UART(직렬 통신 장치) 레지스터에 값을 직접 읽고 씁니다.
- Swift 함수를 C 이름으로 내보낼 때는 독자 제안에 따라 @_cdecl 대신 새 @c 속성을 썼습니다.
- 결과물은 인사말을 찍고 입력을 그대로 돌려주지만, 글자마다 계속 확인하는 폴링 방식이라 비효율적이라고 밝혔습니다.
HN 반응
- Embedded Swift는 C/C++ 연동이 쉽고 런타임 부담이 없다는 호평과 함께, 커널보다는 헬로 월드에 가깝고 진짜 어려운 건 드라이버라는 지적이 나왔습니다.
- AI 덕분에 새 운영체제 설계 실험이 늘 것이라는 기대에, 리눅스에 쌓인 작업은 쉽게 대체할 수 없다는 반론이 맞섰습니다.
Embedded Swift는 솔직히 정말 멋집니다. 저는 Swift 자체를 제대로 써 본 적은 없지만, 임베디드 개발에는 새로운 도구가 하나쯤 더 있어도 좋고 언어도 꽤 괜찮으니 좋은 틈새라고 생각합니다. 게다가 Swift에 대해 사람들이 오래전부터 지적해 온 문제들(크로스 플랫폼, 느린 컴파일 등)도, 규모가 워낙 작아서 적어도 제게는 거의 해당되지 않는 것 같습니다. :)
처음부터 시작한다면 거의 모든 것(리셋 벡터, 컴파일러가 내보내는 인트린식 등)을 Swift로 꽤 쉽게 작성할 수 있다는 걸 알게 됐습니다. 하지만 그보다 더 좋은 점은 C/C++ 연동이 아주 잘 되고 기본으로 제공된다는 것입니다. 그래서 양방향으로 도입하기가 쉽습니다. 저는 시뮬레이터용 작은 부트 펌웨어를 짜면서, 재미 삼아 부트 과정에 서명 검증(mldsa44+jq255)을 넣어 봤습니다. .c와 .h 파일을 그대로 복사해서 modulemap 파일로 가져오기만 하면 바로 쓸 수 있습니다. 단순한 .o 파일이 만들어지니 링커에 넘기면 됩니다. 직접 구현해야 하는 "freestanding" 함수도 4~5개뿐입니다. 힙 할당도 끌 수 있고요. 등등.
이 방법을 쓰면 예컨대 Zephyr나 U-Boot 드라이버 같은 것도 Swift로 작성하는 게 꽤 멋지고 쉬울 것 같습니다.
커널이라기보다는 헬로 월드에 가깝네요.
그냥 레지스터에 값을 때려 넣는 거죠! 정말 좋네요, 완전 옛날 방식이에요!
사실 DMA가 나오기 전에는 많은 시스템에서 I/O가 그렇게 동작했거든요. 좋은 시절이었죠!
지금도 전부 이렇게 돌아갑니다
글쎄요, 요즘 장치와의 상호작용은 대부분 "명령 목록과 공유 메모리 버퍼를 만든다"는 식이지, 데이터 플레인 작업을 하려고 레지스터를 잔뜩 건드리는 고전적인 방식이 아닙니다. UART는 옛 방식이 남아 있는 마지막 보루 중 하나인데, 디버그 출력을 위해 부팅 과정 초반부터 필요하다 보니 공유 메모리나 명령 목록 방식을 쓰지 않는 편이 편하기 때문입니다.
그렇긴 해도 마이크로컨트롤러의 UART에서도 그런 경우를 본 적이 있습니다. 쓰이지도 않을 수 있는 UART에 FIFO 블록 RAM이 면적을 차지하는 걸 피하려는 겁니다. 그런 곳에서는 UART 안에 최소한의 스테이징 버퍼만 두고, 꽤 유연하게 설정할 수 있는 DMA 컨트롤러로 대신 공용 메인 RAM을 쓰게 합니다.
이런 시도가 앞으로 훨씬 더 많아질 거라고 봅니다. 데스크톱을 뺀 컴퓨팅 영역을 UNIX 커널이 오랫동안 장악해 온 건 설계가 뛰어나서라기보다 소스 코드가 공짜로 딸려 와서 편했기 때문입니다. 이제는 AI 덕분에 실험하기가 아주 쉬워졌으니, OS와 프레임워크 설계에서 새로운 탐색의 시대가 열리길 바랍니다. Omarchy에서 이미 그 시작이 보이긴 하지만 아직은 걸음마 수준이고 가장 밑바닥 계층을 겨냥한 것도 아닙니다. NT, XNU, SeL4, Linux의 뚜렷한 차이만 봐도 밑바닥에서 차별화할 여지는 충분하고, (SeL4를 빼면) 이들이 여전히 서로 꽤 비슷한 건 상업적 압력 때문입니다.
반론을 하나 들자면, 너무 많은 것을 뭉뚱그려서 일반화하고 계십니다. 구체적으로 보면 예컨대 Linux 커널을 원하는 언어로 만든 AI 프로젝트로 그리 간단히 갈아 끼울 수는 없습니다. Linux 커널과 그 설계에는 엄청난 노력이 들어갔고, "UNIX 커널"이라는 겉모습 아래에 있는 기반은 대충 넘길 수 있는 수준이 아닙니다. Linux가 마주한 문제는 C 같은 위험한 언어를 쓰거나 조잡하고 낡은 UNIX 인터페이스와 관습을 쓰는 데서 오는 문제를 훨씬 넘어섭니다(물론 그것도 포함하지만요).
물론 독창적인 방향으로 시도해 볼 수는 있습니다. 하지만 Linux에 들어간 엄청난 노력, 그러니까 우리가 상상도 못 할 대부분의 문제를 이미 해결해 놓은 그 노력을 무시하고 있는 겁니다. AI는 그 문제들을 다시 풀겠다고 시간과 토큰을 잔뜩 태울 텐데, 사람이 상당히 똑똑하게 개입해 주지 않으면 결과도 형편없을 겁니다.
새 프로젝트를 만들어 내기보다는 기존 오픈 소스를 가지고 실험하는 사람이 더 늘어날 가능성이 크다고 봅니다. 이런 새 프로젝트들은 쉽게 생겼다가 쉽게 사라지니까요.
커널이 해결한 까다로운 문제는 대부분 하드웨어의 별난 동작과 관련된 것이고, AI는 기존 드라이버 소스를 참고 자료로 쓰면 됩니다.
저도 같은 생각입니다. OS 덕후인 저는, 컴퓨팅 시스템이 대부분 UNIX/POSIX 대 Windows 구도로 굳어지기 전의 다양성이 그립습니다.
이제는 WSL이 갈수록 중요해지고 있고(MXC, Windows Server 2025, Windows IoT Enterprise), Windows는 UNIX 서브시스템을 얹은 DEC, IBM, 유니시스 메인프레임(마이크로컴퓨터)과 점점 닮아 가고 있습니다[0].
그러니 OS 분야에는 정말로 새로운 아이디어가 필요합니다.
모바일 쪽에는 대안적인 접근이 일부 있지만, 대부분은 UNIX 커널을 그대로 둔 채 사용자 영역만 갈아엎는 방식입니다.
[0] - 네, Windows NT에도 어떻게든 있긴 했지만, 그게 얼마나 성의 없었는지는 다들 아시잖아요.
언젠가 시간이 나면 GraalVM으로 Singularity 스타일의 단일 주소 공간 OS를 만들어 보고 싶습니다. 다만 완전히 가비지 컬렉션이 되는 통합 힙을 쓰는 방식으로요. 예전에는 여러 이유로 현실성이 없었지만 지금은 풀 수 있다고 생각합니다.
그렇게 되면 오버헤드가 정말 많이 사라지고, 훨씬 더 나은 API를 설계할 수 있습니다.
(> 예전에는 현실성이 없었지만)
비르트는 적어도 두 번은 해냈습니다. Medos-2(1983)와 이후 여러 갈래의 Oberon System으로요.
요즘 시대에는 과제가 다릅니다. Spectre 같은 공격, 장애 영역(failure domain)을 정의하는 일, GC 일시 중지를 격리하는 일 같은 것들이요. 그걸 해낼 기술은 이미 있지만, 1983년에는 없었습니다.
맞아요, 1980년에는 대단해 보였겠지만 2026년에 OS에 기대하는 수준에는 못 미칩니다.
"Eric Bier Demonstrates Cedar"
https://www.youtube.com/watch?v=z_dt7NG38V4
동의합니다. 저는 실제로 Claude를 써서 유명한 커널 몇 개를 (OCaml로) 다시 짜 봤습니다. https://github.com/aryx/IX/tree/main/kernels 에 xv6, plan 9, oberon, singularity, 그리고 베어 메탈에서 도는 Squeak가 있습니다. 이제 OS 설계를 실험하기가 그만큼 쉬워졌습니다.
Embedded Swift가 런타임 부담 없이 freestanding ARM을 대상으로 삼을 수 있음을 보여 주는 좋은 개념 증명입니다.
커널은 이미 수십, 수백 개가 있어요. 만드는 거 자체는 어렵지 않으니까요.
진짜 도전을 하고 싶다면 드라이버를 만들어 보세요.
“machine emulators for hackers”
(“해커를 위한 머신 에뮬레이터”)
“Hack the Planet!”? “Mess with the best die like the rest”? 뭐야 이게?
1995년 영화 "Hackers"를 가리키는 말들입니다.
aarch64가 목표이니 "RISC 아키텍처가 모든 걸 바꿀 거야" 같은 대사를 넣을 기회도 놓쳤네요.
그러게요. “RISC is good.”(“RISC가 좋아.”)
1995년 영화 Hackers요.
이게 가짜와 진짜 프로그래머를 가려내는 대표적인 예입니다.
영화 HACKERS를 안 보고 어떻게 프로그래밍을 시작할 수 있죠? 컬트 고전인데요.
그리고 Wargames도요. 아, Antitrust도요.
끔찍하네요. 진짜로요. "while true:" 때문에 CPU를 100%나 씁니다.