쉬워 보이는 속임수 같은 작업
돌고 있는 앱의 스크린샷을 찍어. 연산 하나처럼 들리는데, 실제로는 보편적인 정답이 없는 타이밍 문제야. 어려운 질문이 딱 하나거든. 이 화면은 언제 다 된 거지? 그리고 앱마다 그 답이 서로 양립 안 하는 방식으로 달라.
시계 1 — 실시간
화면한테 정해진 초를 주고, 그때 있는 걸 찍어. 이 플래그가 정하는 건 상한선이야. 그때까지 로드가 안 끝났으면 거기서 멈추고, 더 일찍 끝나는 화면은 더 일찍 찍혀. 어느 쪽이든 이 시계는 눈을 감고 있어. 화면이 다 됐는지는 하나도 모르거든. 조잡한데, 특정 부류엔 맞아. 계속 폴링하는 앱들. 일을 영원히 예약해 넣는 화면은 잠잠해지는 순간이 없어서 감지할 게 없어. 화면이 조용해지길 기다리는 방법은 무한정 기다리게 돼. 이런 앱한테는 뭉툭한 실시간 타임아웃이 확실하게 끝내는 방법이야.
시계 2 — 가상 시간
실제 초로 기다리는 대신, 브라우저가 자기 시계를 최대한 빨리 돌려서 가상 시간 예산을 다 쓸 때까지 두는 거야. 한 번 로드하는 앱한테 맞아. 특히 시작할 때 상태를 비동기로 복원하는 것들. 실제로 걸리는 시간은 들쭉날쭉한데 예약된 일의 양은 유한한 경우지. 고정된 실시간 대기는 이런 걸 복원 중에 끊어버리거나, 최악의 경우를 감당하려고 매 실행마다 시간을 낭비해.
폴링하는 앱한테 겨눴을 때, 작업장의 맨 첫 캡처가 멈췄어. 타이머로 상태 엔드포인트를 폴링하는 가족 채팅 앱이었는데, 9 초짜리 예산을 걸고 5 분 넘게 돌다가, 실시간 타임아웃으로 바꾸니 3.9 초 만에 찍혔어. 여기서 잰 것과 그 설명은 떼어서 봐야 해. 브라우저가 스스로 밝힌 규칙은 이래. 당장 돌릴 일이 없으면 가상 시간은 다음 타이머까지 건너뛰고, 예산을 다 쓰면 멈춰. 그러니 되풀이되는 타이머만으로는 예산이 끝없이 살아 있을 수 없어. 네트워크 요청이 걸려 있는 동안 가상 시간을 세워두는 정책이 하나 있긴 하고. 그 화면을 붙잡은 게 폴링인지, 끝나지 않은 요청인지, 브라우저를 띄운 감싸개인지 작업장은 끝내 가려내지 않았어. '시계가 절대 안 마른다'는 로그의 문장은 측정 옆에 적어둔 추측이야. 결정엔 원인이 필요 없었어. 그 대상에 통한 시계가 기록됐으니까.
시계 3 — 화면한테 물어보기
둘 다 이기는 앱도 있어. 물결처럼 차오르는 화면은 어떤 의미에선 준비가 됐어. 예약된 일도 없고 실제 시간도 흘렀지. 근데 눈으로 보면 미완성이야. 반쯤 채워진 줄이나 뼈대만 보여주고 있어. 눈먼 시계 둘 다 이걸 못 봐. 둘 다 시간을 재고 있는데 진짜 질문은 상태에 관한 거니까.
답은 화면 안에서 준비 조건을 물어보고, 참이라고 답할 때 찍는 거야. 그럼 앱마다 자기만의 '준비됐다' 정의가 필요해지고. 일이 더 많아지는데, 던져진 질문에 실제로 답하는 건 그것뿐이야.