들어가며 — 인증의 다음 전장, 인가
지난 몇 년간 업계는 인증(authentication) 문제를 상당 부분 해결했습니다. OIDC/SAML 기반 SSO는 상식이 되었고, passkey가 비밀번호를 대체하고 있습니다. 그런데 "누구인지 확인"한 다음의 질문 — **"이 사용자가 이 리소스에 이 작업을 해도 되는가?"** — 는 여전히 각 애플리케이션에 흩어진 if문 덩어리로 남아 있는 경우가 대부분입니다.
2026년에 인가(authorization)가 다시 뜨거운 주제가 된 배경은 명확합니다.
1. **마이크로서비스와 멀티테넌시**: 권한 판단 로직이 수십 개 서비스에 중복 구현되면서 일관성과 감사가 불가능해졌습니다.
2. **협업 기능의 보편화**: "이 문서를 이 사람에게 공유"라는 Google Docs식 요구사항은 전통적인 역할 기반 모델로는 표현이 안 됩니다.
3. **AI 에이전트의 등장**: 인간이 아닌 주체가 리소스에 접근하면서, 세밀하고(fine-grained) 감사 가능한 인가가 필수가 되었습니다.
4. **규제**: 최소 권한 원칙(least privilege)의 증명을 요구하는 컴플라이언스가 늘었습니다.
이 글은 RBAC → ABAC → ReBAC으로 이어지는 인가 모델의 진화를 추적하고, [Google Zanzibar 논문](https://research.google/pubs/pub48190/)의 핵심 개념과 그 오픈소스 구현체인 [OpenFGA](https://openfga.dev/docs)의 실전 모델링, 그리고 마이크로서비스 환경에서의 아키텍처 패턴까지 다룹니다.
먼저 용어부터 정리합니다.
| 용어 | 의미 |
| --- | --- |
| AuthN (인증) | 당신이 누구인지 확인 — OIDC, SAML, passkey의 영역 |
| AuthZ (인가) | 당신이 무엇을 할 수 있는지 결정 — 이 글의 주제 |
| PEP | Policy Enforcement Point — 결정을 집행하는 지점 (API 게이트웨이, 서비스 코드) |
| PDP | Policy Decision Point — 허용/거부를 결정하는 지점 (인가 엔진) |
| PAP | Policy Administration Point — 정책을 관리하는 지점 |
| PIP | Policy Information Point — 결정에 필요한 속성을 공급하는 지점 |
RBAC — 그리고 Role Explosion이라는 저주
RBAC(Role-Based Access Control)은 가장 널리 쓰이는 모델입니다. 사용자에게 역할(role)을 부여하고, 역할에 권한(permission)을 묶습니다.
사용자 ──(할당)──> 역할 ──(보유)──> 권한
jane ─────────> editor ────────> document:write
john ─────────> viewer ────────> document:read
RBAC의 장점은 명백합니다. 이해하기 쉽고, 감사가 단순하며("editor 역할 보유자 목록 출력"), NIST RBAC 표준(INCITS 359)이라는 성숙한 이론 기반도 있습니다.
문제는 **현실의 권한 요구가 "역할"이라는 단일 차원으로 표현되지 않는다**는 점입니다.
- "editor인데, 자기 부서 문서만"
- "viewer인데, 근무 시간에만"
- "manager인데, 자기가 결재 올린 건은 승인 불가"
이런 요구를 RBAC으로 욱여넣으면 역할이 차원의 조합 수만큼 폭증합니다. 이것이 악명 높은 **role explosion**입니다.
editor → 부서 차원 추가 → editor-sales
editor-hr
editor-engineering
→ 지역 차원 추가 → editor-sales-kr
editor-sales-us
editor-hr-kr
... (조합 폭발)
실제 대기업 IGA 감사에서 "사용자 수보다 역할 수가 많은" 사례는 드물지 않습니다. 역할이 수천 개가 되는 순간 RBAC의 유일한 장점이었던 "이해하기 쉬움"이 사라집니다.
그럼에도 RBAC은 죽지 않습니다. **조직 수준의 굵직한 권한 구분(coarse-grained)** — 예: admin/member/billing-manager — 에는 여전히 최적입니다. 문제는 리소스 단위의 세밀한 제어를 RBAC으로 하려 할 때 생깁니다.
ABAC — 속성과 정책으로, 그러나 XACML의 교훈
ABAC(Attribute-Based Access Control)은 주체(subject), 리소스(resource), 행위(action), 환경(environment)의 **속성**을 조건식으로 평가합니다.
허용 조건:
subject.department == resource.department
AND action == "edit"
AND environment.time BETWEEN 09:00 AND 18:00
AND subject.clearance >= resource.classification
role explosion 문제는 우아하게 해결됩니다. 부서가 100개여도 정책은 한 줄입니다.
ABAC의 표준화 시도가 OASIS [XACML](https://docs.oasis-open.org/xacml/3.0/xacml-3.0-core-spec-os-en.html)이었습니다. XACML은 PEP/PDP/PAP/PIP라는 아키텍처 어휘를 남겼다는 점에서 유산이 크지만, 그 자체는 사실상 실패한 표준으로 평가됩니다. 이유는 다음과 같습니다.
- **XML 기반의 극단적인 장황함**: 간단한 규칙 하나가 수십 줄의 XML이 됩니다.
- **디버깅 불가능성**: 정책 충돌(combining algorithm)의 결과를 사람이 예측하기 어렵습니다.
- **개발자 경험 부재**: 정책 작성이 전문 도구 없이는 불가능에 가까웠습니다.
XACML의 정신은 이후 **policy-as-code** 진영 — 특히 [OPA(Open Policy Agent)](https://www.openpolicyagent.org/docs/latest/)와 Rego 언어 — 으로 계승됩니다. 같은 ABAC 평가를 훨씬 다루기 쉬운 형태로 구현한 것입니다.
그러나 ABAC에도 구조적 한계가 있습니다. **"jane이 이 특정 문서를 볼 수 있는가"는 잘 답하지만, "jane이 볼 수 있는 문서 전체 목록"(reverse query)을 뽑는 데는 취약**합니다. 또한 "문서 X를 폴더 Y에 넣었고, 폴더 Y는 팀 Z에 공유됐다"처럼 **관계의 연쇄**로 권한이 파생되는 시나리오는 속성으로 모델링하기가 부자연스럽습니다.
ReBAC — Google Zanzibar가 제시한 패러다임
이 지점에서 등장한 것이 ReBAC(Relationship-Based Access Control)입니다. 권한을 속성의 조건식이 아니라 **주체와 객체 사이의 관계 그래프**로 모델링합니다. 그 정점이 2019년 발표된 Google의 [Zanzibar 논문](https://research.google/pubs/pub48190/)입니다. Zanzibar는 Google Docs, Drive, YouTube, Cloud 전체의 인가를 담당하는 단일 글로벌 시스템으로, 수조 개의 ACL을 저장하고 초당 수백만 건의 권한 질의를 10ms 수준의 지연으로 처리합니다.
핵심 개념 1 — Relationship Tuple
Zanzibar의 모든 권한 데이터는 다음 형태의 튜플로 표현됩니다.
object#relation@user
예시:
doc:budget-2026#owner@user:jane jane은 budget-2026 문서의 owner
doc:budget-2026#viewer@group:finance#member
finance 그룹의 member는 viewer
folder:q1#parent@doc:budget-2026 budget-2026의 부모는 q1 폴더
세 번째 예시처럼 user 자리에 **다른 객체의 userset**이 올 수 있다는 점이 강력합니다. "finance 그룹의 멤버 전원"이라는 집합을 한 줄로 가리킬 수 있고, 그룹 멤버십이 바뀌어도 문서 쪽 튜플은 그대로입니다.
핵심 개념 2 — Userset Rewrite
튜플이 데이터라면, userset rewrite 규칙은 **권한의 파생 로직**입니다. 예를 들어 "owner는 자동으로 editor이기도 하다", "부모 폴더의 viewer는 자식 문서의 viewer다" 같은 규칙을 객체 타입별로 선언합니다.
viewer 관계의 평가 규칙 (개념적 표현):
viewer =
직접 viewer로 지정된 사용자 (this)
∪ editor인 사용자 (computed userset)
∪ parent 폴더에서 viewer인 사용자 (tuple-to-userset)
이 세 가지 — 직접 관계, 계산된 관계(computed userset), 관계를 타고 넘어가는 관계(tuple-to-userset) — 의 합집합/교집합/차집합 조합만으로 Google Drive 수준의 공유 모델이 표현됩니다.
핵심 개념 3 — Zookie와 일관성
분산 시스템에서 인가의 고전적 함정은 **"new enemy problem"**입니다. 예를 들어 (1) jane을 문서에서 제거하고 (2) 문서에 민감한 내용을 추가했는데, 복제 지연 때문에 (2)의 읽기 시점에 (1)이 아직 반영되지 않으면, 제거된 jane이 새 내용을 보게 됩니다. 순서가 보장되지 않는 캐시/복제는 보안 사고가 됩니다.
Zanzibar는 **zookie**라는 일관성 토큰으로 이를 해결합니다. 콘텐츠를 수정할 때 zookie를 받아 저장해 두고, 권한 체크 시 그 zookie를 함께 보내면 "최소한 그 시점 이후의 ACL 상태"로 평가가 보장됩니다. 외부 일관성(external consistency)과 성능(과감한 캐싱) 사이의 균형을 잡는 우아한 장치입니다. OpenFGA에서는 consistency 파라미터(예: HIGHER_CONSISTENCY)로 유사한 제어를 제공합니다.
OpenFGA 실전 모델링 — 문서 공유 시스템
[OpenFGA](https://openfga.dev/docs)는 Auth0/Okta가 시작해 CNCF에 기증한 Zanzibar 구현체입니다. DSL이 직관적이어서 ReBAC 입문에 가장 좋습니다. Google Drive를 닮은 문서 공유 시스템을 모델링해 보겠습니다.
model
schema 1.1
type user
type group
relations
define member: [user]
type folder
relations
define owner: [user]
define parent: [folder]
define editor: [user, group#member] or owner or editor from parent
define viewer: [user, group#member] or editor or viewer from parent
type doc
relations
define parent: [folder]
define owner: [user]
define editor: [user, group#member] or owner or editor from parent
define viewer: [user, group#member] or editor or viewer from parent
define can_share: owner or editor
define can_delete: owner
이 모델 하나로 표현되는 것들:
- 사용자/그룹 단위 공유 (group#member 타입 제약)
- owner ⊃ editor ⊃ viewer 권한 계층 (computed relation)
- 폴더 권한의 하위 상속 (편의상 "editor from parent" — tuple-to-userset)
- 행위 수준 권한 (can_share, can_delete)
튜플을 써 넣고 질의해 봅니다.
튜플 쓰기: finance 그룹 멤버에게 q1 폴더 viewer 부여
fga tuple write --store-id "$FGA_STORE_ID" \
"group:finance#member" viewer "folder:q1"
jane을 finance 그룹에 추가
fga tuple write --store-id "$FGA_STORE_ID" \
"user:jane" member "group:finance"
budget-2026 문서를 q1 폴더에 배치
fga tuple write --store-id "$FGA_STORE_ID" \
"folder:q1" parent "doc:budget-2026"
질의: jane은 budget-2026을 볼 수 있는가?
fga query check --store-id "$FGA_STORE_ID" \
"user:jane" viewer "doc:budget-2026"
→ allowed: true (group → folder → doc 관계 연쇄로 파생)
애플리케이션 코드에서는 SDK로 체크합니다.
const fga = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL,
storeId: process.env.FGA_STORE_ID,
});
// 단건 체크 (PEP에서 호출)
const { allowed } = await fga.check({
user: 'user:jane',
relation: 'viewer',
object: 'doc:budget-2026',
});
// 역질의: jane이 볼 수 있는 문서 목록 (UI 필터링용)
const { objects } = await fga.listObjects({
user: 'user:jane',
relation: 'viewer',
type: 'doc',
});
ABAC이 어려워하던 **reverse query(ListObjects)가 1급 API**라는 점에 주목하십시오. "내가 접근 가능한 리소스 목록" 화면을 만들 때 결정적인 차이를 만듭니다.
생태계 — SpiceDB, Ory Keto, 그리고 OPA와의 역할 구분
Zanzibar 계열 구현체는 OpenFGA만이 아닙니다.
| 프로젝트 | 특징 | 스키마 언어 |
| --- | --- | --- |
| OpenFGA | CNCF, Auth0 출신, 가장 친절한 DSL과 문서 | FGA DSL / JSON |
| SpiceDB (AuthZed) | Zanzibar 논문에 가장 충실, caveat(조건부 관계) 지원 | SpiceDB schema |
| Ory Keto | Ory 생태계(Kratos/Hydra)와 통합 | Ory Permission Language |
| Permify | 멀티테넌시 강조 | Permify schema |
그렇다면 OPA/Rego는 어디에 들어갈까요? **OPA는 정책 평가 엔진이고, Zanzibar 계열은 관계 데이터 저장소 겸 그래프 평가 엔진**입니다. 거칠게 나누면:
- **OPA가 잘하는 것**: 입력으로 주어진 컨텍스트에 대한 규칙 평가. "이 K8s 매니페스트가 보안 기준을 만족하는가", "이 요청의 JWT scope가 이 API에 충분한가" 같은 stateless 판단. 정책이 코드로 버전 관리되는 policy-as-code.
- **ReBAC 엔진이 잘하는 것**: "jane → 그룹 → 폴더 → 문서"처럼 **저장된 관계 데이터**를 그래프로 탐색해야 하는 판단. 수억 건의 관계 위에서의 check/list 질의.
요청 → API Gateway/서비스 (PEP)
│
├─ 굵은 판단: JWT scope, 테넌트 검증 → OPA (stateless 정책)
│
└─ 세밀한 판단: 이 사용자가 이 문서를? → OpenFGA (관계 그래프)
둘은 경쟁자가 아니라 레이어가 다른 도구이며, 함께 쓰는 조합이 흔합니다. Rego 예시로 감을 잡아 봅니다.
OPA Rego — coarse-grained API 정책 (개념 예시)
package httpapi.authz
default allow := false
allow if {
input.method == "GET"
startswith(input.path, "/api/public/")
}
allow if {
input.method == "POST"
input.path == "/api/docs"
"docs:write" in input.token.scopes
input.token.tenant == input.headers["x-tenant-id"]
}
아키텍처 패턴 — 중앙집중 PDP vs 라이브러리 임베딩
인가 엔진을 배치하는 방식은 크게 두 갈래입니다.
패턴 A: 중앙집중 PDP 패턴 B: 사이드카/라이브러리 임베딩
───────────────────── ─────────────────────────────
svc-a ──┐ svc-a ── [PDP sidecar/lib]
svc-b ──┼──> AuthZ Service (PDP) svc-b ── [PDP sidecar/lib]
svc-c ──┘ + 단일 관계 DB svc-c ── [PDP sidecar/lib]
(정책/데이터 복제 배포)
장점: 단일 진실 공급원, 장점: 지연 최소(로컬 평가),
감사 용이, 모델 일관성 네트워크 의존 없음
단점: 네트워크 홉 추가, 단점: 데이터 동기화 복잡,
가용성이 전체에 영향 일관성 보장 어려움
실무 가이드라인은 다음과 같습니다.
- **관계 데이터 기반 판단(ReBAC)은 중앙집중이 기본**입니다. 관계 그래프를 모든 서비스에 복제하는 것은 일관성 악몽입니다. 지연은 같은 가용 영역 배치 + 캐싱으로 1~5ms 수준까지 줄일 수 있습니다.
- **stateless 정책(OPA)은 임베딩이 자연스럽습니다**. OPA는 사이드카/라이브러리로 각 서비스 옆에 두고, 정책 번들을 중앙(PAP)에서 배포하는 모델이 표준입니다.
- 중앙 PDP의 가용성은 인증 IdP와 동급으로 취급해야 합니다. 다중화, 헬스체크 기반 페일오버, 그리고 "PDP 장애 시 fail-closed"가 원칙입니다(fail-open은 인가 우회입니다).
Keycloak Authorization Services와 외부 엔진의 결합
[Keycloak](https://www.keycloak.org/docs/latest/authorization_services/index.html)에도 자체 인가 기능(Authorization Services)이 있습니다. UMA 2.0 기반으로 resource/scope/policy/permission을 정의하고, 토큰에 권한(RPT)을 실어 보내는 방식입니다. 그렇다면 Keycloak만으로 충분할까요?
현실적인 역할 분담은 이렇습니다.
| 레이어 | 담당 | 도구 |
| --- | --- | --- |
| 신원/역할 발급 | 사용자가 누구이고 어떤 굵은 역할을 갖는지 (토큰 클레임) | Keycloak |
| API 수준 정책 | 이 토큰으로 이 엔드포인트 호출 가능 여부 | Keycloak AuthZ 또는 OPA |
| 리소스 수준 관계 | 이 사용자가 이 문서/프로젝트/티켓에 무엇을 | OpenFGA/SpiceDB |
전형적인 결합 패턴: Keycloak이 발급한 토큰의 sub 클레임을 OpenFGA의 user 식별자로 사용하고, 역할/그룹 클레임의 변경을 이벤트로 받아 FGA 튜플에 동기화합니다.
로그인 → Keycloak → access_token (sub: user:jane, groups: [finance])
│
요청 → 서비스(PEP) ───────┤
├─ 토큰 검증 (서명, aud, exp) ← Keycloak 공개키
└─ fga.check(user:jane, viewer, doc:X) ← OpenFGA
Keycloak의 그룹 멤버십을 FGA 튜플로 동기화하는 이벤트 리스너 개념 예시입니다.
// Keycloak SPI — 그룹 멤버십 변경을 OpenFGA에 반영하는 이벤트 리스너 (개념 코드)
public class FgaSyncEventListener implements EventListenerProvider {
@Override
public void onEvent(AdminEvent event, boolean includeRepresentation) {
if (event.getResourceType() == ResourceType.GROUP_MEMBERSHIP) {
String userId = extractUserId(event.getResourcePath());
String groupId = extractGroupId(event.getResourcePath());
if (event.getOperationType() == OperationType.CREATE) {
fgaClient.writeTuple("user:" + userId, "member", "group:" + groupId);
} else if (event.getOperationType() == OperationType.DELETE) {
fgaClient.deleteTuple("user:" + userId, "member", "group:" + groupId);
}
}
}
}
마이크로서비스에서 인가 데이터 동기화
ReBAC 엔진을 도입하면 새로운 운영 과제가 생깁니다. **애플리케이션 DB의 사실(소유권, 멤버십, 폴더 구조)과 FGA의 튜플을 어떻게 일치시키는가**입니다.
전략은 세 가지입니다.
1. **동기 이중 쓰기(dual write)**: 리소스 생성 트랜잭션에서 FGA 쓰기를 함께 수행. 단순하지만 부분 실패(DB는 성공, FGA는 실패) 시 권한 구멍이 생깁니다. 보상 트랜잭션 또는 재시도 큐가 필수입니다.
2. **Transactional Outbox + CDC**: 권장 패턴. 리소스 변경과 outbox 레코드를 한 트랜잭션으로 묶고, Debezium 류의 CDC가 outbox를 읽어 FGA에 반영합니다. at-least-once 전달이므로 튜플 쓰기는 멱등하게 설계합니다.
3. **주기적 재조정(reconciliation)**: 위 두 전략과 병행하여, 배치로 애플리케이션 DB와 FGA 튜플의 차이를 비교/복구합니다. 인가 데이터의 drift는 곧 보안 취약점이므로 재조정은 선택이 아니라 필수입니다.
서비스 트랜잭션
┌──────────────────────────────┐
│ INSERT INTO documents (...) │
│ INSERT INTO outbox ( │ CDC (Debezium) OpenFGA
│ event: doc.created, │ ───────────────────────> tuple write
│ owner: user:jane ) │ (at-least-once) (멱등 처리)
└──────────────────────────────┘
▲
nightly reconciliation ───┘ (drift 탐지/복구)
삭제는 더 까다롭습니다. 리소스가 삭제되면 관련 튜플을 모두 지워야 하며(고아 튜플은 감사 노이즈 + 잠재적 오판), 폴더처럼 계층이 있는 객체는 하위 객체의 튜플 정리 순서까지 설계해야 합니다.
선택 가이드 — 무엇을 언제 쓰는가
| 상황 | 권장 모델 |
| --- | --- |
| 사내 admin 도구, 역할이 5개 이하로 안정적 | RBAC (IdP 역할 클레임으로 충분) |
| 테넌트/부서/시간 등 속성 조건이 핵심 | ABAC (OPA policy-as-code) |
| 문서/폴더/프로젝트 공유, 계층 상속, 협업 기능 | ReBAC (OpenFGA/SpiceDB) |
| K8s admission, 인프라 정책, CI 게이트 | OPA/Rego |
| 규제 산업 + 접근 결정의 중앙 감사 필요 | 중앙 PDP + 결정 로그 파이프라인 |
| 위 요구가 섞여 있음 (대부분의 현실) | RBAC(굵게) + ReBAC(세밀하게) + OPA(정책) 조합 |
판단 기준을 질문 형태로 정리하면:
1. **"X를 볼 수 있는 사람 목록" 또는 "내가 볼 수 있는 X 목록"이 필요한가?** → 필요하면 ReBAC. ABAC으로는 고통받습니다.
2. **권한이 리소스 간 관계(폴더→문서, 조직→프로젝트)에서 파생되는가?** → ReBAC.
3. **권한이 요청 컨텍스트(시간, IP, 디바이스 상태)에 의존하는가?** → ABAC/OPA. 단, SpiceDB caveat이나 OpenFGA conditions로 ReBAC에 조건을 섞는 것도 가능합니다.
4. **조직 전체에서 권한 모델을 통일할 준비가 됐는가?** → 안 됐다면 한 도메인(예: 문서 서비스)부터 ReBAC을 도입하고 점진 확장하십시오.
안티패턴 모음
1. **JWT에 세밀한 권한을 다 싣기**: 토큰에 문서 ID 목록을 넣으면 토큰이 비대해지고, 권한 회수가 토큰 만료까지 지연됩니다. 토큰에는 신원과 굵은 클레임만, 세밀한 판단은 PDP 실시간 질의로.
2. **fail-open PDP**: 인가 서비스 장애 시 "일단 허용"은 인가 우회 백도어입니다. fail-closed + 캐시된 결정의 짧은 TTL 허용이 정석입니다.
3. **프론트엔드 인가를 신뢰**: UI에서 버튼을 숨기는 것은 UX이지 보안이 아닙니다. 모든 집행은 서버 측 PEP에서.
4. **관계 모델 없이 튜플부터 쌓기**: 모델(스키마) 리뷰 없이 튜플을 쌓으면 나중에 마이그레이션 지옥이 옵니다. 모델 변경은 코드 리뷰 + 테스트(FGA의 model test)를 거치십시오.
5. **결정 로그 미수집**: "왜 허용됐는가"를 재구성할 수 없으면 감사 대응이 불가능합니다. check 요청/응답을 구조화 로그로 남기십시오.
6. **이중 쓰기 후 재조정 생략**: drift는 반드시 발생합니다. 탐지 없는 drift는 침묵하는 권한 버그입니다.
마치며
인가 모델의 진화는 "표현력"과 "운영 가능성" 사이의 긴장 속에서 진행되어 왔습니다. RBAC은 단순했지만 role explosion으로 무너졌고, ABAC(XACML)은 표현력을 얻었지만 개발자 경험을 잃었으며, Zanzibar/ReBAC은 관계라는 자연스러운 모델과 reverse query, 그리고 zookie라는 일관성 장치로 현재의 균형점을 제시했습니다.
실무 결론은 의외로 보수적입니다. **굵은 권한은 IdP(Keycloak)의 역할로, 정책적 판단은 OPA로, 리소스 수준 관계는 OpenFGA로** — 각 레이어에 맞는 도구를 조합하되, 모든 결정을 감사 가능하게 남기는 것. 그것이 2026년 인가 아키텍처의 모범 답안입니다.
다음 글에서는 이 인가 인프라 위에 올라탈 새로운 주체 — AI 에이전트의 아이덴티티와 MCP 인증을 다룹니다.
참고 자료
- [Zanzibar: Google's Consistent, Global Authorization System](https://research.google/pubs/pub48190/) — Zanzibar 논문 원문
- [OpenFGA Documentation](https://openfga.dev/docs) — OpenFGA 공식 문서
- [OpenFGA Modeling Guide](https://openfga.dev/docs/modeling) — 모델링 실전 가이드
- [SpiceDB Documentation](https://authzed.com/docs) — SpiceDB/AuthZed 문서
- [Ory Keto Documentation](https://www.ory.sh/docs/keto) — Ory Keto 문서
- [Open Policy Agent Documentation](https://www.openpolicyagent.org/docs/latest/) — OPA/Rego 공식 문서
- [OASIS XACML 3.0 Specification](https://docs.oasis-open.org/xacml/3.0/xacml-3.0-core-spec-os-en.html) — XACML 표준
- [NIST RBAC — INCITS 359](https://csrc.nist.gov/projects/role-based-access-control) — RBAC 표준 프로젝트
- [Keycloak Authorization Services Guide](https://www.keycloak.org/docs/latest/authorization_services/index.html) — Keycloak 인가 기능
- [RFC 9700 — Best Current Practice for OAuth 2.0 Security](https://datatracker.ietf.org/doc/html/rfc9700) — OAuth 보안 BCP
현재 단락 (1/238)
지난 몇 년간 업계는 인증(authentication) 문제를 상당 부분 해결했습니다. OIDC/SAML 기반 SSO는 상식이 되었고, passkey가 비밀번호를 대체하고 있습니다...