Cloudflare 글로벌 마비 사고
서버 도메인 연결할때 쓴 Cloudflare 살펴보기
들어가며
이때 기억하면 친구랑 디코에서 롤 하고 있었는데 게임이 자꾸 안 됐다. 처음엔 "내 인터넷이 문제인가?" 하고 클라이언트를 껏다가 켜보고 했는데 소용없었다. 근데 게임뿐 아니라 다른 여러 사이트도 같이 먹통이였던 것이였다.
이유는 전 세계 인터넷의 상당 부분을 떠받치고 있는 Cloudflare라는 회사에 장애가 터진 거였다.
Cloudflare 란?
Cloudflare는 웹사이트 앞단에 서서 일종의 문지기 + 고속도로 역할을 하는 회사다.
- 사이트로 들어오는 트래픽을 대신 받아서 DDoS 같은 공격을 막아주고
- 콘텐츠를 전 세계에 미리 뿌려놔서 CDN으로 사이트를 빠르게 열어주고
- 트래픽이 올바른 서버로 가도록 길을 안내해준다.
문제는, 너무 많은 서비스가 Cloudflare를 거쳐서 동작한다는 점이다. 그래서 Cloudflare가 오류나면 그 뒤에 있던 수많은 사이트·게임·앱이 같이 쓰러진다.
모르는 단어
위에서 Cloudflare 역할을 적긴 했는데, 사실 그 한 문장 안에 모르는 단어가 잔뜩 들어 있었다. 하나 찾으면 그 안에서 또 모르는 게 나와서, 꼬리에 꼬리를 물고 공부하게 됐다. 그 순서대로 정리해본다.
Cloudflare의 역할
우선 "Cloudflare가 대체 뭘 하는 회사냐"를 찾아보았다. 정리해보니, 내 폰이나 PC와 진짜 웹사이트 서버 중간에 끼어 앉아서 대신 일해주는 회사였다. 서버 사이에 선 중간 관리인 같은 느낌이다. 하는 일이 크게 세 가지였는데, 여기서 모르는 단어가 줄줄이 나왔다. 바로 DDoS 방어, CDN, 그리고 BGP로 길을 안내하는 일이다.
1. DDoS 방어
첫 번째 역할이 "공격을 막아준다"였는데, 그 공격이 DDoS 였다.
DDoS는 영어로 Distributed Denial of Service, 우리말로 분산 서비스 거부 공격이다. 쉽게 말하면 떼로 몰려가서 가게 입구를 막아버리는 것이다. 공격자가 좀비처럼 조종하는 수많은 컴퓨터로 한 서버에 동시에 엄청난 양의 접속을 퍼부어서, 정상 손님이 아예 못 들어가게 서비스를 마비시킨다. 앞에 붙은 "분산"이라는 말은 한 명이 아니라 사방에서 동시에 친다는 뜻이다.
Cloudflare는 이 폭주 트래픽을 중간에서 대신 받아내서 걸러주는 역할을 한다. 가게 앞에 큰 방패를 들고 선 셈이다.
2. CDN
두 번째 역할이 "사이트를 빠르게 열어준다"였고, 그게 CDN 이었다.
CDN은 영어로 Content Delivery Network, 우리말로 콘텐츠 전송 네트워크다. 전 세계 곳곳에 콘텐츠 복사본을 미리 깔아두는 것을 말한다. 원본 서버가 미국에 있어도, 한국 사용자는 한국 근처에 있는 복사본에서 받으니 훨씬 빠르다. 동네마다 편의점을 두고, 멀리 본사까지 안 가도 가까운 데서 물건을 받게 하는 느낌이다. 이때 동네 편의점 역할을 하는 복사본 서버를 캐시 서버라고 부른다. 그래서 사이트가 빨리 열린다.
3. 길 안내 → BGP
세 번째 역할이 "트래픽이 올바른 서버로 가게 길을 안내한다"였는데, 그 길 안내를 담당하는 게 BGP 였다. 이번 사고의 핵심 단어이기도 하다.
BGP는 영어로 Border Gateway Protocol, 우리말로 경계 경로 프로토콜이다. 인터넷에서 "이 IP 주소로 가려면 이쪽 길로 오세요" 라고 알려주는 내비게이션이라고 보면 된다. 인터넷은 수많은 네트워크가 연결된 거대한 도로망인데, 어디로 가야 목적지에 닿는지 서로 알려주는 약속이 BGP다. 이렇게 경로를 알려주는 행위를 "방송한다"고 표현한다. (broadcast 가 아닌 announce)
여기까지 오니 이번 사고가 왜 났는지 이해됐다. Cloudflare가 BGP로 "이 사이트는 이쪽으로 오세요" 하고 계속 방송해줘야 사람들이 찾아오는데, 실수로 그 방송을 꺼버린 게 사고였다. 이렇게 방송을 거둬들이는 걸 "회수한다"고 한다. 내비게이션이 갑자기 "목적지를 찾을 수 없습니다"가 된 셈이다. 자세한 건 아래 근본 원인에서 이어진다.
꼬리물기 정리: Cloudflare 역할에서 출발해, 떼로 막는 공격인 DDoS, 복사본을 미리 깔아두는 CDN, 인터넷 내비게이션인 BGP까지. 역할 하나를 풀었더니 그 안의 단어 셋이 줄줄이 나왔고, 마지막 BGP가 이번 사고의 원인으로 그대로 연결됐다.
타임라인
다행히 이 사건은 Cloudflare가 직접 상세한 사고 보고서를 공개했다. 이렇게 사고가 끝난 뒤 원인과 경과를 정리해 내놓는 보고서를 영어로 포스트모템이라고 부른다. 정리하면 이렇다.
- 17:48 UTC — 잘못된 자동 정리 작업이 실행되기 시작.
- 17:56 UTC — 본격적으로 영향 발생. 고객들의 IP 대역이 BGP에서 사라지기 시작.
- 18:46 UTC — 엔지니어들이 원인을 찾아 문제의 작업을 중단.
- 19:19 UTC — 고객이 대시보드에서 직접 복구할 수 있게 됨.
- 23:03 UTC — 최종 복구 완료.
- 총 장애 시간: 약 6시간 7분. 이 사이 약 1,100개의 IP 대역이 삭제됐다.
타임라인에서 눈여겨볼 점이 있다. 문제를 멈춘 게 18:46인데, 완전 복구는 23:03이었다. 즉 원인을 찾고 잘못된 작업을 중단한 뒤에도 네 시간 넘게 더 걸렸다는 뜻이다. 망가뜨리는 건 1초면 되는데, 되돌리는 건 훨씬 오래 걸린다는 걸 보여주는 대목이다. 삭제된 1,100개 대역을 하나하나 다시 인터넷에 알리고, 그 정보가 전 세계 네트워크에 퍼져 자리 잡는 데까지 시간이 필요했기 때문이다.
그리고 중요한 포인트 하나. 이건 해킹이나 사이버 공격이 아니었다. 회사 내부의 실수로 인한 장애였다. 보안 공부를 하다 보면 "보안 사고 = 해커의 침입"이라고만 생각하기 쉬운데, 이렇게 아무도 공격하지 않았는데 서비스가 마비되는 것도 엄연한 보안 사고다. 뒤에서 다시 이야기하겠다.
근본 원인
여기가 제일 흥미로웠다. 원인을 최대한 쉽게 풀어보면 (내가 이해하기 쉽게...!)
1. BYOIP와 BGP
BYOIP는 영어로 Bring Your Own IP, 말 그대로 "내 IP를 가져와서 쓴다"는 뜻이다. 고객이 자기 IP 주소 대역을 Cloudflare에 맡겨서 관리받는 서비스다. "내 주소인데 관리는 너희가 해줘" 같은 느낌이다.
BGP는 앞에서 공부했듯이 인터넷에서 길을 안내하는 내비게이션 역할을 한다. 즉 Cloudflare가 BGP로 "이 고객들 주소는 우리 쪽으로 오세요"라고 계속 방송해주고 있어야, 전 세계에서 그 사이트로 찾아올 수 있다.
2. 자동 청소 작업
Cloudflare는 IP 주소를 관리하는 Addressing API에서 자동 정리 작업을 돌리고 있었다. 그런데 이 작업에 쓰인 데이터베이스 쿼리가 잘못 짜여 있었다.
문제의 핵심은 이거다. 쿼리에서 "삭제 대기 중인 항목만 골라라"라고 해야 했는데, 여기서 삭제 대기 상태를 가리키는 pending_delete라는 값이 빈 문자열("")로 들어왔다. 그러자 API 서버는 이 빈 값을 "삭제 대기뿐 아니라 BYOIP 대역을 전부 달라" 는 뜻으로 잘못 해석했고, 결국 가져온 대역을 전부 지워버렸다.
쉽게 비유하면, "이 목록 중 특정 항목만 지워"라고 해야 하는데, 조건이 비어버리는 바람에 "전부 지워"가 돼버린 거다. SQL 좀 만져본 사람이라면 WHERE 조건이 날아간 DELETE 문을 떠올리면 딱 맞다. 등골 서늘해지는 그거.
3. 잘못된 BGP에서 회수
그 결과 Cloudflare는 BYOIP 고객들의 IP 대역을 BGP에서 회수해버렸다. 앞에서 말한, 길 안내 방송을 거둬들이는 그 "회수"가 실제로 일어난 것이다. 길 안내 방송이 갑자기 꺼진 셈이다. 그러면 인터넷은 그 주소로 어떻게 가야 할지 모르게 되고, 해당 사이트·서비스는 통째로 접속 불가가 된다. 내 롤도 이래서 안 됐던 거다.
제품별 증상
"Cloudflare 장애"라고 뭉뚱그렸지만, 실제로는 Cloudflare의 여러 서비스가 조금씩 다른 방식으로 영향을 받았다. 이름이 낯설어도, "이런 것들이 있구나" 정도로 보면 된다.
- CDN·보안 서비스 — 트래픽이 Cloudflare가 보호하는 웹사이트까지 아예 도달하지 못했다. 가장 많은 사이트가 여기 걸려서 "접속 불가"가 됐다. 내 게임도 이 영향권이었을 가능성이 크다.
- Spectrum — 게임·앱 같은 일반 트래픽을 중계해주는 서비스인데, 중계가 끊겼다.
- Dedicated Egress — 고객 서버가 바깥으로 트래픽을 내보내는 통로인데, 나가는 길이 막혔다.
- Magic Transit — 네트워크를 통째로 보호해주는 서비스로, 연결이 자꾸 시간 초과(timeout)됐다.
- 1.1.1.1 웹사이트 — Cloudflare가 운영하는 유명한 DNS 서비스인데, 그 안내 웹페이지가 403 에러를 뱉었다. 다만 DNS 기능 자체(주소 변환)는 멀쩡했다는 점이 흥미롭다.
여기서 배운 게 하나 있다. 같은 사고여도 어떤 서비스를 쓰고 있었느냐에 따라 증상이 다 다르게 나타난다. 누구는 "사이트가 안 열려", 누구는 "403 에러가 떠", 누구는 "자꾸 끊겨"라고 말하지만 원인은 하나였던 거다. 그래서 사고 초반엔 다들 자기 문제인 줄 알고 헤맸다. 나처럼.
어떻게 대응했나
엔지니어들이 문제를 파악한 뒤, 사라졌던 IP 대역들을 다시 BGP로 방송하면서 경로를 복구했다. 꺼졌던 내비게이션 안내를 다시 켠 셈이다. 그렇게 약 6시간 만에 정상화됐다.
Cloudflare가 약속한 재발 방지책은 대략 이렇다.
- 빈 값이 "전부"로 해석되지 않도록 API 표준화·입력값 검증 강화
- 설정 상태를 분리해서 DB 스냅샷 없이도 빠르게 롤백 가능하게 개선
- 위험한 대량 작업을 자동으로 감지하고 멈추는 서킷 브레이커 모니터링 도입. 서킷 브레이커는 전기 회로의 누전 차단기처럼, 이상한 작업이 감지되면 자동으로 회로를 끊어 더 큰 사고를 막는 안전장치를 말한다.
사실 처음이 아니다
조사하다 알게 된 건데, Cloudflare 같은 거대 인프라 회사의 대형 장애가 이번이 처음이 아니다. 불과 몇 달 전인 2025년 11월에도 Cloudflare 장애로 전 세계 수많은 사이트가 동시에 먹통이 된 적이 있다. 그때도 원인은 외부 공격이 아니라 내부 설정/코드 문제였다.
비슷한 일이 다른 회사에서도 반복된다. 큰 클라우드 업체에서 설정 오류 하나로 수많은 서비스가 동시에 멈추는 사고가 종종 일어난다. 패턴이 비슷하다. 해커가 아니라, 내부의 작은 변경 하나가 거대한 시스템을 무너뜨린다.
왜 자꾸 이럴까? 시스템이 너무 크고 복잡해져서, 한 사람이 전체를 다 이해하기 어렵기 때문이다. "이 작은 변경이 저 멀리서 무슨 영향을 줄지" 예측이 안 되는 지점이 생긴다. 그래서 요즘 보안·인프라에서 자동 안전장치와 모니터링을 그렇게 강조하는 거구나, 하고 이해하게 됐다.
단일 장애점이라는 개념
이번 사건을 관통하는 핵심 개념이 하나 있다. 단일 장애점[SPOF] 이다.
말 그대로 "여기 하나만 고장 나면 전체가 멈추는 지점" 을 뜻한다. 아무리 큰 시스템이라도 이런 급소가 하나 있으면, 그 하나가 무너지는 순간 전부 같이 무너진다. 이번엔 Cloudflare가 너무 많은 서비스의 길목을 쥐고 있다 보니, Cloudflare 자체가 인터넷의 거대한 단일 장애점이 돼버린 셈이다.
그래서 보안·안정성을 따질 때 "이 시스템의 단일 장애점이 어디냐" 를 찾는 게 중요하다고 한다. 그리고 그걸 없애려고 이중화 — 즉 같은 역할을 하는 예비를 하나 더 두는 — 같은 걸 한다. 한쪽이 죽어도 다른 쪽이 받쳐주게. 이번 사고는 그 개념을 아주 비싼 값으로 보여준 사례였다.
보완이 미흡했던 부분
처음 배우는 입장에서도 교훈이 선명했다.
- 빈 값에 대한 방어가 없었다 — "값이 비면 위험하니 아무것도 하지 말자"는 가드레일이 있었다면 사고 자체가 안 났다. 사소해 보이는 입력 검증이 이렇게 크다.
- 자동화의 문제점 — 자동 작업은 편하지만, 잘못된 명령을 사람보다 훨씬 빠르고 넓게 실행해버린다. 자동화일수록 안전장치가 더 중요하다는 걸 느꼈다.
- 느린 복구 — 망가뜨리는 데 1초, 복구하는 데 4시간. 사고를 막는 것만큼이나 빠르게 되돌리는 능력인 롤백 도 중요하다는 걸 알았다. 그래서 재발방지책에도 "빠른 롤백"이 들어간 거다.
- 한 곳에 너무 몰린 인터넷 — Cloudflare 하나 삐끗했다고 내 게임까지 멈춘 것 자체가, 인터넷이 소수 기업에 크게 의존하는 단일 장애점 구조라는 걸 보여준다. 이건 Cloudflare만의 잘못은 아니라, 우리 모두가 편리함을 위해 감수하고 있는 위험이다.
마무리하며 느낀 점
그냥 게임 안 된다고 짜증냈던 저녁이, 알고 보니 WHERE 조건 하나가 비는 바람에 전 세계 인터넷 일부가 6시간 멈춘 사건이었다는 게 아직도 신기하다.
특히 인상 깊었던 건, 이게 거창한 해킹이 아니라 평범한 코드 실수에서 시작됐다는 점이다. 보안이라고 하면 해커가 뚫는 것만 생각했는데, 내부의 작은 실수도 서비스를 마비시키는 보안 사고가 된다는 걸 처음 배웠다. 보안에서는 이렇게 "서비스가 멈추지 않고 계속 쓸 수 있는 성질"을 가용성이라고 부르는데, 이번 사고는 바로 그 가용성이 무너진 경우였다. 앞으로 내가 코드 짤 때도 빈 값 검사, 조건 확인을 절대 우습게 보면 안 되겠다고 생각했다.