기산전자
경력근거: 최종 소비자와 매장 운영자의 VOC·사용 행태를 파악하여 실제 문제를 정의
※ 실제 산출물이 아닌 AI 예측 시안입니다.
기산전자 연구본부는 이 자리에 최종 소비자와 매장 운영자의 VOC·사용 행태로 실제 문제를 정의하는 일을 맡기고, 해결은 REST API/JSON 으로 자사 AI·결제·플랫폼과 연계해 Payment·AI/Vision·Platform 도메인 오너와 함께 하라고 적었습니다. 결제 승인과 AI 상품 인식이 한 기기 안에서 차례로 일어나는 키오스크·POS 제품이라서, VOC 한 건을 어느 단계 문제로 보고 어느 도메인 오너에게 넘길지가 곧 우선순위이고 이 판정은 그 제품의 단계 로그가 있어야 성립합니다. 이 포트폴리오는 VOC 와 사용 로그를 시각과 단계로 맞춰 재현 여부를 세는 규칙, 그리고 그 결과를 여러 사람이 함께 보는 화면을 보여줍니다. VAN·PG 승인망이나 비전 인식 모델 내부에 대한 전문성은 주장하지 않습니다.
주요업무 첫 줄이 최종 소비자와 매장 운영자의 VOC·사용 행태를 파악해 실제 문제를 정의하는 일입니다. 운영자가 전화나 게시판으로 남긴 불만이 정말 제품 결함인지부터 가려야 우선순위를 세울 수 있습니다.
Figma 와 코딩 Agent 로 동작하는 SW 를 빠르게 만들고, REST API/JSON 으로 자사 AI·결제·플랫폼과 연계해 PoC·QA 를 하는 자리입니다. 기기 사용 로그를 JSON 으로 받아 VOC 와 맞춰 보는 화면이 그 연계를 직접 다룹니다.
자격요건에 테스트 시나리오·예외 케이스·로그·데이터로 결과물을 검증하는 능력이 있고, 개선은 Payment·AI/Vision·Platform Domain Owner 와 함께 합니다. VOC 판정 결과를 어느 도메인 오너에게 넘길지 정하는 일이 이 두 줄 사이에 있습니다.
매장 운영자가 남긴 VOC 목록과 키오스크가 남긴 사용 로그를 받아 VOC 마다 네 판정 중 하나를 붙입니다. 운영자는 「카드 승인」·「결제수단선택」처럼 자기 말로 단계를 적고 한국 시각으로 접수하지만, 기기 로그는 PAY_APPROVE 같은 단계 코드와 UTC 시각으로 남습니다. 그래서 먼저 단계 이름을 코드로 옮기고 접수 시각을 UTC 로 바꾼 뒤, 앞뒤 30분 안에 같은 매장·같은 단계 로그가 있는지와 그중 실패가 있는지를 셉니다. 재현된 VOC 는 최근 7일 동안 같은 단계에서 실패한 매장 수를 세어, 한 매장 문제인지 여러 매장에 걸친 문제인지 제품 담당자가 도메인 오너와 그 자리에서 정합니다.
매장 운영자 VOC 를 받아 무엇을 먼저 고칠지 Payment·AI/Vision 도메인 오너와 정하는 기산전자 연구본부 제품 담당자
VOC 는 운영자의 기억으로 적혀 단계 이름과 시각이 로그와 어긋나 있어, 지금은 담당자가 매장마다 로그를 열어 비슷한 시각을 눈으로 찾습니다. 단계 이름과 시각대를 먼저 맞춰 두면 재현 여부는 세는 일로 끝나고, 같은 단계가 여러 매장에서 실패한다는 사실이 VOC 한 건 옆에 바로 서서 결제 쪽과 AI/Vision 쪽 중 어디부터 고칠지 근거를 갖고 정합니다.
제품 담당자가 VOC 목록과 사용 로그 JSON 을 올리면 VOC 마다 네 판정 중 하나와 그 근거 로그가 나오는 관리자 페이지입니다. 운영자가 적은 단계 이름을 로그의 단계 코드로 옮기는 사전과, 한국 시각 접수를 UTC 로 바꿔 앞뒤 30분을 세는 규칙이 이 주에 들어갑니다. 로그는 파일로 받는 것으로 시작하고, 자사 플랫폼 API 에서 직접 끌어오는 일은 3주차로 둡니다.
VOC 120건에 손으로 정답 판정을 붙여 자동 판정과 대조하고 판정별 일치율을 냅니다. 재현된 VOC 를 단계 코드에 따라 Payment 와 AI/Vision 담당 묶음으로 나눠, 제품 담당자가 도메인 오너 회의에 그 묶음을 그대로 띄웁니다.
VOC 접수와 기기 로그 조회를 REST API 로 연결해 새 VOC 가 들어올 때마다 그 매장의 앞뒤 30분 로그를 끌어와 판정합니다. 여러 매장 반복으로 바뀐 단계가 생기면 그 단계의 도메인 오너 채널에 요약 한 건을 남깁니다.
제품 담당자가 VOC 목록과 사용 로그를 올리면 VOC 마다 재현 판정과 근거 로그가 서고, 여러 매장에서 같은 단계가 실패한 VOC 가 맨 위 묶음에 모이는 과정을 시연합니다.
운영자가 「결제수단선택」·「카드 승인」처럼 적은 단계 이름과 한국 시각 접수가 UTC 로 남은 로그와 어떻게 맞춰지는지, 한 VOC 를 펼쳐 옮겨진 단계 코드와 30분 창의 시작·끝 시각을 화면에서 읽습니다.
창 시작보다 30초 앞선 로그, 창 시작 정각에 찍힌 로그, 로그를 한 줄도 올리지 않은 신규 매장, 증상 칸이 비어 있는 VOC, 매장 로그는 있는데 그 단계 줄만 없는 VOC, 7일 창에서 몇 시간 차이로 빠지는 실패 매장을 섞은 입력에서 판정이 어느 쪽으로 가는지 보여주고, 형식이 깨진 로그 파일 12종을 올려도 화면이 서는지 확인합니다.
VOC 120건에 손으로 매긴 정답 판정과 자동 판정의 일치율을 냅니다. 정답과 로그를 모두 제가 지은 합성 기준이라 이 수는 성능이 아니라 규칙이 설계대로 도는지를 잰 값입니다.
위 수치는 더미데이터 자가채점이며, 실제 재현 판정의 정확도는 기산전자 매장의 실 VOC 와 기기 로그, 그리고 그 VOC 를 실제로 고친 기록이 있어야 측정됩니다. 이 포트폴리오는 그 데이터가 오면 같은 러너로 바로 다시 잴 수 있는 상태로 만듭니다.
일치율은 제가 지은 VOC 와 로그에 제가 매긴 정답을 대조한 값이라 성능 증명이 아닙니다. 면접에서는 어떤 입력에서 판정이 서고 어디서 갈리는지를 시연하는 데까지로 설명합니다.
VOC 와 로그를 제가 함께 지었으니 로그가 깔끔하게 맞아떨어지는 VOC 만 넣으면 판정이 틀릴 수가 없습니다. 창 시작보다 30초 앞선 로그, 창 시작 정각의 로그, 로그가 없는 신규 매장, 증상 칸이 빈 VOC, 7일 창 밖으로 몇 시간 차이로 빠지는 실패, 어느 단계로도 옮겨지지 않는 「화면 멈춤」 같은 단계 이름을 더미에 일부러 넣은 이유입니다.
로그에 실패가 없다고 VOC 가 거짓이라는 뜻은 아닙니다. 버튼이 늦게 반응하는 체감 문제는 결과 코드에 남지 않으므로, 모두 성공 판정은 기각이 아니라 로그 밖에서 더 볼 VOC 로 둡니다.
운영자는 문제가 난 뒤 한참 지나 접수하는 경우가 많아 30분 창이 실제 접수 지연과 맞지 않을 수 있습니다. 매장별 접수 지연 분포를 보고 창 폭을 다시 잡는 일은 실데이터가 온 뒤의 도입 과제로 둡니다.
이 포트폴리오는 VOC 와 로그를 시각·단계로 맞춰 세는 규칙과 그 결과 화면을 보여줍니다. 승인이 왜 거절됐는지, 비전 모델이 왜 상품을 못 잡았는지 원인 분석은 각 도메인 오너의 일로 남깁니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
매장 운영자가 전화·게시판으로 남긴 VOC 를 접수 담당이 옮겨 적은 표입니다. flow_step 은 운영자가 쓴 단계 이름 그대로라 「결제수단선택」·「카드 승인」처럼 로그의 단계 코드와 다르게 들어오고, reported_at 은 한국 시각입니다. 증상 칸이 비어 있는 VOC 와 사용 로그를 한 줄도 올리지 않은 신규 매장의 VOC 를 일부러 담았습니다. 같은 매장이 같은 날 두 번 올린 VOC 와, 「화면 멈춤」처럼 어느 단계로도 옮길 수 없는 단계 이름도 한 건씩 넣었습니다.
| voc_id | store_id | store_name | reported_at | flow_step | symptom |
|---|---|---|---|---|---|
| VOC-3308 | ST-1021 | 성수점 | 2026-09-15T12:40:00+09:00 | 결제 승인 | 카드를 꽂았는데 승인 중 화면에서 1분 넘게 멈췄다고 합니다 |
| VOC-3311 | ST-1034 | 판교점 | 2026-09-16T14:10:00+09:00 | AI 인식 | 빵을 두 개 올렸는데 인식 중 표시만 돌다 처음 화면으로 갔습니다 |
| VOC-3339 | ST-1034 | 판교점 | 2026-09-16T14:20:00+09:00 | 영수증 출력 | 영수증이 두 장 연달아 나왔다고 합니다 |
| VOC-3316 | ST-1093 | 수원점 | 2026-09-19T14:00:00+09:00 | 카드 승인 | 승인 대기 뒤에 다시 처음 화면으로 돌아갔습니다 |
| VOC-3319 | ST-1047 | 부산서면점 | 2026-09-17T19:05:00+09:00 | 결제수단선택 | 간편결제 버튼을 눌러도 반응이 없었다고 합니다 |
아래 JSON Schema 에 맞는 VOC 행을 더 만들어 주세요. {"type":"object","properties":{"voc_id":{"type":"string"},"store_id":{"type":"string"},"store_name":{"type":"string"},"reported_at":{"type":"string","description":"운영자가 접수한 시각입니다. +09:00 오프셋이 붙은 ISO 8601 입니다."},"flow_step":{"type":"string","description":"운영자가 적은 단계 이름 원문입니다."},"symptom":{"type":["string","null"]}},"required":["voc_id","store_id","store_name","reported_at","flow_step","symptom"]} 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) symptom 이 null 인 VOC, (2) flow_step 이 「결제승인」·「카드 결제」·「스캔」처럼 띄어쓰기나 현장 말로 적힌 VOC, (3) usage_logs 에 한 줄도 없는 신규 store_id 의 VOC, (4) 같은 매장에서 같은 날 두 번 접수된 VOC. reported_at 은 반드시 +09:00 오프셋을 붙이고, 생성한 행은 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"voc_id":{"type":"string"},"store_id":{"type":"string"},"store_name":{"type":"string"},"reported_at":{"type":"string","description":"운영자가 접수한 시각입니다. +09:00 오프셋이 붙은 ISO 8601 입니다."},"flow_step":{"type":"string","description":"운영자가 적은 단계 이름 원문입니다."},"symptom":{"type":["string","null"]}},"required":["voc_id","store_id","store_name","reported_at","flow_step","symptom"]}키오스크가 결제 흐름의 단계마다 남긴 사용 로그를 세션 단위로 펼친 표입니다. flow_step 은 기기의 단계 코드이고 event_at 은 UTC 시각입니다. VOC 접수 시각에서 30분 30초 앞에 찍힌 로그와 정확히 30분 앞에 찍힌 로그, 7일 창 바로 밖에 있는 실패 로그를 일부러 담았습니다.
| session_id | store_id | event_at | flow_step | result_code | app_version |
|---|---|---|---|---|---|
| SES-0912-7731 | ST-1034 | 2026-09-12T06:14:05Z | PAY_APPROVE | PG_TIMEOUT | 4.2.1 |
| SES-0913-2208 | ST-1047 | 2026-09-13T09:51:22Z | PAY_APPROVE | PG_DECLINED | 4.2.1 |
| SES-0914-0415 | ST-1052 | 2026-09-14T02:20:10Z | PAY_APPROVE | PG_TIMEOUT | 4.2.0 |
| SES-0915-1180 | ST-1021 | 2026-09-15T03:28:40Z | PAY_APPROVE | PG_TIMEOUT | 4.2.1 |
| SES-0915-1181 | ST-1021 | 2026-09-15T03:31:05Z | PAY_APPROVE | OK | 4.2.1 |
아래 JSON Schema 에 맞는 키오스크 사용 로그 행을 더 만들어 주세요. {"type":"object","properties":{"session_id":{"type":"string"},"store_id":{"type":"string"},"event_at":{"type":"string","description":"기기가 찍은 UTC 시각입니다. Z 로 끝나는 ISO 8601 입니다."},"flow_step":{"type":"string","enum":["MENU_SELECT","AI_RECOGNIZE","PAY_METHOD","PAY_APPROVE","RECEIPT_PRINT"]},"result_code":{"type":"string","description":"OK 이면 성공이고 나머지는 모두 실패 코드입니다."},"app_version":{"type":["string","null"]}},"required":["session_id","store_id","event_at","flow_step","result_code"]} 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 어떤 VOC 접수 시각에서 30분을 몇 초 넘긴 로그와 정확히 30분인 로그, (2) 같은 단계에서 실패 뒤 곧바로 OK 가 찍힌 재시도 세션, (3) 접수 시각 기준 7일 창 바로 밖에 찍힌 실패 로그, (4) app_version 이 null 인 로그. event_at 은 반드시 Z 로 끝나는 UTC 로 쓰고, 생성한 행은 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"session_id":{"type":"string"},"store_id":{"type":"string"},"event_at":{"type":"string","description":"기기가 찍은 UTC 시각입니다. Z 로 끝나는 ISO 8601 입니다."},"flow_step":{"type":"string","enum":["MENU_SELECT","AI_RECOGNIZE","PAY_METHOD","PAY_APPROVE","RECEIPT_PRINT"]},"result_code":{"type":"string","description":"OK 이면 성공이고 나머지는 모두 실패 코드입니다."},"app_version":{"type":["string","null"]}},"required":["session_id","store_id","event_at","flow_step","result_code"]}| TypeScript | 단계 이름 사전과 시각 환산, 30분 창 세기, 7일 매장 수 세기, 판정 차례를 담은 규칙 엔진과 화면 코드의 언어입니다. |
| React | 제품 담당자가 판정별 VOC 묶음을 펼쳐 근거 로그를 보는 관리자 페이지입니다. |
| Figma | 1주차 첫날 판정 묶음과 근거 펼침 화면을 먼저 그려 도메인 오너가 볼 정보의 순서를 정합니다. |
| REST API | 3주차에 VOC 접수와 기기 로그 조회를 자사 플랫폼 API 로 받아 판정을 새 VOC 마다 돌립니다. |
| JSON | 키오스크 사용 로그를 받는 형식입니다. 세션 단위 JSON 을 그대로 읽어 단계 코드와 결과 코드를 꺼냅니다. |
| SQL | 로그를 매장·단계·시각으로 조회하는 저장소 질의입니다. 30분 창과 7일 창을 인덱스를 타는 조건으로 씁니다. |
| Git | 단계 이름 사전과 판정 규칙을 바꿀 때마다 정답 세트 대조 결과와 함께 이력을 남깁니다. |
| Claude | 판정이 정해진 뒤 운영자가 적은 증상과 로그의 실패 코드를 엮어 도메인 오너에게 넘길 한 문장을 씁니다. |
| Cursor | 규칙 엔진과 화면을 코딩 Agent 로 나눠 만들고, 만든 코드는 정답 세트 대조로 확인한 뒤 합칩니다. |
✗ fail → 옮기지 못한 단계 이름이 1할을 넘으면 별칭 사전을 먼저 넓히고, 그때까지 그 VOC 는 판정 없이 목록에 따로 세웁니다.
✓ pass → VOC 120건 정답 대조와 도메인 오너별 묶음으로 2주차를 엽니다.
✗ fail → 어긋난 VOC 만 모아 30분 창 폭과 3개 매장 문턱을 다시 잡습니다.
✓ pass → 3주차 REST API 연결과 새 VOC 즉시 판정으로 넘어갑니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
verdict사유 라벨 · voc_id + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
여러 매장에서 같은 단계 실패여러 매장 반복로그로 재현됨재현됨그 단계 로그는 모두 성공로그상 정상그 시각 로그가 없음로그 없음VOC 한 건이 단계 이름 옮기기와 시각 환산, 30분 창·7일 창 세기를 거쳐 어떤 재현 판정을 받는지 남기는 형식입니다. 판정은 규칙이 정하고 도메인 오너에게 넘길 문장만 모델이 씁니다.
{"type":"object","properties":{"voc_id":{"type":"string"},"store_id":{"type":"string"},"flow_step":{"type":"string","description":"voc_tickets 에 적혀 온 단계 이름 원문입니다."},"step_code":{"type":"string","description":"flow_step 을 별칭 사전으로 옮긴 usage_logs 단계 코드입니다. 사전으로 옮기지 못한 VOC 는 판정하지 않고 「옮기지 못한 단계 이름」 목록에 따로 세우므로 이 형식에는 들어오지 않습니다."},"window_start_utc":{"type":"string","description":"reported_at 을 UTC 로 바꾼 뒤 30분을 뺀 시각입니다."},"window_end_utc":{"type":"string","description":"reported_at 을 UTC 로 바꾼 뒤 30분을 더한 시각입니다."},"store_log_count":{"type":"integer","minimum":0,"description":"창 안에 찍힌 같은 store_id 의 usage_logs 줄 수입니다. 창의 시작·끝 시각에 정확히 찍힌 줄도 셉니다."},"step_log_count":{"type":"integer","minimum":0,"description":"그중 flow_step 이 step_code 와 같은 줄 수입니다."},"step_fail_count":{"type":"integer","minimum":0,"description":"그중 result_code 가 OK 가 아닌 줄 수입니다."},"fail_store_count_7d":{"type":["integer","null"],"minimum":0,"description":"재현된 VOC 에만 채웁니다. reported_at 기준 7일 전부터 window_end_utc 까지 같은 step_code 에서 result_code 가 OK 가 아닌 줄을 남긴 서로 다른 store_id 수입니다. 창 끝을 window_end_utc 로 잡아 이 VOC 를 재현한 자기 매장 실패가 늘 들어갑니다."},"verdict":{"type":"string","enum":["로그로 재현됨","그 단계 로그는 모두 성공","그 시각 로그가 없음","여러 매장에서 같은 단계 실패"]},"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":["voc_id","store_id","flow_step","step_code","window_start_utc","window_end_utc","store_log_count","step_log_count","step_fail_count","verdict","evidence","summary"]}[
{
"voc_id": "VOC-3308",
"store_id": "ST-1021",
"flow_step": "결제 승인",
"step_code": "PAY_APPROVE",
"window_start_utc": "2026-09-15T03:10:00Z",
"window_end_utc": "2026-09-15T04:10:00Z",
"store_log_count": 2,
"step_log_count": 2,
"step_fail_count": 1,
"fail_store_count_7d": 4,
"verdict": "여러 매장에서 같은 단계 실패",
"evidence": [
{
"field": "reported_at",
"value": "2026-09-15T12:40:00+09:00"
},
{
"field": "event_at",
"value": "2026-09-15T03:28:40Z"
},
{
"field": "result_code",
"value": "PG_TIMEOUT"
},
{
"field": "store_id",
"agg": "count",
"value": 4
}
],
"summary": "성수점 결제 승인 멈춤은 12시 28분 PG_TIMEOUT 로그로 재현되고, 같은 주에 판교·부산서면·대전둔산점도 결제 승인에서 실패했습니다.",
"hedge": null
},
{
"voc_id": "VOC-3311",
"store_id": "ST-1034",
"flow_step": "AI 인식",
"step_code": "AI_RECOGNIZE",
"window_start_utc": "2026-09-16T04:40:00Z",
"window_end_utc": "2026-09-16T05:40:00Z",
"store_log_count": 2,
"step_log_count": 2,
"step_fail_count": 1,
"fail_store_count_7d": 1,
"verdict": "로그로 재현됨",
"evidence": [
{
"field": "event_at",
"value": "2026-09-16T05:02:30Z"
},
{
"field": "result_code",
"value": "VISION_TIMEOUT"
},
{
"field": "store_id",
"agg": "count",
"value": 1
}
],
"summary": "판교점에서 빵 두 개가 인식되지 않았다는 VOC 는 14시 2분 VISION_TIMEOUT 로그로 재현되며, 최근 7일 AI 인식 실패는 이 매장뿐입니다.",
"hedge": null
},
{
"voc_id": "VOC-3336",
"store_id": "ST-1093",
"flow_step": "상품 인식",
"step_code": "AI_RECOGNIZE",
"window_start_utc": "2026-09-21T01:00:00Z",
"window_end_utc": "2026-09-21T02:00:00Z",
"store_log_count": 1,
"step_log_count": 1,
"step_fail_count": 1,
"fail_store_count_7d": 2,
"verdict": "로그로 재현됨",
"evidence": [
{
"field": "flow_step",
"value": "상품 인식"
},
{
"field": "reported_at",
"value": "2026-09-21T10:30:00+09:00"
},
{
"field": "event_at",
"value": "2026-09-21T01:00:00Z"
},
{
"field": "result_code",
"value": "VISION_LOW_CONF"
},
{
"field": "store_id",
"agg": "count",
"value": 2
}
],
"summary": "수원점 샐러드 용기 오인식은 접수 정확히 30분 전 VISION_LOW_CONF 로그로 재현되고, 7일 동안 AI 인식에서 실패한 매장은 판교점과 이곳 두 곳이라 반복 문턱에는 닿지 않습니다.",
"hedge": "운영자가 「상품 인식」이라고 적어 AI_RECOGNIZE 로 옮겨 읽었습니다. 로그가 창의 시작 시각에 정확히 걸려 창 안으로 셌습니다."
},
{
"voc_id": "VOC-3342",
"store_id": "ST-1021",
"flow_step": "결제 승인",
"step_code": "PAY_APPROVE",
"window_start_utc": "2026-09-21T10:40:00Z",
"window_end_utc": "2026-09-21T11:40:00Z",
"store_log_count": 2,
"step_log_count": 2,
"step_fail_count": 1,
"fail_store_count_7d": 2,
"verdict": "로그로 재현됨",
"evidence": [
{
"field": "event_at",
"value": "2026-09-21T10:58:12Z"
},
{
"field": "result_code",
"value": "PG_DECLINED"
},
{
"field": "store_id",
"agg": "count",
"value": 2
}
],
"summary": "성수점 승인 거절은 19시 58분 PG_DECLINED 로그로 재현되며, 7일 창 안에서 결제 승인에 실패한 매장은 성수점과 수원점 두 곳입니다.",
"hedge": "대전둔산점의 9월 14일 11시 20분 실패는 창 시작보다 약 9시간 앞서 빠졌습니다. 접수가 9시간만 빨랐어도 실패 매장이 세 곳이 되어 여러 매장 반복으로 갔을 VOC 입니다."
},
{
"voc_id": "VOC-3319",
"store_id": "ST-1047",
"flow_step": "결제수단선택",
"step_code": "PAY_METHOD",
"window_start_utc": "2026-09-17T09:35:00Z",
"window_end_utc": "2026-09-17T10:35:00Z",
"store_log_count": 2,
"step_log_count": 2,
"step_fail_count": 0,
"fail_store_count_7d": null,
"verdict": "그 단계 로그는 모두 성공",
"evidence": [
{
"field": "flow_step",
"value": "결제수단선택"
},
{
"field": "result_code",
"value": "OK"
},
{
"field": "session_id",
"agg": "count",
"value": 2
}
],
"summary": "부산서면점 간편결제 버튼 무반응 VOC 는 앞뒤 30분 결제 수단 선택 로그 두 세션이 모두 OK 라 로그로는 재현되지 않습니다.",
"hedge": "버튼 반응 지연처럼 결과 코드에 남지 않는 체감 문제일 수 있어 기각이 아니라 화면 녹화로 더 볼 VOC 로 둡니다."
},
{
"voc_id": "VOC-3330",
"store_id": "ST-1071",
"flow_step": "AI 인식",
"step_code": "AI_RECOGNIZE",
"window_start_utc": "2026-09-20T01:30:00Z",
"window_end_utc": "2026-09-20T02:30:00Z",
"store_log_count": 2,
"step_log_count": 2,
"step_fail_count": 0,
"fail_store_count_7d": null,
"verdict": "그 단계 로그는 모두 성공",
"evidence": [
{
"field": "symptom",
"value": null
},
{
"field": "result_code",
"value": "OK"
},
{
"field": "session_id",
"agg": "count",
"value": 2
}
],
"summary": "홍대점 AI 인식 VOC 는 앞뒤 30분 인식 로그 두 세션이 모두 OK 입니다.",
"hedge": "증상 칸이 비어 있어 문장에 증상을 쓰지 않았습니다. 운영자에게 무엇이 잘못 보였는지 되물을 VOC 입니다."
},
{
"voc_id": "VOC-3324",
"store_id": "ST-1052",
"flow_step": "결제 승인",
"step_code": "PAY_APPROVE",
"window_start_utc": "2026-09-18T00:10:00Z",
"window_end_utc": "2026-09-18T01:10:00Z",
"store_log_count": 0,
"step_log_count": 0,
"step_fail_count": 0,
"fail_store_count_7d": null,
"verdict": "그 시각 로그가 없음",
"evidence": [
{
"field": "reported_at",
"value": "2026-09-18T09:40:00+09:00"
},
{
"field": "event_at",
"value": "2026-09-18T00:09:30Z"
},
{
"field": "session_id",
"agg": "count",
"value": 0
}
],
"summary": "대전둔산점 승인 오류 VOC 는 앞뒤 30분 안에 이 매장 로그가 한 줄도 없고, 가장 가까운 로그는 창 시작보다 30초 앞선 9시 9분 30초의 성공 로그입니다.",
"hedge": "오픈 직후라 기기가 로그를 올리기 전이었을 수 있습니다. 로그 전송 지연인지 기기 꺼짐인지 Platform 도메인 오너에게 확인할 VOC 입니다."
},
{
"voc_id": "VOC-3333",
"store_id": "ST-1088",
"flow_step": "결제 승인",
"step_code": "PAY_APPROVE",
"window_start_utc": "2026-09-20T06:00:00Z",
"window_end_utc": "2026-09-20T07:00:00Z",
"store_log_count": 0,
"step_log_count": 0,
"step_fail_count": 0,
"fail_store_count_7d": null,
"verdict": "그 시각 로그가 없음",
"evidence": [
{
"field": "store_id",
"value": "ST-1088"
},
{
"field": "session_id",
"agg": "count",
"value": 0
}
],
"summary": "일산점 결제 불가 VOC 는 이 매장이 사용 로그를 한 줄도 올린 적이 없어 재현 여부를 볼 수 없습니다.",
"hedge": "신규 매장이라 로그 수집이 아직 켜지지 않았을 수 있습니다."
},
{
"voc_id": "VOC-3339",
"store_id": "ST-1034",
"flow_step": "영수증 출력",
"step_code": "RECEIPT_PRINT",
"window_start_utc": "2026-09-16T04:50:00Z",
"window_end_utc": "2026-09-16T05:50:00Z",
"store_log_count": 2,
"step_log_count": 0,
"step_fail_count": 0,
"fail_store_count_7d": null,
"verdict": "그 시각 로그가 없음",
"evidence": [
{
"field": "flow_step",
"value": "영수증 출력"
},
{
"field": "session_id",
"agg": "count",
"value": 2
},
{
"field": "flow_step",
"value": "AI_RECOGNIZE"
}
],
"summary": "판교점 영수증 중복 출력 VOC 는 앞뒤 30분 안에 이 매장 로그 두 줄이 있지만 모두 AI 인식 단계이고 영수증 출력 단계 로그는 없습니다.",
"hedge": "같은 날 앞서 올린 AI 인식 VOC 와 시각이 겹칩니다. 인식이 멈춰 세션이 영수증 단계까지 가지 못한 것인지, 영수증 단계가 로그를 남기지 않은 것인지 Platform 도메인 오너에게 확인할 VOC 입니다."
}
][자동 검증 · 코드가 판정합니다] 1. verdict 가 네 값 중 하나인지, step_code 가 usage_logs 의 다섯 단계 코드 중 하나인지 확인합니다. 별칭 사전으로 옮기지 못한 단계 이름의 VOC 는 네 판정 어디에도 넣지 않고 「옮기지 못한 단계 이름」 목록에 따로 세웁니다. 이 VOC 를 로그 없음으로 보내면 로그가 있는데도 없다고 말하게 됩니다. 2. voc_id·store_id·flow_step·step_code·window_start_utc·window_end_utc·store_log_count·step_log_count·step_fail_count·verdict·evidence·summary 필드가 빠짐없이 존재하는지 확인합니다. 3. store_log_count·step_log_count·step_fail_count·fail_store_count_7d 가 0 이상이고 step_fail_count 가 step_log_count 이하, step_log_count 가 store_log_count 이하인지 확인합니다. 4. window_start_utc 와 window_end_utc 가 reported_at 을 UTC 로 바꾼 시각에서 각각 30분을 빼고 더한 값과 같은지, 두 값의 차이가 60분인지 다시 계산합니다. 5. 그 시각 로그가 없음은 같은 store_id 의 usage_logs.event_at 이 창 안에 한 줄도 없는지 다시 셉니다. 매장 로그는 창 안에 있는데 step_code 줄이 0개인 VOC 도 그 단계 시각 로그가 없는 것으로 보고 이 판정으로 둡니다. 6. 그 단계 로그는 모두 성공은 step_log_count 가 1 이상이고 step_fail_count 가 0 인지 다시 셉니다. 7. 여러 매장에서 같은 단계 실패는 step_fail_count 가 1 이상이고 fail_store_count_7d 가 3 이상인지, 로그로 재현됨은 step_fail_count 가 1 이상이고 fail_store_count_7d 가 3 미만인지 다시 셉니다. 7일 창은 reported_at 7일 전부터 window_end_utc 까지라, 접수 뒤 30분 안에 찍힌 자기 매장 실패도 셉니다. 8. evidence 의 field 이름이 voc_tickets 또는 usage_logs 에 있는 컬럼인지 대조합니다. 없는 이름을 인용하면 문장이 지어낸 것이라 규칙이 만든 기본 문장으로 되돌립니다. 9. evidence 의 value 가 수록된 행의 원문 값과 같은지 확인합니다. 여러 줄을 세어 얻은 수는 agg 를 적습니다. 10. summary 가 존댓말로 끝나는지 확인합니다. [판정 차례 · 위 규칙이 둘 이상 동시에 걸릴 때] VOC 한 건에는 판정을 하나만 남깁니다. ① 그 시각 로그가 없음 → ② 그 단계 로그는 모두 성공 → ③ 여러 매장에서 같은 단계 실패 → ④ 로그로 재현됨. 창의 시작·끝 시각에 정확히 찍힌 로그는 창 안으로 세고(VOC-3336 이 시작 시각 정각 로그로 재현됩니다), 7일 창도 접수 시각에서 정확히 7일 전 시각을 포함합니다. [하드 케이스 · 판정이 갈리는 이유] VOC-3319 는 「결제수단선택」을 띄어쓰기를 걷어 PAY_METHOD 로 읽고, VOC-3336 은 「상품 인식」을 AI_RECOGNIZE 로 읽습니다. VOC-3316 의 「카드 승인」은 PAY_APPROVE 로 읽혀 7일 창 안 실패 매장이 다섯 곳이라 여러 매장 반복으로 갑니다. VOC-3327 은 영수증 출력 단계 로그 한 줄의 PRINTER_PAPER_OUT 으로 재현되며 다른 매장 실패가 없어 로그로 재현됨으로 둡니다. VOC-3339 는 판교점이 같은 날 두 번째로 올린 VOC 로, 창 안에 매장 로그 두 줄이 있지만 모두 AI 인식 단계라 영수증 출력 줄이 0개여서 그 시각 로그가 없음으로 갑니다. VOC-3347 의 「화면 멈춤」은 다섯 단계 어디에도 옮겨지지 않아 판정하지 않고 옮기지 못한 단계 이름 목록에 세웁니다. [평가 러너 · 2주차] 손으로 매긴 정답 판정 120건과 자동 판정을 대조해 판정별 일치율을 내고, 어긋난 VOC 는 따로 모아 30분 창 폭과 3개 매장 문턱, 별칭 사전 빈칸을 다시 봅니다. [수동 검증 · 사람이 봅니다] 1. 모두 성공으로 간 VOC 20건을 열어 결과 코드에 남지 않는 체감 문제인지 제품 담당자가 판단합니다. 2. 여러 매장 반복으로 올라온 단계를 Payment 와 AI/Vision 중 어느 도메인 오너가 먼저 볼지 회의에서 정합니다.