ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [VueJS] 적응형 모바일 - 태블릿 멀티 디바이스 환경 구축기 (구조 편)
    frontend/vue&nuxt 2022. 4. 5. 17:10

    오늘은 제가 작년 이 맘때쯤 진행했던 Vue 멀티 디바이스 환경 프로젝트에 대해서 얘기해보려고 합니다. 일단 제게 주어진 상황은 다음과 같았습니다.

     

    1. 짧은 개발기간
    2. 재구축건으로 AS-IS가 있음
    3. 프론트엔드 개발자 단 1명..(본인)..분량 많음
    4. 반응형 웹이 아닌 적응형 웹으로 분기 ( 모바일과 태블릿의 화면 depth 차이)

    이러한 상황이였기 때문에 최대한 빠른 시간내에 정확히 많은 양을 처낼 수 있는 방법이 필요했습니다. 위와 같은 조건으로 인해 반응형으로도 개발할 수 없었기 때문에 저는 다음과 같은 방법을 생각했었습니다. 이 방법이 정답이 아니며 그냥 여러 방향중 가능성 있는 하나 정도로 보시면 될 것 같습니다. 그럼 제가 진행했던 방식과 그렇게 진행한 이유에 대해서 천천히 살펴보도록 하겠습니다.

    1. 라우팅 분기

    가장 먼저 작업이 필요한 부분은 라우팅 분기입니다. 저는 가장 최상단 컴포넌트인 App.vue 컴포넌트에서 분기 시켰습니다. 코드는 아래와 같이 작성하였습니다.

    //App.vue
    <template>
      <div id="app">
        <router-view v-if="!isMobile"/>
        <router-view v-else name="mobile"/>
      </div>
    </template>
    <script>
    export default {
      name: "App",
      data: () => ({
        isMobile:false,
      }),
      mounted(){
        this.onResize();
        window.addEventListener('resize',this.onResize,{passive:true});
      },
      beforeDestory(){
        if(typeof window === 'undefined') return;
        window.removeEventListener('resize',this.onResize,{passive:true});
      },
      methods:{
        onResize(){
          this.isMobile = window.innerWidth < 600
        }
      }
    }
    </script>

    위와 같이 디바이스의 크기별로 다른 화면을 보여줘야 되었기 때문에 제일 상단 컴포넌트에서 분기를 시켜주었습니다. 위의 코드는 mounted시점에 onResize 이벤트를 등록하고 resize시에 onResize를 다시 해서 mobile일때는 모바일화면을 태블릿일때는 태블릿 화면을 보여주도록 하였습니다. 그 후 라우터에서는 다음과 같이 작성하면 됩니다.

    import Vue from 'vue';
    import Router from 'vue-router';
    
    Vue.use(Router)
    
    const routes = [
      {
        path: '/',
        component: {
          default:() => import('@/views/Tablet.vue'),
          mobile:() => import('@/views/Mobile.vue')
        }
      }
    ]
    
    export default new Router({
      routes: routes,
    });

    위와 같이 name이 mobile인 router-view는 mobile컴포넌트와 매칭이 되고 그 외에는 default컴포넌트와 매칭이 되게 작성을 합니다. 당시에 vue-router가 3버전이였어서 현재는 선언부가 조금 달라질 것입니다. routes내는 같습니다. 이까지 오셨으면 기본적인 라우팅 분기는 끝이 났습니다. 이제 상태관리와 공통 함수등을 어떻게 이용할지에 대해서 고민을 해보아야 할 시간입니다.

    2. 화면과 메소드의 분리

    이런 멀티 디바이스 환경 구축을 할때 특히, 적응형 웹으로 개발을 하게 될 시에 다 따로 개발을 하게 되면 화면에 따라 중복되는 메소드를 두번 작성해야되는 케이스도 있을 것이고 데이터 관리 또한 상당히 귀찮아 질 수도 있습니다. 의미없는 반복 코딩이 생길수도 있습니다. 저는 그래서 이러한 상황을 최소화 하고 싶어서 당시에 아래와 같은 구조를 생각했습니다.

    위의 구조는 제가 당시에 진행했던 프로젝트 구조입니다. 업무 단위별로 태블릿과 모바일로 분기하고 태블릿은 common과 tablet 믹스인을 가지고 모바일은 common과 mobile 믹스인을 가지고 있으며 해당 화면의 상태는 vuex를 통해서 관리 하고 있었습니다. 공통으로 사용할 수 있는 부분을 최대한으로 공통으로 사용하고 추후 유지보수시 장애나 보수가 필요한 부분을 빠르게 대응하기 위해서 위와 같은 방식으로 작업하였습니다. vuex내부가 비대해지는 부분은 mount와 destory시점에 적절하게 데이터를 제어 한다면 크게 문제가 없다고 생각하여 진행하였었습니다. 실제 패키지를 보면 아래와 같은 방식으로 되어 있었습니다.

    사내 시스템이라 실제 패키지 구조를 들고 올순 없고 위와 같은 방식으로 구현하였습니다. 한 화면에 관한 API와 공통 믹스인들은 한 패키지내에서 유지보수 할 수 있도록 구성하였습니다. 

    //index.js
    export const mobile = {}
    export const tablet = {}
    export const common = {}

    index.js내부에는 위와 같이 mobile, table, common을 한군데서 관리하고 있었으며, 이런 믹스인 구성은 장단점이 있었는데 간단한 화면 같은 경우는 해당 파일 하나만 보아도 된다는 것이었고, 화면 복잡도가 조금 난해해진다면 안그래도 복잡한 화면에서 vue2의 optional은 되게 비대한 코드를 가질 수 밖에 없는데 그런 것이 3개로 나누어져 있어서, 더욱 복잡해지고 코드가 길어질 수 있는 단점이 있었습니다. 당시에 작업할 양이 엄청 많았고 이상하지만.. 프론트엔드는 저 혼자 였기 때문에 짧은 작업시간내에 최대한 보기 편하고 유지보수시에도 최대한 리스크가 작게 가져갈 수 있는 방법을 선택하였습니다. 실제 화면에서는 이러한 방식으로 되어 있다고 볼 수 있습니다.

    <script>
    import { common, tablet } from '..'
    export default {
        mixins: [common, tablet]
    }
    </script>
    <template>
        <div>태블릿</div>
    </template>

    위와 같은 방식으로 믹스인을 공통, 태블릿을 두가지를 동시에 상속받아 동작하고 mixin내부에서는 vuex를 통해 화면별로 상태를 관리하고 있었습니다. 이렇게 하라고 만들어 놓은것은 아닐테지만 개발 기간을 상당히 단축시킬 수 있는 방법이였습니다. 내부코드는 크게 보여드리지 못하고 이번에는 구조적인 부분만 말씀 드렸습니다. 다음에는 좀더 구체적으로 내부 소스코드와 상태관리는 어떻게 진행했었는지에 대해서도 글을 남겨보도록 하겠습니다.

     

    요즘 회사 내의 사이드 프로젝트, 개인 사이드 프로젝트로 인해 글 작성 빈도가 좀 줄어들었네요. 좋은 글로 돌아올 수 있도록 하겠습니다.

    반응형

    댓글

Designed by Tistory.