이 글에서 얻는 것

  • 인증(Authentication)과 인가(Authorization)를 분리해서 설계해야 하는 이유를 실무 장애 사례 관점으로 이해합니다.
  • RBAC, ABAC, ReBAC를 단순 정의가 아니라 팀 규모·도메인 복잡도·성능 예산 기준으로 선택할 수 있습니다.
  • 정책 엔진(애플리케이션 내장 또는 외부 PDP) 도입 시 필요한 수치 기준(지연시간, 캐시 전략, 장애 대응 우선순위)을 가져갑니다.
  • “정책이 늘어나면 유지보수가 무너진다”는 문제를 피하는 운영 패턴(버전 관리, 테스트, 롤아웃)을 익힙니다.

핵심 개념/이슈

1) 인가를 늦게 다루면 왜 비용이 폭증할까

초기 서비스는 보통 “로그인됐으면 허용”으로 시작합니다. 사용자 수가 적고 도메인이 단순하면 버틸 수 있습니다. 문제는 기능이 늘어날 때입니다.

  • B2B에서 고객사별 권한 요구가 분기됨
  • 관리자/운영자/파트너 역할이 서비스마다 다름
  • 데이터 접근 범위가 조직, 프로젝트, 문서 단위로 세분화됨

이때 인가를 서비스 코드 곳곳의 if (isAdmin) 형태로 흩뿌려 두면, 정책 변경 한 번에 수십 파일을 수정해야 합니다. 실제로는 버그보다 더 무서운 문제가 생깁니다. 정책 변경 속도가 비즈니스 속도를 따라가지 못하는 상태입니다.

실무에서 인가 체계는 “보안 기능”이면서 동시에 “제품 출시 속도”를 결정하는 아키텍처 요소입니다.

2) RBAC, ABAC, ReBAC를 어떻게 구분해야 하나

RBAC (Role-Based Access Control)

역할(Role) 중심 모델입니다. ADMIN, EDITOR, VIEWER 같은 역할을 부여하고, 각 역할에 권한을 매핑합니다.

  • 장점: 이해 쉽고 구현 빠름, 감사 로그 설명이 단순
  • 단점: 역할이 많아질수록 Role Explosion 발생
  • 잘 맞는 상황: 초기 SaaS, 단순 조직 구조, 정책 변경 빈도 낮음

ABAC (Attribute-Based Access Control)

사용자/리소스/환경 속성(attribute) 조합으로 허용 여부를 판단합니다.

예: user.department == resource.department AND request.time in businessHours

  • 장점: 세밀한 제어 가능, 조건식으로 유연함
  • 단점: 정책 가독성/디버깅 난이도 증가
  • 잘 맞는 상황: 조직별 예외가 많고 규정 준수 요구가 강한 서비스

ReBAC (Relationship-Based Access Control)

사용자와 리소스의 관계 그래프를 기반으로 권한을 계산합니다.

예: “해당 문서의 소유자”, “같은 워크스페이스의 멤버”, “상위 프로젝트의 관리자”

  • 장점: 협업형 도메인(문서, 프로젝트, 소셜)에 자연스럽게 맞음
  • 단점: 관계 탐색 비용/캐시 설계가 중요
  • 잘 맞는 상황: 공유/초대/위임이 핵심인 제품

핵심은 모델의 우열이 아니라 도메인의 권한 변화 패턴입니다. 단순 CRUD 관리 시스템에 ReBAC를 과하게 쓰면 복잡도만 증가하고, 협업 서비스에 RBAC만 고집하면 예외 규칙이 폭발합니다.

3) 실무 의사결정 기준(숫자·조건·우선순위)

아래 기준은 팀이 빠르게 선택할 때 유용합니다.

  1. 정책 변경 빈도

    • 월 1회 이하: RBAC 우선
    • 주 1회 이상, 고객사별 예외 다수: ABAC 또는 Hybrid(RBAC+ABAC)
  2. 권한 판정 지연시간 예산

    • 동기 API p95가 150ms 목표라면, 인가 판정은 보통 p95 5~15ms 내에 들어와야 전체 예산 관리가 쉽습니다.
    • 외부 정책 엔진 호출 시 네트워크 왕복 포함 p95 20ms를 넘기면 캐시/사전계산 없이는 병목이 됩니다.
  3. 정책 수/예외 수

    • 정책 20개 미만, 예외 적음: 코드 내 선언형 정책도 가능
    • 정책 50개 이상, 팀 3개 이상이 정책 수정: 중앙 정책 저장소+리뷰 프로세스 필요
  4. 감사/규정 요구 수준

    • “누가, 왜 허용됐는지”를 설명해야 하는 도메인(금융/헬스케어)은 정책 결정 로그와 리플레이 도구를 우선 도입해야 합니다.

실무 적용

1) 단계별 도입 전략: 단일 모델 집착보다 Hybrid가 현실적

실무에서는 다음 순서가 실패율이 낮습니다.

  • 1단계: RBAC로 기본 뼈대 구성(역할 5~10개 이내)
  • 2단계: 예외 규칙만 ABAC로 분리
  • 3단계: 공유/협업 도메인에 ReBAC 도입

즉, 처음부터 전면 ABAC/ReBAC로 가는 것보다 “기본은 단순, 예외는 확장” 전략이 운영 난이도를 낮춥니다.

2) 정책 엔진 배치 패턴

패턴 A: 애플리케이션 내장 정책

  • 장점: 네트워크 오버헤드 없음, 디버깅 간단
  • 단점: 서비스별 정책 중복 가능
  • 추천: 초기/중소 규모, 정책 수 적음

패턴 B: 중앙 PDP(Policy Decision Point) + 로컬 캐시

  • 장점: 정책 일관성, 감사/버전 관리 유리
  • 단점: 장애 전파 위험, 캐시 불일치 대응 필요
  • 추천: 멀티 서비스 환경, 감사 요구 강함

운영 기준 예시:

  • 정책 조회 캐시 TTL: 30~120초
  • 캐시 미스 시 폴백 정책: 기본 거부(deny-by-default)
  • PDP 장애 시 읽기 전용 기능만 제한적으로 허용할지 사전 정의

3) 테스트 전략(정책 품질의 핵심)

정책은 코드보다 더 자주 깨집니다. 이유는 정책 변경이 비즈니스 요청으로 직접 들어오기 때문입니다.

필수 테스트 세트:

  • 허용 케이스(positive) + 거부 케이스(negative) 최소 1:1
  • 회귀 테스트: 기존 정책 변경 시 영향도 확인
  • 경계 테스트: 시간대, 조직 이동, 역할 변경 직후

권장 수치:

  • 핵심 정책(결제/정산/개인정보) 테스트 커버리지 90% 이상
  • 정책 변경 PR마다 최소 1개 이상 감사 로그 시나리오 추가

4) 운영 가시성: “왜 허용/거부됐는지"를 남겨라

관측 항목을 미리 정의해야 장애 대응이 됩니다.

  • authz.decision.allow_rate (역할/엔드포인트별)
  • authz.decision.latency.p95/p99
  • authz.cache.hit_ratio
  • authz.policy_version 태그

경보 기준 예시:

  • allow_rate가 평소 대비 ±20% 급변
  • p95 15ms 초과 5분 지속
  • cache hit 80% 미만 하락

트레이드오프/주의점

  1. 유연성 vs 설명 가능성
    ABAC/ReBAC는 유연하지만 “왜 허용됐는지” 설명이 어려워집니다. 운영/감사 관점에서는 설명 가능성이 낮아지면 오히려 리스크가 커집니다.

  2. 중앙화 vs 가용성
    중앙 PDP는 일관성이 강하지만 장애 시 전체 서비스가 영향을 받을 수 있습니다. 캐시·타임아웃·폴백 정책을 설계하지 않으면 단일 장애점이 됩니다.

  3. 정책 속도 vs 안전성
    제품팀이 즉시 정책을 바꾸고 싶어도, 승인 없는 실시간 배포는 위험합니다. 최소한 2인 리뷰 + 단계적 롤아웃(10%→50%→100%)을 권장합니다.

  4. Deny-by-default의 UX 비용
    보안상 안전하지만 오탐 거부가 늘면 사용자 불만이 커집니다. 거부 사유 메시지와 재시도/요청 플로우를 반드시 준비해야 합니다.

체크리스트 또는 연습

  • 내 서비스의 권한 모델을 RBAC/ABAC/ReBAC 중 무엇으로 시작할지, 변경 빈도 기준으로 결정했다.
  • 인가 판정 지연시간 예산(p95/p99)을 수치로 정의했다.
  • 정책 변경 프로세스(리뷰어, 승인 조건, 롤아웃 단계)를 문서화했다.
  • 정책 결정 로그에서 “누가/무엇을/왜”를 추적할 수 있다.
  • PDP 장애/캐시 불일치 상황의 폴백 정책을 테스트했다.

연습 과제:

  1. 현재 API 10개를 골라 인가 규칙을 표로 정리해보세요(역할, 속성, 관계).
  2. 역할이 15개를 넘는다면 Role Explosion 신호입니다. 공통 권한을 분리하고 예외만 속성 규칙으로 옮겨보세요.
  3. 인가 실패(403) 상위 5개 시나리오를 분석해 정책 문제인지 UX 문제인지 분리해보세요.

관련 글