기본 권한과 메타 권한

이전 포스트에서 예고한 대로 이번에는 기본 권한과 메타 권한에 대해 포스팅해 보고자 합니다.

구 워드프레스에는 회원들의 권한을 구분하기 위해 ‘레벨’이라는 개념을 사용했습니다. 예전 제로보드4 에서도 볼 수 있었던 개념입니다. 레벨 1부터 숫자가 높을 수록 권한이 낮아지는 방식의 권한 테이블 방식으로, 방법은 간단하나 썩 훌륭한 방법은 아니었습니다. 왜냐면 한 회원은 반드시 어떤 레벨에 종속되어 버리는 문제가 있고, 또 실제 운영에 있어서 권한의 높낮이보다 각기 회원의 세밀한 권한 설정도 중요할 때가 많은데, 이를 확장할 방법이 부족한 것이었죠.

워드프레스 2.0버전부터 새로운 개념인 역할과 권한(roles and capabilities)이 생겼습니다. 이 달라진 권한 개념은 레벨이라는 개념을 완전히 버리고 새롭게 디자인된 권한 설정입니다. 그럼 역할과 권한이 어떤 특성을 가졌는지부터 간단하게 설명해 보도록 할께요.

역할과 권한

권한(capability)은 워드프레스에서 어떤 동작에 대한 허용을 말합니다. 보통 권한의 이름은 그 동작에서 따와 이름을 지어 두는데, 해당 권한이 없는 사용자의 동작은 실행되지 않도록 되어 있습니다. 예를 들어 권한 중 ‘switch_themes’라는 것이 있는데, 이것은 테마를 변경할 권한을 뜻합니다. 이 권한이 없는 사용자는 테마를 변경할 수 없겠죠. 코덱스를 참고하면 다양한 권한이 상세하게 나누어져 있는 것을 볼 수 있습니다. 그리고 권한은 자유롭게 확장 가능합니다. 없는 권한은 만들어 넣을 수 있습니다.

역할(role)은 권한의 모둠(preset)이라고 생각할 수 있습니다. 어떤 일을 관리할 사람들이 필요하지만 그 사람들이 필요 이상의 권한을 가져가게 하고 싶지는 않을 때 쓸 수 있습니다. 전체 최고관리자와 게시판별 관리자를 생각해 보면 쉽게 이해하실 수 있을 것 같네요. 또 권한 여부를 판별할 때 역할을 가지고도 판단할 수도 있습니다. 그러면 그 역할에 속한 사람만 작업을 진행할 수 있겠죠.

역할 또한 자유롭게 만들어낼 수 있습니다. 그리고 역할은 태깅과 비슷하여서, 한 사용자가 복수의 역할을 가지고 있을 수 있습니다. 사용자 ‘철수’에 ‘글쓴이’ 역할과, ‘회원 관리자’라는 역할(새로 만든 역할이겠죠)을 같이 부여할 수 있습니다. 그러면 철수는 다른 글쓴이처럼 글도 쓰지만, 회원 관리자의 역할도 가능합니다.

 

권한 판단

예를 들어, 사용자 ‘정원‘과 ‘시윤‘이 있습니다. 정원은 A 역할이고 시윤은 B 역할을 가지고 있다고 생각해 봅니다. A 역할은 x, y 권한을 묶은 것이고, B 역할은 x, z 권한을 묶은 거라고 합니다. 그렇다면 권한 체크는,

  • A 역할로 판단: 정원 (A역할이므로)
  • B 역할로 판단: 시윤 (B 역할이므로)
  • x 권한으로 판단: 정원, 시윤 (A, B 두 역할이 x 권한을 가짐)
  • y 권한으로 판단: 정원 (A 역할에만 포함)
  • z 권한으로 판단: 시윤 (B 역할에만 포함)
  • x, y, z 권한으로 판단: 없음 (둘 다 세 권한을 동시에 가지지는 못함)

이렇게 판단될 것입니다. 권한 판단 때 사용자는 제시된 권한을 모두 가지고 있어야 합니다. 단 하나라도 부족하면 안 됩니다.

 

기본 권한과 메타권한

워드프레스 사용 측면에서는 크게 중요한 것은 아니라 잘 설명되지 않지만, 워드프레스를 좀 더 여러 사람들이 복잡한 권한을 두고 작업을 해야 한다고 하며 반드시 이해햐 할 부분입니다. 아무래도 흔한 개념은 아니고, register_post_type() 같은 개발 수준의 문서에서나 언급되는 부분입니다. 그러나 저는 이 부분을 목적으로 포스팅을 한 번은 해 보고 싶었습니다.

기본 권한(primitive capability)은, 우리가 통상적으로 이해한 그 권한이라고 생각하면 됩니다. 사용자의 권한 여부에서 기준이 되는 그 기준들입니다. edit_posts, delete_posts 등등 보통은 복수형으로 표시됩니다(항상 그렇지는 않습니다).

메타 권한(meta capbility)은 기본 권한과는 반대로 주로 단수형으로 끝나는 권한들입니다. 예를 들어 커스텀 포스트와 관련된 메타 권한은 edit_post, read_post, and delete_post 셋을 대표로 들 수 있습니다. 메타 권한이 기본 권한과 다른 점은 ‘유동성’입니다. 쉽게 말해 메타 권한은 반쪽짜리 상태 권한이고, 이대로는 최종 권한 판단 과정에서 쓰이지 않으며, 문맥에 따라 기본 권한으로 변환되는 작업을 거칩니다. 그러므로 이 문맥에 따라 똑같은 메타 권한이라도 대응되는 기본 권한은 달라질 수 있습니다.

예로 edit_post 메타 권한을 들어 보죠. 이 메타 권한은 post로 단수형입니다. 말로 풀어 쓰자면 ‘사용자가 하나의 포스트를 편집할 수 있는가?’입니다. 이 질문에 바로 대답할 수가 없습니다. 문맥이 너무 부족합니다.

  • 사용자가 누구인지 뚜렷이 알 수 없습니다. 물론 현재 로그인한 사용자를 기본적으로 생각할 수는 있지만, 현재 사용자라고 단정할 수는 없습니다.
  • 어떤 포스트인지 명시되어 있지 않습니다. 현재 메인 쿼리에서 찾은 포스트일 수도 있지만, 역시 그 포스트라고 단정할 수도 없습니다.
  • 또한 포스트의 상태에 따라 답할 수 있는 결과는 다릅니다. 포스트의 저자, 상태, 기타 정보에 의해 영향을 받을 수 있습니다.

이것을 명확히 하기 위해 문맥 정보로 사용자와 포스트의 정보를 부가적으로 넣습니다. 그렇다면 다음과 같이 고려할 수 있겠죠.

  • 사용자와 포스트의 저자를 고려해 볼 수 있습니다. 사용자가 포스트의 저자라면 edit_posts 권한을 쓰겠죠. 다른 이의 포스트라면 edit_others_posts 권한을 필요로 할 겁니다.
  • 포스트의 상태도 고려해야 합니다. 만약 포스트가 발행된 상태라면 edit_published_posts 권한을 필요로 해야 할 겁니다. 만약 비공개 포스트라면 edit_private_posts나 read_private_posts 같은 권한을 필요로 하겠죠. 만약 휴지통에 있는 포스트를 고치려고 하면 막을 겁니다. 휴지통에 들어간 포스트는 편집 대상이 아니니까요.
  • 기타 액션 혹은 필터에 의해 이 정보는 추가될 수도 있습니다.

이렇게 문맥에 따라 메타 권한은 기본 권한으로 변환되어, 사용자가 그 기본 권한을 모두 충족하는지를 테스트 하는 것입니다.

사용자가 권한이 있는지 없는지를 판별하기 위해 user_can(), current_user_can() 함수를 사용합니다 여기의 인자로는 기본 권한과 메타 권한 둘다 입력이 가능하며, 메타 권한인 edit_post의 경우 판단이 되는 포스트의 ID를 추가 인자로 넣어야 합니다. 이렇게 되면 user_can(), current_user_can()에 의해 자동적으로 사용자를 파악할 수 있고, 추가 인자에 의해 대상 포스트를 알 수 있게 됩니다. 이것을 파악하는 함수는 map_meta_cap() 함수로, user_can(), current_user_can() 함수 내부에서 호출됩니다. 이 함수에 의해 메타 권한이 기본 권한 목록으로 변환됩니다.

 

메타 권한의 장점

워드프레스의 권한은 매유 유동적입니다. 역할도 확장 가능하고, 권한도 확장 가능하며, 메타 권한이라는 장치에 의해 문맥에 따라서 권한을 설정하는 일도 가능합니다. 메타 권한은 문맥 또한 필터에 의해 보다 확장될 수 있어 더욱 복잡한 권한 문제에도 효과적으로 대응할 수 있다는 장점이 있습니다.

예를 들어, 어떤 사이트의 포스트 카테고리에는 ‘연예” 카테고리와 ‘시사’ 카테고리가 있습니다. 그리고 각 카테고리별로 별도의 편집자를 두고 싶습니다. 연예는 연예 편집자 역할이, 시사는 시사 편집자 역할이 담당하게 하는 거죠. 그런데 이런 동작이 가능하게 하려면 기존의 동작만으로는 한계가 있습니다. 카테고리별로 권한을 제어하는 것은 그다지 일반적인 일은 아니기 때문입니다.

이 때 메타 권한을 활용하면 됩니다.

  1. 연예 카테고리, 시사 카테고리를 편집할 수 있다는 권한을 추가로 만듭니다.
  2. 해당 편집자들에게 각 권한을 부여합니다.
  3. ‘map_meta_cap’ 필터를 활용합니다. edit_post 권한 매핑 중 편집자가 연예/시사 카테고리 포스트를 접근하는 경우에 요구되는 권한을 덧붙이는 코드를 콜백으로 작성합니다.
  4. 코어가 알아서 사용자별로 필터합니다.

이렇게 메타 권한을 활용하면 edit_post라는 워드프레스가 만든 메타 권한에 의해 판별이 되기 때문에, WP-REST API, AJAX, RSS 피드 같은 관리자 화면 외 여러 사항에 대해 잘 대응할 수 있습니다. 특정 패턴에 의해 국지적으로 current_user_can()을 활용하는 법이나 권한 체크 로직을 별도로 짜는 것보다 훨씬 안전합니다. 권한은 일종의 보안입니다. 한편 메타 권한은 문맥에 따라 변할 수 있는 여지가 다분합니다. 예상치 못한 값에 의해 권한의 구멍이 뚫리는 일이 없도록 신중하게 고려하여 제작해야 함을 명심해야 합니다.

다른 방법

필터와 액션은 다양하기 때문에, 어떤 필터의 사용이 꼭 유일한 해결책은 아닙니다. user_has_cap 필터를 활용할 수도 있습니다. 이에 관해서는 제가 전에 작성한 레시피를 참고해 주세요.

 

마치며

이번 포스트에서는 기본 권한과 메타 권한에 대해 알아봤습니다. 나름 간단하게 설명을 작성할 수 있었던 것 같아 상쾌합니다. 그동안 이 개념과 저 개념이 뒤죽박죽되어 복잡하게 느껴졌는데, 적절히 잘 떼어 놓고 보니 그렇게 어렵지만도 않군요.

아, 저 스스로 알아보고 조사한 것을 기록하는 포스트이기 때문에 틀린 점이 있을 수 있습니다. 꼭 코덱스나 다른 참고 서적을 보고 교차 검증하도록 하세요.

댓글 1개

댓글 남기기