에이전트에게 브라우저를 맡길 때 만나는 두 개의 벽#

2026-07-25

에이전트에게 브라우저를 맡길 때

코딩 에이전트에게 일을 시킬 때 필자가 중요하게 여기는 원칙 하나는, 코드를 고쳤으면 결과를 에이전트가 직접 확인하게 하는 것입니다. 웹 프로젝트라면 브라우저를 띄워 화면을 보게 합니다. 이를 위해 chrome-devtools-mcpPlaywright MCP 같은 MCP(Model Context Protocol, 에이전트에 외부 도구를 연결하는 표준) 서버를 사용합니다. 에이전트가 크롬을 실행하고, 페이지를 열고, 클릭하고, 스크린샷을 찍어 자기 작업을 스스로 검증하는 구조입니다.

그런데 이 워크플로우를 굴리다 보면 두 개의 벽에 부딪힙니다. 하나는 에이전트 세션을 여러 개 병행할 때 크롬이 충돌하는 문제이고, 다른 하나는 에이전트가 띄운 크롬에서는 구글 로그인이 차단되는 문제입니다. 이 글은 두 문제의 원인을 파고들어 각각의 해법을 정리한 기록입니다. 지난 글에서 다뤘듯 필자는 에이전트 세션 여러 개를 병행하는 방식으로 일하므로, 둘 다 피해 갈 수 없는 문제였습니다.

첫 번째 벽: “크롬이 이미 실행 중입니다”#

세션 A가 크롬으로 검증 작업을 하는 중에 세션 B에게도 브라우저 검증을 시키면, B는 크롬이 이미 실행 중이라며 거절하거나, 심하면 A가 쓰던 크롬을 종료하고 새로 띄워버립니다. 병행 작업이 브라우저 검증 단계에서 직렬화되는 셈입니다.

원인은 두 가지 사실이 겹친 데 있습니다.

첫째, 크롬은 하나의 프로필 디렉토리(user-data-dir)당 브라우저 프로세스를 하나만 허용합니다. 같은 프로필로 두 번째 실행을 시도하면 잠금에 걸려 실패하거나 기존 프로세스에 위임됩니다.

둘째, 두 MCP 서버 모두 기본값이 공유 영속 프로필입니다. chrome-devtools-mcp는 캐시 디렉토리 아래 고정 경로의 프로필을 모든 인스턴스가 공유하고, Playwright MCP도 기본적으로 영속 프로필을 사용하며 공식 문서에 “영속 프로필은 한 번에 하나의 브라우저 인스턴스만 사용할 수 있다"고 명시되어 있습니다.

에이전트 세션마다 MCP 서버 프로세스는 따로 뜨지만, 그 서버들이 바라보는 크롬 프로필이 전역으로 하나뿐이니 충돌은 필연입니다. 해법은 간단하게도 옵션 하나입니다. 두 도구 모두 지원하는 --isolated 플래그를 붙이면, 서버 인스턴스마다 임시 프로필을 만들어 각자의 크롬을 띄우고 종료 시 정리합니다.

"chrome-devtools": {
  "command": "npx",
  "args": ["chrome-devtools-mcp@latest", "--isolated"]
},
"playwright": {
  "command": "npx",
  "args": ["@playwright/mcp@latest", "--isolated"]
}

이것으로 세션 수 제한 없이 병행 검증이 됩니다. 대신 임시 프로필이므로 로그인과 쿠키가 브라우저 종료와 함께 사라집니다. 로컬 개발 서버 화면을 확인하는 용도라면 아무 문제가 없지만, 이 트레이드오프가 곧바로 두 번째 벽으로 이어집니다.

두 번째 벽: “이 브라우저 또는 앱은 안전하지 않을 수 있습니다”#

에이전트가 띄운 크롬에서 구글 로그인을 시도하면 이 메시지와 함께 차단됩니다. 브라우저 안에서 사람이 직접 아이디와 비밀번호를 타이핑해도 마찬가지입니다. 구글 계정이 필요한 페이지를 에이전트에게 검증시키려던 계획이 여기서 막힙니다.

원인은 자동화 표식입니다. 두 MCP 서버가 크롬을 실행할 때는 자동화 제어용 플래그(--enable-automation)가 붙고, 이 상태의 브라우저는 자바스크립트에서 navigator.webdriver 값이 참이 되는 등 “자동화 도구가 제어 중"이라는 신호를 내보냅니다. 구글 로그인 서버는 계정 탈취 봇을 막기 위해 이런 신호가 감지되는 브라우저의 로그인 시도를 거부합니다(구글 공식 안내). 즉 크롬 자체의 문제가 아니라, 자동화 플래그가 붙은 크롬을 구글이 신뢰하지 않는 것입니다.

돌파구는 차단의 정확한 범위에 있습니다. 조사해 보니 차단되는 것은 “로그인 시도"라는 행위뿐이고, 이미 로그인된 세션 쿠키는 자동화 브라우저에서도 정상 동작합니다. 그렇다면 로그인만 자동화 플래그가 없는 환경에서 미리 해두고, 에이전트는 그 결과물(쿠키가 담긴 프로필)만 물려받으면 됩니다.

attach 패턴#

여기서 발상을 뒤집습니다. MCP 서버가 크롬을 실행하게 하는 대신, 사람이 보통의 크롬을 직접 띄워두고 MCP 서버는 거기에 접속(attach)만 하게 하는 것입니다.

open -na "Google Chrome" --args \
  --remote-debugging-port=9222 \
  --user-data-dir="$HOME/.cache/cdp-profiles/attach-9222"

이렇게 띄운 크롬은 자동화 플래그가 없는 보통 크롬이므로 구글 로그인이 정상적으로 됩니다. 로그인 정보는 전용 프로필에 저장되므로 최초 한 번만 로그인하면 됩니다. 대신 --remote-debugging-port로 CDP(Chrome DevTools Protocol, 크롬을 외부에서 제어하는 프로토콜) 포트를 열어두었기 때문에, MCP 서버가 이 포트로 연결해 페이지 이동·클릭·스크린샷을 모두 수행할 수 있습니다. 연결 옵션의 이름만 도구별로 다릅니다.

"chrome-devtools-attach": {
  "command": "npx",
  "args": ["chrome-devtools-mcp@latest", "--browserUrl=http://127.0.0.1:9222"]
},
"playwright-attach": {
  "command": "npx",
  "args": ["@playwright/mcp@latest", "--cdp-endpoint", "http://127.0.0.1:9222"]
}

주의할 점이 하나 있습니다. 크롬 136부터는 보안상의 이유로 일상용 기본 프로필에서는 원격 디버깅 포트 옵션이 무시됩니다(Chrome 공식 블로그). 위 명령처럼 반드시 별도의 --user-data-dir를 지정해야 하는데, 이는 제약이라기보다 올바른 방향입니다. 뒤에서 다시 이야기하겠지만, 평소 쓰는 브라우저를 에이전트에 물리는 것은 애초에 피해야 할 일이기 때문입니다.

운용으로 다듬기#

해법의 뼈대는 나왔지만, 실제로 굴리려면 두 가지를 더 다듬어야 했습니다.

크롬 실행을 누가 챙길 것인가. attach 방식은 크롬이 먼저 떠 있어야 동작합니다. 매번 사람이 실행 명령을 기억해 치는 것은 번거로우므로, 이 확인 자체를 에이전트에게 맡겼습니다. “디버그 포트가 응답하는지 확인하고, 없으면 전용 프로필로 크롬을 실행한 뒤 attach하라"는 절차를 프로젝트 스킬(에이전트가 특정 작업에서 따르는 절차 문서)로 만들어 두면, 사람은 “로그인 크롬으로 이 페이지 검증해줘"라고 말하는 것으로 끝납니다. 마침 두 MCP 서버 모두 세션 시작 시점이 아니라 첫 도구 호출 시점에 브라우저와 연결하므로, 세션 도중에 크롬을 띄워도 attach가 됩니다.

탭을 어떻게 나눌 것인가. attach용 크롬은 하나이므로 여러 세션이 공유하게 되는데, 다행히 CDP 포트는 다중 클라이언트 접속을 허용하고, “현재 조작 대상 페이지"라는 상태도 MCP 서버 인스턴스별로 따로 관리됩니다. 조작이 화면에 보이는 활성 탭에만 가능한 것도 아니어서, 백그라운드 탭에서도 페이지 이동과 클릭, 스냅샷이 모두 동작합니다. 그래서 “작업 시작 시 자기 전용 탭을 새로 만들고, 그 탭에서만 작업하고, 끝나면 자기 탭만 닫는다"는 규율을 스킬에 넣는 것으로 세션 간 간섭을 정리했습니다. 다만 크롬이 백그라운드 탭의 렌더링을 절전 목적으로 제한하므로, 애니메이션처럼 타이밍에 민감한 검증은 부정확할 수 있다는 한계는 남습니다.

최종 구성은 이렇습니다. 용도에 따라 서버를 골라 쓰는 사분면이 만들어졌습니다.

로그인 불필요로그인 필요
Chrome DevToolschrome-devtools (–isolated)chrome-devtools-attach
Playwrightplaywright (–isolated)playwright-attach

병행 세션의 일반 검증은 왼쪽 열로 제한 없이 돌리고, 구글 계정이 필요한 검증만 오른쪽 열에서 공유 크롬 + 탭 분리로 처리합니다.

보안에 대한 단상#

이 구성에서 의도적으로 지킨 경계가 하나 있습니다. 에이전트에게 물리는 브라우저는 항상 전용 프로필이라는 것입니다. attach용 프로필에는 검증에 필요한 계정만 로그인해 둡니다. 평소 쓰는 브라우저에는 메일, 클라우드 저장소, 결제 수단까지 온갖 세션이 살아 있는데, 거기에 에이전트 제어권을 주는 것은 노출 범위를 불필요하게 넓히는 일입니다. 크롬 136의 기본 프로필 디버깅 차단도 같은 문제의식에서 나온 조치입니다. 에이전트의 능력을 넓혀줄수록, 그 능력이 미치는 범위는 좁게 유지하는 것이 균형이라고 생각합니다.

마치며#

돌아보면 두 벽 모두 근본 원인은 같았습니다. 브라우저 자동화 도구들의 기본값은 “사람 한 명, 세션 하나"를 가정하고 만들어져 있다는 것입니다. 프로필을 전역으로 하나만 두는 것도, 자동화 브라우저에서 사람이 로그인할 일이 없으리라 보는 것도 그 가정 위에서는 자연스럽습니다. 그런데 에이전트 여러 개가 각자 브라우저를 쥐고 일하는 순간 가정이 깨지고, 기본값들이 일제히 벽이 되어 나타납니다.

에이전트 시대의 도구 정비란 결국 이런 낡은 가정을 하나씩 찾아 갱신하는 일인지도 모릅니다. 이번에는 브라우저였지만, 같은 종류의 벽이 다른 도구에서도 기다리고 있을 것입니다. 부딪히면 또 원인을 파고, 정리해 두겠습니다.