오픈에이아이
경력근거: Build full-stack systems that deliver customer value
오픈에이아이 Forward Deployed Engineer 는 전략 고객사 팀에 밀착해 필요를 파악하고 첫 프로토타입부터 안정 운영까지 배포를 끌고 가는 자리라서, 고객사 담당자가 지금 손으로 하고 있는 일을 그 회사가 이미 쓰는 파일 그대로 받아 자동화가 되는지 확인하는 것이 시작점입니다. 제안팀의 요구사항 엑셀은 병합 셀과 소계 행과 흔들리는 필수 표기가 섞인 실제 업무 문서라서, 잘 정리된 API 응답을 가정한 도구는 현장에서 첫날에 막힙니다. 이 포트폴리오는 화면을 만들지 않고 담당자가 터미널에서 바로 돌려 보는 CLI로 기능을 검증하며, 모델이 쓴 문장이 대응표 품질에 어떻게 드러나는지를 추출 평가로 재서 현장 피드백으로 남깁니다. 이 포트폴리오가 보여주는 것은 지저분한 엑셀 파싱과 규칙 판정과 인용 검증과 문서 생성 기술이며, 공공 조달 절차나 제안 평가 기준 같은 도메인 전문성은 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
고객 팀에 밀착해 필요를 파악하고 만든 것의 도입까지 이끄는 게 핵심 업무입니다. 고객사 제안팀이 이미 엑셀로 굴리는 파일을 그대로 입력으로 받는 CLI가 그 첫 프로토타입의 형태입니다.
LLM 으로 시스템을 만들고 모델 동작이 제품 경험에 어떻게 영향을 주는지 이해해야 합니다. 요구사항 추출 정확도를 재고 잘못 만들어낸 항목을 사례로 남기는 부분이 그 자리와 직접 닿습니다.
동작하는 패턴을 도구와 운영 가이드와 재사용 블록으로 정리합니다. 판정 규칙과 문서 생성 골격을 규칙 파일로 분리해 다른 고객사 문서에 갈아끼우는 흐름이 이와 맞습니다.
계약된 전략 고객사의 제안팀이 쓰는 파일 두 개, 즉 발주처 RFP 요구사항을 손으로 옮겨 놓은 엑셀과 제품 사양 카탈로그 엑셀을 읽어 요구사항마다 충족 여부를 판정하는 CLI입니다. 터미널에서 reply build 명령에 두 파일을 주면 충족과 부분충족과 미충족과 확인 필요가 절 단위로 갈리고 판정마다 근거 셀 인용과 응답 문장 초안이 붙은 요구사항 대응표 Markdown 파일이 생기며, 표준출력에는 판정 분포 요약 표가 찍힙니다. 판정은 사양 표의 목표 수치 비교와 지원 수준 값으로 규칙이 내리고, 병합 셀 때문에 상위 항목이 빈 행이나 한 칸에 두 요구가 들어간 행처럼 규칙으로 가를 수 없는 행은 확인 필요로 따로 모아 사람이 볼 목록으로 냅니다.
발주처 RFP 요구사항 수백 줄을 제품 사양 카탈로그와 하나씩 눈으로 맞춰 가며 대응표를 채우다가, 제출 이틀 전에야 필수 요구 하나가 미충족이라는 것을 알게 되던 전략 고객사 제안팀 담당자입니다. 늘 쓰던 요구사항 엑셀과 사양 카탈로그 파일을 그대로 건네고 터미널에서 명령 한 번을 쳐서, 충족과 부분충족과 확인 필요가 근거 셀로 갈린 대응표 초안을 받아 문장만 다듬어 제출하고 싶은 사람입니다.
요구사항의 목표 수치와 사양 카탈로그의 값은 둘 다 표에 적힌 데이터라서, 충족 여부를 사람의 기억이 아니라 수치 비교와 지원 수준 규칙으로 판정하면 대응표의 골격이 자동으로 서고, 담당자는 조건이 붙은 항목과 확인 필요 항목에만 시간을 쓰게 된다는 가정입니다.
고객사에서 받는 형태의 요구사항 엑셀과 제품 사양 카탈로그 엑셀 더미를 놓고 터미널에서 reply build 명령을 치면, 요구사항마다 충족과 부분충족과 미충족을 사양 표의 셀 인용으로 판정하고 규칙으로 가를 수 없는 행을 확인 필요 절로 모은 요구사항 대응표 Markdown 파일이 생기며 표준출력에 판정 분포 요약 표가 찍히는 완결품입니다. 만드는 덩어리는 엑셀 대조 판정 규칙과 Markdown 문서 생성 둘뿐이고 화면과 서버와 배포가 없어 평일 닷새에 혼자 끝나는 범위이며, 데이터는 실제 고객 자료 대신 작성자가 만든 더미를 씁니다.
제안팀이 요구사항을 손으로 옮기던 단계를 없애도 되는지 확인하는 계층입니다. extract 하위 명령이 RFP 원문 PDF 에서 요구사항 번호와 본문과 쪽수를 뽑고, 손으로 정리한 엑셀을 정답으로 두어 재현율과 정밀도를 계산하며, 놓친 항목과 잘못 만들어낸 항목을 사례 목록으로 남깁니다.
요구사항 표기와 사양 어휘를 규칙 파일로 분리해, 다른 고객사의 보안 질의서 같은 문서에도 같은 골격을 갈아끼워 돌려 보는 확장입니다. 두 번째 문서 유형으로 실제 실행하고 교체에 든 시간을 기록해 재사용 블록의 설명서로 남깁니다.
요구사항 68행과 사양 카탈로그 54행을 놓고 터미널에서 reply build 명령을 치면, 충족과 부분충족과 미충족과 확인 필요가 근거 셀 인용으로 갈린 요구사항 대응표 Markdown 파일이 생기고 표준출력에 판정 분포 요약 표가 찍히는 흐름을 시연합니다.
병합 셀로 상위 항목이 빈 행과 한 칸에 두 요구가 들어간 행과 번호가 겹치는 행과 필수 표기가 빈 행과 소계·머리글 행이 섞인 입력 30종을 넣어도 도구가 멈추지 않고 확인 필요로 분리하는 것을 보입니다. 다만 입력과 정답을 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
같은 입력에서 두 번 실행하면 문자까지 같은 파일이 나오는 결정론을 테스트로 보이고, 필수 요구 가운데 미충족이 하나라도 있으면 종료 코드로 알려 제출 전에 사람이 멈추게 합니다.
2주차에는 RFP 원문 PDF 에서 뽑은 요구사항을 제안팀이 손으로 정리한 엑셀과 대조합니다. 정답 68건 가운데 58건을 그대로 찾아 재현율 약 85%, 잘못 만들어낸 항목 6건으로 정밀도 약 91% 입니다. 정답이 원문에 그대로 있는 문장이라 대조가 규칙으로 끝납니다.
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 전부 작성자가 만든 더미데이터 자가채점이며, 실제 대응표 품질은 고객사의 실제 RFP 와 사양 문서와 제안 담당자의 검토가 있어야 측정 가능합니다. 이 도구는 그 검증을 바로 돌릴 수 있는 상태로 만듭니다.
수치는 합성 데이터 자가채점이라 성능 증명이 아닙니다. 면접에서는 데모가 도는 상태와 실검증 준비 상태로 솔직히 설명합니다.
정답을 작성자가 만들었으니 잘 맞는 것이 당연합니다. 상위 항목이 빈 행과 한 칸에 두 요구가 들어간 행과 번호가 겹치는 행과 지원 수준이 unknown 인 사양을 더미에 일부러 섞어 두었습니다.
판정이 틀리면 미충족 요구가 충족으로 적힌 대응표가 발주처에 나갑니다. 수치 비교로 가를 수 없는 항목은 억지로 판정하지 않고 확인 필요로 돌리며, 조건이 붙은 사양은 부분충족으로 두고 그 조건 문장을 그대로 붙입니다.
실제 RFP 는 문서마다 번호 체계와 필수 표기가 달라 한 고객사에서 맞춘 규칙이 다음 고객사에서 그대로 돌지 않습니다. 규칙 파일 분리를 3주차 과제로 두었고, 그래도 남는 차이는 도입 단계에서 담당자와 맞춰야 합니다.
이 포트폴리오가 보여주는 것은 지저분한 엑셀 파싱과 규칙 판정과 인용 검증과 문서 생성 기술이며, 공공 조달 절차나 제안 평가 기준 같은 도메인 전문성은 주장하지 않습니다. 모르는 부분은 면접에서 모른다고 말합니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
전략 고객사 제안팀이 발주처 RFP 원문을 보며 손으로 옮겨 놓은 요구사항 엑셀의 시트 추출본입니다. CLI가 가장 먼저 읽는 입력이고, 2주차 PDF 추출의 정답 역할도 합니다. 병합 셀 때문에 상위 항목이 빈 행과 소계·머리글 행과 흔들리는 필수 표기를 그대로 두어, 잘 정리된 표만 다루는 도구가 아님을 보입니다. 전부 작성자가 만든 더미입니다.
| req_id | section | row_kind | requirement_text | mandatory_raw | target_value_raw | source_page |
|---|---|---|---|---|---|---|
| 3.1 | 성능 | section_header | 3.1 시스템 성능 요구사항 | — | — | 12 |
| 3.1.1 | — | requirement | 동시 접속 사용자 2,000명 환경에서 주요 조회 화면의 응답시간 평… | 필수 | 3초 | 12 |
| 3.1.2 | — | requirement | 대용량 배치 처리 시 시간당 100만 건 이상을 처리하고, 실패 건은… | M | 100만 건/시간 | 12 |
| 3.1.2 | — | requirement | 배치 재처리 이력을 관리자 화면에서 조회할 수 있을 것 | — | — | 13 |
| 소계 | 성능 | subtotal | 성능 요구사항 소계 4건 | — | — | — |
아래 JSON Schema에 맞는 RFP 요구사항 시트 행을 30건 더 만들어 주세요. {"type":"object","properties":{"req_id":{"type":"string"},"section":{"type":["string","null"]},"row_kind":{"type":"string","enum":["requirement","section_header","subtotal","note"]},"requirement_text":{"type":"string"},"mandatory_raw":{"type":["string","null"]},"target_value_raw":{"type":["string","null"]},"source_page":{"type":["integer","null"]}},"required":["req_id","row_kind","requirement_text"]} 전부 가상 더미로 만들고, 쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어 주세요. 첫째 병합 셀 때문에 section 이 null 인 requirement 행 다수, 둘째 한 칸에 두 가지 요구가 붙어 있는 행 4건, 셋째 req_id 가 다른 행과 겹치는 행 2건, 넷째 mandatory_raw 가 필수·M·선택·빈 문자열·null 로 제각각인 행, 다섯째 target_value_raw 의 단위가 초와 ms 와 건/시간처럼 섞인 행, 여섯째 row_kind 가 section_header 와 subtotal 과 note 인 행이 요구사항 사이에 끼어 있는 경우, 일곱째 target_value_raw 가 비어 있어 수치 비교가 불가능한 행 4건. JSON 배열만 내주세요.{"type":"object","properties":{"req_id":{"type":"string"},"section":{"type":["string","null"]},"row_kind":{"type":"string","enum":["requirement","section_header","subtotal","note"]},"requirement_text":{"type":"string"},"mandatory_raw":{"type":["string","null"]},"target_value_raw":{"type":["string","null"]},"source_page":{"type":["integer","null"]}},"required":["req_id","row_kind","requirement_text"]}고객사 제품팀이 관리하는 제품 사양 카탈로그 엑셀의 추출본입니다. 판정 규칙이 요구사항과 대조하는 근거 표이고, 대응표에 인용으로 실리는 셀이 여기에서 나옵니다. 조건이 붙은 사양과 지원 여부가 확인되지 않은 사양을 섞어, 모든 요구를 깔끔하게 가를 수 없는 상황을 그대로 둡니다. 전부 작성자가 만든 더미입니다.
| spec_id | feature | capability_text | support_level | value | unit | condition | doc_ref |
|---|---|---|---|---|---|---|---|
| S-101 | 동시 접속 | 동시 접속 3,000명까지 부하 시험 완료 | full | 3,000 | 명 | 웹 서버 2대 구성 기준 | 성능시험보고서 p.7 |
| S-102 | 조회 응답시간 | 주요 조회 화면 평균 응답시간 2.4초 | full | 2.4 | 초 | 표준 구성과 데이터 3년치 기준 | 성능시험보고서 p.9 |
| S-103 | 배치 처리량 | 배치 처리량 시간당 60만 건 | partial | 600,000 | 건/시간 | 단일 노드 기준이며 노드 증설 시 거의 선형으로 늘어남 | 구축가이드 p.31 |
| S-104 | 배치 재처리 | 실패 건 자동 재처리와 재처리 이력 조회 제공 | full | — | — | — | 운영자매뉴얼 p.52 |
| S-201 | 전송 구간 암호화 | TLS 1.3 적용, 1.2 하위 호환 지원 | full | 1.3 | TLS 버전 | — | 보안백서 p.4 |
아래 JSON Schema에 맞는 제품 사양 카탈로그 행을 25건 더 만들어 주세요. {"type":"object","properties":{"spec_id":{"type":"string"},"feature":{"type":"string"},"capability_text":{"type":"string"},"support_level":{"type":"string","enum":["full","partial","none","unknown"]},"value":{"type":["number","null"]},"unit":{"type":["string","null"]},"condition":{"type":["string","null"]},"doc_ref":{"type":["string","null"]}},"required":["spec_id","feature","capability_text","support_level"]} 전부 가상 더미로 만들고, 쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어 주세요. 첫째 support_level 이 partial 이면서 condition 에 고객사 추가 도입이나 증설 같은 전제가 붙은 행 6건, 둘째 support_level 이 unknown 이라 사람이 확인해야 하는 행 3건, 셋째 value 는 있는데 unit 이 null 이라 단위를 알 수 없는 행 2건, 넷째 doc_ref 가 null 이라 근거 문서를 댈 수 없는 행 3건, 다섯째 같은 feature 를 다루는 행이 두 개라 어느 쪽을 근거로 삼을지 갈리는 경우 2쌍, 여섯째 capability_text 에 지원과 미지원이 한 문장에 함께 적힌 행 2건. JSON 배열만 내주세요.{"type":"object","properties":{"spec_id":{"type":"string"},"feature":{"type":"string"},"capability_text":{"type":"string"},"support_level":{"type":"string","enum":["full","partial","none","unknown"]},"value":{"type":["number","null"]},"unit":{"type":["string","null"]},"condition":{"type":["string","null"]},"doc_ref":{"type":["string","null"]}},"required":["spec_id","feature","capability_text","support_level"]}| Python | 2주차 추출 평가 하니스의 구현 언어입니다. PDF 에서 뽑은 요구사항을 정답 엑셀과 대조해 재현율과 정밀도를 계산하고 놓친 항목을 집계합니다. |
| JavaScript | CLI 본체를 TypeScript 로 구현합니다. 엑셀 시트 읽기와 충족 판정 규칙과 Markdown 문서 생성과 하위 명령 해석이 전부 여기에 있습니다. |
| OpenAI | 요구사항 문장을 판정 가능한 조건으로 정규화하고 응답 문장 초안을 쓰는 모델 연동입니다. 데모는 클로드로 돌리고 실무에서는 오픈에이아이 모델로 바꿔 끼웁니다. |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우려면 2주차에서 RFP 원문 PDF 추출과 추출 정확도 측정을 붙입니다.
✓ pass → 여기까지도 완결입니다. 더 키우려면 3주차에서 규칙 파일을 분리해 다른 고객사 문서로 갈아끼웁니다.
요구사항 한 건에 대한 대응 항목입니다. 어느 사양 행을 근거로 어떤 규칙이 그 판정을 내렸는지 담아, 발주처나 내부 검토자가 이유를 물으면 제안 담당자가 바로 근거를 답하게 합니다.
{"type":"object","properties":{"req_id":{"type":"string"},"verdict":{"type":"string","enum":["meets","partially_meets","not_met","needs_review"]},"basis":{"type":"string","enum":["rule_value_compare","rule_support_level","spec_missing","input_defect"]},"matched_spec_ids":{"type":"array","items":{"type":"string"}},"evidence":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"quote":{"type":"string"}},"required":["field","quote"]}},"draft_sentence":{"type":["string","null"]},"needs_human_review":{"type":"boolean"},"hedge":{"type":["string","null"]}},"required":["req_id","verdict","basis","matched_spec_ids","evidence","needs_human_review"]}[
{
"req_id": "3.1.1",
"verdict": "meets",
"basis": "rule_value_compare",
"matched_spec_ids": [
"S-102"
],
"evidence": [
{
"field": "requirement.target_value_raw",
"quote": "3초"
},
{
"field": "spec.value",
"quote": "2.4"
},
{
"field": "spec.condition",
"quote": "표준 구성과 데이터 3년치 기준"
}
],
"draft_sentence": "표준 구성 기준 주요 조회 화면의 평균 응답시간이 2.4초로 측정되어 요구 기준 3초 이내를 충족합니다.",
"needs_human_review": false,
"hedge": null
},
{
"req_id": "3.1.2",
"verdict": "partially_meets",
"basis": "rule_value_compare",
"matched_spec_ids": [
"S-103"
],
"evidence": [
{
"field": "requirement.target_value_raw",
"quote": "100만 건/시간"
},
{
"field": "spec.value",
"quote": "600000"
},
{
"field": "spec.condition",
"quote": "단일 노드 기준이며 노드 증설 시 거의 선형으로 늘어남"
}
],
"draft_sentence": "단일 노드 기준 처리량은 시간당 60만 건이며, 노드 증설 구성으로 요구 기준 100만 건을 만족하는 방안을 제안드립니다.",
"needs_human_review": true,
"hedge": "증설 구성이 전제라 구성안과 비용은 제안 담당자가 확인해야 합니다."
},
{
"req_id": "3.2.3",
"verdict": "partially_meets",
"basis": "rule_value_compare",
"matched_spec_ids": [
"S-203"
],
"evidence": [
{
"field": "requirement.target_value_raw",
"quote": "5년"
},
{
"field": "spec.value",
"quote": "3"
},
{
"field": "spec.condition",
"quote": "스토리지 증설 옵션 적용 시 5년까지 확장"
}
],
"draft_sentence": "접근 이력 기본 보관 기간은 3년이며, 스토리지 증설 옵션을 적용하면 요구 기준 5년까지 확장됩니다.",
"needs_human_review": true,
"hedge": "옵션 적용이 전제라 범위와 비용은 제안 담당자가 확인해야 합니다."
},
{
"req_id": "4.1.1",
"verdict": "not_met",
"basis": "rule_support_level",
"matched_spec_ids": [
"S-301",
"S-302"
],
"evidence": [
{
"field": "spec.support_level",
"quote": "none"
},
{
"field": "spec.capability_text",
"quote": "ERP 연계는 표준 어댑터 없이 개별 구축 범위"
}
],
"draft_sentence": null,
"needs_human_review": true,
"hedge": "필수 요구인데 ERP 연계 사양이 미지원이라 제출 전에 대응 방향을 정해야 합니다."
},
{
"req_id": "3.1.2",
"verdict": "needs_review",
"basis": "input_defect",
"matched_spec_ids": [],
"evidence": [
{
"field": "input.req_id",
"quote": "3.1.2"
},
{
"field": "input.requirement_text",
"quote": "배치 재처리 이력을 관리자 화면에서 조회할 수 있을 것"
}
],
"draft_sentence": null,
"needs_human_review": true,
"hedge": "같은 번호가 두 행에 있어 어느 쪽이 원문 항목인지 담당자가 확인해야 합니다."
}
][자동 검증. 코드가 매 출력마다 자동으로 거릅니다] 1. 항목 JSON 이 위 스키마를 통과하는지 확인합니다. verdict 나 basis 가 정해진 값 밖이면 그 항목을 버립니다. 2. basis 가 rule_value_compare 인 항목은 evidence 의 quote 가 입력 표의 실제 셀 값과 문자 그대로 같은지 대조합니다. 수치 판정에 지어낸 근거가 붙으면 대응표 전체를 믿을 수 없기 때문입니다. 3. matched_spec_ids 가 사양 카탈로그에 실재하는 식별자인지 확인합니다. 없는 식별자는 지어낸 것으로 보고 그 항목을 확인 필요로 돌립니다. 4. draft_sentence 에 등장하는 수치가 evidence 의 값과 일치하는지 대조합니다. 모델이 문장을 쓰면서 숫자를 바꾸면 여기서 걸립니다. 5. verdict 가 needs_review 이거나 사양의 support_level 이 partial 또는 unknown 이면 needs_human_review 가 true 인지 확인합니다. 6. 같은 입력으로 두 번 실행한 대응표 파일이 문자 그대로 같은지 비교합니다. 결정론이 깨지면 판정 규칙에 순서 의존 버그가 들어간 것입니다. [수동 검증. 사람이 일부만 확인합니다] 1. 생성된 대응표 한 부를 제안 담당자 관점에서 읽고, 발주처에 그대로 내도 되는 문장인지 봅니다. 2. 필수 요구 가운데 미충족과 확인 필요 항목을 원본 사양 문서와 하나씩 대조합니다. 3. 확인 필요로 빠진 항목이 실제로는 규칙으로 가를 수 있었던 것인지 살펴, 과하게 사람에게 넘기는 규칙을 다듬습니다.
근거: Build full-stack systems that deliver customer value