수집 장치를 늘리려고 API 계정을 더 만들었다. 상대 쪽 화면에서 아무 경고 없이 만들어졌고 며칠 동안 잘 돌았다.
그러다 새로 만든 계정이 전부 정지됐다.
Table of contents
Open Table of contents
계약에 개수 제한이 있었다
연락해 보고 계약서를 다시 꺼내 읽었다.
동시 접속 계정: 최대 10개
초과 시 계정 정지 및 별도 협의
우리는 14개를 만들어 쓰고 있었다. 상대 쪽 화면이 안 막았으니 되는 줄 알았다.
만들어진다는 것과 써도 된다는 것은 다른 이야기였다. 그 둘을 같은 것으로 본 것이 이번 일의 시작이었다.
원인 — 두 종류의 한도
정리해 보니 우리가 지켜야 할 한도가 두 종류였다.
| 종류 | 확인처 | 넘으면 |
|---|---|---|
| 기술 한도 | API 문서, 응답 헤더 | 오류 응답 |
| 계약 한도 | 계약서, 요금제 | 정지·과금·협의 |
기술 한도는 시스템이 감당할 수 있는 선이고 계약 한도는 지불한 금액이 정하는 선이다. 대개 계약 쪽이 더 낮다.
성질도 달랐다. 기술 한도를 넘으면 HTTP 응답이 그 자리에서 거부로 돌아오므로 바로 안다.
계약 한도는 넘어도 당장은 아무 일이 없다. 상대 쪽이 정산하거나 점검하다가 발견하고 그때 조치가 오는데 며칠에서 몇 주가 걸린다. 그동안 그것을 전제로 만들어 둔 것이 한꺼번에 무너진다.
계약서에서 확인할 것을 목록으로 만들었다
연동마다 계약서를 다시 읽고 같은 항목을 뽑아 적었다.
연동 A
계정 수 10개
일 요청 100,000건
동시 연결 50
저장 기간 90일
용도 제한 자사 서비스에 한함, 재판매 불가
연동 B
계정 수 제한 없음
월 요청 1,000,000건 (초과분 건당 과금)
...
개수와 요청량과 보관 기간은 숫자라 재기 쉽다. 그런데 용도 제한이 가장 걸렸다.
재판매 불가 같은 조항은 기술적으로는 아무것도 막지 않는다. API 는 누가 쓰든 똑같이 응답하므로 코드로는 확인할 수가 없다. 사람이 읽고 기억하는 수밖에 없어서 문서에 크게 적었다.
검증 — 지금 얼마나 쓰는지 세기
한도를 알았으니 현재 사용량을 셌다.
SELECT COUNT(DISTINCT account_id) FROM api_account WHERE use_yn='Y';
SELECT COUNT(*) FROM api_log WHERE DATE(reg_date) = CURDATE();
api_account 에서 활성 계정 수를 세고 api_log 에서 당일 요청 수를 센다. 이 둘을 매일 한 줄로 기록했다.
2016-10-24 계정 10/10 요청 42,180/100,000
절대 수만 적으면 그것이 많은지 적은지 모른다. 한도를 옆에 붙여 적으니 여유가 얼마나 남았는지가 한눈에 보였다.
한도에 가까워지면 알렸다
기록만 해서는 아무도 안 본다. 비율이 올라가면 먼저 알리게 했다.
$ratio = $used / $limit;
if ($ratio > 0.8) {
notify("연동 A 사용량 " . round($ratio * 100) . "% ({$used}/{$limit})");
}
$ratio 가 0.8을 넘으면 notify 로 알린다. 백 퍼센트가 되기 전에 협의할 시간을 벌자는 것이다.
계정 수는 성격이 달라서 만드는 자리에서 아예 막았다.
$cnt = $this->countActiveAccounts();
if ($cnt >= CONTRACT_ACCOUNT_LIMIT) {
return error("계약 한도 {$cnt}개에 도달했습니다. 담당자 협의가 필요합니다.");
}
countActiveAccounts 로 센 값이 CONTRACT_ACCOUNT_LIMIT 에 닿으면 화면에서 거부한다. 상대 쪽이 안 막아 준다면 우리 쪽에서 막는 것이 맞았다.
설정 — 한도와 그 출처를 같이 적기
한도 값을 코드에 넣을 때 숫자만 넣지 않고 근거를 붙였다.
// 계약서 3조 2항 (2016-08-01 체결). 변경 시 담당자 확인 필요
define('CONTRACT_ACCOUNT_LIMIT', 10);
define('CONTRACT_DAILY_LIMIT', 100000);
숫자만 있으면 나중에 누군가 답답하다고 임의로 늘린다. 어느 조항에서 온 값인지가 옆에 있으면 고치기 전에 확인하게 된다.
이름도 MAX_ 가 아니라 CONTRACT_ 로 시작하게 했다. 기술 한도가 아니라 계약 한도라는 것이 이름에서 드러나야 했다.
계약이 바뀌면 코드도 바꾼다
계약을 갱신하면서 계정 한도가 20개로 늘어난 적이 있었다. 그런데 CONTRACT_ACCOUNT_LIMIT 를 안 고쳐서 열한 번째 계정이 안 만들어졌다.
이번에는 반대로 계약보다 코드가 더 엄격했던 것이다. 그래서 갱신할 때 볼 것을 목록으로 만들었다.
계약 갱신 확인 목록
- 계정 한도가 바뀌었나 → 코드 상수 갱신
- 요청 한도가 바뀌었나 → 감시 임계 갱신
- 용도 제한이 바뀌었나 → 관련 기능 검토
- 만료일 → 달력에 등록
만료일 등록이 특히 쓸모 있었다. 만료 한 달 전에 알림이 오게 해 두니 협의를 미리 시작할 수 있었다.
계약 밖의 제약 세 가지
계약서만 본다고 끝이 아니었다. 코드로는 되는데 하면 안 되는 것이 세 종류 더 있었다.
법적 제약은 개인정보 보관 기간과 국외 이전 제한 같은 것이다. 상대의 정책은 문서에 없지만 운영 기준으로 막는 것이고 내부 규정은 어느 자료를 밖으로 보낼 수 있는지를 정한다.
셋 다 API 응답으로는 확인이 안 된다. 그래서 연동 문서에 기술 규격과 나란히 적었다. 규격만 적어 두면 다음 사람이 같은 선을 또 넘는다.
정리
- 동작하는 것과 써도 되는 것은 다르다
- 기술 한도는 시스템이 정하고 계약 한도는 금액이 정한다
- 기술 한도는
HTTP응답으로 바로 알고 계약 한도는 나중에 온다 - 계약서에서 개수·요청량·기간·용도 제한을 뽑아 목록으로 만든다
- 사용량을 한도와 나란히 기록하고
$ratio가 0.8을 넘으면 알린다 - 개수 제한은
countActiveAccounts로 만드는 자리에서 막는다 - 한도를 코드에 적을 때 계약 조항을 출처로 남긴다
- 갱신 확인 목록에 상수 갱신과 만료일 등록을 넣는다
- 법적 제약·상대 정책·내부 규정도 연동 문서에 같이 적는다