Vue.js에 관해 질문드립니다.

조회수 3547회

야무님 안녕하세요? IT회사에서 퍼블리셔로 근무중이며 프론트엔드로 넘어가고 싶은 일인입니다. 스크립트는 정말 어려운 거 같아요 ㅠㅠ 야무님 온라인 강의 들으며 이제 클로저의 개념을 이해할까 싶은데, 요즘은 react에 vue에 공부해야 할 게 너무 많은 듯 합니다.

예전에 패스트캠퍼스에서 Vue.js 강의를 들은 적 있는데, 정말 개념 정도만 익힌 수준입니다.

하지만 수업을 들으면서 궁금했던 부분이, Vue.js를 보면 컴포넌트 방식으로 다 나눠져서 templete 소스 아래에 css와 script가 인라인으로 들어가는데, 이렇게 하면 구조와 동작, 표현을 분리한다는 웹표준 기본 개념에 어긋나는 게 아닌가 싶습니다. Vue를 작성하면서도 css와 js를 분리하는 방법이 있는 건가요??

항상 감사드립니다.

  • (•́ ✖ •̀)
    알 수 없는 사용자

2 답변

  • 안녕하세요 yuna 님

    질문에 답변 드립니다. ^ ㅡ ^

    Q1

    Vue.js를 보면 컴포넌트 방식으로 다 나눠져서 templete 소스 아래에 css와 script가 인라인으로 들어가는데, 이렇게 하면 구조와 동작, 표현을 분리한다는 웹표준 기본 개념에 어긋나는 게 아닌가요?

    A1

    구조와 표현, 동작의 분리

    먼저 구조와 표현, 동작이 분리되어야 한다는 개념을 예제로 비교해봅시다.

    아래 코드는 구조, 표현, 동작이 한데 묶인 코드입니다. 이러한 코드는 복잡해 읽기 어렵고 중복이 많을 뿐더러 수정도 불편해 유지보수 문제를 일으킵니다.

    HTML+CSS+JavaScript

    <a 
      href="#point-312" 
      onclick="scrollAnimateTo(this.href)" 
      style="text-decoration: none; color: tan; font-size: 16px;"
    >312로 이동</a>
    
    <a 
      href="#point-471" 
      onclick="scrollAnimateTo(this.href)" 
      style="text-decoration: none; color: tan; font-size: 16px;"
    >471로 이동</a>
    

    반면 아래 코드는 구조, 표현, 동작이 분리된 코드입니다. 각 역할별로 관심사의 분리가 잘 이루어져 코드의 복잡성과 중복이 없습니다. 그리고 유지보수에도 용이합니다.

    관심사의 분리(SOC, Seperation Of Concerns)란?

    프로그래밍의 기초 개념으로 관심이 같은 것 끼리 하나의 객체 안으로 또는 친한 객체로 모이게 하고, 관심이 다른 것은 가능한 따로 떨어져서 서로 영향을 주지 않도록 분리하는 것을 말합니다.

    HTML

    <a href="#point-312" class="scroll-link">312로 이동</a>
    <a href="#point-471" class="scroll-link">471로 이동</a>
    

    CSS

    .scroll-link {
      text-decoration: none; 
      font-size: 16px;
      color: tan;
    }
    

    JavaScript

    function scrollAnimateTo(targetId) {
      // ...
    }
    
    document.querySelectorAll('.scroll-link')
      .forEach(link => 
        link.addEventListener('click', e => 
          scrollAnimateTo(e.target.getAttribute('href'))
        )
      )
    

    Vue 컴포넌트 파일과 "관심사의 분리"

    그렇다면? 컴포넌트 중심 개발을 지향하는 Vue.js의 싱글 파일 컴포넌트(SFC, Single File Component)는 "관심사의 분리" 개념에 어긋난 것 일까요?

    Vue.js 문서를 살펴보면 이 부분에 대해 기술한 내용이 있습니다. 같이 살펴보죠.

    관심사의 분리는 무엇입니까?

    주목해야 할 중요한 점은 관심사 분리가 파일 타입 분리와 같지 않다는 것입니다. 현대적인 UI 개발에서 코드베이스를 서로 얽혀있는 세 개의 거대한 레이어로 나누는 대신, 느슨하게 결합 된 컴포넌트로 나누고 구성하는 것이 더 중요합니다.

    컴포넌트 내부에서 템플릿, 로직 및 스타일이 본질적으로 결합되어 배치 되면 컴포넌트의 응집력과 유지 보수성이 향상됩니다.

    문서에서 기술한 것처럼 Vue 파일을 살펴보면 구조와 표현, 동작이 하나의 파일에 느슨하게 묶인 것일 뿐. 뒤엉켜 한데 뭉쳐 진 것은 아닙니다. 각각의 HTML, CSS, JavaScript 파일로 나눌 것을 하나의 Vue 파일로 묶은 것입니다.

    Vue

    <!-- 구조(템플릿) -->
    <template>
      <div class="demo-vue">
        <a 
          v-for="(link, i) of links"
          :key="i"
          :href="link.href"
          @click.prevent="scrollAnimateTo(link.href)"
          class="scroll-link"
        >
          {{ link.text }}
        </a>
      </div>
    </template>
    
    <!-- 동작(로직) -->
    <script>
    export default {
      data: () => ({
        links: [ 
          { text: '312로 이동', href: '#point-312' },
          { text: '471로 이동', href: '#point-471' },
        ]
      }),
      methods: {
        scrollAnimateTo (targetId) {
          // ...
        }
      }
    }
    </script>
    
    <!-- 표현(스타일) -->
    <style scoped>
    .scroll-link {
      text-decoration: none; 
      font-size: 16px;
      color: tan;
    }
    </style>
    

    Q2

    Vue를 작성하면서도 css와 js를 분리하는 방법이 있는 건가요??

    A2

    싱글 파일 컴포넌트 방식에서 구조, 표현, 동작 분리

    Vue.js 문서는 추가적으로 다음과 같이 기술합니다.

    싱글 파일 컴포넌트에 대한 아이디어가 마음에 들지 않더라도 JavaScript와 CSS를 별도의 파일로 분리하여 핫 리로드 및 사전 컴파일 기능을 활용할 수 있습니다.

    네. 맞습니다. 하나의 파일에 구조, 표현, 동작을 느슨하게 묶는 것보다 기존처럼 HTML, CSS, JavaScript 파일로 분리하고 싶다면 다음과 같이 작성할 수 있습니다.

    Vue

    <!-- 구조(템플릿) -->
    <template src="./structure.html"></template>
    
    <!-- 동작(로직) -->
    <script src="./behavior.js"></script>
    
    <!-- 표현(스타일) -->
    <style src="./presentation.css" scoped></style>
    

    HTML

    <div class="demo-vue">
      <a 
        v-for="(link, i) of links"
        :key="i"
        :href="link.href"
        @click.prevent="scrollAnimateTo(link.href)"
        class="scroll-link"
      >
        {{ link.text }}
      </a>
    </div>
    

    CSS

    .scroll-link {
      text-decoration: none; 
      font-size: 16px;
      color: tan;
    }
    

    JavaScript

    export default {
      data: () => ({
        links: [ 
          { text: '312로 이동', href: '#point-312' },
          { text: '471로 이동', href: '#point-471' },
        ]
      }),
      methods: {
        scrollAnimateTo (targetId) {
          // ...
        }
      }
    }
    

    HTML, CSS, JavaScript, Vue 파일이 각각 분리된 CodeSandbox 예제를 직접 살펴보세요. ^ ㅡ ^

    정리

    Vue.js 프레임워크를 프로젝트에 사용한다면 기본적으로 vue 파일에 템플릿, 로직, 스타일을 느슨하게 묶어 사용하는 방법이 기본입니다. 필요한 경우 각각의 HTML, CSS, JavaScript 파일을 나눠 관리할 수 있지만, 그렇다고해서 vue 파일이 불필요해지는 것은 아닙니다.

    개인적으로 컴포넌트 단위 개발 방식에서 Vue.js가 선택한 방법은 적절하다고 봅니다. ^ ㅡ ^

    • (•́ ✖ •̀)
      알 수 없는 사용자
  • 구조와 동작, 표현의 분리라는 것은 일반론입니다. 응용단계에서는 여러 이유로 변화를 줄 수 있습니다. 특히 Vue와 같이 고도화된 프레임워크를 사용하려면 그것만의 프로그래밍 철학을 이해하고 정해진 방식대로 사용하는게 맞습니다.

    Vue의 싱글파일 컴포넌트에 대한 설명을 보시면 될 것 같고요. https://kr.vuejs.org/v2/guide/single-file-components.html

    그리고 결정적으로, 마지막 산출물에서는 우려하신 일은 일어나지 않습니다. 실제 싱글파일에 css가 인라인처럼 선언된 것으로 보이지만 실제로 번들링 이후에는 질문자분이 우려하신 상황이 아닌, 페이지의 모든 요소가 분리된 상태로 구조화 됩니다.

    번들링하면 스타일들은 따로 모여서 style 태그에 선언되고요, 자바스크립트 또한 하나 혹은 설정에 따라 복수의 파일로 묶입니다. HTML 마크업 역시 별도로 렌더링 되고요.

    Vue와 같은 프레임워크를 사용한다는 것은 그런겁니다. 이걸 사용하면 어지간한건 다 깔끔하고 성능 좋게 만들어 줄테니까 너는 편하게 구현에만 집중해. 웹 플랫폼 기반의 프레임워크니까 웹표준에서 권장하는 사항을 크게 벗어나지 않겠죠.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)