Anthropic이 2주 동안 claude.ai 웹과 Claude 데스크톱 앱의 주요 사용 흐름을 약 3배 빠르게 만들었습니다. 2026년 9월 23일에 공개한 엔지니어링 글에 따르면, 엔지니어들은 Slack 채널에서 Claude에게 성능 개선을 맡기고 3,000건이 넘는 변경을 병합하는 동안 고객이 겪은 장애나 되돌리기(rollback)가 한 건도 없었다고 밝혔습니다. 눈여겨볼 점은 모델의 능력보다 일하는 방식입니다. 무엇을 잴지 먼저 정하고, 그 숫자를 agent(스스로 판단하며 여러 단계 작업을 이어 가는 AI)가 끝까지 낮추게 한 구조가 성과를 만들었습니다.
숫자로 본 2주의 결과
Anthropic은 실제 사용자의 75번째 백분위수(p75) 값으로 개선 폭을 쟀습니다. 측정 대상은 앱 실행, 대화 시작, 기존 대화 불러오기, 메시지 보내기의 네 가지 흐름이며, 이 흐름이 전체 사용 활동의 95%를 차지합니다.
| 사용 흐름 | 이전 | 이후 | 개선 폭 |
|---|---|---|---|
| claude.ai 웹, 입력 가능한 화면까지 | 3.1초 | 0.55초 | 5.6배 |
| Claude 데스크톱 앱 처음 실행 | 6,310ms | 3,328ms | 1.9배 |
| claude.ai 웹, 새 대화 시작 | 416ms | 273ms | 1.5배 |
| Claude 데스크톱, 새 대화 시작 | 945ms | 451ms | 2.1배 |
| claude.ai 웹, 대화 불러오기 | 1,557ms | 646ms | 2.4배 |
| Claude Cowork, 대화 불러오기 | 2,586ms | 728ms | 3.5배 |
| Claude Cowork, 메시지 보내기 | 928ms | 48ms | 19배 |
| 데스크톱 Claude Code, 메시지 보내기 | 250ms | 52ms | 4.8배 |
작업에는 Opus 5.5와 비슷한 수준의 내부 연구용 모델로 움직이는 Slack bot인 Claude Tag가 쓰였습니다. 처음 2주 목표로 잡은 13개 지표 가운데 12개를 사흘째에 달성했습니다.

▲ agent 성능 개선 순환 구조
먼저 측정을 바로잡았다
팀은 Slack 채널에 상시 지시문을 두고 Claude에게 성능 개선 전반을 맡겼습니다. 배포 뒤 성능이 나빠지지 않았는지 감시하고, 측정값이 정확한지 따지고, 대시보드를 관리하고, 새 개선 과제를 제안하는 일까지 포함됐습니다. Claude는 Datadog MCP 서버로 실제 사용 데이터에 접근해 영향이 큰 흐름을 골라냈고, 네 가지 흐름은 웹과 데스크톱을 합쳐 13개의 측정 지점으로 나뉘었습니다.
핵심은 측정 구간입니다. 사용자가 무언가를 누른 순간부터 화면에 마지막 결과가 그려질 때까지를 한 구간으로 재고, 클라이언트 처리와 서버 처리를 구분했습니다. 대시보드에는 응답 200ms로 찍히는데 실제 사용자는 8초를 기다리는 일이 생기는 것도, 중간 상태 전환을 재지 않기 때문입니다. agent에게 최적화를 맡기기 전에 사용자가 실제로 느끼는 시간을 재는 장치부터 갖춰야 하는 이유가 여기에 있습니다.
들쭉날쭉한 시간 대신 흔들리지 않는 지표
실제 경과 시간(wall-clock)은 잴 때마다 값이 달라 agent가 조금씩 개선하는 기준으로 삼기 어렵습니다. 한 엔지니어가 이를 대체할 지표를 묻자 Claude는 순수 JavaScript 구간에는 Valgrind로 센 명령어 수를 쓰자고 제안했습니다. node --predictable 옵션으로 실행해 저장소에 둔 기준값과 비교하면 통계적 잡음이 없다는 것입니다. 명령어 수를 셀 수 없는 브라우저 환경에는 상호작용 한 번당 React commit 수, V8 함수 호출 수, layout·style 재계산 횟수, DOM 변경 횟수 같은 대체 지표를 차례로 제시했습니다.
benchmark 하나에는 두 가지 역할이 주어졌습니다. 실험 단계에서는 Claude가 오를 목표가 되고, 이후에는 숫자가 줄어드는 쪽으로만 움직이게 고정하는 CI ratchet(성능 기준을 되돌릴 수 없게 조이는 자동 점검)이 됩니다. 대체 지표의 개선이 실제 경과 시간 단축으로 이어진다는 점도 Claude가 증명하게 했습니다.
| 개선 구간 | 명령어 수 | 실제 경과 시간 | 속도 |
|---|---|---|---|
| 메시지 트리 조립 | 48% 감소 | 76% 감소 | 4.6배 |
| Claude Code 상태 표시줄 스캐너 | 31% 감소 | 44% 감소 | 1.8배 |
메시지 트리 조립에서는 같은 메시지 ID를 세 번씩 찾는 megamorphic 사전 조회(여러 형태의 객체가 섞여 엔진이 빠른 경로를 쓰지 못하는 조회)가 명령어의 25%를 차지하고 있었습니다.
agent가 찾아낸 병목들
반복 구조는 단순했습니다. 엔지니어가 느린 흐름을 화면 녹화로 알리면 Claude가 그 흐름을 재현하는 benchmark를 만들고, 기능 플래그 뒤에 숨긴 PR을 올리고, 배포 뒤 실사용 데이터를 확인합니다. 개선이 확인되면 기준을 조이고, 아니면 플래그를 끄고 다시 시도합니다. 2주째에는 이 구조를 넓혀 100개가 넘는 Claude 스레드를 돌렸고, 동시에 최대 50개가 움직였습니다. 가장 많은 날에는 하루 200건이 넘는 변경이 병합됐습니다.
이렇게 드러난 문제는 다음과 같습니다.
- 메시지 입력창에서 글자를 칠 때마다 React hook 6,900개와 store 구독 900개가 다시 계산되고 있었습니다.
- 최상위에 걸린 CSS
:has선택자 하나가 DOM이 바뀔 때마다 24ms씩 style 재계산을 늘렸습니다. - 남아 있던
location.reload()호출이 하루 약 50만 번의 보이지 않는 페이지 새로고침을 일으켰습니다. - 백그라운드 탭에서 같은 캐시 스냅샷을 1분에 두 번씩 메인 스레드에서 IndexedDB로 복제하고 있었습니다.
- 대시나 굽은 따옴표가 섞인 Markdown 때문에 V8이 문자열을 UTF-16으로 저장하면서 코드 강조용 정규식이 느린 경로로 돌았고, 코드 블록을 강조할 때 화면이 약 1초 멈췄습니다. 강조 전에 코드 블록을 1바이트 문자열로 복사하는 20줄 변경으로 해결했습니다.
시작 속도를 높인 방법도 구체적입니다. 메시지 입력창을 정적 HTML로 미리 넣어 React가 준비되기 전에 입력할 수 있게 했고, 데스크톱 앱은 V8 코드 캐시를 미리 컴파일해 실행할 때 스크립트를 처음부터 해석하지 않게 했습니다. 대화를 옮겨도 입력창을 그대로 두고, 사이드바에 마우스를 올리면 대화를 미리 불러오게 해 사이드바 다시 그리기를 90% 줄였습니다. 긴 답변을 받는 동안 메인 스레드가 막히는 시간은 750ms 넘던 것이 약 200ms로 줄었고, CPU 사용량은 3분의 1 수준이 됐습니다.
사람이 맡은 일: 안전장치, 방향, 취향
속도를 낸 만큼 안전장치도 촘촘했습니다. 모든 PR에는 자동 CI 점검과 최소 한 명의 사람 승인이 필요했고, 위험한 변경은 짧게 쓰고 지우는 기능 플래그 뒤에 두었습니다. 2주 동안 만든 플래그가 200개 가까이 됩니다. 정적 입력창은 14가지 화면 크기에서 React가 그린 결과와 1픽셀 안으로 맞는지 시험했습니다.
그래도 시험이 놓친 문제가 있었습니다. 정적 입력창을 사내에 낸 지 4시간 만에 한 직원이 화면이 흔들린다는 녹화를 보냈습니다. 원인은 기업이 관리하는 Chrome 프로필의 새 탭 화면에 붙는 56픽셀짜리 관리 안내 줄이었습니다. Chrome이 주소를 입력하는 동안 페이지를 미리 그려 두는데, 그 크기가 새 탭 화면 기준이었고 안내 줄이 100ms 뒤 사라지면서 높이를 비율로 계산하던 입력창이 움직였습니다. 화면 아래에 고정하지 않고 위에서부터 비율로 위치를 잡은 설계가 근본 원인이었습니다.
방향을 잡는 일도 사람 몫이었습니다. Claude는 기본적으로 작업 범위를 좁게 잡고 일정을 넉넉히 추정했습니다. 기본 측정 장치를 만드는 데 며칠이 걸린다고 하자 한 엔지니어가 더 과감하게 하라고 요청했고, Claude는 예상 시간을 1시간 이내로 고쳤습니다. 초기 목표를 일찍 달성한 뒤에는 “엉뚱한 아이디어도 환영한다”고 말해 새 과제를 끌어냈습니다. 반대로 메시지를 보낼 때 2ms를 줄이려고 빌드 플러그인을 새로 만든 900줄짜리 PR은 유지 부담에 비해 이득이 작아 반려했습니다. 150개 스레드는 저마다 benchmark 하나나 흐름 하나에만 집중하게 범위를 좁혔습니다.
스레드마다 사람 담당자를 두고 사용자가 느낄 변화는 전후 녹화나 스크린숏으로 보여 주게 한 것도 같은 맥락입니다. 표를 칸 단위로 흘려보낼지 행이 끝날 때까지 기다릴지, skeleton 화면(내용이 오기 전에 보여 주는 빈 틀)을 언제 보여 줄지, 단어마다 페이드 효과를 넣는 데 프레임 예산의 20%를 쓸 가치가 있는지는 숫자로 정할 수 없는 판단이었습니다.

▲ 캐시와 서버 상태의 어긋남
지표만 좇을 때 생기는 빈틈
빨라진 claude.ai를 실제로 써 보면 아쉬운 점도 보입니다. prompt(AI에 보내는 요청 문장)를 보내고 곧바로 새로고침하면 새 대화가 사이드바에서 사라지고, 다른 창에서 지운 대화가 캐시에 남아 사이드바에 계속 보이며, 누르면 “더 이상 사용할 수 없는 세션”이라는 오류가 나옵니다. 사이드바를 IndexedDB 캐시로 바로 그려 속도를 얻었지만 서버와 다시 맞춰 보는 장치가 부족해 보입니다. 캐시한 데이터를 서버 확인 전까지 흐리게 보여 주는 방식이 대안이 될 수 있습니다.
여기서 얻을 교훈은 대체 지표만 주고 맡기면 agent가 필요한 미리 불러오기나 캐시를 꺼 버릴 수 있다는 점입니다. 사이드바 흔들림을 잡으려는 엄격한 layout 시험도 지나치면 캐시에 있던 4개 항목 뒤로 서버의 새 항목 1개가 들어오는 정상 동작까지 막을 수 있습니다. 사용자는 미세한 끊김이나 늦은 동기화를 거의 신고하지 않으므로, 개발자가 직접 써 보는 확인을 대신할 수 없습니다.
내 프로젝트에 적용할 순서
이번 사례는 agent에게 측정 가능한 숫자를 주면 막막하던 최적화 문제가 풀 수 있는 문제로 바뀐다는 점을 보여 줍니다. 비슷한 작업을 맡길 때는 다음 순서를 참고할 만합니다.
- 사용자 행동부터 최종 화면 표시까지를 한 구간으로 재는 측정 지점을 만듭니다.
- 경과 시간 대신 명령어 수, React commit 수처럼 흔들리지 않는 지표를 agent의 목표로 줍니다.
- 대체 지표의 개선이 실제 시간 단축으로 이어지는지 확인한 뒤 CI ratchet으로 고정합니다.
- 위험한 변경은 기능 플래그 뒤에 두고, PR마다 사람이 한 번은 승인합니다.
- agent가 범위를 너무 좁게 잡으면 과감한 시도를 명시적으로 허락하고, 이득이 작은 복잡한 변경은 반려합니다.
- 숫자로 잡히지 않는 끊김과 동기화 문제는 직접 써 보며 확인합니다.