Make Your Components Easier to Think About (μ»΄ν¬λνΈμ λν΄ λ μ½κ² μκ°νκΈ°)
π‘μλ³ΈκΈ : https://michaelnthiessen.com/make-your-components-easier-to-think-about
λλ μκ°νλκ±Έ μ«μ΄νλ€.
μ¬μ€ μ λ μκ°νλ κ²μ μ’μνμ§λ§, λ¬Έμ λ₯Ό ν΄κ²°νκ±°λ μ§μ μ μ΄λ£°μ μμλλ§ μκ°μ ν©λλ€. νμ§λ§ μ’ μ’ μ½λκ° μ΄λ₯Ό λ°©ν΄ν λκ° μμ΅λλ€. ν μν¬μ μ°Έμμκ° μ½λ μ½κΈ°μ λν΄ λ§νλ―μ΄ “λ§μ½ νΌλμ€λ½λ€λ©΄ λμ μλͺ»μ΄ μλλλ€.” λ€μμ μ½λλ₯Ό λ μ½κ² μκ°νμ¬ νΌλμ μ€μ΄κ³ μ€μ μμ μ μλ£ν μ μλ λͺ κ°μ§ λ°©λ²μ λλ€.
κ°λ μ±μ μν μ»΄ν¬λνΈλ₯Ό μΆμΆνκΈ°
μ¬λμ΄ μ΄ν΄νκΈ° μ½λλ‘ μ»΄ν¬λνΈλ₯Ό μ΅μ ννλ ν κ°μ§ λ°©λ²μ μλ(intention)μ ꡬν(implementation)μ λΆλ¦¬νλ κ²μ λλ€. μ΄λ μλ‘μ΄ μ»΄ν¬λνΈλ₯Ό λ§λ€μ΄μΌ νλ κ°μ₯ μ€μν μ΄μ μ€ νλμ΄λ©°, μ½λμ μΌλΆλΆμ ν΄λΉ μ½λμ κΈ°λ₯μ μ€λͺ νλ μ½λλ‘ λ체ν μ μμ΅λλ€.
λ€μμ μ€μ κΈ°λ³Έμ μΈ μ»΄ν¬λνΈμ λλ€.
<template>
<div>
<p>{{ user.name }} ({{ user.age }})</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const user = ref({
name: 'John Doe',
age: 28,
});
</script>
UserInfo μ»΄ν¬λνΈλ₯Ό μΆμΆνλ©΄ μ΄ ν μ€μ΄ νλ μΌμΈ μ¬μ©μ μ 보λ₯Ό νμνλ κ²μ΄ λ§€μ° λͺ νν΄μ§λλ€.
<template>
<div>
<UserInfo :user="user" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import UserInfo from './UserInfo.vue';
const user = ref({
name: 'John Doe',
age: 28,
});
</script>
μ΄ μ»΄ν¬λνΈλ₯Ό λ§λ€κΈ° μν΄μλ λͺ κ°μ§ 보μΌλ¬ νλ μ΄νΈλ₯Ό ꡬμ±ν΄μΌ ν©λλ€.
<template>
<p>{{ user.name }} ({{ user.age }})</p>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
user: Object,
});
</script>
리ν©ν λ§ν μ½λμμλ μ¬μ©μ μ 보λ₯Ό UserInfo μ»΄ν¬λνΈλ‘ μΆμΆνμ΅λλ€. μ΄λ κ² λΆλ¦¬νλ©΄ μ½λκ° λͺ¨λνκ° λ©λλ€. μ΄μ μ°λ¦¬ μ½λλ μ’λ μ½κΈ° μ¬μμ§λλ€. μ΄κ²μ κ°λ¨ν μμμ΄λ©°, μ΄μ μ μ μ΅λλ€. λ κΈΈκ³ λ³΅μ‘ν μ»΄ν¬λνΈμμλ μ΄λ¬ν λ°©μμΌλ‘ μ»΄ν¬λνΈλ₯Ό μΆμΆνλ©΄ ν¨μ¬ λ λ§μ μ΄μ μ μ»μ μ μμ΅λλ€. μ΄κ²μ λν self-documenting code(μ€μ€λ‘ λ¬Έμνλ μ½λ)λ₯Ό μμ±νλ λ°©λ²μ ν μμμ΄κΈ°λ ν©λλ€. μ΄κ²μ΄ λ°λ‘ Clean Components Toolkitμ ν΅μ¬ λΆλΆμ λλ€. λͺ¨λ ν¨ν΄, κΈ°μ λ° μμΉμ “μ΄λ»κ² νλ©΄ μ½λλ₯Ό λ μ€λͺ μ μΌλ‘ λ§λ€μ μμκΉ?”λΌλ μ§λ¬Έμ λμ§λλ€. λ§μ½ μ½λλ₯Ό λ μ€λͺ μ μΌλ‘ λ§λλ ν¨ν΄μ λ°λ₯΄κ³ μλ€λ©΄ μ’μ ν¨ν΄μ΄ μλ κ°λ₯μ±μ΄ λμ΅λλ€. κ·Έλ¬λ self-documenting code(μ€μ€λ‘ λ¬Έμνλ μ½λ)λ μ»΄ν¬λνΈ μ΄λ¦λΏλ§ μλλΌ λ μΈλΆνν μ μμ΅λλ€.
μ’ λ self-documenting code(μ€μ€λ‘ λ¬Έμνλ μ½λ)λ₯Ό μμ±νκΈ°
Vue μ»΄ν¬λνΈμλ props, data, computed μμ±, methods, λΌμ΄λΈμ¬μ΄ν΄ hooks λ±λ±μ λν΄ λͺ ννκ³ μλ―Έμλ μ΄λ¦μ΄ μμ΄μΌ ν©λλ€. λν ν νλ¦Ώ μ½λκ° μ μ ν λ€μ¬μ°κΈ°, μμ(formatting), λλ¬Έ μ£Όμμ μ¬μ©νμ¬ μ²΄κ³μ μ΄κ³ κ°λ μ±μ΄ μ’μμΌ ν©λλ€. λμ μ½λκ° self-documenting(μ€μ€λ‘ λ¬Έμνλ μ½λ) λμ΄ μλ€λ©΄ ν΄λΉ μ½λκ° μννλ μμ μ μλλ₯Ό μ리λλ° λμλ©λλ€. ν°λ¬΄λμλ μμμΌ μλ μμ§λ§(λκ° μ΄λ° μ½λλ₯Ό μμ±νκ² μ΄μ?) μ½λμμ λ¬΄μ¨ μΌμ΄ μΌμ΄λκ³ μλμ§ νμ νλ €λ©΄ μ½κ°μ λ Έλ ₯μ΄ νμνμ£ .
<template>
<div>
<button @click="c">Increment</button>
<p>{{ a }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const a = ref(0);
function c() {
a.value++;
}
</script>
λ§μ΅λλ€. counter μ λλ€. νμ§λ§ λ€μ μμλ₯Ό 보면 보μλ§μ 무μμΈμ§ μ¦μ μ μ μμ΅λλ€.
<template>
<div>
<button @click="incrementCounter">Increment</button>
<p>{{ counterValue }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const counterValue = ref(0);
function incrementCounter() {
counterValue.value++;
}
</script>
리ν©ν λ§λ μ½λμμλ λ³μμ λ©μλμ μ΄λ¦μ λ μ μ€λͺ ν μ μλλ‘ κ°μ νμ΅λλ€. μ΄μ μ΄ μ»΄ν¬λνΈλ‘ λμμ¬ λλ§λ€ μκ°κ³Ό μ μ μ μλμ§λ₯Ό λλΉν νμκ° μμ΅λλ€.
λ무 κΈ΄ μ»΄ν¬λνΈ λΆν νκΈ°
μ»΄ν¬λνΈκ° λ무 λ§μ μΌμ νκ³ λ무 κΈΈμ΄μ§λ©΄ μ΄ν΄νκ³ μ μ§ λ³΄μ κ΄λ¦¬νκΈ°κ° μ΄λ €μΈ μ μμ΅λλ€. κΈ΄ μ»΄ν¬λνΈ μμΉμ λ°λ₯΄λ©΄ κΈ΄ μ»΄ν¬λνΈλ₯Ό λ μκ³ μ§μ€λ μ»΄ν¬λνΈλ‘ λλλ©΄ κ°λ μ±, μ¬μ¬μ©μ± λ° ν μ€νΈ κ°λ₯μ±μ κ°μ νλ λ° λμμ΄ λ©λλ€. λ€μμ μ΄ λͺ¨λ κ²μ μλνλ μ μμκ±°λ μμ μ μ»΄ν¬λνΈμ λλ€.
<template>
<div>
<h1>{{ title }}</h1>
<p>{{ description }}</p>
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }} - {{ item.price }}
<button @click="addToCart(item)">Add to cart</button>
</li>
</ul>
<div>
<h2>Cart</h2>
<ul>
<li v-for="item in cart" :key="item.id">
{{ item.name }} - {{ item.price }}
<button @click="removeFromCart(item)">Remove</button>
</li>
</ul>
<p>Total: {{ totalPrice }}</p>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const title = ref('My Store');
const description = ref('Welcome to my store!');
const items = ref([
{ id: 1, name: 'Item A', price: 10 },
{ id: 2, name: 'Item B', price: 20 },
]);
const cart = ref([]);
function addToCart(item) {
cart.value.push(item);
}
function removeFromCart(item) {
const index = cart.value.indexOf(item);
if (index !== -1) {
cart.value.splice(index, 1);
}
}
const totalPrice = computed(() => {
return cart.value.reduce((sum, item) => sum + item.price, 0);
});
</script>
μ΄λ₯Ό λΆν νλ λ° λμμ΄ λλ Clean Components Toolkitμ μ»΄ν¬λνΈ κ²½κ³ ν¨ν΄μ μ¬μ©ν΄ λ³΄κ² μ΅λλ€. μ΄ ν¨ν΄μ μΌλ°μ μΌλ‘ μ½λμ μ΄λ―Έ μ μλ κ²½κ³κ° μμ΄ μ»΄ν¬λνΈλ₯Ό λΆν νλ λ° μ¬μ©ν μ μμμ μλ €μ€λλ€. μ΄λ¬ν κ²½κ³λ₯Ό μ°Ύλ κ°μ₯ μ¬μ΄ λ°©λ²μ ν νλ¦Ώμ μ΄ν΄λ³΄λ κ²μ λλ€. μ΄λ κ² νλ©΄ μΆμΆν μ μλ μΈ κ°μ§ κ°λ³ κ΅¬μ± μμλ₯Ό μ°Ύμ μ μμ΅λλ€.
- StoreHeader
- ItemList
- Cart
<template>
<div>
<!-- StoreHeader -->
<h1>{{ title }}</h1>
<p>{{ description }}</p>
<!-- ItemList -->
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }} - {{ item.price }}
<button @click="addToCart(item)">Add to cart</button>
</li>
</ul>
<!-- Cart -->
<div>
<h2>Cart</h2>
<ul>
<li v-for="item in cart" :key="item.id">
{{ item.name }} - {{ item.price }}
<button @click="removeFromCart(item)">Remove</button>
</li>
</ul>
<p>Total: {{ totalPrice }}</p>
</div>
</div>
</template>
μλ‘κ³ κ°μνλ κ΅¬μ± μμλ λ€μκ³Ό κ°μ΅λλ€. μ΄μ λ¬΄μ¨ μΌμ΄ μΌμ΄λκ³ μλμ§ ν¨μ¬ λ μ½κ² μ΄ν΄ν μ μμ΅λλ€.
<template>
<div>
<StoreHeader :title="title" :description="description" />
<ItemList :items="items" @addToCart="addToCart" />
<Cart :cart="cart" @removeFromCart="removeFromCart" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import StoreHeader from './StoreHeader.vue';
import ItemList from './ItemList.vue';
import Cart from './Cart.vue';
const title = ref('My Store');
const description = ref('Welcome to my store!');
const items = ref([
{ id: 1, name: 'Item A', price: 10 },
{ id: 2, name: 'Item B', price: 20 },
]);
const cart = ref([]);
function addToCart(item) {
cart.value.push(item);
}
function removeFromCart(item) {
const index = cart.value.indexOf(item);
if (index !== -1) {
cart.value.splice(index, 1);
}
}
</script>
StoreHeader μ»΄ν¬λνΈμ λλ€.
<template>
<div>
<h1>{{ title }}</h1>
<p>{{ description }}</p>
</div>
</template>
<script setup>
const props = defineProps({
title: String,
description: String,
});
</script>
ItemList μ»΄ν¬λνΈμ λλ€.
<template>
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }} - {{ item.price }}
<button @click="$emit('addToCart', item)">Add to cart</button>
</li>
</ul>
</template>
<script setup>
const props = defineProps({
items: Array,
});
</script>
Cart μ»΄ν¬λνΈμ λλ€.
<template>
<div>
<h2>Cart</h2>
<ul>
<li v-for="item in cart" :key="item.id">
{{ item.name }} - {{ item.price }}
<button @click="$emit('removeFromCart', item)">Remove</button>
</li>
</ul>
<p>Total: {{ totalPrice }}</p>
</div>
</template>
<script setup>
import { defineProps, computed } from 'vue';
const props = defineProps({
cart: Array,
});
const totalPrice = computed(() => {
return props.cart.reduce((sum, item) => sum + item.price, 0);
});
</script>
μ¬κΈ°μ νΈλ μ΄λμ€νλ₯Ό λ°κ²¬νμμλ μμ΅λλ€. νλμ 볡μ‘ν μ»΄ν¬λνΈλ₯Ό μ¬λ¬ κ°μ κ°λ¨ν μ»΄ν¬λνΈλ‘ λ°κΎΈλ κ²μ λλ€. μ½λκ° μ‘°κΈ λ λ§μμ§κΈ΄ νμ§λ§ μ΄ν΄νκΈ° ν¨μ¬ μ½κ³ μ μ§ κ΄λ¦¬ λ° μμ νκΈ° μ¬μ΄ μ½λκ° λ©λλ€. μ κ° λ³΄μ¬λλ¦° μμλ€ μ¬μ΄μλ ν΅μΌλ μμΉμ΄ μμ΅λλ€.
κ°μ₯ λ©μ²νκ³ , κ°μ₯ μ’μ νκ³ , κ°μ₯ νΌκ³€ν μκΈ°μμ μ μν΄. μ΅μ ν νμΈμ.
μ λ μ리ν μ½λλ₯Ό μμ±νλ κ²½ν₯μ΄ μμ΅λλ€.(μ μ΄λ μ κ° λλνλ€κ³ λκ»΄μ§λλ‘ λ§λ€μ£ .) νμ§λ§ λ€μλ μμμ΄ λ¨μ΄μ§κ±°λ μλμ§κ° μ€μ΄λ μνλ‘ λμμ€λ©΄ λ¬΄μ¨ μΌμ΄ μΌμ΄λκ³ μλμ§ νμ νκΈ° μ΄λ ΅μ΅λλ€. μ°λ¦¬λ μ΅μ μ λ μλ μ΄ν΄ν μ μκ³ μμ°μ μΌλ‘ μμ ν μ μλ λͺ νν μ½λλ₯Ό μμ±νκ³ μΆμ΅λλ€. μ΄λ μ’μ μ΄λ¦ μ§μ κ³Ό μ 리, λͺ ννκ³ κ°κ²°ν λ¬Έμμ μμ λ₯Ό μ‘°ν©νμ¬ λ¬μ±ν μ μμ΅λλ€. λν μΌκ΄λ ν¨ν΄κ³Ό κ·μΉμ μ¬μ©νλ©΄ μΈμ§μ λΆνλ₯Ό μ€μ΄κ³ ν΄μμ΄λ μ€λ¨ νμλ νλ‘μ νΈ μμ μ κ³μνκΈ°κ° μ¬μμ§ μ μμ΅λλ€.
κ²°λ‘
μ¬λμ΄ μ΄ν΄ν μ μλλ‘ μ»΄ν¬λνΈλ₯Ό μ΅μ ννλ κ²μ μ μ§λ³΄μμ±, κ°λ μ± λ° μ λ°μ μΈ νλ‘μ νΈ μ±κ³΅μ μν΄ λ§€μ° μ€μν©λλ€. μ¬λ°λ₯Έ λͺ λͺ κ·μΉμ μ¬μ©νκ³ , μ»΄ν¬λνΈ λ©μλλ₯Ό μΆμΆνκ³ , μ½λλ₯Ό μ 리νκ³ , λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄λ©΄ Vue μ»΄ν¬λνΈμ λ μ½κ² μ κ·Όνκ³ μμ νκΈ° μ½κ² λ§λ€μ μμ΅λλ€. μ΄ λ¬Έμμλ λͺ κ°μ§ λ°©λ²μ μκ°νμ§λ§, κ·Έ μΈμλ λ€μν λ°©λ²μ΄ μμ΅λλ€. Clean Component Toolkitμλ λ λμ Vue μ»΄ν¬λνΈλ₯Ό μμ±νλ λ° λμλλ ν¨ν΄, κΈ°μ λ° κ°λ κ³Ό κ°μ 21κ°μ§ λκ΅¬κ° ν¬ν¨λμ΄ μμ΅λλ€. κ°κ°μ μ€μ μ½λ μμ μ λꡬλ₯Ό μ μ©νλ λ°©λ²μ 보μ¬μ£Όλ λ¨κ³λ³ 리ν©ν°λ§ μμ λ₯Ό ν¬ν¨νμ¬ λ§€μ° μμΈνκ² λ€λ£Ήλλ€. λ°λΌμ Vue μ½λλ₯Ό κ°μ νλ λ°©λ²μ λν΄ μμΈν μμλ³΄κ³ μΆλ€λ©΄ Clean Components Toolkitμ μ¬μ©νλ κ²μ΄ μ’μ΅λλ€.