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

쏘고 아무것도 안 받기

~12 min · coupling, async, callbacks, cli-contract

Level 0불 꺼진 작업장
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

비대칭이 요점이야

부르는 쪽은 포인터를 쏴. 그다음 아무것도 안 돌아와. 완료 콜백도, 폴링할 상태 필드도, 자기 데이터베이스에 기록되는 결과도, 알림도 없어. 영상이 만들어졌는지, 얼마나 걸렸는지, 실패했는지조차 몰라. 부르는 쪽 입장에선 버튼 누른 게 이야기의 끝이야.

처음 보면 잘못된 것처럼 느껴져. 요청엔 응답이 있어야 한다고 본능이 말하니까. 근데 응답이 뭘 요구하는지 봐. 상태를 받으려면 부르는 쪽이 '어떤 상태들이 존재하는지'에 대한 모형을 가져야 해. 뭐가 단계고, 뭐가 실패 양상이고, 뭐가 종료인지. 결과를 받으려면 결과가 뭔지에 대한 모형이 필요하고. 둘 다 영상 지식이야. 앞 강의의 금지가 반환 경로로 되돌아온 거지.

답은 어디에 사나

아무도 뭘 알 수 없는 시스템이 아냐. 정보는 있어. 부르는 쪽이 아니라 메시지 스레드에 살 뿐이야. 논의도, 판정도, 렌더 경로도, 마무리도 거기 쌓이고, 사람이 거기서 읽어. 그 요청을 닫는 게 곧 출고고.

그러니까 "다 됐어?"엔 답이 있어. 그냥 부르는 쪽의 질문이 아닐 뿐이야. 이 재구성이 요령의 전부야. 세상의 수많은 상태 필드가 '일을 시작한 시스템이 추적도 해야 한다'는 가정 때문에 존재해. 근데 그 두 역할은 진짜로 분리될 수 있어. 특히 추적의 독자가 다른 이유로 이미 그 스레드를 읽고 있는 사람일 때는.

네트워크 계약이 아니라 명령줄 계약

이걸 정직하게 지켜주는 게 하나 더 있어. '외주'라는 말은 읽는 사람한테 API 호출을 상상하게 만드는데, 그런 건 없어. 작업장엔 부를 서버가 없거든. 경계를 건너가는 건 사람이 집어 드는 메시지 하나고, 그다음 그 사람이 명령줄 도구를 돌려. 이 이음매는 제일 강한 의미에서 비동기야. 두 쪽이 프로토콜로 연결돼 있질 않아. 오래 남는 메시지 하나랑 그걸 읽는 사람으로만 이어져 있어.

이게 신뢰성에 진짜 영향을 줘. 조정할 타임아웃도, 재시도 정책도, 죽은 편지 큐도 없어. 요청은 받았는데 응답이 유실되는 부분 실패도 없고. 요청은 스레드에 있거나 없거나 둘 중 하나야. 이렇게 지을 수 있는 시스템은 비상식적으로 튼튼해. 네트워크를 단단하게 만든 게 아니라 없애버렸기 때문이야.

Code

같은 넘김의 두 가지 형태·text
COUPLED — the caller tracks the work

  caller ──request──▶ worker
     ▲                   │
     └────status─────────┘

  the caller now needs:
    a status vocabulary   (which states exist?)
    a result model        (what came back?)
    a failure model       (what does retry mean?)
    a timeout policy      (how long is too long?)
  ...all of which are the worker's domain knowledge, leaking backward.


ONE-WAY — the thread tracks the work

  caller ──pointer──▶ [ durable thread ] ◀──reads/writes── person
                                              │
                                              ▼
                                          workshop (CLI)

  the caller needs: nothing. it emitted and it is done.
도움 되는 척하는, 사실은 함정인 버전·python
# TEMPTING - and it re-imports the whole domain through the back door.
class RenderStatus(str, Enum):
    QUEUED = "queued"
    FETCHING = "fetching"      # <- a stage name. that is video knowledge.
    SYNTHESIZING = "synthesizing"
    ENCODING = "encoding"
    FAILED_TTS = "failed_tts"  # <- a failure taxonomy. also video knowledge.
    DONE = "done"

# Every rename in the workshop is now a migration on the caller.
# The enum IS the coupling; the network call was never the problem.


# CHOSEN - the caller's entire model of the work:
#   (nothing)
# The thread holds the narrative; a person holds the judgment.

External links

Exercise

네가 가진 요청-응답 연동 중에 응답을 결국 사람만 읽는 걸 하나 찾아봐. 그 응답을 해석하려고 부르는 시스템이 지금 뭘 모형으로 갖고 있어야 하는지 적어봐. 상태 이름, 에러 코드, 중간 상태들. 그다음 한 방향 버전을 설계해봐. 대신 어떤 오래 남는 기록이 이야기를 들고 있을지, 누가 그걸 읽을지. 그리고 정직하게 판정해. 그 응답이 하중을 받고 있었나, 아니면 그냥 함수 호출의 기본 형태였나.
Hint
결정적 단서는 부르는 쪽에 있는 상태 enum 인데 값 이름이 작업자의 내부 단계를 따라간 경우야. 그 이름들은 작업자의 구현이고, 저쪽에서 이름 하나 바꿀 때마다 양쪽 동시 배포가 돼. 사려던 적 없는 결합의 정의가 딱 그거지.

Progress

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

댓글 0

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

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