마야크루
경력근거: 인플루언서와 자영업 사장님을 연결하는 체험단 마케팅 플랫폼
※ 실제 산출물이 아닌 AI 예측 시안입니다.
마야크루의 슈퍼멤버스는 인플루언서와 자영업 사장님을 연결하는 체험단 마케팅 플랫폼이고, 공고에 적힌 대로 월 3,200곳 이상의 유료 가맹점과 누적 42만 명의 블로거가 참여합니다. 사장님은 구독료를 내고 후기를 받는 쪽이고 블로거는 조건을 지켜 후기를 쓰는 쪽이라, 두 약속이 맞았는지 세는 계산이 양면 플랫폼 한가운데에 놓입니다. 공고가 말한 리텐션도 여기서 갈라집니다. 조건을 못 지킨 후기를 받은 사장님이 다음 달 구독을 끊기 때문입니다. 가맹점 수가 이만큼이 아니면 사람이 한 건씩 열어 보면 되는 일이라 이 화면이 생길 이유가 없습니다. 다만 이 포트폴리오는 조건표와 후기를 맞추는 계산과 그 결과를 읽는 화면을 보여줍니다. 노출 랭킹 알고리즘이나 결제·정산 시스템의 깊이는 주장하지 않습니다. 후기가 조건을 지켰는지 세는 데까지가 제가 손으로 확인해 본 범위이고, 노출 랭킹과 정산 쪽은 면접에서 배우고 싶은 자리로 남겨 둡니다.
슈퍼멤버스는 인플루언서와 자영업 사장님을 연결하는 체험단 마케팅 플랫폼이고 유료 가맹점이 월 3,200곳이라고 공고가 밝혔습니다. 사장님이 낸 돈과 블로거가 올린 후기 사이를 맞춰 보는 자리가 이 제품의 한복판입니다.
운영·CX·세일즈가 반복하던 일을 AI·자동화로 다시 설계해 실제 운영에 정착시키는 것까지가 범위라고 적혀 있습니다. 후기를 한 건씩 열어 보던 확인을 판정 화면으로 옮기는 일이 그 범위 안에 그대로 들어갑니다.
설계·구현·배포·측정까지 한 바퀴를 직접 도는 Product Engineer 를 찾는다고 적혀 있습니다. 표 두 장에서 화면과 측정까지 한 사람이 닫아 본 결과물이 그 한 바퀴와 같은 모양입니다.
운영 담당자가 그 주 마감분 후기 목록과 캠페인 조건표를 올리면, 후기 한 건마다 그 캠페인이 건 글자수·사진·키워드·구매 링크·마감일을 차례로 짚어 여섯 판정 중 하나를 답니다. 키워드는 사장님이 적은 대로와 블로거가 쓴 대로가 띄어쓰기부터 달라서, 쉼표로 끊고 띄어쓰기를 뗀 뒤 남는 것만 빠진 키워드로 셉니다. 못 지킨 후기는 사유별로 서고 모자란 글자수와 사진 장수가 숫자로 붙어, 어느 블로거에게 무엇을 보완해 달라고 할지 운영 담당자가 그 자리에서 정합니다.
체험단 캠페인이 약속대로 돌아가는지 보는 슈퍼멤버스 운영 담당자
캠페인마다 사장님이 건 조건이 달라서 운영 담당자가 후기를 한 건씩 열어 조건표와 번갈아 보며 세고 있습니다. 조건을 표로 받아 후기와 맞춰 사유별로 내면 보완을 요청할 후기가 마감 당일에 가려지고, 사장님이 받는 후기의 모양이 캠페인마다 흔들리는 폭이 줄어듭니다.
후기 목록과 캠페인 조건표를 올리면 후기마다 여섯 판정 중 하나가 붙고 사유별로 나오는 관리자 페이지입니다. 후기 본문 수집은 사내 API 가 이미 세어 준 글자수·사진 장수·본문에서 잡힌 키워드를 받는 것으로 가정하고, 블로그 크롤링은 다루지 않습니다.
후기 412건에 손으로 매긴 정답 판정을 붙여 자동 판정과 대조하고 사유별 일치율을 냅니다. 2주차부터 AWS 로 배포해 운영 담당자가 웹 주소로 들어와 그 주 마감분을 올려 봅니다.
못 지킨 후기마다 블로거에게 보낼 보완 요청 문안 초안을 화면에서 뽑고, 블로거 등급별로 어느 조건이 자주 남는지 캠페인 기간 단위로 보여주는 단계입니다.
운영 담당자가 후기 목록과 캠페인 조건표를 올리면 못 지킨 후기가 사유별로 나오고 모자란 글자수와 사진 장수가 숫자로 붙는 과정을 시연합니다.
그 주 마감분 후기 412건에 운영 담당자 눈으로 정답 판정을 하나씩 달아 두고 자동 판정과 맞춰 사유별 일치율을 냅니다. 정답도 후기도 제가 만든 합성 표라, 이 값은 성능이 아니라 데모 조건에서 규칙이 흔들리지 않는지를 보는 수치입니다.
판정이 서기 전에 망가진 후기 표 24가지를 먼저 올려 봅니다. 키워드 칸이 비거나 조건표에 없는 캠페인 번호가 섞이거나 사진 장수가 0 인 후기를 올려도 화면이 서고, 조건을 걸지 않은 캠페인은 판정 자리 대신 hedge 로 내려갑니다.
마감 주간 후기 8천 건과 캠페인 600건을 한 번에 올려 판정이 끝나는 시간을 재고, 마감일 오후에 눌러도 기다릴 만한지 봅니다.
제가 실제로 잰 것은 후기 412건에서 나온 사유별 일치율 하나입니다. 일치율은 제가 꾸민 후기에 제가 매긴 정답을 붙여 나온 숫자이고, 보완 요청이 구독 유지로 이어졌는지는 슈퍼멤버스의 실제 후기와 구독 기록이 들어와야 나옵니다. 그 기록이 붙는 주에 곧바로 돌릴 수 있도록 채점 러너와 정답 후기 서식을 먼저 짜 두었습니다.
후기 412건은 제가 사장님 조건표까지 지어내 만든 표이고 정답 판정도 같은 손이 매겼습니다. 그래서 사유별 일치율은 이 화면이 도는 범위를 보이는 숫자일 뿐, 슈퍼멤버스의 실제 후기에서 얼마나 맞는지는 말해 주지 않습니다. 면접에서는 그 범위와, 실제 후기가 오면 바로 재볼 수 있다는 준비 상태까지만 말씀드립니다.
같은 사람이 후기도 쓰고 조건표도 걸었으니 둘이 맞아떨어지는 것은 놀랄 일이 아닙니다. 그래서 키워드 칸이 빈 후기와 사진을 한 장도 안 올린 후기, 사장님이 키워드를 걸지 않은 캠페인을 일부러 섞어 빈 칸과 0장과 조건 없음이 화면에서 어떻게 서는지 먼저 보게 했습니다.
글자수와 사진 장수를 채웠다고 좋은 후기는 아닙니다. 이 판정이 세는 것은 사장님이 건 조건을 지켰는지까지이고, 후기가 손님을 데려오는지는 다른 이야기라 화면에서도 두 가지를 섞어 말하지 않습니다.
사장님이 적은 키워드와 블로거가 쓴 표기는 띄어쓰기 말고도 조사나 어미가 붙어 갈라집니다. 사람이 보면 같은데 다르게 센 건은 판정 대상에서 빼고 목록에 따로 세우며, 어디까지 같은 것으로 볼지는 운영 담당자와 정할 과제로 둡니다.
이 포트폴리오는 조건표 대조와 사유별 화면을 보여줍니다. 노출 랭킹이나 결제·정산 시스템의 깊이는 주장하지 않습니다. 판정은 숫자 비교와 키워드 대조가 하고 모델은 블로거에게 보낼 문안 초안만 씁니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
그 주 마감분 체험단 후기를 한 건씩 적은 표입니다. 판정의 대상 표이며, 본문에서 잡힌 키워드가 비어 있는 후기를 담아 빈 칸이 그대로 판정 사유가 되는 경로를 보여줍니다.
| post_id | campaign_id | blogger_id | char_count | photo_count | used_keywords | has_link | posted_at |
|---|---|---|---|---|---|---|---|
| P-77310 | CMP-3041 | BL-10233 | 1,420 | 12 | 연남 소금집,숙성회 | true | 2026-09-16T21:04 |
| P-77318 | CMP-3041 | BL-10471 | 1,180 | 9 | 연남동맛집,연남 소금집,숙성회 | true | 2026-09-15T13:22 |
| P-77342 | CMP-3058 | BL-11902 | 1,360 | 4 | 강남 필라테스,체험 후기 | true | 2026-09-17T19:40 |
| P-77355 | CMP-3058 | BL-12240 | 1,510 | 11 | 강남 필라테스,체험 후기 | true | 2026-09-17T10:05 |
| P-77388 | CMP-3072 | BL-10908 | 820 | 14 | 수원 한우,한우 오마카세 | true | 2026-09-18T20:11 |
아래 JSON Schema 에 맞는 행을 더 만들어 주세요. {"type":"object","properties":{"post_id":{"type":"string"},"campaign_id":{"type":"string"},"blogger_id":{"type":"string"},"char_count":{"type":"integer","minimum":0},"photo_count":{"type":"integer","minimum":0},"used_keywords":{"type":["string","null"]},"has_link":{"type":"boolean"},"posted_at":{"type":"string"}},"required":["post_id","campaign_id","blogger_id","char_count","photo_count","used_keywords","has_link","posted_at"]} 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) used_keywords 가 null 인 후기, (2) photo_count 가 0 인 후기, (3) 요구 키워드와 띄어쓰기만 다른 키워드를 쓴 후기(연남동맛집), (4) 마감일 자정을 갓 넘겨 발행한 후기, (5) 같은 블로거가 같은 주에 서로 다른 캠페인 후기를 올린 행 쌍, (6) campaign_terms 에 없는 campaign_id. 생성한 행은 반드시 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"post_id":{"type":"string"},"campaign_id":{"type":"string"},"blogger_id":{"type":"string"},"char_count":{"type":"integer","minimum":0},"photo_count":{"type":"integer","minimum":0},"used_keywords":{"type":["string","null"]},"has_link":{"type":"boolean"},"posted_at":{"type":"string"}},"required":["post_id","campaign_id","blogger_id","char_count","photo_count","used_keywords","has_link","posted_at"]}사장님이 캠페인마다 건 조건을 적은 표입니다. 판정의 기준 표이며, 키워드를 걸지 않은 캠페인과 구매 링크를 요구하지 않는 캠페인을 함께 담아 조건이 없는 자리에서 판정을 멈추는 경로를 보여줍니다.
| campaign_id | store_name | min_chars | min_photos | required_keywords | link_required | due_at |
|---|---|---|---|---|---|---|
| CMP-3041 | 연남 소금집 | 1,000 | 8 | 연남동 맛집,연남 소금집,숙성회 | true | 2026-09-18 |
| CMP-3058 | 강남 필라테스 | 1,200 | 8 | 강남 필라테스,체험 후기 | true | 2026-09-19 |
| CMP-3072 | 수원 한우마당 | 1,000 | 10 | 수원 한우,한우 오마카세 | true | 2026-09-19 |
| CMP-3085 | 부산 카페온 | 1,000 | 8 | 부산 카페,광안리 카페 | true | 2026-09-18 |
| CMP-3096 | 대전 파스타공방 | 900 | 6 | 대전 파스타 | false | 2026-09-22 |
아래 JSON Schema 에 맞는 행을 더 만들어 주세요. {"type":"object","properties":{"campaign_id":{"type":"string"},"store_name":{"type":"string"},"min_chars":{"type":"integer","minimum":0},"min_photos":{"type":"integer","minimum":0},"required_keywords":{"type":["string","null"]},"link_required":{"type":"boolean"},"due_at":{"type":"string"}},"required":["campaign_id","store_name","min_chars","min_photos","required_keywords","link_required","due_at"]} 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) required_keywords 가 null 인 캠페인, (2) link_required 가 거짓인 캠페인, (3) 요구 키워드가 다섯 개를 넘는 캠페인, (4) 최소 글자수가 1,500자를 넘는 까다로운 캠페인, (5) 마감일이 주말인 캠페인. 한 campaign_id 는 한 줄만 두고, 생성한 행은 반드시 위 스키마를 통과해야 합니다.{"type":"object","properties":{"campaign_id":{"type":"string"},"store_name":{"type":"string"},"min_chars":{"type":"integer","minimum":0},"min_photos":{"type":"integer","minimum":0},"required_keywords":{"type":["string","null"]},"link_required":{"type":"boolean"},"due_at":{"type":"string"}},"required":["campaign_id","store_name","min_chars","min_photos","required_keywords","link_required","due_at"]}캠페인에 참여한 블로거 명단과 등급입니다. 걸린 후기를 누가 썼는지 별명으로 되짚고, 3주차 등급별 추이를 세는 기준이 됩니다.
| blogger_id | blog_alias | grade | joined_at |
|---|---|---|---|
| BL-10233 | 소소한 미식기록 | 골드 | 2024-03-11 |
| BL-10471 | 주말마다 한접시 | 실버 | 2025-06-02 |
| BL-10908 | 먹고쓰는사람 | 블랙 | 2022-09-19 |
| BL-11044 | 오늘의 골목 | 실버 | 2026-08-25 |
| BL-11902 | 카페런 다이어리 | 골드 | 2023-11-07 |
아래 JSON Schema 에 맞는 행을 더 만들어 주세요. {"type":"object","properties":{"blogger_id":{"type":"string"},"blog_alias":{"type":"string"},"grade":{"type":"string","enum":["블랙","골드","실버"]},"joined_at":{"type":"string"}},"required":["blogger_id","blog_alias","grade","joined_at"]} 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 합류한 지 한 달이 안 된 블로거, (2) 별명이 서로 비슷해 사람이 헷갈리는 블로거 쌍, (3) 등급이 실버인데 활동 기간이 가장 긴 블로거. 한 blogger_id 는 한 줄만 두고, 생성한 행은 반드시 위 스키마를 통과해야 합니다.{"type":"object","properties":{"blogger_id":{"type":"string"},"blog_alias":{"type":"string"},"grade":{"type":"string","enum":["블랙","골드","실버"]},"joined_at":{"type":"string"}},"required":["blogger_id","blog_alias","grade","joined_at"]}| TypeScript | 판정 규칙 엔진과 화면, 서버가 같은 타입을 쓰는 언어입니다. 후기 한 건의 판정 결과 모양을 한 곳에 정의해 양쪽이 어긋나지 않게 합니다. |
| JavaScript | 조건표 엑셀을 브라우저에서 바로 읽어 표로 펼치는 업로드 화면 부분입니다. |
| Node.js | 후기 목록과 조건표를 받아 판정을 돌리고 결과를 화면에 넘기는 API 서버입니다. |
| Express | 위 API 서버의 라우팅 골격이며, 업로드와 판정 조회 두 경로만 두어 1주차를 얇게 닫습니다. |
| NestJS | 3주차에 보완 요청 문안 생성과 등급별 집계가 붙으면서 모듈이 늘어나는 자리를 이쪽 구조로 옮깁니다. |
| React | 사유별 목록과 후기 하나를 펼치는 상세, 캠페인 조건 대조표를 그리는 화면입니다. |
| Vue | 사장님 콘솔 쪽에 같은 판정 결과를 얇게 얹어 보는 실험용 화면을 여기로 따로 만들어, 같은 API 가 두 프런트를 받치는지 확인합니다. |
| MySQL | 후기·캠페인 조건·블로거 세 표를 담고, 조건표에 campaign_id 유일 제약을 걸어 한 캠페인에 조건이 두 벌 생기지 않게 합니다. |
| Redis | 캠페인 조건을 캠페인별로 미리 펼쳐 담아 두어 그 주 후기 수천 건을 한 번에 판정할 때 같은 조건을 다시 읽지 않게 합니다. |
| MongoDB | 후기 원문과 본문에서 잡힌 키워드 목록처럼 캠페인마다 모양이 달라지는 기록을 그대로 쌓아 두는 자리입니다. |
| Elasticsearch | 3주차에 같은 키워드가 어느 캠페인에서 자주 남는지 찾는 조회를 이쪽으로 옮겨, 기간과 등급을 섞은 질의가 빨리 돌게 합니다. |
| AWS | 2주차부터 배포와 운영을 맡습니다. 올린 후기 목록과 판정 결과 원본을 S3 에 남기고 RDS 로 저장소를 띄웁니다. |
| Docker | 판정 엔진과 API, 화면을 한 묶음으로 띄워 로컬과 배포 환경이 같은 이미지를 쓰게 합니다. |
| Gemini | 판정이 정해진 뒤 못 지킨 조건 두어 가지를 블로거에게 보낼 보완 요청 문안 초안으로 적습니다. |
✗ fail → 다르게 센 건이 스무 건을 넘으면 띄어쓰기 외에 무엇까지 떼고 볼지 규칙을 다시 정하고 그때까지 그 후기를 판정 대상에서 뺍니다.
✓ pass → 그다음에 2주차 정답 대조와 AWS 배포를 답니다.
✗ fail → 어긋난 건을 모아 판정 차례와 키워드 대조 기준을 다시 봅니다.
✓ pass → 3주차 보완 요청 문안과 등급별 추이로 넘어갑니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
verdict사유 라벨 · post_id + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
조건을 지킴조건 충족글자수가 모자람글자수 미달사진이 모자람사진 장수 미달키워드가 빠짐키워드 누락기한을 넘김마감 초과구매 링크가 없음구매 링크 없음체험단 후기 한 건이 캠페인 조건과 맞춰 어떤 판정을 받는지 남기는 형식입니다. 대표 사유와 함께 걸린 딸린 사유를 갈라 담고, 판정은 규칙이 정하며 요약 문장만 모델이 씁니다.
{"type":"object","properties":{"post_id":{"type":"string"},"campaign_id":{"type":"string"},"verdict":{"type":"string","enum":["조건을 지킴","글자수가 모자람","사진이 모자람","키워드가 빠짐","기한을 넘김","구매 링크가 없음"]},"missing_keywords":{"type":["string","null"],"description":"required_keywords 를 쉼표로 끊고 띄어쓰기를 뗀 뒤 used_keywords 쪽에서 같은 모양을 찾아 남은 것들입니다. 빠진 것이 없거나 키워드 조건이 없는 캠페인이면 비웁니다."},"chars_short_by":{"type":["integer","null"],"description":"min_chars 에서 char_count 를 뺀 값이며 글자수가 모자란 후기에만 채웁니다."},"photos_short_by":{"type":["integer","null"],"description":"min_photos 에서 photo_count 를 뺀 값이며 사진 장수가 모자란 후기에 채웁니다. 대표 사유가 아니라 딸린 사유로 남을 때도 함께 채웁니다."},"days_late":{"type":["integer","null"],"description":"posted_at 의 날짜에서 due_at 을 뺀 날수이며 기한을 넘긴 후기에만 채웁니다."},"other_reasons":{"type":"array","items":{"type":"string","enum":["글자수가 모자람","사진이 모자람","키워드가 빠짐","기한을 넘김","구매 링크가 없음"]},"description":"대표 사유 말고 함께 걸린 사유를 판정 차례 순으로 담습니다. verdict 에 담긴 사유는 여기 다시 적지 않고, 더 걸린 것이 없으면 빈 배열입니다."},"evidence":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"agg":{"type":["string","null"]},"value":{}},"required":["field","value"]}},"summary":{"type":"string"},"hedge":{"type":["string","null"]}},"required":["post_id","campaign_id","verdict","other_reasons","evidence","summary"]}[
{
"post_id": "P-77310",
"campaign_id": "CMP-3041",
"verdict": "키워드가 빠짐",
"missing_keywords": "연남동 맛집",
"chars_short_by": null,
"photos_short_by": null,
"days_late": null,
"evidence": [
{
"field": "used_keywords",
"value": "연남 소금집,숙성회"
},
{
"field": "required_keywords",
"value": "연남동 맛집,연남 소금집,숙성회"
},
{
"field": "store_name",
"value": "연남 소금집"
},
{
"field": "posted_at",
"value": "2026-09-16T21:04"
}
],
"summary": "연남 소금집 후기에 연남동 맛집이 한 번도 나오지 않아 사장님이 건 키워드 세 개 중 하나가 남았습니다.",
"hedge": null,
"other_reasons": []
},
{
"post_id": "P-77342",
"campaign_id": "CMP-3058",
"verdict": "사진이 모자람",
"missing_keywords": null,
"chars_short_by": null,
"photos_short_by": 4,
"days_late": null,
"evidence": [
{
"field": "photo_count",
"value": 4
},
{
"field": "min_photos",
"value": 8
},
{
"field": "store_name",
"value": "강남 필라테스"
},
{
"field": "post_id",
"value": "P-77342"
}
],
"summary": "강남 필라테스 후기에 사진이 4장만 올라와 약속한 8장에서 4장이 남았습니다.",
"hedge": null,
"other_reasons": []
},
{
"post_id": "P-77388",
"campaign_id": "CMP-3072",
"verdict": "글자수가 모자람",
"missing_keywords": null,
"chars_short_by": 180,
"photos_short_by": null,
"days_late": null,
"evidence": [
{
"field": "char_count",
"value": 820
},
{
"field": "min_chars",
"value": 1000
},
{
"field": "store_name",
"value": "수원 한우마당"
},
{
"field": "photo_count",
"value": 14
}
],
"summary": "수원 한우마당 후기가 820자로 끝나 약속한 1,000자에서 180자가 남았습니다.",
"hedge": null,
"other_reasons": []
},
{
"post_id": "P-77401",
"campaign_id": "CMP-3085",
"verdict": "기한을 넘김",
"missing_keywords": null,
"chars_short_by": null,
"photos_short_by": 3,
"days_late": 2,
"evidence": [
{
"field": "posted_at",
"value": "2026-09-20T15:30"
},
{
"field": "due_at",
"value": "2026-09-18"
},
{
"field": "photo_count",
"value": 5
},
{
"field": "min_photos",
"value": 8
},
{
"field": "store_name",
"value": "부산 카페온"
}
],
"summary": "부산 카페온 후기가 9월 18일 마감을 이틀 넘겨 올라왔고 사진도 8장 중 5장만 붙었습니다.",
"hedge": "마감 초과가 대표 사유로 서고 사진 부족은 딸린 사유로 함께 남아 보완 요청에 둘 다 적힙니다.",
"other_reasons": [
"사진이 모자람"
]
},
{
"post_id": "P-77394",
"campaign_id": "CMP-3072",
"verdict": "구매 링크가 없음",
"missing_keywords": null,
"chars_short_by": null,
"photos_short_by": null,
"days_late": null,
"evidence": [
{
"field": "has_link",
"value": false
},
{
"field": "link_required",
"value": true
},
{
"field": "store_name",
"value": "수원 한우마당"
},
{
"field": "char_count",
"value": 1090
}
],
"summary": "수원 한우마당은 구매 링크를 넣기로 한 캠페인인데 이 후기에는 링크가 들어가지 않았습니다.",
"hedge": null,
"other_reasons": []
},
{
"post_id": "P-77455",
"campaign_id": "CMP-3103",
"verdict": "조건을 지킴",
"missing_keywords": null,
"chars_short_by": null,
"photos_short_by": null,
"days_late": null,
"evidence": [
{
"field": "char_count",
"value": 1240
},
{
"field": "min_chars",
"value": 1000
},
{
"field": "photo_count",
"value": 11
},
{
"field": "used_keywords",
"value": "대구 네일,속눈썹 연장,대구 네일샵"
}
],
"summary": "대구 네일샵 후기는 1,240자에 사진 11장이고 키워드 세 개가 모두 나와 조건을 지켰습니다.",
"hedge": null,
"other_reasons": []
},
{
"post_id": "P-77468",
"campaign_id": "CMP-3110",
"verdict": "조건을 지킴",
"missing_keywords": null,
"chars_short_by": null,
"photos_short_by": null,
"days_late": null,
"evidence": [
{
"field": "char_count",
"value": 1780
},
{
"field": "min_chars",
"value": 1200
},
{
"field": "photo_count",
"value": 16
},
{
"field": "post_id",
"value": "P-77468"
}
],
"summary": "청주 성안길 브런치 후기는 1,780자에 사진 16장으로 글자수와 사진 조건을 모두 넘겼습니다.",
"hedge": "이 캠페인은 사장님이 키워드를 걸지 않아 본문에서 잡힌 키워드가 비어 있어도 키워드 판정을 하지 않았습니다.",
"other_reasons": []
},
{
"post_id": "P-77490",
"campaign_id": "CMP-3124",
"verdict": "키워드가 빠짐",
"missing_keywords": "라페스타 맛집",
"chars_short_by": null,
"photos_short_by": null,
"days_late": null,
"other_reasons": [
"구매 링크가 없음"
],
"evidence": [
{
"field": "used_keywords",
"value": "일산 정육식당"
},
{
"field": "required_keywords",
"value": "일산 정육식당,라페스타 맛집"
},
{
"field": "has_link",
"value": false
},
{
"field": "link_required",
"value": true
},
{
"field": "store_name",
"value": "일산 정육식당"
}
],
"summary": "일산 정육식당 후기에 라페스타 맛집이 나오지 않았고 사장님이 넣기로 한 구매 링크도 빠졌습니다.",
"hedge": "키워드 누락이 대표 사유로 서고 구매 링크 없음은 딸린 사유로 함께 남습니다."
}
][자동 검증 · 코드가 판정합니다] 1. verdict 가 여섯 값 중 하나인지 확인합니다. 규칙이 정한 값이라 모델이 새 값을 적으면 그 응답을 버립니다. 2. post_id·campaign_id·verdict·evidence·summary 필드가 빠짐없이 있는지 확인합니다. 3. chars_short_by·photos_short_by·days_late 가 1 이상인지 확인합니다. 모자라지 않은 후기에서는 이 칸을 비웁니다. 4. chars_short_by 를 min_chars 에서 char_count 를 뺀 값으로 다시 계산하고, photos_short_by 를 min_photos 에서 photo_count 를 뺀 값으로 다시 계산합니다. 두 근거 값은 그 후기 행과 그 캠페인 조건 행에서 그대로 가져옵니다. 5. days_late 를 posted_at 의 날짜에서 due_at 을 뺀 날수로 다시 계산합니다. 시각은 한국 시간으로 읽고 자정을 넘긴 발행은 그 다음 날로 셉니다. 6. missing_keywords 를 다시 계산합니다. required_keywords 와 used_keywords 를 쉼표로 끊고 각 조각의 띄어쓰기를 뗀 뒤, 요구 쪽에만 남는 조각을 원래 표기 그대로 적습니다. 다만 required_keywords 가 비어 있으면 키워드 판정을 하지 않고 그 사실을 hedge 에 남깁니다. 7. 걸린 사유를 기한을 넘김, 글자수가 모자람, 사진이 모자람, 키워드가 빠짐, 구매 링크가 없음 차례로 세워 맨 앞을 verdict 에 담고 나머지를 그 차례 그대로 other_reasons 에 담습니다. 하나도 안 걸리면 조건을 지킴을 달고 other_reasons 를 빈 배열로 둡니다. 기한을 넘긴 후기의 사진 부족처럼 뒤로 밀린 사유도 이 칸에 남아 화면에서 사라지지 않습니다. 8. other_reasons 를 다시 계산합니다. verdict 에 담긴 대표 사유가 이 배열에 또 있거나 규칙으로 안 걸린 사유가 들어 있으면 그 응답을 버립니다. 딸린 사유로 남은 조건의 모자란 폭도 chars_short_by·photos_short_by 칸에 그대로 채웁니다. 9. 구매 링크가 없음은 link_required 가 참인 캠페인에서 has_link 가 거짓인지 확인합니다. link_required 가 거짓이면 링크가 없어도 판정하지 않습니다. 10. evidence 의 field 이름이 입력 표에 있는 컬럼인지 대조합니다. 없는 이름을 인용하면 요약이 지어낸 문장이라는 뜻이라 규칙이 만든 기본 문장으로 되돌립니다. 11. evidence 의 value 가 수록된 행의 원문 값과 같은지 확인합니다. 여러 행을 세어 얻은 수치는 agg 를 함께 적습니다. 12. summary 가 존댓말 한 문장으로 끝나는지 확인합니다. [평가 러너 · 2주차] 손으로 매긴 정답 판정 412건과 자동 판정을 대표 사유와 딸린 사유까지 대조해 사유별 일치율을 내고, 어긋난 후기는 따로 모아 키워드 대조 규칙을 손볼지 정합니다. 키워드 표기를 흔들어 만든 후기에 못 지킨 조건을 일부러 심어 두고 심은 수와 잡은 수를 견주는 일도 이 러너에서 합니다. [수동 검증 · 사람이 봅니다] 1. 키워드가 빠짐으로 걸린 후기 20건을 열어 사장님이 건 키워드가 본문에 뜻으로는 들어가 있는지 운영 담당자가 판단합니다. 2. 조건을 지킴으로 넘어간 후기 20건을 표본으로 읽어 글자수만 채운 빈 후기가 섞였는지 보고 판정 차례를 다시 봅니다.