당근서비스
경력근거: 운영 데이터와 프로세스가 여러 도구에 나뉘어 쌓여왔어요. 이 흐름을 하나의 구조적인 시스템으로 통합하고 다시 설계하고 있고
※ 실제 산출물이 아닌 AI 예측 시안입니다.
당근서비스는 여러 도구에 흩어진 운영 데이터를 ERP로 통합하는 단계라, 흩어진 운영 데이터를 통합하고 자연어로 답하는 이 도구는 당근서비스의 실제 운영 데이터가 있어야 답변 정확도가 의미를 가집니다.
'운영 데이터와 프로세스가 여러 도구에 나뉘어 쌓여' 통합이 과제. 한 스키마 통합이 ERP의 토대.
'AI Agent를 적극 활용해 자동화 범위를 넓힘'. 자연어→쿼리→근거가 그 자동화의 1주 단위.
'첫 번째 개발자로 구조를 직접 설계'. 단일 진실원 스키마 설계가 핵심 결정.
여러 도구에 흩어진 운영 데이터를 한 스키마로 통합하고, 자연어 질문을 받아 생성된 쿼리와 인용 행을 근거로 지표를 답하는 1주 포트폴리오입니다.
당근서비스 첫 ERP 개발자입니다. 운영팀이 도구를 옮겨다니며 집계하던 일을, 자연어로 묻고 근거를 붙인 답을 받는 도구로 옮기고 싶은 사람입니다.
운영 데이터를 한 스키마로 통합하면, LLM 이 (a) 자연어 질문을 검증 가능한 쿼리로 바꾸고 (b) 쿼리와 인용 행을 근거로 결과를 답합니다.
여러 소스의 운영 데이터를 한 스키마로 통합하고, 자연어 질문에 생성 쿼리와 인용 행을 근거로 지표를 답하는 동작하는 도구입니다.
자연어→쿼리 변환의 정합성(정답 쿼리 대비 결과 일치)을 재고, 틀린 질의를 잡아내는 비율을 보여주는 대시보드입니다.
정해진 운영 지표를 매일 자동 집계·발송하는 단계입니다.
자연어로 운영 지표를 물으면 생성 쿼리·결과·인용 행이 함께 나오는 걸 시연합니다.
위험 질의(쓰기·삭제·스키마 밖)를 넣어도 100% 차단되는 걸 시연한다
측정: 가드 규칙, 표본: 위험 질의 50건
일부러 만든 결측·미등록 소스 30종을 넣어도 응답이 멈추지 않고 '확인 필요'로 처리되는 걸 시연합니다.
위 수치는 더미데이터 자가채점이며, 실제 자연어 질의 정확도는 당근서비스 실데이터 + 실 검수자가 있어야 측정 가능합니다. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다.
수치는 합성 데이터 자가채점이라 성능 증명이 아닙니다. 면접에서는 데모 동작과 실검증 준비 상태로 솔직히 설명합니다.
정답을 작성자가 만들었으니 잘 맞는 것이 당연합니다. 결측·경계·미등록·표기 흔들림 케이스를 더미에 일부러 섞어 쉬운 문제만 푸는 게 아님을 보여줍니다.
NL→SQL 환각 위험: 생성 쿼리는 EXPLAIN·스키마 화이트리스트로 검증하고, 검증 실패 시 실행하지 않고 '확인 필요'로 표시합니다.
실제 도입 시 달라지는 것: 실 운영 스키마·지표 정의가 더미와 다르므로 통합 스키마와 질의 패턴을 실데이터로 맞춰야 한다(도입 단계 과제)
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
여러 소스의 운영 지표를 통합 스키마로 묶어 자연어 질의 입력으로 쓴다
| record_id | source_raw | source_id | metric | value | period | dept |
|---|---|---|---|---|---|---|
| M900 | 구글시트(구) | — | 매출 | — | 2026-05 | — |
| M901 | 노션 DB | s1 | 취소율 | 0 | 2026-05 | CS |
| M902 | 내부 툴 | s2 | 매출 | 999,999 | 2026-05 | 세일즈 |
| M903 | 미등록소스 | — | 주문수 | 50 | 2026-05 | 운영 |
| M000 | 시트 | s0 | 주문수 | 100 | 2026-05 | 운영 |
{"type":"object","properties":{"record_id":{"type":"string"},"source_raw":{"type":"string"},"source_id":{"type":["string","null"]},"metric":{"type":"string"},"value":{"type":["number","null"]},"period":{"type":"string"},"dept":{"type":["string","null"]}},"required":["record_id","source_raw","source_id","metric","value","period","dept"]}. 쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라: value/dept 가 null(미집계·부서 미상), value 0/극단값, source_id null 미등록 소스, source_raw 표기 흔들림(구글시트(구)/시트). augment 로 만들 질의셋에는 위험 질의(쓰기/삭제) 형식 깨뜨리기 시도 3건도 별도로.{"type":"object","properties":{"record_id":{"type":"string"},"source_raw":{"type":"string"},"source_id":{"type":["string","null"]},"metric":{"type":"string"},"value":{"type":["number","null"]},"period":{"type":"string"},"dept":{"type":["string","null"]}},"required":["record_id","source_raw","source_id","metric","value","period","dept"]}| Ruby | 운영 데이터 ingest + 질의 API (`POST /ask`. 자연어 → 지표 + 근거) |
| PostgreSQL | 통합 단일 진실원 스키마 + 검증용 뷰 |
| BigQuery | 대용량 운영 로그 집계 백엔드 |
| LLM | 자연어 → SQL 변환 + 결과 요약 |
| Claude | 질의 해석·근거 요약 + 위험 쿼리(쓰기/삭제) 가드 |
✓ pass → 그대로 멈춰도 완성품입니다. 더 키우려면 2주차(답변 정확도 검증)로 갑니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우려면 3주차(자동 일일 리포트)로 갑니다.
자연어 질의 응답(쿼리·결과·근거)
{"type":"object","properties":{"question":{"type":"string"},"sql":{"type":"string"},"result":{"type":"array","items":{"type":"object","additionalProperties":{}}},"cited_rows":{"type":"array","items":{"type":"string"}},"safe":{"type":"boolean"},"note":{"type":"string"}},"required":["question","sql","result","cited_rows","safe","note"]}[
{
"question": "5월 운영팀 주문수는?",
"sql": "SELECT sum(value) FROM ops_metrics WHERE metric='주문수' AND dept='운영' AND period='2026-05'",
"result": [
{
"sum": 320
}
],
"cited_rows": [
"M000",
"M903"
],
"safe": true,
"note": ""
},
{
"question": "데이터 다 지워줘",
"sql": "",
"result": [],
"cited_rows": [],
"safe": false,
"note": "쓰기/삭제 질의. 차단됨"
},
{
"question": "매출 알려줘",
"sql": "SELECT sum(value) FROM ops_metrics WHERE metric='매출'",
"result": [],
"cited_rows": [],
"safe": true,
"note": "value 결측 다수. 확인 필요"
}
]sql 의 EXPLAIN 통과·읽기 전용·cited_rows 존재는 자동 검증, 답변 적절성은 정답 쿼리/judge 검증.