728x90

안녕하세요, 개발자 여러분! 오늘은 Vue.js와 TypeScript를 사용해 실무에서 자주 접할 수 있는 컴포넌트 설계와 코드 공유 사례를 다뤄보겠습니다. 이번 예제에서는 배송 정보를 다루는 Delivery.vue 컴포넌트와 그 하위 컴포넌트인 DeliveryDetails.vue를 만들고, TypeScript 파일(Delivery.ts)을 공유하며 실무처럼 구현하는 방법을 소개합니다. 특히 DeliveryDetails.vue에서 그리드 UI를 활용해 배송 세부 항목을 표시한다고 가정하고, 타입 정의를 효율적으로 재사용하는 방법을 살펴보겠습니다.
1. 프로젝트 구조와 기본 설정
먼저 프로젝트 구조를 간단히 정리해보겠습니다.
src/
├── components/
│ ├── Delivery.vue # 배송 기본 정보 컴포넌트
│ └── DeliveryDetails.vue # 배송 세부 항목 컴포넌트 (그리드 포함)
├── types/
│ └── Delivery.ts # 타입 정의 파일
Delivery.vue는 배송의 기본 정보를 표시하고, DeliveryDetails.vue는 그리드 형태로 세부 항목(예: 주문 번호, 배송 상태 등)을 보여줍니다. 이 두 컴포넌트는 Delivery.ts에서 정의된 타입을 공유합니다.
728x90
2. Delivery.ts - 타입 정의
먼저 Delivery.ts 파일에서 배송 정보와 관련된 타입을 정의합니다. 실무에서는 API 응답이나 데이터베이스 스키마를 기반으로 타입을 설계하므로, 이를 반영해 작성해보겠습니다.
// src/types/Delivery.ts
export interface DeliveryInfo {
id: number;
recipient: string;
address: string;
status: 'pending' | 'shipped' | 'delivered' | 'canceled';
createdAt: string;
}
export interface DeliveryDetail {
orderId: string;
itemName: string;
quantity: number;
price: number;
status: string;
}
// 전체 배송 데이터 타입 (필요 시 확장 가능)
export type DeliveryData = DeliveryInfo & {
details: DeliveryDetail[];
};
-
DeliveryInfo: 배송의 기본 정보(수령인, 주소 등)를 정의합니다.
-
DeliveryDetail: 배송 세부 항목(주문 ID, 상품명 등)을 정의합니다.
-
DeliveryData: 두 타입을 결합해 전체 데이터를 나타냅니다.
이 타입들은 Delivery.vue와 DeliveryDetails.vue에서 공유되며, 코드 중복을 줄이고 타입 안정성을 보장합니다.
3. Delivery.vue - 부모 컴포넌트
Delivery.vue는 배송 기본 정보를 표시하고, 하위 컴포넌트인 DeliveryDetails.vue를 포함합니다. TypeScript를 사용해 타입을 명시적으로 지정합니다.
<!-- src/components/Delivery.vue -->
<template>
<div class="delivery-container">
<h2>배송 정보</h2>
<p>수령인: {{ delivery.recipient }}</p>
<p>주소: {{ delivery.address }}</p>
<p>상태: {{ delivery.status }}</p>
<DeliveryDetails :details="delivery.details" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { DeliveryData } from '@/types/Delivery'; // 타입 임포트
import DeliveryDetails from './DeliveryDetails.vue'; // 하위 컴포넌트 임포트
export default defineComponent({
name: 'Delivery',
components: { DeliveryDetails },
props: {
delivery: {
type: Object as () => DeliveryData,
required: true,
},
},
});
</script>
<style scoped>
.delivery-container {
padding: 20px;
border: 1px solid #ddd;
}
</style>
-
설명:
-
DeliveryData 타입을 가져와 props에 적용합니다.
-
DeliveryDetails 컴포넌트에 details 데이터를 전달합니다.
-
4. DeliveryDetails.vue - 자식 컴포넌트 (그리드 포함)
DeliveryDetails.vue는 세부 항목을 그리드 형태로 표시합니다. 여기서는 간단히 <table> 태그로 그리드를 구현하지만, 실무에서는 ag-Grid나 Vuetify 같은 라이브러리를 사용할 수도 있습니다.
<!-- src/components/DeliveryDetails.vue -->
<template>
<div class="delivery-details">
<h3>배송 세부 항목</h3>
<table class="grid-table">
<thead>
<tr>
<th>주문 ID</th>
<th>상품명</th>
<th>수량</th>
<th>가격</th>
<th>상태</th>
</tr>
</thead>
<tbody>
<tr v-for="item in details" :key="item.orderId">
<td>{{ item.orderId }}</td>
<td>{{ item.itemName }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }}원</td>
<td>{{ item.status }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { DeliveryDetail } from '@/types/Delivery'; // 타입 임포트
export default defineComponent({
name: 'DeliveryDetails',
props: {
details: {
type: Array as () => DeliveryDetail[],
required: true,
},
},
});
</script>
<style scoped>
.delivery-details {
margin-top: 20px;
}
.grid-table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ccc;
padding: 8px;
text-align: left;
}
th {
background-color: #f5f5f5;
}
</style>
-
설명:
-
Delivery.ts에서 가져온 DeliveryDetail 타입을 props에 적용합니다.
-
그리드는 <table>로 간단히 구현했으며, v-for를 사용해 데이터를 동적으로 렌더링합니다.
-
5. 사용 예제
이제 최상위 컴포넌트(예: App.vue)에서 Delivery.vue를 사용하는 방법을 보겠습니다.
<!-- src/App.vue -->
<template>
<div>
<Delivery :delivery="sampleDelivery" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import Delivery from './components/Delivery.vue';
import { DeliveryData } from './types/Delivery';
export default defineComponent({
components: { Delivery },
data() {
return {
sampleDelivery: {
id: 1,
recipient: '홍길동',
address: '서울시 강남구 테헤란로 123',
status: 'shipped',
createdAt: '2025-03-29',
details: [
{ orderId: 'ORD001', itemName: '노트북', quantity: 1, price: 1500000, status: '배송 중' },
{ orderId: 'ORD002', itemName: '마우스', quantity: 2, price: 50000, status: '배송 준비' },
],
} as DeliveryData,
};
},
});
</script>
6. 실무 팁
-
타입 재사용: Delivery.ts를 통해 타입을 중앙에서 관리하면, 코드 변경 시 한 곳만 수정하면 됩니다.
-
그리드 확장: 실무에서는 ag-Grid 같은 라이브러리를 도입해 필터링, 정렬, 페이지네이션 기능을 추가할 수 있습니다.
-
에러 처리: API 호출 시 타입 안정성을 유지하려면 axios와 같은 라이브러리에 DeliveryData를 적용하세요.

마무리
이처럼 Vue.js와 TypeScript를 결합하면 컴포넌트 간 데이터 흐름을 명확히 하고, 유지보수를 쉽게 할 수 있습니다. Delivery.vue와 DeliveryDetails.vue가 Delivery.ts를 공유하며 타입 안정성을 확보한 예제를 통해 실무에서의 활용성을 느껴보셨길 바랍니다.
728x90
'Vue.js 를 배워보자' 카테고리의 다른 글
Vue CRUD UI 구성 시 watch와 computed 활용하기 (0) | 2025.04.01 |
---|---|
TypeScript에서 & 연산자의 의미와 활용: DeliveryData 예제를 중심으로 (0) | 2025.03.29 |
Vue에서 반응형 Lookup 객체로 라디오그룹, 콤보박스, 체크박스 관리하기 (0) | 2025.03.27 |
Vue.js에서 사용되는 모든 특수문자 완벽 정리 (0) | 2025.03.25 |
Vue.js에서 watch로 버튼과 그리드의 disabled 상태 동적 제어하기 (0) | 2025.03.16 |