단일 파일 컴포넌트

단일 파일 컴포넌트 (SFC)

컴포넌트의 템플릿, 로직, 스타일을 서로 다른 세 파일에 나눠 관리하다 보면, 수정할 때마다 파일을 오가야 해서 어렵잖아요. Vue는 이 셋을 한 파일에 담는 *.vue 확장자 형식, 단일 파일 컴포넌트(SFC)를 제공합니다. 템플릿·로직·스타일이 한 컴포넌트 안에서 서로 가까이 붙어 있어 관리하기 편해지는 구조예요.

출처: Vue.js 공식 문서 - Single-File Components

SFC 예시

SFC는 HTML·CSS·JavaScript의 고전적인 삼총사를 자연스럽게 확장한 형태예요. <template>, <script>, <style> 블록이 같은 파일 안에서 뷰, 로직, 스타일을 각각 담고 있죠.

<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를 쓰나

SFC는 빌드 단계를 요구하지만, 그 대가로 여러 이점을 줍니다.

  • 익숙한 HTML·CSS·JavaScript 문법으로 모듈화된 컴포넌트를 작성
  • 본질적으로 얽힌 관심사의 위치 공유(콜로케이션)
  • 런타임 컴파일 비용 없이 미리 컴파일된 템플릿
  • 컴포넌트 스코프로 제한된 CSS
  • Composition API를 쓸 때 더 편리한 문법
  • 템플릿과 스크립트를 함께 분석해 더 많은 컴파일 타임 최적화
  • 템플릿 표현식의 자동 완성·타입 검사를 지원하는 IDE 지원
  • 별도 설정 없이 쓸 수 있는 핫 모듈 교체(HMR) 지원

SFC는 Vue를 프레임워크답게 만드는 핵심 기능이에요. 다음 시나리오에서 권장됩니다: 단일 페이지 애플리케이션(SPA), 정적 사이트 생성(SSG), 그리고 빌드 단계를 도입할 만한 개발 경험(DX) 개선이 필요한 규모 있는 프론트엔드.

물론 SFC가 과할 수 있는 상황도 있어요. 그래서 Vue는 여전히 빌드 단계 없이 평범한 JavaScript로도 쓸 수 있습니다. 정적인 HTML에 가벼운 상호작용만 더하려고 한다면, 점진적 향상을 위해 최적화된 6kB짜리 Vue 하위 집합인 petite-vue를 확인해 볼 수 있어요.

동작 방식

Vue SFC는 프레임워크 전용 파일 형식이라, @vue/compiler-sfc가 표준 JavaScript와 CSS로 미리 컴파일해야 해요. 컴파일된 SFC는 표준 JavaScript(ES) 모듈이라, 빌드 설정이 갖춰져 있으면 모듈처럼 import 할 수 있습니다.

import MyComponent from './MyComponent.vue'

export default {
  components: {
    MyComponent
  }
}

SFC 안의 <style> 태그는 개발 중 핫 업데이트를 지원하도록 보통 네이티브 <style> 태그로 주입됩니다. 프로덕션에서는 추출해 하나의 CSS 파일로 합칠 수 있어요.

실제 프로젝트에서는 SFC 컴파일러를 ViteVue CLI(webpack 기반) 같은 빌드 도구와 통합하는 게 일반적이고, Vue는 공식 스캐폴딩 도구도 제공해서 빠르게 시작할 수 있게 해 줍니다. SFC Playground에서 직접 SFC를 가지고 놀며 컴파일 결과를 탐색해 볼 수 있어요.

관심사 분리는 어떻게?

전통적인 웹 개발 배경의 사람이라면, SFC가 HTML·CSS·JS가 분리해야 할 관심사를 한곳에 섞는 것 아닌가 걱정할 수 있어요. 여기서 짚고 넘어갈 게 있는데, 관심사의 분리는 파일 타입의 분리와 같지 않아요. 엔지니어링 원칙의 궁극 목표는 코드베이스의 유지보수성을 높이는 것입니다. 관심사 분리를 파일 타입 분리로 맹목적으로 적용하는 건, 점점 복잡해지는 프론트엔드 앱에서는 그 목표에 도움이 되지 않아요.

현대 UI 개발에서는 코드베이스를 서로 얽히는 거대한 세 층으로 나누기보다, 느슨하게 결합된 컴포넌트로 나눠 조합하는 게 훨씬 합리적이에요. 컴포넌트 안에서 템플릿·로직·스타일은 본질적으로 결합돼 있고, 그것들을 함께 두는 게 오히려 컴포넌트를 더 응집력 있고 유지보수하기 쉽게 만듭니다.

SFC라는 아이디어가 마음에 들지 않아도, Src Import로 JavaScript와 CSS를 별도 파일로 분리해도 핫 리로딩·사전 컴파일 기능은 그대로 누릴 수 있어요.

더 알아보기