- Published on
Keycloak Authorization Services — UMA 2.0 기반 세밀한 권한 제어
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 들어가며
- RBAC의 한계, 그리고 ABAC/ReBAC
- Keycloak Authorization Services 아키텍처
- UMA 2.0 Grant 흐름 해부
- Policy Enforcer 실전 설정 (Java)
- Decision Strategy — 정책 충돌의 해석
- 성능 고려사항
- 외부 인가 엔진과의 비교 — OPA, OpenFGA
- 운영 베스트 프랙티스
- 트러블슈팅 노트
- 마치며
- 참고 자료
들어가며
"이 사용자가 admin role을 갖고 있는가?"라는 질문만으로 권한을 결정할 수 있는 시스템은 생각보다 빨리 한계에 부딪힙니다. "이 사용자가 이 문서를 수정할 수 있는가? 단, 문서 소유자이거나, 같은 부서의 관리자이거나, 업무 시간 내의 요청일 때만"이라는 식의 요구가 들어오는 순간, role 기반 분기문은 애플리케이션 코드 전체로 흩어지기 시작합니다.
2026년 현재 이 문제의식은 더 절실해졌습니다. AI 에이전트가 사용자를 대신해 API를 호출하는 시대(Keycloak 26.6은 MCP authorization server 역할을 위한 OAuth Client ID Metadata Document를 실험적으로 지원합니다)에는 "누가"뿐 아니라 "무엇이, 어떤 위임 범위로, 어떤 리소스에" 접근하는지를 중앙에서 평가하고 감사할 수 있어야 합니다. 이 글에서는 Keycloak Authorization Services의 모델과 UMA 2.0 흐름을 해부하고, 실전 policy enforcer 설정, 성능 고려사항, 그리고 OPA/OpenFGA 같은 외부 인가 엔진과의 관계까지 다룹니다.
RBAC의 한계, 그리고 ABAC/ReBAC
먼저 인가 모델의 스펙트럼을 정리해 봅시다.
| 모델 | 결정 기준 | 예시 | 한계 |
|---|---|---|---|
| RBAC | 사용자에게 부여된 role | admin은 모든 문서 수정 가능 | 리소스 단위 구분 불가, role 폭발 |
| ABAC | 주체/리소스/환경의 속성 | 같은 부서 + 업무 시간이면 허용 | 정책 작성/디버깅 난이도 |
| ReBAC | 주체와 리소스 사이의 관계 그래프 | 문서의 owner 또는 폴더 editor면 허용 | 관계 데이터 동기화 비용 |
RBAC의 전형적인 실패 양상은 **role 폭발(role explosion)**입니다. "프로젝트 A의 편집자", "프로젝트 B의 열람자"를 모두 role로 만들면 프로젝트 수 × 권한 수만큼 role이 늘어나고, 결국 role 관리 자체가 새로운 권한 문제가 됩니다. 그렇다고 애플리케이션 코드에 if 분기로 풀면 정책이 코드 곳곳에 흩어져 감사도 변경도 어려워집니다.
여기서 필요한 것이 **정책의 중앙화와 외부화(policy externalization)**입니다. Keycloak Authorization Services는 OAuth 2.0 위에서 리소스 단위의 세밀한 인가를 중앙에서 평가하는 프레임워크로, RBAC을 포함해 ABAC, 시간 기반, 그리고 제한적인 ReBAC 스타일까지 표현할 수 있습니다.
Keycloak Authorization Services 아키텍처
4개의 빌딩 블록
Keycloak의 인가 모델은 네 가지 개념으로 구성됩니다. client 설정에서 Authorization Enabled를 켜면 해당 client가 "resource server"가 되고, 그 아래에 다음을 정의합니다.
+------------------------------------------------------------+
| Resource Server (client) |
| |
| +-----------+ +---------+ |
| | Resource |---->| Scope | "무엇을" (document:123) |
| | (문서,API) | | (view, | "어떤 행위" (view, edit) |
| +-----------+ | edit) | |
| ^ +---------+ |
| | ^ |
| +-----+----------------+-----+ |
| | Permission | "리소스/스코프와 정책을 연결" |
| | (resource-based / | |
| | scope-based) | |
| +-------------+--------------+ |
| | |
| +-------------v--------------+ |
| | Policy | "누가/어떤 조건에" (role, |
| | (role, user, group, time, | group, time, regex ...) |
| | regex, aggregated ...) | |
| +----------------------------+ |
+------------------------------------------------------------+
- Resource: 보호 대상입니다. URI 패턴, 타입, 소유자(owner)를 가질 수 있습니다. "문서 123" 같은 개별 인스턴스일 수도, "document 타입 전체"일 수도 있습니다.
- Scope: 리소스에 대해 수행 가능한 행위입니다. view, edit, delete 같은 동사를 정의합니다.
- Policy: "누가/어떤 조건에서"를 정의하는 단위입니다. 정책 자체는 리소스를 모릅니다.
- Permission: 리소스(또는 스코프)와 정책을 연결해 "이 리소스의 이 행위는 이 정책들을 통과해야 한다"를 선언합니다.
이 분리가 중요한 이유는 정책의 재사용성 때문입니다. "업무 시간에만"이라는 time policy를 한 번 만들면 수십 개의 permission에서 재사용할 수 있습니다.
Policy 유형 정리
| Policy 유형 | 평가 기준 | 활용 예 |
|---|---|---|
| Role | realm/client role 보유 여부 | 관리자 전용 기능 |
| User | 특정 사용자 지정 | 시스템 계정 예외 |
| Group | 그룹 멤버십 (계층 포함 가능) | 부서 단위 접근 |
| Client | 요청한 client 식별 | 내부 서비스 전용 API |
| Time | 시각/요일/기간 조건 | 업무 시간 제한, 캠페인 기간 |
| Regex | 토큰 클레임에 대한 정규식 매칭 | 이메일 도메인, 속성 패턴 |
| Client Scope | client scope 보유 여부 | 동의 기반 접근 |
| Aggregated | 여러 정책의 조합 | 복합 조건 |
| JavaScript | JS 코드로 임의 로직 (deprecated 흐름) | 레거시 커스텀 로직 |
JavaScript policy에 대한 주의가 필요합니다. 과거에는 Admin Console에서 JS 코드를 직접 입력해 정책을 만들 수 있었지만, 보안상의 이유로 이 기능은 기본 비활성화되었고 배포 JAR을 통해서만 제한적으로 사용할 수 있는 deprecated 경로가 되었습니다. Nashorn 엔진 제거 이후의 흐름까지 고려하면, 신규 설계에서 JS policy에 의존하는 것은 피해야 합니다. 복잡한 커스텀 로직이 필요하다면 (1) 기존 정책 유형의 조합(aggregated policy)으로 풀거나, (2) Policy SPI로 Java 기반 커스텀 정책을 구현하거나, (3) 뒤에서 다룰 외부 인가 엔진과의 병행을 검토하세요.
PEP/PDP 모델
Authorization Services는 고전적인 XACML 용어의 구조를 따릅니다.
+----------------+ (1) 요청 +---------------------+
| Client +-------------------->+ Application |
| (브라우저/앱) | | = PEP |
+----------------+ | (Policy Enforcement |
| Point) |
+----------+----------+
| (2) 결정 요청
| (token / ticket)
+----------v----------+
| Keycloak |
| = PDP + PAP |
| (Policy Decision / |
| Administration) |
+----------+----------+
| (3) Permit/Deny
| (RPT 발급)
+----------v----------+
| 보호된 리소스 |
+---------------------+
- PEP(Policy Enforcement Point): 애플리케이션 측에서 요청을 가로채 인가 결정을 강제하는 지점. Keycloak이 제공하는 policy enforcer 라이브러리가 이 역할을 합니다.
- PDP(Policy Decision Point): 정책을 평가해 Permit/Deny를 결정하는 지점. Keycloak 서버의 token 엔드포인트(UMA grant)가 담당합니다.
- PAP(Policy Administration Point): 정책을 관리하는 지점. Admin Console과 Protection API입니다.
UMA 2.0 Grant 흐름 해부
UMA(User-Managed Access) 2.0은 OAuth 2.0의 확장으로, "리소스 소유자가 자신의 리소스에 대한 접근 정책을 관리하고, 클라이언트는 권한 티켓을 통해 인가를 협상한다"는 모델입니다. Keycloak에서의 흐름을 단계별로 보겠습니다.
Client Resource Server (PEP) Keycloak (PDP)
| | |
| (1) GET /api/doc/123 | |
| (access token, RPT없음) | |
+------------------------->| |
| | (2) permission ticket 요청 |
| +----------------------------->|
| | POST /authz/protection/ |
| | permission |
| |<-----------------------------+
| (3) 401 + WWW-Authenticate: UMA |
| (as_uri, ticket) | |
|<-------------------------+ |
| | |
| (4) POST /token |
| grant_type=uma-ticket, ticket=... |
+-------------------------------------------------------->|
| | (5) 정책 평가 |
| (6) RPT (권한 내장 토큰) | |
|<--------------------------------------------------------+
| | |
| (7) GET /api/doc/123 (RPT) |
+------------------------->| (8) RPT 검증 후 응답 |
|<-------------------------+ |
Permission Ticket과 RPT
두 가지 토큰 개념이 등장합니다.
- Permission ticket: resource server가 "이 요청에는 document:123에 대한 view 권한이 필요하다"는 사실을 Keycloak에 등록하고 받는 일회성 티켓입니다. 클라이언트는 이 티켓을 들고 token 엔드포인트로 가서 인가를 요청합니다.
- RPT(Requesting Party Token): 정책 평가를 통과한 클라이언트에게 발급되는, permission 클레임이 내장된 access token입니다. 어떤 리소스의 어떤 스코프가 허용되었는지가 토큰 안에 들어 있습니다.
실제 HTTP 요청으로 보면 다음과 같습니다.
POST /realms/myrealm/protocol/openid-connect/token HTTP/1.1
Host: sso.example.com
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:uma-ticket
&ticket=PERMISSION_TICKET_VALUE
&submit_request=false
티켓 없이 resource server의 client_id를 audience로 지정해 "내가 가진 모든 권한을 평가해 달라"고 요청할 수도 있습니다. 이는 UMA 프로토콜의 전체 왕복을 생략하는 실용적 단축 경로로 자주 쓰입니다.
POST /realms/myrealm/protocol/openid-connect/token HTTP/1.1
Host: sso.example.com
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:uma-ticket
&audience=document-service
&permission=document-resource#view
&response_mode=decision
response_mode=decision으로 요청하면 RPT 대신 단순한 허용 여부 JSON을 받습니다. RPT가 필요 없는 단건 결정 평가에 유용합니다.
{
"result": true
}
발급된 RPT의 permission 클레임은 다음과 같은 구조입니다.
{
"authorization": {
"permissions": [
{
"rsid": "8f4d2e1a-resource-uuid",
"rsname": "document-123",
"scopes": ["view", "comment"]
}
]
},
"aud": "document-service",
"exp": 1781234567
}
Protection API와 리소스 동적 등록
UMA의 또 다른 축은 Protection API입니다. resource server는 service account 토큰(PAT, Protection API Token)으로 리소스를 동적으로 등록/관리할 수 있습니다. "사용자가 문서를 생성하면 그 문서를 owner와 함께 리소스로 등록"하는 패턴이 대표적입니다.
# 문서 생성 시 리소스 동적 등록
curl -X POST "https://sso.example.com/realms/myrealm/authz/protection/resource_set" \
-H "Authorization: Bearer PAT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "document-123",
"type": "urn:document-service:resources:document",
"owner": "jdoe",
"ownerManagedAccess": true,
"resource_scopes": ["view", "edit", "delete", "share"],
"uris": ["/api/documents/123"]
}'
ownerManagedAccess를 켜면 리소스 소유자가 Account Console에서 직접 다른 사용자에게 접근을 공유하거나 요청을 승인/거부할 수 있습니다. "내 문서를 동료에게 공유" 같은 사용자 주도 공유 시나리오가 UMA의 본래 설계 목적입니다.
Policy Enforcer 실전 설정 (Java)
이론을 코드로 내려보겠습니다. Keycloak이 제공하는 keycloak-policy-enforcer 라이브러리는 Java 애플리케이션에 PEP를 끼워 넣는 표준 방법입니다(구 Keycloak adapter는 deprecated되었고, Spring Security + policy enforcer 조합이 현재 권장 경로입니다).
<!-- pom.xml -->
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-policy-enforcer</artifactId>
<version>26.0.0</version>
</dependency>
enforcer 설정 파일입니다.
{
"realm": "myrealm",
"auth-server-url": "https://sso.example.com",
"resource": "document-service",
"credentials": {
"secret": "CLIENT_SECRET_FROM_VAULT"
},
"http-method-as-scope": true,
"lazy-load-paths": true,
"enforcement-mode": "ENFORCING",
"paths": [
{
"path": "/api/documents/*",
"claim-information-point": {
"claims": {
"request.ip": "{request.remoteAddr}"
}
}
},
{
"path": "/api/health",
"enforcement-mode": "DISABLED"
}
]
}
Spring Security 필터 체인에 enforcer를 연결합니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
.authorizeHttpRequests(authz -> authz.anyRequest().authenticated())
.addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter.class);
return http.build();
}
private ServletPolicyEnforcerFilter createPolicyEnforcerFilter() {
return new ServletPolicyEnforcerFilter(request -> {
try (InputStream is = getClass().getResourceAsStream("/policy-enforcer.json")) {
return JsonSerialization.readValue(is, PolicyEnforcerConfig.class);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
}
설정 포인트를 짚어보면 다음과 같습니다.
http-method-as-scope: HTTP 메서드(GET, POST, DELETE)를 스코프로 매핑합니다. REST API라면 리소스 정의가 단순해집니다.lazy-load-paths: 기동 시 모든 리소스를 미리 받지 않고 요청 시점에 경로별 리소스를 조회합니다. 리소스가 수천 개 이상이면 필수입니다.enforcement-mode: ENFORCING(매핑 없는 경로 거부), PERMISSIVE(매핑 없는 경로 허용), DISABLED를 경로별로도 지정할 수 있습니다. 도입 초기에 PERMISSIVE로 시작해 커버리지를 넓혀가는 점진 전략이 안전합니다.claim-information-point(CIP): 요청 컨텍스트(IP, 헤더, 바디)를 클레임으로 추출해 정책 평가에 전달합니다. ABAC 스타일 정책의 입력으로 활용됩니다.
Decision Strategy — 정책 충돌의 해석
permission 하나에 여러 정책이 붙으면, 결과를 어떻게 합산할지가 decision strategy입니다.
| 전략 | 의미 | 사용 예 |
|---|---|---|
| Unanimous (기본) | 모든 정책이 Permit이어야 Permit | 보안 우선, 기본값 권장 |
| Affirmative | 하나라도 Permit이면 Permit | "관리자이거나 소유자이거나" |
| Consensus | Permit 수가 Deny 수보다 많으면 Permit | 드묾, 투표형 시나리오 |
흔한 함정은 Affirmative가 필요한 자리에 Unanimous를 두는 것입니다. "소유자 정책 + 관리자 role 정책"을 Unanimous로 묶으면 "소유자이면서 동시에 관리자"만 통과합니다. OR 의미라면 permission의 decision strategy를 Affirmative로 바꾸거나, aggregated policy 안에서 전략을 지정해야 합니다.
또 하나, resource server 전체 수준의 decision strategy(여러 permission이 같은 리소스에 걸릴 때의 합산)도 별도로 존재합니다. permission 수준과 resource server 수준의 전략을 혼동하면 디버깅이 어려우니, Admin Console의 Evaluate 탭에서 시뮬레이션하며 확인하는 습관을 들이세요. Evaluate 탭은 특정 사용자/리소스/스코프 조합에 대해 어떤 정책이 어떤 결과를 냈는지 단계별로 보여주는, 이 기능군에서 가장 유용한 디버깅 도구입니다.
성능 고려사항
세밀한 인가는 공짜가 아닙니다. 설계 시 다음을 검토해야 합니다.
- 평가 왕복 비용: ENFORCING 모드의 PEP는 캐시 미스 시 Keycloak에 평가 요청을 보냅니다. 요청당 수~수십 ms가 추가될 수 있으므로, enforcer의 경로/결정 캐시 설정을 조정하고 RPT 재사용(클라이언트가 RPT를 들고 다니게)을 활용합니다.
- 리소스 수 폭발: 문서마다 리소스를 등록하는 인스턴스 단위 모델은 수백만 리소스로 이어질 수 있습니다. Keycloak의 리소스/정책은 RDB에 저장되므로, 이 규모에서는 타입 단위 리소스 + CIP로 인스턴스 판단(소유자 클레임 비교)을 하는 하이브리드 모델이나 외부 ReBAC 엔진을 검토해야 합니다.
- 토큰 크기: RPT에 permission이 수백 개 담기면 토큰이 수십 KB로 커져 헤더 제한에 걸립니다.
permission파라미터로 필요한 리소스만 요청하거나 decision 모드를 쓰세요. - DB 부하: 정책 평가는 Keycloak DB 조회를 동반합니다. 인가 트래픽이 로그인 트래픽보다 훨씬 많다는 점을 캐퍼시티 플래닝에 반영해야 합니다.
경험적 가이드라인
------------------------------------------------------
리소스 수 < 1만, 평가 QPS < 수백 → Keycloak authz 단독으로 충분
리소스 수 10만+, 관계 기반 판단 → 외부 ReBAC (OpenFGA) 병행 검토
정책이 코드/데이터 중심 (배포 파이프라인 정책 등) → OPA 병행 검토
외부 인가 엔진과의 비교 — OPA, OpenFGA
2026년의 인가 생태계에서 Keycloak Authorization Services는 유일한 선택지가 아닙니다. 대표적인 두 외부 엔진과 비교해 봅시다.
| 항목 | Keycloak Authz | OPA (Rego) | OpenFGA (Zanzibar 계열) |
|---|---|---|---|
| 모델 | resource/scope/policy | 범용 정책 엔진 (ABAC 강점) | 관계 튜플 그래프 (ReBAC) |
| 정책 언어 | Admin UI + 정책 유형 | Rego (선언적 언어) | DSL (관계 모델 정의) |
| 데이터 위치 | Keycloak DB | 입력으로 주입 (사이드카/번들) | 자체 튜플 스토어 |
| 강점 | IdP와 통합, UMA, 사용자 주도 공유 | 인프라 전반의 범용 정책 | 대규모 관계 질의 (listObjects) |
| 약점 | 초대규모 리소스, 관계 그래프 | 데이터 동기화는 별도 과제 | IdP 기능 없음, 별도 운영 |
| 표준 | UMA 2.0, OAuth | 사실상 표준 (CNCF) | Zanzibar 논문 기반, OpenID AuthZEN 논의 참여 |
핵심 통찰은 이들이 경쟁 관계라기보다 계층이 다르다는 점입니다. Keycloak은 "누가 인증되었고 어떤 토큰을 가졌는가"의 진실의 원천이고, OPA/OpenFGA는 그 토큰을 입력 중 하나로 받아 더 복잡한 결정을 내리는 PDP가 될 수 있습니다.
함께 쓰는 패턴
실무에서 검증된 조합 패턴은 다음과 같습니다.
패턴 A: Keycloak(인증+coarse) + OPA(fine-grained, 인프라 정책)
+--------+ JWT +-------------+ input(JWT claims, +-----+
| Client +-------->+ API Gateway +-------------------->+ OPA |
+--------+ | / Service | resource attrs) +-----+
+-------------+<--------------------+
allow / deny
패턴 B: Keycloak(인증) + OpenFGA(관계 기반 인가)
+--------+ JWT +----------+ check(user, relation, +---------+
| Client +-------->+ Service +----------------------->+ OpenFGA |
+--------+ +----------+ object) +---------+
| ^
| 쓰기 시 관계 튜플 동기화 |
+-----------------------------------+
- 패턴 A (Keycloak + OPA): Keycloak이 발급한 JWT의 클레임(role, group, 부서 속성)을 OPA 정책의 입력으로 사용합니다. 게이트웨이/서비스 메시 레벨의 정책(이 경로는 내부망만, 이 API는 특정 scope만)에 OPA가 강하고, 사용자 신원 속성은 Keycloak이 책임집니다. Keycloak의 protocol mapper로 정책 평가에 필요한 속성을 토큰에 실어 보내는 것이 연결 고리입니다.
- 패턴 B (Keycloak + OpenFGA): 구글 Zanzibar 논문의 계보를 잇는 OpenFGA는 "문서 → 폴더 → 팀"처럼 관계가 전파되는 모델과 "이 사용자가 볼 수 있는 문서 목록"(listObjects) 질의에 강합니다. Keycloak은 인증과 사용자 식별자를 제공하고, 도메인 서비스가 리소스 생성/공유 시 OpenFGA에 관계 튜플을 기록합니다.
- 혼합: coarse-grained(이 API를 호출할 수 있는가)는 Keycloak scope/role로 토큰에 박아 게이트웨이에서 빠르게 거르고, fine-grained(이 객체에 접근 가능한가)는 OpenFGA/OPA로 서비스 내부에서 평가하는 2단 구조가 대규모 시스템의 일반해로 자리 잡았습니다.
Keycloak Authorization Services가 가장 빛나는 영역은 UMA 기반의 사용자 주도 리소스 공유(Account Console 통합)와 IdP와 정책 관리의 단일화가 주는 운영 단순성입니다. 반대로 수백만 객체의 관계 질의가 핵심이라면 처음부터 ReBAC 엔진을 별도 레이어로 두는 편이 낫습니다.
운영 베스트 프랙티스
- PERMISSIVE로 시작해 ENFORCING으로: 기존 서비스에 도입할 때는 enforcement mode를 PERMISSIVE로 두고 거부 로그만 수집하며 정책 커버리지를 검증한 뒤 전환합니다.
- Evaluate 탭을 CI처럼: 정책 변경 시 대표 시나리오(소유자, 타부서, 비로그인, 시간 외)를 Evaluate API로 자동 검증하는 회귀 테스트를 두면 정책 사고를 크게 줄일 수 있습니다.
- 정책 명명 규칙:
policy-<대상>-<조건>식의 일관된 명명(예: policy-document-owner-only)이 없으면 수십 개 정책에서 길을 잃습니다. - export로 형상 관리: client의 authorization 설정은 JSON으로 export/import할 수 있습니다. 정책을 Git에 커밋하고 환경 간 승격(promote)하는 파이프라인을 구성하세요.
- JS policy 의존 제거: 업그레이드 경로에서 JS policy는 부채입니다. aggregated/regex/CIP 조합 또는 SPI 구현으로 대체 계획을 세우세요.
- audience 검증: RPT를 받는 서비스는 반드시 aud 클레임이 자신인지 검증해야 합니다. 다른 서비스용 RPT 재사용 공격을 막는 기본기입니다.
트러블슈팅 노트
| 증상 | 원인 후보 | 대응 |
|---|---|---|
| 모든 요청이 403 | enforcement ENFORCING + 경로 미매핑 | 경로 설정, PERMISSIVE로 격리 테스트 |
| 소유자인데 거부됨 | decision strategy가 Unanimous | Affirmative로 변경 또는 aggregated 재구성 |
| RPT에 permission이 비어 있음 | audience 누락, 리소스 미매칭 | audience 파라미터, 리소스 URI 패턴 확인 |
| 평가가 느림 | lazy-load 미사용, 리소스 과다 | lazy-load-paths, 타입 단위 리소스로 재설계 |
| 토큰이 너무 큼 | 전체 권한을 RPT에 포함 | permission 파라미터로 범위 축소, decision 모드 |
| 정책 변경이 반영 안 됨 | enforcer 캐시 | 캐시 TTL 확인, 재기동/무효화 |
마치며
Keycloak Authorization Services는 "권한 로직을 코드에서 꺼내 중앙에서 선언적으로 관리한다"는 목표를 OAuth/UMA 표준 위에서 구현한, 생각보다 깊이 있는 프레임워크입니다. resource/scope/policy/permission의 4분할 모델과 decision strategy를 이해하면 RBAC으로는 표현 불가능했던 요구를 우아하게 풀 수 있고, UMA 2.0의 permission ticket 흐름은 사용자 주도 공유라는 독자적 가치를 제공합니다.
동시에 한계도 분명합니다. 수백만 리소스의 관계 질의는 Zanzibar 계열 엔진의 영역이고, 인프라 전반의 범용 정책은 OPA의 영역입니다. 2026년의 현실적인 정답은 "Keycloak으로 인증과 coarse-grained를, 필요한 곳에 ReBAC/정책 엔진을 계층으로 얹는" 구성이며, 그 모든 계층의 입력이 되는 신뢰할 수 있는 토큰을 만드는 것이 Keycloak의 변치 않는 역할입니다. 다음 글에서는 Keycloak의 관측성 — 메트릭, 감사 로그, 이벤트 기반 모니터링을 다룹니다.
참고 자료
- Keycloak Authorization Services Guide
- Keycloak Documentation
- Keycloak 26.6.0 Release Notes
- UMA 2.0 Grant for OAuth 2.0 Authorization
- Federated Authorization for UMA 2.0
- RFC 6749 — The OAuth 2.0 Authorization Framework
- RFC 9700 — Best Current Practice for OAuth 2.0 Security
- RFC 8693 — OAuth 2.0 Token Exchange
- Open Policy Agent Documentation
- OpenFGA Documentation
- Google Zanzibar Paper
- OAuth 2.1 Draft