베이스스톤
경력근거: 보안 요구사항(접근제어, 권한 관리, 로그·감사 추적 등) 반영 및 점검
※ 실제 산출물이 아닌 AI 예측 시안입니다.
공고가 주요업무에 '보안 요구사항(접근제어, 권한 관리, 로그·감사 추적 등) 반영 및 점검' 을 적었고, 바로 앞에 '고객사(기업·공공기관) 환경에 맞춘 구축 및 기술 대응' 을 두었습니다. 환경마다 권한이 다르게 쌓여 있어 정책을 바꿀 때 누가 걸리는지가 매번 문제가 되고, 이 포트폴리오는 그 확인을 시행 전으로 당깁니다. 우대사항의 'LLM API를 활용한 기능 개발 또는 사내 자동화 구축 경험' 도 판정은 규칙이 하고 모델은 사유 문장만 쓰는 이 설계와 맞습니다. 이 포트폴리오가 보여주는 것은 정책을 데이터로 두고 부여 목록과 맞춰 영향 범위를 내는 기술이며, 암호 모듈 구현이나 공공 보안 인증 실무는 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
'보안 요구사항(접근제어, 권한 관리, 로그·감사 추적 등) 반영 및 점검'. 이 편은 그 점검을 정책 변경 전으로 당깁니다.
'고객사(기업·공공기관) 환경에 맞춘 구축 및 기술 대응'. 환경마다 역할 이름이 달라 매핑이 도입 과제가 됩니다.
'LLM API를 활용한 기능 개발 또는 사내 자동화 구축 경험'. 판정은 규칙이 하고 모델은 사유 문장만 씁니다.
바꿀 권한 정책과 지금 부여된 권한을 맞춰 시행 뒤 누가 무엇을 못 하게 되는지 미리 가릅니다. 변경안에 역할과 자원 패턴, 동작, 허용·차단, 시행일을 두고 부여 목록과 맞춰, 결과가 그대로면 영향 없음으로 넘기고 달라지면 새로 막힘·동작 규칙 없음 중 어느 쪽인지 남깁니다. 시행 전에 끝나는 부여는 만료로 빼고, 규칙이 다른 자원을 가리키면 대상 아님으로, 변경안에 없는 역할은 미선언으로 남겨 먼저 정하게 합니다. 부여 목록은 실 고객사 권한 대장 대신 지원자가 공개 접근제어 규격으로 만든 것을 가정합니다.
보안 제품을 만들며 고객 환경의 권한 정책도 함께 손보는 개발자입니다. 정책을 바꾸고 나면 시행 당일 아침부터 '갑자기 안 된다'는 연락을 받고, 그제서야 누가 걸렸는지 대장을 뒤져 세던 사람입니다.
바꿀 규칙을 역할과 자원 패턴, 동작으로 적어 두고 지금 부여와 맞추면, 시행 뒤 막힐 사람과 새로 열릴 사람이 시행 전에 목록으로 나온다는 가정입니다. 변경안에 없는 역할은 미선언으로 빠지므로 아직 결정하지 않은 역할이 그대로 드러납니다.
부여 목록과 변경안을 받아 부여마다 영향 없음·새로 막힘·동작 규칙 없음을 판정하고, 판정하지 못하면 만료·대상 아님·역할 미선언 중 어느 쪽인지 붙여 역할별로 묶은 영향 리포트를 터미널과 Markdown 파일로 내는 CLI 가 도는 완결품입니다.
공개 규격으로 만든 부여 500건에 손으로 붙인 정답 영향과 대조해 일치율을 내고, 미선언이 몰리는 역할을 모아 결정이 빠진 자리를 목록으로 냅니다.
새로 막히는 부여를 담당 조직별로 갈라 시행일과 대체 경로를 담은 안내 초안을 조립하고, 예외 신청이 필요한 건을 따로 내는 단계입니다.
보안 담당자가 부여 목록과 변경안을 넣으면 부여마다 시행 뒤 결과와 사유가 역할별로 묶여 나오는 과정을 시연합니다.
공개 규격으로 만든 부여 500건과 손으로 붙인 정답 영향을 대조해 일치율을 냅니다. 단, 정답과 부여 목록을 모두 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
만료일이 비었거나 역할 표기가 흔들리거나 변경안에 없는 역할이 섞인 입력 30종을 넣어도 출력 형식이 안 깨지고 사유별로 빠지는 비율을 보여줍니다.
자원 패턴과 시행일을 바꿨을 때 옛 판정이 어떻게 뒤집히는지 회귀로 확인합니다.
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 작성자가 만든 부여 목록의 자가채점이며, 실제 영향 정확도는 베이스스톤 고객사의 실 권한 대장과 실 정책이 있어야 측정됩니다. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다.
수치는 합성 데이터 자가채점이라 성능 증명이 아니므로, 면접에서는 데모 동작과 실검증 준비 상태로 솔직히 설명합니다.
정답을 작성자가 붙였으니 잘 맞는 게 당연하므로, 만료일 결측과 표기 흔들림, 변경안에 없는 역할을 일부러 섞어 쉬운 부여만 푸는 함정을 피합니다.
이 포트폴리오가 보여주는 것은 정책을 데이터로 두고 부여 목록과 맞춰 영향 범위를 내는 기술이며, 암호 모듈 구현이나 공공 보안 인증 실무는 주장하지 않습니다. 판정은 패턴 대조와 날짜 비교가 하고 LLM 은 담당자가 읽을 사유 문장만 맡습니다.
권한이 부여만으로 정해지지 않고 상위 그룹에서 상속되는 환경도 있어서, 상속을 다루지 않는다고 리포트 머리에 밝혀 둡니다.
실제 도입 때는 고객사마다 역할 이름과 자원 규칙이 다르므로, 대응 사전을 새로 채우는 일을 도입 단계 과제로 둡니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
지금 부여된 권한 목록입니다. 부여 번호와 계정, 역할 표기, 자원 이름, 동작, 부여일, 만료일, 부여 경로를 한 행에 둡니다. 역할 표기는 등록 경로에 따라 'operator'와 'OPERATOR'처럼 흔들립니다. 만료일이 빈 행, 정책 시행 전에 끝나는 행, 변경안에 없는 역할을 일부러 섞어 두어 사유가 갈리게 둡니다.
| grant_no | account_raw | role_raw | resource_raw | action_raw | granted_at | expires_at | source_raw |
|---|---|---|---|---|---|---|---|
| GR-101 | kim.dh | operator | vault/prod/keys | read | 2026-02-01 | 2026-12-31 | 수동 신청 |
| GR-102 | kim.dh | operator | vault/prod/keys | write | 2026-02-01 | 2026-12-31 | 수동 신청 |
| GR-103 | lee.sm | OPERATOR | audit/prod/logs | read | 2026-03-15 | — | 부서 일괄 |
| GR-104 | park.jw | auditor | audit/prod/logs | read | 2026-01-10 | 2026-08-20 | 수동 신청 |
| GR-105 | park.jw | auditor | audit/prod/logs | export | 2026-01-10 | 2026-12-31 | 수동 신청 |
아래 JSON Schema 를 그대로 만족하는 권한 부여 행을 500개 더 만들어 주세요. 역할을 대여섯 종 두고 자원 이름을 'vault/prod/keys'처럼 슬래시로 나눈 경로로 적습니다. 역할 표기는 몇 행에서 대문자로 두고, 2할은 만료일이나 부여 경로를 비우며, 몇 행은 만료일을 2026년 8월로 두어 시행 전에 끝나게 하세요. 변경안에 없는 역할도 몇 행 넣습니다. 영향 판정은 넣지 마세요.
{"type": "object", "properties": {"grant_no": {"type": "string"}, "account_raw": {"type": "string"}, "role_raw": {"type": "string"}, "resource_raw": {"type": "string"}, "action_raw": {"type": "string"}, "granted_at": {"type": "string"}, "expires_at": {"type": ["string", "null"]}, "source_raw": {"type": ["string", "null"]}}, "required": ["grant_no", "account_raw", "role_raw", "resource_raw", "action_raw", "granted_at", "expires_at"]}{"type": "object", "properties": {"grant_no": {"type": "string"}, "account_raw": {"type": "string"}, "role_raw": {"type": "string"}, "resource_raw": {"type": "string"}, "action_raw": {"type": "string"}, "granted_at": {"type": "string"}, "expires_at": {"type": ["string", "null"]}, "source_raw": {"type": ["string", "null"]}}, "required": ["grant_no", "account_raw", "role_raw", "resource_raw", "action_raw", "granted_at", "expires_at"]}적용하려는 권한 정책 변경안입니다. 규칙 번호와 역할, 자원 패턴, 동작, 허용·차단, 시행일, 담당을 한 행에 둡니다. 같은 역할이라도 동작마다 허용과 차단이 갈려, 읽기는 열어 두고 쓰기만 막는 식으로 결과가 나뉩니다. 부여 목록에 나오는 역할 중 일부는 일부러 넣지 않아 미선언이 도출되게 둡니다.
| rule_no | role_raw | resource_pattern | action_raw | effect_raw | effective_from | owner_name |
|---|---|---|---|---|---|---|
| PC-01 | operator | vault/prod/* | write | deny | 2026-09-01 | 보안운영 |
| PC-02 | operator | vault/prod/* | read | allow | 2026-09-01 | 보안운영 |
| PC-03 | auditor | audit/prod/* | export | deny | 2026-09-01 | 보안운영 |
| PC-04 | auditor | audit/prod/* | read | allow | 2026-09-01 | 보안운영 |
| PC-05 | developer | vault/prod/* | read | deny | 2026-09-01 | 보안운영 |
아래 JSON Schema 를 그대로 만족하는 정책 변경 행을 30개 더 만들어 주세요. 역할마다 동작을 읽기·쓰기·실행·내려받기로 나누고 허용과 차단을 섞습니다. 자원 패턴은 'vault/prod/*'처럼 별표로 끝나게 두고 시행일은 한 날짜로 맞춥니다. 부여 목록에 나오는 역할 중 일부는 일부러 넣지 마세요 — 미선언이 있어야 변경안의 구멍이 드러납니다. 영향 판정은 넣지 마세요.
{"type": "object", "properties": {"rule_no": {"type": "string"}, "role_raw": {"type": "string"}, "resource_pattern": {"type": "string"}, "action_raw": {"type": "string"}, "effect_raw": {"type": "string", "enum": ["allow", "deny"]}, "effective_from": {"type": "string"}, "owner_name": {"type": "string"}}, "required": ["rule_no", "role_raw", "resource_pattern", "action_raw", "effect_raw", "effective_from", "owner_name"]}{"type": "object", "properties": {"rule_no": {"type": "string"}, "role_raw": {"type": "string"}, "resource_pattern": {"type": "string"}, "action_raw": {"type": "string"}, "effect_raw": {"type": "string", "enum": ["allow", "deny"]}, "effective_from": {"type": "string"}, "owner_name": {"type": "string"}}, "required": ["rule_no", "role_raw", "resource_pattern", "action_raw", "effect_raw", "effective_from", "owner_name"]}| Python | 부여 목록과 변경안을 맞춰 자원 패턴을 견주고 결과를 가르는 판정기를 맡습니다. |
| PostgreSQL | 부여 목록과 변경안, 판정 결과를 담습니다. |
| Markdown | 역할별 영향 리포트와 안내 초안을 파일로 냅니다. |
✗ fail → 미선언이 절반을 넘으면 변경안을 먼저 채웁니다.
✓ pass → 2주차 정답 대조로 넘어갑니다.
✗ fail → 어긋난 역할을 모아 자원 패턴을 다시 봅니다.
✓ pass → 3주차 안내 초안으로 넘어갑니다.
부여 하나와 변경 규칙이 만나는 자리마다 시행 뒤 결과가 달라지는지 정합니다. 판정하지 못하면 만료·대상 아님·역할 미선언 중 어느 쪽인지 싣습니다. 리포트는 이 영향 코드로 묶습니다.
{"type": "object", "properties": {"impact_no": {"type": "string"}, "grant_no": {"type": "string"}, "account_raw": {"type": "string"}, "role_raw": {"type": "string"}, "rule_no": {"type": ["string", "null"]}, "impact_code": {"type": "string", "enum": ["unaffected", "newly_blocked", "action_unmatched", "grant_expired", "resource_unmatched", "role_undeclared"]}, "effect_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": ["impact_no", "grant_no", "account_raw", "role_raw", "impact_code", "evidence", "summary"]}[
{
"impact_no": "IM-001",
"grant_no": "GR-101",
"account_raw": "kim.dh",
"role_raw": "operator",
"rule_no": "PC-02",
"impact_code": "unaffected",
"effect_raw": "allow",
"owner_name": "보안운영",
"evidence": [
{
"field": "action_raw",
"agg": null,
"value": "read"
},
{
"field": "effect_raw",
"agg": null,
"value": "allow"
}
],
"summary": "읽기는 바뀐 정책에서도 허용이라 이 계정은 그대로 씁니다.",
"hedge": null
},
{
"impact_no": "IM-002",
"grant_no": "GR-102",
"account_raw": "kim.dh",
"role_raw": "operator",
"rule_no": "PC-01",
"impact_code": "newly_blocked",
"effect_raw": "deny",
"owner_name": "보안운영",
"evidence": [
{
"field": "action_raw",
"agg": null,
"value": "write"
},
{
"field": "effect_raw",
"agg": null,
"value": "deny"
}
],
"summary": "9월 1일부터 이 계정은 운영 키 쓰기를 못 하게 됩니다.",
"hedge": null
},
{
"impact_no": "IM-003",
"grant_no": "GR-103",
"account_raw": "lee.sm",
"role_raw": "OPERATOR",
"rule_no": "PC-02",
"impact_code": "resource_unmatched",
"effect_raw": null,
"owner_name": null,
"evidence": [
{
"field": "resource_raw",
"agg": null,
"value": "audit/prod/logs"
},
{
"field": "resource_pattern",
"agg": null,
"value": "vault/prod/*"
}
],
"summary": "역할 표기를 접으면 규칙을 찾지만 그 규칙이 다른 자원을 가리켜 이 부여에는 걸리지 않습니다.",
"hedge": "만료일이 비어 있어 언제까지 유지되는지도 함께 확인합니다."
},
{
"impact_no": "IM-004",
"grant_no": "GR-104",
"account_raw": "park.jw",
"role_raw": "auditor",
"rule_no": "PC-04",
"impact_code": "grant_expired",
"effect_raw": "allow",
"owner_name": "보안운영",
"evidence": [
{
"field": "expires_at",
"agg": null,
"value": "2026-08-20"
},
{
"field": "effective_from",
"agg": null,
"value": "2026-09-01"
}
],
"summary": "정책 시행 전에 부여가 끝나 이번 변경의 영향을 받지 않습니다.",
"hedge": null
},
{
"impact_no": "IM-005",
"grant_no": "GR-105",
"account_raw": "park.jw",
"role_raw": "auditor",
"rule_no": "PC-03",
"impact_code": "newly_blocked",
"effect_raw": "deny",
"owner_name": "보안운영",
"evidence": [
{
"field": "action_raw",
"agg": null,
"value": "export"
},
{
"field": "effect_raw",
"agg": null,
"value": "deny"
}
],
"summary": "감사 로그 내려받기가 막혀 정기 보고 절차를 먼저 손봐야 합니다.",
"hedge": null
},
{
"impact_no": "IM-006",
"grant_no": "GR-107",
"account_raw": "choi.yh",
"role_raw": "developer",
"rule_no": "PC-05",
"impact_code": "newly_blocked",
"effect_raw": "deny",
"owner_name": "보안운영",
"evidence": [
{
"field": "resource_raw",
"agg": null,
"value": "vault/prod/keys"
},
{
"field": "resource_pattern",
"agg": null,
"value": "vault/prod/*"
}
],
"summary": "개발 역할의 운영 키 읽기가 막혀 배포 절차를 대체 경로로 옮겨야 합니다.",
"hedge": null
},
{
"impact_no": "IM-007",
"grant_no": "GR-109",
"account_raw": "jung.mk",
"role_raw": "support",
"rule_no": null,
"impact_code": "action_unmatched",
"effect_raw": null,
"owner_name": null,
"evidence": [
{
"field": "action_raw",
"agg": null,
"value": "export"
},
{
"field": "rule_no",
"agg": "count",
"value": 12
}
],
"summary": "지원 역할에 내려받기 규칙이 없어 시행 뒤 어떻게 될지 정해 두지 않았습니다.",
"hedge": null
},
{
"impact_no": "IM-008",
"grant_no": "GR-110",
"account_raw": "han.sw",
"role_raw": "vendor",
"rule_no": null,
"impact_code": "role_undeclared",
"effect_raw": null,
"owner_name": null,
"evidence": [
{
"field": "role_raw",
"agg": null,
"value": "vendor"
},
{
"field": "rule_no",
"agg": "count",
"value": 12
}
],
"summary": "협력사 역할이 변경안 열두 행에 없어 어떻게 될지 정해 두지 않았습니다.",
"hedge": null
}
][자동 검증 · 코드가 판정합니다] 1. impact_code 가 enum 여섯 값 중 하나인지 확인합니다. 2. impact_no·grant_no·account_raw·role_raw·impact_code·evidence·summary 가 모두 채워졌는지 확인합니다. 3. grant_no 가 부여 목록에 실재하는 번호인지 대조합니다. 4. rule_no 가 있으면 변경안에 실재하는 행 번호인지 대조합니다. 5. rule_no 가 있으면 effect_raw·owner_name 이 그 규칙 행의 값과 같은지 대조합니다. 6. role_raw 를 대소문자를 접어 변경안과 맞추고, 맞는 행이 없으면 impact_code 가 role_undeclared 인지 확인합니다. 7. resource_raw 가 그 규칙의 resource_pattern 에 드는지 별표 대조로 다시 확인하고, 안 들면 impact_code 가 resource_unmatched 인지 확인합니다. 8. expires_at 이 effective_from 보다 앞서면 impact_code 가 grant_expired 인지 다시 계산합니다. 9. impact_code 가 newly_blocked 이면 그 규칙의 effect_raw 가 deny 이고 동작이 부여의 action_raw 와 같은지 다시 확인합니다. 10. 그 역할 규칙 중 부여의 action_raw 와 같은 동작이 없으면 impact_code 가 action_unmatched 인지 확인합니다. 11. impact_code 가 unaffected 이면 지금 결과와 바뀔 결과가 같은지 다시 확인합니다. 12. evidence 의 field 이름이 부여 목록과 변경안에 실재하는 컬럼인지 대조합니다. 13. agg 가 없는 evidence 의 value 가 그 컬럼에 수록된 행 값과 같은지 확인합니다. 14. summary 가 존댓말로 끝나는지 확인합니다. [평가 러너 · 2주차] 공개 규격으로 만든 부여 500건에 손으로 붙인 정답 영향과 대조해 일치율과 영향 코드별 분포를 내고, 미선언이 몰리는 역할을 모아 결정이 빠진 자리를 목록으로 냅니다. [수동 검증 · 사람이 봅니다] 1. 변경안에 없는 역할을 어떻게 할지 보안 담당이 정합니다. 2. 새로 막히는 부여에 예외를 둘지 담당 조직이 정합니다.