이전 포스트에서 예고한 대로 이번에는 기본 권한과 메타 권한에 대해 포스팅해 보고자 합니다.
구 워드프레스에는 회원들의 권한을 구분하기 위해 ‘레벨’이라는 개념을 사용했습니다. 예전 제로보드4 에서도 볼 수 있었던 개념입니다. 레벨 1부터 숫자가 높을 수록 권한이 낮아지는 방식의 권한 테이블 방식으로, 방법은 간단하나 썩 훌륭한 방법은 아니었습니다. 왜냐면 한 회원은 반드시 어떤 레벨에 종속되어 버리는 문제가 있고, 또 실제 운영에 있어서 권한의 높낮이보다 각기 회원의 세밀한 권한 설정도 중요할 때가 많은데, 이를 확장할 방법이 부족한 것이었죠.
워드프레스 2.0버전부터 새로운 개념인 역할과 권한(roles and capabilities)이 생겼습니다. 이 달라진 권한 개념은 레벨이라는 개념을 완전히 버리고 새롭게 디자인된 권한 설정입니다. 그럼 역할과 권한이 어떤 특성을 가졌는지부터 간단하게 설명해 보도록 할께요.
한때, 워드프레스는 사람들이 무료이고 쓰기 쉬워서 찾는 거지, 구식 개발이고 소스 코드도 알아보기 어렵고… 아무튼 이건 진짜 별로다. 이렇게 생각한 적이 있었습니다. 그러다가 생각이 바뀌게 된 계기가 있는데, 바로 역할과 권한(Role and Capability, 줄여서 RC) 체계를 접하게 된 것이었죠. 이후 워드프레스에 대한 평가가 긍정적으로 변했죠. 특히나 RC의 풍부한 표현은 정말 마음에 듭니다. 조금 어렵기는 해도, 사용자 레벨 같은 거와는 비교할 바가 아닙니다.
워드프레스는 CMS입니다. 단연코 콘텐츠의 관리와 유통에 있어 전문가입니다. 잘 뜯어보면 세심하게 배려한 부분이 정말 많습니다. 개발자 입장에서 볼 때 어떤 콘텐츠를 잘 관리하고 전파할 목적이라면, 어설프게 만들지 말고 워드프레스 써라고 충고하고 싶습니다. 10여년간 그들이 쌓아 올린 콘텐츠 관리에 대한 노하우는 만만한 것이 아닙니다.
사실 그동안 역할과 권한은 잘 쓰면 굉장히 멋진 것이 될 거라 생각은 해 왔습니다. 그러나 그 잘 쓰는 법을 여전히 잘 터득하지 못한 것 같았습니다. 물론 코덱스를 잘 읽으면 어지간한 정보는 습득할 수는 있지만 이것저것 만져보면서 직접 경험해보는 해킹(hacking)이 필요했습니다. 직접 좌충우돌하는 경험을 하고 싶었습니다. 그리고 이 포스트는 그 경험을 기록하기 위해 작성하는 것입니다.
User Role Editor 보다 더욱 세밀한 권한 체크를 진행시킬 수 있는 레시피. ‘user_has_cap’ 필터를 잘 활용하면 된다.
좀 더 구체적인 예로 설명을 하자. 만일 내가 포스트 아이디 1141번을 임시 글로 등록해 두었다고 가정하자. 그리고 단지 이 포스트에 대해서만은 editor들은 편집을 허용하지 않게 만들고 싶다. 그렇다면 다음처럼 코드르 만들 수 있다. 커스텀 포스트 타입은 ‘music_collection’이고 적절히 이에 따라 권한 세트를 생성했다.
콜백 함수는 4개의 인자를 가지고 있으며, 이 인자의 확인이 은근히 복잡하다. 디버깅 및 설명의 편의를 위해 하나의 if로 처리하지 않고 3개의 if로 잘라 넣었다. 실전 코드에서는 당연히 하나로 붙이도록 하자.
첫번째 if는 현재 요구되는 primitive 권한을 체크한다. 어떤 커스텀 포스트에서 요구하는 권한이 내가 제어하고 싶은 범위의 것인지를 검사한다.
두번째 if는 특정 단일 포스트에 대한 권한 요구인지, 아니면 전반적인 복수의 포스트에 대한 요구인지를 체크한다. args에 인자로 0번째는 매핑되기 전의 권한 템플릿 이름, 1번째는 유저의 ID, 2번째로 post의 ID가 있다. 이 부분이 매우 중요하다. 단일 포스트의 권한 검사이므로 args 길이는 3이상이어야 한다.
세번째 if에서 다시 사용자의 권한 체크를 한다. 지금 권한 체크에 대한 콜백 함수인데, 다시 권한 체크를 재귀적으로 부르고 있다. 권한 필터링을 실제 구현하는 것이 은근히 쉽지 않음을 짐작할 수 있다. 물론 익숙해지면 이야기는 다르겠지만, 주 역할과 메타 역할의 개념 등등을 잘 이해하지 못하면 이 권한 체크에 번번히 실패할 가능성이 높다. 재귀 함수의 오버헤드를 줄이려면 바로 $user->caps 를 활용할 수도 있다.
이렇게 설정하면, edtor들은 1141번 포스트에 대해 다음과 같은 화면을 만나게 된다.
특정 포스트를 특정 권한에게 접근 제한했을 때의 결과 예제 스크린샷
글에는 두 가지 draft가 있다. 첫번째 draft는 편집이 가능하지만, 두번째 draft는 접근이 막혀 있다. 이렇게 단일 포스트 단위로 접근을 제어하는 방법은 우리가 흔히 접할 수 있는 user role editor로도 쉽게 구현하기 어려운 기능이다. 게다가 코어의 자연스러운 접근 권한 체크를 하기 때문에 엉뚱한 곳에서 적당히 땜빵 코드로 접근을 막는 것보다 더욱 확실하고 자연스러운 제어가 가능하다. 스크린샷으로도 보이듯 접근 제어가 안 되는 항목은 확실하게 UI적으로도 막혀 있는 것이 보인다. 이렇게 구현하면 예상치 못한 URL로 접근하더라도 코어가 확실히 접근을 차단해 줌을 기대할 수 있는 것이다.
물론 보통은 커스텀 포스트에 이 정도로 세밀한 접근 제어 기능을 구현하지는 않으나, 이와 유사한 요구 사항은 실무에서 많이 발생할 수 있을 것이라 생각한다. 이걸 자유자재로 사용할 수 있다면 정말 훌륭한 플러그인 구현이 되리라 생각한다.
워드프레스의 역할과 권한은 잘 이해하는 사람도 흔치 않을 것 같다 코드가 지저분하든 더럽든 어쨌든 간에, 나는 워드프레스가 훌륭한 CMS라고 생각하며 그 근거 중의 하나로 이 강력하고 유연한 역할과 권한 시스템을 든다. 이걸 사용자가 쉽고 간편하게 쓸 수 있는 UI가 없는 것은 아쉽지만 (아니, 그런 UI를 쉽게 사용하게 만드는 것 자체가 미친 난이도지만) 이러한 시스템이 기저에 있다는 것 자체가 놀라움이다.
덧글 ) 권한 체크는 상당히 어렵다. 비활성화된 항목에 마우스를 가져다 대어 보자.
어이쿠, 이게 뭔가. Trash? 편집은 못하지만 지울 수는 있다. 편집자 역할은 휴지통에 있는 글도 영구 삭제 가능하다. 물론 같은 스태프끼리 그럴 일은 없겠지만… 아, 권한 체크는 세심해야 함을 강조한다. 해당 권한 목록을 꼼꼼하게 살펴서 이런 구멍이 없도록 잘 대비하기를 권한다.