본문 바로가기
C.W.K.
Lesson 02 of 05 · published

주인 하나, 와이어 둘

~12 min · wire, appkit, daemon, ios, shared-types

Level 0불씨
0 XP0/48 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

맥 앱도 클라이언트야

폰이 생기면 맥 앱을 진짜 주인으로, 폰을 덧붙인 특수한 경우로 치고 싶어져. 그 갈라짐은 붙인 공장을 다시 만들어. 데스크톱 타입이 대화로 새고, 폰이 몰래 맥인 프로그램이 되고, AppKit 을 가져오는 타입은 여행하지 못해. Smolder 의 대답은 주인 하나에 일부러 다르게 만든 와이어 둘이야. 맥 앱도 데몬의 클라이언트고, 비공개 소켓으로 주인 자신의 버전 있는 프로토콜을 말해. 폰은 게이트웨이를 거쳐 더 좁은 원격 와이어로 말해. 그 와이어의 타입은 따로 떨어진 타깃에 있고, 그 타깃은 AppKit 도, 로컬 프로세스 검사도, 로컬 파일시스템 가정도 없이 컴파일돼. 표면 둘. 와이어 둘. 둘 뒤의 주인 하나.

"AppKit 없이"는 미학이 아니야. NSView 를 이름 붙인 타입은 iOS 에서 빌드가 안 돼. "이 판의 로컬 PID 가 뭐야"라고 묻는 타입은 판 PID 가 없는 폰에서 못 돌아. /Users/... 가 여기라고 가정하는 타입은 폰이 보기만 하는 호스트의 폴더를 못 말해. 그 가정들은 공유 모듈이 #if os 옷을 입은 맥 모듈이 되는 길이야. 옷은 폰이 채울 수 없는 필드가 필요한 날에 항상 찢어져.

와이어가 해도 되는 말

세션 정체성과 주인의 인카네이션, 저널 덩어리, 표면이 한 행위로 보내는 입력, 치고 있는 표면의 크기 요청, 실행 영수증. 데몬이 아는 것. 픽셀은 아니야. NSFont 도 아니야. 맥의 열기 패널로 들어가는 북마크도 아니야. 각 표면의 에뮬레이터가 같은 핀으로 바이트를 글리프로 바꿔. 와이어는 스크린샷을 실어 나르지 않아. 와이어 위에 스크린샷이 있으면, 에뮬레이터를 포기하고 원격 데스크톱을 시작한 거야. 그건 리사이즈가 틀리고 복사가 틀리고 구경꾼이랑 치는 사람을 구분을 못 해.

나중 트랙의 게이트웨이는 승인된 기기와 한도 있는 WebSocket 으로 말해. 그래도 게이트웨이 자신은 주인의 비공개 소켓에 붙는 또 하나의 클라이언트일 뿐이야. 원격 와이어는 그 소켓과 일부러 갈라 뒀어. 프롬프트 nonce 도, 프로세스 인자 목록도, 임의 실행 명령도, 가족 자격 증명도, 종료도 없어. 데스크톱 타입을 "폰에 안전한" 그림자로 번역하는 게 아니야. 좁은 와이어에는 처음부터 번역할 데스크톱 모양이 없었어. 꽉 찬 프로토콜은 호출자가 같은 맥의 자기 앱인 곳에 남고, 주머니가 받는 건 좁은 쪽이야. 건너는 타입 위에 AppKit 은 영.

로컬 검사는 로컬에 남아

맥 위의 데몬은 자기 프로세스를 검사할 수 있어. 그 검사는 여행하지 않아. 제목을 보여야 하는 폰은 데몬이 이미 쥔 제목을 와이어에 묻지, 실행할 수 없는 sysctl 을 묻지 않아. 크롬을 그려야 하는 맥 창은 AppKit 에 묻고, 데몬이 알아야 하는 사실만 보내 (포커스된 판, 칠 때 청하는 크기). 그 층을 섞으면, 보기만 하는 쪽이 일으킨 리사이즈가 "그냥 창 콜백"이라는 이름으로 새어 들어와.

이 레슨은 '셸은 호스트에 남아' 의 타입 층 버전이야. 와이어가 iOS 에서 컴파일 못 하면 폰은 표면이 아니야. 모델을 공유하는 척하는 원격 조종 스크립트야. 컴파일러를 정직하게 두면 소유도 정직하게 남아.

공유 와이어 타입은 AppKit 없이 컴파일돼. 맥 앱도 같은 데몬의 클라이언트고, 자기 몫으로 더 꽉 찬 프로토콜을 써. 로컬 프로세스 검사, 로컬 파일시스템 가정, 주인의 비공개 동사는 폰의 와이어 밖에 남아. 아니면 폰이 몰래 맥인 프로그램이 돼.

Code

여행할 수 있는 와이어 타입, 가면 안 되는 맥 타입·swift
// The phone's remote wire (abridged from the shipped types).
// Its own target: no AppKit, no SwiftTerm, no local process inspection.
public struct RemoteSession: Codable, Sendable {
    public var id: UUID            // session identity
    public var incarnation: UUID   // which owner process this belongs to
    public var host, folder, title, process: String  // facts the daemon already holds
    public var columns, rows: Int
    public var sequence: UInt64
    public var writer: Bool        // this device may type now
    public var held: Bool?         // a hold is set
    public var surfaces: [String]? // every attached input surface
}
// RemoteEvent .output carries bytes: journal / live output, never pixels.

// Deliberately NOT on this wire (the owner's private socket keeps them):
//   prompt nonce, process argv, arbitrary launch command,
//   family credential, terminate
// Illegal anywhere on it:
//   import AppKit / NSView / pid_t / a URL bookmark into this device's files

// Mac app:  owner's versioned protocol over a private socket, sends its input
// Gateway:  a client of that same socket, speaks the remote wire to the phone
// Daemon:   may inspect local processes; that inspection does not travel

External links

Exercise

폰이 원할 사실 다섯을 적어 (판 제목, 글리프 픽셀, 로컬 PID, 호스트의 폴더 경로, 지금 저널 덩어리). 각각을 와이어에 둘지 밖에 둘지. 밖 항목마다, 그래도 와이어에 넣으면 하게 될 거짓말 한 문장.
Hint
픽셀이랑 PID 는 쉬운 거절이야. 폴더 경로는 데몬이 이미 아는 호스트 이름 문자열로서만 합법이지, 폰의 파일 앱 북마크가 맥인 척하는 게 아니야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.