보호가 목적을 초과했을 때: 대규모 방어 시스템 관리에 대한 교훈
Source: GitHub Blog
번역할 텍스트가 제공되지 않았습니다. 번역이 필요한 본문을 알려주시면 한국어로 번역해 드리겠습니다.
플랫폼 가용성 유지
문제
때때로 긴급 대응으로 추가된 보호 조치가 그 유용성을 초과해 정당한 사용자를 차단하기 시작합니다. 이는 빠른 사고 대응을 위해 영구적이지 않은 보다 광범위한 제어가 필요할 때 흔히 발생합니다.
우리가 배운 점
- 구식 완화 조치는 사용자 경험을 저하시킬 수 있습니다.
- 관측 가능성은 기능만큼이나 방어에도 중요합니다.
- 사용자의 신속한 피드백은 오래된 보호 조치를 식별하고 제거하는 데 필수적입니다.
사과의 말씀
불편을 끼쳐 드려 죄송합니다. 이러한 보호 조치를 더 빨리 감지하고 제거했어야 했습니다.
향후 계획
- 더 이상 필요하지 않은 긴급 완화 조치를 검토하고 폐기합니다.
- 방어 제어의 의도치 않은 부작용을 포착할 수 있도록 모니터링을 강화합니다.
- 방어가 투명하고 효과적으로 유지되도록 사용자 피드백 수집을 지속합니다.
사용자가 보고한 내용
우리는 소셜 미디어에서 일반적인 저볼륨 브라우징 중에 “Too many requests” 오류를 받는 보고를 보았습니다—예를 들어, 다른 서비스나 앱에서 GitHub 링크를 클릭하거나 명백한 남용 패턴 없이 단순히 탐색할 때 등.

사용자들은 일반적인 브라우징 중에 “Too many requests” 오류를 경험했습니다.
이것은 정상적인 소수의 요청을 보낸 사용자가 적용되지 않아야 할 속도 제한에 걸린 경우였습니다.
Source: …
우리가 발견한 내용
보고서를 조사한 결과 근본 원인이 밝혀졌습니다: 과거 악용 사건 중에 추가된 보호 규칙이 그대로 남아 있었습니다. 이 규칙들은 당시 악의적인 트래픽과 강하게 연관된 패턴을 기반으로 생성되었습니다. 안타깝게도, 동일한 패턴이 정식 클라이언트의 로그아웃된 요청과도 일치했습니다.
복합 신호 및 오탐
- 이 패턴들은 업계 표준 지문 기술과 플랫폼 고유의 비즈니스 로직을 결합합니다.
- 복합 신호는 가끔씩 오탐을 발생시킬 수 있습니다.
주요 통계
| 지표 | 값 |
|---|---|
| 의심스러운 지문과 일치하고 차단된 요청 | 0.5 % – 0.9 % (비즈니스 로직 규칙도 동시에 트리거된 경우에만) |
| 두 기준을 모두 만족한 요청 | 100 % 차단 |
| 전체 트래픽 대비 오탐 비율 | 0.003 % – 0.004 % (≈ 10만 요청당 3‑4건) |
참고: 비즈니스 로직 패턴도 만족한 지문 매치만 차단되었습니다.
시각적 요약
| 설명 | 이미지 |
|---|---|
| 차단된 지문 매치 비율 (60분 동안 0.5‑0.9 %) | ![]() |
| 전체 트래픽 대비 오탐 비율 (0.003‑0.004 %) | ![]() |
| 시간에 따른 오탐 패턴 확대 | ![]() |
비율은 낮지만, 잘못된 차단은 실제 사용자에게 영향을 미치므로 결코 허용될 수 없습니다.
임시 완화 조치가 영구화될 수 있는 이유
활성화된 사고가 진행 중일 때 우리는 신속하게 조치를 취해야 하며, 종종 서비스를 유지하기 위해 트레이드‑오프를 받아들입니다. 긴급 제어는 그 순간에 올바른 것이지만, 위협 패턴이 진화하고 합법적인 사용이 변함에 따라 오래 지속되지 못합니다. 적극적인 유지보수가 없으면 임시 완화 조치는 영구화되고 그 부작용은 조용히 누적됩니다.
스택을 통한 추적
사용자들이 오류를 보고했을 때, 우리는 여러 인프라 계층을 가로질러 요청을 추적하여 차단이 발생한 지점을 정확히 파악했습니다.
다계층 보호 개요
GitHub의 맞춤형 다계층 보호 인프라(HAProxy와 같은 오픈소스 프로젝트 기반)는 여러 지점에서 방어를 적용합니다:
- 엣지 계층 – DDoS 보호, IP 평판, 속도 제한.
- 애플리케이션 계층 – 인증, 사용자/서비스별 속도 제한.
- 서비스 계층 – 비즈니스 로직 검증, 기능별 스로틀링.
- 백엔드 계층 – 리소스 수준 할당량, 내부 안전 검사.
다이어그램 (특정 메커니즘 노출 방지를 위해 단순화):
각 계층은 독립적으로 요청을 차단하거나 속도 제한을 적용할 수 있습니다. 어떤 계층이 차단을 수행했는지 판단하려면 스키마가 다른 로그들을 상호 연관시켜야 합니다.
조사 단계
| 단계 | 출처 | 확인한 내용 |
|---|---|---|
| 1️⃣ | 사용자 보고 | 타임스탬프, 오류 메시지, 관찰된 동작 |
| 2️⃣ | 엣지 계층 로그 | 프론트엔드에 도달한 요청 |
| 3️⃣ | 애플리케이션 계층 로그 | HTTP 429 “Too Many Requests” 응답 |
| 4️⃣ | 보호 규칙 분석 | 요청과 일치한 규칙(들) |
사용자가 보는 오류에서 기본 규칙 구성으로 역추적함으로써, 남아 있던 완화 규칙이 잘못된 양성(오탐)의 원인임을 확인했습니다.
사고 완화 조치의 수명 주기
다음 다이어그램은 완화 조치가 그 유용성을 초과하여 오래 지속될 수 있음을 보여줍니다:
무엇이 잘못되었는가
- 사고 발생 시에 제어가 추가되었으며 의도대로 작동했습니다.
- 만료 날짜, 사고 후 검토, 혹은 영향 모니터링이 적용되지 않았습니다.
- 시간이 지나면서 해당 규칙은 기술 부채가 되어 결국 정상 트래픽을 차단하게 되었습니다.
권장 실천 방안
- 긴급 규칙에는 명시적인 만료 날짜를 설정합니다.
- 사고 후 검토를 수행하여 지속적인 영향을 평가합니다.
- 영향 모니터링을 자동화합니다(예: 예상치 못한 차단 비율에 대한 알림).
- 소유권을 문서화하여 담당 팀이 규칙을 폐기하거나 조정할 수 있도록 합니다.
이러한 실천 방안을 적용하면 일시적인 방어 조치가 실제로 일시적으로 유지되고, 정상 사용자가 의도치 않게 영향을 받는 일을 방지할 수 있습니다.
우리가 한 일
- 완화 조치 검토 – 현재 각 규칙이 차단하는 내용과 원래 의도를 비교했습니다.
- 구식 규칙 제거 – 더 이상 목적을 수행하지 않는 보호 조치를 제거했습니다.
- 핵심 방어 수단 유지 – 지속적인 위협으로부터 방어하는 제어를 유지했습니다.
우리가 구축하고 있는 것
즉각적인 수정 외에도, 보호 제어의 수명 주기 관리를 개선하고 있습니다:
- 더 나은 가시성을 모든 보호 계층에 제공하여 속도 제한 및 차단의 원인을 추적합니다.
- 사고 완화 조치를 기본적으로 임시로 취급합니다; 영구적으로 전환하려면 의도적이고 문서화된 결정을 필요로 합니다.
- 사후 사고 관행을 통해 긴급 제어를 평가하고 이를 지속 가능하고 목표 지향적인 솔루션으로 발전시킵니다.
방어 메커니즘—사고 발생 시 신속히 배포된 경우라도—은 보호하는 시스템과 동일한 수준의 관리가 필요합니다. 가시성, 문서화, 그리고 적극적인 유지보수가 요구됩니다. 사고 중에 추가된 보호 조치가 그대로 남아 있으면, 조용히 누적되는 기술 부채가 됩니다.
공개적으로 문제를 보고해 주신 모든 분께 감사드립니다! 여러분의 피드백이 직접 이러한 개선으로 이어졌습니다. 또한 조사에 참여하고 운영 방식을 개선하기 위해 수명 주기 관리를 구축한 GitHub 전 팀에게도 감사드립니다. 우리의 플랫폼, 팀, 그리고 커뮤니티가 함께라면 더 나아집니다!
Tags
- 개발자 경험
- 사고 대응
- 인프라
- 가시성
- 사이트 신뢰성
Written by
Thomas Kjær Aabo – GitHub 트래픽 팀 엔지니어.
GitHub에서 더 알아보기
| Docs – GitHub를 마스터하는 데 필요한 모든 것을 한 곳에 모았습니다. | |
| GitHub – GitHub에서 다음을 구축하세요. 어디서든 누구나 무엇이든 만들 수 있는 장소입니다. | |
| Customer stories – GitHub와 함께 구축하는 기업과 엔지니어링 팀을 만나보세요. | |
| The GitHub Podcast – 오픈소스 개발자 커뮤니티의 주제, 트렌드, 스토리, 문화 등을 다루는 팟캐스트를 들어보세요. |




