← 뉴스레터

2026-06-11

좀비 브라우저가 문을 잠그고 떠났다

에러 메시지는 증상을 말하지, 원인을 말하지 않는다. 그 사실을 잊고 있을 때, 잠금 파일 하나가 나를 30분 가까이 묶어 뒀다.


그날 밤, 마지막으로 해야 할 일이 하나 남아 있었다. 구글 플레이 콘솔에 들어가 개발자 계정의 연락처 이메일을 회사 메일로 바꾸는 것이었다. 앞선 여덟 개 앱의 저장소와 개인정보처리방침은 오후 내내 정리했고, 이 한 칸만 남은 상태였다. 플레이 콘솔은 API로 건드릴 수 없는 필드라 직접 브라우저로 들어가야 했다.

자동화용 브라우저를 여는 명령을 실행했다. 그러자 바로 에러가 떴다.

Browser is already in use for .../mcp-chrome-..., use --isolated

프로세스는 없었고, 잠금은 있었다

처음 든 생각은 “이전 작업에서 브라우저가 안 닫혔나” 였다. 프로세스 목록을 살펴봤다. Chrome 여러 개가 살아 있었다 — 자동화 전용 프로필을 물고 도는 프로세스들이었다. 그런데 조금 더 뜯어보니 상황이 달랐다. 살아 있는 프로세스 중 어느 것도 문제의 프로필 디렉터리를 잡고 있지 않았다.

프로필 디렉터리 안을 직접 열어봤다. 거기 SingletonLock 이라는 이름의 파일이 있었다. Chrome 계열 브라우저는 같은 프로필을 두 곳에서 동시에 열지 못하게 하기 위해, 실행할 때 이 잠금 파일을 만들고 닫을 때 지운다. 정상이라면 브라우저가 닫히는 순간 사라지는 파일이다.

그런데 그 파일이 남아 있었다. 이전 세션이 40% 컨텍스트 한도에 걸려 강제로 닫히면서, 자기가 열어 둔 브라우저를 정상적으로 종료하지 못하고 떠난 것이었다. 프로세스는 사라졌지만 잠금 파일은 디스크에 그대로였다. 다음 세션이 와서 브라우저를 열려 하자, Chrome은 그 파일을 보고 “이미 누가 쓰고 있다” 고 판단해 거부했다.

죽은 세션이 문을 잠가 두고 떠난 셈이었다.

에러 메시지가 숨긴 것

“Browser is already in use” 는 틀린 말이 아니었다. 잠금 파일 기준으로는 사실이었다. 그런데 그 말이 내게 떠올리게 한 그림은 “지금 이 순간 누군가 브라우저를 쓰고 있다” 는 것이었다. 실제로는 “한때 누군가가 썼고, 그 흔적이 남아 있다” 였지만.

에러 메시지는 현재 상태를 묘사했고, 나는 그 묘사를 현재 원인으로 읽었다. 그 차이 때문에 한동안 엉뚱한 방향을 뒤졌다. 살아 있는 프로세스를 찾고, 그걸 종료하려 했다. 실제로 몇 개는 껐다. 그런데 에러는 사라지지 않았다.

멈추고 다시 물었다. “브라우저가 진짜 지금 열려 있는가, 아니면 이전에 열렸던 흔적이 남아 있는 것인가.” 그 질문이 잠금 파일 쪽으로 시선을 돌렸다.

파일 하나를 지우고, 열었다

SingletonLock 파일을 삭제했다. 그리고 브라우저를 다시 열었다. 이번엔 에러가 없었다.

로그인 상태도 확인했다. 구글 계정 세션은 프로필 디렉터리 안의 쿠키 파일에 저장된다. 잠금 파일은 그 옆에 있는 별개의 파일이고, 쿠키와는 무관하다. 프로세스를 강제 종료해도 쿠키는 손대지 않고, 잠금 파일만 지워도 쿠키는 그대로다. 브라우저가 열리자 구글 플레이 콘솔에 이미 로그인된 상태로 들어갔다. 다시 로그인할 필요가 없었다.

그 뒤는 금방이었다. 연락처 이메일을 회사 메일로 바꾸고 저장하자 다이얼로그 하나가 떴다 — “이 변경사항은 즉시 게시됩니다.” 심사나 재제출 없이, 그냥 바로 반영된다는 뜻이었다. 확인을 눌렀다.

잠금 파일이라는 메커니즘

이 구조 자체는 합리적이다. 같은 프로필을 두 인스턴스가 동시에 열면 설정과 쿠키가 충돌한다. 그걸 막기 위해 “열 때 파일을 만들고, 닫을 때 파일을 지운다” 는 약속이 있는 것이다. 정상 종료라면 잠금 파일은 흔적도 없이 사라진다.

문제는 비정상 종료다. 프로세스가 갑자기 사라지면, 닫을 때 해야 할 청소를 못 한다. 잠금 파일이 남는다. 운영체제는 그 프로세스가 사라진 걸 알지만, 파일 시스템의 잠금 파일까지 자동으로 치워 주지는 않는다. 그 불일치가 “죽었는데 잠근 채로 떠난” 상태를 만든다.

이런 패턴은 Chrome 만의 이야기가 아니다. 데이터베이스 잠금 파일, 편집기가 만드는 스왑 파일, 빌드 도구의 PID 파일 — 형태는 달라도 “실행 중에 만들고 종료 시 지우는” 파일들은 어디서나 같은 문제를 안고 있다. 비정상 종료 앞에서 청소는 항상 절반쯤 남는다.

그래서 배운 것

에러 메시지를 읽을 때, 그것이 지금 일어나는 일을 말하는지 과거에 일어난 일의 잔재를 말하는지를 먼저 가려야 한다. “이미 사용 중” 은 현재 사용 중이라는 뜻일 수도 있고, 지난번 사용이 정리되지 않았다는 뜻일 수도 있다. 두 상황이 만드는 에러 메시지가 똑같이 생겼다.

프로세스를 찾아도 없으면, 그 다음 질문은 “프로세스가 남기고 간 파일이 있는가” 다. 파일이 원인이라면, 해법도 파일 하나를 지우는 것이다. 무거운 재설치나 전체 초기화가 아니라.

에러 메시지는 증상을 기술한다. 원인은 그 뒤에 있다.


이 글은 Playwright 기반 브라우저 자동화 중 세션 강제 종료로 발생한 SingletonLock 잔류 문제와 복구 과정을 일반 독자용으로 풀어 쓴 기록입니다.

— 강대종