슈뢰딩거의 Claude in Chrome 탭: 지켜볼 때만 일한다
기계 번역입니다. 오류 제보 환영
Chrome의 백그라운드 탭에서 일하는 AI 에이전트는 왜 느려지고, 잠들어 버리고, 심지어 고객센터 채팅까지 끊기게 만들까.
나는 여러 일을 한꺼번에 돌리는 편이다. 7월 중순의 어느 오후, Claude in Chrome에 일 세 가지를 동시에 맡겼다. 첫 번째 탭에서는 우리 브라우저의 팝업 감지 기능을 검수하고, 두 번째 탭에서는 영상에 어울리는 배경음악을 찾고, 세 번째 탭에서는 Origin Energy 고객센터에 보낼 이의 제기 글을 쓰고 있었다. 그쪽에서 내 전기요금 고지서 하나를 잘못 계산했기 때문이다. 세 가지가 모두 시작되자 나는 브라우저를 뒤로 보내 놓고 터미널로 돌아가, Claude Code로 내 AI 개발팀을 굴리는 일을 계속했다. 내가 에이전트를 쓰는 이유가 바로 이거다. 여러 에이전트가 각자 알아서 일하고, 나는 하나하나 붙어서 지켜보지 않아도 되는 것.
한참 뒤 브라우저로 돌아가 보니 세 작업 중 앞으로 나아간 건 하나뿐이었다. 나머지 둘은 꾸벅꾸벅 졸고 있는 것 같았고, 조금 더 기다리면서 탭을 몇 번 오가 봐도 그대로였다.
이런 일을 겪으면 대부분은 그날따라 네트워크가 느리거나 모델이 느리다고 먼저 생각할 것이다. 하지만 네트워크나 모델이 문제였다면 세 작업이 다 같이 느려졌어야 하는데, 움직이는 건 하나뿐이었다. 나는 오랫동안 브라우저를 만들어 왔고, 곧바로 다른 설명이 떠올랐다. Chrome이 백그라운드 탭의 속도를 늦추고 있었던 것이다.
사실 이건 Chrome의 결함이라고 하기도 어렵다. 브라우저라면 원래 이렇게 해야 한다. 보고 있지도 않은 페이지가 최고 속도로 돌 이유는 없고, 사람들은 탭을 수십 개씩 열어 두니까, 앞에 있든 뒤에 있든 전부 최고 속도로 돌았다면 노트북 배터리는 반나절이면 바닥났을 것이다. 문제는 브라우저 속 페이지가 이제 사람이 보기 위해서만 있는 게 아니라는 점이다. AI 에이전트도 그 안에서 일한다. 사람에게 백그라운드 탭은 지금 당장은 필요 없는 탭이다. 하지만 에이전트에게 같은 탭은 다운로드를 기다리고 있거나, 환불을 처리하고 있거나, 끊기면 안 되는 고객센터 채팅을 붙잡고 있는 중일 수 있다. 아무도 보지 않는 탭에도 할 일은 남아 있을 수 있다.
브라우저의 규칙은 사람을 위해 만들어졌고, 에이전트에게는 잘 맞지 않는다.
7월 16일에 직접 손으로 테스트해 보고 이게 문제라는 걸 확인했다. 그날은 우리가 AI 에이전트를 위해 만드는 브라우저 Embiody에 'AI 탭'이라는 기능을 넣기로 한 날이기도 하다. 최근 그 테스트를 제대로 다시 해 봤다. 알고 싶은 건 세 가지였다. Chrome은 백그라운드 탭을 얼마나 느리게 만드는가. Chrome은 언제 페이지를 통째로 얼려 버리는가. 그리고 가장 고약한 질문, 페이지가 아직 열려 있는데도 에이전트가 엉뚱한 내용을 읽을 수 있는가. 결과는 내 예상보다 나빴다.
1. 8분이 지났는데, 페이지는 1분 30초가 지났다고 생각한다
가장 평범한 카운트다운 페이지부터 시작했다. 1초에 한 칸씩 줄어들고, 결제 페이지나 한정 판매 페이지의 카운트다운과 똑같은 방식으로 작성했다. 한 칸 줄어들 때마다 페이지가 같은 컴퓨터에 있는 작은 서버에 진행 상황을 보고하기 때문에, 브라우저가 페이지를 얼려 버려도 실제로 무슨 일이 있었는지는 서버에 기록으로 남는다.
이 페이지를 두 개 열었다. 하나는 Claude in Chrome이 열고, 하나는 비교용으로 내가 직접 열었다. 그리고 둘 다 8분 동안 눈앞에서 치워 두었다. 치우는 방법은 세 가지로 해 봤다. 다른 탭으로 전환하기, 다른 창으로 창을 완전히 가리기, 창 최소화하기. 세 방법 모두 결과가 거의 똑같았다.
페이지가 안 보이게 된 뒤 첫 1분 동안은 아무 변화가 없었고, 카운트다운은 여전히 1초에 한 칸씩 움직였다. 1분쯤 지나자 1분에 한 칸으로 떨어졌다. 8분 뒤, 현실에서는 480초가 지났는데 페이지는 90초쯤 지났다고 여겼으니 390초가 뒤처진 셈이다. 8분 동안 아침을 먹고 돌아왔더니 집 시계는 1분 30초만 가 있는 것과 같다. 게다가 창을 다시 앞으로 가져오면 카운트다운은 1초에 한 칸으로 돌아오지만, 잃어버린 몇 분은 끝내 되찾지 못한다.
더 중요한 건 Claude in Chrome이 연 페이지가 내가 손으로 연 페이지와 정확히 똑같이 움직였다는 점이다. Claude 쪽은 387~391초, 내 쪽은 392초 뒤처졌다. 그러니 이건 Claude와는 아무 상관이 없다. Chrome에 열려 있는데 아무도 보지 않는 페이지는 전부 이렇게 된다. Chrome에서 에이전트를 돌리는 사람이라면 누구나 이 문제를 만난다는 뜻이다.
(Windows 11, Chrome 157.0.8103.39, Claude 확장 프로그램 1.0.106, 2026년 11월 11일, 컴퓨터 한 대, 경우마다 1~2회 실행.)
그러면 당연한 의문이 하나 생긴다. Claude in Chrome의 탭은 거의 항상 백그라운드에 있다. 백그라운드 탭이 1분에 한 번만 움직인다면 대체 어떻게 일을 해내는 걸까? 그런데 분명히 일은 끝낸다.
2. 에이전트가 만지고 있는 탭만 깨어 있다
알아보려고 실제 작업에 더 가까운 테스트 페이지를 만들었다. 웹사이트에서 가장 흔한 두 종류의 기다림을 넣었다. 첫째는 다운로드다. 페이지에 "90초 후 다운로드가 시작됩니다"라고 나오고, 카운트다운이 0이 되어야 다운로드 버튼을 누를 수 있다. 둘째는 내보내기다. 페이지에 "내보내는 중"이라고 나오고, 2초마다 서버에 끝났는지 묻는데, 서버는 90초 뒤에 끝났다고 답한다.
그다음 Claude in Chrome에게 이런 작업 두 개를 동시에 시켰다. 하나는 탭 A, 하나는 탭 B다. 에이전트는 A부터 작업했고, B는 아무도 건드리지 않은 채 백그라운드에 있었다. 결과는 이렇다.
| 경우 | 다운로드 버튼을 누를 수 있기까지 걸린 시간 |
|---|---|
| 창이 눈앞에 있음 | 90초 |
| A와 B를 함께 열고, 에이전트는 A만 작업 | A: 90초 |
| 위와 같음, B, 1회차 | B: 407초 |
| 위와 같음, B, 2회차 | B: 384초 |
2회차의 B를 창을 다시 앞으로 가져온 순간부터 보자. 페이지가 얼마나 기다렸다고 말하는지 잘 보시라.
페이지는 실제 시간으로 378초를 기다리고도 아직 6초가 남아 있었다. 90초짜리 기다림이 6~7분이 된 것이고, 7월 그 오후에 나에게 일어난 일이 바로 이거였다. 에이전트는 내내 일하고 있었다. 다만 늘 A에서 일하고 있었고, 그동안 B는 백그라운드에서 1분에 한 칸씩 기어가고 있었다. 마침내 에이전트가 B를 들여다봤을 때, 진작 끝났어야 할 카운트다운이 아직 돌고 있었다. 그나마 운이 좋은 경우다. 에이전트가 B로 끝내 돌아오지 않았다면, 1분에 한 칸씩이니 90초짜리 카운트다운에 30분 가까이 걸렸을 것이다.
이상한 건 내보내기는 거의 영향을 받지 않았다는 점이다. 서버가 90초에 끝났다고 답했고, 에이전트는 겨우 3초 뒤에 알아챘다.
둘 다 백그라운드 탭에서 기다린 건데, Chrome은 왜 다운로드 카운트다운만 늦추고 내보내기는 그냥 두었을까?
차이는 두 기다림을 작성한 방식에 있다. 카운트다운은 스스로 알람을 맞춘다. 이번 초의 알람이 울리면 다음 알람을 맞추고, 그게 울리면 또 그다음 알람을 맞춘다. 알람 하나하나가 앞의 알람에 사슬처럼 이어져 있는 것이다. 내보내기는 상대의 회신 전화를 기다린다. 서버에 묻고, 서버가 답한 뒤에야 다음 질문을 예약하니, 매번 다른 사람의 답에서 새로 시작한다. Chrome에는 사슬처럼 이어진 알람만 겨냥한 규칙이 있다. 페이지가 한동안 보이지 않으면 그런 알람은 1분에 한 번만 울릴 수 있다. 그래서 카운트다운은 느려졌고, 회신 전화를 기다리는 내보내기는 이 규칙에 걸리지 않는다.
그러니까 백그라운드 속도 제한은 페이지 전체를 고르게 늦추지 않는다. 페이지가 어떻게 작성됐느냐가 느려질지 말지를 정한다. 그런데 이게 최악은 아니다.
3. 20초가 지나면 페이지가 완전히 멈춘다
위의 느려짐은 그래도 언젠가는 끝난다. 다음 건 정말 깜짝 놀랐다. Claude in Chrome은 새 탭을 기본적으로 백그라운드에, 지금 보고 있는 탭 뒤에 연다. 테스트 탭 하나를 열게 하고 그대로 두었더니, 겨우 20초 만에 페이지가 완전히 멈췄다. 카운트다운은 1분에 한 칸도 움직이지 않았고, 에이전트가 돌아와 그 안에서 뭔가를 할 때까지 아예 그대로였다. 네 번 봤는데 매번 20초 안팎이었고, 그동안 브라우저 창은 화면에 그대로 떠 있었다. 가려지지도, 최소화되지도 않았다.
창이 버젓이 보이는데, 그 안의 페이지가 왜 갑자기 뚝 멈출까?
비교하려고 같은 페이지를 평범한 방법으로 백그라운드 탭에 열어 봤다. 3분이 지나도 계속 돌았고, 1분에 한 칸으로 떨어졌을 뿐이었다. 그러니 20초는 Claude in Chrome과 관련이 있을 수밖에 없다. 탭 표시줄을 한동안 지켜보다가 마침내 발견했다. 에이전트의 마지막 명령 뒤 20초쯤 지나면 Claude의 탭 그룹이 저절로 접히고, 탭 그룹이 접히면 Chrome은 그 안에서 한 번도 표시된 적 없는 탭을 얼려 버린다. 이 클립에서 탭 표시줄을 잘 보시라.
하나씩 떼어 놓고 보면 다 말이 된다. Claude in Chrome은 자기 탭 무더기가 여러분의 탭 표시줄을 차지하길 원하지 않으니, 쉴 때는 그룹을 접어 둔다. Chrome은 접힌 그룹을 한동안 쓸 일이 없어 서랍에 넣어 둔 물건처럼 여기니, 메모리를 아끼려고 전원을 끊는다. 그런데 합리적인 규칙 두 개가 한데 겹치면, 에이전트가 백그라운드에 연 탭은 에이전트가 잠깐 숨을 돌리는 순간 전부 잠들어 버린다.
그래도 에이전트가 실제로 작업 중인 탭은 괜찮겠지? 에이전트에게 탭 A와 B를 맡기고, 처음 3분 동안 30초마다 A를 읽게 했다. A는 내내 정상적으로 돌았고, 아무도 건드리지 않은 B는 2분째부터 사실상 멈췄다. 그다음 B를 읽도록 바꿨다. B는 곧바로 깨어났지만, 30초쯤 뒤에는 방금 손을 뗀 A가 얼어 버렸다.
즉 에이전트가 탭을 만지면 그 탭은 20~30초 동안만 깨어 있다. 에이전트가 다른 일로 넘어가거나, 그냥 조금 더 오래 생각하느라 멈추기만 해도 그룹이 접히고 탭도 함께 잠든다. 사람에게는 브라우저가 메모리를 좀 아낀 것일 뿐이다. 에이전트에게는 훨씬 나쁘다. 방금 떠나온 페이지가 일을 멈췄다는 걸 전혀 모르기 때문이다.
4. 상담원은 끝내 YES를 받지 못했다
카운트다운이 얼면 무언가가 늦게 끝날 뿐이다. 고객센터 채팅이 얼면 일이 실패한다. 실시간 상담 채팅, 인터넷 뱅킹, 시험 페이지, 티켓 대기열은 모두 여러분이 계속 자리에 있기를 기대하고, 몇 초마다 서버에 조용히 "아직 있어요"라고 알린다. 잠깐 상담원 입장이 되어 보자. 상대가 45초 동안 아무 기척이 없다면 어떻게 생각하겠는가? 떠났다고 보고 대화를 닫을 것이다. 7월에 내가 Origin Energy에 넣은 이의 제기가 바로 이런 채팅으로 진행됐다.
그런 상담 페이지를 만들었다. 10초마다 서버에 체크인하고, 서버는 45초 동안 소식이 없으면 채팅을 끝낸다. 채팅이 시작되고 1분 뒤 상담원이 이렇게 보낸다. "Reply YES and I will refund it today."(YES라고 답해 주시면 오늘 환불해 드리겠습니다.)
이번에도 Claude에게 탭 두 개를 맡겼다. 먼저 A에서 다른 일을 끝냈는데 1분 30초가 걸렸다. 그다음 터미널로 명령을 실행하러 갈 때처럼 1분 30초 동안 브라우저를 건드리지 않았다. 마지막으로 B의 상담 페이지로 돌아가 YES라고 답하려 했다. 그동안 창은 계속 화면에 있었고, 맨 앞에는 내 탭이, 그 뒤에 Claude의 탭 그룹이 있었다. 평소 일하는 모습 그대로이고, 특별할 것이 하나도 없다.
에이전트가 멈추고 20초 뒤 Claude의 탭 그룹이 접혔고, B의 상담 페이지가 얼었고, 체크인이 멈췄다. 1분 남짓 지나 에이전트가 B로 돌아왔을 때 본 건 이것이다.
Chat ended: no check-in from this page for 83 s. Please sign in again to start a new chat. (채팅 종료: 이 페이지에서 83초 동안 체크인이 없었습니다. 새 채팅을 시작하려면 다시 로그인하세요.)
여기서 서버가 따지는 건 페이지가 얼마나 오래 조용했느냐이고, 채팅이 얼마나 오래 열려 있었느냐는 상관없다. 페이지가 계속 체크인하는 한 얼마든지 오래 열어 둬도 된다. B가 끊긴 건 얼어붙은 뒤 83초 동안 아무 말도 하지 않았기 때문이다.
입력창과 전송 버튼은 이미 회색으로 바뀌어 있었다. YES는 끝내 보낼 수 없었고, 상담원은 이미 대화를 닫았고, 환불은 흐지부지됐다. 에이전트가 여러분 대신 다시 로그인할 수도 없으니, 이 일은 여러분이 돌아와서 대기열 맨 뒤부터 다시 줄을 설 때까지 멈춰 있다. 같은 작업을 Embiody에서도 돌렸고, 에이전트는 똑같이 1분 30초 자리를 비웠다. 거기서는 상담 페이지가 10초마다 꼬박꼬박 체크인하면서 내내 Connected(연결됨)를 표시했고, YES가 전송됐고, 상담원은 "Done, the refund is on its way."(처리했습니다. 환불이 진행 중입니다.)라고 답했다. 두 화면을 나란히 놓으면 이렇다. 왼쪽이 Chrome, 오른쪽이 Embiody다.
이렇게 반문할 수도 있다. 앞에서 서버의 답을 기다리는 방식은 속도 제한에 걸리지 않는다고 했고, 상담 체크인이 딱 그 방식인데 왜 끊겼느냐고. 맞는 말이다. 속도 제한만 있었다면 상담 페이지는 여전히 10초마다 체크인했을 것이다. 연결을 끊어 놓은 건 동결이다. 속도 제한은 스스로 맞춘 알람을 1분에 한 번 울리게 할 뿐이지만, 동결은 페이지 전체의 전원을 끊는다. 그 안의 모든 것이 멈춘다. 스스로 맞춘 알람도, 회신 전화를 기다리는 것도 마찬가지이니, 체크인이 멈추는 것도 당연하다.
그럼 확장 프로그램이 그룹을 접지 않게 하면 되지 않을까? 사실 그룹을 접는 건 딱 한 경우뿐이다. 창 맨 앞에 표시된 탭이 여러분의 탭일 때다. Claude의 탭 그룹을 별도의 창으로 옮겨서 맨 앞 탭이 Claude의 탭이 되게 해 봤다. 그러자 확장 프로그램은 그룹을 접지 않았고, 상담 페이지는 속도 제한만 받았으며, 11분 내내 연결이 유지됐다. 하지만 누가 이것만을 위해 창을 따로 열겠는가? 그 탭 그룹은 여러분이 쓰고 있는 창 안에 자리 잡는다.
Claude in Chrome 입장에서 보면 진퇴양난이다. 여러분과 브라우저 하나, 창 하나를 같이 쓴다. 접지 않으면 자기 탭이 여러분의 탭 표시줄에 줄줄이 늘어서서 방해가 된다. 접으면 Chrome이 자기 규칙대로 그 탭들을 얼린다. 접기는 확장 프로그램의 제품 결정이고 동결은 Chrome의 규칙이니, 확장 프로그램이 바꿀 수 있는 건 앞의 것뿐이다. 설령 절대 접지 않더라도, 그 탭들은 여전히 여러분의 탭 뒤에 있고, 여전히 보이지 않으며, 여전히 속도 제한을 받는다.
에이전트가 사람을 위해 설계된 브라우저에 세 들어 사는 한, 여기서 빠져나갈 길은 없다. 그렇다고 에이전트가 브라우저 없이 지낼 수도 없다. 웹은 사람을 위해 만들어졌고, 사람과 에이전트가 같은 브라우저에서 같은 사이트를 쓰며 나란히 일하는 것이 분명히 앞으로의 흐름이기 때문이다.
(2026년 11월 12일, Chrome 157.0.8103.51, 확장 프로그램 1.0.106, 각 1회 실행.)
5. 페이지는 누가 보고 있다고 믿지만, 아무것도 그려지지 않는다
여기까지만으로도 이미 큰 문제다. 그런데 더 은밀한 문제를 하나 더 찾았다. 이번에는 페이지가 얼지도 않았고, 타이머도 정확했으며, 페이지는 스스로 화면에 보인다고까지 여겼다. 그런데도 화면은 거의 움직이지 않았다.
진행 막대가 두 개 있는 페이지를 만들었다. 초록 막대는 시간에 따라 1초에 한 칸씩 움직인다. 빨간 막대는 브라우저가 실제로 그린 프레임에 따라, 프레임 하나마다 조금씩 움직인다. Claude에게 백그라운드 탭에서 이 페이지로 2분 동안 작업하게 했다. 한 번 클릭해서 음악을 틀고, 그 뒤로는 10초마다 목록을 스크롤하고 페이지를 읽게 했다. 마지막에 탭을 앞으로 가져왔다.
앞으로 온 순간 초록 막대는 가득 찼고 빨간 막대는 겨우 출발한 정도였다. 타이머는 184초가 지났다고 했지만, 그려진 프레임은 약 620개뿐이었다. 보통의 초당 60프레임이라면 11,000개 안팎이어야 한다. 처음 100초 동안은 고작 387프레임, 평균 초당 4프레임도 안 됐다. 사람 눈에는 슬라이드 쇼처럼 보이는 수준이다. 페이지는 누가 보고 있다고 믿었지만, 렌더러는 실제로 그 페이지를 그리고 있지 않았다.
그러니까 화면이 느리게 그려진다는 건데, 그게 그렇게 중요할까? 숫자를 애니메이션으로 보여 주길 좋아하는 사이트가 많다. 기업 홈페이지에 있는 "98,765개 기업이 함께합니다" 같은 문구를 떠올려 보자. 페이지를 열면 0부터 올라가서 2~3초 뒤에 최종 숫자에서 멈춘다. 에이전트가 이런 페이지를 아무것도 그려지지 않는 백그라운드에서 열면, 숫자가 중간에 멈춰 있을 수 있다.
3초 동안 0에서 98,765까지 올라가는 페이지를 만들고, Claude에게 새 백그라운드 탭으로 열게 한 다음, 다른 일을 하다가 10초 뒤 돌아와 숫자를 읽게 했다. 결과는 이렇다.
| 환경 | 에이전트가 읽은 숫자 |
|---|---|
| Chrome + Claude in Chrome, 3회 | 73,795, 71,215, 69,619 |
| Embiody + BrowserDo, 2회 | 98,765, 98,765 |
이 클립은 에이전트가 다른 일을 하는 동안 두 백그라운드 탭에서 무슨 일이 있었는지 보여 준다.
Chrome에서 세 번 모두 다른 숫자가 나온 건, 페이지가 백그라운드에 숨은 채 프레임을 하나도 그리지 않아서 숫자가 0에 머물러 있었기 때문이다. 에이전트가 읽으러 온 순간 확장 프로그램이 페이지를 '보이는' 상태로 만들었고, 숫자는 그제야 올라가기 시작했는데, 에이전트는 끝날 때까지 기다리지 않았으니 그때까지 올라간 숫자를 읽은 것이다. 달리는 사람 사진을 찍는 것과 같다. 언제 셔터를 누르든, 찍히는 건 트랙 한가운데를 달리고 있는 모습이다.
가장 나쁜 점은 에이전트가 숫자가 틀렸을 수도 있다고 말해 주지 않는다는 것이다. 오류도 나지 않고, 끝나지 않은 애니메이션을 봤다는 걸 에이전트가 알 방법도 없다. 에이전트 입장에서는 페이지가 열렸고, 숫자를 읽었고, 다 괜찮다. 한 번만 읽는다면 틀린 숫자를 사실인 양 여러분에게 건넨다. 게다가 이건 내가 만든 테스트 페이지일 뿐이다. 백그라운드 탭에 있는 에이전트가 여러분 대신 콘서트 티켓이나 타임세일 상품을 잡으려 한다고 상상해 보라.
(2026년 11월 12일, Chrome 157.0.8103.51, 확장 프로그램 1.0.106.)
6. 슈뢰딩거의 탭
이 모든 걸 보다 보니 슈뢰딩거의 고양이가 떠올랐다. 그 유명한 사고 실험에서는 상자를 열기 전까지 고양이가 살았는지 죽었는지 아무도 말할 수 없다. Chrome 속 에이전트의 탭도 거의 같다. 지켜보고 있으면 제대로 일한다. 지켜보지 않으면 1분에 한 번 움직이거나, 이미 얼어 있을 수도 있다. 에이전트가 탭을 조작하는 건 상자를 열어 보는 것과 같아서, 탭은 한동안 깨어난다. 에이전트가 자리를 뜨면 상자는 다시 닫힌다. 이번에는 그 상자가 눈에 보이기까지 한다. 저절로 접히는 바로 그 탭 그룹이다.
에이전트가 여러 일을 동시에 돌릴 때, 한 번에 조작할 수 있는 탭은 하나뿐이고 나머지는 상자 안에 갇혀 있다. 어떤 건 느려졌을 뿐이고, 어떤 건 이미 얼었고, 어떤 건 멀쩡해 보이지만 그려지지도 않고 있다. 그리고 에이전트 자신은 각각이 어떤 상태인지 전혀 모른다. 그러니 이건 조금 빠르냐 느리냐로 끝나는 문제가 아니다. 에이전트가 돌려준 결과를 믿을 수 있느냐가 여기에 달려 있다.
그 뒤에 무엇이 있는지 알아보려고 Chromium 156 소스(내가 테스트한 157과 동작이 같다)와 Claude in Chrome 1.0.106 확장 프로그램의 코드를 나란히 놓고 살펴봤다. 일곱 가지 규칙이 겹겹이 쌓여 있었다.
7. 일곱 가지 규칙은 실제로 무엇을 말하나
이 절에서는 앞의 이야기에 나온 일곱 가지 규칙을 Chromium 소스와 하나씩 맞춰 본다. 끝까지 파고들고 싶거나 소스를 직접 확인해 보고 싶은 독자를 위한 부분이다. 무슨 일이 일어나는지만 궁금하다면 "백그라운드 탭은 속도가 제한되고, 얼고, 그려지지 않는다"만 알면 충분하다. 8절 "Chrome의 제한을 그냥 끄면 안 되나?"로 바로 넘어가도 뒤의 내용을 이해하는 데 지장이 없다.
1. 숨겨진 페이지의 사슬형 타이머는 유예 시간이 지나면 1분에 한 번만 깨어날 수 있다. Chrome 소스는 이것을 intensive wake-up throttling(집중 깨우기 제한)이라고 부른다. 무슨 뜻일까? 앞에서 말한 스스로 맞추는 알람이다. 타이머가 울리면 그 콜백이 다음 타이머를 맞춘다. Chrome은 이 사슬이 몇 단계나 이어졌는지 세고, 7단계부터는 페이지가 한동안 숨겨져 있었다면 그런 타이머를 1분에 한 번만 울리게 한다. 카운트다운이 정확히 그렇게 작성되어 있어서 걸린다. 서버의 답을 받은 뒤에 맞춘 타이머는 다시 1단계부터 세므로, 내보내기와 상담 체크인은 영향을 받지 않는다. 페이지가 숨겨진 뒤의 유예 시간은 보통 60초이고, 에이전트가 백그라운드에 열어서 한 번도 표시된 적 없는 탭도 60초를 받는다. 다른 탭으로 전환하기, 창이 완전히 가려지기, 창 최소화하기는 모두 숨겨진 것으로 친다. 이보다 약한 제한도 두 가지 있다. 어떤 타이머도 1초에 한 번보다 자주 깨어나지 못하고, 숨겨진 지 10초가 지나면 모든 타이머 콜백을 합쳐 CPU의 1%만 쓸 수 있다. 뒤의 것은 콜백에서 무거운 작업을 하는 페이지에만 해당한다. (third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc; 사슬 단계는 third_party/blink/renderer/core/scheduler/dom_timer.cc)
2. 탭 그룹이 접히면 그 안의 탭이 언다. 그룹이 접히는 순간 Chrome은 그 안의 모든 탭에 '동결' 표를 던진다. 최근 5분 안에 표시된 탭은 보호되고, 한 번도 표시된 적 없는 탭은 그 자리에서 언다. 언다는 건 페이지의 코드가 하나도 빠짐없이 멈춘다는 뜻이다. 느려지는 정도로 끝나지 않고 아예 움직이지 않는다. 그 서랍의 전원을 끊어 버리는 것과 같다. (chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc가 표를 던지고, components/performance_manager/freezing/freezing_policy.cc가 결정한다)
3. Claude in Chrome은 20초쯤 쉬면 자기 탭 그룹을 접는다. 창 맨 앞에 있는 탭이 자기 탭이 아닐 때만 그렇고, 다음에 할 일이 생기면 확장 프로그램이 먼저 그룹을 펼친다. 규칙 3에 규칙 2를 더한 것이 앞에서 본 "20초 뒤 완전히 멈춤"이다. 확장 프로그램이 그룹을 접고, Chrome이 그 안의 탭을 얼린다.
4. 확장 프로그램은 작업 중인 탭이 "누가 나를 보고 있다"고 믿게 만든다. 확장 프로그램은 동작하기 전마다 디버깅 프로토콜로 포커스 에뮬레이션(Emulation.setFocusEmulationEnabled)이라는 스위치를 켠다. 이건 무슨 일을 할까? Chrome에 "이 탭을 누가 보고 있다"고 알려 준다. 그러면 페이지의 visibilityState가 visible이 되고, 타이머도 숨겨진 페이지에 걸리는 제한을 더는 받지 않는다. 창 전체가 최소화되어 있어도 그렇다. 동작이 끝나고 20초쯤 지나면 확장 프로그램은 이 스위치를 다시 끈다.
규칙 3과 4를 함께 보면 이상한 현상 하나도 설명된다. 그룹이 접힐 때 에이전트가 마지막으로 작업한 탭은 왜 가끔 얼지 않을까? 나는 확장 프로그램이 일부러 그 탭을 보호한다고 생각했는데, 코드를 보니 순전히 우연이었다. 그룹이 접히면 Chrome은 그 안의 탭마다 동결 명령을 보낸다. 에이전트가 마지막으로 만진 탭은 그 순간 포커스 에뮬레이션이 아직 켜져 있어서, 누가 보고 있다고 믿고 명령을 거부한다. 그런데 Chrome 쪽은 거부당한 걸 알아채지 못하고 그 탭을 어쨌든 "동결됨"으로 기록하고는, 다시는 명령을 보내지 않는다. 포커스 에뮬레이션이 꺼지고 탭이 정말로 안 보이게 되어도, 다시 얼리러 오는 사람은 없다.
다르게 말해 보자. 기숙사 사감이 밤에 소등 점검을 돈다. 여러분이 방 안에서 "아직 사람 있어요"라고 외치자, 사감은 장부에 "소등 완료"라고 적고 지나가서 다시는 오지 않는다. 그러면 여러분이 잠든 뒤에도 불은 밤새 켜져 있다. 이 탭이 깨어 있는 건 오로지 "그룹이 접힘"과 "포커스 에뮬레이션이 꺼짐"이 우연히 그 순서로 일어났기 때문이고, 확장 프로그램도 Chrome도 그렇게 설계한 적이 없다. 앞에서 에이전트가 A에서 B로 옮겨 갔을 때 A는 반대 순서를 만났다. A의 포커스 에뮬레이션이 먼저 꺼졌으니 그룹이 접힐 때 A는 이미 안 보이는 상태였고, 동결 명령은 도착하자마자 적용됐다.
5. 실제로 화면에 그려지지 않는 페이지는 프레임이 1초에 하나로 줄어든다. 포커스 에뮬레이션은 페이지를 속여 누가 보고 있다고 믿게 할 수는 있지만, 화면을 그리는 부분까지 속이지는 못한다. Chrome에는 viz라는 합성(compositing) 서비스가 있어서, 디스플레이 주기에 맞춰 각 탭에 "다음 프레임을 그리기 시작하라"는 신호(BeginFrame)를 보낸다. 어떤 탭의 프레임이 3개 연속으로 어느 창에도 실제로 그려지지 않으면, 그 신호는 1초에 한 번으로 떨어진다. 소스 주석에도 "we throttle BeginFrames to 1 per second"(BeginFrame을 1초에 1번으로 제한한다)라고 분명히 적혀 있다(components/viz/service/frame_sinks/compositor_frame_sink_support.h, kUndrawnFrameLimit = 3). 그래서 다른 탭 뒤에 있거나 최소화된 창 안에 있는 탭은, 타이머가 정상적으로 돌아가더라도 requestAnimationFrame(웹 페이지가 애니메이션을 그릴 때 쓰는 함수)을 1초에 한두 번밖에 실행하지 못한다. 무대를 찍는 카메라와 같다. 배우들은 계속 연기하지만, 카메라는 중계를 보는 사람이 없다는 걸 알아채고 1초에 한 장만 찍는다. 내가 측정한 초당 4프레임 미만 가운데 더 그려진 두세 프레임은, 아마 확장 프로그램이 스크린샷을 찍으면서 덩달아 그려진 것일 테다.
6. 가려지거나 최소화된 창도 안 보이는 것으로 친다. Windows에서 Chrome은 창이 다른 창에 완전히 가려졌는지 스스로 계산하고, 가려졌으면 그 안의 탭을 숨겨진 것으로 취급한다(ui/aura/native_window_occlusion_tracker_win.cc, 기본값 켜짐). 창이 최소화되면 그 창의 합성 영역 전체가 0×0이 된다(desktop_window_tree_host_win.cc).
7. 백그라운드 렌더러 프로세스도 강등된다. 어떤 렌더러 프로세스에 보이는 탭이 하나도 없으면, Chrome은 그 프로세스를 가장 낮은 우선순위로 내리고 Windows에 EcoQoS를 요청한다. EcoQoS는 속도를 희생하는 대신 그 프로세스를 CPU의 가장 전력 효율적인 주파수로 돌리고, 작업을 효율 코어에 올리는 방식이다(base/process/process_win.cc, kUseEcoQoSForBackgroundProcess 기본값 켜짐). 이 규칙은 창이 실제로 보이는지를 보기 때문에 포커스 에뮬레이션으로는 속일 수 없다.
일곱 규칙 하나하나는 그 자체로 합리적이지만, 겹쳐 놓으면 에이전트의 탭은 곤란한 처지에 놓인다. 페이지는 자기가 보인다고 생각하는데 타이머는 제한받을 수 있다. 에이전트가 방금 작업한 탭인데 잠시 뒤 얼 수 있다. 얼지는 않았는데 화면이 거의 움직이지 않는다. 어느 탭이 깨어 있고 어느 탭이 잠들었는지는 확장 프로그램을 만든 사람들조차 말하지 못할 수 있다. 결국 같은 이야기로 돌아온다. 브라우저의 규칙은 사람을 위해 만들어졌다.
8. Chrome의 제한을 그냥 끄면 안 되나?
Chrome의 규칙이 문제라면 실행 플래그로 꺼 버리면 되지 않느냐고 생각할 수 있다. 일부는 된다. --disable-background-timer-throttling, --intensive-wake-up-throttling-policy=0, --disable-renderer-backgrounding, --disable-backgrounding-occluded-windows는 타이머 속도 제한과 프로세스 강등을 끈다. 하지만 프레임 규칙은 끌 수 없다. 화면에 그려지지 않는 탭은 타이머 속도 제한을 껐다고 해서 정상적인 프레임을 되찾지 못하니, 반쯤 올라간 숫자를 읽는 일은 여전히 일어난다.
9. Embiody에서 같은 테스트를 해 보면
우리는 AI 에이전트를 위해 만든 Windows 브라우저 Embiody를 만들고 있다. 에이전트는 이 브라우저를 위해 만든 MCP 서버 BrowserDo를 통해 그 안에서 일한다. Claude Code와 Codex는 명령어 하나로, Cursor와 Claude Desktop은 설정 몇 줄로 연결된다. AI 탭 기능은 7월의 그 오후에서 시작됐다. 나는 내 일을 계속하는 동안 에이전트가 여러 일을 한꺼번에 해 주길 바랐다.
그래서 위의 테스트를 전부 같은 조건으로 Embiody에서 돌렸다. 브라우저만 Embiody로, 도구만 BrowserDo로 바꿨다. 결과는 이렇다.
| 테스트 | Chrome + Claude in Chrome | Embiody + BrowserDo |
|---|---|---|
| 작업 A와 B를 동시에, 창 최소화, 에이전트는 A만 작업: B의 90초 기다림에 걸린 시간 | 407초, 384초 | 90초 |
| 창은 화면에 있고 테스트 페이지는 다른 탭 뒤, 에이전트가 내내 작업: 프레임 | 초당 4프레임 미만 | 앞에 있는 탭만큼 부드러움 |
| 백그라운드 통계 페이지가 3초 동안 0에서 98,765까지 올라가고, 에이전트가 10초 뒤 읽음 | 73,795, 71,215, 69,619 | 98,765 |
| 창은 화면에 있고 맨 앞은 여러분의 탭, 에이전트가 상담 페이지를 1분 30초 비웠다가 답장 | 채팅 종료, 답장 전송 불가 | 연결 유지, 답장 전송됨 |
Embiody에서는 작업 B가 다른 탭 뒤에서, 아무도 건드리지 않은 채, 최소화된 창 안에 있어도 제시간에 끝난다. 에이전트가 백그라운드에서 작업하는 페이지는 계속 그려지고, 통계 숫자는 처음 읽을 때 바로 맞게 읽히며, 상담 채팅은 연결이 유지된다. 다만 이건 에이전트가 쓰고 있는 탭에만 해당한다. 여러분이 직접 연 탭은 평소의 절전 규칙대로 백그라운드에서 여전히 속도가 제한되니, 브라우저에 에이전트가 있다고 해서 여러분의 탭이 전력을 더 쓰지는 않는다. 상자 속 고양이는 계속 깨어 있다. 공정하게 말하자면, 이번 테스트는 Windows 컴퓨터 한 대에서, Embiody는 테스트마다 1~2회 돌린 것이라 대규모 테스트와는 거리가 멀다. 하지만 적어도 이 시나리오들에서는 차이가 분명하다.
하나 더 분명히 해 둘 것이 있다. 이 문제들은 Claude in Chrome만의 문제가 아니다. 어떤 확장 프로그램이나 자동화 도구를 쓰든, Chrome에서 일하는 에이전트는 Chrome의 규칙을 따라야 한다. 맨 처음 카운트다운 테스트에서도 내가 손으로 연 탭이 Claude의 탭과 똑같이 8분 만에 390초 넘게 뒤처졌다. 이번에 마주치지 않은 규칙도 두 가지 있다. 컴퓨터 메모리가 부족하면 Chrome은 가장 오랫동안 보지 않은 백그라운드 탭을 메모리에서 내리고, 돌아오면 다시 불러온다. 그리고 노트북 전원을 뽑은 채 배터리가 20% 아래로 떨어지면, CPU를 꽤 쓰는 백그라운드 탭이 언다. 사람이라면 자리를 비웠다가 이런 일을 겪어도 돌아와서 새로고침하면 그만이다. 하지만 오후 내내 여러 페이지를 동시에 맡아 돌아가는 에이전트는 언젠가 반드시 이런 일을 겪는다.
10. AI에게는 자기만의 브라우저가 필요하다
AI로 일한 지 몇 년이 지나면서 한 가지는 점점 더 확신하게 됐다. AI에게는 자기만의 브라우저가 필요하고, Chrome으로 버티는 건 임시방편이다.
Chrome이 일을 못 한다는 말은 아니다. 이 규칙들은 화면 앞에 앉은 사람이 더 편하도록 오랜 세월 다듬어진 것이다. 보이지 않는 탭은 자원을 덜 써야 하고, 아무도 보지 않는 애니메이션은 그릴 필요가 없고, 오래 쓰지 않은 페이지는 얼리거나 아예 메모리에서 내려야 한다. 확장 프로그램이 할 수 있는 건 그 규칙 위에 한 겹을 더 얹는 것뿐이다. 포커스 에뮬레이션으로 페이지가 누가 보고 있다고 믿게 하거나, 탭 그룹을 접어서 에이전트의 탭이 여러분을 방해하지 않게 하는 식이다. 하지만 규칙은 Chrome의 것이고, Chrome의 구조는 사람을 위해 설계됐다. 근본부터 바꾸지 않는 한 확장 프로그램은 땜질밖에 할 수 없다.
앞에서 본 그 탭, 사감이 장부에 "소등 완료"라고 적어 둔 탭이 바로 땜질이 낳은 결과다. 두 가지 일이 우연히 특정한 순서로 일어났기 때문에 깨어 있을 뿐이다. Chrome 새 버전이 나오면 그 순서는 언제든 바뀔 수 있고, 이런 우연은 피할 수도 예측할 수도 없다. Chrome은 애초에 에이전트를 위해 설계된 적이 없기 때문이다.
우연에 기대지 않으려면 브라우저 자체의 규칙이 에이전트를 고려해야 한다. 사람에게는 탭이 보이느냐 마느냐가 그 탭이 계속 자원을 써도 되느냐를 정한다. 에이전트에게는 아무도 보지 않는 탭이 멈출 수 없는 일을 여러분 대신 하는 중일 수 있고, 그런 탭은 화면 앞에 누가 있든 없든 계속 일해야 한다. 이건 브라우저 엔진 안에서만 정할 수 있고, Embiody의 AI 탭이 바로 이 원칙 위에 만들어졌다.
(Embiody: 테스트마다 1~2회, 2026년 11월 11~12일, 같은 컴퓨터.)
테스트하지 못한 것
- Windows 컴퓨터 한 대, Chrome 버전 하나로만 테스트했다. 7월에 손으로 테스트할 때는 5분이 지나서야 느려지는 게 눈에 띄었던 것으로 기억하는데, 이번(Chrome 157)에는 1분쯤이었다. Chrome이 바뀐 건지 내 기억이 틀린 건지는 모르겠다.
- Mac과 Linux는 테스트하지 않았고, 메모리 절약 모드(Memory Saver)를 켠 상태도 테스트하지 않았다.
- 메모리가 부족할 때 탭을 메모리에서 내리는 것과 배터리가 부족할 때 탭을 얼리는 것은 소스로만 확인했고, 직접 측정하지는 않았다.
2분 만에 직접 해 보기
https://embiody.com/lab/background-tab/ 을 열어 보자. 열자마자 15분짜리 카운트다운이 시작된다. 다른 탭으로 전환하고(창을 다른 창으로 가리거나 최소화해도 된다) 2분 뒤에 돌아와서 "Behind by"(뒤처진 시간) 항목을 보면, 자리를 비운 동안 카운트다운이 잃어버린 초가 나온다. 0 s라면 페이지가 제시간에 계속 돌았다는 뜻이다. 테스트 페이지는 영어로 되어 있다.
마치며
Chrome이 언젠가 에이전트를 위해 이 규칙들을 바꿀지는 모르겠다. Chrome에는 그럴 만한 이유가 있다. 전력을 아끼고, 메모리를 아끼고, 앞에 있는 화면을 매끄럽게 유지하는 건 브라우저가 마땅히 해야 할 일이다. 다만 브라우저는 화면 앞에 사람이 앉아 한 번에 탭 하나를 보고 있다고 가정했는데, 이제는 화면 앞에 아무도 없고, 탭 뒤에서 에이전트가 여러 페이지를 동시에 돌보고 있을 수 있다.
지켜보지 않으면 일하지 않는다. 그런데 에이전트의 일은 바로 여러분이 지켜보지 않는 동안 일어나는 일이다.