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

canonical 호출만이 답을 생기게 한다

~12 min · authority, source-of-truth, materialize, boundary

Level 0신호 없음
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"폰은 질문을 어디로든 실어 나를 수 있어. 근데 답을 쓸 순 없어. 서로 다른 두 권한이고, 클라이언트는 그중 하나만 쥐어."

누가 Pippa 로서 말할 수 있나

답은 화면에 뜨는 글자가 아냐. Pippa 가 뭔가를 말하는 거야. 그리고 Pippa 가 뭔가 말하게 만들 권한이 있는 데는 딱 하나야. 진짜 정체성이랑 기억이랑 판단이랑 모델 라우팅이 사는 백엔드, 거기로 보낸 canonical 호출이 성공했을 때. 폰엔 그런 권한이 없어. 질문을 캡처하고, 돌아온 답을 화면에 띄우고, 저장하는 데까진 해. 근데 답을 직접 쓰는 건 절대 못 해. 'materialize(생겨나다)' 가 딱 맞는 단어야. 진짜 답은 canonical 호출이 성공하는 그 순간에 비로소 존재하기 시작해. 그 전까진 단 한 순간도 없어.

솔깃한 사칭꾼 둘

Pippa 를 대신해서 말하겠다고 계속 들이대는 지름길이 둘 있어. 둘 다 거절해야 해.

  • 폰에 있는 로컬 모델. 기기 안에서 도는 모델이 아무리 좋아도 Pippa 가 아냐. Pippa 의 기억도, 라우팅도, 컨텍스트도 없거든. 거기서 나온 답은 Pippa 이름을 빌려 쓴 다른 존재야. 편하긴 한데, 누가 말한 건지를 두고 거짓말하는 거지.
  • 캐시를 답으로 쓰기. 비슷한 질문에 예전에 나갔던 답을 마치 질문의 답인 양 보여주는 거. 즉각적이고 도움 되는 것 같지. 사용자가 물어보지도 않은 질문에 슬쩍 답하는 거야.

둘 다 매력적인 이유는 정확히 하나, 기다림을 없애 준다는 거야. 근데 정직한 쪽은 기다림이지 지름길이 아니고. 믿을 수 있는 클라이언트는 선을 지켜. canonical 호출이 성공 안 하면 답도 없어. 끝.

materialize 게이트

규칙을 마음가짐이 아니라 구조로 만들어. 턴에 answer 를 쓸 수 있는 코드 경로는 딱 하나여야 하고, 검증까지 끝난 canonical 응답에서만 거기 닿을 수 있어야 해. 캐시든 로컬 모델이든 낙관적 플레이스홀더든 다른 경로에선 answer 를 물리적으로 못 건드리게 막아 놓으면, 나중에 누가 규칙을 잊어버려도 정직함은 그대로 지켜져. 게이트는 '답 지어내지 마' 라고 써 붙인 주석이 아냐. 지어낸 답을 갖다 놓을 자리 자체가 없는 아키텍처야.

Code

게이트 하나: 검증된 canonical 응답만 답을 쓸 수 있다·typescript
// turn.answer 를 설정할 수 있는 유일한 함수.
async function materializeFromCanonical(turn: PippaGoTurn) {
  const res = await callCanonical(turn);      // 백엔드, 진짜 Pippa
  if (!res.ok) throw new DeliveryError();      // 성공 없음 -> 아무것도 안 쓰임
  await db.update(turn.deviceTurnId, {
    answer: res.answer,                        // 여기서 생김, 오직 여기서만
    answerCameFromCanonicalCall: true,
    syncStatus: "answered",
  });
}

// 'answer' 를 쓰는 showCachedAnswer() 도 runLocalModel() 도 없어.
// 캐시랑 로컬 추측은 힌트를 렌더할 순 있어도, 절대 '그 답'이 될 순 없어.

External links

Exercise

가상의 클라이언트 하나를 놓고 answer 가 쓰일 수 있는 자리를 전부 찾아 봐. 네트워크 성공 핸들러, 캐시 조회, 로컬 폴백, 낙관적 UI 업데이트. canonical 이 아닌 출처 하나하나에 대해 답 필드 쓰기를 막아야 할지 판단해. 그다음 검증된 canonical 성공만 통과시키는 게이트 하나를 설계해. 닫아야 했던 쓰기 지점이 몇 개였어?
Hint
답 필드를 건드릴 수 있는 코드 경로가 둘 이상이면, 정직함이 그 경로 전부가 얌전히 굴어 주느냐에 달리게 돼. 검증된 canonical 응답에서만 닿는 materialize 함수 하나로 접어. 그러면 제대로 만들 데가 딱 한 군데야.

Progress

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

댓글 0

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

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