멘타트
경력근거: 조직의 권한(ACL) 체계 매핑, 대규모 문서 수집·동기화 파이프라인 구축
※ 실제 산출물이 아닌 AI 예측 시안입니다.
공고가 NEXUS 플랫폼을 '흩어진 사내 문서를 권한 체계 그대로 검색하는 기업 검색 엔진' 으로 소개하고, FDE 업무에 '조직의 권한(ACL) 체계 매핑, 대규모 문서 수집·동기화 파이프라인 구축' 을 적었습니다. 권한이 안 맞으면 검색이 성립하지 않으므로 문서를 넣기 전에 매핑이 서야 하고, 이 포트폴리오는 그 매핑을 규칙표와 판정으로 만듭니다. 'NEXUS 플랫폼을 로펌·금융기관 등 고객사 온프레미스/망분리 환경에 구축·배포' 한다는 대목도 문서 본문을 밖으로 보내지 않고 그룹 이름과 사유 코드만 다루는 설계로 받았습니다. 이 포트폴리오가 보여주는 것은 권한 규칙을 데이터로 두고 문서 목록과 맞춰 역할을 가르는 기술이며, 망분리·ISMS 구축 실무나 법률·금융 도메인 전문성은 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
'흩어진 사내 문서를 권한 체계 그대로 검색하는 기업 검색 엔진'. 권한이 안 맞으면 검색이 성립하지 않습니다.
'조직의 권한(ACL) 체계 매핑, 대규모 문서 수집·동기화 파이프라인 구축'. 매핑이 이 편의 주제입니다.
'NEXUS 플랫폼을 로펌·금융기관 등 고객사 온프레미스/망분리 환경에 구축·배포'. 현장에서 받는 자료가 내려받은 권한 목록입니다.
고객사 문서 권한이 플랫폼 역할로 옮겨지는지 가릅니다. 그룹 매핑표에 플랫폼 역할과 상속 허용 여부, 기밀등급 상한을 두고 문서관리시스템에서 내려받은 권한 목록과 맞춰, 규칙이 하나로 정해지면 역할을 정하고 그렇지 않으면 규칙 충돌·상속 끊김·등급 초과 중 어느 쪽인지 사유로 남깁니다. 매핑표에 없는 그룹은 미등록으로 남겨 규칙을 먼저 정하게 하고, 소유자와 갱신일이 모두 빈 문서는 확인할 사람을 못 정한다고 표시합니다. 권한 목록은 실 고객사 자료 대신 지원자가 SharePoint·그룹웨어 내보내기 양식으로 만든 것을 가정합니다.
로펌·금융기관 망분리 환경에 검색 플랫폼을 놓는 자리에 앉는 FDE 입니다. 문서를 넣기 전에 어느 그룹이 무엇을 볼 수 있는지를 매번 고객사 권한 목록과 플랫폼 역할표를 번갈아 보며 맞추던 사람입니다.
그룹마다 어떤 플랫폼 역할을 주고 상속을 허용할지, 어느 기밀등급까지 열지를 표로 두고 권한 목록과 맞추면, 옮겨지는 문서와 막히는 문서가 규칙으로 갈리고 막힌 이유가 근거로 남는다는 가정입니다. 같은 그룹에 규칙이 둘 이상이면 충돌로 빠지므로 조직 안에서 권한 해석이 갈리는 지점이 그대로 드러납니다.
권한 목록과 그룹 매핑표를 받아 문서마다 역할 매핑·막힘을 판정하고, 막혔으면 규칙 충돌·상속 끊김·등급 초과·미등록 중 어느 쪽인지 붙여 담당 조직별로 묶은 판정 리포트를 터미널과 Markdown 파일로 내는 CLI 가 도는 완결품입니다.
내보내기 양식으로 만든 권한 목록 500건에 손으로 붙인 정답 역할과 대조해 일치율을 내고, 미등록이 몰리는 그룹을 모아 규칙이 없는 자리를 목록으로 냅니다.
역할이 정해진 문서만 모아 색인 대상 목록으로 조립하고, 막힌 문서는 고객사 정보보호팀에 보낼 확인 목록으로 갈라 내는 단계입니다.
FDE 가 권한 목록과 그룹 매핑표를 넣으면 문서마다 역할과 막힌 사유가 담당 조직별로 묶여 나오는 과정을 시연합니다.
내보내기 양식으로 만든 권한 목록 500건과 손으로 붙인 정답 역할을 대조해 일치율을 냅니다. 단, 정답과 목록을 모두 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
소유자가 비었거나 시스템 표기가 흔들리거나 매핑표에 없는 그룹이 섞인 입력 30종을 넣어도 출력 형식이 안 깨지고 사유별로 빠지는 비율을 보여줍니다.
매핑표를 고쳤을 때 옛 판정이 어떻게 뒤집히는지 회귀로 확인합니다.
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 작성자가 만든 목록의 자가채점이며, 실제 권한 정합은 멘타트 고객사의 실 문서관리시스템과 실 보안 정책이 있어야 측정됩니다. 이 포트폴리오는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다.
수치는 합성 데이터 자가채점이라 성능 증명이 아니므로, 면접에서는 데모 동작과 실검증 준비 상태로 솔직히 설명합니다.
정답을 작성자가 붙였으니 잘 맞는 게 당연하므로, 규칙 충돌과 끊긴 상속, 매핑표에 없는 그룹을 일부러 섞어 쉬운 문서만 푸는 함정을 피합니다.
이 포트폴리오가 보여주는 것은 권한 규칙을 데이터로 두고 문서 목록과 맞춰 역할을 가르는 기술이며, 망분리·ISMS 구축 실무나 법률·금융 도메인 전문성은 주장하지 않습니다. 판정은 규칙 조회와 상속 추적이 하고 LLM 은 담당자가 읽을 사유 문장만 맡습니다.
역할이 정해졌다고 그 문서를 열어도 된다는 뜻은 아니어서, 판정에 걸린 규칙 행을 함께 실어 정보보호팀이 한 번 더 보게 둡니다.
실제 도입 때는 고객사마다 그룹 체계와 기밀등급이 다르므로, 매핑표를 새로 채우는 일을 도입 단계 과제로 둡니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
문서관리시스템·그룹웨어·메일에서 내려받은 문서 권한 목록입니다. 문서 번호와 원천 시스템 표기, 폴더 경로, 그룹, 권한 표기, 기밀등급, 갱신일, 소유자를 한 행에 둡니다. 시스템 표기는 내보내기마다 손으로 적어 'sharepoint'와 'Share Point'처럼 흔들립니다. 상위 폴더가 목록에 없는 상속 행, 소유자와 갱신일이 모두 빈 행, 매핑표에 없는 그룹을 일부러 섞어 두어 사유가 갈리게 둡니다.
| doc_no | source_system_raw | folder_path | group_raw | permission_raw | grade_raw | updated_at | owner_name |
|---|---|---|---|---|---|---|---|
| DC-1001 | sharepoint | /legal/계약 | 법무팀 | read | internal | 2026-08-18 | 김서준 |
| DC-1002 | sharepoint | /legal/계약/기밀 | 법무팀 | read | confidential | 2026-08-18 | 김서준 |
| DC-1003 | Share Point | /finance/결산 | 재무팀 | write | internal | 2026-08-19 | 이하윤 |
| DC-1004 | groupware | /hr/평가 | 인사팀 | read | confidential | 2026-08-19 | 박도현 |
| DC-1005 | groupware | /hr/평가 | 인사팀 | deny | confidential | 2026-08-20 | 박도현 |
아래 JSON Schema 를 그대로 만족하는 문서 권한 행을 500개 더 만들어 주세요. 그룹을 열 종쯤 섞고 시스템 표기는 몇 행에서 'Share Point'처럼 띄어 적어 흔들리게 둡니다. 2할은 소유자나 갱신일을 비우고, 몇 행은 상위 폴더가 목록에 없는 상속으로 두며, 몇 행은 매핑표에 없는 그룹을 씁니다. 역할이나 판정 결과는 넣지 마세요.
{"type": "object", "properties": {"doc_no": {"type": "string"}, "source_system_raw": {"type": "string"}, "folder_path": {"type": "string"}, "group_raw": {"type": "string"}, "permission_raw": {"type": "string"}, "grade_raw": {"type": ["string", "null"]}, "updated_at": {"type": ["string", "null"]}, "owner_name": {"type": ["string", "null"]}}, "required": ["doc_no", "source_system_raw", "folder_path", "group_raw", "permission_raw"]}{"type": "object", "properties": {"doc_no": {"type": "string"}, "source_system_raw": {"type": "string"}, "folder_path": {"type": "string"}, "group_raw": {"type": "string"}, "permission_raw": {"type": "string"}, "grade_raw": {"type": ["string", "null"]}, "updated_at": {"type": ["string", "null"]}, "owner_name": {"type": ["string", "null"]}}, "required": ["doc_no", "source_system_raw", "folder_path", "group_raw", "permission_raw"]}그룹 매핑표입니다. 그룹과 플랫폼 역할, 상속 허용 여부, 기밀등급 상한, 규칙을 쓴 담당 조직을 한 행에 둡니다. 같은 그룹에 조직이 서로 다른 규칙을 걸어 두어 충돌이 도출됩니다. 권한 목록에 나오는 그룹 중 일부는 일부러 넣지 않아 미등록이 도출되게 둡니다.
| rule_no | group_raw | platform_role | inherit_parent | max_grade | owner_name |
|---|---|---|---|---|---|
| AP-1001 | 법무팀 | editor | true | confidential | 정보보호팀 |
| AP-1002 | 재무팀 | editor | true | internal | 정보보호팀 |
| AP-1003 | 인사팀 | reader | false | confidential | 정보보호팀 |
| AP-1004 | 인사팀 | denied | false | confidential | 인사팀 |
| AP-1005 | 전사 | reader | true | public | 정보보호팀 |
아래 JSON Schema 를 그대로 만족하는 그룹 매핑 행을 40개 더 만들어 주세요. 몇몇 그룹에는 담당 조직이 다른 규칙을 둘씩 걸어 충돌이 생기게 하고, 상속 허용과 기밀등급 상한을 그룹 성격에 맞게 다르게 씁니다. 권한 목록에 나오는 그룹 중 일부는 일부러 넣지 마세요 — 미등록이 있어야 매핑표의 구멍이 드러납니다. 판정 결과는 넣지 마세요.
{"type": "object", "properties": {"rule_no": {"type": "string"}, "group_raw": {"type": "string"}, "platform_role": {"type": "string", "enum": ["reader", "editor", "owner", "denied"]}, "inherit_parent": {"type": "boolean"}, "max_grade": {"type": "string", "enum": ["public", "internal", "confidential"]}, "owner_name": {"type": "string"}}, "required": ["rule_no", "group_raw", "platform_role", "inherit_parent", "max_grade", "owner_name"]}{"type": "object", "properties": {"rule_no": {"type": "string"}, "group_raw": {"type": "string"}, "platform_role": {"type": "string", "enum": ["reader", "editor", "owner", "denied"]}, "inherit_parent": {"type": "boolean"}, "max_grade": {"type": "string", "enum": ["public", "internal", "confidential"]}, "owner_name": {"type": "string"}}, "required": ["rule_no", "group_raw", "platform_role", "inherit_parent", "max_grade", "owner_name"]}| Python | 권한 목록과 매핑표를 맞춰 역할을 정하고 상속을 따라가는 판정기를 맡습니다. |
| Docker | 망분리 현장에서 같은 이미지로 돌리도록 CLI 를 컨테이너로 싸 둡니다. |
| Markdown | 담당 조직별로 묶은 판정 리포트와 확인 목록을 파일로 냅니다. |
✗ fail → 미등록이 절반을 넘으면 매핑표를 먼저 채웁니다.
✓ pass → 2주차 정답 대조로 넘어갑니다.
✗ fail → 어긋난 유형을 모아 상속과 등급 규칙을 다시 봅니다.
✓ pass → 3주차 색인 대상 목록으로 넘어갑니다.
문서 한 건과 그룹 규칙이 만나는 자리마다 플랫폼 역할로 옮겨지는지 정합니다. 막히면 규칙 충돌·상속 끊김·등급 초과·미등록·소유자 없음 중 어느 쪽인지 싣습니다. 화면과 리포트는 이 사유 코드로 묶습니다.
{"type": "object", "properties": {"verdict_no": {"type": "string"}, "doc_no": {"type": "string"}, "group_raw": {"type": "string"}, "rule_no": {"type": ["string", "null"]}, "platform_role": {"type": ["string", "null"]}, "acl_code": {"type": "string", "enum": ["mapped", "group_unmapped", "permission_conflict", "inherit_broken", "grade_over", "owner_missing"]}, "conflict_count": {"type": ["integer", "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", "doc_no", "group_raw", "acl_code", "evidence", "summary"]}[
{
"verdict_no": "AV-001",
"doc_no": "DC-1001",
"group_raw": "법무팀",
"rule_no": "AP-1001",
"platform_role": "editor",
"acl_code": "mapped",
"conflict_count": 1,
"owner_name": "정보보호팀",
"evidence": [
{
"field": "permission_raw",
"agg": null,
"value": "read"
},
{
"field": "max_grade",
"agg": null,
"value": "confidential"
}
],
"summary": "법무팀 규칙이 하나뿐이고 기밀등급도 상한 안이라 editor 로 옮깁니다.",
"hedge": null
},
{
"verdict_no": "AV-002",
"doc_no": "DC-1007",
"group_raw": "전사",
"rule_no": "AP-1005",
"platform_role": "reader",
"acl_code": "mapped",
"conflict_count": 1,
"owner_name": "정보보호팀",
"evidence": [
{
"field": "grade_raw",
"agg": null,
"value": "public"
},
{
"field": "max_grade",
"agg": null,
"value": "public"
}
],
"summary": "공개 등급 공지라 전사 reader 규칙 그대로 옮깁니다.",
"hedge": null
},
{
"verdict_no": "AV-003",
"doc_no": "DC-1004",
"group_raw": "인사팀",
"rule_no": null,
"platform_role": null,
"acl_code": "permission_conflict",
"conflict_count": 2,
"owner_name": null,
"evidence": [
{
"field": "group_raw",
"agg": null,
"value": "인사팀"
},
{
"field": "rule_no",
"agg": "count",
"value": 2
}
],
"summary": "인사팀에 reader 와 denied 두 규칙이 걸려 어느 쪽을 쓸지 규칙만으로 못 정합니다.",
"hedge": "규칙을 쓴 조직이 달라 정보보호팀과 인사팀이 합의해야 합니다."
},
{
"verdict_no": "AV-004",
"doc_no": "DC-1003",
"group_raw": "재무팀",
"rule_no": "AP-1002",
"platform_role": "editor",
"acl_code": "mapped",
"conflict_count": 1,
"owner_name": "정보보호팀",
"evidence": [
{
"field": "source_system_raw",
"agg": null,
"value": "Share Point"
},
{
"field": "max_grade",
"agg": null,
"value": "internal"
}
],
"summary": "시스템 표기가 'Share Point'로 달리 적혀 있으나 접으면 같은 원천이고 등급도 상한 안이라 editor 로 옮깁니다.",
"hedge": null
},
{
"verdict_no": "AV-005",
"doc_no": "DC-1009",
"group_raw": "법무팀",
"rule_no": "AP-1001",
"platform_role": "editor",
"acl_code": "inherit_broken",
"conflict_count": 1,
"owner_name": "정보보호팀",
"evidence": [
{
"field": "permission_raw",
"agg": null,
"value": "inherit"
},
{
"field": "folder_path",
"agg": null,
"value": "/orphan/임시"
}
],
"summary": "상속으로 적혀 있는데 상위 폴더가 목록에 없어 어떤 권한을 물려받는지 못 정합니다.",
"hedge": null
},
{
"verdict_no": "AV-006",
"doc_no": "DC-1006",
"group_raw": "외부자문",
"rule_no": null,
"platform_role": null,
"acl_code": "group_unmapped",
"conflict_count": 0,
"owner_name": null,
"evidence": [
{
"field": "group_raw",
"agg": null,
"value": "외부자문"
},
{
"field": "rule_no",
"agg": "count",
"value": 12
}
],
"summary": "매핑표 열두 행에 외부자문이 없어 미등록으로 남기고 규칙을 먼저 정합니다.",
"hedge": null
},
{
"verdict_no": "AV-007",
"doc_no": "DC-1011",
"group_raw": "영업팀",
"rule_no": "AP-1007",
"platform_role": "reader",
"acl_code": "owner_missing",
"conflict_count": 1,
"owner_name": "정보보호팀",
"evidence": [
{
"field": "owner_name",
"agg": null,
"value": null
},
{
"field": "updated_at",
"agg": null,
"value": null
}
],
"summary": "소유자와 갱신일이 모두 비어 있어 누구에게 확인할지 정하지 못합니다.",
"hedge": null
},
{
"verdict_no": "AV-008",
"doc_no": "DC-1012",
"group_raw": "재무팀",
"rule_no": "AP-1002",
"platform_role": "editor",
"acl_code": "grade_over",
"conflict_count": 1,
"owner_name": "정보보호팀",
"evidence": [
{
"field": "grade_raw",
"agg": null,
"value": "confidential"
},
{
"field": "max_grade",
"agg": null,
"value": "internal"
}
],
"summary": "세무 폴더가 기밀 등급인데 재무팀 상한은 사내라 그대로 옮기면 상한을 넘습니다.",
"hedge": null
}
][자동 검증 · 코드가 판정합니다] 1. acl_code 가 enum 여섯 값 중 하나인지 확인합니다. 2. verdict_no·doc_no·group_raw·acl_code·evidence·summary 가 모두 채워졌는지 확인합니다. 3. doc_no 가 권한 목록에 실재하는 번호인지 대조합니다. 4. rule_no 가 있으면 매핑표에 실재하는 행 번호인지 대조합니다. 5. rule_no 가 있으면 platform_role·owner_name 이 그 규칙 행의 값과 같은지 대조합니다. 6. conflict_count 를 그 그룹의 규칙 행 수로 다시 셉니다. 7. acl_code 가 permission_conflict 이면 conflict_count 가 2 이상인지 확인합니다. 8. acl_code 가 mapped 이면 conflict_count 가 1인지 확인합니다. 9. source_system_raw 를 공백을 지우고 대소문자를 접은 뒤 같은 원천으로 묶이는지 확인합니다. 10. permission_raw 가 inherit 이면 folder_path 의 상위 경로가 목록에 실재하는지 대조하고, 없으면 acl_code 가 inherit_broken 인지 확인합니다. 11. acl_code 가 grade_over 이면 grade_raw 가 max_grade 를 넘는지 등급 순서대로 다시 견줍니다. 12. owner_name 과 updated_at 이 모두 비어 있으면 acl_code 가 owner_missing 인지 확인합니다. 13. group_raw 가 매핑표에 없으면 acl_code 가 group_unmapped 인지 확인합니다. 14. evidence 의 field 이름이 권한 목록과 매핑표에 실재하는 컬럼인지 대조합니다. 15. agg 가 없는 evidence 의 value 가 그 컬럼에 수록된 행 값과 같은지 확인합니다. 16. summary 에 문서 본문이 실리지 않았는지 확인합니다. 17. summary 가 존댓말로 끝나는지 확인합니다. [평가 러너 · 2주차] 내보내기 양식으로 만든 권한 목록 500건에 손으로 붙인 정답 역할과 대조해 일치율과 사유 코드별 분포를 내고, 미등록이 몰리는 그룹을 모아 규칙이 없는 자리를 목록으로 냅니다. [수동 검증 · 사람이 봅니다] 1. 규칙이 갈린 그룹을 어느 쪽으로 정할지 정보보호팀과 현업 조직이 합의합니다. 2. 등급 상한을 넘은 문서를 색인에서 뺄지 담당자가 정합니다.
근거: 조직의 권한(ACL) 체계 매핑, 대규모 문서 수집·동기화 파이프라인 구축