오픈서베이 Dataspace는 설문 설계부터 정제·검증까지 자동화하는 리서치 플랫폼이라, 응답 품질을 점검하고 결과를 요약하는 이 도구는 오픈서베이의 실제 설문 응답 데이터가 있어야 필터를 검증한다.
'설문 설계부터 응답·수집·정제·검증·분석·보고서까지' 자동화가 미션. 그 중 정제·검증·요약 한 토막을 1주에 닫는 게 직접적 가치.
합성 패널이 응답을 학습해 시장 반응을 예측. 입력 응답 품질이 곧 예측 품질이라 불성실 응답 탐지가 핵심.
Python·FastAPI·React 풀스택으로 데이터 파이프라인을 제품으로 만드는 직무. ingest→검증→요약 흐름이 직무와 정렬.
설문 응답 로그를 받아 불성실·모순·결측 응답을 자동으로 표시하고, 정제된 응답으로 문항별 핵심 결과를 요약해 근거와 함께 보여주는 1주 포트폴리오.
오픈서베이 PE. 응답 데이터의 불성실 답변을 매번 손으로 걸러내고 요약하던 상황을 끝내고, 그 정제·요약을 자동 도구로 옮기고 싶은 사람.
응답 로그에 문항 메타(타입·정상범위)를 붙이면, LLM/규칙이 (a) 불성실·모순·결측 응답을 근거와 함께 표시하고, (b) 정제된 응답으로 문항별 결과를 요약한다.
설문 응답을 받아 불성실·모순·결측을 표시하고 정제된 응답으로 문항별 결과를 요약해 근거와 함께 보여주는 동작하는 도구.
사람 검수 라벨 대비 불성실 탐지 일치도(놓침/오탐)와 문항 요약 정확도를 보여주는 대시보드.
정제→요약→리포트를 파이프라인으로 묶고 다중 설문을 배치 처리해, 리서처가 결과 해석에만 집중하는 단계.
불성실·악성·결측 응답 30종(직진응답·모순·욕설·빈응답 포함)을 넣어도 필터가 플래그를 놓치지 않는 걸 시연한다
정제된 응답을 넣으면 문항별 결과 요약이 근거와 함께 몇 초 안에 나오는 걸 시연한다
모든 품질 라벨·요약 출력이 형식 검증(Zod)을 통과
측정: 자동 parse, 표본: 응답 100건
불성실 응답 라벨 30개 중 25개가 내가 만든 정답과 일치. 단, 정답·데이터를 작성자가 만든 합성 기준이라 '성능 검증'이 아니라 '데모 조건 동작'
위 수치는 더미데이터 자가채점이며, 실제 불성실 탐지·요약 정확도는 오픈서베이 실제 응답 데이터 + 리서처 검수가 있어야 측정 가능. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태까지 만든다.
이건 고객·실데이터 없이 혼자 만든 포트폴리오라 모든 수치는 합성 데이터 자가채점이다. 면접에서 '데모 동작 + 실검증 준비 상태'로 솔직히 설명하는 게 오히려 신뢰를 준다
정답을 내가 만들었으니 잘 맞는 게 당연. 그래서 직진응답·모순쌍·무의미 주관식·빈응답 같은 헷갈리는 케이스를 더미에 일부러 섞어 쉬운 문제만 푸는 게 아님을 보여준다
'불성실'의 기준은 설문 목적마다 다름. 규칙을 문항 메타로 외부화하고, 애매한 건 단정하지 말고 '검토 필요'로 표시
실제 도입 시 달라지는 것: 실 응답 분포·문항 수·언어가 더미와 다르므로 불성실 규칙과 정상범위를 실데이터로 다시 맞춰야 한다(도입 단계 과제)
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
한 응답자의 문항별 응답 로그. 불성실 탐지·요약 LLM 이 가장 먼저 보는 표. 결측·직진응답·모순·이상 소요시간을 일부러 섞었다.
| resp_id | q_id | q_type | answer | elapsed_sec | straightlined |
|---|---|---|---|---|---|
| r_001 | q1 | scale | 4 | 6.2 | false |
| r_001 | q2 | single | B | 3.1 | false |
| r_001 | q3 | open | 디자인이 깔끔해서 좋았어요 | 21.5 | false |
| r_002 | q1 | scale | 5 | 0.8 | true |
| r_002 | q2 | single | 5 | 0.7 | true |
아래 Zod 스키마에 맞는 설문 응답 로그 80행 JSON 배열로 생성.
z.object({ resp_id: z.string(), q_id: z.string(), q_type: z.enum(["single","scale","open"]), answer: z.string().nullable(), elapsed_sec: z.number().nullable(), straightlined: z.boolean() })
쉬운 데이터만 만들지 말 것. 하드 케이스 의도적 혼입: (1) 직진응답(straightlined=true, 모든 척도 동일+소요시간<1s) 응답자 1~2명, (2) 주관식 무의미 답변('ㅁㄴㅇㄹ', 'asdf') 3건, (3) answer/elapsed_sec=null 결측 각 1~2건, (4) 척도-주관식 모순(별점 최고+불만 텍스트) 1건, (5) 문항지에 없는 q_id(orphan) 1건, (6) 비정상 소요시간(>600s 또는 <1s) 각 1건. JSON 배열만.z.object({ resp_id: z.string(), q_id: z.string(), q_type: z.enum(["single","scale","open"]), answer: z.string().nullable(), elapsed_sec: z.number().nullable(), straightlined: z.boolean() })| Python | 응답 ingest + 불성실 응답 규칙(직진응답·소요시간·모순) + 요약 LLM 호출 |
| FastAPI | 검증·요약 API (`POST /clean`. 응답 배열 → 품질 라벨 + 요약) |
| TypeScript | 품질 리포트 UI + Zod 런타임 검증 |
| React | 문항별 결과·플래그 사유 카드 렌더 |
✓ pass → 그대로 멈춰도 완성품. 더 키우려면 2주차(불성실 탐지·요약이 정확한지 검증)로.
✓ pass → 여기서 멈춰도 완결. 더 키우려면 3주차(리서치 리포트 자동화)로.
응답자/문항 단위 품질 판정 + 문항별 요약 출력. 플래그 사유 + 정제 결과 + 근거.
z.object({ resp_id: z.string(), quality_flags: z.array(z.enum(["straightline","gibberish","contradiction","missing","speeding","none"])).min(1), keep: z.boolean(), evidence: z.array(z.object({ field: z.string(), quote: z.string() })).min(1), summary_note: z.string().nullable() })[
{
"resp_id": "r_002",
"quality_flags": [
"straightline",
"speeding",
"gibberish"
],
"keep": false,
"evidence": [
{
"field": "straightlined",
"quote": "true"
},
{
"field": "elapsed_sec",
"quote": "0.7"
}
],
"summary_note": "직진+초고속+무의미 주관식 → 제외 권장"
},
{
"resp_id": "r_003",
"quality_flags": [
"missing",
"contradiction"
],
"keep": false,
"evidence": [
{
"field": "answer",
"quote": "전혀 만족 안 하는데 별점은 최고로 줬어요"
}
],
"summary_note": "척도-주관식 모순, 일부 결측"
},
{
"resp_id": "r_001",
"quality_flags": [
"none"
],
"keep": true,
"evidence": [
{
"field": "elapsed_sec",
"quote": "21.5"
}
],
"summary_note": null
}
]자동: (1) Zod parse, (2) evidence.field 가 입력 스키마 실제 필드명인지, (3) keep=false 면 quality_flags 에 none 외 사유가 있는지 규칙 체크. 수동/judge: 주관식 무의미 판정은 LLM-as-judge + 5% 사람 확인.