브라우저 자동화 설계 근거 — 쓰던 크롬에 붙이고 동시성을 2와 8로 묶은 이유
로그인된 세션 위에서 도는 자동화를 지을 때 갈리는 결정 다섯 개를 실측 근거로 정리했습니다. 전용 브라우저를 안 띄운 이유, 경로를 둘로 나눈 이유, 상한을 2와 8에서 끊은 계산, 좌표 클릭을 버린 이유까지.
방구석컴퍼니
혼자 일하는 사람 · 작업 기록

브라우저 자동화에서 결과를 가르는 건 어떤 라이브러리를 쓰느냐가 아니라, 창을 새로 띄울지·동시에 몇 개를 굴릴지·성공을 어디서 읽을지 세 가지입니다. 저는 챗GPT 이미지 생성을 자동으로 돌리는 배선을 만들면서 이 셋을 전부 한 번씩 틀렸고, 그 대가로 파일 24개가 전부 0바이트로 남은 아침을 받았어요. 고친 뒤로는 같은 배치가 24/24로 통과합니다.
로그인된 서비스 위에서 도는 자동화를 직접 짜려는 사람, 또는 누가 만들어둔 배선을 가져다 쓸지 판단하다 막힌 사람을 위한 글입니다. 여기엔 따라 하기 순서도, 요금 손익 계산도 없어요. 순서를 뒤집어 절차부터 손대면 대개 더 오래 헤맵니다.
로그인된 세션 위의 자동화는 설계 제약이 다릅니다
공개 API를 두드리는 자동화는 실패해도 요청 하나가 죽고 끝납니다. 반면 내 계정으로 로그인된 화면을 조종하는 자동화는 실패의 종류부터 달라요. 화면 구조가 바뀌면 통째로 멎고, 너무 세게 굴리면 계정 자체가 위험해지고, 무엇보다 잘못돼도 예외가 안 뜨고 조용히 빈 결과가 쌓입니다. 그래서 이 판의 설계는 "얼마나 빠른가"가 아니라 "무엇을 포기해서 무엇을 지킬 것인가"로 짜야 합니다.
첫 번째 갈림길: 새 창을 띄울 것인가, 쓰던 창에 붙을 것인가
자동화 예제 대부분은 프로그램이 브라우저를 직접 실행합니다. 깔끔하고 재현도 잘 되지만, 그렇게 태어난 창에는 자동화 도구가 남기는 흔적이 붙습니다. 사람인지 확인하는 화면에서 걸렸다는 보고가 이 계열에서 꾸준히 나오는 이유고요. 저는 반대로 갔습니다. 늘 쓰던 크롬에 조종 허용 스위치만 하나 붙여 다시 켜고, 프로그램이 그 창에 손님으로 들어가게 했어요. 새 출입증을 파는 대신, 이미 앉아 있던 내 자리를 그대로 쓰는 쪽입니다.
그 선택이 실제로 포기하는 것
쓰던 창을 재사용하면 흔적 문제는 사라지지만 세 가지를 잃습니다. 창 하나를 자동화가 점유하니 그 시간엔 사람이 같은 창을 만지면 안 되고, 실행 환경이 내 PC에 묶여 서버에서 무인으로 돌리기 어려워지고, 남의 컴퓨터에서 똑같이 재현된다는 보장이 약해집니다. 저는 하루에 몇 번 돌리는 개인 작업이라 이 셋을 다 내줘도 괜찮다고 판단했어요. 무인 서버에서 24시간 굴려야 하는 요구라면 이 설계는 처음부터 틀린 답입니다.
프로필을 따로 잡는 건 재사용 원칙의 예외입니다
"쓰던 창 그대로"라고 해놓고 정작 프로필은 전용으로 하나 팠습니다. 모순처럼 보이지만 이유가 있어요. 요즘 크롬은 평소 쓰는 기본 프로필에 외부 조종이 붙는 걸 막아둬서, 포트만 열어봐야 창은 뜨고 조종은 안 됩니다. 그래서 프로필만 새로 파고 그 안에서 사람이 직접 한 번 로그인해 진짜 세션을 심어두는 방식으로 봉합했습니다. 브라우저는 새것이되 세션은 사람 손으로 만든 것이라는 절충이에요.
두 번째 갈림길: 왜 경로를 하나로 안 두고 둘로 갈랐나
같은 결과물을 얻는 길이 두 개 있었습니다. 하나는 방금 말한 크롬 창을 누르는 길, 다른 하나는 OpenAI가 직접 배포하는 명령줄 도구(코덱스)를 거치는 길이었어요. 성능만 보면 후자 하나로 통일하는 게 맞습니다. 그런데 저는 굳이 둘 다 살려뒀는데, 두 길이 서로 다른 이유로 깨지기 때문입니다.
두 경로는 실패 방식이 겹치지 않습니다
크롬 창 쪽은 화면 구조가 바뀌면 선택자가 어긋나 죽습니다. 명령줄 쪽은 화면과 무관하지만 인자를 넘기는 규칙이 까다로워서 첨부가 조용히 빠지는 사고가 납니다. 한쪽이 깨졌을 때 다른 쪽으로 그날 작업을 넘길 수 있다는 게 둘을 유지하는 값어치예요. 가용성을 사는 대신 유지보수 대상이 두 배가 되는 거래고, 저는 배선이 멎으면 그날 영상 제작이 통째로 밀리는 처지라 이쪽을 골랐습니다.
같은 시스템인데 동시 상한이 다른 이유
여기가 이 배선에서 제일 많이 오해받는 자리입니다. 두 경로는 상한이 다릅니다.
| 항목 | 크롬 창 경로 | 명령줄 경로 |
|---|---|---|
| 동시 상한 | 2 | 8 안팎 |
| 상한을 그 값으로 정한 근거 | 사람이 쓰던 계정을 직접 조작하므로 리스크 최소화 우선 | 정식 기능 호출이라 처리량 우선, 수확 체감 지점에서 절단 |
| 깨질 때 증상 | 화면 요소를 못 찾아 멈춤 | 인자 해석이 어긋나 첨부 유실 |
| 되돌리기 비용 | 선택자 수정 (반나절) | 문자열 조립 수정 (수 분) |
즉 "동시 실행"이라는 같은 단어를 써도 두 경로가 기대할 수 있는 속도는 네 배쯤 벌어집니다. 12장을 118초에 받은 기록은 명령줄 경로의 것이고, 크롬 창 경로로 같은 장수를 돌리면 5분대가 나와요. 이 구분을 흐리면 실행 계획이 통째로 어긋납니다.
상한 8은 성능이 아니라 수확 체감에서 나온 숫자입니다
명령줄 경로는 8보다 더 올릴 수 있었습니다. 실제로 12건까지 던져봤고 한도에 걸려 실패한 건은 0이었어요. 그런데 숫자를 나눠보면 늘릴 이유가 약해집니다.
| 동시 건수 | 전체 소요 | 장당 환산 |
|---|---|---|
| 8건 | 87.5초 | 약 10.9초 |
| 12건 | 118초 | 약 9.8초 |
동시 건수를 1.5배로 올려서 얻은 건 장당 10% 남짓입니다. 한 번에 노출되는 요청 수는 1.5배가 되는데 돌아오는 이득은 10%짜리라면, 그건 좋은 거래가 아니에요. 기본값을 8로 못 박은 근거가 이 표 두 줄입니다.
동시성 숫자는 속도 손잡이가 아니라 리스크 예산입니다
크롬 창 쪽을 2로 묶은 데는 실측 근거가 아니라 판단이 들어갔습니다. 2탭이면 대기 시간이 겹쳐 체감이 확 좋아지는데, 4탭 8탭으로 올려도 그건 같은 한도를 더 빨리 쓰는 것이지 더 많이 쓰는 게 아니거든요. 총량은 그대로인데 눈에 띄는 정도만 올라갑니다. 얻는 게 대기 시간뿐이라면 그 대기는 그냥 내는 편이 낫다고 봤어요.
세 번째 갈림길: 좌표를 찍을 것인가, 이벤트를 쏠 것인가
브라우저 자동화의 표준적인 클릭은 화면 좌표를 계산해 그 지점을 누르는 방식입니다. 사람과 가장 비슷하다는 장점이 있죠. 그런데 이 방식엔 조건이 하나 붙습니다. 그 탭이 화면 맨 앞에 나와 있어야만 먹힙니다. 탭 두 개를 동시에 굴렸을 때 늘 한쪽만 실패하던 원인이 정확히 여기였어요.
화면에 안 보이는 탭에서 브라우저는 일을 미룹니다
크롬은 창이 다른 창에 가려지면 그 탭의 렌더링과 타이머를 뒤로 미룹니다. 배터리를 아끼려고 만든 정상 동작이에요. 문제는 이때 좌표 클릭이 에러를 내며 실패하는 게 아니라 아무 일도 없었던 것처럼 조용히 삼켜진다는 겁니다. 로그에는 클릭했다고 찍히는데, 결과만 안 와요. 자동화가 반쯤만 성공하는 증상이 보이면 이 계열을 먼저 의심하는 게 빠릅니다.
그래서 좌표를 버리고 신호를 직접 재현했습니다
해결은 좌표 계산을 통째로 버리고, 마우스를 가져다 대고 누르고 떼는 동안 브라우저가 차례로 받는 신호들을 요소에 직접 쏘는 겁니다. 이렇게 하면 탭이 뒤에 숨어 있어도 눌려요. 부수 효과가 하나 더 있었는데, 탭을 앞으로 끌어오던 코드를 통째로 걷어낼 수 있었어요. 자동화가 도는 동안 화면이 제멋대로 튀지 않게 된 것도 이 변경 덕입니다.
통제 비교: 클릭 방식만 바꿨을 때
조건을 맞춰야 의미가 있으니 붙여두겠습니다. 같은 계정, 같은 프롬프트 24개, 같은 비율, 탭 2개 동시, 같은 날 기준으로 클릭 방식 하나만 교체한 결과입니다.
| 클릭 방식 | 24장 배치 결과 | 실패 양상 |
|---|---|---|
| 화면 좌표 클릭 | 절반가량 실패 | 에러 없이 빈 결과 |
| 이벤트 직접 발화 | 24/24 성공 | — |
바뀐 건 코드 한 군데였고 성공률은 두 배가 됐습니다. 성능 튜닝으로는 절대 안 나올 폭인데, 원인을 잘못 짚으면 몇 날 며칠 성능 쪽만 뒤지게 되는 종류의 문제예요.
네 번째 갈림길: 입력을 어디까지 다듬어서 넘길 것인가
명령줄 경로에서 참고 이미지가 통째로 사라지는 사고가 있었습니다. 원인은 제가 넘긴 문장 안에 들어 있던 줄바꿈 하나였어요. 명령줄에서 줄바꿈은 글자가 아니라 인자와 인자를 가르는 경계로 읽힐 수 있습니다. 그래서 뒤에 붙은 참고 이미지 인자가 다른 덩어리로 떨어져 나갔던 거고요. 최종 문자열을 공백 하나짜리 한 줄로 눌러서 넘기게 바꾼 뒤로는 5컷 전부 정상입니다.
이 사고에서 뽑은 설계 규칙
여기서 얻은 건 줄바꿈 처리법이 아니라 더 일반적인 규칙입니다. 여러 조각을 조립해 만든 문자열은 경계를 넘기기 직전에 한 번 정규화한다. 조립 과정 어디서 개행이 섞였는지 추적하는 것보다, 나가는 문 앞에서 한 번 다림질하는 쪽이 압도적으로 싸거든요. 참고 이미지 용량에 상한(600KB)을 둔 것도 같은 규칙의 적용입니다. 1.8MB짜리를 그대로 넣으면 에러도 없이 업로드 표시만 영원히 도니까, 들어가기 전에 잘라서 그 상태 자체를 못 만들게 막았어요.
다섯 번째 갈림길: 성공을 어디서 읽을 것인가
이게 제일 비싸게 배운 항목입니다. 그날 아침 파일은 24개가 다 있었고, 로그에도 전부 성공이라고 찍혀 있었어요. 정작 파일은 전부 0바이트였습니다. 도구가 돌려주는 "성공"은 요청이 오갔다는 뜻이지 쓸 만한 결과가 나왔다는 뜻이 아니었던 거예요. 그래서 지금은 성공 판정을 도구 출력이 아니라 산출물 자체에서 읽습니다. 개수가 맞는지, 0바이트가 섞였는지, 참고로 넣은 그림이 결과물 자리에 그대로 저장되진 않았는지 세 가지를 봅니다.
원인의 개수를 1로 가정한 게 이틀을 태웠습니다
그 24장 사고에서 로그에 찍힌 문장은 하나였어요. 입력창이 비워지지 않았다, 이게 전부였습니다. 저는 그 문장을 검색창에 넣고 이틀을 보냈는데, 파보니 뒤에 범인이 여섯 명 서 있었습니다. 외부 도구의 요청 가로채기, 첨부 누적, 제거 버튼을 넓게 잡아 생긴 모드 해제, 큰 참고 이미지, 가려진 탭의 클릭 유실, 그리고 줄바꿈. 하나를 고칠 때마다 증상이 그대로라 계속 헛다리를 짚었어요. 증상 하나에 원인 하나를 가정한 게 설계가 아니라 수사의 실패였습니다.
추측 대신 실패한 순간의 화면을 꺼내는 게 빨랐습니다
여섯 개 중 마지막 두 개는 로그를 아무리 봐도 안 나왔습니다. 실제로 그 대화창을 열어보고서야 잡혔어요. 특히 참고용으로 물려둔 그림이 결과물 자리에 저장되던 버그는 도구 출력만 봤다면 영영 못 찾았을 종류입니다. 그래서 지금 배선에는 실패 시점의 화면 상태를 꺼내 보는 경로를 남겨뒀고, 러너 안에서 찍는 출력은 서브프로세스에 갇히기 쉬워서 상태값을 예외 메시지에 실어 던지게 해뒀습니다.
이 설계가 넘지 않기로 한 선
여기는 단정하면 안 되는 자리라 확인된 것만 적습니다. OpenAI 이용약관의 금지 목록에는 프로그램을 써서 산출물을 긁어내는 행위, 그리고 제한을 우회하는 행위가 나란히 올라 있고, 제재 범위에는 계정 정지와 해지까지 들어가죠. 이 방식 때문에 계정이 잘렸다는 1차 기록은 끝내 안 나왔는데, 사례가 안 보이는 것과 문제가 없는 것은 서로 다른 이야기예요. 그래서 단정하는 대신 상한을 낮게 묶고, 연속 실패가 쌓이면 재시도 없이 멈추게 하고, 요금을 받고 남의 그림을 뽑아주는 용도는 이 설계의 전제 밖에 뒀습니다.
한도 숫자를 근거로 삼을 수 없다는 것도 설계 조건입니다
플랜별로 이미지가 몇 장까지 되는지는 공개된 적이 없습니다. 검색으로 나오는 숫자들은 이용자들이 각자 세어본 관측값이고요. 회사가 직접 밝힌 문장은 하나뿐인데, 이미지 작업이 플랜에 포함된 사용량을 3~5배 속도로 깎는다는 내용입니다. 남은 양을 알 수 없고 상한선도 모른다면, 설계가 할 수 있는 일은 소비 속도를 스스로 낮게 묶어두는 것뿐이에요.
솔직한 한계: 이 구조가 깨지는 조건들
좋은 쪽만 적으면 글이 광고가 되니 약한 지점도 남겨둡니다. 챗GPT 쪽 화면이 개편되면 창을 누르는 경로는 그날로 멎고, 그 경로로 돌린 작업은 계정 안에 대화가 계속 남는데 자동 정리는 안 붙여뒀어요. 남은 사용량을 조회할 방법이 없으니, 한 장 뽑는 시간이 갑자기 늘어지면 그걸 신호로 읽는 정도가 전부입니다. 두 경로가 각각 별도의 사용량 계정을 쓴다는 것도 어디까지나 제가 관찰한 정황이지, 회사가 확인해준 사실이 아닙니다. 이 가정 위에 물량 계획을 세우면 관측이 뒤집히는 날 계획도 같이 무너져요.
내가 만든 부분과 남의 것을 구분해두면
명령줄 도구에서 이미지를 만드는 기능 자체는 2026년 4월에 정식으로 열린 것이고, 레시피 일부는 MIT 라이선스로 공개된 오픈소스(chatgpt-imagegen)를 참고했습니다. 윈도우에서 그대로 돌지 않아 다시 짜긴 했지만, 아이디어가 제 것이라고 말하면 거짓이에요. 제가 실제로 만든 건 두 경로에 작업을 배차하고 상한을 지키며 결과를 검수하는 층 하나입니다. 이 구분을 흐리지 않는 게 이런 글의 최소 조건이라고 생각합니다.
남이 만든 자동화를 고를 때 던져볼 질문 다섯 개
지금까지의 갈림길을 그대로 뒤집으면 남의 배선을 평가하는 체크리스트가 됩니다. 하나, 브라우저를 새로 띄우나 기존 세션에 붙나. 둘, 경로가 하나뿐이면 그게 멎을 때 대안이 있나. 셋, 동시성 기본값에 근거가 붙어 있나 아니면 그냥 크게 잡혀 있나. 넷, 실패가 예외로 오나 조용한 빈 결과로 오나. 다섯, 성공 판정을 도구 출력에서 읽나 산출물에서 읽나. 다섯 개 중 셋 이상에 답이 안 나오는 배선이라면, 잘 도는 게 아니라 아직 안 깨져본 것일 가능성이 큽니다.
정리하면
이 배선에서 성능을 만든 결정은 하나도 없었습니다. 전용 브라우저를 안 띄운 것도, 경로를 둘로 나눈 것도, 상한을 2와 8에서 끊은 것도 전부 깨지는 방식을 미리 고르는 결정이었어요. 24장이 0바이트로 남은 아침에 제가 잃은 건 이틀이었고, 그 이틀이 지금은 다섯 줄짜리 체크리스트로 남아 있습니다.
지금 굴리고 있는 자동화가 있다면, 그게 실패할 때 예외가 뜨던가요 아니면 조용히 빈 결과가 남던가요. 후자라면 오늘 손볼 자리는 속도가 아닙니다.
배선을 짜 올리는 과정과 여섯 개를 하나씩 걷어낸 기록은 영상에 화면 그대로 남겨뒀고, 완성본은 방구석컴퍼니 오픈톡방에서 받으실 수 있습니다.