강연자는 가상의 펫 관리 앱 ‘Potrax’를 통해 권한 시스템이 어떻게 진화하고 복잡해지는지 단계별로 설명하며, 일반적인 개발 과정에서 겪을 수 있는 문제점과 해결책을 제시합니다.
초기 단순 권한 관리의 함정
- 관리자 접근: 초기에는
user.is_admin?
과 같이 간단한 불리언 필드로 관리자 권한을 부여하는 경향이 있습니다. - 역할 기반 접근 제어(RBAC) 도입: 여러 보호자, 수의사 사무실 통합 등 요구사항이 증가함에 따라
owner_user_id
,caretaker_user_id
와 같은 역할별 컬럼을 추가하고 컨트롤러에서if
문으로 권한을 확인합니다. 특히 MongoDB와 같은 비관계형 데이터베이스에서 사용자 ID를 컬렉션에 직접 삽입하는 방식은 관계형 데이터의 유연성을 잃게 만듭니다. - 문제점: 이러한 방식은 컨트롤러를 복잡하게 만들고, 권한 로직이 여러 곳에 분산되어 가독성과 유지보수성을 저해하며, 시간이 지남에 따라 기술 부채를 가중시킵니다.
Pundit에서 영감을 받은 정책 기반 접근
user.can_update_medication?
과 같이 ‘사용자가 리소스에 대해 특정 작업을 수행할 수 있는가?’라는 질문에 답하는 코드를 목표로 합니다.- 정책 클래스 활용: Pundit과 유사하게
MedicationPolicy
와 같은 순수 Ruby 클래스를 만들어update
메서드 내에 역할 및 비즈니스 로직을 캡슐화합니다. 이는 컨트롤러를 깔끔하게 만들고 권한 로직을 중앙 집중화하는 효과를 가져옵니다.
엔터프라이즈 요구사항과 시스템의 한계
- 커스텀 역할 및 SKIM 연동: 엔터프라이즈 고객은 자체적인 커스텀 역할 정의와 SKIM(System for Cross-domain Identity Management)을 통한 사용자 프로비저닝을 요구합니다.
- 기존 시스템의 문제:
- 역할 모델링의 부재: 역할이 계정 컬렉션의 단순한 컬럼으로 존재하여, 동적인 커스텀 역할 추가가 불가능합니다.
- 하드코딩된 정책: 모든 권한이 정책 파일에 하드코딩되어 있어, 고객에게 권한 설정 UI를 제공하거나 메타데이터를 추적하기 어렵습니다.
- 비즈니스 로직 혼재: 정책 내에 너무 많은 비즈니스 로직이 포함되어 권한 검증이 복잡해집니다.
- 일관성 없는 권한 이름: ‘transfer_invites’와 같이 동사와 명사가 혼재된 권한 이름은 외부 이해 관계자에게 혼란을 줍니다.
미래를 위한 권한 시스템 설계 원칙
- 유연한 데이터 모델: 단순한 역할 컬럼 대신
Member
와 같은 별도의 모델을 사용하여User
,Account
,Role
간의 관계를 명확히 하고, 역할 변경 및 메타데이터(추가/제거 시점)를 추적합니다. - 컨벤션 준수: CRUD 기반의 권한 명명 규칙(예:
can_update_medication
)을 따르고, 권한 로직에서 비즈니스 로직을 분리하여 순수성을 유지합니다. - 중앙 집중식 권한 정의: CanCan과 같은 Gem의
ability.rb
파일처럼 권한 정의를 한 곳에 모아 외부 서비스, 프론트엔드, 지원팀 등이 권한 구조를 쉽게 이해하고 활용할 수 있도록 합니다. - 성공을 가정하고 설계: 애플리케이션이 성공하여 확장될 것을 가정하고, 초기부터 유연하고 확장 가능한 권한 시스템을 구축하여 미래의 기술 부채를 줄여야 합니다.