포티투마루
경력근거: 도메인 특화 데모 및 기술 제안서(RFP·제안발표 대응 포함) 작성
※ 실제 산출물이 아닌 AI 예측 시안입니다.
공고가 프리세일즈 항목에 '도메인 특화 데모 및 기술 제안서(RFP·제안발표 대응 포함) 작성' 을 적었고, 바로 위에 '고객의 규제·보안 요구사항을 반영한 솔루션 아키텍처 제안' 을 두었습니다. 제안서를 쓰기 전에 무엇을 답할 수 있고 무엇을 못 답하는지가 서야 하고, 못 답하는 항목은 일찍 알수록 협력사를 붙일 시간이 남습니다. 이 포트폴리오는 그 대응표를 기능 목록과 규칙으로 만듭니다. '영업 및 사업개발팀과 협업하여 기술 세일즈 사이클을 시니어 관점에서 리딩' 도 그 목록을 먼저 넘기는 자리를 가리킵니다. 이 포트폴리오가 보여주는 것은 기능 목록을 데이터로 두고 공고 요구항목과 맞춰 답할 수 있는지 가르는 기술이며, 국방·방산 도메인 지식이나 조달 심사 실무는 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
'도메인 특화 데모 및 기술 제안서(RFP·제안발표 대응 포함) 작성'. 대응표를 먼저 만들어야 제안서가 서 있습니다.
'고객의 규제·보안 요구사항을 반영한 솔루션 아키텍처 제안'. 보안 항목은 근거 문서 없이는 답이 안 됩니다.
'영업 및 사업개발팀과 협업하여 기술 세일즈 사이클을 시니어 관점에서 리딩'. 못 답할 항목을 일찍 넘기는 일이 그 리딩입니다.
공고에서 뽑은 요구항목을 우리 기능 목록과 맞춰 답할 수 있는지 항목마다 가립니다. 기능 목록에 분야와 열쇳말, 기능 이름, 성숙도, 인용할 근거 문서를 두고 요구항목과 맞춰, 정식 기능이고 근거 문서가 있으면 충족으로 배점을 확보하고 그렇지 않으면 부분 충족·기능 없음·근거 없음 중 어느 쪽인지 사유로 남깁니다. 배점이 안 적힌 항목은 셀 수 없다고 표시하고, 기능 목록에 없는 분야는 미매핑으로 남겨 어느 조직이 답할지 정하게 합니다. 요구항목은 실 사업 자료 대신 지원자가 공개된 조달 공고 양식으로 만든 것을 가정합니다.
공공·국방 사업 제안을 앞에서 끌고 가는 FDE 입니다. 공고를 받아 요구항목을 표로 옮기고 우리 기능과 하나씩 맞춰 보다가, 못 답하는 항목을 마감 직전에 발견해 밤을 새우던 사람입니다.
기능마다 분야와 열쇳말, 성숙도, 근거 문서를 목록으로 두고 공고 요구항목과 맞추면, 답할 항목과 못 답할 항목이 제안 착수 첫날 갈리고 못 답하는 이유가 근거로 남는다는 가정입니다. 기능 목록에 없는 분야는 미매핑으로 빠지므로 우리가 아니라 다른 조직이 답할 자리가 그대로 드러납니다.
요구항목과 기능 목록을 받아 항목마다 충족·미충족을 판정하고 확보 배점을 더하며, 미충족이면 부분 충족·기능 없음·근거 없음·배점 없음·분야 미매핑 중 어느 쪽인지 붙여 공고별로 묶은 대응표를 터미널과 Markdown 파일로 내는 CLI 가 도는 완결품입니다.
공개된 조달 공고 20건을 내려받아 조항 번호와 배점이 붙은 문장을 요구항목으로 뽑고, 손으로 붙인 정답 목록과 대조해 추출 일치율을 냅니다.
충족 항목마다 근거 문서와 쪽수를 붙인 대응 문장 초안을 만들고, 못 답하는 항목은 협력사 검토 목록으로 갈라 사업개발에 넘기는 단계입니다.
FDE 가 요구항목과 기능 목록을 넣으면 항목마다 충족 여부와 확보 배점, 미충족 사유가 공고별로 묶여 나오는 과정을 시연합니다.
공개 양식으로 만든 요구항목 400건과 손으로 붙인 정답 판정을 대조해 일치율을 냅니다. 단, 정답과 요구항목을 모두 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
배점이 비었거나 열쇳말이 흔들리거나 기능 목록에 없는 분야가 섞인 입력 30종을 넣어도 출력 형식이 안 깨지고 사유별로 빠지는 비율을 보여줍니다.
성숙도 기준을 바꿨을 때 확보 배점 합계가 어떻게 달라지는지 회귀로 확인합니다.
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 작성자가 만든 요구항목의 자가채점이며, 실제 제안 승률은 포티투마루의 실 사업 이력과 실 심사 기준이 있어야 측정됩니다. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다.
수치는 합성 데이터 자가채점이라 성능 증명이 아니므로, 면접에서는 데모 동작과 실검증 준비 상태로 솔직히 설명합니다.
정답을 작성자가 붙였으니 잘 맞는 게 당연하므로, 배점 결측과 근거 문서 부재, 기능 목록에 없는 분야를 일부러 섞어 쉬운 항목만 푸는 함정을 피합니다.
이 포트폴리오가 보여주는 것은 기능 목록을 데이터로 두고 공고 요구항목과 맞춰 답할 수 있는지 가르는 기술이며, 국방·방산 도메인 지식이나 조달 심사 실무는 주장하지 않습니다. 판정은 목록 대조가 하고 LLM 은 담당자가 읽을 사유 문장만 맡습니다.
요구항목을 뽑는 일 자체가 해석이라 사람이 읽은 것과 다를 수 있어서, 2주차에 손으로 붙인 목록과 대조해 어느 문장 모양을 놓치는지 셉니다.
실제 사업에서는 기능 성숙도와 근거 문서가 계속 바뀌므로, 기능 목록을 제품 조직과 함께 고치는 일을 운영 과제로 둡니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
공고에서 뽑은 요구항목입니다. 항목 번호와 공고 번호, 분야, 요구 문장, 필수 여부, 배점, 열쇳말, 공고일을 한 행에 둡니다. 배점이 안 적힌 행과 기능 목록에 없는 분야, 필수인데 우리 기능이 시험 단계인 항목을 일부러 섞어 두어 사유가 갈리게 둡니다.
| item_no | rfp_no | section_raw | req_text | must_flag | weight_pct | keyword_raw | published_on |
|---|---|---|---|---|---|---|---|
| RI-001 | RFP-2026-11 | 기술 | 한국어 문서에 대한 검색 증강 생성 기능을 제공할 것 | true | 12 | RAG | 2026-08-10 |
| RI-002 | RFP-2026-11 | 기술 | 질의 응답 결과에 근거 문서와 쪽수를 함께 제시할 것 | true | 8 | 출처표기 | 2026-08-10 |
| RI-003 | RFP-2026-11 | 기술 | 기관 보유 문서를 주기적으로 색인에 반영할 것 | false | 6 | 색인동기화 | 2026-08-10 |
| RI-004 | RFP-2026-11 | 운영 | 관리자가 질의 이력을 조회하고 내려받을 것 | false | 5 | 질의이력 | 2026-08-10 |
| RI-005 | RFP-2026-11 | 보안 | 사용자 권한에 따라 검색 결과를 제한할 것 | true | 10 | 권한필터 | 2026-08-10 |
아래 JSON Schema 를 그대로 만족하는 요구항목 행을 400개 더 만들어 주세요. 공고를 스무 건 두고 공고마다 항목을 열댓 개 붙이며, 분야를 기술·보안·운영·성능·교육·사업관리로 섞습니다. 배점 합이 공고마다 100 근처가 되게 두고, 2할은 배점이나 열쇳말을 비웁니다. 필수 여부를 참·거짓으로 섞고 기능 목록에 없는 분야도 몇 행 넣으세요. 충족 판정이나 확보 배점은 넣지 마세요.
{"type": "object", "properties": {"item_no": {"type": "string"}, "rfp_no": {"type": "string"}, "section_raw": {"type": "string"}, "req_text": {"type": "string"}, "must_flag": {"type": "boolean"}, "weight_pct": {"type": ["number", "null"]}, "keyword_raw": {"type": ["string", "null"]}, "published_on": {"type": "string"}}, "required": ["item_no", "rfp_no", "section_raw", "req_text", "must_flag", "weight_pct", "keyword_raw", "published_on"]}{"type": "object", "properties": {"item_no": {"type": "string"}, "rfp_no": {"type": "string"}, "section_raw": {"type": "string"}, "req_text": {"type": "string"}, "must_flag": {"type": "boolean"}, "weight_pct": {"type": ["number", "null"]}, "keyword_raw": {"type": ["string", "null"]}, "published_on": {"type": "string"}}, "required": ["item_no", "rfp_no", "section_raw", "req_text", "must_flag", "weight_pct", "keyword_raw", "published_on"]}우리 제품이 지금 할 수 있는 일의 목록입니다. 기능 번호와 분야, 열쇳말, 기능 이름, 성숙도, 제안서에 인용할 근거 문서, 담당을 한 행에 둡니다. 성숙도가 정식이 아니면 필수 항목을 그대로 약속하기 어렵고, 근거 문서가 없으면 심사에서 인용할 것이 없습니다. 요구항목에 나오는 분야 중 일부는 일부러 넣지 않아 미매핑이 도출되게 둡니다.
| cap_no | section_raw | keyword_raw | cap_name | maturity_raw | evidence_doc | owner_name |
|---|---|---|---|---|---|---|
| CA-01 | 기술 | RAG | 한국어 문서 검색 증강 생성 | ga | 제품소개서 3장 | 제품 |
| CA-02 | 기술 | 출처표기 | 근거 문서·쪽수 표기 | ga | 제품소개서 4장 | 제품 |
| CA-03 | 기술 | 색인동기화 | 문서 주기 색인 | beta | — | 플랫폼 |
| CA-04 | 운영 | 질의이력 | 질의 이력 조회·내보내기 | ga | 운영매뉴얼 2장 | 플랫폼 |
| CA-05 | 보안 | 권한필터 | 권한 기반 결과 제한 | beta | 보안백서 5장 | 보안 |
아래 JSON Schema 를 그대로 만족하는 기능 행을 40개 더 만들어 주세요. 분야를 기술·보안·운영·성능으로 나누고 열쇳말을 요구항목과 이어지게 적습니다. 성숙도를 정식·시험·검증·없음으로 섞고, 시험·검증 단계 기능 몇 개는 근거 문서를 비웁니다. 요구항목에 나오는 분야 중 일부는 일부러 넣지 마세요 — 미매핑이 있어야 우리가 답할 수 없는 자리가 드러납니다. 판정 결과는 넣지 마세요.
{"type": "object", "properties": {"cap_no": {"type": "string"}, "section_raw": {"type": "string"}, "keyword_raw": {"type": "string"}, "cap_name": {"type": "string"}, "maturity_raw": {"type": "string", "enum": ["ga", "beta", "poc", "none"]}, "evidence_doc": {"type": ["string", "null"]}, "owner_name": {"type": "string"}}, "required": ["cap_no", "section_raw", "keyword_raw", "cap_name", "maturity_raw", "evidence_doc", "owner_name"]}{"type": "object", "properties": {"cap_no": {"type": "string"}, "section_raw": {"type": "string"}, "keyword_raw": {"type": "string"}, "cap_name": {"type": "string"}, "maturity_raw": {"type": "string", "enum": ["ga", "beta", "poc", "none"]}, "evidence_doc": {"type": ["string", "null"]}, "owner_name": {"type": "string"}}, "required": ["cap_no", "section_raw", "keyword_raw", "cap_name", "maturity_raw", "evidence_doc", "owner_name"]}| Python | 요구항목과 기능 목록을 맞춰 성숙도와 근거를 견주고 배점을 더하는 판정기를 맡습니다. |
| PostgreSQL | 기능 목록과 요구항목, 판정 결과를 담습니다. |
| Markdown | 공고별 대응표와 협력사 검토 목록을 파일로 냅니다. |
✗ fail → 미매핑이 절반을 넘으면 기능 목록을 먼저 채웁니다.
✓ pass → 2주차 공고 자동 추출로 넘어갑니다.
✗ fail → 놓친 문장 모양을 모아 추출 규칙을 다시 봅니다.
✓ pass → 3주차 대응 문장으로 넘어갑니다.
요구항목 하나와 우리 기능이 만나는 자리마다 답할 수 있는지 정하고 확보 배점을 냅니다. 못 답하면 부분 충족·기능 없음·근거 없음·배점 없음·분야 미매핑 중 어느 쪽인지 싣습니다. 대응표는 이 사유 코드로 묶습니다.
{"type": "object", "properties": {"verdict_no": {"type": "string"}, "item_no": {"type": "string"}, "rfp_no": {"type": "string"}, "section_raw": {"type": "string"}, "cap_no": {"type": ["string", "null"]}, "cover_code": {"type": "string", "enum": ["covered", "partial_cover", "capability_gap", "evidence_missing", "weight_missing", "section_unmapped"]}, "scored_pct": {"type": ["number", "null"], "description": "그 항목의 weight_pct 를 그대로 적은 확보 배점입니다. 충족으로 판정된 항목에만 채웁니다."}, "maturity_raw": {"type": ["string", "null"]}, "owner_name": {"type": ["string", "null"]}, "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": ["verdict_no", "item_no", "rfp_no", "section_raw", "cover_code", "evidence", "summary"]}[
{
"verdict_no": "RR-001",
"item_no": "RI-001",
"rfp_no": "RFP-2026-11",
"section_raw": "기술",
"cap_no": "CA-01",
"cover_code": "covered",
"scored_pct": 12,
"maturity_raw": "ga",
"owner_name": "제품",
"evidence": [
{
"field": "weight_pct",
"agg": null,
"value": 12
},
{
"field": "maturity_raw",
"agg": null,
"value": "ga"
}
],
"summary": "정식 출시된 기능이고 근거 문서도 있어 배점을 그대로 확보합니다.",
"hedge": null
},
{
"verdict_no": "RR-002",
"item_no": "RI-006",
"rfp_no": "RFP-2026-11",
"section_raw": "보안",
"cap_no": "CA-06",
"cover_code": "covered",
"scored_pct": 7,
"maturity_raw": "ga",
"owner_name": "보안",
"evidence": [
{
"field": "evidence_doc",
"agg": null,
"value": "보안백서 6장"
},
{
"field": "must_flag",
"agg": null,
"value": true
}
],
"summary": "필수 항목이고 보안백서에 근거가 있어 제안서에 바로 인용합니다.",
"hedge": null
},
{
"verdict_no": "RR-003",
"item_no": "RI-005",
"rfp_no": "RFP-2026-11",
"section_raw": "보안",
"cap_no": "CA-05",
"cover_code": "partial_cover",
"scored_pct": null,
"maturity_raw": "beta",
"owner_name": "보안",
"evidence": [
{
"field": "maturity_raw",
"agg": null,
"value": "beta"
},
{
"field": "must_flag",
"agg": null,
"value": true
}
],
"summary": "필수 항목인데 아직 시험 단계라 배점을 다 못 가져가고 일정 약속이 필요합니다.",
"hedge": null
},
{
"verdict_no": "RR-004",
"item_no": "RI-003",
"rfp_no": "RFP-2026-11",
"section_raw": "기술",
"cap_no": "CA-03",
"cover_code": "evidence_missing",
"scored_pct": null,
"maturity_raw": "beta",
"owner_name": "플랫폼",
"evidence": [
{
"field": "evidence_doc",
"agg": null,
"value": null
},
{
"field": "weight_pct",
"agg": null,
"value": 6
}
],
"summary": "기능은 있는데 제안서에 인용할 문서가 없어 심사에서 근거를 못 댑니다.",
"hedge": null
},
{
"verdict_no": "RR-005",
"item_no": "RI-007",
"rfp_no": "RFP-2026-12",
"section_raw": "기술",
"cap_no": null,
"cover_code": "capability_gap",
"scored_pct": null,
"maturity_raw": null,
"owner_name": null,
"evidence": [
{
"field": "keyword_raw",
"agg": null,
"value": "음성인식"
},
{
"field": "cap_no",
"agg": "count",
"value": 12
}
],
"summary": "기능 목록 열두 행에 없어 협력사를 붙일지 제안 범위에서 뺄지 정해야 합니다.",
"hedge": null
},
{
"verdict_no": "RR-006",
"item_no": "RI-008",
"rfp_no": "RFP-2026-12",
"section_raw": "기술",
"cap_no": "CA-07",
"cover_code": "weight_missing",
"scored_pct": null,
"maturity_raw": "ga",
"owner_name": "제품",
"evidence": [
{
"field": "weight_pct",
"agg": null,
"value": null
},
{
"field": "maturity_raw",
"agg": null,
"value": "ga"
}
],
"summary": "기능은 있으나 배점이 안 적혀 얼마를 확보하는지 셀 수 없습니다.",
"hedge": "공고 본문에 배점표가 별첨으로 빠졌을 수 있어 원문을 다시 봅니다."
},
{
"verdict_no": "RR-007",
"item_no": "RI-009",
"rfp_no": "RFP-2026-12",
"section_raw": "성능",
"cap_no": "CA-08",
"cover_code": "partial_cover",
"scored_pct": null,
"maturity_raw": "poc",
"owner_name": "플랫폼",
"evidence": [
{
"field": "maturity_raw",
"agg": null,
"value": "poc"
},
{
"field": "evidence_doc",
"agg": null,
"value": "성능시험보고서 1장"
}
],
"summary": "시험 구축에서만 확인한 성능이라 근거는 있어도 필수 항목을 그대로 약속하기 어렵습니다.",
"hedge": null
},
{
"verdict_no": "RR-008",
"item_no": "RI-010",
"rfp_no": "RFP-2026-12",
"section_raw": "교육",
"cap_no": null,
"cover_code": "section_unmapped",
"scored_pct": null,
"maturity_raw": null,
"owner_name": null,
"evidence": [
{
"field": "section_raw",
"agg": null,
"value": "교육"
},
{
"field": "cap_no",
"agg": "count",
"value": 12
}
],
"summary": "기능 목록에 없는 항목이라 사업관리 쪽에서 답할 자리입니다.",
"hedge": null
}
][자동 검증 · 코드가 판정합니다] 1. cover_code 가 enum 여섯 값 중 하나인지 확인합니다. 2. verdict_no·item_no·rfp_no·section_raw·cover_code·evidence·summary 가 모두 채워졌는지 확인합니다. 3. item_no 가 요구항목에 실재하는 번호인지 대조합니다. 4. cap_no 가 있으면 기능 목록에 실재하는 행 번호인지 대조합니다. 5. cap_no 가 있으면 maturity_raw·owner_name 이 그 기능 행의 값과 같은지 대조합니다. 6. keyword_raw 를 띄어쓰기를 접어 기능 목록과 맞추고, 그 분야 자체가 기능 목록에 없으면 cover_code 가 section_unmapped 인지 확인합니다. 7. 분야는 있는데 열쇳말이 맞는 기능이 없으면 cover_code 가 capability_gap 인지 확인합니다. 8. evidence_doc 이 비어 있으면 cover_code 가 evidence_missing 인지 확인합니다. 9. 근거 문서가 있는데 maturity_raw 가 ga 가 아니면 cover_code 가 partial_cover 인지 확인합니다. 10. weight_pct 가 비어 있으면 cover_code 가 weight_missing 인지 확인합니다. 11. cover_code 가 covered 이면 scored_pct 가 weight_pct 와 같은지 대조합니다. 12. 공고별로 covered 인 항목의 scored_pct 합이 100 을 넘지 않는지 다시 셉니다. 13. evidence 의 field 이름이 요구항목과 기능 목록에 실재하는 컬럼인지 대조합니다. 14. agg 가 없는 evidence 의 value 가 그 컬럼에 수록된 행 값과 같은지 확인합니다. 15. summary 가 존댓말로 끝나는지 확인합니다. [평가 러너 · 2주차] 공개 조달 공고 20건에서 자동으로 뽑은 요구항목과 손으로 붙인 목록을 대조해 추출 일치율과 사유 코드별 분포를 내고, 필수 항목 중 못 답하는 건수를 함께 냅니다. [수동 검증 · 사람이 봅니다] 1. 기능이 없는 항목에 협력사를 붙일지 사업개발이 정합니다. 2. 시험 단계 기능을 필수 항목에 약속할지 제품 조직이 정합니다.