끝났다고 먼저 말했다
주식 앱의 결제를 팠다. 한쪽 스토어에서 결제한 사람들의 돈은 빠져나갔는데 우리 쪽에는 아무것도 없었다. 실패 기록이 쌓인 것도 아니고 아예 요청이 도착한 적이 없는 쪽. 몇 달째 그 상태였다.
원인은 앱이 결제 정보를 꺼내는 자리에 있었다. 두 스토어가 건네주는 결제 객체의 생김새가 다른데, 한쪽에만 있는 칸을 양쪽에서 똑같이 꺼내려 했다. 없는 칸을 꺼내면 빈 값이 나오고, 값이 비면 서버에 물어보는 단계를 건너뛰게 되어 있었다. 여기까지는 흔한 실수. 문제는 그다음 줄이었다. 건너뛴 채로 앱이 스토어에 이 결제는 다 처리했다고 알렸다.
그 신호는 되돌릴 수 없다. 영수증은 사본이 없어서 닫는 순간 사라진다. 사용자는 돈을 냈고 받은 건 없고, 나중에 우리가 원인을 찾아내도 다시 지급할 근거가 남아 있지 않다. 버그 대부분은 고친 다음 다시 돌려볼 수 있는데 이 종류는 좀 다르다. 실패하면서 자기 흔적을 같이 지우는 쪽. 우리 기록이 그렇게 깨끗했던 이유다.
어제 실기기로 직접 결제해보니 이번엔 서버까지 왔다. 그런데 검증에서 막혔다. 우리가 넣어둔 열쇠값이 스토어 쪽과 안 맞았기 때문. 그때 서버가 앱에게 돌려준 답이 영수증이 잘못됐다는 뜻의 번호였다. 앱은 그 답을 곧이곧대로 믿는다. 다시 시도해봐야 소용없는 종류의 거절이라고 읽고, 또 영수증을 닫으려 든다. 틀린 건 우리 설정인데 답장은 당신 영수증이 문제라고 나간 셈이다. 번호 하나 차이로 되살릴 수 있는 상황이 되살릴 수 없는 상황으로 바뀐다.
그래서 실패 사유를 두 갈래로 갈랐다. 정말 무효인 영수증과, 우리 설정이 틀렸거나 스토어가 잠깐 흔들린 경우. 뒤쪽에는 이제 나중에 다시 물어보라고 답한다. 앱은 영수증을 쥔 채로 기다리다가 다음에 열릴 때 한 번 더 묻는다. 그사이 설정을 고쳐두면 그때 지급된다. 아니오와 지금은 아니오를 같은 말로 보내고 있었던 것.
같은 날 반대편에서 같은 모양의 실수를 했다. 고친 버전을 심사에 올린 뒤 앱 안의 안내 기준을 그 버전으로 올려버렸다. 스토어에는 아직 그 버전이 없었다. 이미 최신인 사람까지 존재하지 않는 버전으로 업데이트하라는 카드를 봤다. 아침에 되돌렸다. 심사에 넣은 것과 사람들이 받을 수 있는 것을 내가 한 칸으로 취급한 셈이다.
둘 다 아직 안 끝난 일을 끝났다고 먼저 말한 것이다. 앞의 것은 스토어에 대고, 뒤의 것은 쓰는 사람에게. 완료 신호는 늘 실제 완료보다 앞서 나가고 싶어 하는데, 앞서 나가고 나면 뒤에 남는 게 없다.
조회를 하나 더 만들었다. 결제한 걸로 되어 있는데 지금은 아무것도 못 받고 있는 사람이 있는지 매일 아침 묻는 질문. 실제 데이터에 한 번 돌려봤더니 한 명이 나왔다. 5월에 결제했고 6월에 끊겼고 다섯 주 동안 그대로였다. 그동안 아무것도 묻지 않았고, 지금은 들어오지 않는다.
그 질문은 이제 매일 아홉 시에 돈다.