C.W.K.
Stream
Lesson 02 of 04 · published

resolver 하나, 봉투 둘

~12 min · shared-code, divergence, ownership-boundary, design

Level 0신호 없음
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"똑같은 부분은 공유하고; 소유가 다른 딱 그 데서 갈라져. 한 줄 일찍도, 한 줄 늦게도 아니라."

공유되는 중간

Pippa Go 엔 이미지를 나르는 두 흐름이 있어: Prompt Macro(대화 턴 없이 composer 를 돌리는 유틸리티)랑 Ask(canonical 스트리밍 챗). 둘 다 정확히 같은 문제로 시작해 — 사용자가 이미지를 골랐고, 그게 이제 기기 로컬 staging 에 blob 이랑 메타데이터로 앉아 있어. 그 staged blob 을 진짜, 쓸 수 있는 바이트 + 올바른 media type 으로 바꾸는 건 어느 흐름이든 동일한 작업이야. 그래서 단일 공유 staged-media resolver 에서 한 번 해. 그 해소를 두 데서 복제하면 고전적 drift 버그야: 인코딩, 방향, media-type 감지에 대해 천천히 어긋나는 두 복사본.

의도된 분기

그다음, 바이트를 해소했으니, 두 흐름이 갈라져 — 그리고 그 분기는 우연이 아니라 원칙적이야. 소유 경계에서 갈라져. 이미지한테 뭐가 일어나는지가 결과를 누가 소유하냐에 달렸으니까:

  • Prompt Macro → utility 봉투. Macro 는 대화가 아니라 apply-free 유틸리티야. 그 이미지는 canonical 상태를 안 만드는 one-shot 호출에 맞는 가벼운 utility 봉투(인라인 인코딩 바이트)로 다녀.
  • Ask → canonical 봉투. Ask 는 진짜 대화 턴을 만드니까, 그 이미지는 canonical 첨부로 업로드되고 chat 메시지가 참조해 — canonical 턴의 다른 모든 것처럼 백엔드가 소유해.

같은 해소된 바이트, 두 봉투. Macro 의 결과는 일회용이고 Ask 의 결과는 canonical 이라서. 분기는 사마귀가 아냐; 코드를 통해 비치는 소유 모델이야.

규칙: 경계까지 공유, 경계에서 분기

이건 재사용 가능한 설계 본능이야. 두 흐름이 앞 작업을 공유하고 나중에 다르면, 공유 부분을 한 컴포넌트로 빼고 정확히 요구사항이 실제로 다른 지점 — 여기선 결과 이미지의 소유 — 에서 갈라지게 해. 너무 조금 공유하면 resolver 를 복제해(drift). 너무 많이 공유하면 Macro 랑 Ask 를 둘 다 안 맞는 하나의 봉투로 밀어넣어(leaky abstraction). staged-media resolver 는 선을 맞는 데 그어: '진짜 바이트 + media type 을 가졌다'까지는 공통; 그 바이트가 어디 사는지는 흐름별.

Code

공유 resolver, 그다음 소유 경계에서 봉투 둘·typescript
// 공유: 두 흐름에 동일 — staged blob -> 진짜 바이트 + media type.
async function resolveStagedImage(localId: string): Promise<ResolvedImage> {
  const blob = await readStagedBlob(localId);
  return { bytes: await blob.arrayBuffer(), mediaType: blob.type };
}

// Prompt Macro: 일회용 유틸리티 호출 -> 인라인 utility 봉투.
async function macroEnvelope(img: ResolvedImage) {
  return { inlineData: toBase64(img.bytes), mediaType: img.mediaType };
}

// Ask: canonical 턴 -> canonical 첨부로 업로드, 참조.
async function askEnvelope(convId: string, img: ResolvedImage) {
  const ref = await uploadCanonicalAttachment(convId, img); // 백엔드 소유
  return { attachmentRef: ref };
}

// resolver 하나가 둘 다 먹여. 소유가 다른 딱 그 데서 갈라져.

External links

Exercise

앞 처리를 공유하지만 산출물이 다른 두 기능을 골라(예: 같은 문서에서 시작하는 '초안 내보내기' vs '라이브 공개'). 요구사항이 갈라지는 정확한 경계를 짚어. 공유 작업을 한 함수로, 갈라지는 꼬리를 둘로 빼. 그다음 확인해: 경계까지 정확히 공유했어, 아니면 실수로 경계 넘어 leaky 한 하나-크기 경로로 공유했어?
Hint
맞는 이음매는 두 흐름이 동일한 산출을 원하는 마지막 지점이야. 그 전은 전부 공유; 요구사항의 첫 차이가 쪼개는 데야. 공유 함수 안에 'if flow === A' 가 있으면, 한 걸음 너무 멀리 공유한 거야.

Progress

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

댓글 0

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

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