앱이 느려서 Claude에게 고쳐 달라고 해도, 어느 동작이 얼마나 빨라져야 하는지 모르면 결과를 판단하기 어렵습니다. Anthropic 팀은 앱을 열고 메시지를 보내는 데 걸리는 시간을 먼저 측정했습니다. 그런 다음 Claude에게 코드를 고치게 하고 숫자가 줄었는지 확인하며 작업을 반복했습니다. 이 글은 그 측정 방법과 안전하게 배포한 과정을 설명합니다.

한눈에 보기

  • 2026년 8월, 2주 동안 집중해서 개선한 결과 claude.ai와 Claude 데스크톱 앱의 주요 동작이 약 3배 빨라졌습니다.
  • 개선 전후를 비교할 수 있는 수치가 생기자 Claude가 코드를 고치고 효과를 확인하는 일을 반복할 수 있었습니다.
  • 3천 건 넘는 변경을 합쳤지만 고객에게 보이는 장애나 이전 버전으로 되돌리는 롤백은 없었다고 합니다.
  • 사람은 얼마나 더 개선할지, 바뀐 화면이 쓰기 편한지, 여러 작업이 충돌하지 않는지를 판단했습니다.

원문 소개

  • 저자: Raymond Wang, Sam Attard, Issac G. / 발행일: 2026-09-23
  • 원문: How we made claude.ai 3x faster in two weeks
  • 이런 분께 맞습니다: AI 에이전트에게 코드 수정을 맡기면서 어떻게 통제할지 고민하는 개발자, 프런트엔드 성능을 다루는 분

무엇을 얼마나 빠르게 했나

팀은 사용자 활동의 95%를 차지하는 동작 네 가지에 집중했습니다. 앱 실행, 대화 시작, 기존 대화 불러오기, 메시지 보내기입니다. 원문에서 말하는 사용자 여정은 사용자가 이 동작을 시작해서 끝낼 때까지의 과정입니다.

웹과 데스크톱, 제품별로 나눠 13개 지점을 측정했습니다. 개선 폭은 각 지점의 배율을 종합하는 기하평균으로 3.1배였습니다. 모든 동작이 똑같이 빨라졌다는 뜻은 아닙니다. 아래는 p75 기준의 일부 결과입니다. p75는 측정값을 빠른 순서로 놓았을 때 75% 지점의 시간으로, 사용자 4명 중 3명이 이 시간 안에 동작을 마치는 기준입니다. ms는 밀리초 단위이며 숫자가 작을수록 덜 기다립니다.

  • claude.ai 웹 첫 로딩, 입력 가능해질 때까지: 3,085 ms에서 550 ms
  • 데스크톱 앱 콜드 스타트, 앱이 실행되지 않은 상태에서 처음 켜기: 6,310 ms에서 3,328 ms
  • Claude Cowork 클라우드 세션 불러오기: 2,566 ms에서 728 ms

원문 차트: 4개 사용자 여정의 13개 항목에서 개선 전후 p75 시간을 비교

그림 1. 원문의 차트에서 여정 이름과 설명만 한글화했습니다. 막대의 길이는 개선 전후 걸린 시간이고, 오른쪽은 빨라진 배수와 시간 감소율입니다. 출처: 원문 .

막대 끝의 퍼센트가 줄어든 비율이고 오른쪽 숫자가 이전과 이후 시간입니다. 감소율이 가장 큰 곳은 Claude Cowork 데스크톱(클라우드)의 메시지 전송으로 928 ms에서 48 ms가 됐고(95%), 가장 작은 곳은 웹 Chat의 대화 시작으로 416 ms에서 273 ms였습니다(34%).

팀은 Slack 채널 하나에서 작업했습니다. 여기에 Claude Tag(베타)로 Opus 5.5와 대략 비슷한 내부 연구용 모델을 붙였습니다. Claude는 처리가 늦어지는 병목을 찾고, 같은 조건에서 속도를 비교하는 시험인 벤치마크를 만들고, 배포 뒤 수치까지 확인했습니다. 처음 계획한 프로젝트는 스무 개쯤이었고 13개 목표 중 12개를 사흘째에 달성했습니다.

대표적인 변경은 입력창을 HTML로 미리 그려 두는 것이었습니다. React가 화면에 클릭과 입력 같은 동작을 연결하는 하이드레이션을 마칠 때까지 기다리지 않고 타이핑할 수 있게 했습니다. 사이드바를 다시 그리는 리렌더링도 90% 줄였습니다.

실험실에서 재는 방법

실제 사용자의 시간은 배포 뒤에야 모입니다. 코드 수정마다 이 결과를 기다리면 작업이 느려지므로, 팀은 개발 환경에서 빠르게 반복할 수 있는 측정값을 찾았습니다. 컴퓨터가 바쁜 정도에 따라 실행 시간은 달라질 수 있지만 같은 계산에 쓰이는 CPU 명령어 수는 더 일정하게 잴 수 있다는 점에 착안했습니다.

명령어 수가 줄었다고 사용자의 기다림도 줄어드는지는 별도로 확인했습니다. 예를 들어 메시지 사이의 관계를 조립하는 코드가 같은 메시지 ID를 세 번 찾고 있었습니다. 한 번만 찾게 바꾸자 명령어는 48%, 실제 실행 시간(wall-clock)은 78% 줄었습니다. 측정 숫자와 실제 속도가 함께 좋아진 사례입니다.

이렇게 확인한 벤치마크는 코드를 합칠 때 자동 검사를 돌리는 CI에 넣었습니다. 상한선(ratchet)은 앞으로 이 숫자를 넘는 변경을 통과시키지 않겠다는 기준입니다. 개선으로 상한선이 내려가면 다시 올리지 못하게 해서 성능이 나빠지는 변경을 막았습니다. 측정할 때마다 값이 흔들리거나 실제 지연 시간과 맞지 않는 벤치마크는 버렸습니다.

실험실 지표를 줄였을 때 실제 시간도 줄어드는지 확인했습니다. 결과가 들쭉날쭉한 불안정(flaky) 벤치마크는 버렸습니다. Claude Code 출력의 상태 줄을 읽는 스캐너(status-line scanner)에서도 명령어 31%, 시간 44%가 함께 줄었습니다. 이후 매일 실행하는 작업이 개선된 숫자에 맞춰 상한선을 내려, 다음 변경에서 성능이 다시 나빠지지 않게 했습니다.

작업은 점차 아래 순서로 반복됐습니다. 누군가 Slack 스레드에 느린 구간을 제보하면 Claude가 같은 문제를 벤치마크로 재현합니다. 수정은 검토하기 쉬운 크기로 나눠 PR, 즉 코드를 합치기 위한 검토 요청으로 올립니다.

사용자에게 보이는 변경에는 기능 플래그를 붙입니다. 플래그는 배포한 기능을 켜거나 끌 수 있는 스위치입니다. 배포 뒤 실제 사용자의 수치가 좋아지면 상한선을 내리고, 나빠지면 스위치를 꺼서 변경의 적용을 중단한 뒤 다시 시도합니다.

이 루프에서 상한선을 내릴지 플래그를 끌지는 배포 뒤 실제 사용자의 현장 수치가 정합니다. 실패해도 플래그를 끄고 다시 시도할 수 있다는 점도 눈여겨볼 만합니다.

스레드가 150개 넘게 동시에 진행됐고 여러 병목이 드러났습니다. 입력창에서는 키를 누를 때마다 화면 상태를 처리하는 훅 6,900개와 상태 변경을 받아 보는 스토어 구독 900개가 리렌더링에 얽혀 있었습니다. 사용자의 작은 입력이 많은 화면 처리로 이어진 것입니다. 숨은 location.reload() 호출 때문에 하루 50만 번의 새로고침도 일어나고 있었습니다.

코드의 문법에 따라 색을 입히는 하이라이팅에서도 예상 밖의 병목이 나왔습니다. 답변에 em dash 같은 Latin-1 밖의 문자가 있으면 JavaScript 실행 엔진인 V8이 문자열 전체를 UTF-16 방식으로 저장했습니다. 원문은 이 저장 방식의 차이 때문에 문자열에서 패턴을 찾는 정규식 처리가 느려졌다고 설명합니다.

하이라이트 전에 코드 블록을 1바이트 문자열로 복사하는 20줄 수정으로, 실험실에서 첫 블록 처리 중 메인 스레드가 멈추는 시간이 1.0초에서 0.35초로 줄었습니다. 메인 스레드는 화면 그리기와 사용자 입력을 처리하므로, 이곳이 오래 멈추면 앱이 잠깐 얼어붙은 것처럼 느껴집니다.

원문 입력창 로딩 비교 화면: 개선 전 2.93초와 개선 후 0.36초

그림 2. 왼쪽은 개선 전, 오른쪽은 개선 후입니다. 4G로 제한한 원문 시연에서 입력 가능한 시점이 2.93초에서 0.36초로 앞당겨졌습니다. 오른쪽은 먼저 간단한 입력창을 띄우고, 정식 입력창이 준비되면 입력한 내용을 이어받습니다. 출처: 원문 .

안전장치와 사람의 역할

모든 PR은 자동 리뷰와 사람 승인을 거쳤고 최적화 전에 단위 테스트를 먼저 썼습니다. 사용자에게 영향이 갈 만한 변경은 수명이 짧은 기능 플래그 뒤로 나갔고, 고위험 변경은 직원, 사용자 1%, 전체 순서로 배포했습니다. 플래그는 200개 가까이 생겼는데 Claude가 하나씩 정리해서 2주가 끝날 때 절반 넘게 치웠습니다.

테스트, 리뷰와 승인, 기능 플래그를 안전장치로 썼습니다. 직원에서 1%, 전체로 넓히는 단계 배포는 고위험 변경에 적용했습니다.

사람의 몫은 세 가지였습니다.

  • 도전 수준: Claude는 기본적으로 범위를 조심스럽게 잡습니다. Raymond는 PR을 지금 올리면 바로 머지하고 배포하겠다며 더 대담하게 밀어 줬습니다.
  • 사용성 판단: 표를 셀 단위로 채울지 같은 체감 판단은 스레드마다 정해진 담당자가 내렸습니다.
  • 작업 조율: 스레드를 좁게 유지하고 서로 부딪치는 스레드를 합치거나 효과가 줄어든 스레드를 닫았습니다.

답변이 생성되는 대로 조금씩 화면에 표시하는 스트리밍 렌더링에서도 사람의 판단과 Claude의 수정이 함께 쓰였습니다. 120Hz 화면은 자주 갱신되므로, 한 번의 화면 갱신에 쓸 수 있는 프레임 예산은 8.33ms입니다. 팀은 긴 답변을 그리는 데 걸리는 시간을 갱신 단위로 재며 줄였고 스레드 하나에서 PR이 60개 가까이 나왔습니다. 긴 답변이 메인 스레드를 막는 시간은 약 750ms에서 약 200ms로 줄었습니다.

인사이트

여기서부터는 원문이 아니라 이 블로그의 해석입니다.

  1. 에이전트에게 개선을 맡기려면 좋아졌는지 확인할 수 있는 목표가 필요합니다. “앱을 빠르게 해 줘"보다 어느 동작에 걸리는 시간을 줄일지 정하는 편이 결과를 판단하기 쉽습니다. 데이터 처리나 에이전트 서비스에서도 수정 전후를 같은 기준으로 비교할 수 있어야 스스로 고치고 확인하는 작업을 반복할 수 있습니다.

  2. 개발 중에 재는 숫자와 실제 사용자의 기다림을 함께 봐야 합니다. 호출 수나 화면을 다시 그리는 횟수는 빠르게 반복 측정할 수 있지만 그 숫자가 줄었다고 사용자가 체감하는 속도까지 좋아졌다고 단정할 수는 없습니다. 이런 지표는 코드를 합칠 때 자동으로 검사하는 CI에 활용하고 실제로 걸리는 시간도 따로 확인하는 편이 좋겠습니다.

  3. 변경을 많이 적용하려면 문제가 생겼을 때 멈추거나 되돌릴 방법부터 준비해야 합니다. 새 기능을 켜고 끄는 설정, 일부 사용자에게 먼저 적용하는 배포 방식, 성능이 다시 나빠지는 변경을 막는 기준이 여기에 해당합니다. 원문의 3천 건이 넘는 변경도 이런 장치가 있었기에 적용할 수 있었던 것으로 보입니다.

측정할 목표와 실제 효과를 확인하는 방법, 문제가 생겼을 때 되돌릴 방법을 함께 준비해야 에이전트가 엉뚱한 숫자만 줄이는 일을 막을 수 있습니다.

바로 해볼 것

  • 맡은 서비스에서 느린 동작 하나를 고릅니다. 예를 들어 화면을 여는 작업이라면 버튼을 누른 순간부터 화면에 입력할 수 있는 순간까지 시간을 재는 식으로 시작점과 끝점을 정합니다.
  • 같은 동작을 같은 조건에서 반복해 시간을 재고, 호출 수나 화면을 다시 그리는 횟수도 기록합니다. 코드를 고친 뒤 숫자와 실제 대기 시간이 함께 줄었는지 비교합니다.
  • 에이전트가 만든 변경을 켜고 끌 수 있는 기능 플래그를 준비합니다. 문제가 생겼을 때 설정을 꺼서 이전 동작으로 돌아갈 수 있는지 확인합니다.

원문: How we made claude.ai 3x faster in two weeks