ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Vue] 유저 권한 및 로그인 여부에 따른 페이지 접근 설정(feat. Pinia)
    Vue 2023. 8. 14. 02:09

    Vue.js의 공식 Store인 Pinia이다.

     

    회사에서 프로젝트를 진행하면서 다양한 권한 별로 페이지 접근을 설정할 일이 많아졌다. 단순히 접근을 하고 안하고를 떠나서 권한에 따라 보여줘야할 컴포넌트가 달라질 때가 많았다. 그뿐 아니라 로그인 여부에 따라 개별 페이지에서 접근 여부가 달라지기도 했다. 그러한 부분들은 나는 Pinia라는 전역 상태관리 라이브러리를 활용하여 해결하였고 코드와 함께 간단히 공유하고자 한다. 저 귀여운 파인애플이 로고이다.

     

    먼저 나의 경우에는 로그인 여부에 따라 달라지는 접근 권한과 로그인 이후의 사용자별 권한이 크게 나뉘었다. 로그인 이후에는 권한이 크게 일반 사용자 권한과 관리자 권한이 있었고, 관리자 내부에서도 3가지 권한이 존재했다. 이러한 것들을 알기 위해서는 가장 먼저 쿠키에 저장된 유저 정보가 있는지 체크해야했다. 로그인을 한 이후라면 쿠키에 권한 설정을 비롯한 다양한 유저 정보들을 담아두기 때문이다. 그런데 수많은 페이지와 컴포넌트에서 권한 등이 포함된 유저 정보를 얻고자 하기 때문에 그때마다 쿠키 값을 조회하는 코드를 짜는 것은 상당히 비효율적이다. 그러므로 가장 최상위 컴포넌트인 레이아웃 컴포넌트에서 쿠키값을 한번 조회하고 그 값을 전역 상태 관리로 저장함으로써 수많은 컴포넌트에서 쉽게 가져다 쓸 수 있도록 하였다.

     

    const $q = useQuasar();
    const store = useLoginState();
    const { loginInfo } = storeToRefs(store);
    loginInfo.value = $q.cookies.get('user');

     

    위의 코드를 가장 최상단 컴포넌트의 setup 함수에 추가했다. 함께 사용하고 있는 퀘이사의 경우 쿠키 값을 비교적 쉽게 가져다가 쓸 수 있도록 하는 플러그인을 제공하여 사용하였다. 이렇게 최상단 컴포넌트에서 전역 상태 관리를 진행하므로 새로고침을 하더라도 전역 상태가 계속해서 유지되는 장점이 있다.

     

    관리자 페이지의 경우에는 로그인을 하지 않은 유저와 유저 권한(userlevel)이 관리자가 아닌 유저를 막아두는 것이 필요하다. 물론 대부분의 관리자가 아닌 유저들을 관리자 페이지 버튼이 노출되지 않으므로 진입할 수 없지만, 로그인이 만료된 경우나 url을 통해 접근하는 경우에 페이지 접근을 막아야하기 때문이다. 아래의 코드는 관리자 페이지의 레이아웃 컴포넌트로 해당 사항들을 구현해보았다. 참고로 userlevel에는 4가지의 권한이 있는데 그 중에 10 초과의 userlevel만 관리자에 해당한다.

     

    <template>
      <q-layout
        v-if="loginInfo !== null"
        view="lHh Lpr lff"
        container
        style="height: 100vh"
        class="shadow-2 rounded-borders"
      >
        <manager-drawer v-if="loginInfo.userlevel > 10" />
    
        <q-page-container v-if="loginInfo.userlevel > 10">
          <q-page padding>
            <router-view />
          </q-page>
        </q-page-container>
      </q-layout>
    </template>
    
    <script>
    import { storeToRefs } from "pinia";
    import { useQuasar } from "quasar";
    import ManagerDrawer from "src/components/drawer/ManagerDrawer.vue";
    import { useLoginState } from "src/stores/loginState";
    
    export default {
      components: {
        ManagerDrawer,
      },
      setup() {
        const $q = useQuasar();
        const store = useLoginState();
        const { loginInfo } = storeToRefs(store);
        loginInfo.value = $q.cookies.get("user");
    
        // 로그인을 안한 경우
        if (loginInfo.value === null) {
          if (window.confirm("로그인이 필요한 서비스입니다. 로그인하시겠습니까?")) {
            return window.location.replace("/user_service");
          } else {
            return window.location.replace("/");
          }
        }
    
        // 로그인은 했지만, 연구원인 경우
        if (loginInfo.value !== null) {
          if (loginInfo.value.userlevel === 10) {
            window.location.replace("/");
            return alert("관리자만 접근이 가능한 페이지입니다.");
          }
        }
    
        return {
          loginInfo,
        };
      },
    };
    </script>
    
    <style lang="sass" scoped></style>

     

    먼저 미리 최상단 컴포넌트에서 저장해놓은 loginInfo 전역 상태를 확인한다. 만약 로그인을 하지 않았다면 쿠키에서 user라는 키에 저장된 값이 없을 것이므로 loginInfo가 false가 될 것이다. 이 값이 false일 때 접근하지 못하도록 alert와 이전 페이지로 돌아가도록 router 처리를 하였다.

     

    또한 template 태그 안에 모든 태그를 감싸고 있는 가장 바깥 layout 태그에 v-if 설정을 하여 아예 html조차 보이지 않게 하였다. 왜냐면 alert와 이전 페이지로 돌아가도록 하는 처리를 하여도 html이 먼저 보여 문제가 될 때가 있기 때문이다. 특히나 관리자 페이지의 경우에는 일반 유저나 권한이 없는 사용자가 url을 입력하여 접근했을 때 기밀인 사항이 나타나있는 html이 조금이라도 노출되면 안되기 때문이다.

     

Designed by Tistory.