728x90

온라인 쇼핑몰 장바구니 수량 조절
당신은 온라인 쇼핑몰의 프론트엔드 개발자입니다. 사용자가 장바구니에 담긴 상품의 수량을 늘리거나 감소시킬 수 있는 기능을 만들어야 합니다. 또한 수량이 변경될 때마다 콘솔에 변경 내역을 기록해 디버깅하거나 추후 서버로 전송할 데이터를 준비하려고 합니다. 이를 Vue.js의 ref와 watch를 활용해 간단히 구현해보겠습니다.
코드 예제
<template>
<div class="cart-item">
<p>장바구니 상품 수량: {{ count }}</p>
<button @click="count++">수량 증가</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const count = ref(0); // 장바구니 상품 수량 초기값
// 수량이 변경될 때마다 로그 기록
watch(count, (newValue, oldValue) => {
console.log(`수량이 ${oldValue}에서 ${newValue}로 변경되었습니다.`);
// 실무에서는 여기서 서버로 업데이트 요청을 보낼 수 있음
// 예: updateCartItem(newValue);
});
return {
count
};
}
};
</script>
<style>
.cart-item {
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
max-width: 300px;
text-align: center;
}
</style>
시나리오 전개
-
초기 상태: 사용자가 장바구니에 상품을 추가하면 count 값이 0으로 시작합니다.
-
수량 증가: 사용자가 "수량 증가" 버튼을 클릭하면 count 값이 1씩 증가합니다.
-
변경 감지: watch가 count의 변화를 감지하고, 변경 전(oldValue)과 변경 후(newValue) 값을 콘솔에 출력합니다.
-
실무 적용: 콘솔 로그 대신, 변경된 수량을 서버에 전송하거나, 수량이 10개를 넘으면 경고 메시지를 띄우는 로직을 추가할 수 있습니다.
실무에서의 확장 가능성
-
감소 버튼 추가: <button @click="count > 0 ? count-- : null">수량 감소</button>를 추가해 수량이 0 이하로 내려가지 않게 제어.
-
서버 연동: watch 내부에서 API 호출을 통해 실시간으로 장바구니 상태를 업데이트.
-
UI 개선: 수량이 변경될 때마다 애니메이션 효과를 추가해 사용자 경험을 향상.
마무리
이 간단한 예제는 Vue.js의 반응형 데이터 관리와 이벤트 감지의 기본을 보여줍니다. 실무에서는 여기에 에러 처리, 입력 검증, 사용자 피드백 등을 추가해 더 견고한 기능을 만들 수 있습니다. Vue.js의 setup과 watch를 활용하면 코드도 깔끔하고 유지보수도 쉬워지니, 작은 기능부터 적용해보세요!
728x90
Vue.js로 실시간 투표 시스템 구현하기
시나리오: 실시간 투표 모니터링 대시보드
당신은 이벤트 관리 플랫폼의 개발자로, 실시간 투표 시스템을 구축해야 합니다. 사용자가 특정 항목에 투표를 추가할 수 있고, 투표 수가 변경될 때마다 로그를 남기며, 투표 수가 100을 넘으면 관리자에게 경고를 띄워야 합니다. 또한, 사용자가 투표를 취소할 수 있는 기능도 필요합니다. Vue.js의 ref와 watch를 활용해 이를 구현해보겠습니다.
코드 예제
<template>
<div class="vote-dashboard">
<h2>실시간 투표 수: {{ voteCount }}</h2>
<button @click="addVote" :disabled="isMaxReached">투표 추가</button>
<button @click="removeVote" :disabled="voteCount === 0">투표 취소</button>
<p v-if="warning" class="warning">경고: 투표 수가 100을 초과했습니다!</p>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const voteCount = ref(0); // 투표 수 초기값
const warning = ref(false); // 경고 상태
const isMaxReached = ref(false); // 최대 투표 수 제한 플래그
// 투표 수 변경 감지
watch(voteCount, (newValue, oldValue) => {
console.log(`투표 수가 ${oldValue}에서 ${newValue}로 변경됨`);
// 투표 수가 100 초과 시 경고 활성화
if (newValue > 100) {
warning.value = true;
// 실무에서는 서버로 알림 전송 가능
// 예: sendNotificationToAdmin(newValue);
} else {
warning.value = false;
}
// 최대 투표 수 제한 (예: 200)
isMaxReached.value = newValue >= 200;
});
// 투표 추가 함수
const addVote = () => {
if (!isMaxReached.value) {
voteCount.value++;
}
};
// 투표 취소 함수
const removeVote = () => {
if (voteCount.value > 0) {
voteCount.value--;
}
};
return {
voteCount,
warning,
isMaxReached,
addVote,
removeVote
};
}
};
</script>
<style>
.vote-dashboard {
padding: 20px;
border: 2px solid #007bff;
border-radius: 8px;
max-width: 400px;
text-align: center;
}
.warning {
color: red;
font-weight: bold;
margin-top: 10px;
}
button {
margin: 5px;
padding: 8px 16px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
}
button:disabled {
background-color: #ccc;
}
</style>
시나리오 전개
-
초기 상태: 투표 수가 0으로 시작하며, "투표 추가"와 "투표 취소" 버튼이 표시됩니다.
-
투표 추가: 사용자가 "투표 추가" 버튼을 클릭하면 voteCount가 증가하고, watch가 변경을 감지해 콘솔에 기록합니다.
-
경고 조건: 투표 수가 100을 넘으면 경고 메시지가 화면에 표시됩니다.
-
최대 제한: 투표 수가 200에 도달하면 "투표 추가" 버튼이 비활성화됩니다.
-
투표 취소: "투표 취소" 버튼으로 투표 수를 줄일 수 있으며, 0 이하로는 내려가지 않습니다.
실무에서의 고도화된 활용
-
서버 동기화: watch 내에서 투표 수 변경 시 서버로 PATCH 요청을 보내 실시간 동기화.
-
타임스탬프 기록: 투표 변경 시 Date.now()를 사용해 언제 변경되었는지 로그에 추가.
-
사용자 피드백: 경고 메시지 대신 모달 창이나 토스트 알림으로 UX 개선.
-
다중 항목 지원: voteCount를 객체 배열로 확장해 여러 투표 항목을 관리 가능.
추가 개선 예시
watch(voteCount, async (newValue) => {
try {
await fetch('/api/update-votes', {
method: 'PATCH',
body: JSON.stringify({ votes: newValue })
});
console.log('서버에 투표 수 업데이트 완료');
} catch (error) {
console.error('업데이트 실패:', error);
}
});
마무리
이 예제는 단순한 카운터를 넘어 실시간 데이터 모니터링과 조건 기반 피드백을 포함한 고도화된 기능을 보여줍니다. Vue.js의 watch와 ref를 활용하면 복잡한 비즈니스 로직도 깔끔하게 관리할 수 있습니다. 실무에서 이런 패턴을 적용하면 유지보수성과 확장성이 크게 향상될 겁니다!
728x90
Vue.js로 지역별 판매량 그리드 구현하기
판매 데이터 분석 대시보드
당신은 소매업체의 데이터 분석 대시보드를 개발 중입니다. 각 지역별로 월별 판매량을 표시하고, 각 행과 열의 합계 및 평균을 자동으로 계산해 보여줘야 합니다. 사용자는 데이터를 한눈에 파악하고, 필요 시 특정 값을 수정할 수 있어야 합니다. Vue.js의 ref로 데이터 상태를 관리하고, computed로 합계와 평균을 계산하며, 그리드 UI로 이를 시각화해보겠습니다.
코드 예제
<template>
<div class="sales-grid">
<h2>지역별 월별 판매량 (단위: 개)</h2>
<table>
<thead>
<tr>
<th>지역</th>
<th v-for="month in months" :key="month">{{ month }}</th>
<th>합계</th>
<th>평균</th>
</tr>
</thead>
<tbody>
<tr v-for="(region, index) in salesData" :key="region.name">
<td>{{ region.name }}</td>
<td v-for="(sales, monthIdx) in region.sales" :key="monthIdx">
<input
type="number"
v-model.number="salesData[index].sales[monthIdx]"
min="0"
@input="logChange(region.name, months[monthIdx], $event.target.value)"
/>
</td>
<td>{{ rowTotals[index] }}</td>
<td>{{ rowAverages[index] }}</td>
</tr>
<tr class="totals-row">
<td>합계</td>
<td v-for="(total, idx) in columnTotals" :key="idx">{{ total }}</td>
<td>{{ grandTotal }}</td>
<td>-</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { ref, computed } from 'vue';
export default {
setup() {
const months = ['1월', '2월', '3월']; // 월 목록
const salesData = ref([
{ name: '서울', sales: [120, 150, 180] },
{ name: '부산', sales: [90, 110, 130] },
{ name: '대구', sales: [70, 85, 95] }
]); // 지역별 판매량 데이터
// 행별 합계 계산
const rowTotals = computed(() => {
return salesData.value.map(region =>
region.sales.reduce((sum, sales) => sum + sales, 0)
);
});
// 행별 평균 계산
const rowAverages = computed(() => {
return salesData.value.map(region =>
(region.sales.reduce((sum, sales) => sum + sales, 0) / months.length).toFixed(2)
);
});
// 열별 합계 계산
const columnTotals = computed(() => {
return months.map((_, monthIdx) =>
salesData.value.reduce((sum, region) => sum + region.sales[monthIdx], 0)
);
});
// 전체 합계 계산
const grandTotal = computed(() => {
return rowTotals.value.reduce((sum, total) => sum + total, 0);
});
// 변경 로그 기록
const logChange = (region, month, newValue) => {
console.log(`${region}의 ${month} 판매량이 ${newValue}로 변경됨`);
// 실무에서는 서버로 업데이트 요청 가능
// 예: updateSalesData(region, month, newValue);
};
return {
months,
salesData,
rowTotals,
rowAverages,
columnTotals,
grandTotal,
logChange
};
}
};
</script>
<style>
.sales-grid {
padding: 20px;
max-width: 800px;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ccc;
padding: 8px;
text-align: center;
}
th {
background-color: #f4f4f4;
}
input[type="number"] {
width: 60px;
padding: 4px;
text-align: center;
}
.totals-row {
font-weight: bold;
background-color: #f9f9f9;
}
</style>
시나리오 전개
-
초기 상태: salesData에 서울, 부산, 대구의 1~3월 판매량이 초기값으로 설정됩니다.
-
데이터 수정: 사용자가 <input> 필드에서 값을 변경하면 salesData가 실시간으로 업데이트됩니다.
-
합계와 평균 계산:
-
rowTotals: 각 지역의 월별 판매량 합계.
-
rowAverages: 각 지역의 월별 평균 판매량.
-
columnTotals: 각 월의 지역별 합계.
-
grandTotal: 전체 판매량 합계.
-
-
변경 감지: 값이 변경될 때마다 logChange 함수가 호출되어 콘솔에 기록됩니다.
실무에서의 고도화된 활용
-
데이터 유효성 검사: 입력값이 음수일 경우 경고를 띄우고 이전 값으로 롤백.
logChange(region, month, newValue) { if (newValue < 0) { alert('판매량은 음수가 될 수 없습니다!'); return; } console.log(`${region}의 ${month} 판매량이 ${newValue}로 변경됨`); }
-
서버 연동: watch를 추가해 데이터 변경 시 서버로 동기화.
watch(salesData, async (newData) => { await fetch('/api/update-sales', { method: 'POST', body: JSON.stringify(newData) }); }, { deep: true });
-
필터링 및 정렬: 지역명 클릭 시 판매량 기준으로 정렬하거나, 특정 월만 표시하는 필터 추가.
마무리
이 예제는 computed를 활용해 복잡한 데이터 계산을 효율적으로 처리하며, 엑셀과 유사한 인터랙티브 그리드를 구현했습니다. 실무에서는 여기에 차트 연동, 데이터 내보내기(CSV/Excel), 다중 사용자 동시 편집 등의 기능을 추가해 더욱 강력한 대시보드로 확장할 수 있습니다.
728x90
'Vue.js 를 배워보자' 카테고리의 다른 글
GSAP와 Vue.js로 만드는 화려한 애니메이션 예제 (0) | 2025.03.15 |
---|---|
Vue.js로 실시간 판매량 그리드에 부드러운 숫자 애니메이션 구현하기 (0) | 2025.03.14 |
Vue.js 그리드 데이터 흐름 제어: 임시 이동, 커서 위치 갱신, 롤백, 반응형 데이터 처리 A to Z (0) | 2025.03.13 |
Vue.js와 Axios로 데이터셋을 그리드로 로딩하고 클릭 시 Input Text에 자동 바인딩하기 (0) | 2025.03.04 |
Vue.js에서 JSON Server 포트 변경하기 (0) | 2025.03.02 |