permissions-dsl

1 개의 포스트

figma

Figma에서 커스텀 권한 (새 탭에서 열림)

Figma는 기존 Ruby 모놀리스의 `has_access?` 메서드에 모든 권한 로직을 집중시킨 결과, 복잡성·디버깅 난이도·계층형 권한의 한계·데이터베이스 부하 문제에 직면했다. 이를 해결하기 위해 자체 권한 도메인 특화 언어(DSL), 크로스플랫폼 권한 로직 엔진을 구축하고 핵심 권한 규칙을 새 시스템으로 이전했다. 목표는 권한 정확성과 성능을 높이는 동시에 개발자가 안전하게 권한 규칙을 변경할 수 있도록 만드는 것이었다. ## Figma의 권한 모델 - Figma의 협업 기능은 파일과 폴더, 팀, 조직 단위의 복잡한 권한 구조를 필요로 한다. - 파일 접근 방식은 크게 두 가지다. - **역할 기반 접근**: 상위 폴더·팀·조직에서 상속된 역할에 따라 접근한다. - **링크 기반 접근**: 링크를 가진 사용자의 접근 수준, 만료 기간, 비밀번호, 조직 정책 등을 조합해 결정한다. - 파일 삭제 여부, 계층 구조, 조직 제한, 결제 상태 등도 접근 가능 여부에 영향을 준다. - 기존에는 각 ActiveRecord 모델의 `has_access?` 메서드가 사용자와 리소스를 받아 접근 가능 여부를 boolean으로 반환했다. ## 기존 `has_access?` 방식의 한계 - 권한 판단에 필요한 모든 비즈니스 로직이 하나의 긴 메서드에 들어갔다. - 제품 엔지니어가 컨트롤러에서 이 메서드를 적절한 시점에 직접 호출해야 했다. - 작은 변경도 전체 권한 체계에 영향을 줄 수 있어 개발자들이 메서드 수정 자체를 꺼리게 됐다. - 권한 버그는 Figma의 모든 파일에 대한 접근 허용으로 이어질 수 있어 위험성이 컸다. - 디버깅 시 특정 규칙만 분리해 확인하기 어려웠고, 수십 개의 로그를 코드 곳곳에 추가해야 했다. ## 계층형 권한과 boolean 플래그의 문제 - 권한 수준을 정수로 표현했지만, 실제 동작은 여러 boolean 플래그에 의해 달라졌다. - 예시 메서드는 다음과 같은 선택적 인자를 포함했다. - `ignore_link_access` - `org_candidate` - `ignore_archived_branch` - 같은 권한 수준이라도 플래그 조합에 따라 결과가 달라져 개발자가 이해해야 할 경우의 수가 많았다. - 리소스마다 플래그의 의미와 동작이 달라 일관된 권한 모델을 만들기 어려웠다. - 예를 들어 `300` 수준의 편집 권한은 있어도, 특정 조건을 무시한 `100` 수준의 보기 권한 검사는 통과하지 못할 수 있었다. - 따라서 기존 계층 구조만으로는 표현하기 어려운, 서로 독립적인 세밀한 권한이 필요했다. - 새로운 시스템은 기존 계층형 권한을 지원하면서도 비계층적이고 독립적인 권한 체계를 추가할 수 있어야 했다. ## 권한 검사로 인한 데이터베이스 부하 - Figma의 사용자와 리소스 규모가 빠르게 증가하면서 권한 검사가 데이터베이스에 큰 부담을 줬다. - 전체 데이터베이스 부하 중 약 **20%**가 권한 검사에서 발생했다. - 데이터베이스를 수직·수평 확장하는 것만으로는 물리적 한계가 있었기 때문에, 권한 로직 자체가 데이터 계층에 가하는 부하를 줄여야 했다. - 새로운 권한 시스템에는 권한 데이터를 어떻게 조회하고 처리할지에 대한 더 세밀한 제어가 필요했다. ## 자체 권한 DSL과 로직 엔진 - Figma는 외부 솔루션을 우선 검토하는 일반적인 방침과 달리, 권한 문제에는 자체 시스템을 선택했다. - 구축한 구성 요소는 다음과 같다. - 권한 규칙을 명확하게 표현하는 **도메인 특화 언어(DSL)** - 여러 환경에서 동작하는 **크로스플랫폼 권한 로직 엔진** - 기존의 핵심 권한 규칙을 새 시스템으로 이전하는 마이그레이션 체계 - 이를 통해 권한 규칙을 하나의 거대한 조건문으로 관리하지 않고, 독립적이고 조합 가능한 규칙으로 다룰 수 있게 하는 것이 목표였다. - 결과적으로 권한 로직을 제품 기능과 분리하고, 규칙 추가·수정·삭제 시 기존 권한 체계를 모두 다시 이해해야 하는 부담을 줄이려 했다. ## 실용적인 결론 복잡한 권한 시스템에서는 단순한 `if/else` 함수와 호출 규약만으로 규모 확장을 감당하기 어렵다. 권한을 독립적인 규칙으로 모델링하고, 선언적인 DSL과 공통 실행 엔진을 사용하면 정확성·성능·개발자 경험을 함께 개선할 수 있다.