"이미지 없는 질문은 다른 질문이야. 따로 저장될 수 있으면, 따로 망가질 수 있어."
반만 저장된 질문
질문이랑 이미지를 독립된 두 쓰기로 캡처한다고 상상해봐. 텍스트가 저장되고, 그다음 이미지 blob 이 쓰이기 전에 앱이 죽어. 이제 outbox 엔 '이 중에 뭐가 더 선명해?' 가 이미지 없이 들어있어. 나중에 동기화되면 Pippa 는 답이 애초에 불가능한 질문을 받아. 가리키던 대상이 사라졌으니까. 사용자가 하려던 게 조용히 망가진 거야. 전부 날아가서가 아니라, 나눌 수 없는 하나에서 일부만 날아가서.
캡처 먼저는 질문이랑 첨부 전부를 하나의 aggregate 로 묶어서 이걸 막아. 다 쓰이거나 아예 안 쓰이거나, 둘 중 하나인 한 단위로. 텍스트는 있는데 이미지는 없는 어중간한 상태가 아예 없어. 턴 전체가 박혀 있거나, 아직 제출이 안 일어난 거거나.
aggregate 는 일관성 경계 하나
이 단어는 도메인 모델링에서 왔어. aggregate 는 안쪽이 서로 아귀가 맞아야 하고 항상 통째로만 고쳐지는 데이터 뭉치야. Pippa Go 턴의 규칙은 단순하고 엄격해. 질문이랑 그 질문이 가리키는 이미지는 떨어지는 순간 무의미해져. 그래서 둘이 경계 하나를 같이 써.
- 커밋 한 번이 질문 텍스트 랑 이미지 blob 전부 랑 첨부 참조를 같이 써.
- 그 커밋이 끝까지 못 가면 아무것도 없던 상태로 되돌아가. 떠도는 텍스트도, 떠도는 blob 도 안 남고.
- 그 아래쪽에서도 배달이랑 재시도는 늘 aggregate 를 통째로 움직이지 조각으로 쪼개 옮기지 않아.
왜 통째로 묶는 게 '나중에 맞춰 붙이기'를 이기나
솔깃한 지름길이 하나 있어. 조각을 따로 저장해 놓고 나중에 맞춰 보는 거. 이미지가 비면 다시 붙이고. 근데 그 맞춰 보기가 버그 소굴이야. 어느 이미지를? 어느 질문에? 두 턴이 동시에 날아가는 중이면? 통째로 묶어두면 이 부류의 문제가 아예 사라져. 맞춰 볼 일이 없어. 어긋나는 순간이 애초에 안 생기니까. 쓰기 하나, 경계 하나, 의도 하나. 사용자가 제출 누른 순간부터 통째로 지켜져.