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

이어서 할 수 있게 만든 단계들

~15 min · firelink, state-machine, resumable, saga

Level 0식은 재
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Birth 는 세상을 단계로 건드려. 다음 단계로 넘어가기 전에 지금까지를 저장해두니까, 중간에 죽어도 잔해가 아니라 이어서 할 지점이 남아."

바깥을 건드리는 일이 줄줄이 있어

repo 를 birth 하는 건 동작 하나가 아니라 바깥 세상을 건드리는 일들의 줄이야. scaffold 준비하고, 로컬 Git repo 만들고, private remote 를 요청하고, 첫 커밋을 push 하고, 자리에 올리고, roster 갱신하고, network ledger 갱신하고, operation registry 갱신하고, 마지막으로 확인하고. 하나하나가 프로세스 밖의 뭔가를 건드려. 파일시스템, GitHub, ledger 파일. 중간에 하나라도 실패했을 때 '어디까지 진짜로 벌어진 거지?' 를 짐작하게 두면 안 되지. 그래서 Birth 는 이어서 할 수 있는 단계 구조로 돌아. 순서가 있고, 한 단계가 끝나는 순간 다음 바깥 작업을 시작하기 전에 저장돼.

저장하고, 그다음 단계로

규율은 단순하고 빡빡해. 다음 바깥 작업을 시작하기 전에 끝난 단계를 저장한다. remote 를 만들었으면 그 사실이 push 를 시도하기 전에 이미 남아 있어. 그러니까 push 가 실패해도 run 은 'remote 만들어짐' 에서 이어져. remote 를 또 만들지도, repo 를 다시 init 하지도, 뭘 두 번 하지도 않아. 실패는 마지막으로 멀쩡했던 지점에 세워둔 run 을 남기고, 재시도는 자기가 반쯤 해둔 것과 싸우는 대신 거기서부터 가. Birth 가 반쪽짜리 상태를 두고 끝났다고 하는 일도 없고, 평범한 재시도가 지난번 잔해와 부딪히는 일도 없어.

따로 짓고, 다 되면 한 번에 올리고, 끝나면 확인해

이 줄의 앞뒤를 안전장치 둘이 감싸. 먼저 Birth 는 scaffold 를 Firelink 가 쓰는 임시 자리에서 짓고, 로컬 준비가 완전히 끝난 다음에야 새 디렉터리를 제자리로 한 번에 올려. 그래서 반쯤 지어진 껍데기가 진짜 경로에 나타나는 일이 없어. 그리고 마지막 단계는 자기 장부를 안 믿어. 새 멤버를 FamilyRegistry 와 FamilyReconciler 로 다시 엮어보고, 제대로 엮이는 걸 확인한 다음에야 성공이라고 해. 단계가 다 돌았다고 끝난 게 아니라, 다시 엮은 가족 안에 새 멤버가 실제로 들어 있어야 끝난 거야.

바깥을 건드리는 여러 단계짜리 작업은, 다음 단계 전에 지금까지를 저장하고, 실패하면 처음이 아니라 마지막 멀쩡한 지점에서 이어가게 만들어. 어디까지 갔는지 기억하는 구조가 중간에 죽는 사고를 '뭐가 망가졌는지 모름' 에서 '여기서부터 다시' 로 바꿔줘. 그리고 성공의 마지막 증거는 단계가 돌았다는 믿음이 아니라, 결과를 다시 만들어보는 거야.

Code

바깥 단계 하나가 끝나면 다음 전에 저장된다·bash
# Birth orchestrates real effects. Each completes and is PERSISTED as a
# state before the next external effect starts, so a crash is resumable.

git init cwkNewThing                       # -> state: local-git-created   (persist)
git -C cwkNewThing add -A
git -C cwkNewThing commit -m "scaffold shell"   # scaffold only, no product
gh repo create cwkNewThing --private       # -> state: private-remote-created (persist)
git -C cwkNewThing push -u origin main     # -> state: initial-push-complete  (persist)

# If the push dies HERE, the run is parked at 'private-remote-created'.
# The retry resumes from there: it does NOT re-init the repo or re-create
# the remote. No step is repeated, no partial work is fought.
#
# ...then roster-updated -> network-updated -> registry-updated ->
#    registry-VERIFIED (rebuild via FamilyRegistry+Reconciler) -> complete.

External links

Exercise

바깥 시스템을 둘 이상 건드리는, 네가 만들었거나 쓰는 여러 단계짜리 작업을 그려봐. 유저 만들기 + 환영 메일 보내기 + 작업 공간 만들기 같은 거. 단계를 순서대로 적고, 네 단계 중 두 번째가 끝난 다음에 죽었다고 쳐봐. 네 설계는 어디서 멈췄는지 정확히 알아? 재시도가 1·2 단계를 다시 안 하고 이어갈 수 있어? 아니면 단계마다 저장을 붙이고, 재시도가 그걸 어떻게 쓰는지 적어봐.
Hint
찾아야 할 사고는 이거야. 1단계가 이미 끝났다는 걸 아무도 안 적어놔서 재시도가 1단계를 또 도는 것. 유저가 둘 생기고 메일이 두 번 나가는 거지. 고치는 법은 다음 단계 시작 전에 'N 단계 끝' 을 남기는 거고, 그게 Birth 가 하는 것과 같은 모양이야.

Progress

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

댓글 0

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

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