브라우저 자동화는 세 세대를 거쳐 발전했습니다. 각 세대는 이전 세대의 병목을 해결하는 동시에 새로운 병목을 다른 곳으로 옮겼습니다. 도구 이름을 외우는 것보다 각 세대가 남긴 문제를 이해하는 편이 더 유용합니다.
브라우저 자동화는 20년 넘게 사용되어 왔고, 그동안 주된 방식은 세 세대에 걸쳐 바뀌었습니다. 흥미로운 점은 각 세대가 서로 다른 종류의 문제를 해결하며, 하나의 병목을 해소하면 그 병목이 다시 다른 곳으로 이동한다는 것입니다.

1세대: 운영체제 수준에서 사람이 마우스를 움직이는 것처럼 흉내 내기
초기의 자동화는 사실 브라우저 안에서 이루어지지 않았습니다. 운영체제 수준에서 스크립트가 마우스를 움직이고 키를 눌렀으며, 브라우저는 그 입력을 수동적으로 받는 역할만 했습니다.
장점은 범용성이었습니다. 화면에 보이는 것이라면 웹페이지, 클라이언트 애플리케이션, 오래된 데스크톱 소프트웨어를 가리지 않고 조작할 수 있었고, 브라우저가 별도 인터페이스를 제공할 필요도 없었습니다. 대가는 분명했습니다. 스크립트는 화면 좌표를 기준으로 동작하므로 해상도, 시스템 배율, 창 위치 중 하나만 바뀌어도 같은 동작이 엉뚱한 곳을 클릭할 수 있었습니다. 페이지 로딩이 끝났는지도 알 수 없어 고정 대기 시간에 의존해야 했습니다. 병렬 실행은 더 어려웠습니다. 한 대의 머신에는 마우스와 키보드가 한 세트뿐이므로 환경이 열 개라면 머신도 열 대가 필요했습니다.
이 세대가 남긴 문제는 간단했습니다. 페이지를 볼 수 없다는 것입니다.
2세대: 화면을 우회해 브라우저와 직접 통신하기
WebDriver의 등장은 자동화를 픽셀 수준에서 요소 수준으로 끌어올렸습니다. 화면의 800번째 픽셀 위치가 아니라 페이지 안의 특정 요소를 찾게 된 것입니다. 같은 코드로 여러 브라우저를 제어할 수 있고 다양한 언어로 작성할 수 있었으며, 이 점이 나중에 테스트 분야의 표준으로 자리 잡은 이유이기도 합니다.
이후 브라우저 디버깅 프로토콜을 기반으로 한 방식이 이 경로를 더 발전시켰습니다. Puppeteer와 Playwright 계열은 브라우저 엔진과 직접 통신해 페이지 내부 상태를 가져올 수 있습니다. 요소가 준비될 때까지 자동으로 기다리고, 요청을 가로채거나 다시 작성하고, 이미 실행 중인 브라우저 인스턴스에 연결하고, headless로 실행하며, 여러 context를 병렬로 열 수 있습니다. 지금은 당연하게 여기는 많은 기능이 이 단계에서 완성되었습니다.
이 세대는 제어와 안정성을 해결했지만 두 가지 다른 문제를 남겼습니다. 첫째, 스크립트는 여전히 사람이 고정해서 작성했습니다. 페이지 구조가 바뀌거나 selector가 깨지면 다시 코드를 수정해야 했고, 유지보수 비용은 프로젝트 규모와 함께 늘었습니다. 둘째, 더 근본적인 문제는 어떻게 조작할지는 다루지만 누가 조작하는 것처럼 보이는지는 다루지 않는다는 점입니다. 프로토콜 직접 연결은 제어를 더 정밀하게 하지만, 통신 방식을 바꾼다고 자동화의 흔적이 사라지는 것은 아닙니다. 아무리 안정적으로 실행되는 스크립트라도 외부에서는 여전히 스크립트처럼 보일 수 있습니다.
3세대: 사람이 단계별로 작성하지 않아도 되고, 문제의 위치도 다시 바뀌다
3세대의 변화는 제어 방식이 아니라 의사결정 방식에 있습니다. 앞선 두 세대에서는 어떤 버튼을 누르고, 어떤 필드를 채우며, 어떤 순서로 진행할지를 사람이 하나씩 명확히 적어야 했습니다. 모델 기반 세대에서는 목표만 주면 모델이 경로를 스스로 계획하고, 페이지가 개편되어도 새로운 진입점을 다시 찾을 수 있습니다.
그 결과 selector를 어떻게 작성할지, 얼마나 기다릴지와 같은 예전의 세세한 문제는 점차 덜 치명적이 됩니다. 하지만 새로운 문제가 곧바로 나타납니다.
핵심은 모델 자체가 웹페이지에 접속하는 것이 아니라는 점입니다. 실제로 페이지를 열고, 리소스를 로드하고, 로그인 상태를 유지하는 것은 여전히 브라우저입니다. 그래서 작업이 불안정해질 때 원인은 모델이 잘못 판단해서라기보다 그 아래의 실행 환경에 있는 경우가 많습니다. 여러 작업이 하나의 브라우저를 공유해 Cookie와 캐시를 서로 오염시키고, fingerprint 특성이 지나치게 비슷해 플랫폼에서는 모든 작업이 같은 머신에서 온 것처럼 보이며, 계정이 작업 사이에서 섞여 하나의 이상이 여러 작업에 영향을 줄 수 있습니다. 환경은 임시로 만들고 사용 후 회수해야 하지만 이를 통합해서 스케줄링하는 체계도 필요합니다. 모델이 어떻게 할지를 해결하면서 어디에서 할지가 새로운 병목이 됩니다.
아키텍처에 추가되는 한 계층
세 세대를 함께 놓고 보면 차이는 단순히 어느 쪽이 더 발전했느냐가 아닙니다. 각 세대는 이전 세대가 해결하지 못한 것을 이어받아야 합니다. 앞선 두 세대에서 환경이 큰 문제가 아니었던 이유는 자신의 머신에 있는 브라우저를 직접 조작했기 때문입니다. Agent 단계에서는 작업이 대량으로 동시에 무인 실행되므로 환경을 명시적으로 관리해야 합니다. 각 작업은 독립된 환경에서 실행되고 fingerprint와 session이 섞이지 않아야 하며, 로그인 상태는 작업 간에 유지되어 매번 다시 로그인할 필요가 없어야 합니다. IP, 시간대, 언어도 하나의 세트로 맞춰야 하고, 환경은 컴퓨팅 자원처럼 필요할 때 생성하고 사용 후 회수해야 합니다.
PurpleMark가 하는 일이 바로 이 계층에 있습니다. 브라우저 환경을 스케줄링 가능한 리소스로 만들어 Agent가 작업 로직에 집중하도록 합니다.
선택 기준도 더 분명해집니다. 기업 테스트 스택과 기존 스크립트 자산은 현재 경로를 유지하면 되고, 요청 수준의 제어가 필요한 복잡한 Web 애플리케이션은 프로토콜 기반 세대에 맞습니다. 모델이 작업을 계획하고 장기간 안정적으로 실행해야 하는 경우에는 앞선 두 세대의 기술도 계속 사용할 수 있지만, 환경 계층은 별도로 해결해야 합니다. 실제 사용자가 조작하는 것처럼 보여야 하는 시나리오라면, 어느 세대이든 자동화 framework 자체만으로 제공할 수 있는 기능은 아닙니다.
기술적 경로 밖에도 한 가지 경계가 있습니다. 자동화 작업은 대상 플랫폼의 규칙과 현지 법률을 따라야 합니다. 기술적으로 실행 가능하다는 것이 곧 비즈니스적으로 적절하다는 뜻은 아닙니다.


