[Vue3] props

gminnimk·2025년 3월 21일

Vue3

목록 보기
8/39

저번 시간에 <Modal/> 컴포넌트를 만들어봤는데, 모달창이 제대로 뜨지 않았습니다.

문제는 데이터 바인딩에 있습니다.

Modal.vue 코드에서는 아래와 같이

<div class="black-bg" v-if="모달창열렸니 == true">
  <div class="white-bg">
    <img :src="원룸들[누른거].image" style="width:100%">
    <h4>{{ 원룸들[누른거].title }}</h4>
    <!-- (생략) -->
  </div>
</div>

와 같이 원룸들, 누른거 등의 변수를 사용하고 있는데,

Modal.vue 내부에 해당 데이터가 없어서 바인딩에 문제가 생긴 것입니다.

(데이터 바인딩을 하려면 해당 데이터가 컴포넌트 내부에 존재해야 합니다.)


1️⃣ 왜 데이터를 복사해 붙여넣으면 안 될까요?

  • 데이터 사본 문제: 만약 App.vue에 있는 원룸들 데이터를 Modal.vue로 복사해 붙여넣으면,
    업데이트가 발생했을 때 사본 간에 동기화가 되지 않아 문제가 발생합니다.
  • 미래 확장 고려: 데이터는 한 곳(최상위 컴포넌트)에 저장해두고 공유해야, 유지보수와 업데이트가 쉬워집니다.

따라서 옳은 방법은 App.vue에 저장된 원룸들 데이터를 props를 통해 전달하는 것입니다.


2️⃣ Props를 통한 데이터 전달 (3단계)

부모 컴포넌트(App.vue)에서 자식 컴포넌트(Modal.vue)로 데이터를 전달하려면 아래 3단계를 따릅니다.

  1. 보내기 (Parent → Child)
  2. 등록하기 (Child에서 props로 받기)
  3. 사용하기 (Child의 템플릿에서 데이터 바인딩)

용어 정리:

  • App.vue는 상위(부모) 컴포넌트
  • Modal.vue는 하위(자식) 컴포넌트

자식이 부모의 데이터를 사용하려면 props를 통해 전송받아야 합니다.


1. 데이터 보내기 (부모 컴포넌트 - App.vue)

부모에서는 아래와 같이 props로 데이터를 전달합니다.

<!-- App.vue -->
<template>
  <!-- 원룸들 데이터가 Modal.vue로 전달됩니다. -->
  <Modal :원룸들="원룸들" />
</template>

<script setup>
import { ref } from 'vue'
import Modal from './Modal.vue'

// 원룸들 데이터는 배열 형태로 관리 (예시)
const 원룸들 = ref([
  { image: 'image1.jpg', title: '원룸 A' },
  { image: 'image2.jpg', title: '원룸 B' },
  // 기타 데이터...
])
</script>

참고: :원룸들="원룸들" 문법은 데이터 바인딩과 props 전송 두 가지 역할을 합니다.

(이처럼 이름을 동일하게 쓰면 간편합니다.)


2. 데이터 등록하기 (자식 컴포넌트 - Modal.vue)

<!-- Modal.vue -->
<template>
  <div class="black-bg" v-if="모달창열렸니">
    <div class="white-bg">
      <img :src="원룸들[누른거].image" style="width:100%" />
      <h4>{{ 원룸들[누른거].title }}</h4>
      <!-- (생략) -->
    </div>
  </div>
</template>

<script setup>
  
// 부모로부터 전달받은 원룸들 데이터를 등록합니다.
const props = defineProps({
  원룸들: {
    type: Array,
    required: true // 필수 여부
  }
})

// 만약 Modal.vue 내부에서 사용하는 다른 상태(예: 모달창열렸니, 누른거)도 있다면
// 아래와 같이 별도로 관리합니다.
// 예시:
// import { ref } from 'vue'
// const 모달창열렸니 = ref(true)
// const 누른거 = ref(0)
</script>

중요:

  • 등록된 props는 템플릿에서 자유롭게 읽기 전용으로 사용할 수 있습니다.
  • props 데이터를 수정하려고 하면 Vue에서는 에러가 발생합니다.
    (수정이 필요하면 부모에서 데이터 변경을 해야 하거나, 자식 컴포넌트 내에서 별도의 반응형 변수로 복사 후 사용합니다.)

3. 전달받은 데이터 사용하기 (Child 템플릿)

  • Modal.vue 템플릿 내에서 등록된 props.원룸들을 사용하여,<img :src="원룸들[누른거].image"> 와 같이 자유롭게 데이터 바인딩이 가능합니다.
  • 다른 props들 (예: 모달창열렸니, 누른거)도 동일하게 사용할 수 있습니다.

Q. 애초에 Modal.vue에 데이터를 직접 저장하면 안되나요?

  • 의견: 만약 Modal.vue에서만 해당 데이터를 사용한다면,<script setup> 내부에 data()를 사용해 직접 저장해도 되지만...
  • 원칙:
    "데이터를 사용하는 컴포넌트들 중 최상위 컴포넌트(App.vue)에 데이터를 저장해야 함"
    - 이유: 데이터를 위로 전달(부모 → 자식)이 쉽지만, 반대로 전달하는 것은 복잡하고 추적하기 어렵기 때문입니다.
  • 결론:
    가능하면 App.vue에 데이터를 저장하고, 필요한 하위 컴포넌트로 props를 통해 전달하는 것이 바람직.

오늘의 교훈

  • 컴포넌트를 많이 쪼개면 props 보내는 것이 귀찮을 수 있음
    → 컴포넌트 분리 전에 "정말 이득이 있을까?" 고민해보는 것이 좋습니다.
  • 데이터의 일관성과 관리 편의성을 위해,
    데이터를 최상위 컴포넌트에 저장하고 props로 전달하는 방식을 유지해야 합니다.

0개의 댓글