STARRY PASS 7 — 환불 창구에 선 스무 명
천 장의 업무표를 무한한 직원에게 떠넘기지 않고, 스무 번의 환불을 성공 열 장·정상 거절 열 장·기술 장애 영 장으로 끝까지 설명하는 이야기
STARRY의 낮 공연이 갑자기 취소된 날, 계산대 앞에는 손님 대신 번호표 스무 장이 놓였다. 실제 손님을 세워 두고 연습할 수는 없어서, 니지카가 같은 선불 카드에서 1,000원씩 돌려받으려는 스무 요청을 만든 것이다. 카드의 시작 잔액은 10,000원이었다.
키타는 번호표를 부채처럼 펼쳤다. “스무 명이 한꺼번에 오면 직원도 스무 명을 부르면 되죠?”
료가 그 옆에 더 두꺼운 묶음을 내려놓았다. “그럼 업무표가 천 장이면 직원도 천 명을 부를 거야?”
키타가 웃음을 멈췄다. 히토리는 천 명이 좁은 계단에 서 있는 광경을 떠올리다 조용히 벽 쪽으로 물러났다.
니지카는 탁자에 여섯 개의 봉투를 차례로 놓았다. 여섯 봉투에는 같은 시험이 다시 나오는 경우도 있었고, 한 봉투를 열면 네 가지 확인이 한꺼번에 실행되는 경우도 있었다. 그래서 봉투 수, 실제 확인 횟수, 서로 다른 확인의 수는 같지 않았다.
봉투는 여섯 번 열렸다. 그 안에서 확인 도장은 모두 아홉 번 찍혔다. 겹치는 이름을 하나로 모으면 서로 다른 확인은 여섯 개였다. 그중 다섯 개는 이번 연습에서 처음 들어온 것이고, 반대 방향 이체 확인 하나는 앞 연습에서 가져온 것이었다. 두 번째 봉투에서 일부러 틀린 창구를 먼저 돌리는 과정까지 세면 물리적인 실행은 하나 더 늘지만, 그것은 최종 통과 실행 수와 따로 적어야 했다.

니지카는 먼저 돈을 전혀 건드리지 않는 모형 업무표 천 장을 준비했다. 각 표는 출발 신호를 기다렸다가 아주 짧게 멈춘 뒤 성공표를 돌려주는 일이었다. 실제 카드나 금고를 쓰는 일이 아니었다.
첫 연습에서는 창구를 열 개만 열었다. 업무표는 천 장이었지만 동시에 일을 잡을 수 있는 직원은 최대 열 명이었다. 한 직원이 표 하나를 끝내면 줄의 다음 표를 집었다. 이어서 창구를 쉰 개, 이백 개로 바꿔 같은 천 장을 다시 돌렸다.
“업무표 천 장이 곧 직원 천 명이라는 뜻이 아니네요.” 히토리가 말했다. “저는 할 일이 천 개 생기면 자아도 천 개로 나뉘는 줄 알았는데…….”
“넌 자아 하나도 자주 멈추잖아.” 료가 답했다.
직원 수가 열 명인 실행에서 동시에 움직였다고 관찰한 최댓값은 적어도 한 명, 많아도 열 명이어야 했다. 쉰 명이면 한 명부터 쉰 명 사이, 이백 명이면 한 명부터 이백 명 사이였다. 반드시 모든 직원이 같은 순간 바쁘다고 채점하지는 않았다. 실제 운영체제가 어떤 순서로 깨우는지까지 통제할 수 없기 때문이다.
또 성공·업무 거절·기술 장애 세 바구니에 들어간 표의 합이 매 실행마다 천 장인지 확인했다. 기술 장애 바구니는 비어 있어야 했다. 다만 채점표가 성공 천 장과 업무 거절 영 장을 각각 직접 비교한 것은 아니었다. 이 모형 작업은 정상이라면 성공이라는 글자만 돌려주지만, 채점식이 직접 묻는 것은 세 바구니의 합 천 장, 기술 장애 영 장, 동시 활동의 상한이었다.
“그러면 이백 창구가 제일 빠르다는 결론인가요?” 키타가 물었다.
니지카는 고개를 저었다. “그 속도를 비교하는 채점은 없어. 이건 창구 수의 상한과 결과표 회수 장치가 제대로 움직이는지 보는 연습이야. 실제 금고 연결 수도 모르고, 실제 환불도 하지 않았어.”
료는 보고서 첫 줄에 ‘모형 업무 천 장’이라고 크게 썼다. ‘실제 데이터베이스 환불 천 건’, ‘운영 처리량’, ‘최대 수용량’이라는 문장은 모두 지웠다.
천 장을 한꺼번에 겹치게 하려면 출발 장치가 필요했다. 직원들은 자기 차례가 되면 준비 깃발 하나를 내리고 닫힌 문 앞에서 기다렸다. 필요한 깃발이 모두 내려오면 진행자가 출발 종을 한 번 울렸다. 종이 울린 뒤에야 직원들이 일을 시작했다.
“각자 준비되는 대로 바로 하면 안 되나요?” 히토리가 물었다.
“그러면 첫 사람이 거의 다 끝난 뒤 마지막 사람이 시작할 수도 있어.” 니지카가 답했다. “우리가 확인하려는 겹침이 만들어지지 않았는데도 아무 사고가 없었다고 착각할 수 있지.”
료가 창구 두 개와 업무표 두 장을 놓았다. 준비 깃발은 일부러 세 개를 요구했다. 실제 직원 둘은 깃발을 하나씩 내려 두 개까지 만들고 출발 종을 기다렸다. 그러나 세 번째 깃발을 내릴 직원은 존재하지 않았다. 100밀리초짜리 모래시계가 끝나자 준비 실패표가 나왔다.
키타가 빈 계산대를 보았다. “아무 일도 안 일어났는데 조용한 성공으로 치면 안 되나요?”
“동시 연습을 시작하지 못한 거야.” 니지카가 말했다. “준비 시간 초과라는 말이 들어간 실패가 나와야 해. 기다리다 끝난 일을 성공으로 삼키면 가장 위험한 거짓 통과가 돼.”
실패가 나더라도 출발 종은 마지막 정리에서 내려갔다. 문 앞에 갇힌 직원이 남지 않게 한 뒤 창구를 닫았다. 정상 실행에서도, 중간에 문제가 난 실행에서도 정리 동작은 빠지지 않았다.
각 업무표를 끝내는 결과표에도 기다림 상한이 있었다. 바깥 진행자는 결과표 하나마다 최대 30초를 기다렸다. 첫 결과표부터 마지막 결과표까지 모두 합쳐 30초라는 뜻은 아니었다. 하나씩 차례로 꺼내며 각 표에 같은 상한을 적용했다. 모형 업무의 준비에는 최대 10초를 주었다.
“마지막 숫자가 맞으면 중간 결과표 몇 장은 못 받아도 괜찮지 않을까요?” 히토리가 물었다.
료가 세 바구니를 다시 가리켰다. “안 돼. 성공, 정상 거절, 기술 장애의 합이 제출한 업무표 수와 같아야 해. 결과를 잃어버린 채 마지막 숫자만 맞는 사고도 있거든.”
이제 진짜 카드가 등장했다. 시작 잔액은 10,000원, 요청은 스무 장, 요청마다 1,000원이었다. 모든 요청은 같은 손님과 같은 카드에 접근했지만, 요청표 이름은 0부터 19까지 서로 달랐다. 직원도 스무 명을 열어 모두 준비 깃발을 내린 뒤 출발 종을 함께 기다리게 했다.
니지카는 먼저 일부러 비어 있는 창구 규칙을 보여 줬다. 이 규칙은 요청 금액이 양수인지와 카드가 존재하는지, 카드 주인이 맞는지만 확인했다. 그 뒤에는 돈을 빼지도, 거래표를 만들지도, 장부를 적지도 않은 채 지금 보이는 잔액을 성공처럼 돌려줬다.
스무 요청은 모두 성공표를 들고 나왔다. 그런데 카드 잔액은 여전히 10,000원이었고 출금 장부도 영 줄이었다.
키타가 놀랐다. “실패가 아니라 성공이 너무 많아서 틀린 거네요.”
“맞아.” 니지카가 말했다. “채점표는 성공 열 장을 기대해. 첫 성공 수 검사에 우리가 붙여 둔 이름이 남으면서 의도한 실패가 드러나지. 아무 빨간 결과나 받는 게 아니라, 바로 그 계약이 깨졌다는 표시를 확인해야 해.”
히토리는 ‘성공 스무 장’을 좋은 소식 칸에 넣으려다가 멈췄다. 돈을 하나도 움직이지 않은 거짓 성공은 기술 장애만큼 위험했다. 채점표가 기대한 것은 스무 번 전부의 성공이 아니라, 가능한 열 번만 성공하고 나머지 열 번은 잔액 부족을 정확히 알리는 일이었다.
그들은 빈 규칙을 걷어 내고 완성된 창구 규칙을 직접 옮겨 적었다. 요청 금액이 양수인지 확인하고, 카드를 읽기 전에 그 카드의 행 열쇠를 잡았다. 카드가 있는지, 주인이 맞는지를 확인한 뒤 카드 안의 출금 규칙으로 잔액을 줄였다. 같은 작업 안에서 완료된 출금 거래표 한 장과 출금 장부 한 줄을 저장하고, 새 잔액을 돌려줬다. 이 모든 단계는 한 묶음으로 끝나거나 함께 되돌아가야 했다.
첫 성공은 10,000원을 9,000원으로 만들었다. 다음 성공은 열쇠를 받은 뒤 최신 9,000원을 읽어 8,000원으로 만들었다. 이런 식으로 열 번째 성공 뒤 잔액은 0이 되었다. 뒤에 열쇠를 받은 요청은 1,000원을 더 뺄 수 없었고, 잔액 부족이라는 정상 업무 거절을 돌려줬다.
스무 결과표를 전부 모으자 성공 열 장, 정상 거절 열 장, 기술 장애 영 장이었다. 카드 잔액은 0, 출금 종류의 장부는 열 줄이었다.

“어느 요청표 번호가 성공했는지도 정해져 있나요?” 키타가 물었다.
“아니.” 료가 답했다. “스무 직원이 경쟁하니까 0번부터 9번이 반드시 성공한다고 채점하지 않아. 성공이 열 장인지, 정상 거절이 열 장인지가 계약이야.”
업무 거절 바구니에는 아무 예외나 넣지 않았다. 잔액 부족이라는 정확한 업무 코드만 정상 거절이었다. 카드 없음이나 주인 불일치처럼 다른 업무 오류가 나오면 기술 실패 바구니로 갔다. 예상하지 못한 실행 오류도 기술 실패였다. 이렇게 나눠야 데이터베이스 연결 오류를 잔액 부족으로 위장하지 않았다.
준비 깃발은 최대 10초 기다렸고, 각 결과표는 최대 30초 기다렸다. 스무 결과표의 공통 30초 마감이 아니라 각 결과표를 차례로 받을 때의 상한이었다. 단 한 번의 실행에서 이 다섯 수가 맞았다는 사실은 중요했지만, 서른 번 반복 안정성이나 천 건 실제 금고 부하, 느린 쪽 응답 시간, 운영 처리량까지 증명하지는 않았다.
료는 장부 열 줄을 세고 펜을 내려놓았다. “열 줄이라는 확인만 있어. 각 줄의 금액과 부호, 거래표 열 장의 수, 요청표 이름의 유일성까지 이 채점이 모두 직접 묻는 건 아니야.”
“요청표 이름을 거래표 글자에 넣었으니 같은 이름이 다시 오면 한 번만 처리되나요?” 히토리가 물었다.
니지카는 다음 주에 쓸 번호표 상자를 꺼냈다가 다시 넣었다. “아직 아니야. 이름을 기록하는 것과, 같은 이름의 첫 요청만 주인이 되게 원자적으로 차지하는 건 달라. 이번 스무 장은 애초에 이름이 모두 다르고, 같은 이름을 재전송하는 시험이 없어.”
다음 봉투에는 방금 만든 스무 요청 확인이 다시 들어 있었다. 새 기능이나 새 시험이 아니었다. 정답을 가리고 준비 깃발, 출발 종, 세 결과 바구니와 마지막 두 숫자를 다시 설명한 뒤 같은 확인을 회수하는 봉투였다.
히토리가 새 도장을 꺼내려 하자 료가 막았다. “실행 노출은 한 번 늘어도 서로 다른 확인 수는 늘지 않아.”
니지카는 칠판에 ‘봉투 여섯’, ‘최종 확인 아홉’, ‘고유 확인 여섯’을 다시 적었다. 방금 스무 요청 확인은 두 봉투에서 각각 한 번씩 실행되지만 같은 한 가지 확인이었다.
그 옆에는 숫자 계산 연습이 있었다. 1부터 30까지의 값이 오름차순으로 놓였다. 가운데는 15와 16 사이였으므로 두 값을 더해 둘로 나눈 15.5였다. 느린 쪽 95퍼센트 지점은 서른에 0.95를 곱한 뒤 올림한 스물아홉 번째 값, 곧 29였다.
“95퍼센트면 28.5 아닌가요?” 키타가 물었다.
료가 자 위의 29를 짚었다. “여기서 정한 방법은 위치를 올림하는 방식이야. 다른 도구는 값을 사이에서 보간할 수도 있으니, 숫자만 쓰지 말고 계산 약속을 함께 적어야 해.”
비교표는 이름이 ‘전’과 ‘후’ 두 종류일 때만 받아들였다. 각 종류는 정확히 서른 줄이어야 했다. 전 서른 줄과 후 서른 줄, 모두 예순 줄이면 요약표를 만들었다. 한 줄이 빠져 쉰아홉 줄이 되거나, ‘다른 것’이라는 세 번째 이름이 하나라도 끼거나, 아예 빈 표가 오면 숫자를 그럴듯하게 계산하지 않고 입력 오류로 돌려보냈다.
“그러면 후가 전보다 빨라졌다는 것도 확인한 건가요?” 히토리가 물었다.
“아니.” 니지카가 답했다. “표 모양과 계산법을 확인했을 뿐이야. 실제 시간 자료를 측정해 넣은 것도 아니고, 후가 더 작다고 비교하는 채점도 없어.”
이 숫자 연습 네 가지는 마지막 봉투에서 한꺼번에 다시 실행됐다. 창구 상한과 결과 천 장, 도달할 수 없는 준비 깃발의 실패, 1부터 30의 가운데와 느린 지점, 전후 표의 정확한 모양이었다. 그래서 마지막 봉투 하나가 확인 도장 네 개를 만들었다. 봉투 수와 실제 확인 횟수가 다른 가장 큰 이유였다.
한편 앞 연습에서 가져온 반대 방향 이체 확인도 다시 펼쳐졌다. 두 카드의 시작 잔액은 각각 10,000원이었다. 한 방향 열 건, 반대 방향 열 건, 모두 스무 작업이 각각 100원씩 옮겼다. 준비 깃발 스무 개와 출발 종 하나를 썼고, 각 결과표를 최대 30초씩 기다렸다.
스무 결과표가 모두 예외 없이 돌아온 뒤 두 카드의 잔액 합은 20,000원이었다. 이체 장부의 부호 있는 금액을 모두 더하면 0이었다.
키타가 두 카드 아래에 각각 10,000원을 적으려 하자 니지카가 멈췄다. “방향과 금액이 대칭이라 그렇게 끝날 거라고 예상할 수는 있어도, 이 확인의 마지막 채점은 카드별 10,000을 따로 묻지 않아. 합계 20,000과 장부 합 0이 직접 증거야.”
실제 교착을 일부러 일으키는 비교표도 없었다. 자동 재시도나 느린 기다림의 분포, 모든 부하에서의 안전도 확인하지 않았다. 앞 연습의 정렬된 열쇠 경로가 이 두 카드와 스무 작업에서 끝났다는 범위만 다시 확인했다.
계산대 아래에서는 애플리케이션 카드와 분리된 SQL 연습장 두 권이 나왔다. 첫 장에는 완료된 이체 하나와 그 아래의 장부 줄들이 그려져 있었다.
거래표 301번을 장부표에 이어 붙이자 같은 거래 번호 아래 두 줄이 나왔다. 101번 카드에서 300원이 나간 줄 하나, 102번 카드로 300원이 들어온 줄 하나였다. 거래 한 행이 장부 두 행과 이어졌으므로 결과가 두 행이 된 것이다.
하지만 모든 이체가 완전하다고 가정하면 안 됐다. 거래표 302번에는 101번 카드에서 200원이 나간 줄 하나만 있었고 들어온 줄은 일부러 빠져 있었다. 그래서 모든 이체 거래를 한꺼번에 붙이면 301번의 두 줄과 302번의 한 줄, 모두 세 줄이었다. 301번만 골라 ‘한 거래가 두 줄로 늘어나는 모양’을 볼 수는 있지만, 그것을 모든 거래가 완전하다는 증명으로 넓히지 않았다.
이 연습장에는 복사할 정본 답안이 없었다. 시작 표, 한 행의 뜻, 예상 행 수와 불완전한 반례를 스스로 정해 실제 실행 기록으로 남겨야 했다. 301번을 좁혀 두 행을 보는 예시는 한 가지 학습 답안일 뿐, 제공된 유일 정답이 아니었다.
둘째 장은 손님마다 카드가 몇 장인지 세는 문제였다. 손님은 여섯 명, 카드는 여덟 장이었다. 1번·2번·3번 손님은 각각 카드 두 장, 4번은 한 장, 5번은 영 장, 6번은 한 장이었다.
“카드가 없는 5번 손님도 결과에 넣을까요?” 히토리가 물었다.
“문제가 바로 그 선택을 적으라고 해.” 니지카가 답했다. “모든 손님을 왼쪽에 남기고 카드를 붙이면 5번도 영 장으로 나와서 여섯 행이 돼. 카드가 있는 손님에서 시작하면 5번은 사라져 다섯 행이 되지.”
영 장을 포함하는 예시에서는 빈 연결을 하나로 잘못 세지 않도록 카드 번호를 셌다. 손님 행 전체를 세면 카드가 없어도 한 행이 남아 1로 보일 수 있었다.
이 문제도 제공된 정본 답안 파일은 없었다. 영 장 손님을 포함할지 제외할지 가정을 먼저 적고, 그 선택과 맞는 시작 표·연결 방식·예상 행 수를 증거로 남겨야 했다. 니지카는 영 장을 포함하는 여섯 행 예시를 골랐지만, 그 선택을 숨긴 채 결과만 내놓지 않았다.

마감표에는 세 종류의 증거가 나란히 놓였다. 새로 들어온 일반 창구 확인 네 가지, 새로 들어온 스무 출금 확인 한 가지, 앞 연습에서 가져온 반대 방향 이체 확인 한 가지였다. 서로 다른 확인은 여섯 개였고, 최종 통과 실행에서 실제 찍힌 확인 도장은 아홉 개였다.
일반 창구 확인은 모형 업무 천 장에서 직원 수 상한, 결과 수 보존, 준비 시간 초과 실패, 작은 숫자의 통계 계산과 전후 표 모양을 보장했다. 실제 금고 처리량이나 운영 속도는 보장하지 않았다.
스무 출금 확인은 한 번의 데이터베이스 실행에서 성공 10·잔액 부족 10·기술 장애 0·잔액 0·출금 장부 10줄을 확인했다. 서른 번 반복, 천 건 실제 부하, 지연 백분위, 같은 요청표의 중복 방지는 확인하지 않았다.
반대 방향 이체 확인은 스무 결과표 회수, 잔액 합 20,000, 이체 장부 합 0을 다시 확인했다. 카드별 잔액, 실제 교착 재현, 자동 재시도, 보편적인 안전은 확인하지 않았다.
히토리는 마지막 칸에 ‘모든 것이 안전하다’라고 쓰려다 멈췄다. 대신 ‘어떤 무대에서 무엇을 직접 봤는가’를 숫자와 함께 적었다.
니지카는 확인표를 한 번 더 뒤집었다. 앞면에는 통과한 숫자가 있었고, 뒷면에는 그 숫자를 만들지 않은 조건이 적혀 있었다. 모형 직원이 천 장을 처리한 컴퓨터와 실제 스무 출금이 돈을 움직인 금고는 같은 상자가 아니었다. 작은 통계 자의 서른 값도 실제 응답 시간을 서른 번 잰 기록이 아니었다. 같은 ‘천’과 ‘서른’이 보여도 무엇을 세었는지부터 확인해야 했다.
키타는 숫자 옆에 단위를 붙였다. 천은 모형 task, 서른은 독립 벡터와 variant별 sample 행, 스무는 실제 출금 요청과 이월 이체 작업이었다. 단위가 붙자 서로 빌려 쓸 수 없는 증거가 눈에 보였다. 히토리는 마지막으로 ‘한 번 관찰’과 ‘언제나 보장’ 사이에도 굵은 선을 그었다.
“결과가 많아질수록 짧게 말하기가 어려워져요.” 히토리가 말했다.
“그래서 숫자를 버리는 게 아니라 상자를 나누는 거야.” 니지카가 답했다. “모형 창구, 실제 출금, 이월 이체, SQL 예시. 각 상자의 경계를 붙이면 쉬운 설명도 정확할 수 있어.”
료는 요청표 이름이 적힌 빈 상자를 계산대 가운데 놓았다. “다음에는 같은 이름의 요청이 쉰 번 도착해도 돈은 한 번만 움직여야 해.”
키타가 상자에 ‘첫 요청의 주인’이라는 표를 붙였다. 히토리는 스무 명의 경쟁보다 같은 의도 쉰 번이 더 무섭다고 생각했지만, 이번에는 도망가지 않고 다음 연습의 첫 줄을 적었다.
“기록된 이름과 한 번만 처리한다는 약속은 다르다.”
그 문장 아래에는 성공 열 장, 정상 거절 열 장, 기술 장애 영 장, 잔액 영 원, 장부 열 줄이 가지런히 놓여 있었다.
이미지 출처와 이용 안내: 공식 장면컷은 TV 애니메이션 《봇치 더 록!》 공식 사이트 자료입니다. ©はまじあき/芳文社・アニプレックス. 이 문서는 개인 학습용 비공식 구성으로 원작의 공식 설정과 별개이며, 개념 그림은 실제 W11 소스와 SQL workbook seed를 바탕으로 새로 만든 교육용 SVG입니다.