Cloudflare

37 posts
AI 크롤러를 막으면 돈이 될까?

AI 크롤러를 막으면 돈이 될까?

1년 전 Cloudflare가 꽤 과감한 일을 벌였습니다. 2025년 7월 1일을 "콘텐츠 독립기념일"이라 부르면서, 신규 도메인에서는 AI 크롤러를 기본으로 차단하도록 정책을 뒤집었거든요. 그동안 웹의 기본값은 "일단 열려 있음"이었는데, 그걸 "먼저 허락을 구하라"로 바꾼 겁니다. 여기에 크롤링 한 건마다 요금을 매기는 Pay Per Crawl까지 얹었습니다. 30년 가까이 예약석으로만 남아 있던 402 Payment Required 상태 코드를 꺼내 쓴 것도 이때였고요. 저처럼 개인 블로그를 운영하는 사람 입장에서 궁금한 건

Web Bot Auth: IP 대신 서명으로 봇의 신원을 증명하기

Web Bot Auth: IP 대신 서명으로 봇의 신원을 증명하기

서버 로그에 GPTBot이 찍혀 있다고 해봅시다. 이게 정말 OpenAI가 보낸 요청일까요? 🤔 User-Agent 헤더는 그냥 문자열입니다. curl -A "GPTBot" 한 줄이면 누구나 GPTBot 행세를 할 수 있죠. 그래서 지금까지는 IP 주소로 한 번 더 확인했습니다. 봇 운영자가 자기 IP 대역을 공개하면 사이트는 요청이 그 대역에서 왔는지 대조하는 방식이었는데요. 그런데 이 방식이 요즘 급격히 무너지고 있습니다. AI 에이전트가 사용자를 대신해 웹을 돌아다니기 시작하면서부터입니다. 이런 에이전트는 서버리스 환경이나

Cloudflare OS: AI 에이전트를 위한 운영체제

Cloudflare OS: AI 에이전트를 위한 운영체제

에이전트에게 작업을 맡겨두고 커피를 타러 다녀온 적 있으신가요? 돌아와 보면 첫 단계에서 승인 창을 띄워놓고 얌전히 기다리고 있죠. 😅 이런 일이 몇 번 반복되면 손이 가는 곳은 대체로 정해져 있습니다. 자동 승인을 켜거나, 권한 설정을 통째로 건너뛰는 옵션을 쓰거나. 안전하게 쓰라고 만든 장치가 오히려 위험한 선택을 부추기는 셈인데요. 개인이 쓰는 코딩 에이전트에서도 이런데, 회사 전체가 에이전트에 GitHub, Google Docs, Slack을 물려준다고 생각하면 문제는 훨씬 커집니다. Cloudflare가 2026년 8월에

Cloudflare Agents SDK로 상태 있는 AI 에이전트 만들기

Cloudflare Agents SDK로 상태 있는 AI 에이전트 만들기

AI 채팅을 하나 만들었다고 해볼까요? 사용자가 목표를 알려주고 대화를 나누는 동안에는 제법 그럴듯하게 동작합니다. 그런데 브라우저를 닫았다가 다시 열면 이전 목표를 잊습니다. "30분 뒤에 다시 알려줘"라고 해도 그때까지 프로세스를 붙잡아 둘 방법이 마땅치 않고요. 여러 기기에서 같은 대화에 접속하면 상태가 서로 어긋나기도 합니다. 🤔 대형 언어 모델(large language model, 이하 LLM)을 호출하는 것만으로는 이런 문제를 해결할 수 없습니다. 모델 밖에서 사용자별 상태를 저장하고, 실시간 연결을 관리하고, 정해진

Cloudflare Cron Triggers로 정기 작업 스케줄링하기

Cloudflare Cron Triggers로 정기 작업 스케줄링하기

매일 새벽에 낡은 데이터를 지우거나, 30분마다 외부 API에서 시세를 긁어오거나, 아침마다 요약 리포트를 보내는 일. 이런 정기 작업은 흔하지만, 이거 하나 돌리자고 서버나 VM을 24시간 켜두는 건 아깝죠. crontab을 걸어둘 상시 머신이 필요하고, 그 머신은 대부분의 시간을 놀면서 요금만 축내니까요. Cloudflare Workers의 Cron Triggers는 이 문제를 관리형으로 풉니다. 정해진 시각이 되면 Cloudflare가 알아서 우리 코드를 깨워주고, 실행이 끝나면 다시 잠들어요. 상시 켜둘 서버도 cron 데몬

Cloudflare Workers로 서버리스 Discord 봇 만들기

Cloudflare Workers로 서버리스 Discord 봇 만들기

게이트웨이로 봇을 띄우면 한 가지 숙명이 따라옵니다. 봇 프로세스가 24시간 살아 있어야 한다는 거예요. 노트북을 끄면 봇도 오프라인이 되니, 늘 켜져 있는 서버나 컨테이너에 올려둬야 하죠. "간단한 슬래시 커맨드 하나 만들려는 건데 서버까지 빌려야 하나?" 싶은 순간이 옵니다. 그런데 슬래시 커맨드나 버튼에만 반응하는 봇이라면, 굳이 항상 켜둘 필요가 없습니다. 요청이 올 때만 깨어나는 서버리스로 만들 수 있거든요. 이번 글에서는 Cloudflare Workers에 슬래시 커맨드에 응답하는 봇을 올려서, 호스팅 걱정 없이 배포하는

Void AI: 라우트 핸들러에서 LLM을 타입 안전하게 호출하기

Void AI: 라우트 핸들러에서 LLM을 타입 안전하게 호출하기

앱에 AI 기능을 하나 붙이려고 마음먹으면, 정작 모델을 부르는 코드보다 그 주변을 차리는 일이 더 번거롭습니다. 어느 제공사를 쓸지 정하고, SDK를 설치하고, API 키를 환경변수로 빼고, 스트리밍 응답을 직접 파싱하고, 사용량이 얼마나 나왔는지 따로 추적하고… 정작 "프롬프트를 보내고 답을 받는" 본질은 한 줄인데 말이죠. Void는 이 주변 작업을 void/ai라는 클라이언트로 미리 차려둡니다. Cloudflare의 AI 게이트웨이 위에서 동작하는 타입 안전한 클라이언트인데, Void 라우팅에서 본 라우트 핸들러 안에서 모델

SQLite FTS5로 전문 검색 구현하기

SQLite FTS5로 전문 검색 구현하기

블로그나 문서 앱을 만들다 보면 처음에는 검색 기능을 아주 단순하게 시작하게 됩니다. 제목이나 본문에 검색어가 들어 있는지 LIKE '%검색어%'로 확인하면 되니까요. 데이터가 몇십 개일 때는 이것만으로도 충분합니다. 그런데 글이 수백 개, 수천 개로 늘어나면 느낌이 달라집니다. 검색 속도가 느려지고, 관련도 순 정렬도 어렵고, 검색 결과에서 어느 부분이 매칭됐는지 보여주기도 번거로워요. "검색"이라는 단어가 한 번 들어간 글과 본문 전체가 검색에 관한 글을 같은 수준으로 다루게 되는 것도 아쉽습니다. 이럴 때 SQLite만 쓰고

Cloudflare AI Gateway로 AI 요청 캐싱하고 모니터링하기

Cloudflare AI Gateway로 AI 요청 캐싱하고 모니터링하기

앱에 LLM 호출 한 줄을 붙이는 건 쉽습니다. 그런데 그게 프로덕션에 올라가는 순간 이야기가 달라지죠. 같은 질문이 하루에도 수백 번 들어오는데 매번 돈을 내고 모델을 부르고 있진 않은지, OpenAI가 잠깐 흔들릴 때 서비스가 같이 멈추진 않을지, 이번 달 토큰 비용이 얼마나 나왔는지, 누가 우리 키로 폭주하고 있진 않은지… 정작 "프롬프트 보내고 답 받기"는 한 줄인데 그 주변을 지키는 일이 훨씬 많습니다. 게다가 Cloudflare Workers AI의 자체 모델로 시작했다가도, 복잡한 추론은 GPT나 Claude로 넘기고

Cloudflare Sandbox에서 안전하게 코드 실행하기

Cloudflare Sandbox에서 안전하게 코드 실행하기

AI 코딩 도구를 만들다 보면 결국 "생성한 코드를 어디서 실행할 것인가?"라는 문제를 만나게 됩니다. 단순히 코드를 문자열로 돌려주는 것만으로는 부족하거든요. 테스트도 돌려봐야 하고, 파일도 만들어야 하고, 때로는 개발 서버를 띄운 뒤 브라우저에서 확인할 수 있는 미리보기 URL도 필요합니다. 그렇다고 사용자의 코드를 내 서버에서 그대로 실행하기에는 부담이 큽니다. 코드는 파일 시스템을 건드릴 수도 있고, 오래 실행될 수도 있고, 의도치 않게 서버 자원을 많이 쓸 수도 있으니까요. 그래서 AI 에이전트나 코드 실행 서비스를 만들

Void로 프로덕션 앱 이전하기: 하루 만의 컷오버 실전 기록

Void로 프로덕션 앱 이전하기: 하루 만의 컷오버 실전 기록

지난번 Void는 Vite 네이티브 배포 플랫폼이라는 글에서 "이게 자바스크립트의 Rails가 될 수 있을까"를 다뤘는데요. 그때는 직접 써보지 않고 개념만 파헤친 소개글이었습니다. 이번엔 다릅니다. TanStack Start + Cloudflare Workers + D1으로 운영 중이던 실서비스를 하루 만에 Void로 컷오버하면서 직접 부딪힌 기록이에요. 결론부터 말씀드리면 코드 변경은 거의 없었고, 빌드는 3배 빨라졌고, 그리고 베타 제품답게 문서에 없는 지뢰를 다섯 개나 밟았습니다. 💥 이 글은 그 지뢰들을 어떻게 역공학으로

Void 환경변수: env.ts로 타입 안전하게, 시크릿까지

Void 환경변수: env.ts로 타입 안전하게, 시크릿까지

Void 인증을 붙이고 나면 곧바로 BETTER_AUTH_SECRET이라는 비밀 키를 마주하게 됩니다. 세션 토큰을 서명하는 값인데, 코드에 적을 수도 없고 깃에 올릴 수도 없죠. 비단 인증만의 문제도 아닙니다. Stripe 키, 웹훅 URL, 외부 API 토큰까지, 앱을 키우다 보면 "코드 밖에서 주입해야 하는 값"이 계속 늘어나거든요. 그런데 우리가 환경변수로 늘 겪던 불편이 있습니다. process.env.PORT는 항상 문자열이라 매번 숫자로 바꿔야 하고, 키 이름에 오타가 나도 런타임에야 터지고, 어떤 값이 필수인지는 RE

Cloudflare Access 신원 공급자(IdP) 연동 제대로 이해하기

Cloudflare Access 신원 공급자(IdP) 연동 제대로 이해하기

Cloudflare Access로 내부 대시보드를 막아두고 나면, 자연스럽게 다음 질문이 따라옵니다. "그래서 로그인은 대체 누가 처리하는 거지?" Access 설정 화면 어디에도 비밀번호를 저장하는 곳은 없고, 사용자 목록을 직접 만드는 메뉴도 보이지 않거든요. 그런데도 @mycompany.com 직원만 통과시키고, 인턴 그룹은 제외하고, MFA를 강제하는 정책이 멀쩡히 돌아갑니다 🤔 비밀은 Access가 인증을 직접 하지 않는다는 데 있습니다. 대신 외부 신원 공급자(Identity Provider, 이하 IdP)에게 "이 사

Void 인증: Better Auth로 로그인부터 라우트 보호까지

Void 인증: Better Auth로 로그인부터 라우트 보호까지

Void 데이터베이스에서 테이블을 만들고 Void 라우팅으로 API까지 열고 나면, 다음으로 부딪히는 벽은 늘 똑같습니다. "그래서 이 요청을 보낸 사람이 누구인지 어떻게 알지?"라는 질문이죠. 로그인 없는 앱은 결국 누구나 같은 화면을 보는 앱이니까요. 다행히 Void는 인증을 거의 공짜로 얹어줍니다. 따로 라이브러리를 고르고 세션 저장소를 붙이고 콜백을 짜는 그 지난한 과정 없이, 설정 한 줄과 헬퍼 몇 개로 로그인이 돌아가거든요. 이번 글에서는 인증을 켜고, 회원가입과 로그인을 붙이고, "로그인한 사람만 들어올 수 있는" 영역

Void 폼과 액션: useForm으로 끝까지 타입 안전하게

Void 폼과 액션: useForm으로 끝까지 타입 안전하게

Void 라우팅에서 데이터를 읽어 오는 로더는 자세히 봤는데요. 정작 데이터를 바꾸는 쪽은 "로더 대신 action을 내보낸다"는 한 줄로 넘어갔습니다. 사실 폼을 다루는 일은 읽기보다 손이 많이 가죠. 입력값을 검증하고, 에러를 화면에 표시하고, 제출 중에는 버튼을 막고, 성공하면 목록을 새로고침하고… 이번 글에서는 Void가 이 과정을 useForm 하나로 어떻게 묶어주는지 살펴보겠습니다. 액션으로 데이터 바꾸기 데이터를 읽을 때 로더를 썼다면, 바꿀 때는 액션을 씁니다. 페이지의 .server.ts에서 action을 내보내면

Cloudflare Vectorize로 엣지에서 벡터 검색 구현하기

Cloudflare Vectorize로 엣지에서 벡터 검색 구현하기

요즘 챗봇이나 검색 기능을 만들다 보면 "의미 기반 검색"이 거의 필수가 됐어요. 사용자가 "환불 받고 싶어요"라고 입력해도 "결제 취소 절차"가 적힌 문서를 찾아줘야 하잖아요. BM25 같은 키워드 검색은 단어가 정확히 일치해야 하기 때문에 이런 경우에 약한데, 그 빈틈을 메우는 게 바로 의미 기반 검색입니다. 이런 의미 기반 검색을 구현하려면 텍스트를 벡터로 바꿔 저장하고 비슷한 벡터를 빠르게 찾아주는 벡터 데이터베이스가 필요합니다. Pinecone, Weaviate, Qdrant 같은 전문 서비스도 좋지만 Cloudflare

1Password Shell Plugins로 CLI 인증 관리하기

1Password Shell Plugins로 CLI 인증 관리하기

CLI 도구를 쓰다 보면 인증 토큰을 어디에 둘지가 늘 고민입니다. GitHub CLI는 GH_TOKEN, Cloudflare Wrangler는 CLOUDFLARE_API_TOKEN 같은 환경 변수를 지원하는데요. 편하다고 셸 설정 파일이나 .env 파일에 토큰을 넣어두면 어느 순간 평문 시크릿이 로컬 디스크 여기저기에 흩어집니다. 1Password에는 이런 문제를 줄여주는 Shell Plugins 기능이 있습니다. CLI가 인증 정보를 필요로 할 때 1Password가 토큰을 꺼내 환경 변수로 주입하고, 사용자는 지문이나 Appl

Void 데이터베이스: 로컬 SQLite에서 Cloudflare D1까지

Void 데이터베이스: 로컬 SQLite에서 Cloudflare D1까지

Void: Vite 네이티브 배포 플랫폼에서 데이터베이스를 소개할 때 "로컬에서는 SQLite, 프로덕션에서는 Cloudflare D1로 매핑된다"는 한 줄로 짚고 넘어갔는데요. 이번엔 그 데이터베이스 레이어를 제대로 들여다볼게요. 스키마는 어떻게 정의하고, 마이그레이션은 어떻게 굴리고, 쿼리는 어떻게 날리는지까지 차근차근 살펴보겠습니다. Void 라우팅에서 API 핸들러에 insertUserSchema로 입력을 검증하는 예제를 봤는데, 그 검증기가 어디서 오는지도 이 글에서 채워집니다. 로컬은 SQLite, 프로덕션은 D1 Voi

Void 라우팅: pages로 화면을, routes로 API를

Void 라우팅: pages로 화면을, routes로 API를

Void: Vite 네이티브 배포 플랫폼에서 프로젝트 구조를 훑어볼 때 pages/와 routes/ 디렉토리를 잠깐 스쳐 지나갔는데요. 사실 이 두 디렉토리가 Void로 앱을 만드는 거의 모든 것을 담당합니다. 화면을 그리는 일도, API를 여는 일도 결국 "어떤 파일을 어디에 두느냐"로 결정되거든요. 이번 글에서는 Void의 라우팅을 제대로 파헤쳐볼게요. 파일 하나가 어떻게 URL이 되는지, 서버에서 가져온 데이터가 어떻게 화면 컴포넌트로 흘러가는지, API 핸들러는 어떻게 쓰고 입력 검증과 미들웨어는 어떻게 거는지까지 차근차근

Cloudflare Images Transformations으로 이미지 최적화를 엣지에 맡기기

Cloudflare Images Transformations으로 이미지 최적화를 엣지에 맡기기

블로그나 커머스 사이트를 운영해 보신 분이라면 이미지 때문에 골머리를 앓아본 경험이 한 번쯤 있으실 텐데요. 원본은 4000픽셀짜리인데 썸네일은 300픽셀이면 충분하고, 어떤 브라우저는 AVIF를 좋아하는데 어떤 브라우저는 WebP만 받아먹고, 심지어 같은 이미지를 카드용과 히어로용으로 다르게 잘라야 하는 경우도 있죠. 😅 예전에는 이런 작업을 하려면 Sharp 같은 라이브러리로 직접 변환 파이프라인을 짜거나, imgix 같은 별도의 이미지 CDN을 붙이는 게 일반적이었는데요. Cloudflare는 조금 다른 접근을 제안합니다.

Discord