Closure Table을 이용한 File Authority 적용기 본문
File에 권한 체계를 적용하는데 사용한 closure table을 소개하고, 적용한 사례를 소개합니다.
파일 구조를 만들면서 가장 걱정되었던 부분은 어떻게 authority를 적용시키느냐 였습니다.
파일 구조는 태생적으로 계층구조를 띄게 되고, 상위 파일의 권한에 영향을 받을 수 밖에 없으니까요.
RDB는 이런 계층 구조를 나타내기에 적합하지 않기도 해서 다양한 방법들을 고민했습니다.
여기서 parent-child 기법을 사용해서 파일 시스템을 구성했는데… 문제는 다음과 같았습니다.

폴더 아래에 파일이 있습니다. 사용자는 폴더에 대해 update 권한을, 파일에 대해 read 권한을 가지고 있습니다.
이런 경우 사용자는 파일에 대해서도 update를 할 수 있어야 합니다.
즉, 한 파일이나 폴더에 대한 권한은 그 위에 모든 폴더들의 권한을 뒤져 max를 가져와야 합니다.
상위 1계층에 대해서만 권한 확인을 하면 참… 쉬웠겠지만, 더 상위에 있는 폴더의 권한들을 모두 봐야 하는 상황 이였습니다.
재귀적 쿼리를 통해 모든 부모를 가져올 수는 있습니다.
set @id := 26; -- node id
set @L := 0;
SELECT @r AS _ID
, (SELECT @r := pid FROM t_test WHERE id = _ID) AS _PARENT_ID
, (@L := @L + 1) AS level
FROM ( SELECT @r := @id) AS vars, (SELECT * FROM t_test WHERE id < @id) AS h
WHERE @r <> 0;
하지만, jpa를 사용하는 BE 입장에서는 native 보다는 queryDsl을 사용하고 싶은데… 이건 queryDsl로 짤 수도 없을 뿐더러, authority table을 join 시키는 것도 문제였습니다.
단순하게 보자면 “어떻게 하면 내 상위에 있는 모든 파일을 한번에 쿼리하고, 여기에 Authority를 join할 수 있을까?” 를 해결하면 쉬운 문제였습니다.
이를 해결하기 위해 closure table을 도입했습니다.
What is closure table?
Closure table은 Anti-pattern 입니다.
Releation을 통해 부모-자식 관계를 엮는게 아니라, 데이터로서 이를 관리하기 때문입니다.
어? 부모-자식을 데이터로 관리한다? 어떻게 하는 걸까요?

위와 같은 파일 구조가 있습니다.
클로저 테이블에서는 아래와 같이 계층 구조를 저장합니다.

Ancestor에는 부모를, Desendant는 자식을, Depth는 부모-자식간의 depth를 정의합니다.
특징은, 자기 자신에 대한 데이터 또한 저장한다는 것입니다.
이런 테이블이 있을 때, 4번에 대해 모든 부모를 가져오고 싶다면 어떻게 해야 할까요?
SELECT ancestor
FROM closure_table
WHERE descendant = 4;

즉, 자식으로 4를 가진 부모를 모두 쿼리해오면….! 바로 4의 모든 부모를 가져올 수 있습니다.
심지어 depth를 조건에 포함시켜 위/아래로 특정 위치에 있는 부모/자식을 가져오는 것 또한 매우 편합니다.
Why closure table 도입?
우리가 사용하고 있는 authority DB를 아래와 같이 가정해봅시다.

각 유저가 어떤 리소스에 대해 어떤 권한을 가지고 있는지 알 수 있습니다. (1번 유저: 파일 1,4 번에 대해 각각 Admin 권한과 read 권한)
이 테이블에 resource sn == ancestorSn 조건과 decendant == 4를 걸어 join 하면 어떻게 될까요?
SELECT *
FROM authority
JOIN closuer_table
ON resource_sn = ancestor_sn
WHERE decendant = 4;

다음과 같이 4번 파일 상위에 있는 모든 파일중에 권한이 있는 것들의 정보를 한번에 쿼리해옵니다!
여기서 max( authority_type )을 하면 1번 사용자가 4번 파일에 대한 최종 권한을 확인할 수 있습니다!
2번 파일에 대한 권한정보가 없어도 알아서 최상위 파일에 대한 권한까지 뒤져서요!
어마어마 하지 않습니까?
재귀나 특정 SQL 문법을 사용하지 않아 QueryDsl 로 짤 수 있다는 장점 또한 있습니다.
단점
장점만 있는 기술은 없듯이 단점또한 큽니다.
- 테이블이 한 개 더 필요하다.
- 파일이 추가될 때마다 클로저 테이블에 추가할 데이터가 크게 늘어난다.
- 파일 이동에 따른 클로저 테이블 업데이트가 어렵다.
- 파일 삭제시 클로저 테이블 데이터를 삭제해야 한다.
하지만, 권한 확인이 파일 수정/삭제 보다 훨씬 많은 빈도로 발생하기 때문에 클로저 테이블을 선택했습니다.
요약
- 파일 하나에 대한 권한 확인이 아닌, 파일 상위의 모든 권한을 확인해야 하기에 클로저 테이블을 도입했다.
- 파일 이동 / 파일 삭제 에 대한 코스트가 많이 들어가지만, authority 확인에 대해 이득이 훨씬 크기에 클로저 테이블을 도입했다.
'ETC' 카테고리의 다른 글
RDBMS 에서 tree structure 다루기 (0) | 2025.03.17 |
---|---|
[Java] StringBuilder 주요 메소드 (0) | 2025.01.21 |
Cursor AI 사용기 (9) | 2024.11.07 |
MST (Minimum Spanning Tree) 최소 신장 트리 (0) | 2022.04.07 |
벨만포드 알고리즘 (0) | 2022.04.05 |