레브잇
경력근거: LLM을 활용해 상품의 모든 속성(제품 속성 및 체감 속성 등)을 추출하고 체계화하는
레브잇 PMF팀은 10~20년 쌓인 전통 가격비교를 넘어 LLM 으로 상품의 제품 속성·체감 속성을 추출하고 체계화하는 카탈로그를 만듭니다. 뽑는 것보다 어려운 쪽은 어떤 값을 표준으로 확정해 남길지이고, 그 판단은 패션·뷰티·건강식품처럼 표기가 제각각인 카테고리를 매일 보는 운영자만 내릴 수 있어 화면이 필요합니다. 이 포트폴리오가 보여주는 것은 LLM 후보 추출·스키마 강제·사람이 결정을 내리는 화면 설계 역량이며, 특정 카테고리 상품 전문성은 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
레브잇 PMF팀은 LLM 으로 상품의 모든 속성(제품 속성·체감 속성)을 추출·체계화하는 카탈로그 시스템을 초기부터 만듭니다. 뽑은 값을 무엇으로 확정해 카탈로그에 남길지가 그 시스템의 핵심입니다.
LLM 라이브러리로 서비스·파이프라인을 구축하고 프롬프트 엔지니어링·성능 개선을 해본 사람을 찾습니다. 후보 추출 파이프라인과 사람이 확정하는 화면을 한 사슬로 붙인 구성이 JD 요구와 맞습니다.
초기 스타트업에서 핵심 제품을 주도하고 AI 제품 실험을 직접 설계해본 경험을 우대합니다. 운영자의 확정이 사전 규칙을 갱신해 자동 확정 비율이 오르는 루프를 직접 설계합니다.
LLM 이 상품 원문에서 뽑은 속성 후보를 곧바로 카탈로그에 넣지 않고 확정 대기 큐에 세워 두고, 운영자가 화면에서 후보를 고르거나 새 표준값을 직접 입력하거나 근거 없는 값을 버려야 그 상품이 카탈로그에 반영되는 검수 화면입니다. 확정한 표기는 속성 사전에 별칭으로 쌓여 다음 상품부터는 규칙 매칭만으로 자동 확정됩니다. 근거는 채용공고 정렬입니다.
상품 원문 수천 건의 속성을 표에 옮겨 적다가 사람마다 표기가 달라져 같은 상품이 두 값으로 남는 게 괴로운, 레브잇 카탈로그를 매일 손보는 사내 운영자입니다.
뽑은 값을 자동으로 확정하지 않고 운영자가 화면에서 고르게 하면, (a) 근거 없는 값과 제목·리뷰가 어긋난 값이 카탈로그에 들어가지 않고, (b) 운영자가 고른 표기가 사전 별칭으로 쌓여 다음 상품이 규칙만으로 자동 확정되며, (c) 화면에 남는 대기 건수가 줄어드는 것으로 개선이 눈에 보입니다.
상품 하나를 열면 왼쪽에 근거 문장이 하이라이트된 원문, 오른쪽에 속성 카드가 뜨고, 후보 선택·새 표준값 입력·폐기 셋 중 하나를 모든 카드에 정해야 반영 버튼이 열려 카탈로그에 커밋되는 화면입니다. 확정한 표기는 사전에 별칭으로 쌓여 같은 표기의 대기 건이 자동 확정으로 큐에서 빠집니다.
누가 언제 무엇을 골랐는지 남기고, 잘못 확정한 건과 잘못 자동 확정된 건을 큐로 되돌려 사전 별칭을 고치는 감사 화면입니다.
패션 외 뷰티·건강식품의 속성 축을 화면에서 새로 정의하고, 확정된 카탈로그로 속성 조건 검색이 실제로 도는 것까지 잇는 단계입니다.
대기 12건이 쌓인 큐를 화면에서 하나씩 확정해 카탈로그에 반영되는 데까지 시연합니다. 확정을 누르기 전에는 그 상품이 카탈로그 조회에 나오지 않는 것도 같이 보여줍니다
일부러 만든 어려운 건(근거 없는 과장 광고문, 상세정보가 준비 중인 빈 원문, 제목과 상세가 어긋나는 혼용률, 사전에 없는 표기)은 자동으로 넘어가지 않고 사람이 정해야만 큐에서 빠지는 걸 보여줍니다
2주차 기준으로 30건을 확정하고 나면 사전에 쌓인 별칭 덕분에 다음 30건 중 11건(약 37%)이 규칙 매칭만으로 자동 확정돼 화면에 뜨지 않습니다. 단, 표기 분포를 작성자가 만든 합성 기준이라 '성능 검증'이 아니라 '데모 조건에서의 동작'임을 명시합니다
3주차에는 자동 확정된 건 중 잘못 걸린 2건을 감사 화면에서 큐로 되돌려 별칭을 고치는 과정을 보여줍니다. 자동 확정을 늘리면 오확정도 함께 는다는 걸 숨기지 않습니다
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 전부 작성자가 만든 더미데이터 자가채점이며, 실제 확정 속도와 오확정률은 레브잇 실 상품 원문과 실제 카탈로그 운영자가 있어야 측정 가능합니다. 이 화면은 그 측정을 바로 돌릴 수 있는 상태로 만듭니다.
이건 고객·실데이터 없이 혼자 만든 포트폴리오입니다. 모든 수치는 합성 데이터 자가채점이라 '성능 증명'이 아닙니다. 면접에서 '데모 조건 동작 + 실검증 준비 상태'로 솔직히 설명합니다
확정 대상을 작성자가 직접 고르니 잘 맞는 게 당연합니다. 근거 없는 과장 광고문·빈 원문·제목과 상세가 어긋난 혼용률·사전에 없는 표기를 더미에 일부러 섞어, 쉬운 건만 확정하는 게 아님을 보여줍니다
자동 확정은 편해지는 만큼 위험합니다. 별칭 하나를 잘못 등록하면 뒤따르는 상품이 조용히 같은 값으로 굳으므로, 자동 확정 건을 따로 표시하고 되돌리기와 이력을 함께 만듭니다
체감 속성은 리뷰 표현이 주관적이라 후보 자체가 흔들립니다. 값마다 근거 문장을 원문에서 인용하게 하고, 원문에 없으면 근거 없음으로 표시해 사람이 폐기하도록 넘깁니다
이 포트폴리오가 보여주는 것은 후보 추출과 사람이 결정을 내리는 화면 설계 역량이며, 패션·뷰티·건강식품 카테고리의 상품 전문성은 주장하지 않습니다. 실제 도입 시 카테고리 속성 축을 다시 맞춰야 하고 확정 기준도 실제 운영자 기준으로 교체해야 합니다
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
상품 원문(제목·상세·리뷰) 문서입니다. 후보 추출의 입력이며 화면 왼쪽에 그대로 뜹니다. 속성이 없는 과장 광고문, 빈 원문, 제목과 상세가 어긋난 혼용률, 사전에 없는 표기를 일부러 섞어 쉬운 데이터만 다루는 게 아님을 보여줍니다.
소재는 면 100%이며 넉넉한 오버핏입니다. 실착 후기: 여름에 입어도 통풍이 잘 되고 두께가 적당해 비침이 없어요.
발색이 선명하고 지속력이 좋습니다. 리뷰: 물 마셔도 잘 안 지워지고 6시간은 유지돼요. 다만 살짝 건조한 느낌.
아래 JSON Schema 에 맞는 상품 원문 문서 30건 JSON 배열로 생성.
{"type":"object","properties":{"product_id":{"type":"string"},"category":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"}},"required":["product_id","category","title","body"]}
쉬운 데이터만 만들지 말 것. 하드 케이스 혼입: (1) 속성 정보 없이 과장 광고만 있는 원문 2건(후보가 '근거 없음'으로 떠 사람이 폐기해야 함), (2) body 가 '상세정보 준비 중'인 빈 원문 1건, (3) 제목과 상세의 값이 어긋나는 원문 2건(제목 '린넨 100%' vs 상세 '린넨 55%, 레이온 45%' 처럼 사람이 골라야 하는 충돌), (4) 사전 표준값에 없는 표기 2건(세미크롭핏 등, 새 표준값 등록 대상), (5) 같은 속성의 표기 흔들림(무향/무취/무향료). 카테고리는 패션·뷰티·건강식품·가전 섞어서. JSON 배열만.{"type":"object","properties":{"product_id":{"type":"string"},"category":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"}},"required":["product_id","category","title","body"]}화면에 뜨는 확정 대기 큐입니다. 상품 1건의 속성 1개가 한 행이고, 후보 목록과 근거 문장·플래그를 담습니다. 확정되기 전까지 이 행은 큐에 남고 카탈로그에는 존재하지 않습니다. 충돌·근거 없음·사전 미등록을 섞어, 사람이 정하지 않으면 넘어가지 못하는 흐름을 보여줍니다.
| queue_id | product_id | attr_id | candidates | flag |
|---|---|---|---|---|
| q_001 | p_001 | a_material | [{"value":"면 100%","source":"body","evidence_span":"소재는 면 100%이며"}] | single |
| q_002 | p_001 | a_fit | [{"value":"오버핏","source":"body","evidence_span":"넉넉한 오버핏입니다"}] | single |
| q_003 | p_001 | a_thickness | [{"value":"적당","source":"review","evidence_span":"두께가 적당해 비침이 없어요"}] | single |
| q_004 | p_002 | a_lasting | [{"value":"롱래스팅","source":"title","evidence_span":"롱래스팅 립틴트 로즈"},{"value":"6시간 유지","source":"review","evidence_span":"물 마셔도 잘 안 지워지고 6시간은 유지돼요"}] | single |
| q_005 | p_006 | a_power | [] | no_evidence |
아래 JSON Schema 에 맞는 확정 대기 큐 30행 JSON 배열로 생성.
{"type":"object","properties":{"queue_id":{"type":"string"},"product_id":{"type":"string"},"attr_id":{"type":"string"},"candidates":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"source":{"type":"string","enum":["title","body","review"]},"evidence_span":{"type":["string","null"]}},"required":["value","source"]}},"flag":{"type":"string","enum":["single","conflict","unmapped","no_evidence"]}},"required":["queue_id","product_id","attr_id","candidates","flag"]}
쉬운 데이터만 만들지 말 것. 하드 케이스 혼입: (1) flag=conflict 4건(title 과 body 후보 값이 서로 다름, 사람이 골라야 반영 버튼이 열림), (2) flag=no_evidence 3건(candidates 빈 배열), (3) flag=unmapped 3건(사전 표준값·별칭에 없는 표기), (4) 같은 attr_id 를 서로 다른 product_id 가 표기만 다르게 쓰는 행 4건(하나를 확정하면 나머지가 자동 확정되는 시연용). evidence_span 은 반드시 products_raw 의 body 부분 문자열로. JSON 배열만.{"type":"object","properties":{"queue_id":{"type":"string"},"product_id":{"type":"string"},"attr_id":{"type":"string"},"candidates":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"source":{"type":"string","enum":["title","body","review"]},"evidence_span":{"type":["string","null"]}},"required":["value","source"]}},"flag":{"type":"string","enum":["single","conflict","unmapped","no_evidence"]}},"required":["queue_id","product_id","attr_id","candidates","flag"]}카테고리별 속성 축과 표준값·별칭 사전입니다. 운영자가 화면에서 고른 표기가 여기 별칭으로 쌓여 다음 상품의 자동 확정 규칙이 됩니다. 별칭이 비어 있는 속성과 표준값이 '표기없음' 뿐인 속성을 섞어, 사전에 없는 표기를 만나면 자동으로 넘어가지 않고 사람에게 넘어가는지 보여줍니다.
| attr_id | category | attr_name | attr_type | canonical_values | aliases |
|---|---|---|---|---|---|
| a_fit | 패션 | 핏 | perceptual | ["오버핏","레귤러핏","슬림핏"] | ["루즈핏"] |
| a_material | 패션 | 소재 | product | ["면100%","폴리에스터","스판데님"] | ["코튼100","면 100"] |
| a_scent | 뷰티 | 향 | product | ["무향","플로럴","시트러스"] | ["무취","무향료"] |
| a_lasting | 뷰티 | 지속력 | perceptual | ["높음","보통","낮음"] | ["롱래스팅","오래감"] |
| a_finish | 뷰티 | 마무리감 | perceptual | ["매트","글로우","세미매트"] | — |
아래 JSON Schema 에 맞는 카테고리별 속성 사전 30행 JSON 배열로 생성.
{"type":"object","properties":{"attr_id":{"type":"string"},"category":{"type":"string"},"attr_name":{"type":"string"},"attr_type":{"type":"string","enum":["product","perceptual"]},"canonical_values":{"type":"array","items":{"type":"string"}},"aliases":{"type":["array","null"],"items":{"type":"string"}}},"required":["attr_id","category","attr_name","attr_type","canonical_values"]}
쉬운 데이터만 만들지 말 것. 하드 케이스 혼입: (1) aliases=null 인 별칭 미등록 속성 3건(원문 표기가 사전에 없어 화면에서 새 표준값을 등록해야 하는 대상), (2) canonical_values 가 ['표기없음']뿐인 속성 1건(값 없음 처리), (3) 두 표준값이 서로 겹치게 보이는 속성 2건(사람이 하나를 골라야 하는 경우), (4) attr_type 이 product/perceptual 고르게. enum 은 카테고리별로 갈아끼운다. JSON 배열만.{"type":"object","properties":{"attr_id":{"type":"string"},"category":{"type":"string"},"attr_name":{"type":"string"},"attr_type":{"type":"string","enum":["product","perceptual"]},"canonical_values":{"type":"array","items":{"type":"string"}},"aliases":{"type":["array","null"],"items":{"type":"string"}}},"required":["attr_id","category","attr_name","attr_type","canonical_values"]}| Python | 후보 추출 파이프라인(상품 원문 → LLM 후보 → 확정 대기 큐 적재), 사전 별칭 매칭 기반 자동 확정 규칙 |
| TypeScript | Next.js 확정 화면(대기 큐 목록, 원문 하이라이트, 속성 카드의 선택·입력·폐기 조작, 전부 결정해야 열리는 반영 버튼, 키보드로 다음 건 이동) |
| PostgreSQL | products_raw / review_queue / attr_dictionary / catalog_rows / decisions 단일 진실원. 확정 전 상품은 catalog_rows 에 존재하지 않습니다 |
| LLM | Claude 로 속성 후보와 근거 문장을 제안하되 확정은 하지 않습니다. 카테고리 속성 축을 few-shot 으로 주입합니다 |
| Prompt Engineering | 카테고리별 속성 스키마 강제 프롬프트 + 근거 문장 원문 인용 필수 + 원문에 없는 값은 근거 없음으로 표시 |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우고 싶으면 2주차(확정 이력과 되돌리기)로 진행합니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우면 3주차(카테고리 속성 축 추가와 조건 검색 연결)로 진행합니다.
운영자가 화면에서 대기 카드 하나에 내린 확정 기록입니다. 무엇을 골랐는지 또는 새로 넣었는지, 그 근거 문장이 무엇인지, 사전에 어떤 별칭이 추가됐는지, 그 덕분에 몇 건이 자동 확정돼 큐에서 빠졌는지를 담습니다. 카탈로그 행은 이 기록이 있을 때만 생성됩니다.
{"type":"object","properties":{"decision_id":{"type":"string"},"queue_id":{"type":"string"},"product_id":{"type":"string"},"attr_id":{"type":"string"},"action":{"type":"string","enum":["pick","new_value","discard"]},"chosen_value":{"type":["string","null"]},"evidence_span":{"type":["string","null"]},"alias_learned":{"type":["string","null"]},"auto_confirmed_after":{"type":"integer","minimum":0},"decided_by":{"type":"string"}},"required":["decision_id","queue_id","product_id","attr_id","action","chosen_value","auto_confirmed_after","decided_by"]}[
{
"decision_id": "d_001",
"queue_id": "q_001",
"product_id": "p_001",
"attr_id": "a_material",
"action": "pick",
"chosen_value": "면100%",
"evidence_span": "소재는 면 100%이며",
"alias_learned": "면 100%",
"auto_confirmed_after": 1,
"decided_by": "operator_a"
},
{
"decision_id": "d_002",
"queue_id": "q_005",
"product_id": "p_006",
"attr_id": "a_power",
"action": "discard",
"chosen_value": null,
"evidence_span": null,
"alias_learned": null,
"auto_confirmed_after": 0,
"decided_by": "operator_a"
},
{
"decision_id": "d_003",
"queue_id": "q_011",
"product_id": "p_013",
"attr_id": "a_material",
"action": "pick",
"chosen_value": "린넨 55% 레이온 45%",
"evidence_span": "실제 혼용률은 린넨 55%, 레이온 45%입니다",
"alias_learned": null,
"auto_confirmed_after": 0,
"decided_by": "operator_b"
},
{
"decision_id": "d_004",
"queue_id": "q_012",
"product_id": "p_014",
"attr_id": "a_fit",
"action": "new_value",
"chosen_value": "세미크롭핏",
"evidence_span": "밑단이 살짝 짧은 세미크롭핏입니다",
"alias_learned": "세미크롭",
"auto_confirmed_after": 2,
"decided_by": "operator_b"
}
][자동 검증] 1. 출력이 스키마를 통과하는가(필수 필드·타입·enum). 2. action 이 pick 이면 chosen_value 가 그 queue 행의 candidates 값 또는 사전 표준값과 일치하는가(화면에 없던 값이 몰래 들어오지 못하게 차단). 3. action 이 pick·new_value 면 evidence_span 이 실제 원문 body 의 부분 문자열인가, discard 면 chosen_value·evidence_span 이 모두 null 인가. 4. alias_learned 는 표준값 하나에만 붙는가(같은 별칭이 두 표준값에 붙으면 실패). 5. auto_confirmed_after 를 사전 갱신 후 문자열 매칭으로 다시 계산해 같은 수가 나오는가(자동 확정이 규칙으로 재현되는지). 6. decision 이 없는 queue 행이 catalog_rows 에 존재하는가(하나라도 있으면 실패). [수동 검증] 1. 충돌·근거 없음·사전 미등록 카드를 사람 선택 없이 지나칠 수 있는 경로가 있는지 화면에서 클릭으로 확인합니다. 2. 체감 속성 확정이 리뷰 표현을 과장 해석하지 않는지 확정 건의 5%를 다시 봅니다.