AI업무자동화로 외주 공고를 고를 때 무엇이 문제였나?
결론부터 적습니다. AI업무자동화로 외주 공고를 고를 때 저희를 막은 것은 공고 수가 아니라 납품에 쓸 수 있는 시간이었고, 그래서 공고 채점 기준을 키워드 일치에서 시간당 실수령액으로 바꿨습니다. 함께 공고 수집 주기를 하루 2회에서 2시간 간격으로 줄였는데, 처음 올린 방식은 예약 실행이 한 번도 돌지 않아 다시 고쳐야 했습니다.
상황은 이랬습니다. 위시켓 같은 외주 중개 플랫폼에는 매일 개발 의뢰 공고가 올라옵니다. 저희는 공개 공고를 주기적으로 모아 목록 파일에 쌓고, 판매 중인 서비스와 맞는 공고에 등급을 매겨 대표에게 메신저 카드로 알리는 수집기를 돌리고 있었습니다. 처음 채점 방식은 단순했습니다. 공고 제목과 본문에 'AI'·'자동화'처럼 판매 서비스와 겹치는 낱말이 있으면 높은 등급을 줬습니다.
대표의 지시는 두 가지였습니다. 수주할 수 있는 건이 한 달에 몇 개나 될지 먼저 가늠하고, 단가가 높고 실적이 쌓이는 일을 최대한 많이 잡도록 자동화하라는 것이었습니다. 키워드 채점은 이 지시의 앞부분에 답하지 못했습니다. 낱말이 맞는 공고를 전부 올리면 홈페이지 수정처럼 손은 많이 가고 금액은 작은 일도 같은 등급을 받았습니다.
이 글은 그 채점 기준을 바꾸고 수집 주기를 늘린 과정, 그리고 바꾼 직후 드러난 결함 세 가지를 순서대로 정리합니다. 같은 수집기에서 포트폴리오를 자동으로 붙이는 규칙을 고친 이야기는 위시켓 포트폴리오 자동 첨부를 제목 핵심어 규칙으로 고친 기록에 따로 적었습니다.
처음 잰 숫자: 적합 공고 월 36건, 기대 계약 월 0.9~2.8건
자동화를 손보기 전에 시장 규모부터 쟀습니다. 8월과 9월에 따로 모아 둔 공고 실측 자료를 다시 계산했습니다. AI·자동화와 시스템 개발에 해당하는 적합 공고는 공개 외주 기준으로 월 36건이었습니다. 금액 중앙값은 800만 원, 공고 한 건에 붙는 지원자는 중앙값 39명이었습니다.
지원자 39명 중 무작위로 뽑힌다고 가정하면 기대 계약은 월 0.9건입니다. 제안서 덕에 선택 확률이 무작위의 3배라고 가정하면 월 2.8건까지 올라갑니다. 수요 쪽 숫자만 보면 월 1건에서 3건 사이의 계약이 가능한 시장이었습니다.
문제는 반대편에서 나왔습니다. 실제로 지원했던 기준 공고 한 건의 공수를 대입해 보니, 1,000만 원짜리 일에 441시간이 드는 구조였습니다. 시간당으로 나누면 2.3만 원입니다. 대표가 한 달에 납품에 쓸 수 있는 시간을 134시간으로 가정하면, 이 단가로는 월 0.38건만 소화할 수 있고 실수령은 월 244만 원에 그칩니다.
목표 쪽에서 거꾸로 계산하면 차이가 더 분명했습니다. 같은 134시간으로 월 1,000만 원을 벌려면 발주액 기준 시간당 9.3만 원짜리 일이 필요합니다. 기준 공고는 2.3만 원이었습니다. 계산을 마친 뒤 결정 기록에는 이렇게 적었습니다.
막는 것은 수요가 아니라 납품 시간이다.
| 항목 | 값 | 비고 |
|---|---|---|
| 적합 공고(AI·자동화+시스템) | 월 36건 | 공개 외주 기준 |
| 공고 금액 중앙값 | 800만 원 | |
| 공고당 지원자 중앙값 | 39명 | |
| 기대 계약 | 월 0.9~2.8건 | 무작위 ~ 제안서 3배 가정 |
| 기준 공고 공수 | 1,000만 원 / 441시간 | 시간당 2.3만 원 |
| 대표 가용 시간 | 월 134시간 | 가정, 대표 확인 대기 |
| 이 단가로 소화 가능 | 월 0.38건 | 실수령 월 244만 원 |
| 월 1,000만 원에 필요한 단가 | 시간당 9.3만 원 | 발주액 기준 |
측정 방법: 8월·9월 공고 실측 자료 재계산(2026년 9월 15일).

세운 가설: 시간당 실수령으로 고르고 더 자주 모으면 된다
숫자가 가리키는 방향은 둘이었습니다. 하나는 시간을 덜 쓰고 더 받는 공고를 골라야 한다는 것, 다른 하나는 그런 공고를 놓치지 않게 더 빨리 봐야 한다는 것이었습니다. 이 두 가지를 가설로 세우고 자동화를 다섯 갈래로 고쳤습니다.
- 채점 기준 전환: 키워드 일치 대신 시간당 실수령으로 등급을 매긴다. A등급은 총액 490만 원 이상, 판매 서비스 적합, 시간당 실수령 3.6만 원 이상을 모두 만족해야 한다. 결제 연동·데이터 이관류는 손이 많이 가므로 시간당 2.3만 원으로 낮게 잡는다.
- 수집 주기 단축: 하루 2회에서 2시간 간격(08:17~22:17)으로 바꾸고, 하루 페이지 상한 120은 그대로 둔다.
- 자동 초안: A등급 공고마다 AI가 공개 공고 전문과 포트폴리오 등록 원문만 근거로 제안서 초안을 쓴다.
- 결정론 검사: 연락처, 없는 실적 고백, 재직 중 겸업 노출, 직무 현재형 표현, 번역체, 길이를 규칙으로 검사한 뒤 메신저 카드로 보낸다.
- 사람 승인 제출: 대표가 메신저에 '제출'이라고 한마디 보내야만 검사를 통과한 초안이 지원서 양식에 채워진다.
시간당 3.6만 원이라는 기준은 실측이 아니라 가정이었습니다. 표본이 기준 공고 한 건뿐이었기 때문입니다. 그래서 지원부터 미팅·계약·실제 투입 시간까지를 기록하는 실적 목록을 함께 만들고, 실측이 쌓이면 이 가정값을 갈아 끼우기로 했습니다.
버린 대안도 두 개 남깁니다. 첫째, 제출까지 완전히 자동으로 하는 매크로는 기각했습니다. 플랫폼 약관이 직거래와 크롤링을 금지하고, 제출은 한 번 나가면 되돌릴 수 없어 잘못된 초안이 그대로 발주자에게 갑니다. 평점이 곧 상품인 채널에서 사고 한 번은 치명적입니다. 둘째, 키워드만 맞으면 전부 지원하는 방식도 기각했습니다. 저시급 공고에 대표의 한정된 시간을 쓰면 전체 시간당 수입이 내려가기 때문입니다.
수집 주기를 2시간으로 잡으면서 예약 시각은 정각이 아니라 매시 17분으로 두었습니다. GitHub Actions의 예약 실행은 부하가 몰리는 정각에 밀릴 수 있어서 17분 오프셋을 줬습니다. 이 대비가 문제를 막지 못했다는 사실은 다음 날 드러났습니다.
가설은 어디서 틀렸나?
코드 세 묶음을 합치고 테스트 38개가 통과한 뒤, 실제 공고 한 건으로 자동 초안을 처음부터 끝까지 돌렸습니다. 첫 초안부터 틀린 곳이 나왔습니다. 포트폴리오 원문을 근거로 넣기 전 1회차 초안에 '직무로 운영하고 있습니다'라는 현재형 문장이 들어갔습니다. 과거에 한 일을 지금도 하고 있는 것처럼 쓴 문장이라, 직무 현재형 검사를 그 자리에서 추가했습니다.
두 번째 균열은 수집 쪽이었습니다. 9월 15일 23시 7분에 손으로 돌린 수집이 8페이지째에서 오류 코드 없는 차단 신호를 받고 멈췄습니다. 이때는 원인을 특정하지 못했고, 차단 상세를 기록하는 칸만 추가해 다음 날 다시 보기로 했습니다.
세 번째 균열이 가장 컸습니다. 다음 날 아침 '새 2시간 주기의 첫 슬롯이 실제로 도는지' 확인하려고 GitHub API로 예약 실행 기록을 조회했습니다. 결과는 total_count 0이었습니다. 9월 15일 18시 30분용 표현식과 9월 16일 08시 17분용 표현식, 서로 다른 예약 두 개가 연속으로 한 번도 실행되지 않았습니다. '2회 → 2시간'으로 바꿨다고 적었지만 실제 예약 실행 횟수는 0회였습니다.
네 번째 균열은 채점 공식에서 나왔습니다. 9월 16일 낮에 수집 창을 30건에서 120건으로 넓히고 후보를 다시 채점하자 이상한 A등급이 보였습니다. 공고 총액 1,700만 원짜리 홈페이지 공고가 A를 받았는데, 저희 홈페이지 표준가 상한이 1,000만 원이라 실제로 받을 수 있는 금액은 800만 원이었습니다. 800만 원을 340시간으로 나누면 시간당 2.4만 원으로, A 기준 3.6만 원보다 낮습니다.
다섯 번째는 제안 금액이었습니다. 예산 280만 원인 공고에 초안 생성기가 350만 원을 제안했습니다. 금액 규칙 문서에는 '공고 총액 그대로 제안한다'고 적혀 있었는데, 초안 생성기 안에만 하한 350만 원을 끌어올리는 계산이 따로 들어 있었습니다.
| 시점 | 증상 | 처음 짐작 |
|---|---|---|
| 9월 15일, 첫 초안 | '직무로 운영하고 있습니다' 현재형 문장 | 생성 지시 부족 |
| 9월 15일 23:07 | 수동 수집이 8페이지째 차단 신호로 정지 | 미확인 |
| 9월 16일 아침 | 예약 실행 기록 total_count 0 | 예약 표현식 오류 |
| 9월 16일 낮 | 1,700만 원 공고가 A등급, 실수령은 시간당 2.4만 원 | 등급 기준값 문제 |
| 9월 16일 낮 | 예산 280만 원 공고에 350만 원 제안 | 초안 생성기 단독 버그 |
결정 기록과 인접 결정 기록의 Result 칸에서 추렸다.

진짜 원인은 무엇이었나?
예약 실행 0회는 처음에 표현식 문제로 의심했습니다. 표현식을 다시 고쳐 재시도하는 안이 가장 먼저 떠올랐습니다. 하지만 설정을 하나씩 지워 나가자 다른 그림이 나왔습니다. 워크플로 상태는 active였고, Actions 권한도 켜져 있었고, 파일도 기본 브랜치에 있었습니다. 서로 다른 표현식 두 개가 똑같이 0회였으니, 원인은 표현식이 아니라 GitHub의 예약 실행 자체에 있었습니다. 표현식을 바꿔도 같은 일이 다시 날 수 있었습니다.
채점 오판은 계산식 한 줄에서 왔습니다. 시간당 실수령을 공고 총액으로 계산하고 있었습니다. 상한을 넘는 공고일수록 받지도 못할 금액으로 등급이 부풀었습니다. 제안 금액 문제도 뿌리가 같았습니다. 금액 규칙이 문서, 제안서 문구 생성, 초안 생성기 세 곳에 따로 살고 있었고, 초안 생성기 쪽만 문서와 다른 값을 내고 있었습니다.
규칙을 고치는 도중에 사고가 하나 더 났습니다. 채점과 초안 작업이 도는 사이 공고 목록 파일이 120건에서 60건으로 줄었습니다. 삭제 코드는 어디에도 없었습니다. 초안 생성기가 목록 파일을 읽어 사본을 만든 뒤 AI 초안 3건에 14분을 쓰고, 그 낡은 사본을 통째로 다시 썼습니다. 그 14분 동안 다른 수집 작업이 넣은 60건이 덮여 사라졌습니다. 흔히 '갱신 유실'이라고 부르는 경쟁 상태입니다.
원인이 표현식이 아니라 GitHub 예약 자체이므로 표현식을 바꿔도 재발 가능성이 남는다.
돌아보면 다섯 결함은 두 종류로 묶입니다. 하나는 '돌고 있다고 믿은 것이 실제로는 돌지 않은' 결함(예약 실행)이고, 다른 하나는 '한 값이 여러 곳에 따로 있어 서로 어긋난' 결함(금액 규칙, 목록 파일 사본)입니다. 앞의 것은 실행 기록을 직접 조회해야만 보였고, 뒤의 것은 수집 창을 넓혀 표본이 늘어난 뒤에야 보였습니다.
조치: 로컬 크론이 직접 기동하고, 금액 규칙은 한 함수로
예약 실행에는 더 기대지 않기로 했습니다. 로컬 PC의 크론이 2시간마다 매시 47분(08시~22시)에 깨어나, 수집 결과를 받기 전에 GitHub CLI로 수집 워크플로를 직접 띄웁니다. 그다음 15초 간격으로 최대 40회, 즉 10분까지 완료를 기다립니다. 실패하거나 시간을 넘기면 마지막으로 성공한 수집 결과를 그대로 쓰고, 12시간 동안 수집이 멈추면 경보를 보내는 장치는 남겨 두었습니다.
반대 방향의 대안, 즉 GitHub Actions를 버리고 전부 로컬로 옮기는 안은 기각했습니다. 로컬 크론은 PC가 켜져 있어야만 돕니다. PC가 꺼져 있어도 최소한의 수집 시도는 남아야 했습니다. 나중에 예약 실행이 살아나 같은 작업이 두 번 돌더라도, 동시 실행 묶음 설정과 하루 120페이지 상한이 중복을 막습니다.

금액 규칙은 한 함수로 모았습니다. 제안 금액을 계산하는 함수 하나를 새로 만들고, 제안서 문구와 등급 채점이 모두 이 함수를 부르게 했습니다. 채점식은 '돈은 제안 금액, 공수는 공고 총액'으로 나눴습니다. 예산이 '협의'로만 적힌 공고는 공수를 알 수 없으니 등급을 올리지 않습니다. 기존 테스트 하나가 이 부작용을 잡아 줘서 한 번 되돌린 뒤 반영했습니다.
상한을 아예 없애고 공고 총액 그대로 계산하는 안도 있었지만 기각했습니다. 홈페이지 표준가 자체가 판매 상한이라, 받지 못할 금액으로 등급을 매기면 같은 왜곡이 다시 나옵니다. 규칙이 바뀔 때마다 목록 전체를 다시 채점하는 명령도 만들었고, 이때 대표가 이미 내린 판정과 보고 시각은 건드리지 않습니다.
목록 파일 쓰기는 '다시 읽고 병합하기'로 바꿨습니다. 쓰기 직전에 파일을 다시 읽어, 지정한 행의 지정한 칸만 덮어씁니다. 초안 생성기, 메신저 발송 뒤 상태 갱신, 판정 기록 세 곳을 이 방식으로 옮겼습니다. 파일 잠금으로 순서를 줄 세우는 안도 검토했지만, 문제는 동시 접근이 아니라 읽고-고치고-통째로 쓰는 구조 자체였고 동시 접근은 드물었습니다. 1초 안에 끝나는 수집 병합 작업만 전체 쓰기를 유지했습니다.
재측정 결과: 수집은 몇 번 돌았고 등급은 몇 건 바뀌었나?
수집 경로는 세 번 확인했습니다. 추가한 기동 블록만 따로 돌린 실행이 완료됐고, 고친 스크립트 전체를 09시 49분에 돌린 실행도 완료됐습니다. 이때 수집·보고·자동 초안 단계가 전부 정상 종료 코드로 끝났습니다. 마지막으로 10시 47분, 사람이 손대지 않은 실제 크론 슬롯이 이 경로로 성공했습니다. 기동부터 완료까지 실측 1~2분이라 최대 10분 대기는 실제로는 거의 쓰이지 않았습니다.
로컬 직접 기동 3회 = 블록 단독 실행, 09:49 전 구간 실행, 10:47 실제 크론 슬롯. 2026년 9월 16일.

채점 쪽은 목록 전체를 새 규칙으로 다시 채점해서 쟀습니다. 18건의 등급이 바뀌었고, 대표 사례가 앞에서 본 1,700만 원 공고의 A에서 B로의 강등입니다. 사라진 60건은 수집 창 기록 120건을 다시 적재해 복구했습니다. 복구 뒤 한 번 더 전체 재채점을 돌렸을 때 바뀐 등급은 0건이었습니다. 복구한 데이터가 새 규칙과 어긋나지 않는다는 확인입니다.
테스트 수도 단계마다 기록했습니다. 처음 자동화를 합칠 때 38개, 금액 규칙 함수를 넣을 때 17개(신규 4개), 다시 읽고 병합하기를 넣을 때 19개(신규 2개)가 통과했습니다. 구버전 코드로 돌고 있던 초안 작업 하나는 멈추고 새 코드로 다시 돌렸습니다.

8일 뒤 같은 초안 생성기에서 한 가지를 더 쟀습니다. 9월 24일, 제출 후보 4건과 이미 제출한 3건을 기호 기준으로 전수 검사하니 7건 전부 본문에 긴 대시(. )가 8~19개씩 들어 있었습니다. 한국어 글에서 긴 대시는 AI가 쓴 글이라는 인상을 줍니다. 문장 규칙은 이미 있었지만 초안 검사기가 기호를 보지 않았습니다. 검사기에 기호 검사를 붙이고 초안 생성 단계에서 미리 바꾸게 했으며, 이 검사의 테스트 10개와 수집기 전체 테스트 58개가 통과했습니다.
남는 한계는 무엇인가?
가장 큰 한계는 채점의 뿌리가 아직 가정이라는 점입니다. 시간당 3.6만 원 기준은 공고 한 건의 공수에서 나온 추정이라 판매 서비스마다 오차가 큽니다. 첫 계약 2건의 실제 투입 시간과 받은 금액이 실적 목록에 쌓이기 전까지, 등급 판정은 추정값 위에 서 있습니다. 대표의 월 가용 시간 134시간도 가정이며, 이 가정과 납품 인력 확충 여부는 대표 판정을 기다리고 있습니다.
재채점에도 빈틈이 있습니다. 규칙이 바뀌어 등급이 달라져도 이미 대표에게 보낸 메신저 카드는 고치지 않습니다. 재발송 대신 다음 조회부터 새 등급을 보여 주므로, 그 사이에는 카드와 목록 파일의 등급이 어긋날 수 있습니다. 다시 읽고 병합하기도 호출마다 디스크를 다시 읽어 느립니다. 다만 이 방식을 쓰는 세 곳은 원래 AI 호출이나 메신저 발송이 있어 상대적으로 비용이 작습니다.
로컬 직접 기동은 슬롯마다 워크플로 호출과 최대 10분 대기를 더합니다. 실측 1~2분이라 부담은 작지만, PC가 꺼진 시간에는 결국 GitHub 예약 실행에 기대야 하고, 그 예약은 이번에 0회를 기록했습니다. 9월 15일 밤 8페이지째에서 받은 차단 신호의 원인도 이 글을 쓰는 시점까지 기록만 남아 있습니다.
자동 초안의 문장 품질도 끝나지 않았습니다. 이미 제출한 3건에 남은 긴 대시는 지원서 수정이 가능한지 확인하지 못해 그대로 두었습니다. 포트폴리오 8건의 제목·설명에도 낫표가 남아 있습니다. 기호 치환이 대시를 괄호처럼 쓴 자리를 쉼표나 콜론으로 바꿔 어색해진 곳도 있어서, 4건 중 5곳은 사람이 다시 다듬었습니다.
그래도 바꾼 것 하나는 분명합니다. 무엇을 자동화할지가 낱말 일치가 아니라 '이 일로 시간당 얼마를 받나'라는 질문에서 출발하게 됐습니다. 외주 공고 수집·채점·초안 자동화를 직접 붙여 보고 싶다면 상담에서 상황을 들려주세요.