위시켓 포트폴리오 자동 첨부에서 무엇이 문제였나?
위시켓 포트폴리오를 공고마다 자동으로 고르는 기준은 판매 서비스 분류가 아니라 공고 유형과 제목 핵심어여야 했습니다. 고치기 전 스크립트는 공고에 붙은 서비스 태그 하나를 보고, 그 태그에 미리 정해 둔 포트폴리오 3건을 그대로 붙였습니다. 태그가 없는 공고에는 아무것도 붙지 않았고, 태그가 잘못 붙은 공고에는 엉뚱한 사례가 붙었습니다.
지원서 본문은 말이고, 포트폴리오는 그 말을 확인할 증거입니다. 예약 홈페이지를 만들어 달라는 공고에 법인카드 대조 엔진을 붙여 보내면, 발주자는 지원자가 공고를 제대로 읽지 않았다고 볼 수 있습니다. 반대로 첨부가 0건이면 증거 없이 말만 보내는 셈입니다. 어느 쪽이든 지원서 한 장의 신뢰가 깎입니다.
이 비용은 지원서 한 건에서 끝나지 않습니다. 스크립트가 공고를 매일 모으고 지원서 초안까지 자동으로 쓰는 구조라, 첨부 규칙 하나가 틀리면 모든 초안이 같은 실수를 반복합니다. 사람이 제출 직전에 첨부를 일일이 바꿔 끼우면 자동화를 만든 이유가 사라집니다. 그래서 첨부를 고르는 규칙 자체를 다시 짜야 했습니다.
이 글은 처음 잰 숫자, 세운 가설, 그 가설이 틀린 자리, 진짜 원인, 조치, 재측정, 남는 한계 순서로 적습니다. 처음부터 답을 알고 고친 일이 아니어서, 버린 가설도 그대로 남겨 둡니다.
처음 잰 숫자: 태그 없는 공고 130건, 첨부 0건
측정은 공고 목록 파일 전체를 읽어, 공고마다 어떤 포트폴리오가 붙는지 현재 규칙으로 다시 계산하는 방식으로 했습니다. 맞는 첨부인지는 사람의 감으로 가르지 않고 기준 하나로 봤습니다. 포트폴리오 제목에 들어 있는 핵심어가 공고와 하나라도 겹치는가. 겹치는 단어가 없으면 무관한 첨부로 셌습니다.
- 서비스 태그는 5종이었다: 챗봇(chatbot), 백오피스(backoffice), 문서 검토(doc_review), 시스템 연동(integration), 홈페이지(homepage)
- 태그마다 붙는 포트폴리오는 고정 3건이었다
- 서비스 태그가 붙지 않은 공고가 130건이었고, 이 공고들에 붙은 첨부는 0건이었다
- 공개해 둔 포트폴리오 ⑫번(주문 실행 시스템)은 코드의 포트폴리오 목록에 없어서 한 번도 첨부된 적이 없었다
130건은 수집한 공고 가운데 우리 서비스 5종 어디에도 들어가지 않는다고 분류한 공고입니다. 그 안에는 저희가 해 본 종류의 일도 섞여 있었는데, 태그가 비어 있다는 이유 하나로 첨부 단계를 통째로 건너뛰었습니다. 분류 단계에서 떨어진 공고가 첨부 단계에서는 아예 보이지 않았던 셈입니다.
포트폴리오 제목을 기준으로 삼은 이유도 적어 둡니다. 발주자가 지원서에서 가장 먼저 보는 글자는 첨부 목록에 뜨는 포트폴리오 제목입니다. 본문까지 열어 보지 않아도 제목만으로 공고와 관계가 보여야 하고, 그래서 제목에 공고의 낱말이 하나도 없으면 무관한 첨부로 셌습니다. 사람마다 판정이 갈리지 않는 기준이라, 고치기 전과 후를 같은 잣대로 비교할 수 있었습니다.

태그가 붙은 공고라고 안전하지도 않았습니다. 표의 두 사례가 대표적입니다. “공간대여 예약 홈페이지”는 백오피스 태그를 받아 법인카드 대조 엔진을 첨부받았고, “비트코인 주문 실행 엔진” 역시 백오피스로 묶여 메일 회신 자동화를 첨부받았습니다. 정작 주문 실행 공고에 가장 가까운 ⑫번 주문 실행 시스템은 코드에 등록조차 안 돼 있었습니다.
처음 세운 가설은 무엇이었나?
처음 설계는 “공고를 서비스 5종 중 하나로 정확히 분류하기만 하면, 서비스마다 대표 사례 3건을 붙여도 충분하다”는 가정 위에 서 있었습니다. 서비스 태그는 공고 등급을 매기고 제안 금액을 고르는 데도 쓰는 값이라, 첨부까지 같은 값에 묶으면 관리할 곳이 하나로 줄어든다는 계산이었습니다. 처음 만들 때는 이 단순함이 장점으로 보였습니다.
이 가정이 맞으려면 조건이 둘 필요했습니다. 들어오는 공고 대부분이 서비스 5종 중 하나에 깔끔하게 들어가야 하고, 같은 서비스로 묶인 공고끼리는 비슷한 사례를 원해야 합니다. 처음 설계할 때 두 조건을 데이터로 확인한 적은 없었습니다. 공고를 모으는 범위를 넓히면서 두 조건이 동시에 흔들렸습니다.
문제가 보이자 떠올린 두 번째 가설은 정반대 방향이었습니다. 규칙으로는 공고의 다양성을 따라가지 못하니, 언어 모델(LLM)에 공고 본문을 주고 공고마다 첨부를 고르게 하자는 안입니다. 사람처럼 문맥을 읽으니 키워드 오분류 문제도 함께 사라지리라고 기대했습니다.
- 가설 1: 서비스 태그만 정확하면 태그별 고정 3건으로 충분하다 (기존 설계)
- 가설 2: 태그 정확도가 문제라면 LLM이 공고마다 첨부를 고르게 하면 된다
- 가설 3: 공고 유형을 따로 판정하고, 포트폴리오 제목 핵심어가 공고와 겹칠 때만 붙인다
세 가설은 같은 질문에 다르게 답합니다. 첨부를 무엇에 매달 것인가. 가설 1은 판매 분류에, 가설 2는 모델의 판단에, 가설 3은 공고와 포트폴리오 사이의 글자 겹침에 매답니다. 아래에서 앞의 둘이 어디서 틀렸는지부터 적습니다.
세 가설 모두 “첨부는 몇 건이어야 하는가”에는 답하지 않는다는 점도 짚어 둡니다. 기존 설계는 이 질문에 늘 3건이라고 답했고, 그 답이 뒤의 문제를 키웠습니다. 몇 건을 붙일지는 규칙이 아니라 겹치는 사례가 몇 건 있는지에 맡겨야 했습니다.
가설은 어디서 틀렸나?
가설 1은 숫자 하나로 무너졌습니다. 서비스 태그가 없는 공고 130건 전부에서 첨부가 0건이었습니다. 태그를 더 정확하게 매겨도 이 공고들은 애초에 서비스 5종 밖이라 태그를 받지 못합니다. 분류 정확도의 문제가 아니라, 분류 체계가 닿는 범위 자체가 좁았습니다.
태그를 받은 공고에서도 가설 1은 틀렸습니다. 서비스 태그는 공고 본문의 키워드로 정하는데, 키워드 분류가 틀리면 첨부가 그 오류를 그대로 물려받습니다. 예약 홈페이지와 주문 실행 엔진이 둘 다 백오피스로 들어간 순간, 두 공고의 첨부 3건이 전부 어긋났습니다. 태그 하나가 금액, 등급, 첨부를 한꺼번에 정하는 구조라 오분류 한 번이 세 곳으로 번졌습니다.
가설 2는 실행 전에 기각했습니다. 근거는 같은 시스템에서 나온 기록입니다. 지원서 초안을 LLM으로 쓰는 단계에서 초안 3건에 14분이 걸린 적이 있고, 그 14분 사이 다른 작업이 공고 목록 파일을 고치면서 공고 120건이 60건으로 줄어드는 사고까지 났습니다(나중에 복구했습니다). 첨부 선택까지 LLM에 맡기면 공고 한 건마다 몇 분씩 더 붙습니다.
시간보다 큰 문제는 재현성이었습니다. 왜 이 포트폴리오를 골랐는지 코드로 다시 계산할 수 없으면 테스트로 고정할 수 없고, 틀렸을 때 어디를 고쳐야 하는지도 알 수 없습니다. 같은 공고를 두 번 넣어 다른 첨부가 나오면, 지원서를 검토하는 사람은 어느 쪽을 믿어야 할지 판단할 길이 없습니다.
억지로 3건을 채우지 않는다. 관련 없는 첨부보다 첨부 0건이 낫다.
가설 3을 고르면서 이 한 줄을 같이 정했습니다. 기존 설계는 “항상 3건”을 지키느라 맞지 않는 사례까지 끼워 넣었습니다. 숫자를 맞추는 일과 맞는 사례를 붙이는 일이 충돌하면, 맞는 사례 쪽을 고르기로 했습니다.
진짜 원인: 판매자 분류에 매달아 둔 고정 목록
진짜 원인은 첨부를 고르는 단위가 잘못 잡혀 있었다는 데 있었습니다. 발주자가 보는 단위는 공고 하나이고, 공고가 묻는 질문은 “이런 종류의 일을 해 본 적이 있는가”입니다. 그런데 스크립트는 “이 공고를 저희가 어떤 서비스로 팔 수 있는가”라는 판매자 쪽 질문의 답에 첨부를 매달아 두었습니다.
판매자 쪽 분류는 서비스가 5종뿐이라 거칠 수밖에 없습니다. 반면 포트폴리오는 11종이고, 하나하나 제목에 구체적인 일의 이름이 들어 있습니다. 거친 칸 5개에 포트폴리오를 3건씩 미리 나눠 넣으면, 칸 경계에 걸친 공고는 늘 엉뚱한 3건을 받고, 어느 칸에도 들지 않는 공고는 0건을 받습니다. 처음 잰 숫자 두 개(오분류 사례와 130건 첨부 0건)가 모두 이 한 구조에서 나왔습니다.
⑫번 누락도 뿌리가 같았습니다. 위시켓에 공개한 포트폴리오 목록과 코드 안의 포트폴리오 목록을 따로 관리했고, 둘을 맞춰 보는 장치가 없었습니다. 포트폴리오를 공개해 놓고도 코드는 그 존재를 몰랐고, 아무도 알아채지 못했습니다. 사람 손으로 두 목록을 맞추는 방식은 포트폴리오가 늘어날수록 더 자주 어긋납니다.
정리하면 원인은 분류의 정확도가 아니라 분류의 주인이었습니다. 판매자가 자기 사정으로 만든 분류에 발주자가 볼 증거를 매달았고, 분류 밖으로 떨어진 공고와 분류가 틀린 공고가 함께 피해를 봤습니다. 고칠 대상은 태그 키워드 목록이 아니라 첨부가 무엇을 기준으로 움직이는가였습니다.
조치: 공고 유형 18종과 제목 핵심어 겹침 규칙
서비스 태그는 금액과 등급 계산에 그대로 두고, 첨부 선택만 새 함수(pick_portfolios)로 떼어 냈습니다. 새 함수는 네 단계로 움직입니다.
서비스 태그를 아예 없애지 않은 데도 이유가 있습니다. 태그는 제안 금액과 공고 등급을 정하는 데 여전히 쓰이고, 그 계산은 이번 문제와 관계가 없었습니다. 문제는 한 값이 성격이 다른 두 질문(얼마에 팔 것인가, 무엇을 보여 줄 것인가)에 동시에 답하던 구조였습니다. 그래서 값을 고치지 않고 질문을 나눴습니다.
- 1단계: 공고 제목과 본문으로 공고 유형을 판정한다. 유형은 18종이고, 각 유형은 대상·비대상·빈칸 중 하나다
- 2단계: 그 유형에 정해 둔 우선 첨부 목록에서, 포트폴리오 제목 안의 핵심어가 공고와 1개 이상 겹치는 포트폴리오만 고른다. 핵심어는 중심어(core)와 보조어(support) 2단으로 나눴다
- 3단계: 모자라면 나머지 포트폴리오 가운데 핵심어가 2개 이상 겹치는 포트폴리오로 채운다
- 4단계: 그래도 모자라면 채우지 않는다. 3건을 억지로 맞추지 않는다

2단계와 3단계의 문턱이 다른 데는 이유가 있습니다. 유형이 이미 맞은 우선 목록 안에서는 핵심어 1개만 겹쳐도 충분한 근거가 됩니다. 우선 목록 밖에서 끌어올 때는 우연히 한 단어가 겹칠 위험이 커서 2개 이상을 요구했습니다. 문턱을 둘로 나누니 우선 목록이 비어 있는 유형에서도 무리하지 않고 첨부를 찾을 수 있었습니다.
비대상 유형은 상주 인력, 네이티브 앱, 인프라, 머신러닝 모델, 순수 UI/UX 디자인 같은 공고입니다. 공고 목록 파일 전체에서 82건이 여기에 들어갔고, 이 공고들에는 첨부를 붙이지 않습니다. 해당 분야 포트폴리오가 없는데 비슷해 보이는 사례를 끌어다 붙이면 처음 문제(엉뚱한 첨부)가 다른 모양으로 돌아옵니다. 빈칸을 메우려고 포트폴리오를 새로 만들지도 않기로 했습니다.
규칙 기반을 고른 이유는 두 가지입니다. 같은 입력에 늘 같은 답을 내므로 테스트로 고정할 수 있고, 어떤 단어가 겹쳐서 이 포트폴리오를 골랐는지 근거를 지원서 검토 카드에 함께 남길 수 있습니다. 제출 전에 첨부를 확인하는 사람은 겹친 단어를 보고 바로 맞는지 가릴 수 있습니다. 근거가 남지 않는 방식이었다면 사람이 포트폴리오 본문까지 열어 공고와 대조해야 했습니다. 규칙과 LLM 사이에서 비용을 따져 고른 다른 사례는 LLM 토큰 비용과 규칙 라우터 선택 기록에 정리했습니다.
⑫번 같은 누락은 테스트로 막았습니다. 공개 중인 포트폴리오 목록과 코드의 포트폴리오 목록을 비교해서, 차이가 하나라도 있으면 테스트가 실패합니다. 이 검사를 넣은 뒤로는 공개해 두고 코드가 모르는 포트폴리오가 남아 있을 수 없습니다.
재측정 결과: 무관한 첨부 0건, AI 에이전트 공고 첨부 2회에서 11회로
바꾼 규칙으로 공고 목록 파일 전체를 다시 계산했습니다. 서비스 태그가 없던 130건 가운데 107건(82.3%)에 공고 유형이 붙었습니다. 고치기 전에는 이 130건 모두 첨부 단계에 들어가지도 못했습니다. 유형이 붙은 공고 중 비대상 유형은 원래 의도대로 첨부 0건으로 남습니다.

두 번째로 본 숫자는 무관한 첨부입니다. 당시 모집 중이던 공고 가운데 자동 채점에서 상위 등급(A·B)을 받은 21건을 골라 자동 첨부 결과를 하나씩 확인했습니다. 포트폴리오 제목의 핵심어가 공고와 하나도 겹치지 않는 첨부는 0건이었습니다. 처음 측정에서 본 예약 홈페이지와 법인카드 대조 엔진 같은 조합은 다시 나오지 않았습니다.
세 번째는 가장 크게 달라진 자리입니다. LLM·AI 에이전트 유형으로 판정된 공고 10건에 붙은 첨부 횟수가 2회에서 11회로 늘었습니다. 다만 이 증가를 규칙 하나의 효과로 읽으면 안 됩니다. 같은 날 포트폴리오 ③번과 ⑥번의 제목을 보강해 핵심어가 제목에 드러나게 했고, 두 변경이 함께 들어간 결과입니다. 둘을 나눠 잰 숫자는 없습니다.

| 항목 | 고치기 전 | 고친 뒤 |
|---|---|---|
| 첨부를 정하는 기준 | 서비스 태그 5종, 태그별 고정 3건 | 공고 유형 18종 + 제목 핵심어 겹침 |
| 서비스 태그 없는 공고 130건 | 첨부 0건 | 107건(82.3%)에 유형 부착 |
| LLM·AI 에이전트 유형 10건 | 첨부 2회 | 첨부 11회 |
| 모집 중 A·B 등급 21건의 무관 첨부 | 재지 않음 | 0건 |
| 공개 목록과 코드 목록의 차이 | ⑫번 누락 | 차이가 있으면 테스트 실패 |
변경은 pytest 26건이 모두 통과한 상태로 반영했다.
이번 재측정에서 바뀌지 않은 숫자도 있습니다. 비대상 유형 82건은 고친 뒤에도 첨부 0건입니다. 고치기 전과 결과는 같지만 이유가 다릅니다. 예전에는 규칙이 이 공고들을 보지 못해서 0건이었고, 지금은 보고 나서 붙일 사례가 없다고 판정해서 0건입니다.
이 차이는 숫자로는 보이지 않지만 운영에서는 큽니다. 예전의 0건은 규칙이 공고를 놓친 결과라 고칠 방법이 없었습니다. 지금의 0건은 “이 유형에는 우리 사례가 없다”는 판정이라, 같은 유형 공고가 계속 쌓이면 그 분야 작업을 해 볼지 정하는 근거로 쓸 수 있습니다. 첨부 규칙이 지원서 품질뿐 아니라 우리에게 없는 경험의 목록까지 남기게 된 셈입니다.
남는 한계는 무엇인가?
규칙이 늘수록 손볼 곳도 늘어납니다. 공고 유형 18종과 포트폴리오 11종을 규칙으로 들고 있어서, 새 포트폴리오를 하나 등록하려면 포트폴리오 목록, 파일 경로, 핵심어 목록, 해당 공고 유형 항목까지 4곳을 함께 고쳐야 합니다. 하나를 빠뜨리면 테스트가 바로 실패하도록 만들었지만, 고치는 일 자체가 줄지는 않습니다.
이 비용은 LLM 선택안과 맞바꾼 값입니다. LLM에 맡기면 포트폴리오를 추가할 때 목록 한 곳만 고치면 되지만, 그 대신 공고마다 몇 분의 지연과 재현할 수 없는 판단을 떠안습니다. 포트폴리오 등록은 가끔 일어나고 공고 수집은 매일 일어나므로, 드문 쪽에 수고를 몰아 두는 편이 낫다고 판단했습니다. 포트폴리오가 지금보다 훨씬 많아지면 이 판단을 다시 따져야 합니다.
글자 겹침에 기대는 방식의 약점도 실제로 드러났습니다. 나중에 “중심의”라는 표현이 문서 검토 쪽 핵심어 “심의”로 잡히는 오탐이 나와 따로 고쳤고, 인쇄·편집디자인 공고 제목도 제외 목록에 넣었습니다. 한 낱말이 다른 낱말 안에 들어 있기만 해도 겹친다고 보는 한, 이런 오탐은 새 공고가 들어올 때마다 다시 나올 수 있습니다.
재측정에도 빈칸이 있습니다. 무관한 첨부 0건은 상위 등급 21건에서 확인한 결과이고, 하위 등급 공고 전체를 같은 기준으로 보지는 않았습니다. 첨부가 맞아진 뒤 지원서 응답률이 올랐는지도 아직 재지 않았습니다. 첨부가 정확해졌다는 숫자와 발주자가 더 많이 답했다는 숫자는 서로 다른 숫자입니다.
제목에 기대는 규칙이라 생기는 부작용도 하나 있습니다. 이번에 포트폴리오 ③번과 ⑥번 제목을 보강했듯, 첨부가 잘 붙게 하려면 포트폴리오 제목에 핵심어를 드러내야 합니다. 그 과정에서 제목이 사람이 읽기 좋은 문장보다 검색어 나열에 가까워질 위험이 있습니다. 규칙이 제목을 읽는 만큼 발주자도 같은 제목을 읽으니, 제목을 고칠 때는 두 독자를 함께 봐야 합니다.
유형을 받지 못한 공고도 남아 있습니다. 판정 규칙이 모르는 공고는 빈칸으로 두는데, 빈칸이 어떤 공고들로 채워졌는지는 아직 따로 분류하지 않았습니다. 빈칸이 쌓이는 모양을 보고 유형을 늘릴지, 그대로 둘지 정해야 합니다. 비슷한 자동 첨부나 분류 규칙을 설계하는 중이라면 상담 페이지에서 문의를 남길 수 있습니다.