소프트웨어는 경쟁이 아니다: 그것은 우리의 좌절감 지도다
Source: Dev.to
소개
본론에 들어가기 전에 분명히 하고 싶습니다: 저는 여기서 어떤 것을 마케팅하려는 것이 아닙니다. 저는 다른 개발자들에게 말하는 개발자의 입장에서 이 글을 씁니다. 저는 “창업자”라는 모자를 쓰고 있는 것이 아니라, 터미널 앞에서 밤을 새우며 두 개의 소프트웨어가 내가 원하는 대로 서로 대화하도록 만들지 못해 좌절했던 사람의 모자를 쓰고 있습니다. 저는 제 입장에서 말하고 있습니다, 왜냐하면 우리는 소프트웨어 경쟁에 대해 이야기하는 방식이 근본적으로 잘못됐다고 생각하기 때문입니다.
개발자 커뮤니티—Hacker News, Reddit, Twitter—에 조금이라도 발을 들여놓으면, 모든 것을 순위 매겨야 한다는 끊임없고 피곤한 요구를 보게 됩니다. 우리는 “가장 좋은” 프레임워크가 무엇인지, 이번 주의 “Selenium 킬러”가 무엇인지, 혹은 Tool X 대신 Tool Y를 쓰는 이유가 무엇인지 알고 싶어 합니다. 우리는 소프트웨어 개발을 시즌이 끝날 때 단 하나의 프로젝트만이 트로피를 차지할 수 있는 고위험 스포츠 리그처럼 대합니다.
하지만 Doppelganger를 만든 뒤에 나는 *“더 나은”*이라는 말이 엔지니어링에서는 거의 쓸모없는 단어라는 것을 깨달았습니다.
소프트웨어는 “나쁨”에서 “좋음”으로 직선적으로 진화하지 않습니다. 어떤 객관적인 완벽함을 향해 나아가는 것도 아닙니다. 소프트웨어는 수평적으로 진화합니다. 이전 세대의 도구—얼마나 강력하고 다듬어졌든—가 결코 메우도록 설계되지 않은 특정하고 고통스러운 공백을 메우기 위해 갈라져 나갑니다. 어떤 도구도 다른 도구를 완전히 대체하지 않으며, 단지 다른 문제 집합에 대한 다른 트레이드‑오프 세트를 제공할 뿐입니다.
“갭”의 아키텍처
이것은 단순히 브라우저 자동화에 관한 것이 아니라, 우리가 소프트웨어를 구축하는 근본적인 법칙에 관한 이야기입니다.
클라우드의 역사를 생각해 보세요. 우리는 물리적인 온프레미스 서버에서 가상 머신(VM)으로 옮겨간 이유가 VM이 비트를 더 잘 처리하기 때문이 아니라, VM이 **스케일링 갭(Scaling Gap)**을 메워 주었기 때문입니다—즉, 하드웨어를 잘라서 사용할 수 있게 해 주었기 때문이죠. 그 다음에 Docker로 옮겨간 것도 VM을 대체하기 위해서가 아니라, **포터블리티 갭(Portability Gap)**을 메우기 위해서였습니다. Docker는 “내 컴퓨터에서는 동작한다”는 문제를 해결했습니다.
프론트엔드 세계에서는 jQuery에서 React로 옮겨간 이유가 jQuery가 “망가졌다”는 것이 아니라, 웹 애플리케이션이 거대해지면서 React가 **상태 관리 갭(State Management Gap)**을 메워 주었기 때문입니다. jQuery는 복잡하고 데이터‑드리븐한 대시보드를 다루기 위해 설계된 것이 아니었으며, 망치가 나사를 돌리는 데 쓰이는 것이 아니라는 비유와 같습니다.
모든 도구는 단지 의견이 결정화된 형태일 뿐입니다. 그것은 창조자가 가장 중요하게 생각한 것의 지도이며, 더 중요한 것은 그 목표를 달성하기 위해 기꺼이 포기한 것이 무엇인지를 보여줍니다.
브라우저 기술 전문화의 역사
이를 실제로 확인하려면 지난 10년간의 “브라우저 전쟁”을 살펴보세요. 어느 라이브러리가 더 우수한지에 대해 모두가 논쟁하지만, 자세히 보면 이들은 모두 서로 다른 종류의 불편함을 해결하고 있을 뿐입니다:
-
The Compatibility Gap (Selenium):
Selenium은 웹이 조각나고 일관성이 없는 혼란스러운 상태였을 때 탄생했습니다. 빠르게 만들기 위해 설계된 것이 아니라, IE6, Safari, Firefox 등에서 사이트가 동일하게 동작하도록 하는 범용 번역기 역할을 위해 만들어졌습니다. 그 주된 “갭”이 바로 호환성이었기 때문에, 아직도 레거시 엔터프라이즈 그리드를 거의 모든 다른 도구보다 잘 처리합니다. -
The Reliability Gap (Playwright / Puppeteer):
웹이 무거운 싱글 페이지 애플리케이션(SPA) 쪽으로 이동하면서 기존 WebDriver 프로토콜은 점점 불안정하게 느껴졌습니다. 이 도구들은 Selenium을 “죽이는” 것이 아니라, 개발자들이 타이밍 문제와 “요소 대기(wait‑for‑element)” 루프에 좌절감을 느꼈기 때문에 속도와 엔진 직접 동기화(CDP)를 우선시했습니다. -
The Infrastructure Gap (Browserless):
스크립트를 작성하는 것만으로는 절반에 불과합니다. 프로덕션 Docker 컨테이너에서 헤드리스 Chrome을 실행해 본 사람이라면 메모리 누수, 좀비 프로세스, 리소스 급증이라는 악몽을 잘 알 것입니다. Browserless는 Playwright API를 다시 쓰려 하지 않았고, “내 IDE에서는 동작한다”와 “스케일에서 동작한다” 사이의 격차를 메워 주었습니다. -
The Distribution Gap (Apify):
그들은 세상을 바라보며 스크래퍼를 작성하는 것이 어렵지만, 이를 확장하고 터미널 없이도 사용할 수 있게 만드는 것이 더 어렵다는 것을 깨달았습니다. 그래서 접근성과 수익화라는 격차를 메워 주었습니다.
AI 트레이드‑오프: 정확도 vs. 효율성
우리는 현재 AI 브라우저 에이전트가 폭발적으로 늘어나면서 같은 현상이 반복되는 것을 보고 있습니다. 같은 사이클이지만 훨씬 빠르게 진행되고 있죠.
-
Skyvern은 한때 주요 플레이어였습니다. 컴퓨터 비전을 활용해 Resilience Gap을 해결했죠. AI가 DOM 선택자를 읽는 대신 화면을 “볼” 수 있게 함으로써, 개발자가 CSS 클래스를 변경해도 깨지지 않는 자동화를 만들었습니다. 혁신적이었지만, 비전은 무겁고 계산 비용이 많이 들며 종종 느립니다.
-
Browser Use는 나중에 등장했습니다. Skyvern보다 “더 나은”가 될까요? 원시적인 시각적 추론이나 고도 복잡성 측면에서는 아닐 수도 있습니다. 하지만 Efficiency Gap을 메웠습니다. 전체 작업의 80 %에 대해 고성능 비전을 약간 포기하고도 더 저렴하고 빠르며 구현이 쉬운 방식을 사용할 수 있다는 것을 깨달은 것이죠.
이는 대체가 아니라 갈림길입니다. 목재를 운반하기 위해 페라리를 사지는 않으며, 드래그 레이스에서 승리하기 위해 트럭을 사지는 않죠. 어느 도구도 “잘못된” 것이 아니라, 서로 다른 우선순위에 맞춰 설계된 것입니다.
왜 나는 Doppelganger를 만들었는가: “통합 격차”
이것이 바로 내가 이 프로젝트를 시작하게 된 실제 이유다. n8n을 어떤 웹사이트와 연결하려고 할 때 매우 구체적인 장벽에 부딪혔다. 상황을 살펴보니 그 사이에 거대한 구멍이 있음을 깨달았다.
사이트와 상호작용하는 에이전트를 원한다면, 내 사용 사례에 맞는 옵션이 근본적으로 부실했다. 기본적으로 두 가지 선택지만 있었다:
- 무거운 AI 브라우저 에이전트에게 전체 제어권을 넘겨 매번 페이지가 로드될 때마다 “추론”을 해야 했다. 마치 사람을 고용해 웹사이트를 탐색하게 하는 것과 같았으며—느리고, 비용이 많이 들며, 예측할 수 없었다.
- 각 작업마다 완전히 별개의 에이전트나 마이크로서비스를 수동으로 배포·관리 해야 했다.
그 사이에 중간 지점은 없었다. 브라우저를 무제한 로컬 API처럼 엔드포인트를 호출하는 방법도 없었다. 나는 브라우저 안에 “로봇 사람”이 있기를 원하지 않았다; 브라우저가 연결된 서버와 대화하고 싶었다.
나는 통합 격차(Integration Gap) 를 메우고 싶었다.
Doppelganger의 핵심 철학… (내용 계속)
# Doppelganger: Let the AI Use Functions, Not Browsers
**Agents shouldn't be navigating browsers; they should be calling functions.**
I wanted to predefine a task—like “fetch the last three invoices” or “check the status of this shipment”—and turn that into a self‑hosted API endpoint.
Now, instead of an n8n workflow or a LangChain agent trying to “be a human” and fumbling through a UI, it just sends a JSON request to a URL. Doppelganger handles the browser mess in the background and sends back the data. It’s deterministic, it’s fast, and it’s self‑hosted. It’s not trying to replace the AI’s brain; it’s trying to give the AI a better pair of hands.
최종 생각
우리는 소프트웨어를 경쟁 대상으로 보는 것을 멈춘다면 모두에게 더 나은 상황이 될 것이라고 생각합니다. 여러분의 스택에 있는 모든 도구는 누군가가 특정한 제한에 좌절하고 그 위에 다리를 놓기로 결심했기 때문에 존재합니다.
저는 “브라우저 전쟁”에서 승리하려 하거나 차세대 “업계 표준” 도구를 마케팅하려는 것이 아닙니다. 저는 단지 제 작업 흐름을 원활하게 만들기 위해 필요한 다리를 구축하고 있을 뿐입니다. 만약 여러분이 브라우저를 구조화된 워크플로에 억지로 끼워 넣으려다 비용이 많이 들거나 5분마다 깨지는 상황에 좌절했다면, 이 다리가 여러분에게도 도움이 될 수 있습니다. 마케팅도, 과대광고도 없습니다—그냥 다른 틈새를 메우는 또 다른 도구일 뿐입니다.