dev.syw

기본·이름 있는·범위 슬롯으로 컴포넌트에 콘텐츠를 끼워 넣기.

슬롯으로 콘텐츠 전달

props는 데이터를 넘기지만, 때로는 HTML 조각 자체를 컴포넌트 안에 끼워 넣고 싶을 때가 있습니다. 카드의 본문, 모달의 내용처럼요. 이걸 가능하게 하는 것이 슬롯(slot) 입니다. 슬롯을 쓰면 컴포넌트는 "틀"을 제공하고, 그 안을 채우는 건 부모가 결정하게 됩니다.

학습 목표

  • <slot> 으로 기본 슬롯을 만들고 콘텐츠를 받는다.
  • 이름 있는 슬롯으로 여러 위치에 콘텐츠를 배치한다.
  • 범위 슬롯(scoped slot)으로 자식의 데이터를 부모 콘텐츠에 노출한다.
  • 슬롯이 비었을 때의 폴백 콘텐츠를 지정한다.

기본 슬롯

자식이 <slot /> 을 두면, 부모가 그 컴포넌트 태그 사이에 넣은 내용이 그 자리에 들어갑니다.

<!-- BaseCard.vue -->
<template>
  <div class="card">
    <slot />
  </div>
</template>
<!-- 사용하는 쪽 -->
<template>
  <BaseCard>
    <h3>제목</h3>
    <p>이 내용이 slot 자리에 들어갑니다.</p>
  </BaseCard>
</template>

폴백 콘텐츠

슬롯에 아무것도 넘어오지 않았을 때 보여줄 기본 내용을 <slot> 안에 적어둘 수 있습니다.

<template>
  <button class="btn">
    <slot>확인</slot>   <!-- 부모가 안 채우면 "확인" 표시 -->
  </button>
</template>

이름 있는 슬롯

여러 영역(헤더·본문·푸터)에 각각 콘텐츠를 받으려면 슬롯에 이름을 붙입니다.

<!-- Layout.vue -->
<template>
  <div class="layout">
    <header><slot name="header" /></header>
    <main><slot /></main>            <!-- 이름 없으면 default -->
    <footer><slot name="footer" /></footer>
  </div>
</template>

부모는 <template #이름> 으로 채웁니다(#v-slot: 축약).

<template>
  <Layout>
    <template #header><h1>사이트 제목</h1></template>
    <p>본문 내용 (기본 슬롯)</p>
    <template #footer><small>© 2026</small></template>
  </Layout>
</template>

💡 TIP — 이름을 지정하지 않은 콘텐츠는 모두 default 슬롯으로 들어갑니다.

범위 슬롯 (scoped slot)

때로는 부모가 끼워 넣을 콘텐츠를 만들 때 자식이 가진 데이터가 필요합니다. 예를 들어 목록 컴포넌트가 각 항목 데이터를 넘겨주고, 모양은 부모가 정하게 하고 싶을 때죠. 자식은 <slot> 에 props처럼 데이터를 묶어 보냅니다.

<!-- TodoList.vue -->
<script setup>
defineProps({ items: Array });
</script>

<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <slot :todo="item" :index="item.id" />
    </li>
  </ul>
</template>

부모는 v-slot 으로 그 데이터를 받아 씁니다.

<template>
  <TodoList :items="todos">
    <template #default="{ todo }">
      <strong>{{ todo.text }}</strong> ({{ todo.done ? '완료' : '진행' }})
    </template>
  </TodoList>
</template>

이렇게 하면 데이터 반복은 자식이, 각 항목의 표현은 부모가 책임지는 유연한 구조가 됩니다.

⚠️ 주의 — 기본 슬롯에 범위 데이터를 받을 때는 <TodoList v-slot="{ todo }"> 처럼 컴포넌트 태그에 바로 쓸 수도 있지만, 이름 있는 슬롯과 섞을 땐 반드시 <template #default> 형태를 쓰세요.

요약

  • <slot /> 으로 부모가 넣은 콘텐츠를 받는다.
  • <slot>기본값</slot> 으로 폴백 콘텐츠를 지정한다.
  • 이름 있는 슬롯(name/#이름)으로 여러 영역에 콘텐츠를 배치한다.
  • 범위 슬롯은 자식 데이터를 부모 콘텐츠에 노출해 표현을 위임한다.

연습문제

  1. 본문을 슬롯으로 받는 Alert.vue 를 만들고, 슬롯이 비면 "알림"이 표시되도록 폴백을 넣어 보세요.
  2. header·footer 이름 있는 슬롯을 가진 Panel.vue 를 만들어 사용해 보세요.
  3. 사용자 배열을 받아 각 사용자를 범위 슬롯으로 노출하는 UserList.vue 를 만들고, 부모에서 이름을 굵게 표시해 보세요.
  4. 이름 없는 콘텐츠가 어떤 슬롯으로 들어가는지 설명해 보세요.

힌트 — 범위 슬롯은 자식에서 <slot :user="u" />, 부모에서 <template #default="{ user }">.

💡 연습문제 풀이

불러오는 중…

함께 보면 좋은 자료

댓글 0

Vue.js” 강좌에 대한 댓글입니다.

댓글을 작성하려면 로그인이 필요합니다.