인프라 하다 보면 결국 "격리를 어디까지, 어떤 비용으로 걸 것인가"라는 질문으로 수렴한다. 컨테이너 격리, VM 격리, 네임스페이스, seccomp… 다 이 문제다. 그런데 이 격리 경계를 OS 커널 자체로 내려서 생각하면 마이크로커널 이야기가 나온다.
최근 GeekNews에 올라온 "현대 하드웨어 시대에 마이크로커널을 다시 검토해야 할지도" 글이 재밌었던 건, 과거 성능 때문에 접었던 아키텍처를 IOMMU·공유 메모리 같은 요즘 하드웨어 기준으로 다시 계산해보자는 논지였기 때문이다. 실무자 입장에서 이게 헛소리인지 진짜 검토할 만한지 정리해봤다.
1. 도입: 왜 지금 이 얘기가 다시 나오나
먼저 용어 정리부터. 마이크로커널과 모놀리식 커널의 차이는 "무엇을 커널 특권 모드(ring 0)에 넣느냐"다.
- 모놀리식 커널 (Linux, 기존 BSD): 스케줄러, 메모리 관리, 파일시스템, 네트워크 스택, 그리고 수천 개의 디바이스 드라이버까지 전부 커널 공간에 있다. 빠르다. 대신 드라이버 하나가 널 포인터 하나 잘못 건드리면 커널 패닉으로 시스템 전체가 죽는다.
- 마이크로커널 (seL4, QNX, Fuchsia의 Zircon): 커널에는 스케줄링, IPC(프로세스 간 통신), 기본적인 메모리/주소공간 관리 정도만 남긴다. 파일시스템, 네트워크, 드라이버는 전부 사용자 공간 프로세스로 뺀다.
왜 지금 화제냐면, 우리가 요즘 인프라에서 하는 짓이 사실 이 방향이기 때문이다. CrowdStrike 사태 기억하는가? 커널 드라이버 하나의 잘못된 설정 파일 때문에 전 세계 Windows가 부팅 불가 상태로 죽었다. 원문에서도 지적한다 — Windows가 마이크로커널이었다면 그 버그는 "일부 보안 담당자의 텔레메트리 수집만 멈추는" 정도로 끝났을 수 있다고. 드라이버가 사용자 공간에 있었다면 죽어도 프로세스만 죽지 커널은 안 죽으니까.
2. 핵심: 동작 원리를 예시로
과거에 왜 느렸나 — 문맥 전환 지옥
마이크로커널이 90년대에 망한 이유는 단순하다. 드라이버가 사용자 공간에 있으니, 디스크 한 번 읽으려면:
- 앱 → 시스템 호출 → 커널 (문맥 전환 1회)
- 커널 → 파일시스템 서버 프로세스로 IPC (문맥 전환 2회)
- 파일시스템 서버 → 디스크 드라이버 프로세스로 IPC (문맥 전환 3회)
- 다시 역순으로 데이터 복사하며 돌아옴
모놀리식이면 시스템 호출 한 번으로 끝날 일에 문맥 전환과 메모리 복사가 줄줄이 붙는다. Mach 커널이 이 문제로 결국 드라이버를 커널 안으로 다시 넣으면서 "사실상 모놀리식"이 됐다는 게 유명한 교훈이다.
IOMMU와 공유 메모리가 바꾼 것
핵심 아이디어는 이거다. "매번 커널을 거치지 말고, 드라이버 프로세스가 하드웨어에 직접 접근하되 IOMMU로 그 범위를 하드웨어 수준에서 가둔다."
IOMMU(Intel VT-d, AMD-Vi)는 원래 VM에 물리 디바이스를 직접 붙일 때(PCI passthrough) 쓰는 물건이다. 디바이스가 볼 수 있는 메모리 주소를 하드웨어가 제한해준다. 이걸 마이크로커널에 쓰면, 사용자 공간 드라이버가 폭주해도 IOMMU가 허용한 메모리 영역 밖은 건드리지 못한다.
여기에 공유 링 버퍼 기반 비동기 IPC를 얹는다. GPU 드라이버가 쓰는 방식과 똑같다 — 커맨드 큐를 공유 메모리에 두고, 시작/끝 포인터만 원자적 CAS(compare-and-swap)로 갱신하면 문맥 전환 없이 메시지를 주고받는다. 코어가 충분하면 수신자가 다른 코어에서 이미 돌고 있으니 문맥 전환 자체가 안 일어난다.
이 구조는 사실 낯설지 않다. 리눅스의 io_uring이 정확히 같은 발상이다. 공유 링 버퍼(SQ/CQ)에 요청을 쌓아두고 배치로 처리해서 시스템 호출 빈도를 낮춘다. 지금 리눅스에서 io_uring 링 상태를 직접 확인해볼 수 있다.
# io_uring을 쓰는 프로세스가 있는지 확인
$ sudo ls -la /proc/$(pgrep -n your_app)/fd | grep io_uring
lrwx------ 1 root root 64 Feb 10 14:22 12 -> anon_inode:[io_uring]
# 커널이 io_uring을 지원하는지 (5.1+)
$ uname -r
6.5.0-27-generic
# io_uring 관련 시스템 호출이 seccomp 등으로 막혀있는지 확인
$ grep -i io_uring /proc/$(pgrep -n your_app)/status
Seccomp: 2
Seccomp_filters: 1
포인트는, "링 버퍼로 배치 처리해서 문맥 전환을 줄인다"는 마이크로커널의 성능 해법이 이미 모놀리식 리눅스 안에도 들어와 있다는 거다. 원문 댓글에서 누군가 지적했듯 — readdir()/stat()을 파일마다 호출하는 POSIX식 워크로드는 마이크로커널이 불리하지만, io_uring 같은 배치 API로 가면 IPC 지연이 큰 약점이 아닐 수 있다.
3. 실무 관점: 트레이드오프와 흔한 함정
냉정하게 보는 성능 현실
희망적인 이론과 별개로, 원문 댓글의 실무자 증언들이 아주 정직하다. 요약하면:
- QNX: "빠른 마이크로커널"로 유명하지만 실제로 써본 사람은 "빠르지 않았다"고 함. FireWire 영상 처리를 QNX로 우아하게 짰는데 처참하게 느렸고, 같은 걸 리눅스 DMA 드라이버로 12시간 만에 붙였더니 성능이 확 올랐다는 경험담.
- seL4 + Genode: 리눅스 VM을 부팅해봤더니 32비트만 되고, 절반 부팅하는 데 수 분 걸렸다는 증언. 그래서 실제로 쓸 만한 NOVA microhypervisor 포크가 기본 플랫폼이 됐다고.
- 결론적 정서: "데이터 이동 비용이 한 자릿수(10배 이상) 줄지 않으면 경쟁력 확보가 어렵다."
즉, IOMMU와 공유 메모리로 정상 경로(happy path)에서 문맥 전환을 없앨 수 있다는 건 맞지만, 그건 "코어가 충분하고, 워크로드가 배치 친화적일 때"라는 전제가 붙는다. 지연에 민감한 동기 워크로드에선 여전히 불리하다.
흔한 함정 ① — IOMMU가 꺼져 있다
드라이버 격리를 하드웨어로 하려면 IOMMU가 켜져 있어야 하는데, 이게 BIOS/펌웨어와 커널 파라미터 양쪽에서 활성화돼야 한다. VFIO passthrough 세팅해본 사람은 다 겪는 함정이다. IOMMU가 꺼진 상태에서 디바이스를 vfio-pci에 바인딩하려 하면 이런 걸 만난다:
$ sudo dmesg | grep -i -e DMAR -e IOMMU
[ 0.000000] DMAR: IOMMU enabled
# 만약 아래처럼 나오면 커널 파라미터가 빠진 것
[ 0.000000] DMAR: IOMMU disabled
# vfio 바인딩 시도 시 그룹이 없다고 뜨는 전형적 에러
$ echo 0000:01:00.0 > /sys/bus/pci/drivers/vfio-pci/bind
bash: echo: write error: No such device
# dmesg에 함께 찍히는 메시지
vfio-pci: probe of 0000:01:00.0 failed with error -22
해결은 커널 부팅 파라미터에 IOMMU를 켜주는 것이다.
# Intel CPU
$ sudo vim /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on iommu=pt"
# AMD CPU
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash amd_iommu=on iommu=pt"
$ sudo update-grub
$ sudo reboot
# 재부팅 후 IOMMU 그룹이 잡히는지 확인
$ for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf 'IOMMU Group %s: ' "$n"
lspci -nns "${d##*/}"
done | head -5
IOMMU Group 0: 00:02.0 VGA compatible controller [0300]: Intel ...
IOMMU Group 1: 00:14.0 USB controller [0c03]: Intel ...
IOMMU Group 13: 01:00.0 VGA compatible controller [0300]: NVIDIA ...
여기서 IOMMU 그룹이 하나로 뭉쳐 나오는 것도 함정이다. 같은 그룹에 묶인 디바이스는 통째로만 격리·패스스루가 가능하다. 마이크로커널이든 VM이든, 격리 단위가 하드웨어 IOMMU 그룹 경계에 발목 잡히는 건 실무에서 자주 만나는 벽이다.
흔한 함정 ② — "격리했으니 안정적"이라는 착각
원문 댓글에서 가장 날카로운 지적. 리눅스가 모든 드라이버를 트리 안에 넣는 진짜 이유는 "안정적인 out-of-tree 커널 모듈 ABI가 없기 때문"이지, 마이크로커널이라야만 이걸 해결하는 게 아니라는 것. 마이크로커널로 가도 내부 API의 불안정성은 그대로다. 단지 그 불안정한 경계가 프로세스 경계를 넘나들 뿐이다.
즉 "사용자 공간으로 뺐으니 모듈성이 좋아진다"는 자동으로 성립하지 않는다. 인터페이스 계약(ABI)을 안정적으로 유지하는 건 여전히 사람이 하는 설계 문제다.
대안: 리눅스는 이미 반쯤 마이크로커널로 가고 있다
실무 인프라 엔지니어라면 굳이 seL4로 갈아탈 게 아니라, 리눅스가 격리를 흡수하는 방식을 아는 게 훨씬 실용적이다.
- 사용자 공간 드라이버 프레임워크:
uio,vfio로 이미 드라이버를 사용자 공간에서 돌릴 수 있다. DPDK, SPDK가 이걸로 네트워크/스토리지를 커널 우회해서 처리한다. - eBPF: 커널에 코드를 넣되 검증기(verifier)로 안전성을 강제한다. "커널 확장의 공격 표면을 줄인다"는 목표가 마이크로커널의 격리 철학과 통한다. 커널 재부팅 없이 로직을 넣고 뺄 수 있다는 점에서 CrowdStrike 같은 사고의 완화책이기도 하다.
- io_uring: 앞서 본 배치 IPC. 시스템 호출/문맥 전환 빈도 자체를 낮춘다.
eBPF 검증기가 실제로 어떻게 코드를 거부하는지 보면 "격리를 위해 성능/자유도를 포기한다"는 트레이드오프가 눈에 보인다.
# 안전하지 않은 eBPF 프로그램 로드 시도 시 verifier가 거부하는 전형적 에러
$ sudo bpftool prog load ./unsafe.o /sys/fs/bpf/test
libbpf: prog 'handle_tp': BPF program load failed: Permission denied
libbpf: prog 'handle_tp': -- BEGIN PROG LOAD LOG --
0: R1=ctx() R10=fp0
; int handle_tp(void *ctx) @ unsafe.c:5
0: (b7) r2 = 0
1: (85) call bpf_probe_read#4
R1 type=scalar expected=fp
processed 2 insns (limit 1000000)
-- END PROG LOAD LOG --
libbpf: failed to load program 'handle_tp'
Error: failed to load object file
이게 마이크로커널 철학의 리눅스식 구현이다. "신뢰할 수 없는 코드를 특권 영역에 넣되, 그 범위를 강제로 제한한다." 접근 방식만 다를 뿐 목표는 같다.
4. 정리: 한 줄 요약과 판단 기준
한 줄 요약: IOMMU와 공유 링 버퍼 덕분에 마이크로커널의 옛 성능 약점이 상당 부분 해소될 여지가 생겼지만, 데이터 이동 비용이 극적으로 줄지 않는 한 범용 데스크톱/서버에서 리눅스를 밀어낼 만큼은 아직 아니다.
누가 언제 쓰나:
- 마이크로커널이 유리한 곳: 안전성 인증이 필수인 임베디드/항공/자동차, 공격 표면을 극단적으로 줄여야 하는 보안 크리티컬 시스템(seL4는 형식 검증까지 된다). 구성이 고정적이고 워크로드가 예측 가능한 환경.
- 여전히 모놀리식이 답인 곳: 일반 서버 인프라, 다양한 하드웨어를 굴려야 하는 클라우드, 지연에 민감한 동기 워크로드.
- 인프라 엔지니어의 실전 결론: seL4로 갈아탈 일은 당장 없다. 대신 "격리는 공짜가 아니다"라는 원칙을 컨테이너/VM 설계에 그대로 적용하라. 격리 경계를 하나 그을 때마다 문맥 전환·데이터 복사 비용이 붙는다. 그래서 io_uring, eBPF, VFIO 같은 배치·하드웨어 격리 기법을 아는 게 실무에선 마이크로커널 논쟁보다 백 배 유용하다.
마지막으로 원문 댓글의 뼈아픈 문장 하나. "리눅스가 지배적이 된 데는 순수 기술 외의 요인도 컸다." 아키텍처가 우아하다고 이기는 게 아니다. 생태계와 드라이버 지원, 개발자 규모가 이긴다. 마이크로커널은 30년째 이 벽 앞에 서 있다.
참고 자료
- 현대 하드웨어 시대에 마이크로커널을 다시 검토해야 할지도 모름 (GeekNews)
- seL4 Microkernel 공식 사이트
- Fuchsia Zircon 커널 문서
- Linux VFIO 공식 문서 (사용자 공간 디바이스 접근)
- Lord of the io_uring (io_uring 가이드)
- eBPF 공식 소개
- Microkernel — Wikipedia
※ 본문의 명령어 출력 예시는 환경에 따라 값이 다를 수 있습니다. IOMMU 그룹 구성, 커널 버전별 동작은 각자 환경에서 확인 바랍니다.
'Tech_News' 카테고리의 다른 글
| Postgres LISTEN/NOTIFY는 확장 안 된다는 편견, 배치 버퍼링으로 초당 6만 건까지 뚫는 법 (0) | 2026.07.28 |
|---|---|
| 보안 카메라 펌웨어에서 GitHub 관리자 토큰이 나왔다 — 시크릿 유출은 왜 반복되는가 (0) | 2026.07.26 |
| 과제형 면접 ZIP을 열었더니 .git/hooks에 악성코드가 심어져 있었다 (0) | 2026.07.25 |
| Passkey는 왜 엔지니어인 우리조차 헷갈리는가: FIDO2/WebAuthn 실무 도입기 (0) | 2026.07.24 |
| AI 모델이 격리 환경을 뚫고 프로덕션에 침투했다: OpenAI-Hugging Face 사고에서 배우는 격리 아키텍처 설계 (0) | 2026.07.23 |
