Vue 3.0/04.Component

[vue 3] 03. 컴포넌트간 통신 2 props

  • -

이번 포스트에서는 props 사용 시 주의 사항에 대해 알아보자.

 

props validation

 

props로 다양한 타입의 데이터 전달 가능

props에는 문자열 뿐 아니라 모든 속성이 파라미터로 전달될 수 있다. 다음과 같은 Component를 생각해 보자.

<template>
    <div>
        <h3> {{ name }}</h3>
        <ul>
            <li>나이: {{ age }}, 20년 후에는 {{ 20+age }} 살</li>
            <li>전화: 번호는 {{ phone.number }}, 기종은 {{ phone.os }}</li>
        </ul>
    </div>
</template>

<script setup>
    defineProps(["name", "age", "phone"]);
</script>

<style scoped></style>

이 컴포넌트를 작성할 때 name은 문자열, age는 숫자, phone은 number와 os를 속성으로 갖는 객체를 고려했다. 따라서 아래의 입력과 출력이 원하는 상태이다.

const user1 = { name: 'hong', age: 20,
                         phone: { number: 
'1234', os: 'Android' } }

<PropTypes :name="user1.name"
                     :
age="user1.age" :phone="user1.phone" />

하지만 컴포넌트 사용자가 잘 모르고 다음과 같이 입력하면 머리가 아파진다.

const user2 = { name: 'jang', age: '20',
                         phone: 
'010-1234-5678' }

<PropTypes :name="user2.name"
                     :
age="user2.age" :phone="user2.phone" />

 

전달해야 하는 데이터에 대한 validation이 필요한 시점이다.

참고로 객체의 여러 속성을 바인딩시키려는 경우v-bind를 통해 객체를 설정하면 된다. 이때는 v-bind를 :형태로 축약할 수 없다.

 <PropTypes v-bind="user3" />

 

props 데이터에 대한 validation

props를 선언하면서 배열이 아닌 객체 형태를 이용하면 전달받은 property에 대한 validation이 가능해진다.

이제 name, age, phone이 어떤 식으로 작성되어야 하는지에 대한 설정이 되었다. 만약 이에 어긋나는 입력이 들어오면 Vue는 브라우저의 콘솔에 경고를 날린다.  검증 로직이 좀 복잡한 경우validator를 사용하고 boolean으로 결과를 반환한다.

외부를 포함한 다른 개발자가 작성한 Component를 사용하면서 부적절하게 사용되는 일이 없도록 할 때 유용한 기능이다.

참고로 validation 처리를 위해서는 다양한 옵션들이 있는데 아래 link를 참조하자.

https://ko.vuejs.org/guide/components/props.html#prop-validation

 

Props | Vue.js

 

ko.vuejs.org

 

 

props는 readonly로 사용하자!

 

props는 단방향의 데이터 흐름

props는 부모 -> 자식 방향으로 단방향의 데이터 흐름을 갖는다. 이 말은 최초 데이터를 발생시킨 부모가 값을 변경시키면 이 값을 props로 받은 모든 자식들의 값이 변경된다. 하지만 자식이 전달받은 props 값을 변경했다고 부모의 값이 변경되지는 않는다.

만약 자식 1이 전달받은 props를 변경했을 때 부모의 값이 변경돼버린다면 자식 2나 3도 영향을 받아버리니까 엄청난 혼선이 올 것이다.

자식이 변경한 props가 부모에게 영향을 준다면?

 

props는 readonly로 사용하자!

그럼 어차피 전달받은 props는 자식꺼니까 자식이 마음대로 변경해서 사용해도 괜찮을까? 이것도 역시 아니다.  자식이 props로 열심히 연산을 하다가 부모가 새로운 값을 던져줘 버리면 이제까지 자식이 하던 일은 말짱 헛 일이 된다.

자식이 열심히 작업 중인데 느닷없이 새 값이 넘어오면?

 

따라서 props의 값은 readonly로 사용하는 것이 좋다. 하지만 문제는 그냥 props를 편집해 보면 경고는 나오지만 된다는 점이다. 강제할 수는 없다.

eslint상에서는 오류가 출력되지만 동작은 한다.

하지만 v-model 영역에서는 props의 값을 할당하기만 해도 오류가 발생하면서 컴파일이 되지 않는다.

 

props를 readonly로 강제하려면?

하지만 프로그래밍을 하다 보면 props를 변경하는 실수를 하는 경우가 많다. 이 실수를 방지하기 위해서 크게 2가지 방법을 사용할 수 있다.

  • props로 전달된 값을 로컬 데이터에 할당해서 사용한다. 그럼 로컬 데이터를 변경하는데 문제없고 부모와의 관계도 없어진다. 만약 전달받은 props가 객체형일 때에는 deep copy 해서 사용해야 한다. 이때 단점은 부모가 변경되었을 때 자식이 그 상황을 파악하지 못한다.
// 지역 변수에 할당해서 사용하기
const localNum2 = ref(props.num2);
const localObj = reactive({...props.obj});

 

  • 두 번째 방법은 단순한 로컬 데이터에 저장하지 않고 computed 속성으로 정의하는 것이다. computed는 관련 데이터가 변경되면 자동으로 변경되는 특성이 있기 때문에 부모가 변경되었을 때 자식도 변경되고, computed는 readonly이기 때문에 값을 수정하려는 경우 오류가 발생한다.
// computed로 사용하기
const computedNum3 = computed(()=>props.num3)

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.