์์ด๋ธ๋ฆฌ์ ๋ฉ์์ด ์ฌ์๋ค์ฒ๋ผ์์ ์งํํ๋ CleanCode TDD,Vue.js ๊ธฐ๋ฐ์ผ๋ก ๊ต์กํ ์ต์คํด์ญ ํ๋ก๊ทธ๋๋ฐ ํ๋ก์ ํธ ์ ๋๋ค. FE Externship 1๊ธฐ๋ก ์ฐธ๊ฐํ์ฌ ์ฃผ์ฐจ๋ณ ๋ฏธ์ ์ ์งํํ์ฌ ์์ด๋ธ๋ฆฌ ๋ชจ๋ฐ์ผ ์น ์ฌ์ดํธ๋ฅผ ๊ตฌํํ์ต๋๋ค.
- ์ฒ์์ผ๋ก vue ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ jest ์ฌ์ฉ์ ํด๋ดค์ต๋๋ค.
- ๊ธฐ๋ณธ์ ์ธ vue ๋ผ์ดํ์ฌ์ดํด ํ ์ ์ฌ์ฉํ์ฌ ๊ตฌํํ์ต๋๋ค.
1์ฃผ์ฐจ - Boilerplate์ฝ๋์์ ์ผ๋ถ๋ฅผ ์์ ํ์ฌ ๊ฐ๋ฐ ํ์ด์ง์ ๋์ฐ๊ธฐ & Vue.js ๊ฐ๋ฐ ํ๊ฒฝ ์ธํ ํ๊ธฐ
- ๋ฏธ์ ์ฝ๋๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์ ์ด๋ค ์๊ฐ๋ค์ ํ๋์ง ์ ๋ฆฌํด๋ณด์ธ์.
- ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ดํด๋๋ฅผ ๋์ด๊ธฐ ์ํด commit๋ฉ์ธ์ง ๊ธฐ๋ณธ ๊ท์น์ ๋ฐ๋ผ ์ ์ฉํ๋ ค๊ณ ํ์ต๋๋ค.
- TDD ์์ฑ ์์น์ ์ํด ์ต์ํ์ ๊ธฐ๋ฅ๋ค์ ๊ตฌํํ ํ ํ ์คํธ ํ๋ ค๊ณ ํ์ต๋๋ค.
- vue๋ฅผ ์ด์ฉํด์ ๊ฐ๋ฐํ๋ ๊ฒ์ด ์ฒ์์ด๋ผ ๊ณผ์ ์งํ์ ํ๋ฉด์ ์๊ธฐ๋ ์ค๋ฅ๋ค์ ์ฒ์ ์ ํ๋ ๊ฒ๋ค์ด์์ต๋๋ค. ๊ตฌ๊ธ๋งํ๋ฉด์ ์ค๋ฅ ์ฝ๋ ์์ ํ๊ณ ์ ์ฒด ๊ธฐ๋ฅ๋ค ๋ํ ๊ณต๋ถํ๋ฉด์ ๋์์ ๊ณผ์ ์ํ์ ํด๋๊ฐ์ผ ํ์ต๋๋ค. ์ด ๊ณผ์ ์์ ์๊ฐ ๋ถ๋ฐฐ๋ฅผ ์ ๋ชปํ ์ ์ด ์์ฌ์ ์ง๋ง 1์ฃผ์ฐจ ๊ณผ์ ๋ฅผ ํตํด vue์๋ํด ์ด๋์ ๋ ์์ง๋ฅผ ํ๊ฒ ๊ฐ์ ์ฌ๋ฏธ์์์ต๋๋ค
- ๋ํ TDD๋ฅผ ํตํด ์ฝ๋ฉํ๋ ๊ฒ๋ ์ฒ์ ์๋ํด๋ณด๊ฒ ๋์๋๋ฐ,๊ทธ ๊ณผ์ ์์ ์ฌ๋ฌ๊ฐ์ง vue ๊ณต์๋ฌธ์๋ ์ ํ๋ธ๋ฅผ ์ฐธ๊ณ ํด์ ์คํํ๋๋ฐ, ์กฐ๊ธ๋ ํด๋ฆฐํ ์ฝ๋๋ฅผ ์ง์ง ๋ชปํ๊ฑฐ ๊ฐ์ ์์ฌ์ ์ต๋๋ค.
- ํ์ ๋ฌธ์์ด๊ณผ alert์ฐฝ ๊ตฌํ์ ๊ฐ์ component์์ ์งํํ๊ณ ํ ์คํธ ํ๋ ์ ์ด ์ข ์์ฝ๊ฒ ๋๊ปด์ง๋๋ค.
https://drive.google.com/file/d/1fCSrUfxCfLk_kyU5xTElBlnDmdUIrPZK/view
- ํ๋์ ํ์ด ๋ง๋ค์ด ์ก๋ค๊ณ ์๊ฐํ์๋ ์ํต์ ์ค๋ฅ๊ฐ ์๊ธฐ์ง ์๋๋ก ์๊ตฌ์ฌํญ์ ์ธ๋ถ์ ์ผ๋ก ๋๋์ด ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ค ํ์์ต๋๋ค.
- ์ฝ๋์ ๋ถํ์ํ ๋ฐ๋ณต์ ์ค์ฌ ์ ์ง๋ณด์ํ ์ ์ฝ๋๋ฅผ ์ฝ๋๋ฐ ์ด๋ ค์์ด ์๋๋ก ํ์์ต๋๋ค.
- ํ์ด์ง ์ด๋ํ ์ ๋์ ๋ผ์ฐํ ๋งค์นญ์ ์ด์ฉํ์ฌ ๋์ ์ธ ์๊ฐ์ ์๊ตฌ์ฌํญ์ ๋์ถํ๋ ๊ฒ์ ์ ๊ฒฝ์ผ์ต๋๋ค.
- ์ํ๋ฆฌ์คํธ์ ๊ธฐ๋ฅ์ ๊ตฌํ ํ ํ ์์ธํ์ด์ง๋ก ๋ก๋ฉ์ด ๋๋ค๊ณ ์๊ฐ์ด ๋์ด์ ์์ธํ์ด์ง ๊ตฌํํ๊ธฐ ์ ์ํ ๋ฆฌ์คํธํ์ด์ง๋ฅผ ๋จผ์ ๋ง๋ ํ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์์ต๋๋ค.
- vue ํ๋ ์ ์ํฌ ๋ด์์ ๋์ ๋ผ์ฐํ ๋งค์นญ์ ํ๋ ๋ฐฉ๋ฒ์ด ์ด๋ค์์ผ๋ก ์ด๋ฃจ์ด์ง๋์ง ์ ์ดํด๊ฐ ๊ฐ์ง ์์์ต๋๋ค. ์ ํ๋ธ๋ ๊ณต์๋ฌธ์๋ฅผ ๋ณด๋ฉฐ ๋ฐ๋ผํ๋ฉฐ ์ฃผ๋จน๊ตฌ๊ตฌ์์ผ๋ก ๊ตฌํํด๋ณด์๋๋ฐ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ธ์ง๋ ํ์ ์ด ๋ค์ง ์์ ์กฐ๊ธ ๋ ์์๋ณผ ํ์๊ฐ ์์๊ฒ ๊ฐ์ต๋๋ค.
https://drive.google.com/file/d/1cpzVyuyIAHUU_4rpSpKvoNfXvcFiS7ZU/view
-
์๋๋ ๊ธฐํ์๊ฐ ํด์ผํ๋ ์ผ์ด๋ผ๊ณ ์๊ณ ์์ง๋ง ์ด๊ธฐ ํ๋ก์ ํธ๋ผ๋ ๊ฐ์ ํ์ ์ง์ ํ๋ก ํธ์๋์์ ํ๋กํ ํ์ ์ ์ ์ํ๋ค๊ณ ๊ฐ์ ํ์์ต๋๋ค.
-
์๊ตฌ์ฌํญ ๋ช ์ธ๋ฅผ ์ด์ฉํด ๊ฐ๋จํ๊ฒ ์์ธ์ ๋ณด ํ์ด์ง์ ๋ํ ๊ธฐํ์๋ฅผ ์์ฑํ์ต๋๋ค.
-
ํ์ด์ง ์ ์ ์ ์๊ตฌ์ฌํญ ๋ช ์ธ๋ฅผ ๋ชฉ๋ก๋ณ๋ก ์ธ๋ถํํด ๊ธฐ๋ฅ๋ณ ๊ตฌํ์ด ์ ๋๋ก ๋๋๋ก ์์ฑํ์์ต๋๋ค.
- ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ณ ์ ์ง๋ณด์์ฑ๊ณผ ์ ์ฐ์ฑ์ ๊ณ ๋ คํ์ฌ ๋ถ๋ชจ์ปดํฌ๋ํธ์ธ ItemLIst ์๋์ ์์ ์ปดํฌ๋ํธ๋ฅผ ๊ธฐ๋ฅ๋ณ๋ก ๊ฐ๊ฐ ๋๋๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋๋ก ํ์์ต๋๋ค.
- ์ฌ์ฌ์ฉ์ฑ์ ์ํด ๊ตฌํํ ์ปดํฌ๋ํธ๋ค์ ๋ถ๋ชจ์ปดํฌ๋ํธ์ ๋ผ์ฐํ ํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์์ต๋๋ค.
- ํค๋ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ ๋ ํค๋๊ฐ ๋ณด์ด๊ณ ์ฌ๋ผ์ง๋ ๋์๋ค์ Lifrcycle Hook์ ์ด์ฉํด ํค๋ ์ปดํฌ๋ํธ๊ฐ ๊ฐ ๋์ํ ๋ mounted๋ฅผ ์ฃผ์ด ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ์ ๋ฌ๋๊ฒ ํ๊ณ , ํด๋น component๊ฐ ๋์์ด ํด์ฒด๋๊ธฐ ์ง์ ์ beforeunmountedํ ์ด ํธ์ถ๋๊ฒ ํ์ฌ method ์์ฑ์ ์ ๊ทผํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์์ต๋๋ค.
- ์ปดํฌ๋ํธ๋ค์ ์ธ๋ถํํด ์์ ํ ๋งํผ ํ ์คํธํ์ผ์ ๊ฐ๊ฐ ์์ฑํด ํ ์คํธ ํด์ฃผ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํด์ฃผ์์ต๋๋ค.
-vue.js์ ํน์ฑ์ ๊ฐ๋ฐ ๊ท๋ชจ๊ฐ ์ปค์ง์๋ก ์ฝ๋๊ฐ ๋ฐฉ๋ํ๊ณ ๋ณต์กํด์ง๋ ๋จ์ ์ด ์๋๋ฐ ์ด๊ฒ์ ํด๊ฒฐํ๊ธฐ ์ํ composition API์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ง๋ณด์์ฑ๊ณผ ์ ์ฐ์ฑ์ ์กฐ๊ธ ๋ ํด๊ฒฐํ์ง ๋ชปํ ๋ถ๋ถ์ด ์์ฝ์ต๋๋ค.
https://drive.google.com/file/d/1jNcyPSXgkje_8Y6iCNw8GxebxpGEoSgb/view
-
vue-router๋ฅผ ๋์ ๋ผ์ฐํ ๋งค์นญ์ ํตํ์ฌ Single Page Application (์ดํ SPA)์์ ์๋ก ๋ค๋ฅธ ํ๋ฉด์ ์ํธ์์ฉ์ ๋ฐ๋ผ ์ ํํ ์ ์๋๋ก ๊ตฌํํ์์ต๋๋ค.
-
APIํธ์ถ์ ํ ๋ ๋ฏธ์ ์๊ตฌ์ฌํญ์ธ Repository pattern ํตํ ์ฐ๋์ ์ฒ์์ด๋ผ ํด๋น ๋ถ๋ถ์ ๋ํด ์์๋ณด๊ณ ์ ๋ฆฌ ํ ๊ฐ๋ฐ์์์ํ์ต๋๋ค.
- Repository pattern์ ํตํ์ฌ API ์ฐ๋์ ์ฌ์ฉํ๊ณ Axios HTTP client๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
- ๋ผ์ฐํ ์ ์คํํ ๋ "Using a Real Router " ๋ฐฉ๋ฒ์ ์ ์ฉํ์ฌ ํ ์คํธ ํ๋๋ก ๋ ธ๋ ฅํ์ต๋๋ค.
- Using a Real Router " ๋ฐฉ๋ฒ์ ์ ์ฉํ์ฌ ํ ์คํธ๋ฅผ ์งํํด๋ณด๊ธด ํ์ง๋ง ํ์คํ ์ฒด๋์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฐ์ต์ด ๋ง์ด ํ์ํจ์ ๋๊ผ์ต๋๋ค.
- ์ถ๊ฐ ๋ฏธ์ ์ธ ๊ตฌํ๋์ง ์์ ๋ค๋ฅธ ํ์ด์ง๋ค์ ๊ฐ๋ฐํ๊ณ API์ฐ๋๊น์ง ํ์ง ๋ชปํด ์์ฝ์ต๋๋ค.
https://drive.google.com/file/d/1FQJmWz26WrCZ0Sw6up6JF_9fMApTJulY/view
-
์ ์ง๋ณด์์ฑ์ ๋์ด๊ธฐ ์ํด ํ ์คํธ์ฝ๋๋ฅผ ์์ฑ ํ ํ์ด์ง๋ค์ ๊ตฌํํ์ต๋๋ค.
-
์ผ๋ถ ํ์ด์ง๋ api์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ณ ์ฅ๋ฐ๊ตฌ๋์์๋ ๋ก์ปฌ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ฒ ๋๋๋ฐ ์ฌ๊ธฐ์์ ํ์ํ ๋ถ๋ถ์ store๋ฅผ ์ด์ฉํด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋๋ก ํ์ต๋๋ค.
์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง ( Cart.vue)
<Header>์ฅ๋ฐ๊ตฌ๋</Header>
<main>
<div>
<CartItem
v-for="item in storedCart"
:id="item.product_no"
:name="item.name"
:original_price="item.original_price"
:description="item.description"
:key="item.product_no"
></CartItem>
</div>
</main>
<OrderBtn/>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import Header from '../components/ItemList/Header.vue';
import CartItem from '../components/Cart/CartItem.vue';
import OrderBtn from '../components/OrderBtn/OrderBtn.vue';
export default {
name: 'OrderPage',
components: {
Header, CartItem, OrderBtn,
},
computed: {
...mapGetters(['storedCart']),
๊ฒฐ์ ํ์ด์ง ( Order.vue)
<template>
<div id='wish-list-page' data-test="order-page">
<Header/>
<main>
<div class="item-detail" data-test="item-list-page">
<CartItem
v-for="item in storedCart"
:id="item.product_no"
:name="item.name"
:img="item.image"
:price="item.price"
:original_price="item.original_price"
:description="item.description"
:key="item.product_no"
></CartItem>
</div>
<div class="order-cutomer"
v-for="order in orders"
:key="order.order_id">
<div class="order-name">
<span data-test="test-name">{{order.name}}</span>
</div>
<div>
<input class="order-input" v-model="order.value"/>
</div>
</div>
</main>
<router-link to="/complete">
<footer>
<input class="order-btn" type="button" value="์ฃผ๋ฌธํ๊ธฐ" onclick="idPwCheck()"/>
</footer>
</router-link>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import Header from '../components/ItemList/Header.vue';
import CartItem from '../components/Cart/CartItem.vue';
export default {
name: 'OrderPage',
components: { Header, CartItem },
computed: {
...mapGetters(['storedCart']),
},
data() {
return {
orders: [
{
order_id: 'o1',
name: '์ฃผ๋ฌธ์๋ช
',
value: '์ด๋ฆ์ ์
๋ ฅํด์ฃผ์ธ์',
},
{
order_id: 'o2',
name: '์ ํ๋ฒํธ',
value: '์ ํ๋ฒํธ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์',
},
{
order_id: 'o3',
name: '์๋ น ์ฃผ์',
value: '์ฃผ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์',
},
{
order_id: 'o4',
name: '์์ฒญ ์ฌํญ',
value: '๋ฐฐ์ก ์์ฒญ ์ฌํญ์ ์
๋ ฅํ์ธ์',
},
],
};
},
};
</script>
- storeํ์ผ ์์ฑ ํ ์ฅ๋ฐ๊ตฌ๋, ๊ฒฐ์ ํ์ด์ง, ๊ฒฐ์ ์๋ฃ ํ์ด์ง ์์๋๋ก ๊ตฌํํ์ต๋๋ค.
- ์ฅ๋ฐ๊ตฌ๋ ๋ชฉ๋ก ์ ๋ณด๊ฐ ๊ฒฐ์ ํ๋ฉด์์ ํ์ฉ์ด ๋๋๋ก ํ์์ต๋๋ค.
- ๊ฒฐ์ ํ๋ฉด์์ ํ์ฌ ์ฌ์ฉ์๊ฐ ์ฃผ๋ฌธํ๋ ์ํ๋ค์ ๋ชฉ๋ก์ ๋ค์ ๋ณด์ฌ์ฃผ๊ณ , ๊ทธ๋ก ์ธํด ์ด ์์ ๊ธ์ก์ด ๋์ค๋๋ก ๊ตฌํํ์ต๋๋ค.
- ๊ฒฐ์ ํ๋ฉด์์ ๊ตฌ๋งค ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ฒฐ์ ์๋ฃ ํ์ด์ง๋ก ๋์ด๊ฐ๋๋ก ๊ตฌํํ์ต๋๋ค.
-์ฅ๋ฐ๊ตฌ๋ ๋ด๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ์ฅ๋ฐ๊ตฌ๋์ ์ถ๊ฐ๋๋ ๊ธฐ๋ฅ์ ๋ํด ๋ง์ด ๊ณ ๋ฏผํด๋ดค์ง๋ง, ๊ตฌํํ์ง ๋ชปํด ์์ฝ์ต๋๋ค. ์ฅ๋ฐ๊ตฌ๋ ๋ฒํผ์ ํด๋ฆญํ๋ฉด action์ ์ด์ฉํด์ ๋ฐ์ดํฐ๊ฐ ์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง์ ์ ๋ฌ๋๋๋ก ์ฝ๋๋ฅผ ์งฐ๋๋ฐ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ๊ณ์ํด์ id๊ฐ์ ์ฝ์ด์ค์ง ๋ชปํ๋ค๋ ์๋ฌ๊ฐ ๋ด์ต๋๋ค. ์ด๋ฒ ๊ณผ์ ๋ฅผ ํ๋ฉด์ store์ ๋ํด ์ดํด๊ฐ ๋ถ์กฑํ๋ค๊ณ ์๊ฐ์ด ๋ค์๊ณ , ๋ํ javascript๋ ๋ง์ด ๋ถ์กฑํ๋ค๋ ๊ฒ์ด ๋๊ปด์ก์ต๋๋ค.
https://drive.google.com/file/d/11BVIEpn8Z9o1UPhTvPRNPFIcUyqWxOI-/view