사용자 권한 DB 모델링

1. 가장 심플한 모델

일반적으로 소규모의 웹프로그램이나 윈도우 어플리케이션에서 가장 간단하게 쓸수 있는 사용자 권한 DB 모델은 사용자 Entity와 사용자 그룹 Entity를 사용하여 나타내는 것이다.
사용자 권한 DB

사용자 그룹을 관리자와 일반사용자로 주로 나누고, 이에 따라 화면 디자인도 하고, 프로그래밍도 한다. 업무룰에 따라 약간의 그룹을 더 생성하고 만들면 된다.
이 모델의 가장 큰 단점은 그룹 Entity가 존재하지만, 실제 그룹에 입력되는 레코드는 초기 업무 분석시에 정해진다는 것이다. 그래서 그 값을 가지고 Hard Coding을 한다.
if userGroup = “Admin” then
어쩌구..
else
저쩌구..
똑똑한 고객 만나서 처음부터 명확하게 업무 분석이 이루어지면 해피하다. 그러나, 수년간 개발을 했지만, 그런 고객 거의 없다. 젤 짜증나는게, 프로젝트 마무리 부분에 “누구 누구가 있는데, 이 사람은 몇가지 메뉴만 보이게 해달라”, “우리 부서장님이 있는데, 그 분은 관리자화면이든 모든 화면을 보여주데, 실제 데이터 입력은 안 할 거니깐, 조회만 하게 해달라”

뭐 이런식의 요구를 해온다.
우리나라 개발자들 용감하다. 해달라는데 안해주랴! 그룹테이블에 그룹하나 만들고, 해당 페이지 찾아서 if문 하나 더 추가하고, 필요한 코딩한다. 한두명을 위한 거라면, 아예 아이디 찾아서 if문에 사용자 아이디 코드로 넣고 친다. 모 나도 그랬다. 프로젝트 막판에 그게 가장 최선이므로…
(* 우리나라 프로그래밍 소스를 제공해주는 책들이 이런식으로 모델링을 많이 해 놨다. 복잡하게 만들면 사용자들이 어렵기도 하겠지만, 순진한 초보개발자들, 책 저자가 써놨는데, 감히 바꿀 생각도 안하고 그냥 그대로 보고 배낀다. ^^;;)
그래도 이 모델은 가장 간단하므로, 개발 기간도 짧아지고, 아직도 가장 많이 사용하는 것 같다.

2. 조금 개선한 모습

사용자 권한 DB

기존의 그룹을 역할이라는 Entity를 두어 다대다 매핑을 했다. 한명의 사용자는 여러 역할 즉, 관리자와 일반사용자 역할을 동시에 할 수 있다. 하나의 아이디로 양쪽을 다 할 수 있어서 기존에는 관리자로 로그인 아이디와 사용자 로그인 아이디를 별도로 두어 운영하던 것을 하나로 할 수 있어서 조금은 개선된 모습이다.

그러나 여전히 개발코드에서는 정해져있는 역할(Role)을 If문으로 체크한다. 관리자에 의해 임의의 역할이 추가되거나 삭제는 불가능하며, 그런 요구가 있을 때에는 프로그램 코드를 수정해야 한다.

3. 역할 기반 사용자 관리

조금 더 개선을 해보면 다음과 같다. 역할기반 사용자 관리의 모습이다.

db_rolebase_model

사용권한 Entity를 추가하였다. 대부분의 어플리케이션에서 사용되는 모습과 유사하다. Mssql 혹은 oracle도 이와 유사하게 동작한다.
모든 프로그램은 사용권한(Permission)을 지정하여, 사용권한을 중심으로 개발한다.
예) if 사용자 have (select permission) then …
예) 게시판이 있을 경우, if 사용자가 게시판 등록권한을 가진다면..
프로그램 개발시 모든 권한은 세분화 되어 지정되며, 그 권한을 가지고 개발한다.

관리자화면에서 사용자 생성 시 정해진 역할을 부여하거나(일반적으로, 일반사용자와 슈퍼관리자 정도는 미리 생성해 둠) 새로운 역할을 만들어 역할에 권한을 부여해 사용자에게 할당할 수 있다. Mssql 엔터프라이즈 매니저에서 데이터베이스 하나 선택하고, 사용자 항목이나 역할 항목을 클릭하고 이것저것 해보면 알 수 있다.

이 모델의 장점은 인터페이스 화면이 동일한 경우, 사용자 계정 정책을 개발자가 아닌 관리자가 유연하게 적용할 수 있다. 가장 심플한 모델의 단점을 대부분 극복할 수 있다. 그렇다고 단점이 없는건 아니다.

이 사용자 권한 DB 모델의 사용시에 사용권한 코드 설계가 아주 중요하다.

어플리케이션의 기능중심으로 사용권한 코드를 생성하는 것이 일반적이다. Mssql의 경우 테이블에 대해 select, insert, update, delete 권한을 두어 개별적인 테이브에 대한 권한을 체크한다.

웹사이트의 경우, 이런식으로 권한을 세분화할 수도 있으나, 나는 세부권한을 묶어서 사용하는 것을 좋아한다.
게시판의 경우 로그인하지 않은 사용자는 게시판을 조회만 가능하다.
로그인한 사용자는 자신의 글에 대해 삭제권한과 글 등록, 수정권한을 가지고 있다.
관리자는 모든 글에 대해 삭제권한과 로그인한 사용자 권한을 가지고 있다.
이 경우 게시판에 3가지 권한 board_logout_user, board_login_user, board_admin으로 구분하여 권한을 만들고 이 사용권한에 따라 개발하기를 좋아한다. 이렇게 권한을 만들 경우 또다른 문제점이 발생하는데, 웹서버 관리자가 관리자화면에서 사용자에게 권한을 부여할 때 각 개별 권한이 배타적인것과 상호보완적인 것이 존재하게 된다.

즉 위의 게시판 권한 중 등록, 수정, 삭제, 조회, 답글 이런식으로 권한을 부여하면 권한체계는 복잡하나 관리자가 임의로 권한을 부여하기가 편리하다. 하지만 board_login_user, board_admin 권한의 경우 한명의 사용자는 2개의 권한 중 하나만 부여 받아야 한다. (게시판의 경우에는 board_admin 권한이 board_login_user권한을 포함하고 있기 때문에 실제 사용자에게 2개의 권한을 모두 부여하여도 문제될 것은 없다. 하지만 경우에 따라선 완전히 배타적으로 처리되어야 할 권한도 존재한다.)

사용권한코드 컬럼 데이터 타입에 대해서도 고려해보자.

사용권한코드 컬럼의 값은 여러가지로 지정하는데, 사이트가 간단하다면, bigint 나 int 로 데이터 타입을 만들고, 각각을 2의 배수로 설정하면 사용자가 로그인할 때 가지고 있는 권한 리스트의 전체 비트합을 리턴하여, 메모리에 담고 있으면, 각 화면에서 제어하기가 간단해질 수 있다..

즉 한명의 사용자가 login, board_admin, account_admin 권한을 가지고 있다고 생각해보자.
login 00000001
board_admin 00000010
account_admin 00000100

데이터가 권한 테이블에 이렇게 들어 있다면, 사용자가 가지고 있는 권한 정보는 각 권한의 비트합으로 00000111이 된다. 화면 제어나 권한 제어 모듈에서 간단한 비트 연산으로 각 기능에 대해 권한이 있는지 없는지 체크하는 함수를 만들어 사용하고, 웹환경이라면 이 비트정보를 쿠키에 저장하여 사용한다면, 괜챦을 것이다.
그러나 mssql의 경우 bigint가 2의 63승 -1이다. 즉 전체 63개의 권한 밖에 설정할 수가 없다. 복잡한 시스템의 경우, 처리하기가 곤란하다. 그래서 문자열로 컬럼을 만들어서 실행시 숫자형으로 변환해 비트연산을 하거나, 아예 문자형 자체를 가지고 처리하기도 한다.

나는 권한 그룹 Entity를 따로 만들어서 권한 그룹별로 각각 권한을 int형으로 만들어서 비트연산을 주로 한다. 어플리케이션에서 하나의 업무단위(웹에선 주로 메뉴단위)에 64가지의 사용권한이 넘질 않기 때문이다.

이 역할 중심 권한 모델의 단점은 웹환경에서 나타난다. 웹환경의 경우, 웹페이지 본문에서 사용자 권한 제어는 거의 위의 모델로 다 되지만, 문제는 메뉴가 문제이다. 전체 메뉴가 나타나고, 사용자 권한에 따라 메뉴를 클릭하였을 경우, “권한이 없습니다”란 메시지를 나타내면 문제가 없지만, 우리나라 대부분의 고객이 그런 것을 싫어하더라. 권한이 없는경우에는 아예 메뉴가 나타나질 않기를 바란다. 텍스트 메뉴의 경우 그나마 메뉴에 대해 접근권한을 별도로 만들어서 각 메뉴에 대해 View 권한이 있다면 화면에 보이게 하면 가능도 하다. 그러나, 요즘 대부분의 사이트는 이미지도 아닌, Flash 메뉴를 많이 사용한다. 물론 Flash도 가능하다. Action Script에 xml자료를 동적으로 생성해서 넘겨주어 해당 메뉴를 자동으로 생성하게 하면 된다. 하지만, 대부분의 웹디자이너들이 기존의 Flash의 Action Script부분은 거의 다른 사람 작업해놓은 것을 배껴서 작업하기 때문에 개발자가 원하는 기능을 자유롭게 개발해 줄 수 있는 사람은 그렇게 많지 않다.

또 다른 문제는 권한을 복잡하게 설정하면 시스템 성능에도 영향을 미친다는 것이다. 체크할 것이 많고 복잡하면 느려지는 건 당연지사 일터.

이런 단점을 보완하고자 시도해 본 것은 권한모델의 가장 심플한 사용자 그룹 Entity를 권한모델 설게에 추가하고, 메뉴부분은 사용자 그룹으로 그룹에 따라 메뉴파일을 별도로 생성해 놓은 후 제어문으로 화면을 생성하고, 웹페이지 내의 본문 영역은 사용자 접근권한(permission)으로 제어를 했다.
모델은 다음과 같다.

db_rolebase_model

이렇게 해서 실제로 위의 모델을 사이트에 적용했었다. 현재도 운영중인 사이트인데, 메뉴와 페이지내의 권한을 별도로 관리하여 개발을 하니, 개발자의 혼동의 어려움이 있었고, 엔드유저의 특이한 요구사항이 있을 시 권한부분은 쉽게 관리자 화면에서 적용이 되나, 메뉴의 적용이 안되어 메뉴부분만은 추가로 수정을 해야 하는 단점도 있었다.

또 다른 사이트(꽤 큰 공공사이트임)에서는 위의 모델에 윈도우의 계정관리 처럼, 사용자에게 사용자 권한을 반드시 역할을 통해서만 부여하는 것이 아니라, 사용자 개인에게도 직접 부여가 가능하도록 하는 기능을 추가 하였다. 윈도우 서버의 계정은 역할(즉 그룹)이 여러종류가 있다. 로컬 그룹, 도메인 그룹 등 그리고 각 그룹은 그룹을 포함할 수 있고, 사용자는 그룹에 포함이 되며, 그룹에 있는 권한과는 별도로 각 사용자에게 직접 권한의 부여도 가능하다. Mssql이 아니고 오라클이라면 OODB의 특성을 조금 부여해 이런 기능을 구현도 가능하겠지만, 일반적인 어플리케이션에서 그정도 복잡한 사용자 관리 모델은 필요도 없을 것 같아. 단지 사용자에게 직접적으로 권한을 부여할 수 있도록 기능만을 추가하였다.

db_rolebase_model

위의 모델을 보면 사용자가 로그인 할 때 사용자 역할을 통한 사용자 권한과 사용자 권한 양쪽에서 쿼리를 해서 정보를 가져와야 한다. 그래서 물리모델에서 사용자 역할 Entity부터 조인하여 사용자 권한을 가져오는 것과 사용자 권한을 직접 쿼리하는 문장을 union하여 쿼리하는 view를 따로 생성한 후 실제 어플리케이션에서 이용하였다.

 

댓글 남기기