역할 기반 접근 제어(RBAC)는 권한을 역할에 연결하고, 사용자는 오직 자신의 역할을 통해서만 권한을 얻는 인가 모델입니다. 핵심은 이 간접 참조에 있습니다. 사람에게 직접 부여되는 것이 아무것도 없으므로 조직의 변화가 곧 데이터의 변화가 됩니다. 승진은 흩어진 권한 부여를 파헤치는 고고학 작업이 아니라 역할 재할당입니다. 1992년 Ferraiolo와 Kuhn이 기존의 임의적 접근 제어와 강제적 접근 제어 모델의 대안으로 제안한 RBAC은 ANSI/INCITS 359 표준이 되었고, 엔터프라이즈 소프트웨어의 기본 인가 어휘로 자리 잡았습니다.
핵심 요약
| 질문 | 답변 |
|---|---|
| 간접 참조 | 사용자 → 역할 → 권한 · 사용자 → 권한 직접 연결은 금지 |
| 역할 ≠ 그룹 | 그룹은 사용자의 모음, 역할은 권한의 모음 |
| 모델 단계 | 핵심 · 계층형(상속) · 제약형(직무 분리) |
| 실패 모드 | 역할 폭발 – 속성을 역할로 인코딩하다가 역할 수가 사용자 수를 넘어서는 상황 |
| 조합 | ACL 항목 안의 역할: 다수에는 RBAC, 예외에는 ACL |
사용자, 역할, 권한: 간접 참조의 실제 동작
권한 역할 사용자
───────────── ───────────── ─────────────
posts:read ─┐
posts:write ├──▶ Editor ◀────── Ada, Grace
posts:publish ─┘
users:manage ─┐
billing:view ├──▶ Admin ◀────── Linus
posts:* ─┘
posts:read ────▶ Viewer ◀────── 그 외 모든 사용자
Ada가 게시할 수 있는 이유는 Editor가 posts:publish를 갖기 때문입니다.
역할을 바꾸면 그 역할이 가진 모든 권한이 함께 옮겨 갑니다.
수정은 N번이 아니라 한 번입니다.
객체 권한에 연결된, 살아 있는 데이터로서의 역할입니다.
// JavaScript / Node.js — Back4app JS SDK
// Roles as data: create a role, add members, grant through it
const roleACL = new Parse.ACL();
roleACL.setPublicReadAccess(true);
const editors = new Parse.Role('Editors', roleACL);
editors.getUsers().add(adaUser);
await editors.save();
// Grant by role, not by user — membership changes in one place
const post = new Parse.Object('Post');
const acl = new Parse.ACL(currentUser); // owner entry
acl.setRoleWriteAccess('Editors', true); // RBAC meets the object's ACL
post.setACL(acl);
await post.save(); // Flutter / Dart — Back4app Flutter SDK
// Roles as data: create a role, add members, grant through it
final roleACL = ParseACL()..setPublicReadAccess(allowed: true);
final editors = ParseObject('_Role')
..set('name', 'Editors')
..setACL(roleACL)
..addRelation('users', [adaUser]);
await editors.save();
// Grant by role, not by user — membership changes in one place
final post = ParseObject('Post');
final acl = ParseACL(owner: currentUser) // owner entry
..setRoleWriteAccess('Editors', true); // RBAC meets the object's ACL
post.setACL(acl);
await post.save(); // iOS / Swift — Back4app Swift SDK
// Roles as data: create a role, add members, grant through it
var editors = try ParseRole(name: "Editors")
let savedRole = try await editors.save()
try await savedRole.users.add([adaUser]).save() // membership = a relation
// Grant by role, not by user — membership changes in one place
var post = Post()
var acl = ParseACL()
acl.setReadAccess(user: currentUser, value: true)
acl.setWriteAccess(user: currentUser, value: true) // owner entry
acl.setWriteAccess(roleName: "Editors", value: true) // RBAC meets the ACL
post.ACL = acl
try await post.save() // Android / Kotlin — Back4app Android SDK
// Roles as data: create a role, add members, grant through it
val roleACL = ParseACL()
roleACL.publicReadAccess = true
val editors = ParseRole("Editors", roleACL)
editors.users.add(adaUser)
editors.save()
// Grant by role, not by user — membership changes in one place
val post = ParseObject("Post")
val acl = ParseACL(ParseUser.getCurrentUser()) // owner entry
acl.setRoleWriteAccess("Editors", true) // RBAC meets the object's ACL
post.acl = acl
post.save() NIST 모델, 정확하게
대부분의 해설은 표준을 목록 몇 줄로 압축해 버리지만, 실제 구조는 30초를 들일 가치가 있습니다. 핵심 RBAC은 사용자, 역할, 권한, 그리고 흔히 잊히는 요소인 세션을 정의합니다. 사용자는 세션마다 자신의 역할 중 일부만 활성화합니다. 관리자가 평소에는 일반 회원 권한으로 탐색하다가 필요할 때 의도적으로 권한을 높일 수 있는 것도 이 덕분입니다. 원 논문의 세 가지 규칙이 이를 하나로 묶습니다. 역할을 통해서만 행동하고, 인가된 역할만 보유하며, 활성 역할이 허용하는 일만 합니다. 계층형 RBAC은 상속을 더합니다. 상위 역할이 하위 역할을 포함하므로(Manager ⊇ Employee) 중복이 사라집니다. 제약 RBAC은 직무 분리를 더합니다. 정적 규칙은 상충하는 역할 할당 자체를 금지하고(결제 생성자와 결제 승인자 역할은 절대 함께 부여되지 않습니다), 동적 규칙은 할당은 허용하되 한 세션에서 둘을 함께 활성화하는 것을 금지합니다. 그리고 흔히 왜곡되는 NIST의 가장 명확한 설명이 있습니다. 그룹은 사용자의 모음이고, 역할은 권한의 모음입니다. 역할은 누가 속해 있는지가 아니라 무엇을 할 수 있는지로 정의됩니다.
RBAC vs. ACL vs. ABAC
| RBAC | ACL | ABAC | |
|---|---|---|---|
| 권한이 연결되는 곳 | 역할 | 각 객체 | 속성 규칙 |
| 본래의 질문 | 이 직무는 무엇을 할 수 있는가? | 누가 이 객체를 만질 수 있는가? | 이것이 이 맥락에서 허용되는가? |
| 관리 | 역할마다 한곳 | 객체별 | 정책별 |
| 객체별 공유 | 표현 불가 | 본래의 영역 | 표현 가능하지만 장황 |
| ”Ada는 무엇을 할 수 있는가?” 감사 | Ada의 역할 확인 | 모든 객체 스캔 | 모든 규칙 평가 |
| 실패 모드 | 역할 폭발 | 목록 난립 | 불투명한 정책 |
벤더들의 검색 결과가 묻어 두는 통찰은 이것입니다. 셋은 경쟁하는 것이 아니라 조합됩니다. 역할은 직무를 따르는 접근을 처리하고, ACL 항목은 객체별 예외를 처리합니다. 둘을 잇는 연결 고리는 역할 항목 ACE입니다. 사용자 대신 역할을 지정하는 ACL 항목으로, 객체 수준의 제어와 한곳에서의 구성원 관리를 함께 제공합니다. 맥락(시간, 테넌트, 레코드 상태)이 실제로 결정을 좌우하는 곳에서는 그 위에 속성 조건이 얹힙니다. “어느 쪽인가?”는 대개 잘못된 질문입니다. “어느 계층이 어떤 결정을 처리하는가?”가 곧 설계입니다.
역할 폭발이라는 실패 모드
역할 폭발은 RBAC 특유의 질병입니다. 예외마다 역할이 하나씩 생기고, 이어서 프로젝트, 리전, 테넌트마다 역할이 곱절로 늘어납니다. Project-A-Manager-Region-West-ReadOnly 같은 역할이 쌓이다 보면 역할 수가 사용자 수를 넘어서고, “누가 무엇을 할 수 있는가?”라는 감사 질문의 답은 “아무도 모릅니다”가 됩니다. 근본 원인은 언제나 같습니다. 맥락 속성을 역할로 인코딩하는 것입니다. 완화책을 순서대로 정리하면 다음과 같습니다. 속성을 역할 이름에서 빼냅니다(리전과 테넌트는 역할이 아니라 조건이나 범위입니다). 객체별 공유는 객체별 역할이 아니라 ACL 항목으로 처리합니다. 역할의 범위는 이름을 비트는 방식이 아니라 구조적으로 테넌트별로 지정합니다. 그리고 감사합니다. 아무도 보유하지 않은 역할, 어떤 역할도 쓰지 않는 권한, 아무도 기억하지 못하는 권한 부여는 드리프트이며, 최소 권한 원칙은 드리프트를 통해 소리 없이 무너집니다. 실용적인 경험칙이 하나 있습니다. 역할 목록이 한 화면에 들어가지 않기 시작하면, 모델이 다른 계층에 속하는 일을 떠맡고 있는 것입니다.
역할 설계: 하향식, 상향식, 또는 둘 다
순위권의 해설들이 다루지 않는 부분은 역할이 어디서 오는가입니다. 하향식은 조직과 프로세스에서 역할을 도출합니다. 현업 담당자를 인터뷰하고, 직무에 이름을 붙이고, 최소한의 권한을 할당합니다. 정확하지만 느립니다. 상향식은 기존 권한 부여에서 역할을 채굴합니다. 누가 이미 무엇을 보유하고 있는지 클러스터링하면 후보 역할이 드러납니다. 빠르지만 과거의 실수를 정책으로 세탁합니다. 실무는 혼합형입니다. 후보를 채굴하고, 직무와 대조해 검증한 다음, 80/20 테스트를 적용합니다. 조직의 대부분은 소수의 넓은 역할로 처리하고, 예외는 맞춤형 역할이 아니라 ACL이나 조건으로 처리합니다. 그리고 어떤 조직 개편보다 오래 살아남는 구현 규칙이 하나 있습니다. 코드는 역할 이름이 아니라 권한을 검사해야 합니다. hasRole('Editor')가 아니라 can('posts:publish')를 검사해야 역할 재정의가 리팩터링이 아니라 데이터 변경이 됩니다. 강제는 서버 측에서, 기본 거부 원칙으로 이루어져야 합니다.
일반적인 사용 사례
- 관리자 패널과 백오피스 – 지원, 모더레이터, 재무, 최고 관리자처럼 직무가 역할에 깔끔하게 대응합니다.
- 콘텐츠 및 퍼블리싱 워크플로 – 작성자, 편집자, 발행자로 나누고, 작성과 발행을 분리합니다.
- B2B SaaS 팀 권한 – 워크스페이스별 owner/admin/member/billing 역할을 테넌트 단위로 범위 지정합니다.
- 컴플라이언스가 요구되는 운영 – 직무 분리를 강제 가능한 역할 제약으로 구현하고, 역할 구성원 목록을 감사 증적으로 활용합니다.
- 데이터 계층의 역할 관문 – 클래스 수준 권한과 행 수준 정책에서 역할이 “누가”를 담당합니다.
RBAC을 선택해야 할까? 결정 매트릭스
| 상황 | 권장 |
|---|---|
| 접근이 직무를 따르는 경우 | RBAC – 본래의 영역 |
| 사용자가 개별 레코드를 그때그때 공유하는 경우 | ACL – 역할로는 표현 불가 |
| 맥락(시간, 상태, 테넌트)이 결정하는 경우 | 역할 위에 속성 조건 |
| 사용자 유형이 몇 가지뿐이고 안정적인 경우 | 넓은 역할 3–7개로 구성한 RBAC |
| 깊은 조직도, 중첩된 팀 | 역할 계층 – 실제 대규모라면 ReBAC |
| ”관리자와 그 외 모두”뿐인 경우 | 역할 관문 하나 – 과도한 모델링은 금물 |
한계와 트레이드오프
- 객체별 공유는 범위 밖입니다. “이 문서를 Ana와 공유”에 대해 RBAC은 문서마다 역할을 만드는 것 외에는 답이 없습니다. 이 결정은 ACL의 몫입니다.
- 같은 역할, 같은 권한입니다. 두 Editor는 서로 구별되지 않습니다. 개인별 세부 조정에는 거의 똑같은 역할을 하나 더 만드는 것이 아니라 다른 계층이 필요합니다.
- 역할 엔지니어링은 상당한 선행 작업입니다. 이를 건너뛰면 조직도 위험 모델도 반영하지 못하는 역할이 만들어지고, 그 역할이 끝없이 복제됩니다.
- 정적인 역할은 동적인 위험을 놓칩니다. 역할 구성원 여부로는 평소와 다른 시간대, 새 기기, 민감한 레코드 상태를 볼 수 없습니다. 이는 속성의 영역입니다.
- 드리프트가 정상 상태입니다. 주기적인 권한 재검토(recertification)가 없으면 역할의 범위는 늘어나기만 합니다. RBAC의 감사 가능성은 보장이 아니라 역량입니다.
Back4app에서의 역할
Back4app은 관리형 데이터베이스, 자동 생성되는 REST 및 GraphQL API, 인증, 파일 스토리지, Cloud Code 서버리스 함수를 결합한 오픈소스 Backend as a Service(BaaS) 플랫폼입니다. 여기서 역할은 코드가 아니라 데이터입니다. 각 역할은 _Role 클래스의 객체로, 구성원을 위한 users Relation과 중첩을 위한 roles Relation을 가집니다. 중첩은 곧 추가 비용 없이 얻는 계층입니다. 하위 역할의 구성원은 상위 역할에 부여된 모든 권한을 상속하기 때문입니다. 권한 부여 자체는 조합 섹션이 가리키는 바로 그 자리에서 이루어집니다. 역할 이름은 큰 틀을 위해 클래스 수준 권한에, 예외를 위해 객체별 ACL 항목에 나타나며(코드 탭이 두 부분을 모두 보여 줍니다), Back4app이 모든 REST, GraphQL, Live Query 요청마다 그 결과를 강제합니다. 역할이 쿼리 가능한 객체이므로 구성원 관리, 감사, 관리자 UI는 평범한 데이터베이스 작업입니다. 역할 폭발 방지가 거버넌스 프로젝트가 아니라 데이터 모델링 습관이 됩니다.
자주 묻는 질문
RBAC을 쉽게 설명하면 무엇입니까?
접근 권한을 사람별이 아니라 직무별로 부여하는 방식입니다. 권한은 Editor, Admin, Support 같은 역할에 연결되고, 사용자는 할당된 역할이 가진 권한을 그대로 물려받습니다. 입사, 승진, 퇴사는 곳곳에 흩어진 권한 수정이 아니라 한곳에서의 역할 변경이 됩니다.
RBAC과 ABAC의 차이는 무엇입니까?
RBAC은 미리 정의된 역할로 결정합니다. 속성 기반 접근 제어(ABAC)는 요청 시점에 사용자, 리소스, 맥락의 속성(부서, 민감도, 시간)을 평가합니다. RBAC은 추론하고 감사하기가 더 쉽고, ABAC은 더 세밀하지만 디버깅하기가 더 어렵습니다. 성숙한 시스템은 RBAC을 기준선으로 삼고, 맥락이 실제로 중요한 곳에 속성 조건을 더합니다.
RBAC과 ACL의 차이는 무엇입니까?
연결 방향입니다. ACL은 주체-권한 항목을 각 객체에 걸고, RBAC은 시스템 전반에 걸쳐 권한을 역할에 겁니다. 둘은 경쟁하는 것이 아니라 조합됩니다. ACL 항목은 역할을 지정할 수 있으며, 이것이 객체별 제어와 한곳에서의 구성원 관리가 공존하는 방법입니다.
RBAC 모델에는 어떤 것이 있습니까?
표준은 핵심 RBAC(사용자, 역할, 권한, 세션), 계층형 RBAC(상위 역할이 하위 역할의 권한을 상속), 제약 RBAC(직무 분리 규칙: 할당에 대한 정적 제약과 한 세션에서 함께 활성화할 수 있는 역할에 대한 동적 제약)을 정의합니다.
RBAC의 세 가지 규칙은 무엇입니까?
1992년의 최초 정식화에 따르면 다음과 같습니다. 주체는 선택한 역할을 통해서만 행동할 수 있고(역할 할당), 주체는 그 역할에 대해 인가되어 있어야 하며(역할 인가), 동작은 활성 역할이 해당 권한을 가진 경우에만 허용됩니다(권한 인가). 요약하면 역할을 거치지 않는 접근은 없습니다.
역할 폭발(role explosion)이란 무엇입니까?
모든 예외, 프로젝트, 리전, 테넌트가 새 역할을 만들어 내면서 역할이 통제 없이 늘어나는 현상입니다. Project-A-Manager-Region-West 같은 역할이 쌓이다 보면 역할 수가 사용자 수를 넘어서고, 아무도 시스템을 감사할 수 없게 됩니다. 근본 원인은 맥락 속성을 조건이나 객체별 항목으로 처리하지 않고 역할로 인코딩하는 데 있습니다.
RBAC은 최소 권한 원칙과 같은 것입니까?
아닙니다. 최소 권한은 원칙이고 RBAC은 그 원칙을 추구하는 메커니즘 중 하나이며, 둘을 연결하는 것은 역할 관리의 규율뿐입니다. 지나치게 넓은 역할은 RBAC 안에서 최소 권한을 위반합니다. 역할의 범위를 최소한으로 잡고 주기적으로 검토하는 것이 실제로 원칙을 실현하는 방법입니다.
RBAC에서 직무 분리란 무엇입니까?
상충하는 권한을 떼어 놓는 제약입니다. 정적 분리는 한 사용자가 결제 생성자와 결제 승인자 역할을 동시에 보유하는 것을 원천 차단합니다. 동적 분리는 둘 다 보유하는 것은 허용하지만 같은 세션에서 함께 활성화하는 것은 막습니다. 역할 규칙으로 표현된 부정 방지 장치입니다.