휴먼코어랩
경력근거: 제품 성장 실험(A/B 테스트)
※ 실제 산출물이 아닌 AI 예측 시안입니다.
공고가 주요업무에 '제품 성장 실험(A/B 테스트)' 과 '고객 데이터 분석 및 인사이트 도출' 을 나란히 적었고, '바이럴 및 퍼포먼스 마케팅 실험' 까지 같은 사람이 본다고 밝혔습니다. 실험을 여럿 돌리면 언제 끝낼지가 매번 감으로 정해지고, 이 포트폴리오는 그 판단을 지표별 기준표로 옮깁니다. 초기 팀이라 실험을 빨리 돌리는 만큼 기준을 미리 적어 두는 편이 되돌리는 비용을 줄입니다. 이 포트폴리오가 보여주는 것은 판독 기준을 데이터로 두고 실험 기록과 맞춰 결론 시점을 가르는 기술이며, 통계 검정이나 심리 분석 도메인 전문성은 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
'제품 성장 실험(A/B 테스트)' 이 주요업무입니다. 실험을 언제 끝낼지가 그 업무의 첫 판단입니다.
'고객 데이터 분석 및 인사이트 도출'. 판독 기준을 미리 적어 두면 그 도출이 흔들리지 않습니다.
'바이럴 및 퍼포먼스 마케팅 실험' 까지 같은 사람이 봅니다. 채널이 달라도 같은 기준으로 재게 둡니다.
돌린 실험이 결론을 내도 되는 상태인지 갈래마다 가릅니다. 지표별 판독 기준에 최소 표본과 최소 기간, 최소 차이를 두고 실험 갈래와 맞춰, 다 채우면 결론 가능으로 넘기고 그렇지 않으면 표본 부족·기간 부족·차이 작음 중 어느 쪽인지 사유로 남깁니다. 전환 수가 안 남은 갈래는 견줄 상대가 없다고 표시하고, 기준에 없는 지표는 미선언으로 남겨 얼마나 모아야 하는지 먼저 정하게 합니다. 실험 기록은 실 서비스 자료 대신 지원자가 만든 예제 서비스에서 남긴 것을 가정하며, 통계 검정이 아니라 미리 정한 기준을 채웠는지만 봅니다.
소비자 서비스를 만들며 성장 실험까지 직접 돌리는 프로덕트 엔지니어입니다. 표가 예뻐 보이면 그대로 반영했다가 다음 주에 숫자가 되돌아오는 것을 몇 번 겪고, 언제 끝내야 하는지를 매번 감으로 정하던 사람입니다.
지표마다 최소 표본과 기간, 차이를 기준으로 적어 두고 실험 갈래와 맞추면, 결론을 낼 실험과 더 돌릴 실험이 갈리고 미루는 이유가 근거로 남는다는 가정입니다. 기준에 없는 지표는 미선언으로 빠지므로 아직 정하지 않은 지표가 그대로 드러납니다.
실험 갈래 기록과 지표별 기준을 받아 갈래마다 결론 가능·보류를 판정하고, 보류면 표본 부족·기간 부족·차이 작음·전환 없음·미선언 중 어느 쪽인지 붙여 실험별로 묶은 판독 리포트를 터미널과 Markdown 파일로 내는 CLI 가 도는 완결품입니다.
작은 예제 서비스에 갈래를 나눠 방문 기록 200건을 만들고, 기록에서 갈래별 표본과 전환을 뽑아 손으로 계산한 정답 판정과 대조해 일치율을 냅니다.
지금 모이는 속도로 며칠 더 돌려야 기준을 채우는지 갈래마다 계산해 내고, 기준을 조금 바꿨을 때 판정이 어떻게 바뀌는지 함께 보여주는 단계입니다.
그로스 담당자가 갈래 기록과 기준표를 넣으면 갈래마다 결론 가능 여부와 보류 사유가 실험별로 묶여 나오는 과정을 시연합니다.
예제 서비스에서 쌓은 갈래 300건과 손으로 계산한 정답 판정을 대조해 일치율을 냅니다. 단, 정답과 기록을 모두 작성자가 만든 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
전환 수가 비었거나 지표 이름이 흔들리거나 기준에 없는 지표가 섞인 입력 30종을 넣어도 출력 형식이 안 깨지고 사유별로 빠지는 비율을 보여줍니다.
최소 표본과 최소 기간을 바꿨을 때 옛 판정이 어떻게 뒤집히는지 회귀로 확인합니다.
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 작성자가 만든 기록의 자가채점이며, 실제 판독 정확도는 휴먼코어랩의 실 실험 기록과 실 기준이 있어야 측정됩니다. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다.
수치는 작성자가 만든 기록의 자가채점이라 성능 증명이 아니므로, 면접에서는 데모 동작과 실검증 준비 상태로 솔직히 설명합니다.
정답을 작성자가 붙였으니 잘 맞는 게 당연하므로, 전환 결측과 짝이 비는 실험, 기준에 없는 지표를 일부러 섞어 쉬운 갈래만 푸는 함정을 피합니다.
이 포트폴리오가 보여주는 것은 판독 기준을 데이터로 두고 실험 기록과 맞춰 결론 시점을 가르는 기술이며, 통계 검정이나 심리 분석 도메인 전문성은 주장하지 않습니다. 판정은 임계 비교가 하고 LLM 은 담당자가 읽을 사유 문장만 맡습니다.
기준을 채웠다고 그 차이가 진짜라는 뜻은 아니어서, 결론 가능은 사람이 판단을 시작해도 되는 상태라는 뜻으로만 씁니다.
실제 도입 때는 지표와 기준이 팀마다 다르므로, 기준표를 그로스 담당과 함께 채우는 일을 도입 단계 과제로 둡니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
돌린 실험을 갈래 단위로 편 기록입니다. 갈래 번호와 실험 번호, 갈래 이름, 지표 이름 표기, 표본, 전환 수, 시작일, 끝난 날, 유입 채널을 한 행에 둡니다. 지표 표기는 적은 사람에 따라 'signup_rate'와 'Signup Rate'처럼 흔들립니다. 전환 수나 끝난 날이 빈 행, 표본이 기준에 못 미치는 행, 사흘만 돈 행, 기준표에 없는 지표를 일부러 섞어 두어 사유가 갈리게 둡니다.
| arm_no | exp_no | arm_raw | metric_raw | users | conversions | started_at | ended_at | channel_raw |
|---|---|---|---|---|---|---|---|---|
| AR-001 | EX-01 | control | signup_rate | 4,200 | 336 | 2026-07-01 | 2026-07-15 | organic |
| AR-002 | EX-01 | variant_a | signup_rate | 4,180 | 460 | 2026-07-01 | 2026-07-15 | organic |
| AR-003 | EX-02 | control | Signup Rate | 2,400 | 192 | 2026-07-20 | 2026-07-27 | paid |
| AR-004 | EX-02 | variant_a | signup_rate | 880 | 88 | 2026-07-20 | 2026-07-27 | paid |
| AR-005 | EX-03 | control | paid_rate | 6,100 | 244 | 2026-08-01 | 2026-08-03 | organic |
아래 JSON Schema 를 그대로 만족하는 실험 갈래 행을 300개 더 만들어 주세요. 실험 하나에 기준 갈래와 비교 갈래를 짝으로 붙이고 지표를 예닐곱 종 섞습니다. 지표 표기는 몇 행에서 띄어쓰기와 대문자로 흔들리게 두고, 2할은 전환 수나 끝난 날을 비우며, 몇 실험은 표본을 천 명 아래로 두고 몇 실험은 사흘만 돌게 하세요. 기준표에 없는 지표도 몇 행 넣습니다. 전환율이나 판정은 넣지 마세요.
{"type": "object", "properties": {"arm_no": {"type": "string"}, "exp_no": {"type": "string"}, "arm_raw": {"type": "string"}, "metric_raw": {"type": "string"}, "users": {"type": ["integer", "null"]}, "conversions": {"type": ["integer", "null"]}, "started_at": {"type": "string"}, "ended_at": {"type": ["string", "null"]}, "channel_raw": {"type": ["string", "null"]}}, "required": ["arm_no", "exp_no", "arm_raw", "metric_raw", "users", "conversions", "started_at", "ended_at"]}{"type": "object", "properties": {"arm_no": {"type": "string"}, "exp_no": {"type": "string"}, "arm_raw": {"type": "string"}, "metric_raw": {"type": "string"}, "users": {"type": ["integer", "null"]}, "conversions": {"type": ["integer", "null"]}, "started_at": {"type": "string"}, "ended_at": {"type": ["string", "null"]}, "channel_raw": {"type": ["string", "null"]}}, "required": ["arm_no", "exp_no", "arm_raw", "metric_raw", "users", "conversions", "started_at", "ended_at"]}지표별 판독 기준표입니다. 규칙 번호와 지표, 최소 표본, 최소 기간, 최소 차이, 담당을 한 행에 둡니다. 지표마다 필요한 표본과 기간이 달라 같은 실험도 어느 지표를 보느냐로 결론 시점이 갈립니다. 갈래 기록에 나오는 지표 중 일부는 일부러 넣지 않아 미선언이 도출되게 둡니다.
| rule_no | metric_raw | min_users | min_days | min_lift | owner_name |
|---|---|---|---|---|---|
| RR-01 | signup_rate | 2,000 | 10 | 0.1 | 그로스 |
| RR-02 | paid_rate | 4,000 | 14 | 0.1 | 그로스 |
| RR-03 | share_rate | 2,000 | 10 | 0.15 | 그로스 |
| RR-04 | retention_d7 | 4,000 | 14 | 0.05 | 프로덕트 |
| RR-05 | purchase_rate | 4,000 | 14 | 0.1 | 그로스 |
아래 JSON Schema 를 그대로 만족하는 판독 기준 행을 20개 더 만들어 주세요. 지표마다 최소 표본을 천에서 오천 사이로, 최소 기간을 이레에서 삼 주 사이로 다르게 두고 최소 차이는 0.05 에서 0.2 사이로 둡니다. 갈래 기록에 나오는 지표 중 일부는 일부러 넣지 마세요 — 미선언이 있어야 기준표의 구멍이 드러납니다. 판정 결과는 넣지 마세요.
{"type": "object", "properties": {"rule_no": {"type": "string"}, "metric_raw": {"type": "string"}, "min_users": {"type": "integer"}, "min_days": {"type": "integer"}, "min_lift": {"type": "number"}, "owner_name": {"type": "string"}}, "required": ["rule_no", "metric_raw", "min_users", "min_days", "min_lift", "owner_name"]}{"type": "object", "properties": {"rule_no": {"type": "string"}, "metric_raw": {"type": "string"}, "min_users": {"type": "integer"}, "min_days": {"type": "integer"}, "min_lift": {"type": "number"}, "owner_name": {"type": "string"}}, "required": ["rule_no", "metric_raw", "min_users", "min_days", "min_lift", "owner_name"]}| TypeScript | 갈래 기록과 판독 기준을 맞춰 전환율과 기간을 견주는 판정기를 맡습니다. |
| Node.js | CLI 실행기와 기록 읽기를 맡습니다. |
| PostgreSQL | 실험 갈래 기록과 판정 결과를 담습니다. |
| Markdown | 실험별 판독 리포트와 남은 기간 표를 파일로 냅니다. |
✗ fail → 미선언이 절반을 넘으면 기준표를 먼저 채웁니다.
✓ pass → 2주차 예제 서비스 기록으로 넘어갑니다.
✗ fail → 어긋난 지표를 모아 최소 표본과 기간을 다시 봅니다.
✓ pass → 3주차 남은 기간 계산으로 넘어갑니다.
실험 갈래 하나와 판독 기준이 만나는 자리마다 결론을 내도 되는지 정합니다. 미루면 표본 부족·기간 부족·차이 작음·전환 없음·미선언 중 어느 쪽인지 싣습니다. 리포트는 이 사유 코드로 묶습니다.
{"type": "object", "properties": {"verdict_no": {"type": "string"}, "arm_no": {"type": "string"}, "exp_no": {"type": "string"}, "metric_raw": {"type": "string"}, "rule_no": {"type": ["string", "null"]}, "readout_code": {"type": "string", "enum": ["callable", "sample_too_small", "period_too_short", "lift_too_small", "conversions_missing", "metric_undeclared"]}, "conv_rate": {"type": ["number", "null"], "description": "conversions 를 users 로 나눈 전환율입니다. 두 값이 모두 있는 갈래에만 채웁니다."}, "min_users": {"type": ["integer", "null"]}, "owner_name": {"type": ["string", "null"]}, "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": ["verdict_no", "arm_no", "exp_no", "metric_raw", "readout_code", "evidence", "summary"]}[
{
"verdict_no": "RD-001",
"arm_no": "AR-002",
"exp_no": "EX-01",
"metric_raw": "signup_rate",
"rule_no": "RR-01",
"readout_code": "callable",
"conv_rate": 0.11,
"min_users": 2000,
"owner_name": "그로스",
"evidence": [
{
"field": "users",
"agg": null,
"value": 4180
},
{
"field": "min_users",
"agg": null,
"value": 2000
}
],
"summary": "표본과 기간이 기준을 넘고 차이도 충분해 결론을 내도 됩니다.",
"hedge": null
},
{
"verdict_no": "RD-002",
"arm_no": "AR-004",
"exp_no": "EX-02",
"metric_raw": "signup_rate",
"rule_no": "RR-01",
"readout_code": "sample_too_small",
"conv_rate": 0.1,
"min_users": 2000,
"owner_name": "그로스",
"evidence": [
{
"field": "users",
"agg": null,
"value": 880
},
{
"field": "min_users",
"agg": null,
"value": 2000
}
],
"summary": "880명은 기준 2000명에 못 미쳐 차이가 커 보여도 결론을 미룹니다.",
"hedge": null
},
{
"verdict_no": "RD-003",
"arm_no": "AR-003",
"exp_no": "EX-02",
"metric_raw": "Signup Rate",
"rule_no": "RR-01",
"readout_code": "period_too_short",
"conv_rate": 0.08,
"min_users": 2000,
"owner_name": "그로스",
"evidence": [
{
"field": "metric_raw",
"agg": null,
"value": "Signup Rate"
},
{
"field": "min_days",
"agg": null,
"value": 10
}
],
"summary": "지표 이름을 띄어쓰기로 적었으나 접으면 같은 값이고, 이레만 돌아 기간이 모자랍니다.",
"hedge": null
},
{
"verdict_no": "RD-004",
"arm_no": "AR-006",
"exp_no": "EX-03",
"metric_raw": "paid_rate",
"rule_no": "RR-02",
"readout_code": "period_too_short",
"conv_rate": 0.044,
"min_users": 4000,
"owner_name": "그로스",
"evidence": [
{
"field": "started_at",
"agg": null,
"value": "2026-08-01"
},
{
"field": "min_days",
"agg": null,
"value": 14
}
],
"summary": "사흘만 돌아 주중과 주말이 다 들어가지 않았습니다.",
"hedge": null
},
{
"verdict_no": "RD-005",
"arm_no": "AR-007",
"exp_no": "EX-04",
"metric_raw": "share_rate",
"rule_no": "RR-03",
"readout_code": "conversions_missing",
"conv_rate": null,
"min_users": 2000,
"owner_name": "그로스",
"evidence": [
{
"field": "conversions",
"agg": null,
"value": null
},
{
"field": "users",
"agg": null,
"value": 3200
}
],
"summary": "기준 갈래의 전환 수가 안 남아 견줄 상대가 없습니다.",
"hedge": null
},
{
"verdict_no": "RD-006",
"arm_no": "AR-010",
"exp_no": "EX-05",
"metric_raw": "retention_d7",
"rule_no": "RR-04",
"readout_code": "lift_too_small",
"conv_rate": 0.225,
"min_users": 4000,
"owner_name": "프로덕트",
"evidence": [
{
"field": "conversions",
"agg": null,
"value": 1113
},
{
"field": "min_lift",
"agg": null,
"value": 0.05
}
],
"summary": "기준 갈래와 차이가 기준선에 못 미쳐 바뀐 것으로 보기 어렵습니다.",
"hedge": null
},
{
"verdict_no": "RD-007",
"arm_no": "AR-012",
"exp_no": "EX-06",
"metric_raw": "nps_reply",
"rule_no": null,
"readout_code": "metric_undeclared",
"conv_rate": 0.111,
"min_users": null,
"owner_name": null,
"evidence": [
{
"field": "metric_raw",
"agg": null,
"value": "nps_reply"
},
{
"field": "rule_no",
"agg": "count",
"value": 12
}
],
"summary": "기준 열두 행에 없는 지표라 얼마나 모아야 결론이 서는지 정해 두지 않았습니다.",
"hedge": "끝난 날도 비어 아직 도는 실험일 수 있습니다."
},
{
"verdict_no": "RD-008",
"arm_no": "AR-008",
"exp_no": "EX-04",
"metric_raw": "share_rate",
"rule_no": "RR-03",
"readout_code": "conversions_missing",
"conv_rate": 0.132,
"min_users": 2000,
"owner_name": "그로스",
"evidence": [
{
"field": "users",
"agg": null,
"value": 3180
},
{
"field": "min_users",
"agg": null,
"value": 2000
}
],
"summary": "이 갈래는 다 채웠지만 짝이 되는 기준 갈래가 비어 함께 미룹니다.",
"hedge": null
}
][자동 검증 · 코드가 판정합니다] 1. readout_code 가 enum 여섯 값 중 하나인지 확인합니다. 2. verdict_no·arm_no·exp_no·metric_raw·readout_code·evidence·summary 가 모두 채워졌는지 확인합니다. 3. arm_no 가 갈래 기록에 실재하는 번호인지 대조합니다. 4. rule_no 가 있으면 기준표에 실재하는 행 번호인지 대조합니다. 5. rule_no 가 있으면 min_users·owner_name 이 그 기준 행의 값과 같은지 대조합니다. 6. metric_raw 를 대소문자와 띄어쓰기를 접어 기준표와 맞추고, 맞는 행이 없으면 readout_code 가 metric_undeclared 인지 확인합니다. 7. conv_rate 를 conversions 를 users 로 나눠 다시 계산합니다. 8. conversions 나 users 가 비었거나 같은 실험의 기준 갈래가 비었으면 readout_code 가 conversions_missing 인지 확인합니다. 9. users 가 min_users 에 못 미치면 readout_code 가 sample_too_small 인지 다시 확인합니다. 10. started_at 과 ended_at 사이 날수가 min_days 에 못 미치거나 ended_at 이 비면 readout_code 가 period_too_short 인지 다시 계산합니다. 11. 같은 실험 기준 갈래의 전환율과 견준 차이가 min_lift 에 못 미치면 readout_code 가 lift_too_small 인지 다시 계산합니다. 12. readout_code 가 callable 이면 위 검사를 모두 통과하는지 다시 확인합니다. 13. evidence 의 field 이름이 갈래 기록과 기준표에 실재하는 컬럼인지 대조합니다. 14. agg 가 없는 evidence 의 value 가 그 컬럼에 수록된 행 값과 같은지 확인합니다. 15. summary 가 존댓말로 끝나는지 확인합니다. [평가 러너 · 2주차] 예제 서비스에서 쌓은 갈래 300건에 손으로 계산한 정답 판정과 대조해 일치율과 사유 코드별 분포를 내고, 미선언이 몰리는 지표를 목록으로 냅니다. [수동 검증 · 사람이 봅니다] 1. 새 지표의 최소 표본과 기간을 그로스 담당이 정합니다. 2. 결론 가능으로 나온 실험을 반영할지 사람이 판단합니다.