
이미 이전 글들을 봐왔다면 이미 익숙하다고 할 수 있는 Single-File Components(SFC)에 대해 간략하게 잠시 다뤄보고자 합니다.
Single-File Componts
Single-File Components(SFC)라고 불리지만 사실 Vue 컴포넌트 *.vue
파일을 말합니다. Single-File이라 표현한 이유는 View(HTML), Logic(Javascript), Styling(CSS)이 하나의 파일에 모여있기 때문이죠. 결국 HTML, CSS, JS를 하나의 파일에 모은 컴포넌트 파일이라고 할 수 있습니다.
<script setup>
import { ref } from 'vue'
const greeting = ref('Hello World!')
</script>
<template>
<p class="greeting">{{ greeting }}</p>
</template>
<style>
.greeting {
color: red;
font-weight: bold;
}
</style>
왜 사용해야하는가?
SFC 파일 자체로는 브라우저에서 볼 수 없습니다. 별도의 빌드 단계가 필요한데 그럼에도 불구하고 장점들이 많이 있습니다.
HMR은 개발할 때 브라우저를 새로고침하지 않고도 웹팩으로 빌드한 결과물이 바로 반영되는 기능입니다.
SFC는 다음과 같은 경우에 사용되는 것이 좋습니다.
SFC를 사용하기에는 좀 간단한 경우이고 상호작용도 적은 HTML 파일이 많다면, petite-vue를 사용하는 것도 좋습니다.
어떻게 동작하는가?
SFC는 Vue를 위한 프레임워크 파일 포맷이기 때문에 @vue/compiler-sfc로 표준 JS, CSS로 미리 컴파일 되어야 합니다.
이렇게 컴파일된 SFC는 표준 JS 모듈이 되기 때문에 설정만 잘 되어있다면 SFC를 모듈처럼 가져올 수 있습니다.
import MyComponent from './MyComponent.vue'
export default {
components: {
MyComponent
}
}
CSS의 경우에는 개발 중에는 <style> 태그를 만들어 삽입하고 개발완료하고 배포한 것은 모든 컴포넌트들에서 추출해서 하나의 CSS 파일에 병합합니다.
HTML과 CSS, JS를 모으는 것에 대하여
일부러 각 기능에 맞게 HTML, CSS, JS로 분리된 것을 다시 SFC로 합치는게 혼란스럽고 합리적인지 의심이 들 수 있습니다. 이에 대해 답하자면, SFC가 구분하고자 하는 것은 사용 목적입니다.
예를 들어, 하나의 버튼을 만들기 위해 HTML, CSS, JS는 각각 파일에 따로 구현해야 합니다. 하지만 SFC는 이를 한 파일에 모아서 구현할 수 있습니다. 버튼이라는 사용 목적을 위해 서로 다른 파일로 있는 것보다 하나의 컴포넌트로 관리되는 것이 코드 유지 관리면에서 더 효율적입니다.
그럼에도 불구하고 분리하고 싶다면 src
속성을 이용해서 분리하실 수 있습니다.
<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>
SFC 문법
HTML과 비슷한 문법을 가지고 있지만, 몇 가지 다른 점들이 있습니다. 그 중 하나가 언어 블록(Language Block)이 있다는 겁니다.
<template>
*.vue
파일마다 하나만 있을 수 있습니다.@vue/compiler-dom
에 전달되서, 자바스크립트 render
함수에 의해 컴파일(pre-compiled)되어 컴포넌트의 render
옵션 값에 들어갑니다.<script>
*.vue
파일마다 하나만 있을 수 있습니다.default export
뒤에 들어갈 값은 컴포넌트 객체여야 합니다. 여기서 말하는 컴포넌트 객체는 컴포넌트 옵션들이 들어간 일반 객체일 수도 있고, defineComponent의 반환값일 수도 있습니다.setup
옵션을 추가할 수 있으며, 이는 script 내부를 setup()
함수처럼 사용할 수 있습니다. 보통은 변수나 함수등을 return해야 template에 노출(expose)되어 사용할 수 있습니다. 하지만 이 경우 하위 스코프가 아닌 최상단(top-level)에서 변수나 함수를 정의했다면 return한 것처럼 자동으로 노출되어 사용할 수 있습니다.<style>
*.vue
파일마다 여러 개 있을 수 있습니다. module
, scoped
속성을 이용해 다른 컴포넌트에 영향 주지 않고 현재 컴포넌트에만 스타일이 적용되도록 할 수 있습니다.v-bind
를 이용해 넣어줄 수 있습니다. 예) color: v-bind('myVal');
그 외에도 라이브러리에 따라 다른 블록들을 넣을 수 있습니다.
커스텀 블록도 만들 수 있는데 이는 다음 글에서 다뤄보도록 하겠습니다.
lang 속성
HTML, CSS, JS 뿐만 아니라 Pug, SASS, TS 등 다른 언어들도 많이 있습니다. lang
속성을 넣어주면 편하게 해당 언어의 문법을 사용해 구현할 수 있습니다.
<script lang="ts">
// use TypeScript
</script>
<template lang="pug">
p {{ msg }}
</template>
<style lang="scss">
$primary-color: #333;
body {
color: $primary-color;
}
</style>
주석
HTML과 유사한 문법을 쓰기 때문에 template, script, style과 같은 곳에서 주석을 써야 한다면 HTML과 동일한 <!-- 주석 -->
방식을 사용합니다. script 내에서는 /* */
, //
를, style 내에서는 /* */
를 사용하시면 됩니다.
<!-- 바깥 주석 -->
<template>
<!-- HTML 주석 -->
</template>
<script>
// JS 주석
/* JS 주석 */
</script>
<style>
/* CSS 주석 */
</style>