본문 바로가기
C.W.K.
Stream
Lesson 04 of 04 · published

repository 는 열 대상이 아니다

~12 min · firelink, domain-model, launch-surface, deep-linking

Level 0식은 재
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"repository 를 여는 게 아냐. 거기서 나온 걸 여는 거지. 나오는 게 있다면."

멤버랑 surface 는 다른 물건이야

'가족이란 repo 목록이고, 실행이란 repo 를 여는 것' 이렇게 생각하기 쉬워. Firelink 는 그 지름길을 안 써. FamilyMember 는 repository 나 제품 정체성이야. 얘가 LaunchSurface 를 0개 이상 갖는데, surface 는 그 멤버가 실제로 내놓는 사용자용 물건이야. WebUI 나 네이티브 앱 같은 거. 런처는 그 surface 를 열지 repository 속을 열지 않아. 이름만 봐도 읽히지. Pippa 의 WebUI surface, Firekeeper 의 메뉴바 앱 surface, Ember 의 engine UI surface. repo 가 멤버고, 열리는 건 surface 야.

surface 가 아예 없는 멤버도 있어

이 구분은 가장자리에서 값을 해. 같이 쓰는 kit 이나 workshop repo 는 열 게 아무것도 없을 수 있거든. 다른 형제가 갖다 쓰는 라이브러리거나, 서버 없이 도는 배치 도구니까. 그래도 Firelink 는 그 멤버를 Web Hub 에 보여줘. 존재하고, Git 상태가 있고, 중요하니까. 대신 없는 실행 대상을 지어내진 않아. 눌러도 아무 일 없는 유령 'Open' 버튼은 안 만들어. surface 가 없으면 런처는 내놓을 게 없는 거고, 그게 정직한 답이야.

'열기'는 지금 어디 있는지를 본다

surface 가 URL 문자열이 아니라 진짜 물건이라서, 여는 방식도 상황을 봐. 같은 web surface 라도 사무실 loopback 에선 localhost 로, 같은 랜에선 LAN 주소로, tailnet 에선 Tailscale HTTPS 로 풀려. 어디서든 통한다고 우기는 'primary' URL 은 일부러 안 뒀어. 카드에 박힌 링크도 메인 Open 버튼이랑 똑같은 방식으로 주소를 골라. surface 는 주소 하나로 버티는 척하는 대신, 네가 어디 있든 거기서 어떻게 닿는지를 알고 있어.

관리하는 것(멤버)이랑 여는 것(surface)을 갈라놔. 멤버는 surface 를 여러 개 가질 수도, 하나만 가질 수도, 아예 안 가질 수도 있어. 이걸 한 덩어리로 뭉치면 surface 없는 멤버한테 가짜 실행 버튼을 달게 되고, 멤버 하나가 열 것을 여러 개 내놓을 수 있다는 것도 놓쳐.

Code

멤버가 surface 를 갖고, 열리는 건 surface·typescript
type LaunchSurface = {
  targetId: string;              // stable, e.g. "cwkPippa:webui"
  ownerId: string;               // the owning FamilyMember
  kind: "web" | "native-app";
  label: string;
  // web: context-specific URLs (localhost / LAN / tailnet), resolved per client
  // native-app: a registered bundle id
};

type FamilyMember = {
  id: string;
  surfaces: LaunchSurface[];      // ZERO or more — a kit may have none
  // ...identity, lifecycle, host affinity, capabilities
};

// A workshop repo with no server:
//   member.surfaces === []  ->  shown in the Web Hub, NO launcher target invented.
// The launcher opens surfaces. It never opens a member, and never fakes one.

External links

Exercise

뭔가를 목록으로 보여주고 열게 해주는 시스템을 골라봐. 관리하는 것이랑 열리는 것을 한 덩어리로 뭉쳐놨어? 관리 항목 하나가 열 것을 둘 내놔야 하는 경우를 찾아봐. 대시보드랑 API 콘솔을 둘 다 가진 서비스 같은 거. 아니면 열 게 아예 없는 항목도 좋고. 멤버랑 surface 를 갈라놓으면 가짜 'Open' 없이 그 둘을 어떻게 정직하게 표현할 수 있을까?
Hint
뭉쳐놓은 티는 두 가지로 나. 열 수도 없는 것에 달린 죽은 'Open' 버튼, 아니면 두 가지 방식으로 열고 싶은데 방법이 하나뿐인 항목. '관리하는 것'과 '여는 것'을 따로 두면 둘 다 사라져.

Progress

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

댓글 0

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

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