Skip to main content

Command Palette

Search for a command to run...

How "Fallthrough Attributes" work in Vue3 (feat. v-if)

Updated
How "Fallthrough Attributes" work in Vue3 (feat. v-if)

What is “Fallthrough Attributes”?

Vue3에서 Fallthrough attributes(이하 폴스루 속성)은 "컴포넌트에 전달되지만 받는 컴포넌트의 props나 emits에 명시적으로 선언되지 않은 속성이나 v-on 이벤트 리스너를 말한다. 일반적인 예시로는 class, style, id 속성들이 있다." ( A "fallthrough attribute" is an attribute or v-on event listener that is passed to a component, but is not explicitly declared in the receiving component's props or emits. Common examples of this include class, style, and id attributes. ) 자세한 설명은 vue3 공식 문서 링크를 참고하고, 간단한 코드로 가볍게 이해해보자.

다음과 같이 Foo1 라는 컴포넌트가 있을 때,

// App.vue
<template>
  <Foo1 status="draft" />
</template>

// Foo1.vue
<template>
  <span>hello</span>
</template>

<script setup>
const props = defineProps({
  label: String,
});
console.log('props', props); // { label: undefined } (no status!)
</script>

Foo1의 caller에서 선언되지 않은 속성들은 props에 들어오지 않는 것이 기본 동작이다. 하지만, class, style, id 등은 굳이 defineProps에 선언되지 않았더라도 caller에서 넘겨준 값이 반영된다는 것이다. 단, single root node component일 때만!

그럼 multiple root node component일 때는 어떨까? 공식 문서에 따르면, 명시적으로 $attrs를 넘기지 않으면 속성 폴스루가 동작하지 않는다. ( Unlike components with a single root node, components with multiple root nodes do not have an automatic attribute fallthrough behavior. If $attrs are not bound explicitly, a runtime warning will be issued. )

그렇다면 여기서 꼬리를 무는 질문 (i.e. 이 글을 쓴 목적!)

template에선 multiple root node를 가지지만, 실제 런타임엔 하나의 node만 렌더링 된다면?

구체적으로, template 내부에서 v-if/v-else-if 등을 이용해 여러 개의 노드가 존재하긴 하지만, 실제로 그려지는 노드가 하나일 수 밖에 없는 상황에서 Vue3의 폴스루 속성은 어떻게 동작할까? 이 내용은 Vue3 공식 문서에서 다루고 있지 않아 직접 코드를 짜서 실험했고, 이를 공유한다.

다음 Foo2 컴포넌트 코드를 보자.

// App.vue
<template>
  <Foo2 class="olaf" />
</template>

// Foo2.vue
<template>
  <span v-if="true">hello</span>
  <span v-else>world</span>
</template>

위 코드는 속성 폴스루가 정상적으로 동작한다.

덧붙여, v-if="false"로 바꾸는 경우에도 “world” 가 출력되지만 class=”olaf” 는 정상적으로 폴스루 된다.

이번에는 한 번 꼬아서, 다음 Foo3 컴포넌트 코드를 보자.

// App.vue
<template>
  <Foo3 class="olaf" />
</template>

// Foo3.vue
<template>
  <span v-if="true">hello</span>
  <template v-else>
    <span v-if="true">olaf</span>
    <span v-else>world</span>
  </template>
</template>

위 코드는 어떨까?

class=”olaf”는 정상적으로 hello에 폴스루되어 <span class=”olaf”>hello</span>이 출력된다.

이번에는 (마지막이다) 한 번 더 꼬아서, 다음 Foo4 컴포넌트 코드를 보자.

// App.vue
<template>
  <Foo4 class="olaf" />
</template>

// Foo4.vue
<template>
  <span v-if="false">hello</span>
  <template v-else>
    <span v-if="true">olaf</span>
    <span v-else>world</span>
  </template>
</template>

위 코드는 어떨까?

여기서는 속성 폴스루가 동작하지 않는다.

vue3의 런타임까지 살펴보진 않았지만, 최근 vue3의 ast를 조작하면서 알게된 지식을 바탕으로 추측하자면:

  1. 속성 폴스루는 node(i.e. child)에 대해서만 동작한다.

  2. <template v-if>는 node(i.e. child)가 아닌 branch로 취급된다.

  3. 따라서 branch는 node가 아니므로 template에 대해는 폴스루 할 수 없다. (설령 그 template이 항상 single root node를 가진다고 하더라도)

위 1,2,3을 이유로 Foo4.vue 코드에서 속성 폴스루는 동작하지 않는다.

맺음말

설명을 위해 Foo3.vue와 Foo4.vue 컴포넌트를 각각 별개의 컴포넌트로 보여줬지만, 사실 이 둘은 같은 컴포넌트이고, 어떨 때에는 속성 폴스루가 동작하지만, 어떤 경우에는 동작하지 않는 것을 발견했다. 재현하기 힘들어서 헤매던 차에 위와 같은 실험을 통해 폴스루가 동작하지 않는 edge case를 찾았고, 이를 공유한다.

More from this blog

Auto-Switch iTerm Profiles on SSH Connection

미국에 있는 서버와 한국에 있는 서버는 핑 차이가 크다. 미국서버에 배포하던 서비스를 최근에 한국으로 옮기니, 로컬 개발 터미널인지 라이브인지 구분이 힘들어졌다. 좋은 방법이 없을까 고민하던 차에 내가 발견한 방법을 공유한다. 1/ 프로필을 생성한다. 나는 평소에 밝은 테마(light theme)를 사용하기 때문에 이 프로필은 어두운 테마(dark theme)로 설정했다. 2/ 라이브 환경으로 접속하는 커맨드(e.g. ssh)에 대해 다음과 ...

Nov 23, 2025
Auto-Switch iTerm Profiles on SSH Connection

warp directory `wd`

터미널에서 특히 자주 찾게되는 폴더들이 있다. nvim 설정 디렉토리, 회사 git repo 디렉토리, 개인 git repo 디렉토리 등등. 이런 디렉토리들을 즐겨찾기처럼 등록하고, 즐겨찾기 목록을 볼 수 있고, 즐겨찾기에 등록된 곳을 바로 이동할 수 있게 만들어주는 스크립트가 https://github.com/mfaerevaag/wd 다. 해당 페이지에 있는 Setup 섹션을 참고해서 설치하자. oh-my-zsh의 경우 plugins에 wd...

Oct 18, 2025
warp directory `wd`

macOS에서 키보드로 출력 오디오 장치 바꾸기

최근에 헤드폰을 하나 샀다. 하지만 헤드폰으로 듣다가 밥을 먹을 때는 맥북 스피커로 바꾸고 싶다. 그렇게 출력 장치를 바꿀 때마다 상단의 제어센터 버튼을 눌러서, 오디오 버튼을 누르고, 위 스크린샷에서 원하는 장치를 고르는 것은 매우 귀찮더라. 키보드 “딸깍”으로 오디오 출력 장치를 바꿀 수 있는지 찾아봤고, 그 결과를 공유한다. https://github.com/deweller/switchaudio-osx 를 활용한다. SwitchAudioS...

Sep 12, 2025
macOS에서 키보드로 출력 오디오 장치 바꾸기

토막글 다섯 개 (5)

1. PR Approve에는 장미를 한 송이 🌹 팀원의 풀 리퀘스트를 Approve 할 때, LGTM와 같은 인삿말도 좋지만 나는 장미를 쓴다. 낭만 있고, 메신저에서 PR Approve 구걸을 할 때 장미를 부탁한다고 하거나, 팀원의 Approve 부탁 메세지에 장미 이모지로 답변하기 참 좋아서 애용하고 있다. PR Approve와는 전혀 상관없는 개념이지만 업무에서 자주 쓰이지 않는 심볼이라면 어느 거라도 적당히 재미있어 추천한다. 2. ...

Aug 19, 2025
토막글 다섯 개 (5)

olaf.kr

50 posts

그 날 기분에 따라 반말과 존댓말을 섞어씁니다.