메타엑스(Meta-X)
경력근거: 병원은 환자 정보와 시뮬레이션 결과를 확인하고 상담 업무를 관리하는 웹 서비스를 사용합니다.
※ 실제 산출물이 아닌 AI 예측 시안입니다.
메타엑스의 MIRI 에서는 환자가 본인 사진으로 성형·시술 시뮬레이션을 확인하고, 관심 시술과 질문을 병원에 미리 전달해 상담을 준비합니다. 병원은 환자 정보와 시뮬레이션 결과를 확인하고 상담 업무를 관리하는 웹 서비스를 씁니다. 보통 병원 예약 시스템에는 상담 전에 환자가 고른 시술과 시뮬레이션 결과가 없어 이 판정을 낼 데이터가 없지만, MIRI 는 그 둘이 예약보다 먼저 병원에 도착하는 제품이라 예약 한 건이 상담 시간 안에 끝날지를 전날 계산할 수 있습니다. 공고가 첫 업무로 든 병원용 클리닉웹과 관리자 페이지의 기능 개발, 데이터 조회·입력 같은 공통 기능, 이후의 시뮬레이션·상담·예약 기능 개발이 이 화면 하나에 모입니다. 시술별 상담 소요 분·시뮬레이션 필요 여부와 예약 분은 공고가 밝히지 않은 칸이라, 시술 목록 표와 예약 표의 모양은 지원자가 정하고 그 가정을 risks 에 적었습니다. 이 포트폴리오는 예약·관심 시술·시술 목록·시뮬레이션 네 표를 예약 단위로 견주는 판정과 그 결과를 전화 업무로 잇는 화면을 보여줍니다. 성형·미용 시술의 의학적 판단이나 상담 전문성은 주장하지 않습니다.
공고는 환자가 MIRI 에서 본인 사진으로 시뮬레이션을 확인하고 관심 시술과 질문을 병원에 미리 전달해 상담을 준비한다고 적었습니다. 예약 한 건이 상담 시간 안에 끝날지, 이 병원이 다루는 시술인지를 상담 전날 계산할 데이터가 제품 안에 이미 있습니다.
주요 업무 첫 줄이 병원용 클리닉웹과 관리자 페이지의 기능 개발 및 사용성 개선이고, 데이터 조회·입력 같은 공통 기능을 거쳐 시뮬레이션·상담·예약 기능으로 넓혀 간다고 적었습니다. 예약·관심 시술·시뮬레이션을 한 화면에서 읽는 이 포트폴리오가 그 범위를 한 번에 지납니다.
공고는 AI 코딩 도구로 만든 결과가 사용자의 요구에 맞는지 확인하고 고치는 일을 개발 업무로 보고, 실제 사용 흐름에서 기능 확인과 오류 재현을 맡깁니다. 판정 함수를 Claude Code 에 맡기되 합계가 딱 맞는 예약, 같은 시술을 두 번 고른 예약, UTC 시각 예약을 테스트로 걸어 결과를 확인하는 방식이 이 요구와 같습니다.
상담실장이 상담 날짜를 고르면 이 화면은 그날 예약마다 환자가 MIRI 앱으로 보낸 관심 시술을 모아 그 병원의 시술 목록과 맞춥니다. 목록에 없는 시술이 하나라도 있으면 병원에서 하지 않는 시술을 물은 예약, 서로 다른 관심 시술의 상담 소요 분을 더한 값이 예약 분을 넘으면 예약 시간 안에 못 끝내는 예약, 시뮬레이션이 있어야 하는 시술인데 그 요청에 상담 시작 전 결과가 없으면 시뮬레이션이 빠진 예약으로 판정합니다. 상담실장과 예약 코디네이터는 전날 오후 걸린 예약만 골라 환자에게 전화해 예약 시간을 늘리거나 상담 범위를 미리 알립니다.
MIRI 클리닉웹을 쓰는 협력 병원의 상담실장과 예약 코디네이터. 전날 오후 다음 날 상담 예약을 넘겨 보며 환자가 미리 보낸 관심 시술·질문·시뮬레이션 결과를 확인하고, 걸린 예약은 환자에게 연락해 예약 시간을 늘리거나 상담 범위를 미리 안내한다
클리닉웹 예약 목록은 상담 시각과 환자 이름만 보여 줘서, 환자가 보낸 관심 시술이 우리 병원 시술 목록에 있는지, 고른 시술을 다 상담하려면 몇 분이 드는지는 예약을 하나씩 열어 시술 목록과 맞춰 봐야 압니다. 전날 오후에 그 일을 다 하지 못하면 하지 않는 시술을 물은 환자가 상담 당일에야 안내를 받고, 시술을 여럿 고른 상담이 뒤 예약을 밀어냅니다. 예약마다 관심 시술을 그 병원 목록과 맞추고 상담 소요 분을 더해 예약 분과 견주면, 상담실장은 전화할 예약만 골라 연락합니다.
강남 A의원과 신사 B의원의 10월 14일 예약 10건을 네 표로 Cloudflare D1 에 넣고, 상담실장은 병원과 날짜를 골라 예약이 네 판정으로 나뉜 화면을 봅니다. 줄마다 연락할 내용 한 줄이 붙고, 줄을 펼치면 관심 시술마다 상담 소요 분, 시뮬레이션 결과 번호, 환자가 남긴 질문을 읽습니다. 화면은 Next.js 로 만들어 Cloudflare 에 올립니다.
코디네이터가 걸린 예약에 전화한 뒤 예약 시간 늘림·상담 범위 안내·시뮬레이션 요청 중 하나를 남기면, 예약 분을 고친 예약은 그 자리에서 판정이 다시 납니다. 판정을 심어 둔 예약 120건을 생성기로 만들어 판정 시험 탭에서 맞은 예약과 빗나간 예약을 규칙별로 봅니다.
걸린 예약을 열면 Claude Haiku 4.5 가 환자의 사전 질문을 받는 첫 문장을 쓰고, 그 뒤에 판정에서 나온 안내 문장이 붙은 연락 문안이 나옵니다. 숫자·기간·효과 어휘가 섞인 초안은 버리고 안내 문장만 보여 주며, 상담실장은 문안을 고쳐 전화할 때 읽습니다.
상담실장이 강남 A의원의 10월 14일을 고르면 예약 6건 중 3건이 다시 연락할 묶음에 섭니다. 시간 초과 묶음의 BK-1042 는 관심 시술 셋의 상담 소요 분 합계 55분이 예약 30분을 25분 넘고, 하지 않는 시술 묶음의 BK-1045 는 사각턱 축소를, 시뮬레이션 없음 묶음의 BK-1047 은 이번 요청에 코 성형 결과가 없음을 연락할 내용 한 줄로 보여줍니다.
코디네이터가 BK-1043 을 펼치면 쌍꺼풀이 두 줄로 들어온 요청인데 상담 소요 분은 한 번만 더해 25분이라 준비 끝에 서 있고, BK-1040 은 합계 30분이 예약 30분과 같아 시간 초과에 서지 않습니다.
신사 B의원으로 바꾸면 BK-1046 이 시간 초과 묶음에 서면서 코 성형 시뮬레이션 없음이 함께 성립한 판정으로 같은 줄에 붙고, BK-1048 은 UTC 로 적힌 결과(2026-10-14T05:12:00Z)를 한국 시각 14:12 로 바꿔 상담 시작 14:00 뒤의 결과로 보고 시뮬레이션 없음에 둡니다.
start_at 형식이 틀린 예약, consult_min 이 숫자가 아닌 시술 줄, 예약 표에 없는 booking_id 를 가리키는 관심 시술 줄 등 일부러 깨뜨린 입력 30종을 넣어도 화면은 멈추지 않고, 판정에서 뺀 줄을 목록 위에 표 이름과 줄 번호로 남깁니다.
위 수치는 작성자가 만든 더미데이터 자가채점이며, 이 판정이 상담 당일의 밀림과 헛걸음을 실제로 줄이는지는 메타엑스 협력 병원의 실제 예약·상담 기록이 있어야 측정됩니다. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태로 만듭니다.
수치는 합성 데이터 자가채점이라 성능 증명이 아닙니다. 시술별 상담 소요 분(강남 A의원 쌍꺼풀 20분 등)과 시뮬레이션 필요 여부는 제가 정한 값이라, 55분이 실제 상담 시간을 맞힌다는 근거가 되지 못합니다. 이 결과가 말하는 것은 병원이 적어 둔 값과 예약 분을 코드가 정확히 견준다는 데까지이고, 협력 병원의 실제 시술 목록을 넣으면 같은 코드가 그대로 돕니다.
다섯 예약은 실수 하나에 하나씩 뒤집히도록 골랐습니다. BK-1040 은 합계 30분이 예약 30분과 같아 '넘으면' 을 '이상' 으로 쓰면 시간 초과가 되고, BK-1043 은 쌍꺼풀이 두 줄이라 줄 수대로 더하면 40분으로 시간 초과가 되며, BK-1045 는 사각턱 축소가 신사 B의원 목록에만 있어 병원으로 거르지 않으면 준비 끝이 됩니다. BK-1047 은 코 성형 결과가 지난달 요청에만 있어 요청 번호 없이 찾으면 준비 끝이 되고, BK-1048 은 UTC 로 적힌 결과를 문자열로 견주면 상담 전 결과로 읽혀 준비 끝이 됩니다.
시술 목록에 상담 소요 분과 시뮬레이션 필요 여부가 있고 예약에 예약 분이 있다는 것은 공고에 없는 가정입니다. 공고가 밝힌 것은 환자가 관심 시술·질문·시뮬레이션 결과를 병원에 미리 보내고 병원이 그 내용을 보며 상담 업무를 관리한다는 데까지라, 실제 클리닉웹이 상담 시간을 시술이 아니라 상담실장 재량으로 잡는다면 시간 초과 판정은 병원별 기본 예약 분과 견주는 방식으로 바꿉니다.
상담 소요 분은 시술을 따로 설명할 때의 시간을 그대로 더하므로, 쌍꺼풀과 코 성형처럼 이어서 설명하면 겹치는 시간이 있는 조합은 실제보다 길게 잡힙니다. 실제 도입에서는 협력 병원의 상담 기록을 보고 겹치는 조합을 덜어 낼지 정합니다.
1주차 데이터는 10월 14일 상담이 끝난 뒤의 기록이라 상담 중에 만든 시뮬레이션(SIM-88110)이 섞여 있습니다. 판정을 조회 시각이 아니라 상담 시작 시각 기준으로 내야 전날 오후에 본 판정과 지난 날짜를 다시 연 판정이 같아지고, 이 기준을 놓치면 2주차 판정 시험이 전날 실제로 본 화면과 다른 답을 정답으로 삼습니다.
이 포트폴리오는 네 표를 예약 단위로 견주는 판정과 그 결과를 전화 업무로 잇는 화면을 보여줍니다. 성형·미용 시술의 적응증이나 상담 내용에 대한 의학적 판단은 주장하지 않습니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
환자가 MIRI 앱에서 병원에 상담 요청을 보낼 때 고른 관심 시술이 한 줄씩 들어갑니다. request_id 하나에 여러 줄이 붙고, 판정은 이 표에서 예약별 관심 시술을 모읍니다. 쌍꺼풀을 시뮬레이션 화면과 시술 목록에서 한 번씩 골라 같은 시술을 두 번 담은 요청(RQ-5043), 강남 A의원에 사각턱 축소를 물은 요청(RQ-5045), 질문 칸이 비어 있는 줄이 섞여 있습니다. 해외에서 앱을 쓰는 환자(RQ-5048)는 picked_at 이 UTC 로 기록됩니다.
| request_id | booking_id | procedure_code | procedure_name | question_text | picked_at |
|---|---|---|---|---|---|
| RQ-5040 | BK-1040 | EYE-DBL | 쌍꺼풀 | 절개 말고 매몰로도 상담받고 싶어요 | 2026-10-11T21:08:00+09:00 |
| RQ-5040 | BK-1040 | SKIN-LSR | 레이저 토닝 | — | 2026-10-11T21:10:00+09:00 |
| RQ-5041 | BK-1041 | NOSE-AUG | 코 성형 | — | 2026-10-12T19:45:00+09:00 |
| RQ-5042 | BK-1042 | EYE-DBL | 쌍꺼풀 | 눈매 교정도 같이 볼 수 있나요 | 2026-10-12T22:20:00+09:00 |
| RQ-5042 | BK-1042 | NOSE-AUG | 코 성형 | 콧대만 높이고 싶어요 | 2026-10-12T22:21:00+09:00 |
아래 JSON Schema 에 맞는 관심 시술 줄을 더 만들어 주세요. {"type":"object","properties":{"request_id":{"type":"string"},"booking_id":{"type":"string"},"procedure_code":{"type":"string"},"procedure_name":{"type":"string"},"question_text":{"type":["string","null"]},"picked_at":{"type":"string","format":"date-time"}},"required":["request_id","booking_id","procedure_code","procedure_name","question_text","picked_at"]} 쉬운 데이터만 만들지 말 것. 다음 경우를 의도적으로 섞으세요: (1) 같은 request_id 에 같은 procedure_code 가 두 줄 들어간 요청, (2) 예약한 병원(bookings.clinic_id)의 시술 목록에는 없고 다른 병원 목록에만 있는 procedure_code, (3) question_text 가 null 인 줄과 시술 효과를 묻는 줄, (4) picked_at 이 Z 로 끝나는 UTC 시각인 줄. request_id 와 booking_id 는 한 요청이 한 예약을 가리키게 맞춰 주세요. 모든 행은 위 스키마를 통과해야 하고, 형식을 깨뜨리는 시도는 따로 3건만 표시해 두세요.{"type":"object","properties":{"request_id":{"type":"string"},"booking_id":{"type":"string"},"procedure_code":{"type":"string"},"procedure_name":{"type":"string"},"question_text":{"type":["string","null"]},"picked_at":{"type":"string","format":"date-time"}},"required":["request_id","booking_id","procedure_code","procedure_name","question_text","picked_at"]}클리닉웹에 잡힌 상담 예약입니다. 예약마다 병원(clinic_id), 상담 시작 시각, 병원이 잡아 둔 예약 분이 있고, 판정은 예약 하나를 한 단위로 냅니다. 강남 A의원 6건과 신사 B의원 4건이 같은 10월 14일에 있어, 판정이 예약마다 그 병원 시술 목록만 보는지 가릴 수 있습니다.
| booking_id | clinic_id | patient_alias | start_at | slot_min |
|---|---|---|---|---|
| BK-1040 | CL-GN01 | 최○○ | 2026-10-14T10:00:00+09:00 | 30 |
| BK-1041 | CL-SC02 | 한○○ | 2026-10-14T10:30:00+09:00 | 30 |
| BK-1043 | CL-SC02 | 윤○○ | 2026-10-14T11:00:00+09:00 | 30 |
| BK-1044 | CL-GN01 | 오○○ | 2026-10-14T11:30:00+09:00 | 20 |
| BK-1042 | CL-GN01 | 김○○ | 2026-10-14T14:00:00+09:00 | 30 |
아래 JSON Schema 에 맞는 상담 예약을 더 만들어 주세요. {"type":"object","properties":{"booking_id":{"type":"string"},"clinic_id":{"type":"string"},"patient_alias":{"type":"string"},"start_at":{"type":"string","format":"date-time"},"slot_min":{"type":"integer","minimum":10,"maximum":120}},"required":["booking_id","clinic_id","patient_alias","start_at","slot_min"]} 쉬운 데이터만 만들지 말 것. 다음 경우를 의도적으로 섞으세요: (1) 관심 시술의 상담 소요 분 합계가 slot_min 과 정확히 같은 예약, (2) 같은 시각에 다른 병원에서 잡힌 예약, (3) slot_min 이 20 처럼 짧은데 관심 시술을 셋 이상 고른 예약. start_at 은 +09:00 시간대를 붙여 주세요. 모든 행은 위 스키마를 통과해야 하고, 형식을 깨뜨리는 시도는 따로 3건만 표시해 두세요.{"type":"object","properties":{"booking_id":{"type":"string"},"clinic_id":{"type":"string"},"patient_alias":{"type":"string"},"start_at":{"type":"string","format":"date-time"},"slot_min":{"type":"integer","minimum":10,"maximum":120}},"required":["booking_id","clinic_id","patient_alias","start_at","slot_min"]}병원이 클리닉웹에 적어 둔 시술 목록입니다. 시술마다 상담 소요 분과 상담 전에 시뮬레이션이 있어야 하는지가 있고, 같은 시술도 병원마다 상담 소요 분이 다릅니다(쌍꺼풀은 강남 A의원 20분, 신사 B의원 15분). 이 표의 모양은 공고에 없어 지원자가 정한 가정입니다.
| clinic_id | clinic_name | procedure_code | procedure_name | consult_min | simulation_required |
|---|---|---|---|---|---|
| CL-GN01 | 강남 A의원 | EYE-DBL | 쌍꺼풀 | 20 | true |
| CL-GN01 | 강남 A의원 | NOSE-AUG | 코 성형 | 20 | true |
| CL-GN01 | 강남 A의원 | EYE-FAT | 눈밑 지방 재배치 | 15 | true |
| CL-GN01 | 강남 A의원 | LIPO-ARM | 팔 지방흡입 | 15 | false |
| CL-GN01 | 강남 A의원 | SKIN-LSR | 레이저 토닝 | 10 | false |
아래 JSON Schema 에 맞는 병원 시술 목록 줄을 더 만들어 주세요. {"type":"object","properties":{"clinic_id":{"type":"string"},"clinic_name":{"type":"string"},"procedure_code":{"type":"string"},"procedure_name":{"type":"string"},"consult_min":{"type":"integer","minimum":5},"simulation_required":{"type":"boolean"}},"required":["clinic_id","clinic_name","procedure_code","procedure_name","consult_min","simulation_required"]} 쉬운 데이터만 만들지 말 것. 다음 경우를 의도적으로 섞으세요: (1) 같은 procedure_code 인데 병원마다 consult_min 이 다른 줄, (2) 한 병원에만 있는 시술, (3) simulation_required 가 false 인 시술만 고른 예약이 생기도록 시뮬레이션이 필요 없는 시술. consult_min 은 5분 단위로 맞춰 주세요. 모든 행은 위 스키마를 통과해야 하고, 형식을 깨뜨리는 시도는 따로 3건만 표시해 두세요.{"type":"object","properties":{"clinic_id":{"type":"string"},"clinic_name":{"type":"string"},"procedure_code":{"type":"string"},"procedure_name":{"type":"string"},"consult_min":{"type":"integer","minimum":5},"simulation_required":{"type":"boolean"}},"required":["clinic_id","clinic_name","procedure_code","procedure_name","consult_min","simulation_required"]}환자가 MIRI 에서 본인 사진으로 만든 시뮬레이션 결과입니다. 결과는 상담 요청(request_id)과 시술에 묶이고, 지난달 다른 요청으로 만든 코 성형 결과(RQ-4871)와 상담 시작 뒤에 만든 결과(SIM-88110, UTC 기록)가 섞여 있습니다. 1주차 데이터는 10월 14일 상담이 끝난 뒤의 기록이라 상담 중에 만든 결과가 들어 있고, 판정은 상담 시작 시각을 기준으로 내므로 전날 오후에 봤을 판정과 같습니다.
| simulation_id | request_id | procedure_code | created_at |
|---|---|---|---|
| SIM-88101 | RQ-5040 | EYE-DBL | 2026-10-11T21:02:00+09:00 |
| SIM-88102 | RQ-5041 | NOSE-AUG | 2026-10-12T19:38:00+09:00 |
| SIM-88103 | RQ-5042 | EYE-DBL | 2026-10-12T22:05:00+09:00 |
| SIM-88104 | RQ-5042 | NOSE-AUG | 2026-10-12T22:12:00+09:00 |
| SIM-88105 | RQ-5043 | EYE-DBL | 2026-10-13T08:30:00+09:00 |
아래 JSON Schema 에 맞는 시뮬레이션 결과를 더 만들어 주세요. {"type":"object","properties":{"simulation_id":{"type":"string"},"request_id":{"type":"string"},"procedure_code":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["simulation_id","request_id","procedure_code","created_at"]} 쉬운 데이터만 만들지 말 것. 다음 경우를 의도적으로 섞으세요: (1) consult_requests 에 없는 예전 request_id 로 만든 결과, (2) 같은 요청인데 관심 시술이 아닌 시술로 만든 결과, (3) created_at 이 그 예약 start_at 보다 늦은 결과, (4) created_at 이 Z 로 끝나는 UTC 시각인 결과와 +09:00 인 결과를 함께. 모든 행은 위 스키마를 통과해야 하고, 형식을 깨뜨리는 시도는 따로 3건만 표시해 두세요.{"type":"object","properties":{"simulation_id":{"type":"string"},"request_id":{"type":"string"},"procedure_code":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["simulation_id","request_id","procedure_code","created_at"]}| TypeScript | 판정 함수와 화면, 연락 결과 API 를 한 언어로 씁니다. 네 판정을 유니온 타입으로 두어 화면이 어느 판정도 빠뜨리지 않게 합니다. |
| React | 판정별 묶음, 펼침 줄, 연락 결과 버튼을 컴포넌트로 나눕니다. |
| Next.js | 병원과 날짜를 고르는 관리자 페이지와 판정을 내는 라우트 핸들러를 둡니다. |
| Cloudflare (Workers · D1) | 1주차부터 화면을 Cloudflare 에 올리고, 네 표를 D1 에 담아 예약별 관심 시술과 병원 시술 목록을 SQL 로 모읍니다. |
| AI 코딩 도구 · Claude Code | 판정 함수와 화면 구현을 맡기고, BK-1040·BK-1043·BK-1045·BK-1048 네 예약을 고정 테스트로 걸어 결과가 요구와 맞는지 직접 열어 보고 고칩니다. |
| API 연동 · 데이터 조회·입력 | 2주차에 연락 결과와 예약 분 수정을 API 로 받아 그 예약의 판정만 다시 냅니다. |
| Claude Haiku 4.5 | 3주차에 환자의 사전 질문을 받는 연락 첫 문장을 씁니다. |
✗ fail → 네 예약 중 하나라도 반대로 서면 '넘으면'을 '이상'으로 쓰지 않았는지, 관심 시술을 procedure_code 로 한 번씩만 모았는지, 시술 목록을 그 예약 clinic_id 로 걸렀는지, 시각을 문자열로 견주지 않았는지부터 봅니다.
✓ pass → 여기서 멈춰도 상담실장이 전날 오후에 쓰는 판정 화면이 완성됩니다. 더 키우려면 전화한 결과를 남기고 판정을 예약 120건으로 시험하는 단계로 갑니다.
✗ fail → 빗나간 예약이 시뮬레이션 시각 규칙에 몰리면 생성기가 만든 created_at 의 시간대 표시부터 확인하고 판정 함수는 그대로 둡니다.
✓ pass → 여기까지도 완결입니다. 더 키우려면 환자가 남긴 질문을 받는 연락 문안 초안을 붙입니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
verdict사유 라벨 · booking_id + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
상담 준비 끝준비 끝병원에서 하지 않는 시술을 물음하지 않는 시술예약 시간 안에 상담을 못 끝냄시간 초과시뮬레이션이 빠진 시술이 있음시뮬레이션 없음상담 예약 판정입니다. 예약 한 건이 네 판정 중 어디에 서는지와, 판정에 쓴 상담 소요 분 합계, 예약 분과의 차, 병원 목록에 없는 시술, 시뮬레이션이 빠진 시술, 상담 시작 뒤라 세지 않은 결과를 남기는 형식입니다. call_reason 은 판정마다 정해 둔 문형이라 모델이 쓰지 않습니다.
{"type":"object","properties":{"booking_id":{"type":"string","description":"판정 대상 예약입니다. bookings.booking_id 값입니다."},"request_id":{"type":"string","description":"그 예약을 가리키는 consult_requests.request_id 입니다."},"clinic_id":{"type":"string"},"start_at":{"type":"string","format":"date-time"},"verdict":{"type":"string","enum":["상담 준비 끝","병원에서 하지 않는 시술을 물음","예약 시간 안에 상담을 못 끝냄","시뮬레이션이 빠진 시술이 있음"],"description":"조건이 여럿 성립하면 병원에서 하지 않는 시술을 물음, 예약 시간 안에 상담을 못 끝냄, 시뮬레이션이 빠진 시술이 있음 순으로 하나를 고릅니다."},"also_flagged":{"type":"array","items":{"type":"string","enum":["병원에서 하지 않는 시술을 물음","예약 시간 안에 상담을 못 끝냄","시뮬레이션이 빠진 시술이 있음"]},"description":"verdict 로 고르지 않았지만 조건이 함께 성립한 판정입니다."},"slot_min":{"type":"integer","minimum":10},"consult_total_min":{"type":"integer","minimum":0,"description":"같은 booking_id 의 관심 시술 중 서로 다른 procedure_code 마다 그 예약 clinic_id 의 clinic_procedures.consult_min 을 한 번씩 더한 값입니다. 그 병원 목록에 없는 시술은 더하지 않습니다."},"minutes_over":{"type":"integer","description":"consult_total_min − slot_min 입니다. 0 이하면 예약 시간 안에 끝납니다."},"unoffered_codes":{"type":"array","items":{"type":"string"},"description":"그 예약 clinic_id 의 clinic_procedures 에 짝이 없는 관심 시술 procedure_code 입니다."},"sim_missing_codes":{"type":"array","items":{"type":"string"},"description":"simulation_required 가 true 인 관심 시술 중, 같은 request_id 에 created_at 이 start_at 을 넘기지 않은 simulations 행이 없는 procedure_code 입니다. 두 시각은 시간대를 붙여 시각으로 바꾼 뒤 견줍니다."},"late_simulation_ids":{"type":"array","items":{"type":"string"},"description":"같은 request_id·procedure_code 인데 created_at 이 start_at 을 넘겨 짝으로 세지 않은 simulations.simulation_id 입니다."},"evidence":{"type":"array","items":{"type":"object","properties":{"scope":{"type":"string"},"field":{"type":"string"},"agg":{"type":"string","enum":["count","sum","avg","min","max"]},"value":{"type":["string","integer","number","boolean","null"]}},"required":["field","value"]}},"call_reason":{"type":"string","description":"판정에서 나온 고정 문형의 연락할 내용 한 문장입니다. 모델이 쓰지 않습니다."},"hedge":{"type":["string","null"]}},"required":["booking_id","request_id","clinic_id","start_at","verdict","also_flagged","slot_min","consult_total_min","minutes_over","unoffered_codes","sim_missing_codes","late_simulation_ids","evidence","call_reason","hedge"]}[
{
"booking_id": "BK-1042",
"request_id": "RQ-5042",
"clinic_id": "CL-GN01",
"start_at": "2026-10-14T14:00:00+09:00",
"verdict": "예약 시간 안에 상담을 못 끝냄",
"also_flagged": [],
"slot_min": 30,
"consult_total_min": 55,
"minutes_over": 25,
"unoffered_codes": [],
"sim_missing_codes": [],
"late_simulation_ids": [],
"evidence": [
{
"field": "booking_id",
"value": "BK-1042"
},
{
"field": "slot_min",
"value": 30
},
{
"scope": "EYE-DBL",
"field": "consult_min",
"value": 20
},
{
"scope": "NOSE-AUG",
"field": "consult_min",
"value": 20
},
{
"scope": "LIPO-ARM",
"field": "consult_min",
"value": 15
},
{
"scope": "관심 시술 합계",
"field": "consult_min",
"agg": "sum",
"value": 55
},
{
"scope": "EYE-DBL",
"field": "simulation_id",
"value": "SIM-88103"
},
{
"scope": "NOSE-AUG",
"field": "simulation_id",
"value": "SIM-88104"
}
],
"call_reason": "관심 시술 세 개를 상담하는 데 55분이 들어 예약 30분을 25분 넘기니, 예약 시간을 늘릴지 환자에게 묻습니다.",
"hedge": "합성 기준 판정입니다. 55분은 병원이 시술마다 적은 상담 소요 분을 그대로 더한 값이라, 세 시술을 이어서 설명할 때 겹치는 시간은 빼지 않았습니다."
},
{
"booking_id": "BK-1045",
"request_id": "RQ-5045",
"clinic_id": "CL-GN01",
"start_at": "2026-10-14T15:00:00+09:00",
"verdict": "병원에서 하지 않는 시술을 물음",
"also_flagged": [],
"slot_min": 30,
"consult_total_min": 10,
"minutes_over": -20,
"unoffered_codes": [
"JAW-RED"
],
"sim_missing_codes": [],
"late_simulation_ids": [],
"evidence": [
{
"field": "booking_id",
"value": "BK-1045"
},
{
"field": "clinic_id",
"value": "CL-GN01"
},
{
"scope": "관심 시술",
"field": "procedure_code",
"value": "JAW-RED"
},
{
"scope": "CL-GN01 시술 목록 중 JAW-RED",
"field": "procedure_code",
"agg": "count",
"value": 0
},
{
"scope": "BTX-JAW",
"field": "consult_min",
"value": 10
},
{
"scope": "관심 시술 합계",
"field": "consult_min",
"agg": "sum",
"value": 10
},
{
"field": "slot_min",
"value": 30
}
],
"call_reason": "사각턱 축소는 이 병원 시술 목록에 없으니, 상담 전에 이번 상담에서 다룰 수 있는 범위를 환자에게 알립니다.",
"hedge": "사각턱 축소는 신사 B의원(CL-SC02) 시술 목록에는 있습니다. 판정은 이 예약 병원의 목록만 봅니다."
},
{
"booking_id": "BK-1047",
"request_id": "RQ-5047",
"clinic_id": "CL-GN01",
"start_at": "2026-10-14T16:30:00+09:00",
"verdict": "시뮬레이션이 빠진 시술이 있음",
"also_flagged": [],
"slot_min": 40,
"consult_total_min": 20,
"minutes_over": -20,
"unoffered_codes": [],
"sim_missing_codes": [
"NOSE-AUG"
],
"late_simulation_ids": [],
"evidence": [
{
"field": "booking_id",
"value": "BK-1047"
},
{
"scope": "NOSE-AUG",
"field": "simulation_required",
"value": true
},
{
"scope": "RQ-5047 의 시뮬레이션",
"field": "procedure_code",
"value": "EYE-DBL"
},
{
"scope": "코 성형 결과가 있는 다른 요청",
"field": "request_id",
"value": "RQ-4871"
},
{
"scope": "관심 시술 합계",
"field": "consult_min",
"agg": "sum",
"value": 20
},
{
"field": "slot_min",
"value": 40
}
],
"call_reason": "코 성형은 상담 전에 시뮬레이션이 있어야 하는 시술인데 이번 요청에 결과가 없으니, 상담 전에 시뮬레이션을 만들어 달라고 환자에게 요청합니다.",
"hedge": "환자는 지난달 다른 요청(RQ-4871)으로 코 성형 시뮬레이션을 만들었습니다. 판정은 이번 요청의 결과만 세므로, 그 결과를 이번 상담에 쓸지는 상담실장이 정합니다."
},
{
"booking_id": "BK-1049",
"request_id": "RQ-5049",
"clinic_id": "CL-GN01",
"start_at": "2026-10-14T17:00:00+09:00",
"verdict": "상담 준비 끝",
"also_flagged": [],
"slot_min": 30,
"consult_total_min": 15,
"minutes_over": -15,
"unoffered_codes": [],
"sim_missing_codes": [],
"late_simulation_ids": [],
"evidence": [
{
"field": "booking_id",
"value": "BK-1049"
},
{
"scope": "EYE-FAT",
"field": "consult_min",
"value": 15
},
{
"scope": "관심 시술 합계",
"field": "consult_min",
"agg": "sum",
"value": 15
},
{
"field": "slot_min",
"value": 30
},
{
"scope": "EYE-FAT",
"field": "simulation_id",
"value": "SIM-88111"
}
],
"call_reason": "연락할 내용이 없습니다.",
"hedge": null
},
{
"booking_id": "BK-1040",
"request_id": "RQ-5040",
"clinic_id": "CL-GN01",
"start_at": "2026-10-14T10:00:00+09:00",
"verdict": "상담 준비 끝",
"also_flagged": [],
"slot_min": 30,
"consult_total_min": 30,
"minutes_over": 0,
"unoffered_codes": [],
"sim_missing_codes": [],
"late_simulation_ids": [],
"evidence": [
{
"field": "booking_id",
"value": "BK-1040"
},
{
"scope": "EYE-DBL",
"field": "consult_min",
"value": 20
},
{
"scope": "SKIN-LSR",
"field": "consult_min",
"value": 10
},
{
"scope": "관심 시술 합계",
"field": "consult_min",
"agg": "sum",
"value": 30
},
{
"field": "slot_min",
"value": 30
},
{
"scope": "EYE-DBL",
"field": "simulation_id",
"value": "SIM-88101"
}
],
"call_reason": "연락할 내용이 없습니다.",
"hedge": "합계 30분이 예약 30분과 같아 시간 초과에 서지 않습니다. 합계가 예약 분을 넘을 때만 시간 초과입니다."
},
{
"booking_id": "BK-1043",
"request_id": "RQ-5043",
"clinic_id": "CL-SC02",
"start_at": "2026-10-14T11:00:00+09:00",
"verdict": "상담 준비 끝",
"also_flagged": [],
"slot_min": 30,
"consult_total_min": 25,
"minutes_over": -5,
"unoffered_codes": [],
"sim_missing_codes": [],
"late_simulation_ids": [],
"evidence": [
{
"field": "booking_id",
"value": "BK-1043"
},
{
"scope": "RQ-5043 의 EYE-DBL 줄",
"field": "procedure_code",
"agg": "count",
"value": 2
},
{
"scope": "EYE-DBL",
"field": "consult_min",
"value": 15
},
{
"scope": "FILL-LIP",
"field": "consult_min",
"value": 10
},
{
"scope": "관심 시술 합계",
"field": "consult_min",
"agg": "sum",
"value": 25
},
{
"field": "slot_min",
"value": 30
},
{
"scope": "EYE-DBL",
"field": "simulation_id",
"value": "SIM-88105"
}
],
"call_reason": "연락할 내용이 없습니다.",
"hedge": "쌍꺼풀을 시뮬레이션 화면과 시술 목록에서 한 번씩 골라 두 줄이 들어왔고, 상담 소요 분은 한 번만 더했습니다. 두 번 더하면 40분이 돼 시간 초과로 뒤집힙니다."
},
{
"booking_id": "BK-1046",
"request_id": "RQ-5046",
"clinic_id": "CL-SC02",
"start_at": "2026-10-14T15:30:00+09:00",
"verdict": "예약 시간 안에 상담을 못 끝냄",
"also_flagged": [
"시뮬레이션이 빠진 시술이 있음"
],
"slot_min": 30,
"consult_total_min": 40,
"minutes_over": 10,
"unoffered_codes": [],
"sim_missing_codes": [
"NOSE-AUG"
],
"late_simulation_ids": [],
"evidence": [
{
"field": "booking_id",
"value": "BK-1046"
},
{
"scope": "NOSE-AUG",
"field": "consult_min",
"value": 25
},
{
"scope": "EYE-DBL",
"field": "consult_min",
"value": 15
},
{
"scope": "관심 시술 합계",
"field": "consult_min",
"agg": "sum",
"value": 40
},
{
"field": "slot_min",
"value": 30
},
{
"scope": "NOSE-AUG",
"field": "simulation_required",
"value": true
},
{
"scope": "RQ-5046 의 NOSE-AUG 결과",
"field": "simulation_id",
"agg": "count",
"value": 0
}
],
"call_reason": "상담에 40분이 들어 예약 30분을 10분 넘기니 예약 시간을 늘릴지 묻고, 같은 통화에서 코 성형 시뮬레이션을 만들어 달라고 요청합니다.",
"hedge": null
},
{
"booking_id": "BK-1048",
"request_id": "RQ-5048",
"clinic_id": "CL-SC02",
"start_at": "2026-10-14T14:00:00+09:00",
"verdict": "시뮬레이션이 빠진 시술이 있음",
"also_flagged": [],
"slot_min": 40,
"consult_total_min": 30,
"minutes_over": -10,
"unoffered_codes": [],
"sim_missing_codes": [
"JAW-RED"
],
"late_simulation_ids": [
"SIM-88110"
],
"evidence": [
{
"field": "booking_id",
"value": "BK-1048"
},
{
"field": "start_at",
"value": "2026-10-14T14:00:00+09:00"
},
{
"field": "simulation_id",
"value": "SIM-88110"
},
{
"field": "created_at",
"value": "2026-10-14T05:12:00Z"
},
{
"scope": "JAW-RED",
"field": "simulation_required",
"value": true
},
{
"scope": "JAW-RED",
"field": "consult_min",
"value": 30
},
{
"field": "slot_min",
"value": 40
}
],
"call_reason": "사각턱 축소는 상담 전에 시뮬레이션이 있어야 하는 시술이니, 상담 전에 결과를 만들어 달라고 환자에게 요청합니다.",
"hedge": "SIM-88110 은 UTC 05:12, 한국 시각 14:12 에 만든 결과라 상담 시작 12분 뒤입니다. 판정은 상담 시작 시각을 기준으로 내므로 전날 오후에 봤을 때와 같은 판정이 나옵니다."
}
][자동 검증 · 코드가 네 표에서 다시 셉니다] 1. verdict 가 enum 네 값 중 하나이고, also_flagged 의 각 값이 상담 준비 끝을 뺀 세 값 중 하나인지 확인합니다. 2. booking_id·verdict·consult_total_min·minutes_over·evidence·call_reason 등 required 필드가 모두 있는지 확인합니다. 3. evidence 의 field 가 네 표의 컬럼(booking_id·clinic_id·start_at·slot_min·request_id·procedure_code·consult_min·simulation_required·simulation_id·created_at)에 실재하는 이름인지 대조합니다. 4. agg 가 없는 evidence 의 value 가 그 컬럼에 수록된 샘플 행의 값 그대로인지 대조합니다. 5. consult_total_min 을 같은 booking_id 의 서로 다른 procedure_code 마다 그 예약 clinic_id 의 consult_min 을 한 번씩 더해 다시 계산하고(쌍꺼풀이 두 줄인 RQ-5043 은 한 번), minutes_over = consult_total_min − slot_min 을 다시 계산합니다. 6. unoffered_codes 가 하나라도 있으면 verdict 는 병원에서 하지 않는 시술을 물음입니다. 성립 사례는 BK-1045(JAW-RED 는 CL-SC02 목록에만 있음), 불성립 사례는 BK-1042 입니다. 7. unoffered_codes 가 없고 consult_total_min 이 slot_min 보다 크면 verdict 는 예약 시간 안에 상담을 못 끝냄입니다. 성립 사례는 BK-1042(55분, 예약 30분)와 BK-1046(40분), 불성립 사례는 합계가 예약 분과 같은 BK-1040(30분)과 BK-1043(25분)입니다. 8. 위 둘에 걸리지 않고 sim_missing_codes 가 하나라도 있으면 verdict 는 시뮬레이션이 빠진 시술이 있음입니다. created_at 과 start_at 은 시간대를 붙여 시각으로 바꾼 뒤 견줍니다. 성립 사례는 BK-1047(코 성형 결과가 RQ-4871 에만 있음)과 BK-1048(SIM-88110 이 UTC 05:12, 한국 시각 14:12 로 상담 시작 뒤), 불성립 사례는 BK-1049 입니다. 9. 세 조건에 모두 걸리지 않으면 verdict 는 상담 준비 끝이고, also_flagged 는 verdict 로 고르지 않은 판정 중 조건이 성립한 값입니다. also_flagged 성립 사례는 BK-1046(시간 초과에 코 성형 시뮬레이션 없음), 불성립 사례는 BK-1042 입니다. 10. call_reason 이 존댓말 한 문장으로 끝나는지 확인합니다. [수동 검증 · 사람이 봅니다] 1. 상담실장과 예약 코디네이터가 연락할 내용 한 줄만 보고 전화할 예약과 할 말을 고르는지, 전날 오후 확인 한 번으로 봅니다. 2. 시간 초과 예약에서 늘릴 분(minutes_over)이 그 병원 상담실 운영에 맞는지 상담실장이 봅니다. [평가 러너 · 2주차] 1. 판정을 심어 만든 예약 120건에 판정을 돌려, 심은 판정과 같은 예약 수를 셉니다. 2. 빗나간 예약은 어느 규칙(시술 목록 대조·합계 비교·시뮬레이션 시각)에서 갈렸는지 같은 줄에 남깁니다.