diff --git a/plm-api/src/controllers/app/salesmgmt/contractwbs.controller.js b/plm-api/src/controllers/app/salesmgmt/contractwbs.controller.js
new file mode 100644
index 0000000..1496bfd
--- /dev/null
+++ b/plm-api/src/controllers/app/salesmgmt/contractwbs.controller.js
@@ -0,0 +1,113 @@
+// src/controllers/admin/users/users.controller.js
+const express = require("express");
+const router = express.Router();
+const Service = require("../../../services/contractwbs.service");
+const authMiddleware = require("../../../middleware/auth.middleware");
+const roleCheck = require("../../../middleware/roleCheck.middleware");
+const { body, param } = require("express-validator");
+const validate = require("../../../middleware/validator.middleware");
+
+router.use(authMiddleware);
+router.use(roleCheck(["super_admin", "company_admin"]));
+
+// 고객사 목록 조회
+router.get("/contractwbsList", async (req, res, next) => {
+  try {
+    const page = parseInt(req.query.page) || 1;
+    const limit = parseInt(req.query.limit) || 10;
+
+    const result = await Service.selectList(req.user, page, limit);
+    res.json(result);
+  } catch (error) {
+    next(error);
+  }
+});
+
+// Create WBS
+router.post(
+  "/Create",
+  [
+    body("oem_id").notEmpty().withMessage("고객사가 필요합니다"),
+    body("product_group_id").notEmpty().withMessage("제품군이 필요합니다"),
+    body("companyId").isUUID().withMessage("유효한 회사 ID가 필요합니다"),
+    validate,
+  ],
+  async (req, res, next) => {
+    try {
+      const carMng = await Service.create(req.body, req.user);
+      res.status(201).json(carMng);
+    } catch (error) {
+      next(error);
+    }
+  }
+);
+
+// Update
+router.put(
+  "/Update/:id",
+  [
+    param("id").isUUID().withMessage("유효한 ID가 필요합니다"),
+    body("oem_id").optional().notEmpty().withMessage("고객사가 필요합니다"),
+    body("companyId").optional().isUUID().withMessage("유효한 회사 ID가 필요합니다"),
+    validate,
+  ],
+  async (req, res, next) => {
+    try {
+      const carMng = await Service.findById(req.params.id);
+
+      if (!carMng) {
+        return res.status(404).json({ message: "고객사를 찾을 수 없습니다" });
+      }
+
+      // company_admin은 자신의 회사 고객사만 수정 가능
+      if (
+        req.user.role === "company_admin" &&
+        carMng.companyId !== req.user.companyId
+      ) {
+        return res.status(403).json({
+          message: "다른 회사의 고객사를 수정할 수 없습니다",
+        });
+      }
+
+      const updatedcarMng = await Service.update(req.params.id, req.body, req.user);
+      res.json(updatedcarMng);
+    } catch (error) {
+      next(error);
+    }
+  }
+);
+
+// Delete CarMng
+router.delete(
+  "/Delete/:id",
+  [
+    param("id").isUUID().withMessage("유효한 ID가 필요합니다"),
+    validate,
+  ],
+  async (req, res, next) => {
+    try {
+      const carMng = await Service.findById(req.params.id);
+
+      if (!carMng) {
+        return res.status(404).json({ message: "고객사를 찾을 수 없습니다" });
+      }
+
+      // company_admin은 자신의 회사 고객사만 삭제 가능
+      if (
+        req.user.role === "company_admin" &&
+        carMng.companyId !== req.user.companyId
+      ) {
+        return res.status(403).json({
+          message: "다른 회사의 고객사를 삭제할 수 없습니다",
+        });
+      }
+
+      await Service.deleteCarMng(req.params.id, req.user);
+      res.status(204).end();
+    } catch (error) {
+      next(error);
+    }
+  }
+);
+
+module.exports = router;
diff --git a/plm-api/src/models/Company.js b/plm-api/src/models/Company.js
index d4690b5..58103f9 100644
--- a/plm-api/src/models/Company.js
+++ b/plm-api/src/models/Company.js
@@ -70,6 +70,8 @@ class Company extends Model {
     this.hasMany(models.OemMng, { foreignKey: "companyId" });
     this.hasMany(models.ProductGroup, { foreignKey: "companyId" });
     this.hasMany(models.Product, { foreignKey: "companyId" });
+    this.hasMany(models.ContractWbs, { foreignKey: "companyId" });
+    
   }
 }
 
diff --git a/plm-api/src/models/ContractWbs.js b/plm-api/src/models/ContractWbs.js
new file mode 100644
index 0000000..190c8c0
--- /dev/null
+++ b/plm-api/src/models/ContractWbs.js
@@ -0,0 +1,73 @@
+// models/ContractWbs.js
+
+const { Model, DataTypes } = require("sequelize");
+
+class ContractWbs extends Model {
+  static init(sequelize) {
+    super.init(
+      {
+        id: {
+          type: DataTypes.UUID,
+          defaultValue: DataTypes.UUIDV4,
+          primaryKey: true,
+        },
+           // 고객사 ID
+           oem_id: {
+            type: DataTypes.UUID,
+            comment: "고객사 ID",
+          },      
+           // 고객사 ID
+           product_group_id: {
+            type: DataTypes.UUID,
+            comment: "제품군 ID",
+          },              
+        writer: {
+          type: DataTypes.STRING(32),
+          allowNull: true,
+          comment: "작성자",
+        },
+        isActive: {
+          type: DataTypes.BOOLEAN,
+          defaultValue: true,
+        },
+        // 새로 추가할 필드들
+        companyId: {
+          type: DataTypes.UUID,
+          comment: "회사 ID",
+        },
+      },
+      {
+        sequelize,
+        modelName: 'ContractWbs',
+        tableName: 'contractwbs',
+        timestamps: true,  
+        indexes: [
+          {
+            fields: ['id'],  
+          },
+        ],
+      }
+    );
+    return this;
+  }
+
+  static associate(models) {
+    // car가 Company에 속함
+    this.belongsTo(models.Company, { foreignKey: "companyId" });
+
+    // wbs가 OEM에 속함
+    this.belongsTo(models.OemMng, { 
+      foreignKey: "oem_id",
+      as: "oem"  // alias 설정
+    });
+
+    // wbs가  제품군에 속함
+    this.belongsTo(models.ProductGroup, { 
+      foreignKey: "product_group_id",
+      as: "productgroup"  // alias 설정
+    });
+  }
+
+}
+
+module.exports = ContractWbs;
\ No newline at end of file
diff --git a/plm-api/src/routes/app.js b/plm-api/src/routes/app.js
index d95b427..e9592be 100644
--- a/plm-api/src/routes/app.js
+++ b/plm-api/src/routes/app.js
@@ -21,7 +21,7 @@ const oemMngController = require("../controllers/app/common/oemmng.controller");
 const productgroupController = require("../controllers/app/common/productgroup.controller");
 const productController = require("../controllers/app/common/product.controller");
 const carMngController = require("../controllers/app/common/carmng.controller");
-const contractController = require("../controllers/app/contract/contract.controller");
+const contractWbsController = require("../controllers/app/salesmgmt/contractwbs.controller");
 
 router.use("/health", healthController);
 router.use("/auth", authController);
@@ -42,6 +42,6 @@ router.use("/oemmng", oemMngController);
 router.use("/productgroup", productgroupController);
 router.use("/product", productController);
 router.use("/carmng", carMngController);
-router.use("/contract", contractController);
+router.use("/contractwbs", contractWbsController);
 
 module.exports = router;
diff --git a/plm-api/src/services/contractwbs.service.js b/plm-api/src/services/contractwbs.service.js
new file mode 100644
index 0000000..a43d3b5
--- /dev/null
+++ b/plm-api/src/services/contractwbs.service.js
@@ -0,0 +1,181 @@
+const {
+  ContractWbs,
+  Company,
+  Role,
+  OemMng,
+  ProductGroup,
+} = require("../models");
+//const { Op } = require("sequelize");
+const alertService = require("./alert.service");
+
+class ContractWbsService {
+  async selectList(currentUser, page = 1, limit = 10) {
+    try {
+      // Initialize the where clause
+      let where = {};
+
+      // company_admin은 자신의 회사 유저만 조회 가능
+      if (currentUser.role === "company_admin") {
+        where.companyId = currentUser.companyId;
+      }
+      // isActive 필터 추가
+      //where.isActive = { [Op.eq]: true };
+
+      const offset = (page - 1) * limit;
+
+      // 전체 개수 조회
+      const count = await ContractWbs.count({ where });
+
+      const resultData = await ContractWbs.findAll({
+        where,
+        include: [
+          {
+            model: Company,
+            attributes: ["id", "name"],
+          },
+          {
+            model: OemMng,
+            as: "oem",
+            attributes: ["oem_name"],
+          },
+          {
+            model: ProductGroup,
+            as: "productgroup",
+            attributes: ["product_group_name"],
+          },
+        ],
+        order: [["createdAt", "DESC"]],
+        offset,
+        limit,
+        distinct: true,
+      });
+
+      // 인덱스 추가
+      const WithIndex = resultData.map((car, index) => {
+        const Json = car.toJSON();
+        Json.index = offset + index + 1;
+        return Json;
+      });
+
+      return {
+        total: count,
+        totalPages: Math.ceil(count / limit),
+        currentPage: page,
+        resultData: WithIndex,
+      };
+    } catch (error) {
+      console.error("Error in findAll:", error);
+      throw error;
+    }
+  }
+
+  async findById(id) {
+    return await ContractWbs.findByPk(id, {
+      include: [
+        {
+          model: Company,
+          attributes: ["id", "name"],
+        },
+      ],
+    });
+  }
+
+  async create(SaveData, currentUser) {
+    const { roleId, ...Fields } = SaveData;
+
+    // 등록자 정보 추가
+    Fields.writer = currentUser.name;
+    Fields.regdate = new Date();
+
+    const ResultData = await ContractWbs.create(Fields);
+
+    if (roleId) {
+      const role = await Role.findOne({
+        where: {
+          id: roleId,
+          companyId: ResultData.companyId,
+        },
+      });
+
+      if (!role) {
+        throw new Error("Role not found or does not belong to the company");
+      }
+
+      await ContractWbs.addRole(role);
+    }
+
+    await alertService.createAlert({
+      type: "info",
+      message: `영업WBS가 ${currentUser.name}에 의해 생성되었습니다.`,
+      companyId: ResultData.companyId,
+    });
+
+    return ResultData;
+  }
+
+  async update(id, updateData, currentUser) {
+    const { roleId, ...carMngFields } = updateData;
+
+    const carMng = await ContractWbs.findByPk(id);
+    if (!carMng) throw new Error("CarMng not found");
+
+    // company_admin 권한 체크
+    if (currentUser.role === "company_admin") {
+      if (updateData.role && updateData.role === "super_admin") {
+        throw new Error("super_admin 역할을 부여할 수 없습니다");
+      }
+      updateData.companyId = currentUser.companyId;
+    }
+
+    // where 조건을 포함하여 업데이트
+    await ContractWbs.update(carMngFields, {
+      where: { id: id }
+    });
+
+    // 업데이트된 데이터 조회
+    const updatedCarMng = await ContractWbs.findByPk(id);
+
+    if (roleId) {
+      const role = await Role.findOne({
+        where: {
+          id: roleId,
+          companyId: carMng.companyId,
+        },
+      });
+
+      if (!role) {
+        throw new Error("Role not found or does not belong to the company");
+      }
+
+      await ContractWbs.addRole(role);
+    }
+
+    await alertService.createAlert({
+      type: "info",
+      message: `영업 WBS가 ${currentUser.name}에 의해 수정되었습니다.`,
+      companyId: carMng.companyId,
+    });
+
+    return updatedCarMng;
+  }
+
+  async deleteData(id, currentUser) {
+    const carMng = await ContractWbs.findByPk(id);
+    if (!carMng) throw new Error("CarMng not found");
+
+    const carMngName = carMng.name;
+    const companyId = carMng.companyId;
+
+    await carMng.destroy();
+
+    await alertService.createAlert({
+      type: "info",
+      message: `영업 WBS가 ${currentUser.name}에 의해 삭제되었습니다.`,
+      companyId: companyId,
+    });
+
+    return true;
+  }
+}
+
+module.exports = new ContractWbsService();
\ No newline at end of file
diff --git a/plm-app/src/app/(user)/layout.tsx b/plm-app/src/app/(user)/layout.tsx
new file mode 100644
index 0000000..3ede07b
--- /dev/null
+++ b/plm-app/src/app/(user)/layout.tsx
@@ -0,0 +1,32 @@
+// src/app/(admin)/layout.tsx
+import React from "react";
+import AdminGuard from "@/components/auth/AdminGuard";
+import { SideNav } from "@/components/layout/SideNav";
+import { TopNav } from "@/components/layout/TopNav";
+
+const AdminLayout = ({ children }: { children: React.ReactNode }) => {
+  return (
+    <AdminGuard>
+      <div className="h-screen flex">
+        {/* 왼쪽 사이드바 */}
+        <aside className="w-64 h-screen flex-shrink-0 bg-gray-800">
+          <SideNav />
+        </aside>
+        {/* 오른쪽 메인 영역 */}
+        <div className="flex-1 flex flex-col">
+          {/* 상단 헤더 */}
+          <header className="h-16 bg-white border-b">
+            <TopNav />
+          </header>
+
+          {/* 메인 컨텐츠 영역 */}
+          <main className="flex-1 overflow-auto bg-gray-50 p-2">
+            {children}
+          </main>
+        </div>
+      </div>
+    </AdminGuard>
+  );
+};
+
+export default AdminLayout;
diff --git a/plm-app/src/app/(user)/salesmgmt/contractwbs/components/ContractWbsForm.tsx b/plm-app/src/app/(user)/salesmgmt/contractwbs/components/ContractWbsForm.tsx
new file mode 100644
index 0000000..c915b09
--- /dev/null
+++ b/plm-app/src/app/(user)/salesmgmt/contractwbs/components/ContractWbsForm.tsx
@@ -0,0 +1,257 @@
+import React, { useEffect, useState } from "react";
+import { useForm } from "react-hook-form";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Switch } from "@/components/ui/switch";
+import { contractWbs} from "@/types/salesmgmt/contractwbs";
+import {
+  Form,
+  FormControl,
+  FormField,
+  FormItem,
+  FormLabel,
+  FormMessage,
+} from "@/components/ui/form";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; // Select 컴포넌트 임포트 추가
+import { api } from "@/lib/api"; // API 호출을 위한 임포트 추가
+
+interface CarFormProps {
+  initialData?: Partial<contractWbs>;
+  onSubmit: (data: Partial<contractWbs>) => void;
+  onCancel: () => void;
+}
+
+export const ContractWbsForm: React.FC<CarFormProps> = ({
+  initialData,
+  onSubmit,
+  onCancel,
+}) => {
+  const form = useForm({
+    defaultValues: {
+      oem_id: initialData?.oem_id || "",
+      product_group_id: initialData?.product_group_id || "",
+      isActive: initialData?.isActive || false,
+    },
+  });
+
+
+  const [productGroups, setProductGroups] = useState([]);
+  const [oems, setoems] = useState([]);
+  
+    useEffect(() => {
+      const fetchSelectOptions = async (modelName, orderField) => {
+        try {
+          const response = await api.get("/api/v1/app/common/select-options", {
+            params: { modelName, orderField },
+          });
+          console.log("Fetched select options:", response.data.data); // 디버깅 로그 추가
+          setProductGroups(response.data.data);
+        } catch (error) {
+          console.error("Failed to fetch select options:", error);
+        }
+      };
+  
+      const fetchSelectOptions1 = async (modelName, orderField) => {
+        try {
+          const response = await api.get("/api/v1/app/common/select-options", {
+            params: { modelName, orderField },
+          });
+          console.log("Fetched select options:", response.data.data); // 디버깅 로그 추가
+          setoems(response.data.data);
+          console.log(response.data.data);
+        } catch (error) {
+          console.error("Failed to fetch select options:", error);
+        }
+      };
+  
+      fetchSelectOptions("OemMng", "oem_name");
+      fetchSelectOptions1("ProductGroup","product_group_name"); 
+    }, []);
+
+
+  return (
+    <Form {...form}>
+      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
+      <div className="grid grid-cols-2 gap-4">
+          <div>
+            <div className="flex items-center gap-4">
+              <div className="w-24 p-2 text-center">
+                <FormLabel>고객사</FormLabel>
+              </div>
+              <FormField
+                        control={form.control}
+                        name="oem_id"
+                        validation={{
+                          required: "고객사는 필수 입력값입니다",
+                        }}
+                        render={({ field }) => (
+                          <FormItem>
+                            <FormControl>
+                              <Select onValueChange={field.onChange} value={field.value}>
+                                <SelectTrigger>
+                                  <SelectValue placeholder="고객사를 선택하세요" />
+                                </SelectTrigger>
+                                <SelectContent>
+                                  {productGroups.map((option) => (
+                                    <SelectItem key={option.id} value={option.id}>
+                                      {option.oem_name}
+                                    </SelectItem>
+                                  ))}
+                                </SelectContent>
+                              </Select>
+                            </FormControl>
+                            <FormMessage />
+                          </FormItem>
+                        )}
+                      />
+            </div>
+          </div>
+          <div>
+            <div className="flex items-center gap-4">
+              <div className="w-36 p-2 text-center">
+                <FormLabel>제품군</FormLabel>
+              </div>
+              <FormField
+                        control={form.control}
+                        name="product_group_id"
+                        validation={{
+                          required: "제품군은 필수 입력값입니다",
+                        }}
+                        render={({ field }) => (
+                          <FormItem>
+                            <FormControl>
+                              <Select onValueChange={field.onChange} value={field.value}>
+                                <SelectTrigger>
+                                  <SelectValue placeholder="제품군를 선택하세요" />
+                                </SelectTrigger>
+                                <SelectContent>
+                                  {oems.map((option) => (
+                                    <SelectItem key={option.id} value={option.id}>
+                                      {option.product_group_name}
+                                    </SelectItem>
+                                  ))}
+                                </SelectContent>
+                              </Select>
+                            </FormControl>
+                            <FormMessage />
+                          </FormItem>
+                        )}
+                      />
+            </div>
+          </div>
+        </div>
+        <div className="grid grid-cols-2 gap-4">
+          <div>
+            <div className="flex items-center gap-4">
+              <div className="w-24 p-2 text-center">
+                <FormLabel>ㅅㅅㅅ</FormLabel>
+              </div>
+              
+            </div>
+          </div>
+          <div>
+            <div className="flex items-center gap-4">
+              <div className="w-36 p-2 text-center">
+              <FormLabel>활성화</FormLabel>
+              </div>
+                      <FormField
+                        control={form.control}
+                        name="isActive"
+                        render={({ field }) => (
+                          <FormItem>
+                            <div className="flex items-center gap-2">
+                              <FormControl>
+                                <Switch
+                                  checked={field.value}
+                                  onCheckedChange={field.onChange}
+                                />
+                              </FormControl>
+                            </div>
+                            <FormMessage />
+                          </FormItem>
+                        )}
+                      />
+            </div>
+          </div>
+        </div>
+
+
+        <div className="grid grid-cols-2 gap-4">
+          <div>
+            <div className="flex items-center gap-4">
+              <div className="w-24 p-2 text-center">
+                <FormLabel>모델명</FormLabel>
+              </div>
+              <FormField
+                control={form.control}
+                name="model_name"
+                validation={{
+                  required: "모델명은 필수 입력값입니다",
+                  maxLength: { value: 64, message: "최대 64자까지 입력 가능합니다" }
+                }}
+                render={({ field }) => (
+                  <FormItem className="flex-1">
+                    <FormControl>
+                      <Input {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </div>
+          </div>
+          <div>
+            <div className="flex items-center gap-4">
+              <div className="w-36 p-2 text-center">
+                 <FormLabel>모델코드</FormLabel>
+              </div>
+              <FormField
+                control={form.control}
+                name="model_code"
+                validation={{
+                  required: "모델코드는 필수 입력값입니다",
+                  maxLength: { value: 64, message: "최대 64자까지 입력 가능합니다" }
+                }}
+                render={({ field }) => (
+                  <FormItem className="flex-1">
+                    <FormControl>
+                      <Input {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </div>
+          </div>
+        </div>
+
+        <FormField
+          control={form.control}
+          name="car_desc"
+          render={({ field }) => (
+            <FormItem>
+              <div className="flex items-center gap-4">
+                <div className="w-24 p-2 text-center">
+                  <FormLabel>설명</FormLabel>
+                </div>
+                <FormControl className="flex-1">
+                  <Input {...field} />
+                </FormControl>
+              </div>
+              <FormMessage />
+            </FormItem>
+          )}
+        />
+
+        <div className="flex justify-end gap-2">
+          <Button type="button" variant="outline" onClick={onCancel}>
+            취소
+          </Button>
+          <Button type="submit">
+            {initialData ? "수정" : "저장"}
+          </Button>
+        </div>
+      </form>
+    </Form>
+  );
+};
\ No newline at end of file
diff --git a/plm-app/src/app/(user)/salesmgmt/contractwbs/page.tsx b/plm-app/src/app/(user)/salesmgmt/contractwbs/page.tsx
new file mode 100644
index 0000000..b34333c
--- /dev/null
+++ b/plm-app/src/app/(user)/salesmgmt/contractwbs/page.tsx
@@ -0,0 +1,353 @@
+"use client";
+
+import React, { useState, useCallback, useMemo } from "react";
+import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { DataTable } from "@/components/ui/data-table";
+import { api } from "@/lib/api";
+import { Button } from "@/components/ui/button";
+import {
+  Dialog,
+  DialogContent,
+  DialogHeader,
+  DialogTitle,
+  DialogDescription,
+} from "@/components/ui/dialog";
+import { useToast } from "@/hooks/use-toast";
+import { Plus, Edit, Trash2, Search } from "lucide-react";
+import { ColumnDef } from "@tanstack/react-table";
+import { useAuthStore } from "@/stores/auth";
+import { AxiosError } from "axios";
+import { ContractWbsForm } from "./components/ContractWbsForm";
+import { Switch } from "@/components/ui/switch";
+import { contractWbs, PaginatedResponse } from "@/types/salesmgmt/contractwbs";
+import { PLMTable } from "@/components/common/Table";
+import { Input } from "@/components/ui/input";
+
+const Page = () => {
+  const { token, user } = useAuthStore();
+  const [isOpen, setIsOpen] = React.useState(false);
+  const [editingUser, setEditingUser] = React.useState<contractWbs | null>(null);
+  const [page, setPage] = useState(1);
+  const [pageSize, setPageSize] = useState(10);
+  const { toast } = useToast();
+  const queryClient = useQueryClient();
+  const [currentPageSize, setCurrentPageSize] = useState(20); // 페이지 크기 상태 추가
+  const [searchQuery, setSearchQuery] = useState(""); // 검색어 상태 추가
+
+  // Fetch CARs with pagination
+  const { data, isLoading } = useQuery<PaginatedResponse>({
+    queryKey: ["contractWbs", page, pageSize],
+    queryFn: async () => {
+      const { data } = await api.get("/api/v1/app/contractwbs/contractwbsList", {
+        params: {
+          page,
+          limit: pageSize,
+        },
+      });
+      return {
+        ...data,
+        resultData: data.resultData.map((wbs: contractWbs) => ({  // resultData 사용
+          ...wbs,
+        })),
+      };
+    },
+    enabled: !!token,
+  });
+
+  const handlePageSizeChange = useCallback((newPageSize: number) => {
+    setPageSize(newPageSize);
+    setPage(1);
+  }, []);
+
+  // 필터링된 데이터 생성
+  const filteredWbsList = useMemo(() => {
+    if (!data?.resultData || !searchQuery) return data?.resultData;
+    
+    return data.resultData.filter(wbs => 
+      wbs.oem_id?.toLowerCase().includes(searchQuery.toLowerCase()) ||
+      wbs.product_group_id?.toLowerCase().includes(searchQuery.toLowerCase())
+    );
+  }, [data?.resultData, searchQuery]);
+
+  // Create user mutation
+  const createMutation = useMutation({
+    mutationFn: async (newCar: Partial<contractWbs>) => {
+      // Include companyId in the user data
+      const carWithCompanyId = {
+        ...newCar,
+        companyId: user?.companyId,
+      };
+
+      const { data } = await api.post<contractWbs>(
+        "/api/v1/app/contractwbs/Create",
+        carWithCompanyId
+      );
+      return data;
+    },
+    onSuccess: () => {
+      queryClient.invalidateQueries({ queryKey: ["contractWbs"] }); // carMngs에서 contractWbs로 수정
+      setIsOpen(false);
+      toast({
+        title: "영업 WBS 생성",
+        description: "새로운 영업 WBS 생성되었습니다.",
+      });
+    },
+    onError: (error: AxiosError) => {
+      toast({
+        title: "영업 WBS 생성 실패",
+        description: (error.response?.data as { message: string }).message,
+        variant: "destructive",
+      });
+    },
+  });
+
+  // Update user mutation
+  const updateMutation = useMutation({
+    mutationFn: async (contractWbsData: Partial<contractWbs>) => {
+      const { data } = await api.put<contractWbs>(
+        `/api/v1/app/contractwbs/Update/${contractWbsData.id}`,
+        contractWbsData
+      );
+      return data;
+    },
+    onSuccess: () => {
+      queryClient.invalidateQueries({ queryKey: ["contractWbs"] }); // carMngs에서 contractWbs로 수정
+      setIsOpen(false);
+      setEditingUser(null);
+      toast({
+        title: "영업 WBS 수정",
+        description: "영업 WBS 정보가 수정되었습니다.",
+      });
+    },
+    onError: (error: AxiosError) => {
+      toast({
+        title: "영업 WBS 수정 실패",
+        description: (error.response?.data as { message: string }).message,
+        variant: "destructive",
+      });
+    },
+  });
+
+  // Delete user mutation
+  const deleteMutation = useMutation({
+    mutationFn: async (id: string) => {
+      await api.delete(`/api/v1/app/contractwbs/Delete/${id}`);
+    },
+    onSuccess: () => {
+      queryClient.invalidateQueries({ queryKey: ["contractWbs"] }); // carMngs에서 contractWbs로 수정
+      toast({
+        title: "영업 WBS 삭제",
+        description: "영업 WBS가 삭제되었습니다.",
+      });
+    },
+    onError: (error: AxiosError) => {
+      toast({
+        title: "영업 WBS 삭제 실패",
+        description: (error.response?.data as { message: string }).message,
+        variant: "destructive",
+      });
+    },
+  });
+
+  // Table columns 수정
+  const columns: ColumnDef<contractWbs>[] = [
+    {
+      id: "index",
+      header: "No",
+      cell: ({ row }) => row.original.index,
+      meta: {
+        width: "60px",
+        textAlign: "center",
+      },
+    },
+    {
+      accessorKey: "oem.oem_name",  // 중첩 객체 접근 방식 확인
+      header: "고객사",
+      meta: {
+        width: "120px",
+        textAlign: "center",
+      },
+    },
+    {
+      accessorKey: "productgroup.product_group_name",  // 제품군 정보 표시
+      header: "제품군",
+      meta: {
+        width: "120px",
+        textAlign: "center",
+      },
+    },
+    {
+      accessorKey: "car_code",
+      header: "WBS",
+      meta: {
+        width: "120px",
+        textAlign: "center",
+      },
+    },
+    {
+      accessorKey: "writer",
+      header: "등록자",
+      meta: {
+        width: "120px",
+        textAlign: "center",
+      },
+    },
+    {
+      accessorKey: "updatedAt",
+      header: "등록일",
+      meta: {
+        width: "200px",
+        textAlign: "center",
+      },
+      cell: ({ row }) => {
+        const date = new Date(row.original.updatedAt);
+        return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
+      }
+    },
+    {
+      accessorKey: "isActive",
+      header: "상태",
+      meta: {
+        width: "100px",
+        textAlign: "center",
+      },
+      cell: ({ row }) => (
+        <div className="text-center">
+          <Switch
+            checked={row.original.isActive}
+            onCheckedChange={(value) => {
+              updateMutation.mutate({ id: row.original.id, isActive: value });
+            }}
+          />
+        </div>
+      ),
+    },
+    {
+      id: "actions",
+      header: "액션",
+      meta: {
+        width: "100px",
+        textAlign: "center",
+      },
+      cell: ({ row }) => (
+        <div className="flex items-center justify-center gap-2">
+          <Button
+            variant="ghost"
+            size="sm"
+            onClick={() => {
+              setEditingUser(row.original);
+              setIsOpen(true);
+            }}
+          >
+            <Edit className="h-4 w-4" />
+          </Button>
+          <Button
+            variant="ghost"
+            size="sm"
+            onClick={() => {
+              if (confirm("정말 삭제하시겠습니까?")) {
+                deleteMutation.mutate(row.original.id);
+              }
+            }}
+          >
+            <Trash2 className="h-4 w-4" />
+          </Button>
+        </div>
+      ),
+    },
+  ];
+
+  if (isLoading) return <div>Loading...</div>;
+
+  return (
+    <div className="w-full h-full">
+      <div className="bg-white rounded-lg shadow">
+        <div className="p-2 border-b border-gray-200">
+          <div className="flex justify-between items-center mb-3">
+            <div>
+              <h1 className="text-2xl font-semibold text-gray-900">영업 WBS관리</h1>
+              <p className="text-sm text-gray-500">
+              영업 WBS를 관리합니다.
+              </p>
+            </div>
+            <Button onClick={() => setIsOpen(true)}>
+              <Plus className="mr-2 h-4 w-4" />
+              WBS 추가
+            </Button>
+          </div>
+          <div className="relative">
+            <Search className="absolute left-2 top-2.5 h-4 w-4 text-gray-400" />
+            <Input
+              placeholder="WBS 검색"
+              value={searchQuery}
+              onChange={(e) => setSearchQuery(e.target.value)}
+              className="pl-8 w-full"
+            />
+          </div>
+        </div>
+
+        <div className="p-2">
+          <div className="h-[650px]">
+            {data?.resultData && data.resultData.length > 0 ? (
+              <>
+                <PLMTable
+                  columns={columns}
+                  data={filteredWbsList || []} // 필터링된 데이터 사용
+                  pageSize={currentPageSize}
+                  onPageSizeChange={setCurrentPageSize}
+                  onRowClick={(row: contractWbs) => {
+                    setEditingUser(row);
+                    setIsOpen(true);
+                  }}
+                  enableCheckbox={true}
+                  isTreeTable={false}
+                />
+              </>
+            ) : (
+              <div className="text-center py-12 text-muted-foreground">
+                등록된 영업 WBS가 없습니다.
+              </div>
+            )}
+          </div>
+        </div>
+      </div>
+
+      {/* User Create/Edit Dialog */}
+      <Dialog
+        open={isOpen}
+        onOpenChange={(open) => {
+          setIsOpen(open);
+          if (!open) setEditingUser(null);
+        }}
+      >
+        <DialogContent className="max-w-3xl max-h-[80vh] overflow-y-auto">
+          <DialogHeader>
+            <DialogTitle>{editingUser ? "영업WBS 수정" : "신규 영업WBS"}</DialogTitle>
+            <DialogDescription>
+              {editingUser
+                ? "기존 영업 WBS를 수정합니다."
+                : "새로운 영업 WBS을 생성합니다."}
+            </DialogDescription>
+          </DialogHeader>
+          <ContractWbsForm
+            initialData={editingUser || undefined}
+            onSubmit={(data) => {
+              if (editingUser) {
+                updateMutation.mutate({ id: editingUser.id, ...data });
+              } else {
+                createMutation.mutate(data);
+              }
+            }}
+            onCancel={() => {
+              setIsOpen(false);
+              setEditingUser(null);
+            }}
+          />
+        </DialogContent>
+      </Dialog>
+    </div>
+  );
+};
+
+export default Page;
diff --git a/plm-app/src/types/salesmgmt/contractwbs.ts b/plm-app/src/types/salesmgmt/contractwbs.ts
new file mode 100644
index 0000000..4b257bb
--- /dev/null
+++ b/plm-app/src/types/salesmgmt/contractwbs.ts
@@ -0,0 +1,22 @@
+export interface contractWbs {
+  id: string;
+  index: number;
+  oem_id?: string | null;
+  product_group_id?: string | null;
+  writer?: string | null;
+  regdate?: Date | null;
+  isActive: boolean;
+  companyId: string;
+  count?: number;
+}
+
+export interface contractWbsResponse {
+  success: boolean;
+  data: contractWbs[];
+}
+
+export interface PaginatedResponse {
+  total: number;
+  totalPages: number;
+  currentPage: number;
+  resultData: contractWbs[]; 
\ No newline at end of file