HN에 글을 올렸더니 웹사이트가 AI 봇 트래픽으로 범람했다
요약
개발자가 HN(Hacker News)에 게시한 커스터마이징 피드 리더 웹사이트가 갑자기 엄청난 트래픽을 받게 되었습니다. 분석 결과, 이 트래픽의 상당 부분은 실제 사용자의 활동이 아닌, AI 요약 뉴스레터 제작을 목적으로 하는 악성 봇(Bot)들로부터 발생한 것으로 밝혀졌습니다. 개발자는 이를 통해 웹사이트를 보호하고 트래픽 부하에 대비하는 방법을 모색했습니다.
핵심 포인트
- HN 게시물 이후 웹사이트가 과도하게 느려지는 현상을 경험함.
- 트래픽의 상당 부분이 실제 콘텐츠 소비가 아닌 봇 요청에서 발생했음을 확인.
- AI 요약 뉴스레터 제작을 목적으로 하는 악성 봇이 주요 원인이었음.
- 웹사이트를 보호하기 위해 로깅 및 트래픽 분석 능력이 중요함을 시사함.
Sammy의 블로그
목차
-
- HN에 글을 올렸더니 웹사이트가 AI BOT 트래픽으로 범람했다
-
- LLM을 사용하여 Emacs 웹 브라우저를 다시 멋지게 만들기
-
- 기술이 좋아졌다면, 왜 모든 것이 나빠졌는가?
-
- Deft 버전 0.2.0
-
- LLM은 어느 정도까지가 적당한가?
-
- 약 350줄의 Clojure로 체스 만들기
-
- Deft 발표: Clojure와 ClojureScript를 위한 클래스 및 인터페이스 시스템
-
- 내 블로그가 이제 RSS를 지원합니다
-
- Wordle에서 이기는 방법
-
- 습관의 힘 (도서 리뷰 Pt 1)
-
- 현대 화폐 이론과 당신
-
- 완벽한 카메라
-
- 카메라 렌즈: 가방 속 내용물
-
- 왜 많은 주요 예측이 틀렸는가
-
- 민주당 경선 뒤에 숨겨진 복잡한 수학
-
- 탄핵 사태는 어떻게 돌아가는가
-
- 화학 요법으로 암 치료하기 (Part 3)
-
- 화학 요법으로 암 치료하기 (Part 2)
-
- 화학 요법으로 암 치료하기 (Part 1)
-
- 아무것도 하지 않는 것의 중요성
-
- 제가 Citizens United를 지지하는 이유
-
- 카메라 설정
1. HN에 글을 올렸더니 웹사이트가 AI BOT 트래픽으로 범람했다
지난 몇 년 동안 저는 sprinklz.io라는 커스터마이징 가능한 피드 리더를 개발해 왔는데, 이 도구는 뉴스 피드에서 특정 주제의 우선순위를 낮출 수 있는 기능 등을 제공합니다.
한 달 전, 제가 이곳 HN에 이 도구를 게시했고 약 100개의 추천을 받았습니다. 좋았죠! 사람들은 LLM(대규모 언어 모델)에 대한 이야기를 듣는 것에 정말 지쳤고, 피드에서 그 주제의 우선순위를 낮출 수 있는 것을 즐기는 것 같았습니다. 이것이 왜 유용한 도구인지 보여주는 좋은 시연이었습니다. 모든 것이 잘 되어가던 중...
제 웹사이트가 느려졌어요. 정말, 고통스러울 정도로요. 처음에는 갑자기 인기 있는 게시물 덕분에 관심이 쏠린 거라고 생각했어요. 어떤 개발자에게나 하는 말이지만, 저는 이 상황을 축하하는 동시에 미래에 제 웹사이트를 더 탄력적으로 만들겠다고 다짐했죠. 그런데 이상하게도 느려진 현상은 계속되었고, 심지어 제가 게시물을 올린 며칠 후에도 악화되기 시작했어요. 그리고 제가 기록한 지표들은 말이 되지 않았어요. 예를 들어, 실제로 활동하는 로그인 사용자 몇 명과, 엄청나게 높은 부하를 보이는 서버가 있었죠.
그래서 저는 데이터를 살펴봤습니다. 모든 엔드포인트에 대해 최상위 로깅을 추가해서 (각 URL 경로로 요청이 얼마나 많이 이루어졌는지) 확인했고, 대부분의 요청들이 뉴스 기사를 가져오려는 시도조차 하지 않았다는 것을 발견했어요! 참고로 제 웹사이트는 단일 페이지 애플리케이션(Single-Page Application)으로 구축되었기 때문에, 이는 대다수의 요청이 페이지를 렌더링하는 데 필요한 자바스크립트(JavaScript) 실행조차 하지 않았다는 뜻이에요(!)
더 깊이 파고들어 악용자를 찾기 위해 집계된 NGINX 로그를 살펴봤는데, 믿을 수 없을 만한 사실을 알게 됐어요. 저희 트래픽의 거의 절반이 특정 사용자로부터 오고 있었던 거예요. 이름을 밝힐 수는 없지만, 그들은 자신들을 웹사이트 변경 사항을 감지하고 이를 AI 요약 뉴스레터로 정리하는 서비스라고 설명했어요. 여기서 '변경 사항을 감지한다'는 것은 분당 수많은 횟수로 저희 웹사이트에 쿼리한다는 뜻이에요. 차단했습니다.
다른 사용자들 중 몇몇은 일반적인 알려진 크롤러들이었고, 자신들을 그렇게 명확히 밝혔습니다. Claude bot, OpenAI bot, 구글 검색 인덱서(Google Search Indexer) 등 여러 개가 있었어요. 심지어 도중에 취약점 스캐너들도 몇 개 잡았죠. 적어도 누군가는 -/wp-content/phpinfo.php에 접근하려고 시도하고 있었어요 (제 웹사이트는 워드프레스 사이트가 아닙니다). 대부분의 AI 스캐너들을 막기 위해 robots.txt를 추가했지만, google-bot과 다른 검색 관련 트래픽은 허용했고, Claude에게 모든 취약점 경로를 쿼리하도록 요청하여 스캐너들을 모방하게 함으로써 제가 무언가를 유출하고 있지 않은지 확인했어요. 또한 합리적인 속도 제한(rate limit) 등등을 추가했습니다.
가장 중요한 교훈은 제 웹사이트를 더 빠르게 만들어야 한다는 것입니다. 저는 실제 트래픽의 xxx QPS(초당 쿼리 수)를 감당할 수 있는 웹사이트, 그리고 무거운 부하에서도 이전보다 더 잘 확장되는 웹사이트가 되고 싶습니다. 이 경험에서 영감을 받아 지난 몇 주 동안 근본적인 인프라에 상당히 많은 개선을 했으며, 이는 모든 사용자에게 상당한 성능 향상을 가져올 것입니다.
P.S. 확인하고 싶으시다면, 웹사이트는 완전히 무료이며 여기에서 이용할 수 있습니다.
요약하자면, 이 서비스는 Hacker News의 점수 합계 같은 것들 외에도 사용자가 직접 커스터마이징을 정의할 수 있게 해줍니다. AI나 LLM과 같은 주제를 필터링하는 데 사용할 수 있지만, 주제는 완전히 임의적이며 자신만의 커스터마이징 기능을 프로그래밍할 수 있습니다.
2. LLM을 사용하여 Emacs 웹 브라우저를 다시 위대하게 만들기
제가 사람들에게 emacs 웹 브라우저에 대해 이야기하면, 그들의 첫 반응은 '잠깐, emacs에 웹 브라우저가 있어?!'이고, 그다음에는 '그래… 뭐, 일종의 웹 브라우저는 맞는 것 같네.'입니다.
emacs 웹 브라우저는 터미널 기반의 텍스트 전용 환경에서 웹페이지를 렌더링하도록 설계되었으며, 기대하는 방식 그대로 작동합니다. HTML만으로 구성된 작고 단순한 콘텐츠가 있는 웹사이트에서는 잘 작동하지만, 다른 종류의 웹사이트에는 그다지 좋지 않습니다.
문제는 emacs가 주로 텍스트 전용 에디터라는 점인데, 현대 인터넷은 결코 순수 텍스트 기반이 아니라는 것입니다. 1990년대의 단순한 스타일로 디자인된 간단한 HTML은 일반 텍스트로 명확하게 변환되지만, 시각적 스타일링, 무거운 JavaScript, 그리고 전반적인 혼란을 동반하는 현대적인 UI 디자인은 그렇지 않습니다.
emacs 웹 브라우저는 우리가 시간 여행을 할 방법을 찾을 수만 있다면 정말 좋을 텐데요…
좋습니다. 계획은 간단합니다. 우리는 현대 웹페이지를 가져와 소스 코드를 구식의 단순 스타일 HTML로 재작성한 다음, 이를 emacs 웹 브라우저로 파이프(pipe)합니다. 이 과정을 쉽고 대규모로 수행할 방법을 찾기만 하면 됩니다.
음, LLM에 대해 잊지 않으셨죠? 전 세계의 스팸 콘텐츠 양을 줄이는 방식으로 사용하게 되어 다행입니다.
기본적으로 계획은 다음과 같습니다:
- Firefox에서 웹페이지를 열고
- 페이지를 로드하고 모든 자바스크립트를 실행하며
- LLM에게 현재 페이지의 내용을 단순화된 텍스트로 변환하는 재사용 가능한 프로그램을 생성하도록 요청합니다. - 생성된 자바스크립트를 Firefox 브라우저에 주입합니다.
- 새로운 페이지 소스를 가져와 emacs 웹 브라우저로 전달합니다.
네, 그래서 제가 사용해 봤는데 아주 잘 작동합니다. 현실적으로 eww(emacs web wowser)가 이전에 실행되지 않았던 많은 웹페이지에서 사용할 수 있습니다.
아래는 전후 비교 예시입니다:
Clojure의 mapcat 문서

그림 1: (이전) eww-readable 사용

그림 2: (이후) simpleweb-simplify-page 사용
초기 수정자 프로그램을 생성하는 데는 시간이 걸리지만, 일단 생성되면 상당히 빠르게 실행되며, 일상적인 브라우징 중에는 추가적인 LLM 호출이 거의 필요하지 않습니다. 저도 직접 사용하면서 이 경험을 즐기고 있습니다.
소스 코드는 여기에 있습니다: https://github.com/sstraust/simpleweb
그리고 오픈 소스이며 설치가 무료입니다, 등등등.
2. 기술이 좋아졌는데 왜 모든 것이 나빠졌는가?
저는 우리 모두가 이 답을 알고 있다고 생각합니다: 잘못된 인센티브(bad incentives).
기술은 시스템을 더 생산적으로 만들지만, 실제로 당신 개인을 더 생산적으로 만드는 것은 아닙니다. 컴퓨터가 더 효율적이 되도록 하는 도구들은 또한 사람들이 당신의 시간, 주의력, 그리고 웰빙을 착취하는 데 더 효율적이도록 만듭니다. 저는 신경망(neural nets)에 대해 이야기하고 있습니다.
저는 2018년에 이 문제를 처음 알아차렸습니다. 아니, 오히려 제가 문제가 있다는 것을 알게 되었는데, 그 문제는 매일 스타크래프트 2 리플레이를 보며 시간을 어떻게 보냈는지, 그리고 어떻게 또 새벽 2시까지 깨어 있을 수 있었는지 궁금해하는 데 하루 3시간을 쓰는 것이었습니다.
저에게 흥미로운 점은 2010년대 후반까지는 이런 문제들이 전혀 없었다는 것입니다. 저는 적어도 2000년대 중반부터 인터넷 연결이 된 컴퓨터를 가지고 있었고, 얼마 지나지 않아 트위터나 레딧 같은 스마트폰도 가졌습니다. 제가 시간이 지나면서 회복력이 떨어졌을 수도 있지만, 저는 변화한 것은 기기들 때문이라는 강한 의심을 하고 있습니다.
정확히 짚어내기는 어렵지만, 시스템이나 웹사이트와 상호작용할 때마다 일종의 적대적인 게임(adversarial game)을 하는 것 같은 느낌이 듭니다. 저는 그저 제 하루를 보내고 컴퓨터에 대한 기사를 좀 읽으려고 하는데, 그쪽에서는 저를 사이트에 조금 더 오래 머물게 할 방법을 찾으려고 애쓰는 식입니다.
또한 소프트웨어 엔지니어링이 취미가나 열정을 가진 사람들의 분야에서 재정이나 비즈니스 마인드를 통해 점점 리더로 발전해 온 과정과 함께, 우리가 사랑했던 주요 도구들이 극도로 지루하면서도 극도로 수익성이 높은 것이 되어버렸다는 느낌도 듭니다.
그럼 우리는 무엇을 할 수 있을까요? 이걸 멈추게 하려면요?
- 풀밭에 나가기(touch grass). 정말로 세상이 이런 상황이라면, 저는 그냥 떠나는 것이 최선의 해결책이라고 생각합니다. 계획 자체가 온라인으로 이루어지는 경우가 많아서 쉽지 않지만, 만약 세팅할 수 있다면 장담컨대 친구들과 공원에서 체스를 두는 하루가 인터넷에서 보낼 수 있는 어떤 시간보다 나을 것입니다.
- 거리로 나가기(take to the streets). 저는 시위하는 것이 효과적이라고 생각하며, 더 많은 사람들이 그렇게 해야 한다고 봅니다. 만약 행동할 의지가 있다면, 그것은 다른 사람들에게도 행동할 수 있다는 모델을 제시합니다.
- 같은 기기로 돌아오는 것을 멈추기. 우리 모두에게는 도박꾼의 오류(gambler's fallacy)가 있는 것 같습니다. 처음에는 돈이 안 돼도 가끔은 되니까 다시 기계에 동전을 넣으려고 하지만, 실제로는 그렇게 작동하지 않습니다. 만약 돈을 잃고 있다면 교훈은 기계에 동전을 넣는 것을 멈추는 것입니다.
편집자 참고 사항: 저는 현대 인터넷에 대한 몇 가지 좌절감을 해소하기 위한 방법으로 무료 사용자 정의 뉴스 리더를 만들고 있습니다. 만약 이 것을 사용하지 않더라도, 개별 블로그나 웹사이트를 팔로우하는 것을 추천합니다. 왜냐하면 이런 거대한 플랫폼에서 완전히 벗어나는 것이 훨씬 더 좋기 때문입니다.
편집자 참고 사항 2: 아직 이 최신 기사를 내 RSS XML에 게시하지 않았습니다. 아직 알림을 보내는 준비가 되지 않았기 때문입니다. 몇 주 안에 추가하겠습니다.
3. Deft 버전 0.2.0
Deft 0.2.0이 출시되었으니, 제가 무엇을 만들었는지, 그리고 왜 그것을 만들었는지에 대해 이야기할 좋은 시점이라고 생각합니다.
Clojure의 everything-is-a-map 툴킷의 핵심은 getter와 setter가 시간 낭비라는 것입니다. Clojure는 부분적으로 2008년의 형편없는 Java 워크플로우에 대응하여 만들어졌는데, 그 워크플로우에서는 getters, setters, 그리고 builders를 작성해야 했고, 아무도 좋아하지 않는 이러한 비대함을 떠안아야 했습니다.
문제는 내장된 defprotocol과 defrecord를 사용하여 데이터를 표현하고, 특정 필드의 존재에 의존하는 함수를 정의하려면, 그 정보를 프로토콜에 인코딩할 수 있는 유일한 방법이 getter와 setter 메서드를 추가하는 것입니다. 찝찝합니다.
프로토콜 + malli 스키마의 조합을 사용해서 이것을 표현할 수도 있지만, 그러면 사용할 때 '이 함수는 이 프로토콜을 구현하고 그리고 이 Malli 스키마를 구현하는 무언가를 입력으로 받는다'고 지정해야 합니다. 이것 역시 찝찝합니다.
우리가 원하는 것은 defprotocol과 defrecord 스타일로 사용할 수 있지만, 기본적으로 모든 getter와 setter 그리고 map 같은 기능을 제공하는 것입니다. 핵심 통찰은 레코드에 필드가 존재하면 다른 좋은 기능들도 얻을 수 있다는 것이므로, 단지 필수 키(required keys)를 가진 프로토콜에 대한 지원만 추가하면 됩니다.
Deft v0.2.0은 타입 및 프로토콜 정의에서 네임스페이스된 키(namespaced keys)에 대한 지원을 추가합니다. 즉, 이제 다음과 같이 할 수 있습니다:
(defp Positioned :required-keys [::pos - ::Point])
그리고
(deft Circle [::location/position radius]) (>Circle ::location/position [1 2] :radius 12)
이것은 해당 필드가 존재하는 것에 의존하는 메서드를 정의할 수 있기 때문에 유용합니다. 즉:
(defp Gremlin :extends [location/Positioned]) (defmethod game-object/get-hitbox ::Gremlin [self] (js/Matter.Bodies.rectangle (get-in self [::location/pos ::location/x]) (get-in self [::location/pos ::location/y]) 15 15))
확인해 보세요!
4. LLM이 너무 많으면 얼마나 많은가?
지난주에 『On the Edge』를 다 읽었는데, 별로였습니다. 네이트 실버(Nate Silver)를 존경하지 않는 건 아닙니다. 정말 많이 존경합니다. 그래서 그의 도박과 위험 감수에 관한 기념비적인 글이 장황한 난장판일 때, 저는 놀랐고 실망했습니다. 그럼에도 불구하고, 완벽주의자 기질 때문에 끝까지 읽었고, 마지막에는 다음과 같은 메시지를 접하게 되었습니다:
"ChatGPT는 이 책을 쓰는 데 큰 도움이 되었으며, 챕터 소제목, 은유, 비유와 같은 것을 생각해 내거나 그 내용을 다듬고, 그 내용이 자신의 코퍼스에 잘 표현될 가능성이 있는 기술적 주제에 대한 저의 이해를 정교화하는 창조적인 뮤즈 역할을 했습니다."
AI 자동 생성 콘텐츠
본 콘텐츠는 HN AI Posts의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기