리눅스 없이 만든 구글의 운영체제, Fuchsia

2021년 5월, 누군가의 부엌 선반 위에 놓인 Google Nest Hub가 평범한 업데이트를 하나 받고 재부팅되더니, 완전히 다른 운영체제로 돌아왔습니다. 홈 화면도 그대로, 사진 액자도 그대로, 알람도 그대로였습니다. 다만 그 아래에 있던 Linux 커널이 사라졌을 뿐입니다.

제가 계속 곱씹게 되는 지점은 여기입니다. Fuchsia가 얼마나 야심찬 프로젝트인지가 아니라, 구글이 이미 팔려 나간 소비자 기기의 운영체제를 통째로 갈아 끼웠는데 그 사실을 알아챈 사람은 설정의 기술 정보 화면을 들여다본 사람들뿐이었다는 것 말입니다.

저장소가 처음 발견된 이후로 커널이 궁금해서 이 프로젝트를 틈틈이 지켜봐 왔습니다. 이 글은 Fuchsia가 정확히 무엇이고, 왜 만들어졌으며, 7년 동안 무엇을 남겼는지 정리해 본 기록입니다.


아무도 발표하지 않은 7년짜리 저장소

2016년 8월, 구글의 git 서버에 fuchsia라는 저장소가 올라왔습니다. 블로그 포스트도, 보도자료도 없었고, 한 줄짜리 설명만 붙어 있었습니다. “Pink + Purple == Fuchsia (a new Operating System)”. 그게 발표의 전부였습니다. 사람들은 우연히 이 저장소를 발견했습니다.

이후 몇 년은 대략 이런 식으로 흘러갔습니다. 2017년에는 Flutter로 만든 Armadillo라는 그래픽 셸이 붙었고, 그 스크린샷이 “구글이 Android 후속작을 만들고 있다”는 증거처럼 퍼져 나갔습니다.

2017년 7월의 Fuchsia Armadillo 셸 2017년 7월의 Fuchsia Armadillo UI. 출처: Wikimedia Commons (Apache License 2.0)

2019년 Google I/O에서 Hiroshi Lockheimer는 이 프로젝트를 직접 언급하며, Fuchsia는 새로운 운영체제 개념을 실험하는 프로젝트이고 휴대폰용 OS라고 단정하지 말아 달라고 말했습니다. 같은 해에 fuchsia.dev라는 문서 사이트가 생겼고, 2020년 12월에는 공개 메일링 리스트, 공개된 로드맵, 이슈 트래커, 그리고 설계 결정을 다루는 RFC 프로세스까지, 제대로 된 오픈 소스 프로젝트의 형태를 갖추게 되었습니다.

그리고 2021년 5월, 제품에 실렸습니다. 1세대 Nest Hub가 Cast 기반 소프트웨어를 Fuchsia로 교체했고, 화면상으로는 아무것도 바뀌지 않았습니다. 2022년에는 Nest Hub Max가 뒤를 이었고, 2023년 5월부터는 2세대 Nest Hub에도 Fuchsia 빌드가 배포되기 시작했습니다.

작명은 보이는 것만큼이나 진지하지 않습니다. 커널인 Zircon의 원래 이름은 Magenta였고 2017년에 개명했습니다. Escher, Scenic, Garnet, Topaz, Starnix까지, 프로젝트 이름들은 보석 카탈로그처럼 읽히는데 그중 몇몇 계층은 이미 사라지고 없습니다.

2023년은 그리 좋은 해가 아니었습니다. 1월 구글의 전사 해고가 Fuchsia 팀을 덮쳤고, New York Times와 9to5Google은 400명 규모 조직에서 약 16%가 정리되었다고 보도했습니다. 7월에는 Assistant 스피커 지원 코드가 트리에서 제거되면서, Fuchsia를 올리기로 했던 Nest Mini, Nest Audio, Nest Wifi가 미지원으로 표시되었습니다.

정리하면 이렇습니다. 7년 동안 개발했고, 실제로 탑재된 제품군은 셋인데 전부 스마트 디스플레이이고, 팀은 방금 줄었습니다.


그냥 리눅스를 쓰면 안 됐을까?

구글은 세상 누구보다도 Linux를 많이 굴리는 회사입니다. Android도, Chrome OS도, 검색 결과를 내려주는 서버들도 전부 Linux입니다. 그런 위치에서 커널을 새로 쓴다는 건 꽤 이상한 선택이므로, 이 질문은 진지하게 따져볼 만합니다.

구글이 공개적으로 밝힌 이유는 구조적인 것들이고, 프로젝트가 내건 원칙에 그대로 드러납니다. 단순할 것, 안전할 것, 업데이트 가능할 것, 성능이 나올 것. 각각은 지금의 방식에 대한 구체적인 불만과 짝을 이룹니다.

첫 번째는 업데이트입니다. Android가 평생 싸워 온 문제죠. 기기는 커널과 벤더 BSP, 그리고 트리 밖 드라이버 더미를 함께 싣고 출시되고, 버전을 올리려면 OEM이 그 스택 전체를 다시 빌드하고 다시 인증받아야 합니다. 2017년의 Project Treble과 2019년의 Project Mainline은 이미 굳어 버린 스택에 뒤늦게 이음매를 내려는 시도였습니다. Linux는 여기서 도움이 되지 않는데, 이건 의도된 설계입니다. 커널은 in-kernel 드라이버 ABI를 일부러 고정하지 않습니다. 드라이버는 트리 안에 있어야 나머지 코드와 함께 고칠 수 있다는 입장이죠. 공학적으로 방어 가능한 입장이면서, 동시에 3년 된 휴대폰이 멈춰 있는 이유이기도 합니다.

두 번째는 보안입니다. Unix 프로세스는 요청한 적도 없는 권한을 쥐고 시작합니다. 파일 시스템 전체가 보이고, /proc을 돌아다닐 수 있고, 무언가를 허용해 주는 user ID를 달고 있습니다. 그래서 우리는 namespace, cgroup, seccomp, SELinux, 컨테이너를 동원해 그 권한을 도로 회수하는 데 엄청난 노력을 씁니다. Fuchsia의 답은 애초에 주지 않는 것입니다.

세 번째는 폼 팩터이고, 가장 덜 언급되는 이유입니다. 최초의 저장소는 신호등까지 포함한 온갖 기기를 언급했습니다. 터치스크린이 없는 스마트 디스플레이나 화면 자체가 없는 스피커는, 어떻게든 돌아가게 만들 수는 있어도 Android의 애플리케이션 모델이 상정한 대상은 아닙니다.

여기에 해설자들이 자주 덧붙이는 네 번째 동기가 있는데, 이건 사실이 아니라 해석이라는 점을 짚어두고 싶습니다. 많은 분석가들이 Fuchsia의 본질은 라이선스와 통제권이라고 주장해 왔습니다. Linux 커널의 GPL 의무, Android의 Java API를 둘러싼 오라클과의 긴 소송, 그리고 업데이트 파이프라인에 대해 OEM이 쥔 지렛대 말이죠. 실제로 Fuchsia는 전부 BSD, MIT, Apache 2.0이고, 구글은 자사 기기에 직접 배포합니다. 저는 업데이트 통제권 쪽 논지는 설득력이 있다고 보지만 GPL 쪽은 과장이 섞였다고 생각합니다. Android는 이미 커널 위쪽 거의 전부를 허용적 라이선스로 유지하고 있으니까요. 구글이 이런 식으로 설명한 적은 없으므로, 추론으로 받아들이시는 게 맞습니다.

Linux / AndroidFuchsia
커널 범위모놀리식. 드라이버, 파일 시스템, 네트워크 스택이 커널 안에Zircon은 스레드, 메모리, IPC, 스케줄링만. 나머지는 유저 스페이스
기본 권한Ambient. user ID, 전역 파일 시스템, /proc없음. 새 프로세스는 넘겨받은 handle만 가짐
드라이버 ABI의도적으로 불안정. 드라이버는 트리 안에 존재안정적인 드라이버 ABI가 명시적 목표. 아직 미달성
업데이트 단위벤더별 시스템 이미지패키지. 콘텐츠 해시로 resolve
IPC여러 메커니즘, 대부분 직접 만든 프로토콜하나의 IDL(FIDL), 하나의 프리미티브(channel)


Zircon

Zircon부터는 Fuchsia가 익숙한 무언가의 변주이기를 그만둡니다.

Zircon은 Travis Geiselbrecht가 만든 임베디드 커널 LK(Little Kernel)에서 갈라져 나왔고, 그 위에 프로세스 모델과 유저 모드, capability 시스템이 붙었습니다. 64비트 전용이며 자원이 넉넉한 기기에서 돌아간다고 가정하는데, LK의 목적과는 정반대인 셈입니다.

커널이 노출하는 syscall은 100개 남짓이고, 대부분 non-blocking입니다. 예외는 대기 자체가 목적인 것들뿐입니다. zx_object_wait_one, zx_object_wait_many, zx_port_wait, zx_nanosleep 정도죠. 나머지는 전부 객체 연산입니다.

여기서 ‘객체’라는 단어가 핵심입니다. Zircon은 유저 스페이스에 파일 시스템을 내보내지 않습니다. 커널 객체를 내보내고, 객체와는 handle을 통해 대화하며, handle은 권한(rights)의 집합을 함께 들고 다닙니다.

객체설명
Job / Process / Thread스케줄링과 자원의 계층 구조. Job이 Process를 품고, 제한은 트리를 따라 내려감
Channel바이트와 handle을 실어 나르는 양방향 메시지 파이프. 모든 IPC의 뼈대
VMOVirtual Memory Object. 매핑·공유·리사이즈가 가능한 메모리 덩어리
Port여러 객체의 signal을 한 번에 기다리기 위해 스레드가 머무는 곳
Event / Futex시그널링과 유저 스페이스 락 프리미티브

handle 모델의 파급 효과는 첫인상보다 큽니다. 우선 fork()가 없습니다. fork는 주소 공간 전체와 권한 집합 전체를 암묵적으로 물려받는다는 뜻이기 때문입니다. 프로세스 생성은 fuchsia.process.Launcher를 거치며, 실행 파일과 명시적인 handle 목록을 받습니다. Unix signal도 없습니다. Zircon은 객체 signal과 observer 패턴을 쓰기 때문에, 비동기 이벤트는 하던 일을 끊고 끼어드는 대신 내가 기다리기로 선택한 port로 도착합니다.

그리고 갓 만들어진 프로세스는 아무것도 가지고 있지 않습니다. 파일 시스템도, 네트워크도, 시계도, 부모도 없습니다. 생성자가 건넨 handle만 정확히 쥐고 있고, 그 밖의 것에는 손을 뻗을 수 없습니다. 뻗을 만한 ambient한 무언가가 존재하지 않으니까요.

Zircon을 마이크로커널이라고 부르는 건 절반만 맞습니다. Linux보다 훨씬 작고 드라이버와 파일 시스템을 유저 스페이스로 밀어낸 건 사실이지만, seL4 같은 의미의 최소 마이크로커널은 아닙니다. 프로젝트 문서 스스로도 커널과 핵심 유저 스페이스 서비스의 묶음이라고 설명하고 있고, syscall 표면은 순수주의자가 납득할 수준보다 훨씬 넓습니다.

flowchart TB subgraph US["User space"] direction TB APP["Components
Chromium, Cast, session UI"] SVC["System services
filesystems, netstack, package resolver"] DRV["Drivers
driver hosts, one process per group"] end KRN["Zircon
threads · virtual memory · IPC · scheduling"] HW["Hardware"] APP --> SVC SVC --> DRV US --> KRN KRN --> HW


모든 것은 컴포넌트다

Unix는 모든 것이 파일이라고 말합니다. Fuchsia는 모든 것이 컴포넌트라고 말하는데, 이 구호는 생각보다 훨씬 문자 그대로입니다.

컴포넌트는 프로그램과 매니페스트의 조합입니다. .cml 파일인 매니페스트에는 이 컴포넌트가 무엇을 필요로 하고, 무엇을 제공하며, 그것을 누구에게 넘기는지가 선언되어 있습니다. 컴포넌트는 트리를 이룹니다. 각 컴포넌트는 자식을 가질 수 있고, 어떤 컴포넌트와 그 자식들을 묶어 realm이라고 부릅니다. 트리 상의 위치는 moniker라고 하는데, 경로처럼 생겼고 실제로 경로처럼 동작합니다.

capability는 이 트리의 간선을 따라 세 가지 방식으로만 움직입니다. 컴포넌트는 필요한 capability를 use하고, 부모는 자식에게 offer하며, 자식은 부모에게 expose합니다. 네 번째 선택지도, 가서 둘러볼 레지스트리도 없습니다. 아무도 나에게 라우팅해 주지 않은 capability는, 내 입장에서는 존재하지 않는 것입니다.

{
    include: [ "syslog/client.shard.cml" ],
    program: {
        runner: "elf",
        binary: "bin/echo_server",
    },
    capabilities: [
        { protocol: "fuchsia.examples.Echo" },
    ],
    expose: [
        {
            protocol: "fuchsia.examples.Echo",
            from: "self",
        },
    ],
}

런타임에는 라우팅된 capability들이 그 컴포넌트의 namespace가 됩니다. 전역 파일 시스템을 대체하는 것이 바로 이것입니다. 프로그램 입장에서 POSIX 디렉터리 트리처럼 보이는 것은 부모가 건네준 것들로 조립된 사적인 뷰이고, 보통은 자기 패키지의 읽기 전용 콘텐츠와 약간의 사적 저장소, 그리고 몇 개의 프로토콜로 구성됩니다.

flowchart TD CORE["core
(parent realm)"] SRV["echo_server"] CLI["echo_client"] SRV -- "expose fuchsia.examples.Echo" --> CORE CORE -- "offer fuchsia.examples.Echo" --> CLI CORE -- "offer fuchsia.logger.LogSink" --> SRV CORE -- "offer fuchsia.logger.LogSink" --> CLI

이 모델을 확장 가능하게 만드는 조각이 둘 더 있습니다. runner는 컴포넌트를 실제로 실행시키는 주체이면서 그 자체가 capability입니다. ELF runner는 네이티브 바이너리를 실행하고, 다른 runner는 다른 런타임을 품습니다. resolver는 컴포넌트 URL을 매니페스트와 blob 묶음으로 바꿔 줍니다. 둘 다 교체 가능한데, 덕분에 완전히 이질적인 런타임을 커널에 특례 코드를 넣지 않고도 나중에 시스템에 얹을 수 있습니다. 이 이야기는 Starnix 절에서 다시 꺼내겠습니다.

매니페스트를 처음 읽었을 때 솔직한 감상은 ‘프로그램 하나 띄우는 데 격식이 참 많다’였습니다. 실제로 많습니다. 그 대가로 얻는 것은, 시스템 전체의 의존성 그래프가 파일에 적혀 있고 빌드가 그것을 검사하며 런타임에는 개발자의 자제력이 아니라 OS가 그것을 강제한다는 점입니다.


FIDL, 그리고 이음매가 중요한 이유

운영체제의 대부분이 유저 스페이스에 산다면, 운영체제의 대부분은 IPC입니다. 파일 시스템 접근도 IPC고, 드라이버와 대화하는 것도 IPC입니다. 그러면 인터페이스 언어는 편의 기능이기를 그만두고 사실상의 시스템 ABI가 됩니다.

그 언어가 FIDL입니다. 프로토콜을 선언하면 컴파일러가 C, C++, Rust, Dart, Go용 바인딩을 생성하고, 메시지는 Zircon channel을 타고 흐릅니다. 커널은 FIDL에 대해 아무것도 모릅니다. 바이트와 handle을 옮길 뿐이죠.

library fuchsia.examples;

@discoverable
protocol Echo {
    EchoString(struct {
        value string:64;
    }) -> (struct {
        response string:64;
    });
};

와이어 포맷은 일부러 심심하게 만들어졌습니다. 리틀 엔디언, 네이티브 정렬, 고정 레이아웃, 압축 없음, 포인터 패칭 없음. 할당 없이 제자리에서 메시지를 읽을 수 있습니다. 초당 수천 건을 처리하는 파일 시스템 서버에게는 이 결정성이 전부입니다.

제가 진짜 흥미롭다고 느낀 부분은 버저닝입니다. 컴포넌트는 target API level을 정해 빌드되고, 결과 패키지의 메타데이터에는 ABI revision이 실립니다. meta.farffx package far list를 돌리면 눈으로 확인할 수 있죠. 플랫폼은 어떤 바이너리가 어떤 계약을 기대하는지 알고 있습니다. ‘업데이트 가능할 것’이라는 원칙을 떠받치는 메커니즘이 이것입니다. 오래된 컴포넌트가 무엇에 맞춰 컴파일되었는지 플랫폼이 알 수 있다면, 나머지가 움직이는 동안에도 그 계약을 계속 지켜 줄 수 있으니까요.

이게 10년을 버틸지는 증명되지 않았습니다. 다만 실제 문제에 대한 실제 설계상의 답이기는 합니다. “전부 다시 컴파일하세요”보다는 훨씬 낫죠.


패키지와 드라이버

Fuchsia의 패키지는 파일이 아닙니다. 패키지의 identity와 콘텐츠 목록을 담은 meta.far 아카이브와 blob 묶음이고, 모든 blob은 Fuchsia Merkle Root, 즉 콘텐츠 해시로 이름 붙습니다. 서로 다른 패키지에 같은 파일이 들어 있으면 저장은 딱 한 번만 됩니다. package resolver가 컴포넌트 URL이 가리키는 것을 가져오고, package server가 신뢰의 뿌리 역할을 합니다.

여기서 유용한 성질은 hermeticity입니다. 런타임에 이름으로 resolve해서 마침 설치되어 있던 무언가를 집어 오는 일이 없습니다. subpackage는 이 성질을 한 단계 더 밀어붙입니다. 패키지가 의존성의 해시를 기록하기 때문에, 의존성이 바뀌면 부모의 해시도 함께 바뀔 수밖에 없습니다. 의존성 지옥을 resolver로 덧대는 대신 이름 짓는 층위에서 닫아 버린 셈입니다.

드라이버도 한 단계 아래에서 같은 대접을 받습니다. Fuchsia의 드라이버는 driver_manager 컴포넌트 아래 유저 스페이스의 driver host 프로세스에 로드되는 공유 라이브러리이고, 일반 프로세스보다 권한이 더 좁습니다. 드라이버는 파일 시스템에 접근할 수 없고 임의의 디바이스를 열람할 수도 없습니다. 드라이버가 죽으면 driver host가 죽고, driver manager가 수습합니다. 기계가 죽지는 않습니다.

드라이버는 프레임워크, 다른 드라이버, 시스템의 나머지와 모두 FIDL로 대화합니다. 같은 호스트에 배치된 드라이버들끼리는 driver runtime을 쓰는데, Zircon의 channel과 port 프리미티브를 프로세스 안에서 흉내 내기 때문에 커널로 넘어가지 않고도 서로 통신할 수 있습니다.

비전과 현재 상태가 가장 크게 벌어져 있는 지점이 드라이버 ABI입니다. 안정적인 드라이버 ABI는 최초의 드라이버 프레임워크 시절부터 목표였지만 2023년 현재까지 제공되지 않았고, DFv2 역시 아직 진화 중이며 ABI가 안정되지 않았다고 명시되어 있습니다. 한 번 컴파일한 드라이버가 플랫폼 버전을 건너뛰며 계속 동작한다는 약속은 여전히 약속입니다.

Google Nest Hub 아무에게도 묻지 않고 커널 교체를 겪어낸 Nest Hub. 사진: Graceoftheshire, CC BY-SA 4.0

Nest Hub 마이그레이션이 가능했던 이유도 여기에 있습니다. 구글은 새 펌웨어 이미지를 밀어 넣고 잘 되기를 빈 게 아닙니다. 그래픽 스택, Cast 런타임, 드라이버가 각각 따로 resolve되는 단위인 시스템에 패키지를 밀어 넣은 것입니다. Fuchsia를 어떻게 평가하든, 이 마이그레이션은 이 모델이 무언가를 해낸다는 가장 강한 증거입니다.


Starnix, 현실적인 선택

백지에서 만든 OS에는 문제가 하나 있습니다. 그 위에서 돌아가는 소프트웨어가 아무에게도 없다는 것이죠. Android 애플리케이션은 Linux에 맞춰 컴파일된 네이티브 코드를 싣고 배포됩니다. 전 세계에 다시 컴파일해 달라고 요구할 수는 없습니다.

Fuchsia의 답이 Starnix입니다. RFC-0082로 제안되어 2021년부터 작업되어 왔습니다. Linux 바이너리가 기대하는 syscall 인터페이스, 즉 Linux UAPI를 구현해서 Zircon 연산으로 번역하는 runner입니다. 수정되지 않은 Linux 바이너리가 Fuchsia 컴포넌트로 실행됩니다. 경로 어디에도 가상 머신이나 에뮬레이션된 하드웨어는 없습니다.

테스트 대상 선정은 진심인 사람이 고를 법한 것들이었습니다. Android 소스 트리의 저수준 바이너리들, 그리고 Linux Test Project의 케이스들이죠. 2022년에는 Fuchsia workstation 빌드에서 Starnix 셸을 쓸 수 있었는데, 이건 일반적인 Linux 환경이 아니라 Fuchsia 위에서 돌아가는 작은 Android 배포판이었고 다른 Android 기기처럼 adb로 붙을 수 있었습니다. 비슷한 시기에 AOSP에서 device/google/fuchsia 디렉터리가 삭제되었는데, 많은 사람들은 이것을 한 접근이 끝나고 다른 접근이 시작된 신호로 읽었습니다.

Windows와 비교하는 게 적절합니다. WSL1이 반대 방향에서 똑같은 일을 했으니까요. VM을 싣는 대신 남의 커널 위에 Linux syscall 인터페이스를 구현하는 방식이었고, 엄청난 양의 실제 작업을 감당할 만큼 쓸 만했지만 결국 진짜 Linux 커널을 쓰는 WSL2에 자리를 내줬습니다. Fuchsia 팀은 시작 전에 WSL1의 성과와 실패 지점을 모두 연구했습니다.

Starnix가 이행기의 전략인지 영구적인 구성 요소인지는 저도 모르겠습니다. 아마 프로젝트 예산을 지켜 주는 쪽이 답이 아닐까 싶습니다.


잘 풀리지 않은 것들

2023년의 Fuchsia를 공정하게 쓰려면 후퇴한 지점들도 적어야 합니다. 꽤 여러 번 있었거든요.

원래 애플리케이션 이야기는 Flutter의 몫이었습니다. 2017년의 UI가 Flutter였고, 초기 SDK는 Dart 우선이었으며, 보도들은 Fuchsia와 Flutter를 한 묶음으로 취급했습니다. 그러다 2022년 RFC-0176이 통과됩니다. Fuchsia 소스 트리에 새로운 Dart 프로그램을 추가할 수 없고, 기존 것들은 allowlist에 올라가 있으며, 새로 넣으려면 예외 승인을 받아야 한다는 내용입니다. 이유로는 바이너리 크기, 성능, 시작 지연 사이의 툴체인 트레이드오프와 트리 안에서 Dart 런타임을 갱신하는 비용이 제시되었습니다. Dart가 삭제된 건 아니지만, Flutter가 전부를 덮는다는 서사는 그렇게 조용히 사실이 아니게 되었습니다.

그래픽 스택도 갈아엎였습니다. Scenic의 원래 Gfx API는 화면을 3D 장면으로 모델링했고, Escher가 자랑하던 볼류메트릭 소프트 섀도까지 갖추고 있었습니다. 그런데 정작 실제 클라이언트인 Flutter, Chromium, 세션 셸은 하나같이 3D 장면을 실제 제품인 2D로 다시 눌러 펴느라 추가 작업을 하고 있었죠. Flatland가 디스플레이 컨트롤러 하드웨어에 대응되는 2D 컴포지션 API로 그 자리를 대체했고, Gfx는 deprecated 상태입니다.

그리고 1월의 해고, 7월의 Assistant 스피커 포기가 있었습니다. 그 스피커에 들어간 Amlogic 칩이 Fuchsia의 CPU 요구 사항을 만족하지 못해서였든, 감원 이후 범위를 좁힌 결과였든, 결과는 같습니다. 7년이 지난 지금 Fuchsia는 스마트 디스플레이에서 돌아가고, 올해 그 목록은 늘지 않고 있습니다.

아무도 피해 가지 못한 비용도 있습니다. 드라이버와 파일 시스템을 유저 스페이스로 옮긴다는 건 Linux가 함수 호출로 끝내는 경로에서 IPC를 한다는 뜻입니다. 같은 호스트의 드라이버들을 커널 밖에 붙들어 두는 in-process driver runtime처럼 Fuchsia의 대응은 훌륭하지만, 어디까지나 스스로 만든 비용에 대한 대응입니다.


내가 훔쳐오고 싶은 것들

저는 Fuchsia가 Android를 대체할 거라고 기대하지 않습니다. 구글도 기대하고 있는지 잘 모르겠고요. 다만 저는 이 프로젝트를 제품 베팅으로 읽기를 그만뒀습니다. 여기 담긴 아이디어들은 다른 곳으로 옮겨 갈 수 있고, 그중 몇 개는 제가 실제로 다루는 시스템에 넣고 싶은 것들이기 때문입니다.

가장 큰 것은 ambient authority 대신 capability를 쓰는 발상입니다. 업계는 이미 10년째 반대편에서 같은 지점으로 수렴하고 있습니다. 모든 컨테이너 런타임, 모든 seccomp 필터, 모든 IAM 정책은 기본값으로 주어진 권한을 되찾아 오려는 시도입니다. Fuchsia의 버전은 그 시작점을 0으로 두면 어떤 모습이 되는지 보여줍니다.

그다음은 매니페스트입니다. 컴포넌트 사이의 모든 의존성이 파일에 선언되고, 빌드가 검증하고, OS가 강제하는 시스템에서는 “이 녀석이 어디까지 닿을 수 있는가”를 테스트가 아니라 읽기로 답할 수 있습니다. 그 질문에 힘든 방식으로 답하느라 쓴 시간이 인정하기 싫을 만큼 많습니다.

그리고 콘텐츠 주소 기반의 hermetic 패키징. 락 파일과 컨테이너 다이제스트와 같은 발상을, 드라이버 층위까지 밀어붙인 것입니다.

Fuchsia가 이미 내놓은 데모는 약속했던 것보다 작습니다. 그리고 저는 그쪽이 오히려 더 흥미롭다고 생각합니다. 운영체제가 판매 중인 소비자 제품 아래에서 스스로를 교체했고, OTA로 그렇게 했으며, 사용자는 끝내 몰랐습니다. 그 일에 7년이 걸렸다는 건 긴 시간일 수도, 싸게 산 것일 수도 있습니다. 그 성과를 물려받을 무언가가 앞으로 나오는지에 달려 있겠죠.


참고 자료