728x90

1. 왜 지금 이 얘기가 나오나

요즘 옵저버빌리티 벤더들 데모를 보면 흐름이 다 비슷하다. 경보가 뜨면 AI가 알아서 관련 메트릭·로그·트레이스를 훑고, 최근 배포 내역과 연결하고, "○○ 서비스의 커넥션 풀 고갈로 보입니다, 3시간 전 배포 커밋 abc123이 유력합니다"라고 슬랙에 카드 하나를 던진다. 심하면 롤백 버튼까지 같이 붙여준다.

실무자 입장에서 이건 솔직히 매력적이다. 새벽 3시에 페이저 울리고, 눈 비비며 Grafana 대시보드 12개를 순회하고, 배포 채널 스크롤 올려가며 "누가 뭘 올렸지" 찾는 그 20분이 통째로 사라지니까. MTTR 그래프는 예쁘게 내려간다.

그런데 이번에 공유된 글이 찌르는 지점은 여기다. 그 20분은 낭비가 아니라 학습 시간이었다는 것. 대시보드를 헤매는 동안 엔지니어는 "아, 이 서비스는 DB 커넥션이 이렇게 흐르는구나", "이 큐가 밀리면 저쪽 API가 먼저 죽는구나"를 몸으로 익힌다. AI가 그 구간을 대신 걸어주면, 결과는 얻지만 지도는 안 남는다.

그리고 결국 AI가 못 푸는 장애 — 처음 보는 형태, 여러 시스템이 얽힌 것, 데이터 정합성이 깨진 것 — 만 사람에게 넘어온다. 그때 넘겨받는 사람이 시스템 감각이 없는 상태라면? 그게 이 글의 문제 제기다. 참고로 원문 전문을 확보하지 못해 세부 논거나 인용된 사례는 원문 확인이 필요하다.

2. 자동화의 아이러니: 40년 전에 이미 나온 얘기

이 현상은 새로운 게 아니다. 인간공학 쪽에서 Lisanne Bainbridge가 1983년에 쓴 "Ironies of Automation"이라는 유명한 논문이 있다. 핵심 주장 두 가지가 지금 AI SRE 상황에 그대로 꽂힌다.

  • 아이러니 1: 자동화는 쉬운 일부터 가져간다. 그래서 사람에게는 자동화가 못 하는, 가장 어려운 일만 남는다.
  • 아이러니 2: 평소에 손을 안 쓰면 기술이 녹슨다. 그런데 정작 사람이 개입해야 하는 순간은 시스템이 최악으로 망가진 순간이다.

항공 쪽 비유가 제일 와닿는다. 오토파일럿이 순항을 다 해주는 조종사는 수동 조작 감각이 무뎌진다. 그리고 오토파일럿이 해제되는 순간은 대체로 기상이 최악이거나 센서가 이상할 때다. 즉 가장 어려운 조건에서, 가장 준비 안 된 사람이 조종간을 잡는다.

온콜에 대입하면 이렇다. AI SRE가 P3~P4 수준 반복 장애(디스크 풀, 파드 OOMKilled, 특정 배포 후 5xx 증가)를 다 처리한다. 주니어는 1년 동안 온콜을 서도 실제로 손을 댄 장애가 서너 건뿐이다. 그러다 어느 날 리전 단위 네트워크 파티션이 터지고 AI가 "관련 신호가 여러 서비스에 분산되어 단일 원인을 특정할 수 없습니다"를 뱉는다. 이때 조종간을 잡을 사람이 없다.

더 고약한 건 조직 차원의 지식이 문서가 아니라 AI 컨텍스트 안에만 쌓인다는 점이다. 예전엔 장애 하나 겪으면 위키에 런북이 늘고, 사람 머릿속에 아키텍처 그림이 갱신됐다. 지금은 그 지식이 벤더 SaaS의 임베딩 인덱스 안에 들어간다. 계약이 끝나거나 모델이 바뀌면 조직에 뭐가 남는지 냉정하게 봐야 한다.

3. 실무 관점: 뭘 맡기고 뭘 쥐고 있을 건가

맡겨도 되는 것 / 쥐고 있어야 하는 것

5년 굴려보면서 정리한 기준은 "되돌릴 수 있냐"와 "판단이 필요하냐" 두 축이다.

  • AI에 맡겨도 되는 것: 컨텍스트 수집. 관련 대시보드 링크 모으기, 최근 30분 배포·설정 변경 목록, 동일 알럿 과거 발생 이력, 관련 서비스 의존성 그래프. 이건 사람이 해도 기계적인 작업이고 실수만 늘어난다.
  • AI가 초안만 내고 사람이 결정할 것: 원인 가설. "이게 원인입니다"가 아니라 "가설 3개와 각각의 근거·반증 방법"을 내게 만들어야 한다. 단일 정답을 주는 순간 사람은 검증을 안 한다.
  • 사람이 쥐고 있어야 하는 것: 상태를 변경하는 모든 액션. 롤백, 스케일 조정, 트래픽 차단, DB 작업. 특히 되돌릴 수 없는 것(데이터 삭제, 마이그레이션, DNS TTL 긴 변경)은 무조건 사람.

여기서 흔한 오해 하나. "그럼 자동 롤백도 하지 말라는 거냐?" 아니다. 자동 롤백은 해도 된다. 다만 조건이 명시적으로 코드에 박혀 있고 사람이 그 조건을 읽을 수 있어야 한다. LLM이 상황 봐서 판단해서 롤백하는 것과, 카나리 에러율 임계치 초과 시 롤백하는 규칙은 완전히 다른 얘기다. 후자는 사람이 규칙을 이해하고 튜닝하지만, 전자는 왜 롤백됐는지 아무도 모른다.

실행 가능한 예제 1: AI가 손대지 못할 영역을 RBAC로 못 박기

AI 에이전트에 쿠버네티스 접근을 줄 때, "일단 편의상 cluster-admin" 하고 나중에 줄이겠다는 계획은 100% 안 지켜진다. 처음부터 읽기 전용으로 시작하는 게 맞다.

# ai-sre-readonly.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: ai-sre-investigator
rules:
- apiGroups: ["", "apps", "batch"]
  resources: ["pods", "pods/log", "events", "deployments", "replicasets", "jobs"]
  verbs: ["get", "list", "watch"]      # create/delete/patch 없음
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list"]

적용하고 실제로 막히는지 확인한다. kubectl auth can-i는 이럴 때 제일 빠르다.

$ kubectl auth can-i get pods/log \
    --as=system:serviceaccount:observability:ai-sre -n prod
yes

$ kubectl auth can-i delete pods \
    --as=system:serviceaccount:observability:ai-sre -n prod
no

$ kubectl auth can-i patch deployments \
    --as=system:serviceaccount:observability:ai-sre -n prod
no

이 세 줄이 "AI는 조사만 하고 손은 사람이 댄다"는 정책의 실체다. 문서에 써놓는 것보다 이게 훨씬 강력하다.

실행 가능한 예제 2: 온콜이 손으로 밟는 조사 경로 남기기

AI가 다 해주더라도, 신규 입사자가 손으로 따라갈 수 있는 최소 경로는 스크립트로 유지해야 한다. 우리 팀은 이런 걸 ops/drill/ 밑에 둔다.

#!/usr/bin/env bash
# ops/drill/trace-5xx.sh  — 5xx 급증 시 사람이 밟는 최소 경로
set -euo pipefail
SVC="$1"; NS="${NS:-prod}"

echo "== 1) 최근 배포 =="
kubectl -n "$NS" rollout history deploy/"$SVC" | tail -3

echo "== 2) 재시작/OOM 파드 =="
kubectl -n "$NS" get pods -l app="$SVC" \
  -o custom-columns='POD:.metadata.name,RS:.status.containerStatuses[0].restartCount,REASON:.status.containerStatuses[0].lastState.terminated.reason'

echo "== 3) 최근 5분 에러율 (PromQL) =="
curl -sG "$PROM_URL/api/v1/query" \
  --data-urlencode "query=sum(rate(http_requests_total{service=\"$SVC\",code=~\"5..\"}[5m]))
    / sum(rate(http_requests_total{service=\"$SVC\"}[5m]))" \
  | jq -r '.data.result[0].value[1] // "no data"'
$ NS=prod ./ops/drill/trace-5xx.sh checkout-api
== 1) 최근 배포 ==
REVISION  CHANGE-CAUSE
41        image: checkout-api:1.22.3
42        image: checkout-api:1.23.0
== 2) 재시작/OOM 파드 ==
POD                              RS   REASON
checkout-api-7c9f4d8b6-2xk4t     3    OOMKilled
checkout-api-7c9f4d8b6-9jm2p     0    
== 3) 최근 5분 에러율 (PromQL) ==
0.0731

핵심은 스크립트 자체가 아니라 "5xx가 뜨면 배포 → 파드 상태 → 에러율 순으로 본다"는 사고 순서를 코드로 박제한다는 점이다. AI가 답을 먼저 줘도, 온콜은 이 순서를 밟아 교차 검증하게 만든다.

흔한 함정

함정 1: 권한을 줄였더니 AI가 "원인 불명"만 뱉는다. 위 RBAC를 적용하고 나서 십중팔구 이런 걸 만난다.

Error from server (Forbidden): events is forbidden: User
"system:serviceaccount:observability:ai-sre" cannot list resource "events"
in API group "" in the namespace "kube-system"

ClusterRole은 만들었는데 특정 네임스페이스에 RoleBinding이 안 걸렸거나, ClusterRoleBinding이 아니라 네임스페이스 한정 바인딩을 걸어놨을 때 나온다. 여기서 귀찮다고 cluster-admin을 붙이는 순간 앞의 설계가 다 무너진다. 필요한 네임스페이스를 열거해서 명시적으로 여는 게 맞다.

함정 2: 그럴듯한 오답. LLM 기반 분석은 근거가 부족해도 자신 있게 결론을 낸다. 실제로 겪은 패턴은 이렇다 — DB 응답이 느려진 진짜 원인은 배치 잡이 테이블 락을 잡은 건데, AI는 같은 시각에 나간 무관한 프론트엔드 배포를 범인으로 지목한다. 시간적 상관관계만 보고 인과로 단정한 것이다. 온콜이 시스템 감각이 있으면 "프론트 배포가 왜 DB를 느리게 해?"라고 되묻지만, 감각이 없으면 그대로 롤백하고 30분을 날린다.

대응은 하나뿐이다. AI 출력에 신뢰도와 반증 방법을 같이 쓰게 강제하는 것. 프롬프트/템플릿 레벨에서 "가설, 지지 근거, 이 가설이 틀렸다면 관측될 신호"를 세 칸으로 나눠 출력하게 한다. 세 번째 칸이 없으면 검증이 안 된다.

함정 3: 알럿 다이어트를 AI가 대신하게 두는 것. 시끄러운 알럿 100개를 AI가 잘 요약해주니까 알럿 정리를 안 하게 된다. 이건 부채를 이자만 내며 굴리는 거다. AI 도입 전에 알럿을 SLO 기반으로 줄이는 작업이 먼저다. 안 그러면 AI는 노이즈를 학습해서 노이즈를 요약해준다.

함정 4: 포스트모템이 AI 요약본으로 대체되는 것. 이게 제일 조용히 진행된다. AI가 타임라인을 자동 생성해주니 사람이 쓰는 부분이 "액션 아이템" 세 줄로 줄어든다. 포스트모템의 가치는 문서가 아니라 여러 명이 모여서 "왜 이게 안 잡혔지"를 따지는 30분에 있는데, 그 자리가 사라진다.

학습이 남는 온콜을 만드는 실무 장치

  • AI 결론 지연 공개(delayed reveal): 훈련 목적 세션에서는 AI 분석 결과를 5~10분 뒤에 공개한다. 온콜이 먼저 자기 가설을 슬랙에 적고, 그다음 AI 답과 비교한다. 이 diff가 그대로 학습 자료다.
  • 섀도 온콜: 주니어가 실제 페이저를 받되, 시니어가 뒤에 붙는다. AI가 이미 답을 냈어도 주니어는 위 trace-5xx.sh 같은 경로를 직접 밟는다. 복구는 빠르게, 학습은 별도로 분리하는 게 핵심.
  • 런북은 절차가 아니라 모델을 담는다: "1. 파드 재시작 2. 확인" 같은 런북은 AI가 대체하면 그만이다. 대신 "이 서비스는 커넥션 풀 크기가 N이고, 업스트림 타임아웃이 M초라 M초를 넘기면 앞단에서 먼저 터진다" 같은 시스템의 작동 원리를 적어야 사람에게 남는다.
  • 게임데이: AI 보조를 꺼놓고 하는 장애 훈련을 분기 1회라도 넣는다. 오토파일럿 끄고 수동 착륙 연습하는 것과 같은 이유다.
  • 지표를 MTTR 하나로 두지 않기: MTTR만 보면 AI 의존도를 올리는 게 항상 정답이 된다. "사람이 직접 조사한 인시던트 비율", "온콜 1인당 신규 유형 장애 경험 건수" 같은 걸 같이 본다. 조직마다 정의는 달라야 하니 그대로 베끼지 말고 팀 상황에 맞춰라.

단계별 도입 순서

한 번에 다 하려다 망하는 걸 여러 번 봤다. 순서는 이렇게 잡는 게 안전하다.

  1. 0단계: 알럿 정리와 서비스 소유권 명확화. AI 붙이기 전에 끝내야 한다.
  2. 1단계: 읽기 전용 컨텍스트 수집만. 알럿에 관련 링크·배포 이력을 자동으로 붙이는 수준.
  3. 2단계: 가설 제안. 단 복수 가설 + 반증 방법 형식 강제.
  4. 3단계: 명시적 규칙 기반 자동 조치(카나리 롤백 등). LLM 판단이 아니라 규칙.
  5. <
728x90
728x90

주말에 HN 올라온 글 하나 읽고 한참 멍하니 있었다. 2018년에 "장난삼아" 산 sondehub.org 도메인 하나가, 결국 미 국방부(Office of the Secretary of War)와 NTSB, FAA 관제탑, 그리고 우크라이나 심층타격팀까지 엮이는 인프라가 되어버린 이야기다.

기술적으로 대단한 스택이 나오는 글은 아니다. 그런데 "내가 만든 공개 API를 내가 통제할 수 없는 사람들이 쓰기 시작했을 때 무슨 일이 벌어지는가"에 대해서는, 내가 본 어떤 아키텍처 문서보다 생생하다. 5년차 인프라 하다 보면 사이드 프로젝트 하나쯤은 공개 엔드포인트로 열어두게 되는데, 그 엔드포인트가 어디까지 갈 수 있는지 감각을 잡아두는 게 좋다.

장난 도메인이 어쩌다 전략 자산이 됐나

흐름을 요약하면 이렇다.

  • 2018.05 — Habhub(아마추어 고고도 풍선 추적 사이트)가 기상 관측용 라디오존데를 기본 필터로 감췄다. 필터 해제 쿼리 파라미터를 매번 치기 귀찮아서 sondehub.org를 사면서 Habhub으로 리다이렉트만 걸었다. 진짜 그게 전부였다.
  • 2018.07 — 리다이렉트만으로는 안 되겠어서 데이터 수집을 프록시로 받기 시작. 자체 OpenSearch 클러스터에 쌓았지만 노출은 안 했다. 저자 본인 표현으로 "AWS 서비스 놀아보는 장난감" 수준.
  • 2019 — Habhub과 aprs.fi 서버가 버티질 못함. 자체 서비스로 전환 시작. 이때부터 정부기관 데이터 요청이 들어온다. (라디오존데가 말에 맞아서 말이 울타리 뚫고 도망간 보험 청구 건... 이런 게 온다)
  • 2021 — 역예측(reverse prediction) 기능 도입. 그리고 군에서 이메일이 온다.
  • 2023.02 — 중국 정찰풍선 사태 + 미군이 아마추어 무선 풍선을 AIM-9X로 격추. Washington Post에 링크되면서 트래픽 폭증.
  • 2024.12 — 예측 API에 알람 폭탄. 추적해보니 우크라이나 쪽 심층타격 작전이었다.

여기서 결정적 분기점이 역예측이다. 원래 예측기는 "지금 이 풍선이 어디로 갈까"를 바람 모델로 계산한다. 이걸 시간축을 뒤집어서 돌리면, 이미 관측된 풍선의 발사 지점이 역산된다. 문서화 안 된 발사장을 여럿 찾아냈고 — 문제는, 상층 바람 데이터는 기상 예보용만이 아니라 포병 사거리 계산에도 쓰인다는 것.

즉 이들이 무심코 만든 건 "미문서화 기상 관측소 지도"가 아니라 포병 진지 지도였다. 2021년에 군에서 "민감/군사 시설이니 지도에 명시적으로 표시하지 말아달라"는 메일을 받는다. 역예측 기능은 유지하되, 정당한 요청이 오면 해당 발사장을 삭제하는 방식으로 타협했다고 한다.

핵심 원리: 파생 데이터는 원본보다 위험하다

이 사례의 기술적 교훈은 딱 하나로 압축된다. 공개 데이터를 모아서 가공하면, 개별 데이터에는 없던 민감도가 생긴다. 인프라 쪽 용어로는 aggregation / inference 문제다.

비유하자면 이렇다. 사내 액세스 로그 한 줄은 아무 의미 없다. 근데 6개월치를 모아서 "이 IP대역이 새벽 3시에만 특정 엔드포인트를 친다"는 패턴을 뽑으면, 그건 배치 스케줄이자 곧 인프라 구조도다. 라디오존데도 똑같다. 개별 좌표 하나는 공개 기상 데이터인데, 수만 건을 역방향 물리 모델에 넣으면 발사 원점이 나온다.

SondeHub이 왜 기존 도구보다 데이터가 좋았냐면 — 지면에 닿을 때까지 끝까지 추적했기 때문이다. 당시 공식 소프트웨어는 그렇지 않았다. 그래서 보험 청구 조사까지 가능했던 거고, 그래서 역예측 정밀도도 나온 거다. 관측 커버리지를 늘렸더니 부작용으로 정보 가치가 폭발한 케이스.

본인 인프라에서 이걸 확인하고 싶다면, 로그에서 "단일 소스가 예측 API만 반복 호출"하는 패턴을 뽑아보는 게 첫 단계다. CloudFront/ALB 액세스 로그 기준 예시:

# ALB 액세스 로그에서 예측 엔드포인트 상위 호출자 뽑기
awk '$13 ~ /predict/ {split($4,a,":"); print a[1]}' alb.log \
  | sort | uniq -c | sort -rn | head -5

  48213 13.54.x.x
    902 203.0.113.9
    311 198.51.100.44
     87 192.0.2.17
     52 172.16.8.3

1등과 2등이 50배 차이 나면 그건 사람이 아니다. 원문에서도 로깅을 켜자마자 단일 IP에서 오고 있었다고 나온다. 처음엔 어떤 사설 업체가 백엔드를 무단으로 쓰는 줄 알고 항의 메일까지 보냈는데, 그쪽은 진범이 아니었다. LLM 스크래퍼 봇이겠거니 하고 예측 요청 좌표를 지도에 찍어봤더니 — 그림이 나왔다.

실무 관점: 공개 API 운영자가 실제로 마주치는 것들

1. 차단이 정답이 아닌 경우가 있다

보통 이런 트래픽 보면 WAF 룰 하나 박고 끝낸다. 근데 이 케이스에서 운영자가 AWS 서포트에 보낸 문장이 이거다.

"HTTP 요청 데이터가 배포되지 않는 것이 대단히 중요합니다. 또한 소스 AWS 계정이 차단·레이트리밋·해지되지 않는 것도 중요합니다 — 인명 손실이 발생할 수 있습니다."

서포트 티켓에 이런 문장을 쓸 일이 있으리라곤 본인도 상상 못 했다고 한다. 요구사항이 두 개인데 서로 충돌한다. (a) 서비스를 끊으면 안 된다 (b) 요청 로그가 새어나가면 발사 지점이 노출된다. 결국 AWS를 통해 "당신 람다가 스크래핑으로 플래그됐으니 운영자에게 연락하라"는 형태로 채널이 열렸고, 로컬 예측기 실행 문서를 넘겨주는 걸로 정리됐다.

2. 진짜 해법은 "떠나게 만드는 것"

여기서 제일 실무적인 판단이 나온다. 저자는 차단 대신 docker compose 파일을 급하게 만들어서 누구나 자기 예측기를 돌릴 수 있게 풀었다. 헤비 유저를 내쫓는 게 아니라 셀프호스팅 경로를 열어준 것.

이건 사내 공용 API 운영할 때도 그대로 적용된다. 특정 팀이 공용 계산 API를 초당 수백 번 때리면, 429 때리기 전에 "그 계산 라이브러리를 너희 파드 안에서 돌려라"를 먼저 제안하는 게 총 비용이 싸다. 사이드카/로컬 배포 경로가 있으면 대부분 알아서 옮겨간다.

# 헤비 유저에게 넘길 최소 셀프호스팅 스택 예시
cat > compose.yml <<'EOF'
services:
  predictor:
    image: ghcr.io/example/predictor:latest
    ports: ["8080:8080"]
    environment:
      - GFS_CACHE_DIR=/data/gfs
    volumes: ["./gfs:/data/gfs"]
EOF

docker compose up -d
curl -s localhost:8080/healthz

{"status":"ok","wind_model":"loaded"}

※ 위 이미지 경로는 예시다. SondeHub 실제 이미지 태그는 공식 저장소 확인 필요.

3. 흔한 함정: 레이트리밋 걸고 나서 벌어지는 일

API Gateway나 CloudFront 앞단에 usage plan 걸면 이런 게 뜬다.

HTTP/1.1 429 Too Many Requests
x-amzn-ErrorType: LimitExceededException
{"message":"Too Many Requests"}

문제는 이걸 받는 쪽 클라이언트가 대개 백오프를 구현 안 했다는 것이다. 429를 받으면 재시도를 더 빨리 돌려서 부하가 오히려 튄다. 원문에서도 "API를 올바르게 사용하지 않는 것 같다"는 의심이 나온다. 그리고 이런 상황에서 진짜 답답한 건, 연락할 방법이 없다는 점이다. User-Agent도 없고 API 키도 없으면 그냥 IP 하나뿐이다.

결국 이들은 우크라이나어로 밀리터리 채팅방에 메시지를 뿌려서 컨택을 잡았다. "파이썬 스크립트로 오픈소스 바람 예측 엔진 쓰는 심층타격팀 아시는 분 연락 주세요, 차단될 수 있으니 조치가 필요합니다" — 이게 실제 컨택 경로였다.

여기서 얻어갈 실무 룰:

  • 익명 접근을 허용하더라도 키 발급은 무료로라도 열어둬라. 차단이 목적이 아니라 연락 채널 확보가 목적이다.
  • 429 본문에 사람이 읽을 수 있는 컨택 정보와 셀프호스팅 링크를 반드시 넣어라. 봇 운영자도 결국 사람이 로그를 본다.
  • 레이트리밋은 계정 단위로, 익명은 IP 단위로. NAT 뒤에 있으면 IP 단위는 애먼 사람 잡는다.

4. 로그 자체가 기밀이 되는 순간

평소엔 액세스 로그를 S3에 던져놓고 라이프사이클 정책만 걸어둔다. 근데 이 케이스에선 요청 파라미터(위경도)가 곧 작전 정보였다. 클라우드 벤더 서포트에게 로그를 넘기는 순간 그게 유출이 된다.

지도에 찍을 때도 좌표 정밀도를 의도적으로 낮췄고, 데이터셋은 상당히 오래된 것만, 블로그 발행 자체를 "풍선 전쟁이 충분히 널리 알려질 때까지" 미뤘다고 한다. 이 판단 자체가 운영 프로세스의 일부다.

대응 원칙 정하고 가자:

  • 쿼리 파라미터를 액세스 로그에 통째로 남길지 여부를 설계 시점에 결정. 좌표·검색어·식별자는 기본적으로 마스킹 후보다.
  • 서드파티(벤더 서포트, APM SaaS)로 나가는 로그 필드를 화이트리스트로 관리. 블랙리스트는 언젠가 샌다.
  • 보존 기간 짧게. 없는 데이터는 유출도 안 되고 소환장에도 안 걸린다.

5. 예상 못 한 이해관계자들

운영하다 보면 상상 못 한 곳에서 메일이 온다. 원문에 나온 것만 봐도:

  • NTSB(2025.09) — "10/16/2025 1200~1300 UTC에 유타 지역 풍선 정보 있나요?" 데이터를 넘겼고, SondeHub 추적 풍선과는 안 맞았지만 Windborne 풍선이 근처에 있었다는 정보를 전달. 나중에 Windborne이 항공기 충돌 가능성을 확인하고 시스템을 수정했다.
  • FAA 관제탑 — "하늘에 항공기가 많은데 이 풍선들 가까이 가고 싶지 않다. 통제 주체와 직접 조율하거나 사전에 임무 정보를 받을 수 있나?" → 기상 풍선은 정기 스케줄로 올라가고 조종되지 않으며 FAA 규정 Part 101.D 범위라고 설명해야 했다. 저자 표현: "FAA에 기상 풍선의 존재를 설명하게 될 줄은 몰랐다."
  • 뺑소니 민원 — 아이오와 아나모사에서 누가 라디오존데 회수하다가 건물 들이받고 쪽지도 안 남기고 도망감. 건물주가 범인 찾아달라고 연락.
  • 미 국방부(2025) — 데이터 요청. 커뮤니티 상호 이익이 있으면 보통 무료로 가공해서 푸는데, 이건 그게 아니라 인보이스를 끊었다. 결과: 결제도 후속 연락도 없었다.

이게 왜 실무 얘기냐면, 공개 서비스를 운영한다는 건 지원 채널을 운영한다는 뜻이기 때문이다. 스펙에도 없고 SLA도 없는 요청이 계속 들어온다. 답변 템플릿과 에스컬레이션 기준, "이건 우리 소관 아님"이라고 말할 수 있는 문서화된 경계선이 없으면 운영자 한 명이 갈려나간다.

정리

한 줄 요약: 공개 API는 어느 순간 당신이 승인하지 않은 용도로 쓰이며, 그때는 차단보다 셀프호스팅 경로 제공과 연락 채널 확보가 더 나은 해법일 수 있다.

체크리스트로 남긴다.

  • 공개 엔드포인트를 열 거면 1일차에 로깅·식별·컨택 경로를 같이 설계해라. 사고 터진 뒤 켜는 로깅은 이미 늦다.
  • 원본 데이터가 공개라고 파생 데이터도 공개해도 되는 건 아니다. 집계·역산으로 새 정보가 생기는지 한 번은 따져봐라.
  • 헤비 유저는 적이 아니라 배포 형태를 잘못 고른 사용자다. 도커 컴포즈 하나가 WAF 룰 열 개보다 낫다.
  • 액세스 로그 필드는 유출 자산으로 취급하고, 서드파티로 나가는 항목은 화이트리스트로.
  • 취미 프로젝트라도 인보이스 끊을 각오는 해두되, 정부기관이 그걸 낼 거라는 기대는 접어라.

솔직히 나는 이 글에서 제일 인상 깊었던 게 아키텍처가 아니라 "AWS 서포트에게 이 계정을 차단하지 말아달라, 인명 손실이 발생할 수 있다"는 문장이었다. 우리가 짜는 레이트리밋 룰 한 줄이 어디까지 가닿을 수 있는지, 가끔은 생각해볼 만하다.

참고 자료

728x90

+ Recent posts