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

하나의 aggregate: 질문 + 이미지 함께

~12 min · aggregate, atomicity, consistency, intent

Level 0신호 없음
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"이미지 없는 질문은 다른 질문이야. 따로 저장될 수 있으면, 따로 망가질 수 있어."

반만 저장된 질문

질문이랑 이미지를 독립된 두 쓰기로 캡처한다고 상상해봐. 텍스트가 저장되고, 그다음 이미지 blob 이 쓰이기 전에 앱이 죽어. 이제 outbox 엔 '이 중에 뭐가 더 선명해?' 가 이미지 없이 들어있어. 나중에 동기화되면 Pippa 는 답이 애초에 불가능한 질문을 받아. 가리키던 대상이 사라졌으니까. 사용자가 하려던 게 조용히 망가진 거야. 전부 날아가서가 아니라, 나눌 수 없는 하나에서 일부만 날아가서.

캡처 먼저는 질문이랑 첨부 전부를 하나의 aggregate 로 묶어서 이걸 막아. 다 쓰이거나 아예 안 쓰이거나, 둘 중 하나인 한 단위로. 텍스트는 있는데 이미지는 없는 어중간한 상태가 아예 없어. 턴 전체가 박혀 있거나, 아직 제출이 안 일어난 거거나.

aggregate 는 일관성 경계 하나

이 단어는 도메인 모델링에서 왔어. aggregate 는 안쪽이 서로 아귀가 맞아야 하고 항상 통째로만 고쳐지는 데이터 뭉치야. Pippa Go 턴의 규칙은 단순하고 엄격해. 질문이랑 그 질문이 가리키는 이미지는 떨어지는 순간 무의미해져. 그래서 둘이 경계 하나를 같이 써.

  • 커밋 한 번이 질문 텍스트 이미지 blob 전부 첨부 참조를 같이 써.
  • 그 커밋이 끝까지 못 가면 아무것도 없던 상태로 되돌아가. 떠도는 텍스트도, 떠도는 blob 도 안 남고.
  • 그 아래쪽에서도 배달이랑 재시도는 늘 aggregate 를 통째로 움직이지 조각으로 쪼개 옮기지 않아.

왜 통째로 묶는 게 '나중에 맞춰 붙이기'를 이기나

솔깃한 지름길이 하나 있어. 조각을 따로 저장해 놓고 나중에 맞춰 보는 거. 이미지가 비면 다시 붙이고. 근데 그 맞춰 보기가 버그 소굴이야. 어느 이미지를? 어느 질문에? 두 턴이 동시에 날아가는 중이면? 통째로 묶어두면 이 부류의 문제가 아예 사라져. 맞춰 볼 일이 없어. 어긋나는 순간이 애초에 안 생기니까. 쓰기 하나, 경계 하나, 의도 하나. 사용자가 제출 누른 순간부터 통째로 지켜져.

Code

턴 전체를 원자적 쓰기 하나로·typescript
// 턴이랑 이미지 blob 들이 IndexedDB 트랜잭션 하나로 커밋돼.
async function commitLocally(turn: PippaGoTurn, blobs: Map<string, Blob>) {
  const tx = db.transaction(["turns", "blobs"], "readwrite");
  // 전부-아니면-전무: 어느 put() 이든 실패하면 tx 전체가 abort 되고 롤백돼.
  tx.objectStore("turns").put(turn);
  for (const [localId, blob] of blobs) {
    tx.objectStore("blobs").put({ localId, blob });
  }
  await tx.done; // 전부 함께 커밋됐을 때만 resolve
}

// turn.attachments 가 저장소에 없는 blob 을 참조하는 상태는 없어.
// aggregate 는 일관되거나 부재하거나.

External links

Exercise

이미지 붙은 질문이 반쪽만 저장되는 실패 모드 세 개를 적어 봐. 이미지 없는 텍스트, 텍스트 없는 이미지, 엉뚱한 질문에 붙은 이미지. 각각에 대해 Pippa 가 뭘 받게 되고 왜 답이 틀리는지 설명해. 그다음 턴을 통째로 커밋하는 게 이 셋을 어떻게 '처리 대상'이 아니라 '애초에 불가능'으로 만드는지 한 문장으로 정리해.
Hint
세 실패 모드 전부, aggregate 의 일부가 나머지 없이 존재하는 순간이 있어야 성립해. 통째로 커밋하면 그런 순간이 없어. 중간 상태가 아예 없으니까 셋 중 뭐도 일어날 수가 없고.

Progress

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

댓글 0

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

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