웹 개발 데일리 브리핑 — 2026-10-17
Soshy··조회수 —

기준 시점: 2026-10-17 06:00 KST
조사 범위: 2026-10-16 06:00 ~ 2026-10-17 06:00 KST
추천 글 범위: 기준 시점 당시 최근 7일
1️⃣ 프론트엔드
이번 조사 범위에서 포함할 만한 주요 신규 발표를 확인하지 못했습니다.
React·Next.js·Vercel, Vue·Nuxt, Angular, Svelte·SvelteKit, Astro, Remix의 공식 블로그와 릴리스 채널을 확인했지만, 해당 24시간에 공개된 주요 프레임워크 기능이나 렌더링 API 변경은 확인하지 못했다.
Vite, TypeScript, ESLint, Biome를 비롯한 프론트엔드 개발 도구에서도 이번 조사 기간에 해당하는 중요한 신규 릴리스는 확인하지 못했다.
전날 소개한 Astro 7.4와 Void처럼 이미 다룬 발표는 반복하지 않았다.
2️⃣ 웹 플랫폼·브라우저
이번 조사 범위에서 포함할 만한 주요 신규 발표를 확인하지 못했습니다.
W3C, WHATWG, TC39, MDN, Chrome Developers·Chromium, Mozilla·Firefox, WebKit·Safari의 공식 발표를 확인했지만, 이번 24시간에 해당하는 주요 웹 API의 정식 출시나 웹 표준의 중요한 변경은 확인하지 못했다.
CSS, 접근성, 브라우저 성능과 관련된 개발 버전의 변경도 검토했으나 별도로 소개할 만한 주요 신규 발표는 확인하지 못했다.
다만 최근 CSS 기능을 활용해 JavaScript 없이 Scrollspy를 구현한 기술 글이 공개됐다. 새로운 브라우저 기능의 출시 발표는 아니므로 마지막 추천 글 섹션에서 다룬다.
3️⃣ 백엔드·인프라
Cloudflare AI Search, 한국어·중국어·일본어 키워드 검색 개선 — Trigram 토크나이저 지원 확대
- 발표일: 2026-10-16 — 정확한 게시 시각 미확인
- 적용 대상: Cloudflare AI Search의 키워드 검색
- 원문: https://developers.cloudflare.com/changelog/post/2026-10-16-cjk-keyword-search/
Cloudflare가 AI Search의 키워드 검색에서 한국어·중국어·일본어 문장을 더 정확하게 처리할 수 있도록 Trigram 토크나이저 지원을 개선했다.
검색 시스템에서 가장 기본적인 작업 가운데 하나는 사용자가 입력한 문장과 문서에 포함된 단어를 비교하는 것이다.
하지만 모든 언어가 동일한 방식으로 단어를 구분하지는 않는다.
영어에서는 일반적으로 공백이 단어의 경계를 나타낸다.
예를 들어 How to deploy a worker라는 문장은 공백을 기준으로 여러 단어로 나눌 수 있다.
반면 중국어와 일본어에서는 단어 사이에 공백을 사용하지 않는 경우가 많다.
한국어는 공백을 사용하지만 조사와 어미가 단어에 결합하는 특성이 있어 영어와 동일한 방식으로 처리하면 검색 정확도가 떨어질 수 있다.
이러한 언어적 차이는 검색 시스템의 토크나이저(Tokenizer) 선택에 직접적인 영향을 준다.
기존 키워드 검색의 문제
토크나이저는 입력된 문자열을 검색과 색인에 사용할 단위인 토큰(Token)으로 나누는 구성요소다.
Cloudflare AI Search에서는 키워드 검색을 위한 토크나이저를 설정할 수 있다.
기존의 porter 토크나이저는 영어와 같은 언어를 처리하는 데 적합하지만, 한국어·중국어·일본어에서는 기대한 검색 결과를 반환하지 못할 수 있었다.
예를 들어 사용자가 일본어로 다음 질문을 입력했다고 가정해 보자.
経費精算の締め日はいつですか?
뜻은 경비 정산 마감일이 언제인지 묻는 질문이다.
기존에는 이러한 문장에 공백이 없으면 검색 시스템이 전체 문자열을 하나의 구문으로 처리할 수 있었다.
이 경우 문서에 같은 내용이 다른 문장 형태로 포함돼 있더라도 정확히 일치하는 구문을 찾지 못해 검색 결과가 반환되지 않을 수 있었다.
문서에 실제로 답이 존재하는데도 검색 시스템이 해당 문서를 발견하지 못하는 것이다.
이번 업데이트는 Trigram 토크나이저를 사용한 키워드 검색에서 이러한 언어의 질의를 더 잘 처리하도록 개선했다.
Trigram 토크나이저의 동작
Trigram은 문자열을 연속된 세 글자 단위로 나누는 방식이다.
예를 들어 다음과 같은 문자열이 있다고 가정해 보자.
데이터베이스
이를 세 글자씩 겹쳐 나누면 다음과 같은 토큰을 만들 수 있다.
- 데이터
- 이터베
- 터베이
- 베이스
이 방식은 언어별 형태소 분석기를 사용하지 않고도 문자열의 일부가 일치하는 문서를 찾는 데 활용할 수 있다.
특히 명확한 공백 경계가 없는 언어에서 유용하다.
사용자가 입력한 표현과 문서의 표현이 완전히 동일하지 않더라도 일부 문자열 단위가 일치하면 검색 후보를 찾을 가능성이 생기기 때문이다.
다만 Trigram 방식이 항상 형태소 분석보다 우수한 것은 아니다.
세 글자 단위의 문자열이 일치한다고 해서 반드시 의미가 같은 것도 아니다.
따라서 검색 결과에는 의미적으로 관련성이 낮은 문서가 포함될 수 있으며, 문서의 길이와 언어 특성에 따라 검색 품질이 달라질 수 있다.
이번 변경은 한국어·중국어·일본어 검색에서 발생하던 기존 키워드 검색의 한계를 완화한 것으로 이해하는 것이 적절하다.
설정 변경에는 전체 재색인이 필요
Cloudflare는 한국어·중국어·일본어 콘텐츠를 처리하는 경우 다음 설정을 사용하도록 안내한다.
keyword_tokenizer: trigram
여기서 중요한 제한사항이 있다.
기존 토크나이저를 Trigram으로 변경하면 전체 재색인(Reindex)이 발생한다.
색인(Index)은 검색을 빠르게 수행하기 위해 문서를 토큰 단위로 정리해 저장한 자료구조다.
토크나이저가 변경되면 같은 문서라도 생성되는 토큰이 달라진다.
따라서 기존 색인을 그대로 사용할 수 없다.
검색 대상 문서를 새로운 토크나이저 기준으로 다시 처리해야 한다.
문서가 적은 프로젝트에서는 큰 문제가 되지 않을 수 있지만, 검색 대상 데이터가 많다면 재색인에 필요한 시간과 자원을 고려해야 한다.
또한 재색인 과정과 검색 서비스의 운영 정책에 따라 일시적으로 검색 결과가 달라질 가능성도 검토할 필요가 있다.
키워드 검색과 의미 검색의 차이
이번 변경이 AI Search의 모든 검색 방식에 동일하게 적용되는 것은 아니다.
특히 키워드 검색을 위한 토큰 처리 개선이라는 점을 구분해야 한다.
키워드 검색은 입력한 단어와 문서에 포함된 문자열 사이의 관계를 이용한다.
반면 벡터 기반 의미 검색(Semantic Search)은 문장이나 문서를 수치 벡터로 표현하고 의미적으로 가까운 데이터를 찾는다.
Trigram 토크나이저의 개선이 곧바로 임베딩 모델의 성능 향상을 의미하는 것은 아니다.
또한 검색 결과를 기반으로 답변을 생성하는 언어 모델 자체가 변경된 것도 아니다.
이번 업데이트는 한국어를 포함한 CJK 언어의 키워드 검색에서 문서를 발견하는 능력을 개선한 변화다.
특히 한국어 문서 검색, 사내 지식 검색, 고객지원 검색처럼 자연어 질문과 문서의 표현이 완전히 일치하지 않는 서비스에서 활용할 수 있는 기능이다.
Cloudflare Tunnel, 계정당 기본 라우트 한도를 1,000개에서 50,000개로 확대 — 대규모 Tunnel 운영을 위한 추가 구매 지원
- 발표일: 2026-10-16 — 정확한 게시 시각 미확인
- 적용 대상: Cloudflare Tunnel, Cloudflare Mesh
- 원문: https://developers.cloudflare.com/changelog/post/2026-10-16-tunnels-for-platforms-and-50k-routes/
Cloudflare가 Tunnel과 Mesh에서 사용할 수 있는 기본 라우트 한도를 계정당 1,000개에서 50,000개로 확대했다.
또한 하나의 계정에서 1,000개 이상의 Tunnel을 운영할 수 있도록 추가 Tunnel 구매 기능을 제공한다.
Cloudflare Tunnel은 외부 인터넷에서 직접 접근할 수 없는 서버나 애플리케이션을 Cloudflare 네트워크와 연결하는 기능이다.
일반적으로 웹서비스를 외부에 공개하려면 서버가 인터넷에서 접근 가능한 주소를 가지고 있어야 한다.
하지만 기업 내부 서비스나 개발 환경에서는 서버를 외부에 직접 노출하고 싶지 않을 수 있다.
이때 Tunnel을 사용하면 서버에서 Cloudflare 방향으로 연결을 생성하고, Cloudflare가 해당 연결을 통해 애플리케이션에 접근하도록 구성할 수 있다.
이를 이용하면 외부에서 서버로 직접 들어오는 연결을 개방하지 않고도 필요한 서비스를 제공할 수 있다.
라우트 한도 50배 확대
이번 업데이트에서는 기본 라우트 한도가 다음과 같이 변경됐다.
| 항목 | 기존 | 변경 |
|---|---|---|
| 계정당 기본 라우트 한도 | 1,000개 | 50,000개 |
| 적용 대상 | Tunnel·Mesh 라우트 | 동일 |
| 별도 설정 필요 | - | 없음 |
이 변경은 모든 계정에 자동으로 적용된다.
따라서 라우트 한도를 늘리기 위해 별도의 신청이나 설정 변경을 수행할 필요는 없다.
새로운 한도에는 다음 종류의 라우트가 포함된다.
- CIDR Route
- Hostname Route
CIDR은 IP 주소의 범위를 표현하는 방식이다.
예를 들어 특정 사설 네트워크 대역에 대한 접근 경로를 Tunnel로 연결할 수 있다.
Hostname Route는 특정 호스트 이름을 기준으로 요청을 전달하는 방식이다.
이번 변경은 이러한 라우트를 대규모로 사용하는 조직의 설정 한도를 확대한 것이다.
Public Hostname과 Route는 다르다
Cloudflare는 이번 발표에서 Published Application과 Route를 구분해야 한다고 강조한다.
Tunnel을 사용해 외부에 공개하는 웹 애플리케이션의 Public Hostname은 이번 라우트 한도에 포함되지 않는다.
예를 들어 하나의 Tunnel에 여러 웹 애플리케이션을 연결하고 다음과 같은 도메인을 사용할 수 있다.
admin.example.comapi.example.compreview.example.com
이러한 Published Application의 개수는 별도의 제한을 따른다.
Cloudflare에 따르면 하나의 Tunnel은 설정 크기에 따라 대략 5,000~10,000개의 Published Application을 지원할 수 있다.
따라서 이번 변경을 하나의 Tunnel에 50,000개의 웹 애플리케이션을 게시할 수 있게 됐다는 의미로 해석해서는 안 된다.
라우트 한도와 Published Application 한도는 서로 다른 설정이다.
Tunnels for Platforms
두 번째 변경은 Tunnels for Platforms다.
기존에는 하나의 Cloudflare 계정에서 운영할 수 있는 Tunnel 개수에 제한이 있었다.
현재 모든 계정에는 기본적으로 1,000개의 Tunnel이 포함된다.
이번 기능을 사용하면 추가 Tunnel을 구매해 하나의 계정에서 1,000개 이상의 Tunnel을 운영할 수 있다.
Cloudflare는 다음과 같은 사용 사례를 제시했다.
- 고객별 독립적인 Tunnel
- 기기별 Tunnel
- 개발 환경별 Tunnel
예를 들어 여러 고객을 대상으로 서비스를 제공하는 SaaS를 생각해 보자.
고객마다 독립된 사설 네트워크나 내부 API가 존재한다면 하나의 공통 Tunnel에 모든 고객을 연결하는 방식보다 고객별 Tunnel을 구성하는 방식이 적합할 수 있다.
이렇게 구성하면 고객별 연결 상태와 설정을 분리해서 관리할 수 있다.
또한 고객의 계약이 종료되거나 특정 고객의 연결에 문제가 발생했을 때 해당 Tunnel만 관리할 수 있다.
그러나 고객별 Tunnel을 분리했다고 해서 인증과 권한 관리가 자동으로 완성되는 것은 아니다.
각 Tunnel을 통해 접근할 수 있는 네트워크와 애플리케이션의 범위는 별도로 제한해야 한다.
추가 Tunnel 과금
추가 Tunnel의 가격은 다음과 같다.
Tunnel당 월 4.50달러
구매는 Cloudflare Dashboard의 Networking > Tunnels에서 진행할 수 있다.
Enterprise 고객은 별도의 계약 기반 또는 사용량 기반 가격을 협의할 수 있다.
여기서 과금 대상은 기본 제공 한도를 초과해 추가로 구매하는 Tunnel이다.
기본 라우트 한도가 50,000개로 늘어났다는 사실만으로 모든 라우트에 추가 요금이 부과되는 것은 아니다.
또한 라우트 수와 Tunnel 수를 같은 개념으로 계산해서는 안 된다.
하나의 Tunnel에 여러 라우트를 연결할 수 있기 때문이다.
이번 변경은 Cloudflare Tunnel의 통신 프로토콜이나 일반적인 요청 처리 방식을 변경한 것이 아니다.
대규모 조직과 플랫폼 운영자가 더 많은 네트워크 경로와 독립적인 Tunnel을 하나의 계정에서 관리할 수 있도록 확장한 인프라 운영 기능이다.
4️⃣ 개발 도구 및 보안
GitHub, 오픈소스 라이선스 정책 검사 정식 출시 — PR 병합 전에 의존성의 라이선스 준수 여부 강제
- 발표일: 2026-10-16 — 정확한 게시 시각 미확인
- 안정화 단계: Generally Available
- 적용 대상: GitHub Enterprise Cloud
- 사용 조건: GitHub Code Security가 활성화된 저장소
- 원문: https://github.blog/changelog/2026-10-16-open-source-license-compliance-generally-available/
GitHub가 오픈소스 의존성의 라이선스가 기업 정책을 준수하는지 검사하고, 정책을 위반한 변경 사항의 PR 병합을 제한하는 기능을 정식 출시했다.
이번 기능은 지난 6월 Public Preview로 공개됐으며, 이후 개선을 거쳐 정식 출시됐다.
웹 애플리케이션을 개발할 때는 수많은 오픈소스 라이브러리를 사용한다.
예를 들어 React, Vite, ESLint를 직접 설치할 수 있고, 이러한 라이브러리가 내부적으로 다른 패키지에 의존할 수도 있다.
이러한 간접적인 패키지를 전이적 의존성(Transitive Dependency)이라고 한다.
문제는 오픈소스 패키지가 모두 동일한 라이선스를 사용하는 것은 아니라는 점이다.
일부 라이선스는 상업적 이용과 수정, 배포에 관해 서로 다른 조건을 요구한다.
기업에서는 법무 또는 보안 정책에 따라 특정 라이선스의 사용을 제한하기도 한다.
하지만 개발자가 매번 모든 의존성의 라이선스를 직접 확인하는 것은 현실적으로 어렵다.
이번 기능은 의존성 변경과 라이선스 정책 검사를 PR 단계에서 연결한다.
Enterprise 단위 라이선스 정책
GitHub는 Enterprise 전체에 적용할 수 있는 라이선스 정책을 제공한다.
관리자는 조직에서 허용하거나 제한할 라이선스를 정의할 수 있다.
이후 Repository Ruleset을 통해 해당 정책을 실제 PR 검사에 연결한다.
새로운 Ruleset 조건의 이름은 다음과 같다.
Require license compliance results before merging
이 조건이 적용된 저장소에서는 PR이 새로운 의존성을 추가하거나 기존 의존성을 변경할 때 라이선스 검사가 수행된다.
예를 들어 개발자가 새로운 npm 패키지를 추가했다고 가정해 보자.
해당 패키지의 라이선스가 조직에서 허용하지 않는 유형이라면 GitHub는 PR에 정책 위반 내용을 표시한다.
개발자는 이러한 문제를 해결해야 병합할 수 있다.
단순히 라이선스 정보를 보여주는 기능에서 더 나아가 기업의 의존성 사용 정책을 코드 병합 과정에서 강제할 수 있도록 한 것이다.
정책 위반을 해결하는 방법
라이선스 정책을 위반한 의존성이 발견되면 여러 방법으로 해결할 수 있다.
첫 번째는 해당 패키지를 제거하는 것이다.
두 번째는 허용된 라이선스를 사용하는 다른 패키지로 교체하는 것이다.
세 번째는 기업의 라이선스 정책 자체를 변경하는 것이다.
네 번째는 특정 패키지에 대한 예외를 승인받는 것이다.
이 가운데 정책 변경이나 예외 승인에는 기업의 관리 절차가 필요할 수 있다.
예를 들어 특정 라이선스의 사용을 일반적으로 제한하더라도, 법무 검토를 거쳐 특정 패키지의 사용만 허용하는 상황을 생각할 수 있다.
GitHub는 이러한 과정을 관리할 수 있도록 새로운 Enterprise 역할을 제공한다.
Enterprise Open-Source License Manager
이 역할을 부여받은 사용자나 팀은 라이선스 관련 예외 요청을 검토하고 승인할 수 있다.
정책 관리자에게는 검토가 필요한 요청에 대한 이메일 알림도 제공된다.
따라서 모든 개발자에게 라이선스 정책을 변경할 수 있는 관리자 권한을 부여할 필요는 없다.
Dependency Review와의 차이
GitHub에는 기존에도 Dependency Review 기능이 존재했다.
Dependency Review는 PR에서 새롭게 추가되거나 변경되는 의존성을 검사한다.
이번 기능은 해당 구조를 확장해 Enterprise 전체에 적용되는 라이선스 정책과 Repository Ruleset을 연결한다.
따라서 개별 저장소가 자체적으로 라이선스를 검사하는 방식보다 정책을 중앙에서 일관되게 관리할 수 있다.
예를 들어 여러 팀이 각각 프론트엔드와 백엔드 프로젝트를 운영하더라도 동일한 라이선스 정책을 적용할 수 있다.
그러나 모든 오픈소스 프로젝트가 기업의 동일한 정책을 따라야 한다는 의미는 아니다.
기업 관리자는 프로젝트의 목적과 배포 방식, 법적 조건을 고려해 정책을 정의해야 한다.
특히 라이선스 사용 가능 여부는 단순히 패키지 이름만으로 판단할 수 없는 경우가 있다.
동일한 패키지도 버전에 따라 라이선스가 변경될 수 있기 때문이다.
SBOM과 라이선스 정보
이번 정식 출시에서는 Data Residency를 사용하는 GitHub Enterprise Cloud 고객에게도 라이선스 정보가 제공된다.
이를 통해 Dependency Graph와 SBOM 내보내기 결과에 라이선스 정보가 포함될 수 있다.
SBOM(Software Bill of Materials)은 소프트웨어가 어떤 구성요소와 의존성으로 이루어져 있는지 기록한 목록이다.
제조업에서 완성품을 구성하는 부품 목록을 관리하는 것과 비슷한 개념이다.
소프트웨어에서는 직접 설치한 패키지뿐 아니라 간접적으로 포함된 라이브러리까지 추적하는 데 활용할 수 있다.
SBOM에 라이선스 정보가 포함되면 기업은 다음과 같은 정보를 함께 관리할 수 있다.
- 어떤 오픈소스 패키지를 사용하는지
- 어떤 버전을 사용하는지
- 해당 패키지에 어떤 라이선스가 적용되는지
- 조직의 라이선스 정책에 적합한지
이 정보는 내부 감사와 규제 대응, 공급망 관리에 사용할 수 있다.
정책 변경 감사 로그
라이선스 정책 변경에 대한 감사 로그도 추가됐다.
기업 관리자가 허용 라이선스 목록을 변경하거나 예외를 추가하면 관련 변경 이력을 기록할 수 있다.
이는 라이선스 정책 위반 여부만큼 누가 어떤 이유로 정책을 변경했는지 추적하는 과정이 중요하기 때문이다.
예를 들어 특정 패키지가 한때 정책을 위반했지만 이후 승인된 예외에 따라 사용하게 됐다면 해당 결정의 이력이 필요할 수 있다.
감사 로그는 외부 관리 시스템과 연동할 수도 있다.
REST API와 AI 코딩 에이전트 연동
이번 정식 출시에서는 라이선스 정책을 관리하는 REST API도 확대됐다.
API를 이용해 다음 작업을 수행할 수 있다.
- Enterprise 라이선스 정책 조회
- 라이선스 정책 업데이트
- 정책 전체 교체
- 특정 패키지의 정책 준수 여부 검사
특히 마지막 기능은 AI 코딩 에이전트와 연결할 수 있다.
예를 들어 코딩 에이전트가 새로운 라이브러리를 도입하려고 한다면 실제 설치 전에 해당 패키지가 기업 정책에 적합한지 확인할 수 있다.
이렇게 하면 패키지를 설치하고 PR을 생성한 뒤에야 라이선스 정책 위반을 발견하는 상황을 줄일 수 있다.
다만 API를 통해 정책 준수 여부를 확인했다고 해서 해당 패키지가 보안상 안전하다는 뜻은 아니다.
라이선스 준수와 취약점 검사는 서로 다른 문제다.
라이선스가 허용된 패키지에도 알려진 보안 취약점이 존재할 수 있다.
반대로 보안 취약점이 없는 패키지라도 기업의 법적 정책에 따라 사용이 제한될 수 있다.
이번 기능은 GitHub Enterprise Cloud에서 사용할 수 있으며 Data Residency 환경도 포함된다.
GitHub Code Security가 활성화된 저장소가 대상이다.
모든 GitHub Free 또는 개인 저장소에서 동일한 정책 강제 기능이 제공되는 것은 아니다.
이번 발표는 오픈소스 의존성의 라이선스 검사를 개발자의 개별 확인 작업에서 기업의 자동화된 병합 정책으로 확장한 변화다.
Cloudflare, Verified Bot의 행동을 지속적으로 평가하는 신뢰도 시스템 도입 — robots.txt와 HTTP 429 준수 여부 분석
- 발표일: 2026-10-16 — 정확한 게시 시각 미확인
- 적용 대상: Cloudflare Verified Bots
- 현재 단계: 내부 평가 시스템 운영
- 원문: https://blog.cloudflare.com/verified-bots-accountability/
Cloudflare가 Verified Bot의 신원을 확인하는 것에서 나아가 실제 웹사이트 접근 행동을 지속적으로 평가하는 시스템을 공개했다.
웹사이트에는 일반 사용자뿐 아니라 다양한 자동화 프로그램이 접근한다.
검색 엔진 크롤러, 서비스 상태 확인 프로그램, 접근성 검사 도구, AI 데이터 수집 봇 등이 대표적이다.
이러한 자동화 프로그램이 모두 악의적인 것은 아니다.
검색 엔진이 웹페이지를 수집해야 사용자가 해당 페이지를 검색할 수 있고, 정상적인 모니터링 프로그램은 서비스 장애를 발견하는 데 도움이 된다.
하지만 봇의 운영 주체가 알려져 있다는 사실만으로 해당 봇이 웹사이트의 정책을 항상 준수한다고 보장할 수는 없다.
예를 들어 신원이 확인된 크롤러라도 다음과 같은 행동을 할 수 있다.
- 웹사이트가 수집을 금지한 경로에 접근
- 짧은 시간에 과도한 요청 전송
- 서버가 요청 속도를 줄이라고 응답했지만 계속 요청
- 설정 오류로 인해 의도하지 않은 대량 접근 발생
Cloudflare는 이러한 문제를 해결하기 위해 봇의 신원과 행동에 대한 신뢰를 구분하는 방식을 도입했다.
Verified Bot의 기존 기준
Cloudflare의 Verified Bot은 정상적인 자동화 프로그램을 식별하기 위한 체계다.
Cloudflare는 Verified Bot에 대해 크게 세 가지 조건을 제시한다.
- 자신이 누구인지 정확하고 안전하게 식별해야 한다.
- 선언한 목적과 일치하는 행동을 해야 한다.
- 다른 웹사이트에 피해를 주는 행동을 해서는 안 된다.
봇은 Web Bot Auth를 사용해 요청에 서명할 수 있다.
Web Bot Auth는 봇이 자신의 신원을 증명할 수 있도록 하는 방식이다.
BotBase는 이러한 봇의 정보를 공개적으로 관리하기 위한 체계다.
그러나 요청의 신원을 검증하는 것은 첫 번째 단계일 뿐이다.
운영자가 실제로 어떤 행동을 하는지는 별도의 관찰이 필요하다.
Cloudflare는 이를 설명하기 위해 Risk와 Trust를 구분한다.
Risk는 특정 요청이 위험할 가능성을 나타낸다.
반면 Trust는 일정 기간 동안 반복적으로 관찰한 행동을 바탕으로 형성되는 신뢰를 의미한다.
예를 들어 하나의 요청이 정상적이었다고 해서 이후에도 모든 요청이 정상적이라고 판단할 수는 없다.
반대로 한 번의 오류가 발생했다고 해서 해당 봇이 항상 악의적이라고 판단하는 것도 적절하지 않다.
따라서 Cloudflare는 지속적인 행동 패턴을 평가한다.
robots.txt 준수 여부 평가
첫 번째 주요 지표는 robots.txt 준수 여부다.
robots.txt는 웹사이트 운영자가 자동화된 크롤러에게 접근을 허용하거나 제한할 경로를 알리기 위해 사용하는 파일이다.
이 파일의 동작은 RFC 9309에 정의돼 있다.
예를 들어 특정 경로에 대한 수집을 금지할 수 있다.
Cloudflare는 크롤러가 실제로 전송한 요청을 웹사이트에 게시된 robots.txt 정책과 비교한다.
중요한 점은 한두 번의 위반만으로 봇의 전체 신뢰도를 결정하지 않는다는 것이다.
설정 오류나 일시적인 문제로 잘못된 요청이 발생할 수 있기 때문이다.
Cloudflare는 사이트의 정책을 반복적으로 무시하는 패턴에 주목한다.
이러한 행동이 지속되면 봇에 대한 신뢰 평가에 부정적인 영향을 줄 수 있다.
다만 robots.txt에 명시적으로 금지되지 않은 모든 요청이 무조건 허용된다는 의미는 아니다.
Cloudflare는 웹사이트가 다른 수단으로 접근을 제한하거나 요청을 중단하도록 요구할 수 있다는 점도 강조한다.
HTTP 429에 대한 반응 평가
두 번째 주요 지표는 HTTP 429 응답 이후의 행동이다.
HTTP 429 Too Many Requests는 서버가 일정 시간 동안 너무 많은 요청을 받았다는 사실을 알리는 상태 코드다.
일반적인 API에서는 Rate Limit을 초과했을 때 반환된다.
예를 들어 서버가 짧은 시간에 너무 많은 요청을 받으면 429를 반환하고 요청 속도를 낮추도록 요구할 수 있다.
일부 응답에는 Retry-After 헤더가 포함될 수도 있다.
이 헤더는 클라이언트가 언제 다시 요청할 수 있는지 안내하는 데 사용된다.
책임감 있게 설계된 크롤러라면 429 응답을 받은 뒤 요청 속도를 줄이거나 일시적으로 요청을 중단해야 한다.
반면 서버가 지속적으로 429를 반환하는데도 동일한 속도로 요청을 보내는 크롤러는 웹사이트에 부담을 줄 수 있다.
Cloudflare는 이러한 행동을 관찰한다.
429 응답 이후 실제 요청량을 줄이는지, 아니면 제한을 반복적으로 무시하는지를 확인하는 방식이다.
한 번의 반응보다 장기간 반복되는 행동 패턴이 중요하다.
Trust Band
Cloudflare는 관찰한 행동을 설명 가능한 Trust Band로 표현하는 구조를 개발했다.
Trust Band는 봇의 신뢰 수준을 범위로 나타내는 방식이다.
단순히 신뢰할 수 있는 봇과 신뢰할 수 없는 봇을 이분법적으로 구분하는 대신, 일정 기간 동안 어떤 행동을 했는지 반영한다.
평가에는 다음과 같은 정보가 사용된다.
- robots.txt 정책을 반복적으로 준수했는지
- 웹사이트의 접근 제한을 무시했는지
- HTTP 429 응답 이후 요청량을 줄였는지
- 문제가 있는 행동이 일시적인지 지속적인지
이러한 정보는 봇 운영자에게도 도움이 될 수 있다.
예를 들어 운영자는 크롤러의 설정 오류로 인해 웹사이트의 정책을 반복적으로 위반하고 있다는 사실을 확인할 수 있다.
Cloudflare는 향후 Trust Band를 Cloudflare Radar에 공개할 계획이라고 밝혔다.
또한 고객이 원하는 신뢰도 기준을 선택해 Verified Bot 트래픽을 처리할 수 있도록 할 계획이다.
현재 사용 가능한 기능과 향후 계획의 차이
이번 발표에서 가장 중요한 제한사항은 현재 신뢰도 평가 시스템을 Cloudflare가 내부적으로 사용하고 있다는 점이다.
Cloudflare는 이미 Verified Bot의 행동을 관찰하고 신뢰도를 평가하기 시작했다고 설명한다.
하지만 Trust Score의 공개와 고객별 신뢰도 기준 설정은 향후 제공할 계획이다.
따라서 현재 모든 Cloudflare 고객이 Dashboard에서 새로운 Trust Band를 조회하거나 해당 값으로 WAF 규칙을 생성할 수 있다고 해석해서는 안 된다.
고객은 기존의 Bot Management와 Bot Preference Sync 등을 계속 사용할 수 있다.
이번 발표는 새로운 봇 차단 규칙이 모든 웹사이트에 일괄적으로 적용됐다는 의미도 아니다.
확인된 봇이라는 사실만으로 자동화된 접근을 신뢰하는 대신, 실제 요청 행동과 웹사이트의 정책 준수 여부를 지속적으로 평가하려는 변화다.
AI 크롤러의 수가 증가하면서 웹사이트 운영자의 접근 정책과 자동화 프로그램의 행동을 어떻게 연결할지 보여주는 사례이기도 하다.
Cloudflare CLI 1.0.0-beta.16, 터미널에서 공식 문서 검색 지원 — 명령어 이름 변경으로 기존 스크립트 호환성 주의
- 발표일: 2026-10-16 — 정확한 게시 시각 미확인
- 버전: Cloudflare CLI 1.0.0-beta.16
- 안정화 단계: Beta
- 원문: https://developers.cloudflare.com/changelog/post/2026-10-16-docs-search/
Cloudflare가 CLI에서 공식 개발 문서를 직접 검색하는 cf docs search 명령을 추가했다.
CLI(Command-Line Interface)는 터미널에서 명령어를 입력해 소프트웨어와 상호작용하는 도구다.
개발자는 Cloudflare Workers, R2, D1, DNS, WAF 등 여러 서비스를 구성할 때 공식 문서를 참고해야 한다.
하지만 개발 중인 터미널에서 브라우저로 이동해 문서를 검색하고 다시 터미널로 돌아오는 과정이 반복될 수 있다.
특히 AI 코딩 에이전트를 사용하는 경우에는 또 다른 문제가 있다.
에이전트가 특정 서비스의 설정 방법을 알고 있다고 가정하고 코드를 생성하지만, 실제 API나 CLI 명령은 업데이트됐을 수 있기 때문이다.
이때 에이전트가 공식 문서에서 현재 지원하는 사용법을 검색할 수 있다면 오래된 지식에만 의존하는 문제를 줄일 수 있다.
이번 기능은 이러한 문서 검색을 CLI에 통합했다.
cf docs search
새로운 명령은 다음과 같다.
cf docs search "검색할 내용"
예를 들어 다음 질문을 검색할 수 있다.
- DNS Record를 프록시하는 방법
- WAF로 요청 속도를 제한하는 방법
- Worker를 예약 실행하는 방법
CLI는 현재 Cloudflare 공식 문서를 검색한다.
검색 결과는 최대 5개가 반환된다.
각 결과에는 다음 정보가 포함된다.
- 제목
- 설명
- 공식 문서 URL
결과 형식은 JSON이다.
따라서 사람이 읽는 용도로도 사용할 수 있지만, 다른 프로그램이 결과를 처리하는 데도 적합하다.
예를 들어 CLI의 첫 번째 검색 결과에서 URL을 가져와 해당 문서의 전체 내용을 다시 요청할 수 있다.
AI 코딩 에이전트와 문서 검색 연결
Cloudflare는 검색 결과를 Markdown 형태의 문서 조회와 결합하는 방법을 제시했다.
공식 문서 URL에 요청할 때 다음 HTTP 헤더를 사용할 수 있다.
Accept: text/markdown
이렇게 하면 문서를 Markdown 형식으로 가져올 수 있다.
AI 코딩 에이전트에서는 다음과 같은 작업 흐름을 구성할 수 있다.
- 사용자가 Cloudflare 설정에 관한 작업을 요청한다.
- 에이전트가
cf docs search로 공식 문서를 검색한다. - 검색 결과의 URL을 확인한다.
- 해당 문서를 Markdown으로 읽는다.
- 문서에서 확인한 API와 설정 방법을 바탕으로 코드를 작성한다.
이 구조는 문서 검색과 코드 생성을 분리한다.
모델이 기억하는 API가 최신인지 확실하지 않을 때 공식 문서를 다시 확인할 수 있도록 하는 것이다.
다만 공식 문서를 읽었다는 사실만으로 생성된 코드가 항상 올바르다는 의미는 아니다.
문서가 설명하는 기능의 지원 범위와 실제 프로젝트의 설정이 다를 수 있기 때문이다.
또한 문서 검색은 인터넷 연결이 필요하다.
오프라인 환경에서는 해당 명령을 사용할 수 없다.
생성된 CLI 명령 이름의 변경
이번 릴리스에는 호환성에 영향을 주는 변경도 포함됐다.
Cloudflare는 자동 생성되는 CLI 명령의 이름을 kebab-case로 표준화했다.
예를 들어 기존 명령에서 사용하던 다음 이름이 변경됐다.
getCredits
새로운 이름은 다음과 같다.
get-credits
이러한 변경은 사람이 CLI를 사용할 때 큰 차이로 느껴지지 않을 수 있다.
하지만 CI/CD 스크립트나 자동화 프로그램에서 기존 명령을 직접 호출하고 있다면 문제가 될 수 있다.
예를 들어 배포 스크립트에 이전 명령 이름이 포함돼 있다면 CLI를 업데이트한 이후 명령을 찾지 못하는 오류가 발생할 수 있다.
따라서 Cloudflare CLI Beta를 사용하는 프로젝트는 업데이트 전에 릴리스 노트의 Breaking Change를 확인해야 한다.
이번 기능은 기존 Workers Runtime이나 Cloudflare API 자체를 변경한 것이 아니다.
공식 문서를 터미널과 AI 코딩 에이전트에서 검색할 수 있도록 확장하면서 CLI 명령 체계를 정리한 개발 도구 업데이트다.
아직 Beta 단계이므로 향후 명령과 출력 형식이 변경될 가능성도 고려해야 한다.
📚 추천 글
Getting Started with TanStack AI: Setup and Basics — React 애플리케이션에서 AI 응답 스트리밍·대화 저장·복구까지 연결하기
- 저자: Adam Rackis / Master.dev
- 게시일: 2026-10-16
- 원문: https://blog.master.dev/unlocking-ai-in-your-apps-with-tanstack-ai/
React 기반 웹 애플리케이션에서 TanStack AI를 이용해 AI 채팅 기능을 구현하고, 스트리밍 응답과 대화 저장, 연결 중단 이후 복구까지 확장하는 과정을 설명한 글이다.
AI 기능을 웹서비스에 추가할 때 가장 단순한 구현은 서버에서 LLM API를 호출한 뒤 결과를 클라이언트에 전달하는 것이다.
하지만 실제 채팅 서비스에서는 여러 문제가 발생한다.
사용자가 응답 전체가 생성될 때까지 기다려야 할 수 있고, 페이지를 새로고침하면 기존 대화가 사라질 수 있다.
또한 응답이 생성되는 도중 네트워크 연결이 끊어지면 진행 중이던 작업의 결과를 잃어버릴 수 있다.
저자는 이러한 문제를 하나씩 해결하면서 TanStack AI가 제공하는 API의 역할을 설명한다.
특히 단순한 채팅 UI에서 시작해 지속적인 상태를 가진 AI 애플리케이션으로 확장하는 과정이 상세하다.
TanStack Start에서 AI 서버 구성
예제는 TanStack Start를 이용해 구성한다.
TanStack Start는 TanStack Router를 기반으로 하는 풀스택 React 프레임워크다.
서버 API와 클라이언트 UI를 하나의 프로젝트에서 구성할 수 있다.
저자는 서버에 AI 요청을 처리하는 Route를 생성한다.
이 Route는 사용자가 보낸 메시지를 받아 모델에 전달한 뒤 결과를 반환한다.
모델 연결에는 다음 패키지를 사용한다.
@tanstack/ai-vercel-gateway
이 Adapter를 이용해 Vercel AI Gateway를 통해 모델을 호출한다.
여기서 Adapter는 TanStack AI가 외부 모델 제공업체와 통신하는 방식을 연결하는 구성요소다.
애플리케이션은 Adapter를 변경하는 방식으로 모델 연결 구조를 조정할 수 있다.
다만 실제로 지원하는 모델과 기능은 Adapter 및 제공업체의 구현 범위에 따라 달라진다.
클라이언트의 useChat
React 클라이언트에서는 @tanstack/ai-react의 useChat을 사용한다.
useChat은 채팅 UI에 필요한 상태와 동작을 제공한다.
예를 들어 다음 정보를 관리할 수 있다.
- 현재 대화 메시지
- 새로운 메시지 전송
- 응답 생성 상태
- 스트리밍 응답 처리
처음에는 서버에 일반적인 요청을 보내고 응답 전체가 완성된 뒤 화면에 표시하는 방식으로 구현한다.
이 구조는 이해하기 쉽지만 사용자 경험에 한계가 있다.
모델이 긴 답변을 생성하는 동안 사용자는 아무런 내용을 볼 수 없기 때문이다.
따라서 저자는 다음 단계에서 스트리밍을 추가한다.
SSE 기반 스트리밍
SSE(Server-Sent Events)는 서버에서 클라이언트로 이벤트를 지속적으로 전달하는 방식이다.
WebSocket과 달리 기본적으로 서버에서 클라이언트 방향으로 데이터를 전달하는 데 초점을 맞춘다.
AI 채팅에서는 모델이 생성한 텍스트를 조금씩 전달하는 데 사용할 수 있다.
TanStack AI는 서버에서 다음 함수를 제공한다.
toServerSentEventsResponse()
이 함수는 AI 모델의 응답을 SSE 형태로 반환할 수 있도록 한다.
클라이언트에서는 다음 연결 도구를 사용한다.
fetchServerSentEvents()
useChat에 해당 연결을 지정하면 모델이 생성하는 응답을 실시간으로 화면에 표시할 수 있다.
즉 서버가 모든 답변을 생성할 때까지 기다리지 않고 사용자에게 부분적인 결과를 전달한다.
이 방식은 응답이 긴 AI 애플리케이션에서 사용자가 느끼는 대기 시간을 줄일 수 있다.
하지만 스트리밍을 사용한다고 해서 모델 자체의 전체 생성 시간이 반드시 감소하는 것은 아니다.
첫 번째 응답을 보여주는 시점과 전체 응답이 완료되는 시점은 서로 다른 성능 지표이기 때문이다.
대화 기록 저장
스트리밍만 구현하면 또 다른 문제가 발생한다.
사용자가 페이지를 새로고침했을 때 기존 메시지가 사라질 수 있다.
저자는 이를 해결하기 위해 다음 패키지를 사용한다.
@tanstack/ai-persistence
TanStack AI의 Persistence 기능은 특정 데이터베이스를 반드시 사용하도록 강제하지 않는다.
대신 대화 기록을 저장하고 읽기 위한 인터페이스를 제공한다.
개발자는 자신이 사용하는 데이터베이스에 맞춰 저장 로직을 구현할 수 있다.
예제에서는 Drizzle을 이용해 필요한 데이터베이스 구조를 구성한다.
서버에는 withPersistence() Middleware를 추가한다.
이를 통해 AI 대화 과정에서 생성되는 메시지와 실행 정보를 저장한다.
중요한 식별자는 다음 두 가지다.
threadId: 대화 단위 식별자runId: 특정 모델 실행 단위 식별자
하나의 대화에는 여러 번의 모델 실행이 포함될 수 있다.
따라서 대화 자체를 식별하는 정보와 개별 실행을 식별하는 정보를 구분한다.
저장된 대화 복원
데이터베이스에 대화 내용을 저장했다고 해서 새로고침 이후 UI가 자동으로 복구되는 것은 아니다.
클라이언트가 기존 대화를 다시 요청해야 한다.
저자는 이를 위해 GET Handler를 추가한다.
서버에서는 reconstructChat()을 이용해 저장된 메시지를 읽어 반환한다.
클라이언트는 threadId를 전달해 어떤 대화를 복원할지 지정한다.
이렇게 하면 사용자가 페이지를 새로고침하더라도 기존 대화가 다시 표시될 수 있다.
하지만 여기에는 중요한 보안 문제가 존재한다.
threadId만으로 대화에 접근할 수 있어서는 안 된다
원문의 예제에는 다음과 같은 인증 콜백이 등장한다.
authorize: async (threadId, req) => true
이 코드는 모든 요청을 허용한다.
학습용 예제에서는 간단하게 동작을 보여줄 수 있지만 실제 서비스에서는 위험하다.
공격자가 다른 사용자의 threadId를 알아내거나 추측할 수 있다면 해당 사용자의 대화 기록에 접근할 가능성이 있기 때문이다.
저자도 이 부분은 실제 인증 및 권한 검증 로직으로 교체해야 한다고 명시했다.
운영 환경에서는 최소한 다음 관계를 확인해야 한다.
- 요청한 사용자가 누구인지
- 해당 사용자가 요청한 대화에 접근할 권한이 있는지
- 대화가 현재 사용자나 조직에 속하는지
특히 대화 기록에는 사용자가 입력한 개인정보나 업무 정보가 포함될 수 있다.
따라서 대화 식별자를 복잡하게 만드는 것만으로 접근 권한 검증을 대체해서는 안 된다.
대화의 소유권을 서버에서 확인하는 과정이 필요하다.
응답 생성 중 새로고침했을 때 복구
대화 저장만으로 해결되지 않는 문제도 있다.
모델이 답변을 생성하는 중간에 페이지를 새로고침하면 기존 SSE 연결이 종료된다.
대화 기록이 데이터베이스에 저장돼 있더라도 진행 중이던 스트림을 이어서 수신하지 못할 수 있다.
저자는 이를 해결하기 위해 Resumability를 추가한다.
TanStack AI는 다음 기능을 제공한다.
memoryStream()resumeServerSentEventsResponse()
memoryStream()은 서버에서 생성 중인 응답을 메모리에 버퍼링한다.
클라이언트 연결이 종료되더라도 해당 실행 상태가 유지되고 있다면 이후 다시 연결할 수 있다.
클라이언트가 페이지를 새로고침하면 GET Handler에서 기존 스트림이 존재하는지 확인한다.
복구 가능한 스트림이 있다면 해당 스트림을 이어서 전달한다.
없다면 데이터베이스에 저장된 대화 기록을 반환한다.
이렇게 하면 일반적인 대화 복원과 진행 중인 스트림 복구를 구분할 수 있다.
메모리 기반 스트림의 제한사항
여기서 중요한 제한은 예제의 memoryStream()이 메모리 기반 구현이라는 사실이다.
같은 서버 프로세스가 계속 실행되고 있다면 스트림을 복구할 수 있다.
하지만 서버가 재시작되거나 요청이 다른 서버 인스턴스로 전달된다면 기존 메모리 상태를 찾지 못할 수 있다.
따라서 여러 서버 인스턴스를 사용하는 운영 환경에서는 별도의 영속적인 스트림 저장소가 필요할 수 있다.
저자는 Cloudflare Durable Objects처럼 일관된 실행 ID를 가진 환경을 활용하거나 별도의 Durable Stream Backend를 사용할 수 있다고 설명한다.
또한 스트림 복구에서도 인증 검증이 필요하다.
저자는 저장된 대화를 읽을 때 사용한 권한 검사를 스트림 복구 과정에도 적용해야 한다고 강조한다.
이번 글은 특정 AI 모델의 성능을 측정한 Benchmark는 아니다.
또한 예제의 구현을 그대로 운영 환경에 배포해도 안전하다고 주장하지 않는다.
대신 React 애플리케이션에서 AI 기능을 구현할 때 단순 API 호출 이후에 발생하는 상태 관리, 스트리밍, 영속성, 재연결, 접근 권한 문제를 어떻게 구분해 해결하는지를 보여준다.
특히 TanStack AI의 각 기능이 어떤 책임을 담당하는지 이해하기 좋은 기술 자료다.
Building a Fancy Scrollspy Using Modern CSS — JavaScript 없이 현재 읽는 문서 위치를 표시하는 목차 구현
- 저자: Mojtaba Seyedi / Master.dev
- 게시일: 2026-10-14
- 원문: https://blog.master.dev/building-a-fancy-scrollspy-using-modern-css/
CSS의 최신 기능을 조합해 JavaScript 없이 Scrollspy를 구현하는 방법을 설명한 글이다.
Scrollspy는 사용자가 긴 문서를 스크롤할 때 현재 읽고 있는 섹션을 목차에서 강조하는 기능이다.
개발 문서나 기술 블로그에서 자주 볼 수 있다.
예를 들어 문서에 다음과 같은 목차가 있다고 가정해 보자.
- 시작하기
- 설치 방법
- 기본 설정
- 고급 기능
- 문제 해결
사용자가 설치 방법 섹션을 읽고 있다면 목차의 설치 방법 항목에 다른 색상이나 표시선을 적용할 수 있다.
기존에는 이러한 기능을 구현하기 위해 JavaScript에서 스크롤 위치를 계산하거나 IntersectionObserver를 사용하는 방식이 일반적이었다.
하지만 이번 글은 스크롤 위치와 목차의 관계를 브라우저가 직접 이해하도록 하는 CSS 기능을 활용한다.
scroll-target-group
첫 번째 핵심 기능은 scroll-target-group이다.
이 속성은 문서 내 특정 위치를 가리키는 Anchor Link들을 하나의 그룹으로 묶는다.
예를 들어 HTML에는 다음과 같은 링크가 존재할 수 있다.
<a href="#installation">설치 방법</a>
이 링크는 id="installation"을 가진 요소로 이동한다.
이러한 Anchor Link는 원래부터 JavaScript 없이 동작한다.
하지만 기존 CSS만으로는 사용자가 현재 어떤 섹션을 보고 있는지 판단하기 어려웠다.
scroll-target-group: auto를 목차의 부모 요소에 적용하면 브라우저가 각 링크와 해당 섹션 사이의 관계를 인식할 수 있다.
이후 스크롤 위치에 따라 현재 활성화된 링크를 구분할 수 있다.
여기서 주의해야 할 점은 scroll-target-group과 scroll-marker-group이 서로 다른 기능이라는 것이다.
scroll-target-group은 개발자가 작성한 Anchor Link를 Scroll Marker로 사용한다.
반면 scroll-marker-group은 브라우저가 Scroll Marker를 생성하는 기능과 관련된다.
따라서 두 속성은 이름이 비슷하지만 동일한 역할을 수행하지 않는다.
:target-current
두 번째 핵심 기능은 :target-current 선택자다.
브라우저는 스크롤 위치에 따라 현재 활성화된 Scroll Marker를 판단한다.
개발자는 해당 링크에 다음과 같은 스타일을 적용할 수 있다.
.toc a:target-current
이 선택자를 이용하면 현재 읽고 있는 섹션에 대응하는 목차 항목의 색상이나 크기를 변경할 수 있다.
중요한 점은 스크롤 이벤트를 직접 감지할 필요가 없다는 것이다.
기존 JavaScript 구현에서는 개발자가 직접 다음 과정을 처리해야 할 수 있었다.
- 현재 화면에 표시된 섹션을 찾는다.
- 해당 섹션의 ID를 확인한다.
- 목차에서 대응하는 링크를 찾는다.
- 이전 활성 링크의 스타일을 제거한다.
- 새로운 활성 링크에 스타일을 적용한다.
이번 CSS 방식에서는 이러한 상태 관리를 브라우저에 맡길 수 있다.
개발자는 활성 상태의 스타일만 정의한다.
:target-before와 :target-after
현재 항목뿐 아니라 앞뒤 항목도 구분할 수 있다.
:target-before: 현재 활성 항목보다 앞에 있는 링크:target-current: 현재 활성 항목:target-after: 현재 활성 항목보다 뒤에 있는 링크
이 기능을 이용하면 현재 읽은 위치를 시각적으로 표현할 수 있다.
예를 들어 이미 지나온 섹션에는 진한 색상의 원을 표시하고, 앞으로 읽을 섹션에는 작은 회색 원을 표시할 수 있다.
현재 섹션에는 강조 효과를 적용할 수 있다.
이러한 UI는 단순히 현재 항목만 다른 색으로 표시하는 방식보다 문서 전체에서 사용자의 위치를 직관적으로 보여줄 수 있다.
CSS Anchor Positioning과 연결선
저자는 여기에서 한 단계 더 나아간다.
각 목차 항목 앞에 원형 Marker를 표시하고, 첫 번째 항목에서 현재 활성 항목까지 이어지는 선을 구현한다.
문제는 연결선의 길이다.
일반적인 구현에서는 현재 항목의 위치를 알아야 선의 길이를 계산할 수 있다.
목차 항목의 높이가 모두 같다면 항목 번호에 일정한 값을 곱하는 방식으로 계산할 수도 있다.
하지만 실제 문서에서는 링크의 길이가 서로 다르다.
긴 목차 항목이 두 줄로 표시되면 해당 항목의 높이가 커진다.
따라서 항목 번호만으로 정확한 위치를 계산하기 어렵다.
저자는 이를 해결하기 위해 CSS Anchor Positioning을 사용한다.
현재 활성화된 링크에 다음 속성을 지정한다.
anchor-name: --current-marker
이렇게 하면 현재 활성화된 링크가 Anchor로 지정된다.
목차의 연결선은 다음 속성으로 해당 Anchor를 참조한다.
position-anchor: --current-marker
이후 다음 설정으로 연결선의 끝 위치를 지정한다.
bottom: anchor(center)
브라우저는 현재 활성화된 링크의 위치를 계산해 연결선의 끝을 해당 위치에 배치한다.
따라서 각 목차 항목의 실제 높이가 달라도 연결선이 현재 활성 항목에 맞춰 이동할 수 있다.
현재 항목이 변경될 때 애니메이션
연결선의 끝 위치는 활성 항목에 따라 변경된다.
저자는 bottom 속성에 Transition을 적용해 연결선이 부드럽게 움직이도록 했다.
이렇게 하면 사용자가 문서를 스크롤할 때 현재 위치를 표시하는 선이 따라 움직이는 효과를 만들 수 있다.
하지만 여기에는 성능상의 트레이드오프가 있다.
bottom은 레이아웃에 영향을 주는 속성이다.
따라서 해당 값을 애니메이션으로 변경하면 브라우저가 레이아웃 계산을 다시 수행해야 할 수 있다.
반면 transform이나 opacity는 상황에 따라 Compositor에서 처리할 수 있어 상대적으로 효율적인 애니메이션을 구현할 수 있다.
즉 JavaScript를 제거했다고 해서 애니메이션의 렌더링 비용까지 자동으로 최소화되는 것은 아니다.
저자는 이 점을 명시적으로 설명한다.
이번 구현의 목표는 모든 환경에서 가장 낮은 렌더링 비용을 달성하는 것이 아니라 현재 활성 항목과 연결선의 관계를 CSS로 표현하는 것이다.
브라우저 지원 범위
이번 구현에는 중요한 제한사항이 있다.
scroll-target-group과 관련 선택자는 현재 Chromium 기반 브라우저에서 지원되지만, Firefox와 Safari에서는 지원되지 않는다.
따라서 모든 브라우저에서 동일한 Scrollspy 효과를 볼 수 있는 것은 아니다.
그러나 기본 HTML 구조는 일반적인 Anchor Link 목록이다.
지원하지 않는 브라우저에서도 목차를 클릭하면 해당 섹션으로 이동하는 기본 기능은 유지된다.
이러한 설계는 Progressive Enhancement의 사례다.
Progressive Enhancement는 기본적인 기능을 먼저 구현한 뒤 브라우저가 지원하는 고급 기능을 추가하는 접근이다.
이번 구현에서는 기본 목차 탐색이 먼저 존재한다.
최신 CSS를 지원하는 브라우저에서만 활성 항목 강조와 연결선 애니메이션이 추가된다.
따라서 지원하지 않는 브라우저에서도 핵심적인 탐색 기능이 사라지지 않는다.
이 글은 브라우저가 제공하는 새로운 상태 표현 기능을 이용해 기존 JavaScript 상태 관리 코드를 줄이는 방법을 보여준다.
특히 CSS Anchor Positioning과 Scroll Marker 기능이 서로 독립적인 기능이 아니라 함께 사용될 수 있다는 점을 구체적으로 설명한다.
How Meta Built Forum With AI-Native Engineering — 코딩 에이전트 중심으로 개발·검증·운영 프로세스를 재설계한 사례
- 저자: Shengbo Guo 외 / Meta Engineering
- 게시일: 2026-10-15
- 원문: https://engineering.fb.com/2026/10/15/ml-applications/how-meta-built-forum-ai-native-engineering/
Meta가 새로운 애플리케이션인 Forum을 개발하면서 AI 코딩 에이전트를 단순한 코드 생성 도구가 아니라 개발 프로세스의 일부로 활용한 방법을 설명한 글이다.
Forum은 Facebook Groups와 관련된 대화를 보다 깊이 있게 탐색할 수 있도록 만든 독립 애플리케이션이다.
Meta는 이 프로젝트를 비교적 작은 팀으로 개발하면서 기존과 다른 개발 방식을 실험했다.
핵심 질문은 AI가 코드를 얼마나 빠르게 작성할 수 있는지가 아니었다.
AI가 작성한 결과를 실제 운영 가능한 수준으로 검증하는 과정까지 얼마나 자동화할 수 있는가였다.
저자들은 단순한 코드 생성량을 생산성 지표로 사용하지 않았다.
대신 빌드가 성공하고, 테스트를 통과하고, 실제 UI에서 의도한 동작을 수행하며, 엔지니어의 최종 검토를 통과한 결과물을 기준으로 삼았다.
Human-in-the-loop에서 Human-on-the-loop로
Meta는 두 가지 개발 방식을 구분한다.
첫 번째는 Human-in-the-loop다.
이 방식에서는 개발자가 작업의 각 단계를 직접 수행한다.
AI는 코드 자동완성이나 함수 생성, 오류 해결 등의 특정 단계에서 도움을 제공한다.
예를 들어 개발자가 코드를 작성하다가 AI에게 특정 함수를 만들어 달라고 요청하고, 이후 개발자가 다시 테스트를 실행하는 구조다.
두 번째는 Human-on-the-loop다.
이 방식에서는 에이전트가 하나의 작업을 여러 단계에 걸쳐 수행한다.
예를 들어 다음과 같은 과정이다.
- 작업 요구사항 분석
- 구현 계획 작성
- 코드 수정
- 빌드 실행
- 테스트 실행
- 오류 수정
- 결과 재검증
- 엔지니어에게 검토 요청
개발자는 모든 단계의 실행을 직접 담당하지 않는다.
대신 작업의 목표를 정의하고 결과를 검토하며 필요한 경우 개입한다.
하지만 Meta는 현재 모든 개발 작업을 완전히 자율적으로 처리하는 단계에 도달했다고 주장하지 않는다.
일부 과정은 여전히 엔지니어가 직접 참여해야 한다.
따라서 Human-on-the-loop는 완성된 상태라기보다 지향하는 운영 모델이라고 설명한다.
코드 생성보다 검증이 중요하다
저자들은 AI를 이용한 개발에서 가장 큰 문제가 코드 생성 속도 자체가 아니라고 설명한다.
AI는 그럴듯한 코드를 빠르게 생성할 수 있다.
하지만 해당 코드가 실제 요구사항을 충족하는지는 별개의 문제다.
예를 들어 React 컴포넌트가 정상적으로 빌드되더라도 실제 UI에서 잘못된 화면을 수정했을 수 있다.
또는 테스트를 통과했더라도 특정 사용자 행동에서 문제가 발생할 수 있다.
따라서 Meta는 작업 완료 기준을 단순한 컴파일 성공보다 높게 설정했다.
에이전트는 코드를 작성한 뒤 직접 테스트를 실행한다.
또한 실제 화면이 요구사항과 일치하는지 확인한다.
이러한 검증 결과가 준비된 이후에 엔지니어가 PR을 검토한다.
즉 검증되지 않은 코드를 대량으로 생성하는 것보다 검증된 결과만 개발자에게 전달하는 구조를 선택했다.
Rules·Skills·Agents·Commands·Hooks
Meta는 에이전트 중심 개발 환경을 다섯 가지 구성요소로 정리했다.
| 구성요소 | 역할 |
|---|---|
| Rules | 프로젝트에서 항상 지켜야 하는 개발 규칙 |
| Skills | 특정 작업을 수행하기 위한 재사용 가능한 절차 |
| Agents | 특정 검증이나 작업을 자동으로 수행하는 실행 단위 |
| Commands | 여러 Skills와 Agents를 연결하는 작업 흐름 |
| Hooks | 특정 시점에 자동으로 실행되는 검사나 작업 |
예를 들어 에이전트가 같은 실수를 반복한다면 매번 새로운 프롬프트로 지적하는 대신 프로젝트의 Rules에 해당 내용을 추가한다.
이렇게 하면 이후 다른 작업에서도 같은 규칙을 재사용할 수 있다.
또한 PR을 생성하기 전에 테스트와 린트를 실행하도록 Hook을 구성할 수 있다.
이러한 구조는 에이전트의 행동을 개별 대화에만 의존하지 않도록 한다.
프로젝트 자체에 필요한 규칙과 검증 절차를 저장하는 방식이다.
에이전트가 화면을 추측하지 않도록 만들기
Meta가 경험한 문제 가운데 하나는 에이전트가 실제 애플리케이션의 상태를 정확하게 알지 못한다는 것이었다.
예를 들어 사용자가 특정 그룹의 상세 화면을 수정해 달라고 요청했는데 에이전트가 홈 화면을 수정할 수 있었다.
또는 에이전트가 실제 버튼의 위치를 확인하지 않고 화면 좌표를 추측해 잘못된 요소를 클릭할 수도 있었다.
Meta는 이를 해결하기 위해 에이전트에게 실제 화면 구조를 조회할 수 있는 도구를 제공했다.
에이전트는 작업 전에 다음 정보를 직접 확인할 수 있다.
- 현재 화면의 View Hierarchy
- 실제로 표시된 UI 요소
- 대상 요소까지의 탐색 경로
- Simulator의 현재 상태
View Hierarchy는 화면을 구성하는 UI 요소의 계층 구조다.
이 정보를 조회하면 에이전트는 화면에 어떤 컴포넌트가 존재하는지 확인할 수 있다.
이는 화면을 단순한 이미지로 해석하거나 좌표를 추측하는 방식보다 구조적인 정보를 제공한다.
Meta는 이러한 도구를 추가한 뒤 잘못된 화면을 수정하는 문제가 크게 감소했다고 설명한다.
정량적인 감소율은 공개하지 않았다.
실험용 코드와 운영 코드를 빌드 단계에서 분리
또 다른 중요한 설계 선택은 실험용 코드의 격리 방식이다.
AI 코딩 에이전트를 사용하면 새로운 기능을 빠르게 실험할 수 있다.
하지만 여러 실험 코드가 운영 애플리케이션에 포함되면 예상하지 못한 문제가 발생할 수 있다.
일반적인 해결 방법은 Feature Flag다.
Feature Flag를 이용하면 기능을 활성화하거나 비활성화할 수 있다.
그러나 기능이 비활성화돼 있더라도 해당 코드가 실제 빌드 결과물에 포함될 수 있다.
따라서 Meta는 별도의 Sandbox Build Flavor를 만들었다.
Sandbox와 Production은 같은 코드베이스와 디자인 시스템을 공유한다.
하지만 플러그인 기반 구조를 이용해 실험용 코드가 Production 빌드에 포함되지 않도록 구성했다.
이 방식에서는 실험 기능이 단순히 비활성화되는 것이 아니라 운영 빌드 결과물에서 제외된다.
따라서 실험용 코드가 운영 환경에서 실행될 가능성을 줄일 수 있다.
또한 디자이너와 다른 직군의 구성원이 Sandbox에서 기능을 실험할 수 있도록 했다.
그러나 실제 운영 서비스에 반영할 기능은 여전히 엔지니어의 검토를 거친다.
AI를 이용한 스트레스 테스트
Meta는 AI 에이전트를 테스트 도구로도 활용했다.
에이전트는 실제 사용자의 행동을 모방하는 반복적인 테스트를 수행했다.
예를 들어 다음과 같은 작업이다.
- 빠르게 스크롤하기
- 여러 그룹을 무작위로 탐색하기
- 화면 사이를 반복적으로 이동하기
- 미디어를 반복해서 로딩하기
이러한 작업을 수행하면서 다음 지표를 관찰했다.
- 애플리케이션 충돌
- 메모리 사용량 증가
- Page Fault
- UI 회귀 문제
이 과정에서 실제 메모리 관련 문제가 발견됐다.
에이전트는 해당 문제가 발생하는 조건을 재현하고 수정안을 제안한 뒤 같은 테스트 환경에서 다시 검증했다.
Meta는 해당 수정 이후 메모리 사용량과 Page Fault가 대략 절반으로 감소했다고 설명한다.
이는 Meta가 특정 운영 환경과 테스트 시나리오에서 측정한 결과다.
모든 AI 기반 테스트가 동일한 성능 개선을 만들어낸다는 의미는 아니다.
또한 AI가 모든 문제를 독립적으로 발견하고 수정했다는 뜻도 아니다.
실제 아키텍처의 중요한 결정과 최종 검토에는 엔지니어가 참여했다.
8주 만에 핵심 기능 구현
Meta는 Forum이 8주 만에 Facebook Groups의 핵심 기능과 기능적 동등성에 도달했다고 밝혔다.
AI 에이전트가 반복적인 구현과 검증 작업을 처리하면서 엔지니어는 아키텍처와 제품 설계, 품질 관리에 집중할 수 있었다고 설명한다.
하지만 이 수치를 AI 도입만으로 개발 속도가 특정 배수만큼 증가했다는 증거로 해석할 수는 없다.
동일한 프로젝트를 AI 없이 개발한 통제 실험이 함께 공개된 것은 아니기 때문이다.
팀 구성, 기존 인프라 재사용, 프로젝트 범위, 내부 도구의 성숙도도 영향을 미쳤을 수 있다.
저자들이 강조하는 부분은 단순한 개발 속도보다 작업의 검증 과정을 자동화해 엔지니어가 결과를 판단하는 데 집중하도록 만들었다는 점이다.
또한 실제로 사용자의 피드백이 들어온 이후에도 에이전트가 오류를 조사하고 관련 코드와 로그를 분석하는 데 활용되고 있다.
이 글은 AI 코딩 도구를 도입할 때 모델 성능뿐 아니라 코드베이스의 구조, 작업 환경, 검증 도구, 배포 격리, 운영 피드백을 함께 설계해야 한다는 점을 실제 프로젝트로 설명한다.
From 2,500 requests to 24: Rebuilding star history without the stargazers — GitHub가 API 요청량을 약 100분의 1로 줄인 방법
- 저자: Taylor Cuilty, Sarita Iyer / GitHub Engineering
- 게시일: 2026-10-14
- 원문: https://github.blog/engineering/architecture-optimization/from-2500-requests-to-24-rebuilding-star-history-without-the-stargazers/
GitHub가 Repository의 Star 증가 추이를 제공하는 API를 다시 설계하면서 개인정보 노출과 데이터베이스 부하 문제를 함께 해결한 과정을 설명한 글이다.
GitHub의 Star는 사용자가 관심 있는 저장소를 표시하는 기능이다.
오픈소스 프로젝트 운영자는 Star 증가 추이를 이용해 프로젝트의 관심도가 언제 증가했는지 파악할 수 있다.
예를 들어 새로운 버전을 출시한 뒤 Star가 증가했는지, 특정 기술 발표 이후 사용자의 관심이 커졌는지 확인할 수 있다.
Star History와 같은 서비스는 이러한 데이터를 시각화한다.
하지만 GitHub의 기존 API는 이러한 용도를 위해 설계된 것이 아니었다.
기존 API는 누가 저장소에 Star를 눌렀는지를 반환하는 데 초점을 맞췄다.
반면 Star History가 실제로 필요한 정보는 언제 Star 수가 증가했는지였다.
이러한 요구사항의 차이가 보안과 성능 문제의 출발점이었다.
기존 API는 사용자 목록을 반환했다
기존 Star 조회 API는 다음과 같다.
GET /repos/{owner}/{repo}/stargazers
이 API는 저장소에 Star를 누른 사용자의 목록을 반환한다.
요청에 특정 미디어 타입을 사용하면 각 사용자가 Star를 누른 시각도 확인할 수 있었다.
Star 증가 추이를 만들려면 다음 과정을 수행해야 했다.
- Star를 누른 사용자 목록을 가져온다.
- 각 사용자가 Star를 누른 시각을 수집한다.
- 날짜별로 Star 개수를 집계한다.
- 사용자 이름은 버리고 집계 결과만 사용한다.
문제는 API가 한 페이지에 최대 100명의 사용자만 반환한다는 점이다.
Star가 많은 저장소에서는 수많은 페이지를 요청해야 했다.
예를 들어 약 251,000개의 Star를 가진 react/react 저장소에서는 전체 데이터를 가져오기 위해 약 2,511번의 API 요청이 필요했다.
이는 외부 도구의 Rate Limit 문제를 유발할 수 있었다.
또한 GitHub 서버에서도 같은 저장소의 데이터를 반복해서 조회해야 했다.
개인정보 노출 문제
기존 API에는 성능 문제뿐 아니라 개인정보 보호 문제도 있었다.
Star 증가 추이를 확인하는 도구는 날짜와 개수만 필요했다.
하지만 API는 개별 사용자 정보를 함께 제공했다.
이 정보는 악의적인 사용자에게 수집될 수 있었다.
GitHub에 따르면 일부 공격자는 공개된 Stargazer 목록을 대량으로 수집해 스팸이나 피싱 캠페인에 활용했다.
GitHub는 이를 완화하기 위해 Stargazer 및 Watcher 목록의 접근 범위를 제한했다.
하지만 이러한 제한은 기존 Star History 도구에도 영향을 미쳤다.
이전에는 접근할 수 있었던 데이터가 더 이상 반환되지 않거나 HTTP 403 응답을 받을 수 있었기 때문이다.
따라서 GitHub는 개인정보를 보호하면서도 프로젝트 운영자가 필요한 추이 정보는 계속 제공할 수 있는 새로운 API를 설계해야 했다.
기존 페이지네이션의 데이터베이스 병목
GitHub가 발견한 중요한 문제는 단순한 API 요청량만이 아니었다.
기존 Stargazer API에서는 페이지네이션을 처리할 때 전체 Star 개수를 다시 계산하는 비효율적인 쿼리가 실행될 수 있었다.
예를 들어 사용자가 두 번째 페이지의 사용자 100명만 요청했다고 가정해 보자.
실제로 필요한 것은 해당 페이지에 포함된 100명의 데이터다.
그러나 기존 구현에서는 전체 페이지 수를 계산하기 위해 Repository의 모든 Star를 세는 작업이 반복될 수 있었다.
GitHub는 접근 제한을 적용하기 직전 일주일 동안 약 37,000개의 느린 Count Query가 실행됐다고 밝혔다.
이러한 쿼리의 평균 실행 시간은 약 3초였다.
또한 데이터베이스 보호 장치가 1,000개 이상의 쿼리를 강제로 중단했다.
이로 인해 일부 API 요청에서 타임아웃이 발생했다.
GitHub는 Stargazer 접근을 제한한 이후 관련 API 요청량이 약 60% 감소했고, Count Query에 소비되는 전체 시간이 약 80% 줄었다고 설명한다.
이는 GitHub의 자체 운영 데이터다.
사용자 정보를 제거하는 것만으로는 해결되지 않았다
GitHub는 처음에 사용자 이름을 제거하고 Star가 생성된 시각만 반환하는 방식을 검토했다.
이 방식은 개인정보 노출 문제를 완화할 수 있다.
하지만 성능 문제는 그대로 남는다.
Star가 251,000개라면 날짜만 반환하더라도 여전히 251,000개의 레코드를 조회해야 하기 때문이다.
즉 응답에서 개인정보를 제거하는 것만으로 데이터베이스가 수행해야 하는 작업량이 줄어드는 것은 아니다.
다음으로 검토한 방법은 날짜별로 Star를 집계한 뒤 페이지네이션을 적용하는 방식이었다.
이 방식에서는 사용자별 레코드 대신 날짜별 개수를 반환한다.
응답 크기는 작아진다.
그러나 쿼리 실행 순서에 문제가 있었다.
데이터베이스가 먼저 전체 Star를 읽고 날짜별로 그룹화한 뒤 정렬하고, 마지막에 LIMIT과 OFFSET을 적용할 수 있었기 때문이다.
이 경우 사용자가 한 페이지의 집계 결과만 요청하더라도 데이터베이스는 전체 Star를 다시 처리해야 한다.
GitHub의 계산에 따르면 react/react 저장소의 전체 기간을 이러한 방식으로 조회하면 약 600만 개의 행을 반복적으로 처리해야 할 수 있었다.
이는 각 페이지 요청이 약 251,000개의 Star를 다시 집계하기 때문이다.
응답에 포함되는 데이터가 적다는 사실과 실제 쿼리가 처리하는 데이터가 적다는 사실은 다르다.
먼저 날짜 범위를 제한하고 집계
GitHub가 최종적으로 선택한 방법은 처리 순서를 변경하는 것이었다.
기존 방식은 다음과 같았다.
전체 Star 조회 → 날짜별 집계 → 정렬 → 페이지네이션
새로운 방식은 다음과 같다.
날짜 범위 계산 → 인덱스 기반 조회 → 해당 범위의 Star 집계 → 응답
즉 집계하기 전에 먼저 날짜 범위를 제한한다.
새로운 API는 페이지네이션을 날짜 범위에 대응시킨다.
각 요청은 최대 30주 분량의 Star 증가 추이를 반환할 수 있다.
사용자가 다음 페이지를 요청하면 더 이전 주차의 날짜 범위를 조회한다.
데이터베이스는 해당 기간에 생성된 Star만 읽으면 된다.
이때 created_at 필드의 인덱스를 이용해 필요한 범위를 효율적으로 조회할 수 있다.
따라서 매 요청마다 저장소의 모든 Star를 읽을 필요가 없다.
2,511번에서 24번으로 감소
새로운 API를 이용하면 react/react 저장소의 Star 증가 추이를 약 24번의 요청으로 조회할 수 있다.
기존에는 약 2,511번의 요청이 필요했다.
비교하면 다음과 같다.
| 항목 | 기존 API | 새로운 API |
|---|---|---|
| 전체 Star History 조회 요청 수 | 약 2,511회 | 약 24회 |
| 반환 데이터 | 사용자별 Star 정보 | 날짜별 Star 개수 |
| 개인정보 | 사용자 식별 정보 포함 | 사용자 식별 정보 제외 |
| 쿼리 범위 | 전체 Star의 반복 조회 | 날짜 범위별 제한 조회 |
요청 수만 비교하면 약 100분의 1 수준으로 감소한 것이다.
하지만 중요한 성능 개선은 네트워크 요청 수에만 있는 것이 아니다.
새로운 구조에서는 전체 기간을 조회하는 동안 데이터베이스가 약 251,000개의 Star를 한 번씩 처리하는 수준으로 작업량을 줄일 수 있다.
기존의 단순 집계 방식에서는 같은 Star를 여러 페이지에서 반복해서 처리할 수 있었다.
따라서 API 응답 크기와 데이터베이스 작업량을 함께 줄이는 효과를 얻었다.
새로운 API의 제한사항
새로운 API에도 한계는 존재한다.
첫 번째는 과거 Star 이벤트를 완벽하게 복원하지 못한다는 점이다.
GitHub의 Star 데이터 모델은 현재 누가 Star를 누르고 있는지를 저장한다.
사용자가 Star를 취소하면 해당 레코드는 제거된다.
따라서 새로운 API가 반환하는 날짜별 개수는 현재 남아 있는 Star의 생성 시각을 기준으로 한다.
과거에 Star를 눌렀다가 취소한 사용자의 기록까지 포함한 완전한 이벤트 로그는 아니다.
두 번째는 날짜 범위에 따라 쿼리 비용이 달라질 수 있다는 점이다.
한 주에 매우 많은 Star가 생성됐다면 해당 날짜 범위의 데이터도 많아진다.
새로운 방식은 전체 Repository의 Star를 반복 조회하지 않도록 하지만, 특정 기간에 데이터가 집중된 경우에도 항상 일정한 쿼리 비용이 발생한다고 보장하지는 않는다.
세 번째는 날짜 경계와 집계 단위의 제한이다.
주 단위로 데이터를 조회하는 구조이므로 임의의 시간 범위에 대해 모든 형태의 집계를 직접 제공하는 것은 아니다.
데이터 모델과 API 요구사항의 관계
이 글은 단순히 SQL 쿼리를 최적화한 사례가 아니다.
처음에는 개인정보 노출을 줄이는 것이 중요한 문제였다.
하지만 실제 사용자가 필요로 하는 데이터가 무엇인지 다시 확인하면서 API 자체를 새롭게 설계했다.
개발자는 개별 사용자의 목록이 아니라 Star 증가 추이만 필요했다.
따라서 새로운 API에서는 불필요한 개인정보를 제거할 수 있었다.
동시에 응답 구조를 날짜별 집계로 변경하면서 데이터베이스가 처리하는 작업량도 줄일 수 있었다.
이는 API가 반환하는 데이터의 범위를 실제 요구사항에 맞게 좁히는 것이 보안과 성능을 동시에 개선할 수 있다는 사례다.
특히 페이지네이션과 집계 쿼리를 설계할 때 결과 개수뿐 아니라 데이터베이스가 실제로 처리하는 행의 수를 함께 확인해야 한다는 점을 구체적으로 보여준다.