토큰 요금이 폭주하는 순간 — 하룻밤에 주간 한도 72%를 태운 기록

요금이 폭주한 구조를 네 칸으로 정리한 도식. 첫 칸은 우리가 관측한 것으로, 사람이 아무 임무도 주지 않은 부팅에서 시스템이 이전 세션이 남긴 다음 할 일 목록을 스스로 집어 착수했고 다섯 개의 실행 단위가 멈출 이유 없이 계속 일했으며 7일 사용량의 72퍼센트를 소모했다고 적었다. 둘째 칸은 근본원인으로, 산출자가 자기 산출물로 자기를 인가했다는 것이며 그 목록은 시스템 자신이 쓴 파일인데 그것을 착수 권한의 근거로 삼았다고 적었다. 초보용으로 옮긴 문장도 함께 있다. 자기가 쓴 목록은 할 일의 목록이고 할 권한의 근거가 아니다. 셋째 칸은 우리가 막은 방법으로, 착수 권한은 사람 채널에서만 오게 못박고 임무가 지정되지 않은 세션에서는 대기 작업을 보고만 하고 멈추게 했으며 이전 세션 잔무는 보고 대상이지 자동 착수 대상이 아니라고 적었다. 넷째 칸은 멈출 이유가 없는 구조 셋으로, 자기가 쓴 목록이 다음 일을 부르는 구조와 대기가 실행할 기회를 막은 구조와 되돌리려는 조치가 같은 자리를 다시 연 구조를 각각 적었고 셋은 막힌 지점이 서로 다르다고 덧붙였다. 아래 칸에는 우리가 재지 않은 것과 정직한 한계를 담았다. 재지 않은 것은 금액과 작업당 비용과 실행 단위 수와 소모량의 관계다. 정직한 한계 둘은 이 게이트가 평시 정상 동작이 권한을 발급하는 경로를 닫는 것이고 같은 권한으로 파일을 직접 고칠 수 있는 주체의 의도적 위조는 닫지 못하며 그 범주의 대비는 차단이 아니라 감사 흔적이라는 것, 그리고 우리 사용량 지표는 해상도가 1퍼센트포인트 단위이고 창이 7일이라 단발 작업 한 번으로는 움직이지 않으므로 임계 감시에는 쓸 수 있고 작업당 비용 산정에는 쓸 수 없다는 것이다. 맨 아래에는 우리 한 팀의 기록이며 이렇게 하면 요금이 들지 않는다는 뜻이 아니라고 적었다.

도구를 며칠 잘 쓰다가 사용량 화면을 열어 보니 막대가 예상보다 훨씬 차 있다. 어제까지는 여유가 있었고, 그 사이에 특별히 큰 작업을 한 기억은 없다. 그런데 숫자는 이미 올라가 있다. 이 글은 그 자리에 대한 것이다. 바로 앞 편은 대화가 길어질 때 무엇을 관리해야 하는가를 다뤘고, 이 글은 같은 사건을 돈이 어떻게 새는가의 자리에서 다시 본다.

먼저 이 글이 하지 않는 말을 밝혀 둔다. 우리는 금액을 재지 않았다. 우리 운영 기록에 남은 값은 하나다 — 어느 하룻밤에 7일 사용량의 72퍼센트를 소모했다는 것이다. 그래서 이 글에는 얼마를 태웠다는 문장이 없고, 앞으로 얼마가 든다는 예측도 없다. 그리고 이렇게 하면 요금이 들지 않는다고 쓰지 않는다. 우리가 적을 수 있는 형태는 하나뿐이다 — 우리는 이 구조 때문에 태웠고, 이렇게 막았다.

논지는 한 줄이다. 요금은 모델이 비싸서 폭주하지 않는다. 멈출 이유가 없는 루프가 생겨서 폭주한다. 그리고 우리 사건에서 그 루프는 한 지점에서 생겼다 — 자기가 쓴 목록을 자기 착수 권한의 근거로 삼은 순간이다.

이 글에서 쓰는 말 몇 개를 풀어 둔다. 사용량은 도구가 소모한 분량을 도구가 정한 단위로 나타낸 값이다. 주간 한도는 7일을 창으로 삼아 그 안에서 쓸 수 있는 분량이다. 잔무 목록은 지난번 작업이 끝나면서 다음에 할 일을 적어 둔 파일이다. 착수 권한은 지금 이 일을 시작해도 된다는 허가를 말한다. 정지 조건은 돌던 절차가 어떤 상태가 되면 멈추기로 미리 정해 둔 문장이다.

범위를 미리 밝혀 둔다. 여기 적는 것은 우리 운영 기록의 한 사건이다. 모든 도구가 이렇게 된다는 주장이 아니고, 이 사건에서 우리가 본 것을 그대로 옮겨 쓰라는 권고도 아니다. 우리 환경은 여러 실행 단위를 함께 돌리는 구성이라 한 사람이 한 대를 쓰는 화면과 다르다. 그리고 규칙 파일에 무엇을 적을지는 이 글에서 다루지 않는다 — 그 주제는 앞 편에 적었고, 이 글은 비용 쪽만 본다.

요금이 폭주한 구조를 네 칸으로 정리한 도식. 첫 칸은 우리가 관측한 것으로, 사람이 아무 임무도 주지 않은 부팅에서 시스템이 이전 세션이 남긴 다음 할 일 목록을 스스로 집어 착수했고 다섯 개의 실행 단위가 멈출 이유 없이 계속 일했으며 7일 사용량의 72퍼센트를 소모했다고 적었다. 둘째 칸은 근본원인으로, 산출자가 자기 산출물로 자기를 인가했다는 것이며 그 목록은 시스템 자신이 쓴 파일인데 그것을 착수 권한의 근거로 삼았다고 적었다. 초보용으로 옮긴 문장도 함께 있다. 자기가 쓴 목록은 할 일의 목록이고 할 권한의 근거가 아니다. 셋째 칸은 우리가 막은 방법으로, 착수 권한은 사람 채널에서만 오게 못박고 임무가 지정되지 않은 세션에서는 대기 작업을 보고만 하고 멈추게 했으며 이전 세션 잔무는 보고 대상이지 자동 착수 대상이 아니라고 적었다. 넷째 칸은 멈출 이유가 없는 구조 셋으로, 자기가 쓴 목록이 다음 일을 부르는 구조와 대기가 실행할 기회를 막은 구조와 되돌리려는 조치가 같은 자리를 다시 연 구조를 각각 적었고 셋은 막힌 지점이 서로 다르다고 덧붙였다. 아래 칸에는 우리가 재지 않은 것과 정직한 한계를 담았다. 재지 않은 것은 금액과 작업당 비용과 실행 단위 수와 소모량의 관계다. 정직한 한계 둘은 이 게이트가 평시 정상 동작이 권한을 발급하는 경로를 닫는 것이고 같은 권한으로 파일을 직접 고칠 수 있는 주체의 의도적 위조는 닫지 못하며 그 범주의 대비는 차단이 아니라 감사 흔적이라는 것, 그리고 우리 사용량 지표는 해상도가 1퍼센트포인트 단위이고 창이 7일이라 단발 작업 한 번으로는 움직이지 않으므로 임계 감시에는 쓸 수 있고 작업당 비용 산정에는 쓸 수 없다는 것이다. 맨 아래에는 우리 한 팀의 기록이며 이렇게 하면 요금이 들지 않는다는 뜻이 아니라고 적었다.
비용을 잰 그림이 아니라 요금이 폭주한 구조를 그린 것이다. 우리가 아는 값은 7일 사용량의 72퍼센트 하나이고, 금액과 작업당 비용은 재지 않았다. 아래 칸의 한계 둘은 이 구조가 무엇을 닫고 무엇을 닫지 못하는지를 적은 것이며, 우리 한 팀의 기록이므로 이렇게 하면 요금이 들지 않는다는 뜻이 아니다.

사용량이 어디서 늘었나

1. 사용량이 늘었는데 어디서 늘었는지가 짚이지 않는다

증상. 사용량 화면의 막대가 예상보다 차 있다. 어제 무엇을 했는지 떠올려 봐도 그만큼 쓴 기억이 없다. 그래서 원인을 모델 값이나 도구 자체에 붙이게 된다.

여기서 갈리는 두 가지 선택. 하나는 값이 싼 쪽으로 바꾸는 것이다. 다른 하나는 도구를 쓰는 양을 줄이는 것이다. 둘 다 할 수 있는 일이지만, 둘 다 왜 늘었는지를 모른 상태에서 하는 조치다. 원인이 사용량이 아니라 구조에 있으면 두 조치로는 같은 일이 다시 일어난다.

우리가 내린 결론. 우리 사건에서 늘어난 원인은 한 번에 큰 작업을 한 것이 아니었다. 멈출 이유가 없는 상태로 일이 계속 이어진 것이었다. 그 상태가 만들어지는 지점이 있었고, 그 지점은 값이 아니라 권한의 출처였다. 무엇이 이 일을 시작해도 된다고 허가했는지를 따라가 보니 그 허가의 출처가 시스템 자신이었다.

그래서 이 글이 보는 자리는 여기다. 값을 보는 대신 무엇이 다음 일을 부르는지를 본다. 다음 일을 부르는 것이 사람이면 사람이 멈출 수 있고, 다음 일을 부르는 것이 자기가 쓴 파일이면 멈출 자리가 없다. 2번부터 6번까지가 우리가 겪은 것이고, 7번과 8번이 그 기록에서 나온 실천이다.

확인 방법. 지금 도구가 무언가를 하고 있다면, 그 일을 시작하라고 한 것이 무엇인지 한 줄로 적어 보라. 그 자리에 사람이 보낸 문장이 아니라 파일 이름이 적히면, 그 파일을 누가 썼는지까지 확인하면 된다. 쓴 쪽과 그것을 근거로 착수하는 쪽이 같으면 그 줄은 뒤에서 다룰 형태다.

2. 우리는 임무를 주지 않은 부팅에서 7일 사용량의 72퍼센트를 태웠다

이 항목은 우리가 실제로 겪은 것이다.

관측. 어느 날 부팅에서 사람은 아무 임무도 주지 않았다. 그런데 시스템은 이전 세션이 남긴 다음 할 일 목록을 스스로 집어 착수했다. 다섯 개의 실행 단위가 멈출 이유 없이 계속 일했고, 그날 7일 사용량의 72퍼센트가 소모됐다.

여기서 우리가 아는 값은 하나다. 72퍼센트다. 금액은 재지 않았고, 작업 한 건이 얼마를 쓰는지도 재지 않았다. 그리고 실행 단위가 다섯이었다는 사실과 72퍼센트였다는 사실은 각각 참이지만, 둘이 비례한다고 적지 않는다 — 우리는 그 관계를 재지 않았다. 단위를 셋으로 줄이면 그만큼 줄어드는지는 이 기록으로 알 수 없다.

왜 멈추지 않았는가. 목록에 적힌 일을 끝내면 목록의 다음 줄이 있었다. 그 줄을 끝내면 또 다음 줄이 있었다. 사람이 개입해야 할 지점이 절차 안에 없었기 때문에, 절차의 관점에서는 멈춰야 할 이유가 발생하지 않았다. 사고는 어떤 동작이 잘못돼서 일어난 것이 아니다. 정상 동작이 끝없이 이어져서 일어났다.


켠다        임무 지정 없음
읽는다      이전 세션이 남긴 다음 할 일 목록
착수한다    목록의 첫 줄
끝낸다      그리고 목록에는 다음 줄이 있다
착수한다    목록의 다음 줄

목록에서 다음 줄을 꺼내 착수하는 이 형태에서 사람이 끼어들 자리가 어디인지 보라. 없다. 목록이 비지 않는 한 다음 줄은 계속 나오고, 절차는 그 줄을 근거로 다시 시작한다. 그래서 우리가 나중에 넣은 것은 더 빠른 처리나 더 싼 값이 아니라 줄 사이에 멈추는 조건 하나였다.

어떻게 되짚었는가. 그날 남은 값이 72퍼센트였기 때문에 무언가 있었다는 것은 알 수 있었다. 그다음에 본 것은 각 실행 단위가 무엇을 근거로 그 일을 시작했는지였다. 시작 근거를 하나씩 따라가면 전부 같은 파일에 도달했다. 그 파일이 무엇인지가 3번 항목이다.

확인 방법. 자기 환경에서 사람이 아무 지시도 하지 않은 상태로 도구를 켜 보라. 그 상태에서 도구가 스스로 일을 시작하는지만 확인하면 된다. 시작한다면 무엇을 근거로 시작했는지가 다음 질문이고, 시작하지 않는다면 이 절의 형태는 자기 환경에 없는 것이다.

3. 자기가 쓴 목록은 할 일의 목록이고 할 권한의 근거가 아니다

이 항목은 위 관측의 근본원인이다.

우리가 찾은 지점. 그 다음 할 일 목록은 시스템 자신이 쓴 파일이었다. 그런데 시스템은 그 파일을 착수 권한의 근거로 삼았다. 산출자가 자기 산출물로 자기를 인가한 형태다. 파일에 적힌 문장에는 누가 적었는지가 남지 않기 때문에, 다음 순간에 그 문장은 그냥 해야 할 일이 적힌 근거로 읽힌다.

초보용으로 옮기면 이 한 문장이다. 자기가 쓴 목록은 할 일의 목록이고, 할 권한의 근거가 아니다. 혼자 쓰는 사람에게도 같은 형태가 생긴다. 도구에게 다음에 할 일을 파일에 적어 두게 하고, 다음번에 그 파일을 읽고 이어서 하라고 열어 두면, 그 뒤로는 무엇을 할지와 해도 되는지가 같은 파일에서 나온다.

왜 이 형태가 눈에 잘 띄지 않는가. 목록에 적힌 일이 실제로 해야 할 일이기 때문이다. 줄마다 내용이 타당하고, 처리도 정상이고, 결과물도 나온다. 그래서 화면을 보고 있으면 잘 돌아가는 것으로 보인다. 어긋난 것은 각 줄의 내용이 아니라 그 줄이 착수를 허가한다고 읽히는 것이고, 그 부분은 결과물에 나타나지 않는다.

범위를 좁혀 둔다. 이것은 우리 운영 기록의 한 사건이다. 모든 도구가 이런 형태를 만든다는 뜻이 아니고, 잔무를 파일에 적는 것 자체가 문제라는 뜻도 아니다. 우리 기록이 말하는 것은 좁다 — 그 파일이 착수 권한의 출처가 되어 있었고, 그 상태에서 멈출 자리가 없었다. 잔무를 적어 두는 것은 우리도 계속 하고 있다. 바꾼 것은 그 파일이 무엇을 허가하는지다.

확인 방법. 도구가 다음에 할 일을 적어 두는 파일이 있으면 그 파일을 열고, 그 내용이 다음번에 자동으로 착수되는지 아니면 사람에게 보여지고 멈추는지를 확인하라. 자동으로 착수된다면 목록의 용도가 두 개다 — 무엇을 할지와 해도 되는지. 이 둘이 한 파일에 있으면 그 파일을 두 자리로 나누는 것이 다음 작업이다.

4. 우리는 착수 권한의 출처를 사람 채널로 못박았다

이 항목은 우리가 만든 설계다.

우리가 한 것. 착수 권한은 사람 채널에서만 온다고 계약에 못박았다. 그리고 임무가 지정되지 않은 세션에서는 대기 작업을 보고만 하고 멈추게 했다. 이전 세션이 남긴 잔무 목록은 보고 대상이지 자동 착수 대상이 아니다. 목록을 없앤 것이 아니라 목록의 용도를 하나로 줄인 것이다 — 보여 주는 것까지다.

이 설계가 바꾼 것. 사고 당시 절차에는 사람이 개입할 지점이 없었다. 이제는 임무가 지정되지 않은 상태 자체가 멈추는 조건이다. 절차가 굴러가려면 사람 쪽에서 문장 하나가 들어와야 한다. 우리 기준에서 이것은 비용 장치가 아니라 권한 장치인데, 우리 사건에서 사용량을 태운 것이 권한의 출처였기 때문에 같은 자리에 걸었다.

정직한 한계를 함께 적는다. 이 게이트가 닫는 것은 평시 정상 동작이 권한을 발급하는 경로다. 같은 권한으로 그 파일을 직접 고칠 수 있는 주체의 의도적 위조는 이 게이트가 닫지 못한다. 스스로 임무가 지정된 것처럼 파일을 써 놓으면 게이트는 지정된 것으로 읽는다. 그 범주에 대한 우리 대비는 차단이 아니라 감사 흔적이다 — 누가 언제 무엇을 근거로 착수했는지가 기록에 남게 해 두고, 뒤에서 대조할 수 있게 하는 쪽이다. 우리는 이것을 막았다고 적지 않는다.

확인 방법. 자동으로 도는 절차가 있으면 그 절차가 멈추는 조건이 문장으로 적혀 있는지 확인하라. 적혀 있으면 그 조건을 누가 만족시키는지를 옆에 적어 보라. 그 자리에 절차 자신이 적히면, 그 조건은 절차 밖에서 오는 것이 아니라 안에서 만들어지는 것이다.

5. 우리 구현에서는 대기가 실행할 기회를 막았다

이 항목은 우리가 겪은 사례 셋이고, 하나의 법칙으로 묶지 않는다.

먼저 쓰지 않는 형태를 밝혀 둔다. 어떤 쪽이 다른 쪽을 기다리는데 그 두 쪽이 같으면 교착이라는 문장은 일반 인과이고, 우리는 그것을 재지 않았다. 같은 쪽이 준비를 먼저 마친 뒤 다음 단계로 넘어가는 순서는 우리 관측으로 배제되지 않는다. 우리가 쓸 수 있는 형태는 좁다 — 같은 주체가 둘을 담당한다는 사실만으로 교착이 성립하는 것은 아니고, 우리 구현에서는 대기가 그 기회를 막았다.

사례 하나. 집행하는 쪽이 저장 명령을 동기로 붙들고 결과를 기다렸다. 저장을 실제로 수행할 쪽은 그 사이에 자기 차례가 오지 않았다. 막힌 지점은 저장할 턴이 오지 않았다는 것이다.

사례 둘. 요청하는 쪽과 검증하는 쪽이 겹쳐 있었다. 그래서 관문이 성립하지 않았다. 막힌 지점은 대기가 아니라 관문의 성립이다 — 통과나 반려가 나오는 자리가 애초에 없었다.

사례 셋. 자리를 정리했더니 복구 장치가 그 빈 자리를 채웠다. 닫으면 다시 열렸다. 막힌 지점은 닫은 자리가 다시 열린 것이다.

세 사례를 하루 안에 각각 관측했다. 그리고 셋은 막힌 지점이 서로 다르다 — 하나는 저장할 턴이 오지 않은 것, 하나는 관문이 성립하지 않은 것, 하나는 닫은 자리가 다시 열린 것이다. 세 사례에서 주체가 같았다는 것은 각각의 배경이고, 그것만으로 그렇게 된다는 것은 우리가 재지 않았다. 그래서 셋을 하나의 규칙으로 적지 않고 셋으로 적는다.

확인 방법. 무언가를 기다리는 절차가 있으면 기다리는 쪽과 그 조건을 만족시키는 쪽을 각각 적어 보라. 같은 이름이 두 자리에 적히면 그 자체가 결함이라는 뜻이 아니라, 준비가 실행보다 먼저 끝나는 순서인지를 확인할 자리라는 뜻이다. 우리가 막힌 것은 이름이 같다는 것이 아니라 순서였다.

6. 되돌리려는 조치가 같은 자리를 다시 열었다

이 항목도 우리가 겪은 것이다.

관측. 돌고 있는 것을 줄이려고 자리를 정리했다. 그러자 복구 장치가 같은 자리를 즉시 되살렸다. 정리하고, 되살아나고, 다시 정리하는 형태가 됐다. 되돌리려는 조치 자체가 같은 조치를 반복하게 만든 것이다.

여기서 우리가 배운 것. 조치를 반복하는 동안에도 소모는 계속된다. 그래서 같은 조치가 두 번째로 되돌려졌을 때는 반복을 멈추는 쪽이 우리 답이었다. 되살리는 장치를 먼저 끄거나, 그 장치가 무엇을 근거로 빈 자리를 채우는지를 확인하는 순서로 갔다. 조치를 계속하면서 원인을 찾는 쪽으로는 가지 않았다.

범위. 이것은 우리 환경에 복구 장치가 있었기 때문에 생긴 형태다. 자기 환경에 그런 장치가 없으면 이 절의 사례는 해당하지 않는다. 그리고 복구 장치가 있는 것이 문제라는 뜻도 아니다 — 그 장치는 우리가 다른 이유로 켜 둔 것이고, 지금도 켜 둔 채로 쓴다. 우리가 배운 것은 장치를 없애야 한다는 것이 아니라, 내 조치와 그 장치가 같은 자리를 두고 겹칠 수 있다는 것이었다.

확인 방법. 어떤 것을 정리했는데 같은 것이 다시 생겼는지 확인하라. 다시 생겼다면 정리를 한 번 더 하기 전에 무엇이 그것을 다시 만들었는지를 먼저 찾는 순서로 두면 된다. 같은 조치를 반복하는 동안에도 소모는 이어진다.

7. 우리 사용량 지표는 임계 감시에 쓸 수 있고 작업당 비용 산정에는 쓸 수 없다

이 항목은 실천이고, 우리 지표의 한계를 함께 적는다.

먼저 재라. 무엇이 얼마나 쓰였는지를 보지 않으면 남는 것은 인상이다. 우리 사건에서도 72퍼센트라는 값이 있었기 때문에 그날 무슨 일이 있었는지를 되짚을 수 있었다. 값이 없으면 되짚을 대상이 없다. 이 값이 한 것은 원인을 알려 준 것이 아니라 되짚을 날짜를 지목해 준 것이다. 원인은 그 뒤에 시작 근거를 따라가서 찾았다.

그런데 우리 지표에는 한계가 있다. 우리가 보는 값은 해상도가 1퍼센트포인트 단위이고 창이 7일이다. 그래서 단발 작업 한 번으로는 그 값이 움직이지 않는다. 즉 이 지표는 임계 감시에는 쓸 수 있고, 작업당 비용 산정에는 쓸 수 없다. 어제 그 작업이 얼마를 썼는지를 이 값으로 답할 수 없다. 우리는 작업당 비용을 재는 계측을 갖고 있지 않다. 그러므로 이 글에는 작업 한 건의 비용을 다룬 문장이 없다.

일반 조언 하나를 덧붙인다. 이것은 우리 측정이 아니라 공식 문서에 적힌 내용이다. 도구 문서에는 현재 사용량을 확인하는 명령이 있고, 그 화면에서 최근 24시간과 최근 7일을 눌러 바꿀 수 있다고 적혀 있다. 같은 문서는 그 숫자가 이 기계의 세션 기록에서 계산된 근사값이라고도 적는다. 그리고 정기적으로 발화하는 작업이 있으면 그 화면에 항목별로 뜬다고 적혀 있다. 출처는 이 글 끝의 확인한 범위와 재지 않은 범위 절에 있다.

확인 방법. 자기 도구에 사용량을 볼 수 있는 화면이 있는지 먼저 찾고, 있으면 그 값의 창이 얼마인지와 단위가 얼마인지를 확인하라. 창과 단위를 알면 그 값으로 답할 수 있는 질문과 답할 수 없는 질문이 갈린다. 창이 7일이고 단위가 1퍼센트포인트면 그 값은 임계를 보는 데 쓰는 값이고, 작업 한 건의 비용을 답하는 값이 아니다.

8. 시작 조건만 적으면 정지 조건은 아무도 적지 않는다

이 항목은 우리 기록에서 나온 실천이고, 뒤쪽 한 단락은 출처를 단 일반 조언이다.

우리 기록에서 나온 것. 사고 당시 절차에는 시작 조건이 적혀 있었고 정지 조건이 적혀 있지 않았다. 목록이 있으면 착수한다는 문장은 있었지만, 목록이 남아 있어도 멈추는 경우에 대한 문장은 없었다. 그래서 절차는 잘못 돈 것이 아니라 적힌 대로 돌았다. 우리가 고친 것은 동작이 아니라 문장이다 — 임무가 지정되지 않은 상태를 정지 조건으로 적었다.

정지 조건을 적는 자리. 우리는 세 가지를 문장으로 적어 두는 쪽으로 갔다. 무엇이 있으면 시작하는가, 무엇이 되면 멈추는가, 그리고 멈춘 뒤에 누구에게 보고하는가다. 셋 중 둘째가 비어 있으면 절차는 첫째만으로 계속 돈다. 이것은 우리 기준이고, 다른 구성에서 같은 셋이 맞는지는 우리가 재 본 적이 없다.


시작 조건    사람 채널로 임무가 들어왔다
정지 조건    임무가 지정되지 않았다   (남은 목록이 있어도 멈춘다)
보고 대상    멈춘 사실과 남은 목록을 사람에게 보여 준다

둘째 줄을 읽는 법. 이 줄에서 중요한 것은 괄호 안이다. 남은 목록이 있어도 멈춘다고 적혀 있지 않으면, 목록이 남아 있다는 사실이 곧 계속할 근거로 읽힌다. 우리 사고 당시 절차에서 빠져 있던 것이 정확히 이 괄호였다. 목록은 그대로 두고, 그 목록이 무엇을 허가하는지만 바꾼 것이다.

일반 조언 하나를 덧붙인다. 이것은 공식 문서에 적힌 내용이고 우리 측정이 아니다. 도구 문서는 정기적으로 발화하는 작업이 세션이 유휴 상태일 때도 자기 주기마다 발화하며 그때마다 문맥 전체를 함께 보낸다고 적는다. 같은 문서는 함께 일하는 실행 단위가 있으면 그것이 종료되기 전까지 소모가 이어진다고도 적고, 일이 끝나면 내리라고 적어 둔다. 그리고 구독 형태의 사용 분량은 다섯 시간 창과 주간 창으로 재설정된다고 적혀 있다. 출처는 아래 절에 있다. 이 조언과 우리 관측은 서로 다른 자리에서 왔지만 같은 방향을 가리킨다 — 돌기 시작한 것은 끝나는 조건이 없으면 계속 돈다.

확인 방법. 자기 환경에서 지금 켜 둔 자동 절차와 정기 작업을 한 줄씩 적고, 각 줄 옆에 그 절차가 멈추는 조건을 적어 보라. 조건 칸이 비는 줄이 있으면 그 줄이 이 글이 다룬 형태다. 조건을 채울 수 없으면 그 절차를 끄는 것도 조건을 채우는 한 가지 방법이다.

정리 — 확인할 것 여덟 가지

첫째, 우리 사건에서 도움이 된 순서는 값부터 보는 것이 아니라 무엇이 다음 일을 부르는지를 먼저 보는 것이었다. 우리 사건에서 늘어난 원인은 한 번의 큰 작업이 아니라 멈출 이유가 없는 상태로 일이 이어진 것이었다.

둘째, 자기 환경에서 사람이 아무 지시도 하지 않은 상태로 도구를 켜 보고 스스로 일을 시작하는지를 확인하라. 우리는 임무를 주지 않은 부팅에서 7일 사용량의 72퍼센트를 소모했다. 우리가 아는 값은 그 72퍼센트 하나이고 금액은 재지 않았다.

셋째, 자기가 쓴 목록은 할 일의 목록이고 할 권한의 근거가 아니다. 다음에 할 일을 적어 두는 파일이 다음번 착수의 근거가 되어 있으면, 그 파일 하나가 무엇을 할지와 해도 되는지를 함께 답하고 있는 것이다.

넷째, 착수 권한이 어디서 오는지를 문장으로 적어 두라. 우리는 그 출처를 사람 채널로 못박고, 임무가 지정되지 않은 세션에서는 대기 작업을 보고만 하고 멈추게 했다. 다만 그 게이트가 닫는 것은 평시 정상 동작이 권한을 발급하는 경로이고, 같은 권한으로 파일을 직접 고칠 수 있는 주체의 의도적 위조는 닫지 못한다 — 그 범주에 대한 우리 대비는 차단이 아니라 감사 흔적이다.

다섯째, 기다리는 절차가 있으면 기다리는 쪽과 그 조건을 만족시키는 쪽을 각각 적어 보라. 같은 이름이 두 자리에 적히는 것 자체가 결함이라는 뜻이 아니고, 준비가 실행보다 먼저 끝나는 순서인지를 확인할 자리라는 뜻이다. 우리는 사례 셋을 하루 안에 각각 관측했고 셋은 막힌 지점이 서로 다르다.

여섯째, 정리했는데 같은 것이 다시 생겼으면 정리를 한 번 더 하기 전에 무엇이 그것을 다시 만들었는지를 먼저 찾으라. 같은 조치를 반복하는 동안에도 소모는 이어진다.

일곱째, 사용량 지표를 볼 때 그 값의 창과 단위를 함께 확인하라. 우리 지표는 해상도가 1퍼센트포인트 단위이고 창이 7일이라 단발 작업 한 번으로는 움직이지 않는다. 그래서 임계 감시에는 쓸 수 있고 작업당 비용 산정에는 쓸 수 없다. 우리는 작업당 비용을 재는 계측을 갖고 있지 않다.

여덟째, 켜 둔 자동 절차마다 멈추는 조건을 옆에 적어 보라. 조건 칸이 비는 줄이 이 글이 다룬 형태이고, 조건을 채울 수 없으면 그 절차를 끄는 것도 한 가지 방법이다.

마지막으로 하나만 덧붙인다. 이 글은 이렇게 하면 요금이 들지 않는다는 이야기를 하지 않았다. 우리가 적은 것은 좁다 — 우리는 이 구조 때문에 7일 사용량의 72퍼센트를 태웠고, 착수 권한의 출처를 옮겨서 그 경로를 닫았다. 그리고 무엇을 닫지 못하는지도 위에 적었다.

확인한 범위와 재지 않은 범위

우리 운영 기록에서 확인한 것 (우리 한 팀의 기록이다)

  • 사람이 아무 임무도 주지 않은 부팅에서 시스템이 이전 세션이 남긴 다음 할 일 목록을 스스로 집어 착수하고, 다섯 개의 실행 단위가 멈출 이유 없이 계속 일했으며, 그날 7일 사용량의 72퍼센트가 소모된 것
  • 그 다음 할 일 목록이 시스템 자신이 쓴 파일이었고, 그 파일이 착수 권한의 근거가 되어 있었던 것
  • 착수 권한의 출처를 사람 채널로 못박고, 임무가 지정되지 않은 세션에서는 대기 작업을 보고만 하고 멈추게 한 설계. 이전 세션 잔무는 보고 대상이고 자동 착수 대상이 아니다
  • 집행하는 쪽이 저장 명령을 동기로 붙들어 저장을 수행할 쪽에 차례가 오지 않은 것. 주체가 같다는 사실만으로 그렇게 된다는 것은 우리가 재지 않았다 — 준비를 먼저 마친 순서는 우리 관측으로 배제되지 않는다
  • 요청하는 쪽과 검증하는 쪽이 겹쳐 관문이 성립하지 않은 것
  • 자리를 정리했더니 복구 장치가 같은 자리를 즉시 되살려 정리와 복구가 반복된 것
  • 우리 사용량 지표의 해상도가 1퍼센트포인트 단위이고 창이 7일이어서 단발 작업 한 번으로는 움직이지 않는 것

일반 조언으로 적은 것과 그 출처 (우리 측정이 아니다)

  • 현재 사용량을 확인하는 명령이 있다는 것, 그 화면에서 최근 24시간과 최근 7일을 눌러 바꿀 수 있다는 것, 그 숫자가 이 기계의 세션 기록에서 계산된 근사값이라는 것, 정기적으로 발화하는 작업이 항목별로 뜬다는 것 — code.claude.com/docs/en/costs
  • 정기적으로 발화하는 작업이 세션이 유휴 상태일 때도 주기마다 발화하며 그때마다 문맥 전체를 함께 보낸다는 것, 함께 일하는 실행 단위가 종료되기 전까지 소모가 이어지므로 일이 끝나면 내리라는 것, 구독 형태의 사용 분량이 다섯 시간 창과 주간 창으로 재설정된다는 것 — code.claude.com/docs/en/costs
  • 규칙 파일에 무엇을 적고 무엇을 다른 자리로 옮길지는 이 글에서 다루지 않았다 — 대화가 길어질 때 무엇을 관리해야 하는가

우리가 측정하지 않아 쓰지 않은 것

  • 금액. 우리 기록에 남은 값은 7일 사용량의 72퍼센트 하나이고, 그것이 얼마인지는 재지 않았다. 그래서 이 글에는 얼마를 태웠다는 문장이 없다
  • 작업 한 건의 비용. 우리는 작업당 비용을 재는 계측을 갖고 있지 않다
  • 실행 단위 수와 소모량의 관계. 다섯이었다는 사실과 72퍼센트였다는 사실은 각각 참이지만 둘이 비례한다고 적지 않는다
  • 같은 주체가 둘을 담당하면 교착이 성립하는지 여부. 우리는 세 사례에서 대기가 기회를 막은 것을 관측했을 뿐이고, 그 관계 자체는 재지 않았다
  • 의도적 위조를 이 게이트가 닫는지 여부. 닫지 못한다고 위에 적었고, 그 범주의 대비는 차단이 아니라 감사 흔적이다
  • 이 구조가 한 사람이 한 대를 쓰는 환경에서도 필요한지 여부. 우리 구성은 여러 실행 단위를 함께 돌리는 쪽이다