박정하 박정하 01-07
250107 박정하 사용자 관리, 관리자 관리 수정정
@c5b9167bde40f7a8022e9a3d3b635aeb317547c7
 
.vscode/settings.json (added)
+++ .vscode/settings.json
@@ -0,0 +1,3 @@
+{
+  "liveServer.settings.port": 5501
+}(파일 끝에 줄바꿈 문자 없음)
client/views/component/connection/EhojoConnection.vue
--- client/views/component/connection/EhojoConnection.vue
+++ client/views/component/connection/EhojoConnection.vue
@@ -199,15 +199,9 @@
 
       // 기본값
       defaultHeaders: [
-        { index: 1, key: "ifId", value: null, required: true },
-        { index: 2, key: "tranId", value: null, required: true },
-        { index: 3, key: "trnmtInstCd", value: null, required: true },
-        { index: 4, key: "rcptnInstCd", value: null, required: true },
-        { index: 5, key: "trnmtInstSysCd", value: null, required: true },
-        { index: 6, key: "rcptnInstSysCd", value: null, required: true },
-        { index: 7, key: "transfGramNo", value: null, required: false },
-        { index: 8, key: "userDeptCode", value: null, required: false },
-        { index: 9, key: "userName", value: null, required: false },
+        { index: 1, key: "transfGramNo", value: null, required: false },
+        { index: 2, key: "userDeptCode", value: null, required: false },
+        { index: 3, key: "userName", value: null, required: false },
       ],
       defaultBodys: [
         { index: 1, key: "curPage", value: 1, required: false },
@@ -335,8 +329,8 @@
         data: vm.job,
       })
         .then((response) => {
-          if (response.data.checkMessage.status == "0000") {
-            let result = response.data;
+          if (response.data.checkMessage.status == 0) {
+            let result = response.data.resultData.dataTable;
             this.dataTable = result;
             this.rowKeys = []; // 초기화
             for (let columnData of result.columnDatas) {
@@ -363,7 +357,6 @@
       jobItm.itm = this.job;
       jobItm.dataTable = this.dataTable;
 
-      console.log("@@", jobItm);
       // 실행
       this.$emit("fnSaveSetup", jobItm);
     },
client/views/layout/TopMenu.vue
--- client/views/layout/TopMenu.vue
+++ client/views/layout/TopMenu.vue
@@ -54,6 +54,7 @@
           pathName: "통합관리",
           subMenu: [
             { path: "/user.page", pathName: "사용자관리" },
+            { path: "/adminManagement.page", pathName: "관리자관리" },
             { path: "/department.page", pathName: "부서관리" },
             { path: "/dbConnectionList.page", pathName: "연계정보관리" },
           ],
 
client/views/layout/back241206_TopMenu.vue (deleted)
--- client/views/layout/back241206_TopMenu.vue
@@ -1,148 +0,0 @@
-<template>
-  <nav class="top-menu">
-    <ul class="main-menu">
-      <li v-for="(mainMenu, idx) in menuList" :key="idx" @mouseover="showAllSubMenus" @mouseout="hideAllSubMenus">
-        <p class="depth1" :class="{ active: isMainMenuActive(mainMenu) }">{{ mainMenu.pathName }}</p>
-        <ul v-if="mainMenu.subMenu" class="sub-menu" :style="subShow ? 'max-height:500px; opacity:1' : 'max-height:0px; opacity:0'">
-          <li v-for="(subMenu, idx) in mainMenu.subMenu" :key="idx" :class="{ active: isSubMenuActive(subMenu) }">
-            <router-link :to="subMenu.path">{{ subMenu.pathName }}</router-link>
-          </li>
-        </ul>
-      </li>
-    </ul>
-    <div class="navbg" :style="subShow ? `height: ${maxSubMenuHeight}px` : `height: 0px`"></div>
-  </nav>
-</template>
-<script>
-
-export default {
-  data() {
-    return {
-      menuList: [
-        // { path: "/", pathName: "Dashboard", },
-        {
-          pathName: "데이터관리",
-          subMenu: [
-            { path: "/fileManagement.page", pathName: "파일관리" },
-            { path: "/hostManagement.page", pathName: "호스트관리" },
-            { path: "/dataManagement.page", pathName: "데이터관리" },
-            // { path: "/jobTest.page", pathName: "데이터 공유 관리" },
-          ],
-        },
-        {
-          pathName: "메타관리",
-          subMenu: [
-            { path: "/dataMetaManagement.page", pathName: "데이터 메타 정보" },
-            { path: "/termManagement.page", pathName: "표준 용어 관리" },
-          ],
-        },
-        {
-          pathName: "작업관리",
-          subMenu: [
-            // { path: "/scheduleManagement.page", pathName: "작업 스케줄 관리" },
-            { path: "/scheduleManagement.page", pathName: "작업 스케줄 관리" },
-            //{ path: "/push.page", pathName: "알림관리" },
-            //{ path: "/scheduleLogManagement.page", pathName: "로그 관리" },
-          ],
-        },
-        {
-          pathName: "데이터활용",
-          subMenu: [
-            { path: "/customSelectList.page", pathName: "데이터 활용 관리" },
-            // { path: "/customInsertDev.page", pathName: "개발테스트" },
-
-            // { path: "/", pathName: "데이터 활용 공유 관리" },
-            // { path: "/", pathName: "GIS데이터 관리" },
-            // { path: "/", pathName: "데이터현황 관리" },
-            { path: "/gisInfoList.page", pathName: "GIS 기능 관리" },
-            { path: "/openApiList.page", pathName: "OpenAPI 목록" },
-            { path: "/openApiKeyList.page", pathName: "OpenAPI key 관리" },
-          ],
-        },
-        {
-          pathName: "통합관리",
-          subMenu: [
-            { path: "/user.page", pathName: "사용자관리" },
-            { path: "/department.page", pathName: "부서관리" },
-            { path: "/dbConnectionList.page", pathName: "연계정보관리" },
-          ],
-        },
-        {
-          pathName: "정보관리",
-          subMenu: [
-            { path: "/myPage.page", pathName: "내정보관리" },
-            { path: "/myPagePwd.page", pathName: "비밀번호 변경" },
-            // { path: "/", pathName: "부서메일" },
-          ],
-        },
-        // {
-        //     pathName: "ai solution",
-        //     subMenu: [
-        //         { path: "/", pathName: "ai solution" },
-
-        //     ],
-        // },
-        // {
-        //     pathName: "템플릿",
-        //     subMenu: [
-        //         { path: "/searchbar.page", pathName: "서치바" },
-        //         { path: "/table.page", pathName: "테이블" },
-        //         { path: "/btnPosition.page", pathName: "버튼별 위치" },
-        //         { path: "/formModal.page", pathName: "form modal" },
-        //         { path: "/listModal.page", pathName: "list modal" },
-        //         { path: "/icon.page", pathName: "icon" },
-        //     ],
-        // },
-        // {
-        //     pathName: "레이아웃 템플릿",
-        //     subMenu: [
-        //         { path: "/vertical.page", pathName: "수직 레이아웃" },
-        //         { path: "/horizontal.page", pathName: "수평 레이아웃" },
-        //     ],
-        // },
-        // {
-        //     pathName: "가이드",
-        //     subMenu: [
-        //         { path: "/guide.page", pathName: "가이드" },
-        //     ],
-        // },
-      ],
-      currentRoute: null,
-      subShow: false
-    }
-  },
-  methods: {
-    showAllSubMenus() {
-      this.subShow = true;
-    },
-    hideAllSubMenus() {
-      this.subShow = false;
-    },
-
-    isMainMenuActive(mainMenu) {
-      return this.currentRoute && (this.currentRoute.path === mainMenu.path || this.isSubMenuActive(mainMenu.subMenu));
-    },
-
-    isSubMenuActive(subMenu) {
-      if (!subMenu) return false;
-      for (let i = 0; i < subMenu.length; i++) {
-        if (this.currentRoute.path === subMenu[i].path) {
-          return true;
-        }
-      }
-      return false;
-    },
-  },
-  watch: {
-    $route(to, from) {
-      this.currentRoute = to;
-    },
-  },
-  computed: {
-    maxSubMenuHeight: function () {
-      let maxSubItems = Math.max(...this.menuList.map(menu => menu.subMenu.length));
-      return maxSubItems * 55; // assuming each item is 50px high
-    }
-  },
-}
-</script>
client/views/pages/AppRouter.js
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
@@ -1,5 +1,14 @@
+import axios from "axios";
+import store from "./AppStore";
 import { createWebHistory, createRouter } from "vue-router";
+// #페이지
+// 통합관리
+import UserManagement from "../pages/integrated/UserManagement.vue"; // 사용자관리
+import AdminManagement from "../pages/integrated/AdminManagement.vue"; // 관리자관리
+import Department from "../pages/integrated/DepartmentManagement.vue"; // 부서관리
+import DBConnectionList from "../pages/dbConnection/DBConnectionList.vue"; // 연계정보관리
 
+import DBConnectionDetail from "../pages/dbConnection/DBConnectionDetail.vue";
 import FileManagement from "../pages/data/FileManagement.vue";
 import HostManagement from "../pages/data/HostManagement.vue";
 import DataManagement from "../pages/data/DataPostManagement.vue";
@@ -8,16 +17,10 @@
 import DataEditView from "../pages/data/DataEditView.vue";
 import TermManagement from "../pages/meta/TermManagement.vue";
 import DataMetaManagement from "../pages/meta/DataMetaManagement.vue";
-
 import ScheduleManagement from "../pages/schedule/ScheduleManagement.vue";
 import ScheduleLogManagement from "../pages/schedule/ScheduleLogManagement.vue";
-
 import Push from "../pages/push/Push.vue";
-import User from "../pages/integration/UserManagement.vue";
-import Department from "../pages/integration/DepartmentManagement.vue";
-import DBConnectionList from "../pages/dbConnection/DBConnectionList.vue";
 import InsertDBConnection from "../pages/dbConnection/InsertDBConnection.vue";
-import DBConnectionDetail from "../pages/dbConnection/DBConnectionDetail.vue";
 import CustomSelectList from "../pages/custom/CustomSelectList.vue";
 import CustomSelectOne from "../pages/custom/CustomSelectOne.vue";
 import CustomInsert from "../pages/custom/CustomInsert.vue";
@@ -34,10 +37,8 @@
 
 // 로그인 화면
 import Login from "../pages/login/Login.vue";
-
 // 차트
 import Chart from "../component/chart/ChartPage.vue";
-
 // 템플릿
 import Searchbar from "../template/templateElement/Searchbar.vue";
 import Table from "../template/templateElement/Table.vue";
@@ -50,139 +51,43 @@
 import Icon from "../template/templateElement/Icon.vue";
 import Guide from "../template/guide/TemplateGuide.vue";
 
-// 테스트용
-import JobTest from "../pages/data/JobTest.vue";
-import store from "./AppStore";
-import axios from "axios";
 
 const routes = [
-  /* 메인화면 */
-  // { path: "/", name: "Main", component: Main },
-  {
-    path: "/fileManagement.page",
-    name: "FileManagement",
-    component: FileManagement,
-  },
-  {
-    path: "/hostManagement.page",
-    name: "HostManagement",
-    component: HostManagement,
-  },
-  {
-    path: "/dataManagement.page",
-    name: "DataManagement",
-    component: DataManagement,
-  },
-  {
-    path: "/insertDataPost.page",
-    name: "InsertDataPost",
-    component: InsertDataPost,
-  },
-  {
-    path: "/dataPostDetail.page",
-    name: "DataPostDetail",
-    component: DataPostDetail,
-  },
-  { path: "/DataEditView.page", name: "DataEditView", component: DataEditView },
-  {
-    path: "/termManagement.page",
-    name: "TermManagement",
-    component: TermManagement,
-  },
-  {
-    path: "/dataMetaManagement.page",
-    name: "DataMetaManagement",
-    component: DataMetaManagement,
-  },
+  // 통합관리
+  { path: "/user.page", name: "User", component: UserManagement }, // 사용자관리
+  { path: "/adminManagement.page", name: "AdminManagement", component: AdminManagement }, // 관리자관리
+  { path: "/department.page", name: "Department", component: Department }, // 부서관리
+  { path: "/dbConnectionList.page", name: "DBConnectionList", component: DBConnectionList }, // 연계정보관리
 
-  { path: "/jobTest.page", name: "JobTest", component: JobTest },
-  {
-    path: "/scheduleManagement.page",
-    name: "ScheduleManagement",
-    component: ScheduleManagement,
-  },
-  {
-    path: "/scheduleLogManagement.page",
-    name: "ScheduleLogManagement",
-    component: ScheduleLogManagement,
-  },
+  { path: "/fileManagement.page", name: "FileManagement", component: FileManagement },
+  { path: "/hostManagement.page", name: "HostManagement", component: HostManagement },
+  { path: "/dataManagement.page", name: "DataManagement", component: DataManagement },
+  { path: "/insertDataPost.page", name: "InsertDataPost", component: InsertDataPost },
+  { path: "/dataPostDetail.page", name: "DataPostDetail", component: DataPostDetail },
+  { path: "/DataEditView.page", name: "DataEditView", component: DataEditView },
+  { path: "/termManagement.page", name: "TermManagement", component: TermManagement },
+  { path: "/dataMetaManagement.page", name: "DataMetaManagement", component: DataMetaManagement },
+  { path: "/scheduleManagement.page", name: "ScheduleManagement", component: ScheduleManagement },
+  { path: "/scheduleLogManagement.page", name: "ScheduleLogManagement", component: ScheduleLogManagement },
   { path: "/push.page", name: "Push", component: Push },
-  { path: "/user.page", name: "User", component: User },
-  { path: "/department.page", name: "Department", component: Department },
-  {
-    path: "/dbConnectionList.page",
-    name: "DBConnectionList",
-    component: DBConnectionList,
-  },
-  {
-    path: "/insertDBConnection.page",
-    name: "InsertDBConnection",
-    component: InsertDBConnection,
-  },
-  {
-    path: "/DBConnectionDetail.page",
-    name: "DBConnectionDetail",
-    component: DBConnectionDetail,
-  },
-  {
-    path: "/customSelectList.page",
-    name: "CustomSelectList",
-    component: CustomSelectList,
-  },
-  {
-    path: "/customSelectOne.page",
-    name: "CustomSelectOne",
-    component: CustomSelectOne,
-  },
+  { path: "/insertDBConnection.page", name: "InsertDBConnection", component: InsertDBConnection },
+  { path: "/DBConnectionDetail.page", name: "DBConnectionDetail", component: DBConnectionDetail },
+  { path: "/customSelectList.page", name: "CustomSelectList", component: CustomSelectList },
+  { path: "/customSelectOne.page", name: "CustomSelectOne", component: CustomSelectOne },
   { path: "/customInsert.page", name: "CustomInsert", component: CustomInsert },
-  {
-    path: "/customInsertDev.page",
-    name: "CustomInsertDev",
-    component: CustomInsertDev,
-  },
-  {
-    path: "/openApiList.page",
-    name: "OpenApiList",
-    component: OpenApiList,
-  },
-  {
-    path: "/openApiInsert.page",
-    name: "OpenApiInsert",
-    component: OpenApiInsert,
-  },
-  {
-    path: "/openApiListOne.page",
-    name: "OpenApiSelectListOne",
-    component: OpenApiSelectListOne,
-  },
-  {
-    path: "/openApiKeyList.page",
-    name: "OpenApiKeyList",
-    component: OpenApiKeyList,
-  },
-  {
-    path: "/gisInfoList.page",
-    name: "GisInfoList",
-    component: GisInfoList,
-  },
-  {
-    path: "/gisInfoInsert.page",
-    name: "GisInfoInsert",
-    component: GisInfoInsert,
-  },
-  {
-    path: "/gisInfoListOne.page",
-    name: "GisInfoSelectListOne",
-    component: GisInfoSelectListOne,
-  },
+  { path: "/customInsertDev.page", name: "CustomInsertDev", component: CustomInsertDev },
+  { path: "/openApiList.page", name: "OpenApiList", component: OpenApiList },
+  { path: "/openApiInsert.page", name: "OpenApiInsert", component: OpenApiInsert },
+  { path: "/openApiListOne.page", name: "OpenApiSelectListOne", component: OpenApiSelectListOne },
+  { path: "/openApiKeyList.page", name: "OpenApiKeyList", component: OpenApiKeyList },
+  { path: "/gisInfoList.page", name: "GisInfoList", component: GisInfoList },
+  { path: "/gisInfoInsert.page", name: "GisInfoInsert", component: GisInfoInsert },
+  { path: "/gisInfoListOne.page", name: "GisInfoSelectListOne", component: GisInfoSelectListOne },
   { path: "/myPage.page", name: "myPage", component: myPage },
   { path: "/myPagePwd.page", name: "myPagePwd", component: myPagePwd },
-
   { path: "/login.page", name: "Login", component: Login },
-
   // 차트
   { path: "/chart.page", name: "Chart", component: Chart },
-
   // 템플릿 화면
   { path: "/searchbar.page", name: "Searchbar", component: Searchbar },
   { path: "/table.page", name: "Table", component: Table },
 
client/views/pages/bu_241206_AppRouter.js (deleted)
--- client/views/pages/bu_241206_AppRouter.js
@@ -1,261 +0,0 @@
-import { createWebHistory, createRouter } from "vue-router";
-
-import Main from "../pages/main/Main.vue";
-import FileManagement from "../pages/data/FileManagement.vue";
-import HostManagement from "../pages/data/HostManagement.vue";
-import DataManagement from "../pages/data/DataPostManagement.vue";
-import InsertDataPost from "../pages/data/InsertDataPost.vue";
-import DataPostDetail from "../pages/data/DataPostDetail.vue";
-import DataEditView from "../pages/data/DataEditView.vue";
-import TermManagement from "../pages/meta/TermManagement.vue";
-import DataMetaManagement from "../pages/meta/DataMetaManagement.vue";
-
-import ScheduleManagement from "../pages/schedule/ScheduleManagement.vue";
-import ScheduleLogManagement from "../pages/schedule/ScheduleLogManagement.vue";
-
-import Push from "../pages/push/Push.vue";
-import User from "../pages/integration/UserManagement.vue";
-import Department from "../pages/integration/DepartmentManagement.vue";
-import DBConnectionList from "../pages/dbConnection/DBConnectionList.vue";
-import InsertDBConnection from "../pages/dbConnection/InsertDBConnection.vue";
-import DBConnectionDetail from "../pages/dbConnection/DBConnectionDetail.vue";
-import CustomSelectList from "../pages/custom/CustomSelectList.vue";
-import CustomSelectOne from "../pages/custom/CustomSelectOne.vue";
-import CustomInsert from "../pages/custom/CustomInsert.vue";
-import CustomInsertDev from "../pages/custom/CustomInsertDev.vue";
-import myPage from "../pages/user/myPage.vue";
-import myPagePwd from "../pages/user/myPagePwd.vue";
-import OpenApiList from "../pages/openapi/OpenApiList.vue";
-import OpenApiInsert from "../pages/openapi/OpenApiInsert.vue";
-import OpenApiSelectListOne from "../pages/openapi/OpenApiSelectListOne.vue";
-import GisInfoList from "../pages/gisinfo/GisInfoList.vue";
-import GisInfoInsert from "../pages/gisinfo/GisInfoInsert.vue";
-import GisInfoSelectListOne from "../pages/gisinfo/GisInfoSelectListOne.vue";
-import OpenApiKeyList from "../pages/openapi/OpenApiKeyList.vue";
-
-// 로그인 화면
-import Login from "../pages/login/Login.vue";
-import FindId from "../pages/register/FindId.vue";
-import FindPwd from "../pages/register/FindPwd.vue";
-import Register from "../pages/register/Register.vue";
-
-// 차트
-import Chart from "../component/chart/ChartPage.vue";
-
-// 템플릿
-import Searchbar from "../template/templateElement/Searchbar.vue";
-import Table from "../template/templateElement/Table.vue";
-import BtnPosition from "../template/templateElement/BtnPosition.vue";
-import Horizontal from "../template/layoutTemplate/Horizontal.vue";
-import Vertical from "../template/layoutTemplate/Vertical.vue";
-import FormModal from "../template/templateElement/FormModal.vue";
-import ListModal from "../template/templateElement/ListModal.vue";
-import AlertModal from "../template/templateElement/AlertModal.vue";
-import Icon from "../template/templateElement/Icon.vue";
-import Guide from "../template/guide/TemplateGuide.vue";
-
-// 테스트용
-import JobTest from "../pages/data/JobTest.vue";
-import store from "./AppStore";
-import axios from "axios";
-
-const routes = [
-  /* 메인화면 */
-  // { path: "/", name: "Main", component: Main },
-  {
-    path: "/fileManagement.page",
-    name: "FileManagement",
-    component: FileManagement,
-  },
-  {
-    path: "/hostManagement.page",
-    name: "HostManagement",
-    component: HostManagement,
-  },
-  {
-    path: "/dataManagement.page",
-    name: "DataManagement",
-    component: DataManagement,
-  },
-  {
-    path: "/insertDataPost.page",
-    name: "InsertDataPost",
-    component: InsertDataPost,
-  },
-  {
-    path: "/dataPostDetail.page",
-    name: "DataPostDetail",
-    component: DataPostDetail,
-  },
-  { path: "/DataEditView.page", name: "DataEditView", component: DataEditView },
-  {
-    path: "/termManagement.page",
-    name: "TermManagement",
-    component: TermManagement,
-  },
-  {
-    path: "/dataMetaManagement.page",
-    name: "DataMetaManagement",
-    component: DataMetaManagement,
-  },
-
-  { path: "/jobTest.page", name: "JobTest", component: JobTest },
-  {
-    path: "/scheduleManagement.page",
-    name: "ScheduleManagement",
-    component: ScheduleManagement,
-  },
-  {
-    path: "/scheduleLogManagement.page",
-    name: "ScheduleLogManagement",
-    component: ScheduleLogManagement,
-  },
-  { path: "/push.page", name: "Push", component: Push },
-  { path: "/user.page", name: "User", component: User },
-  { path: "/department.page", name: "Department", component: Department },
-  {
-    path: "/dbConnectionList.page",
-    name: "DBConnectionList",
-    component: DBConnectionList,
-  },
-  {
-    path: "/insertDBConnection.page",
-    name: "InsertDBConnection",
-    component: InsertDBConnection,
-  },
-  {
-    path: "/DBConnectionDetail.page",
-    name: "DBConnectionDetail",
-    component: DBConnectionDetail,
-  },
-  {
-    path: "/customSelectList.page",
-    name: "CustomSelectList",
-    component: CustomSelectList,
-  },
-  {
-    path: "/customSelectOne.page",
-    name: "CustomSelectOne",
-    component: CustomSelectOne,
-  },
-  { path: "/customInsert.page", name: "CustomInsert", component: CustomInsert },
-  {
-    path: "/customInsertDev.page",
-    name: "CustomInsertDev",
-    component: CustomInsertDev,
-  },
-  {
-    path: "/openApiList.page",
-    name: "OpenApiList",
-    component: OpenApiList,
-  },
-  {
-    path: "/openApiInsert.page",
-    name: "OpenApiInsert",
-    component: OpenApiInsert,
-  },
-  {
-    path: "/openApiListOne.page",
-    name: "OpenApiSelectListOne",
-    component: OpenApiSelectListOne,
-  },
-  {
-    path: "/openApiKeyList.page",
-    name: "OpenApiKeyList",
-    component: OpenApiKeyList,
-  },
-  {
-    path: "/gisInfoList.page",
-    name: "GisInfoList",
-    component: GisInfoList,
-  },
-  {
-    path: "/gisInfoInsert.page",
-    name: "GisInfoInsert",
-    component: GisInfoInsert,
-  },
-  {
-    path: "/gisInfoListOne.page",
-    name: "GisInfoSelectListOne",
-    component: GisInfoSelectListOne,
-  },
-  { path: "/myPage.page", name: "myPage", component: myPage },
-  { path: "/myPagePwd.page", name: "myPagePwd", component: myPagePwd },
-
-  { path: "/login.page", name: "Login", component: Login },
-  { path: "/findId.page", name: "FindId", component: FindId },
-  { path: "/findPwd.page", name: "FindPwd", component: FindPwd },
-  { path: "/register.page", name: "Register", component: Register },
-
-  // 차트
-  { path: "/chart.page", name: "Chart", component: Chart },
-
-  // 템플릿 화면
-  { path: "/searchbar.page", name: "Searchbar", component: Searchbar },
-  { path: "/table.page", name: "Table", component: Table },
-  { path: "/btnPosition.page", name: "BtnPosition", component: BtnPosition },
-  { path: "/horizontal.page", name: "Horizontal", component: Horizontal },
-  { path: "/vertical.page", name: "Vertical", component: Vertical },
-  { path: "/formModal.page", name: "FormModal", component: FormModal },
-  { path: "/listModal.page", name: "ListModal", component: ListModal },
-  { path: "/alertModal.page", name: "AlertModal", component: AlertModal },
-  { path: "/icon.page", name: "Icon", component: Icon },
-  { path: "/guide.page", name: "Guide", component: Guide },
-];
-
-const AppRouter = createRouter({
-  history: createWebHistory(),
-  routes,
-});
-
-AppRouter.beforeEach(async (to, from, next) => {
-  const userId = store.state.loginUser;
-  // userId 없음
-  if (userId == null) {
-    if (to.path == "/login.page" || to.path == "/findId.page" || to.path == "/findPwd.page" || to.path == "/register.page") {
-      next();
-    } else {
-      axios({
-        url: "/getLoginInfo.json",
-        method: "post",
-        headers: { "Content-Type": "application/json; charset=UTF-8" },
-      })
-        .then(function (response) {
-          if (response.data.checkMessage.status > 0) {
-            store.commit("setLoginUser", response.data.resultData.LoginUserInfo);
-            next();
-          } else {
-            next("/login.page");
-          }
-        })
-        .catch(function (error) {
-          this.$showAlert("에러 발생", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
-        });
-    }
-  }
-  // userId 있음
-  else {
-    if (to.path == "/login.page") {
-      next("/fileManagement.page");
-    } else if (to.path == "/department.page" || to.path == "/user.page" || to.path == "/hostManagement.page" || to.path == "/dbConnectionList.page") {
-      let authList = store.state.loginUser.user_auth;
-      let check = false;
-      for (let auth of authList) {
-        if (auth == "ROLE_ADMIN") {
-          check = true;
-          break;
-        }
-      }
-      if (check) {
-        next();
-      } else {
-        alert('접근 권한이 없습니다.');
-        next("/fileManagement.page");
-      }
-    } else {
-      next();
-    }
-  }
-});
-
-export default AppRouter;(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/data/JobTest.vue (deleted)
--- client/views/pages/data/JobTest.vue
@@ -1,82 +0,0 @@
-<template>
-  <div class="container">
-    <div class="content content-box flex100">
-      <JobContainer :jobGroup="jobGroup" />
-      <div class="flex justify-end mt10">
-        <button class="darkg-btn small-btn" @click="saveJobGroup()">
-          데이터 등록
-        </button>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import JobContainer from "../../component/connection/jobContainer.vue";
-import axios from "axios";
-
-export default {
-  openPopup: {
-    type: Boolean,
-    default: false,
-  },
-  data() {
-    return {
-      jobGroup: {},
-    };
-  },
-  methods: {
-    saveJobGroup: function () {
-      let vm = this;
-      axios({
-        url: "/job/insertJobGroup.json",
-        method: "post",
-        headers: {
-          "Content-Type": "application/json; charset=UTF-8",
-        },
-        data: vm.jobGroup,
-      })
-        .then(function (response) {
-          this.$showAlert(
-            "에러 발생",
-            "에러가 발생했습니다. 관리자에게 문의해 주세요."
-          );
-        })
-        .catch(function (error) {
-          this.$showAlert(
-            "에러 발생",
-            "에러가 발생했습니다. 관리자에게 문의해 주세요."
-          );
-        });
-    },
-
-    selectJobGroup: function () {
-      let vm = this;
-      axios({
-        url: "/job/selectJobGroup.json",
-        method: "post",
-        headers: {
-          "Content-Type": "application/json; charset=UTF-8",
-        },
-        data: JSON.stringify({ group_id: "JOBGROUP_2024020517352987547982" }),
-      })
-        .then(function (response) {
-          vm.jobGroup = response.data.resultData.jobGroup;
-        })
-        .catch(function (error) {
-          this.$showAlert(
-            "에러 발생",
-            "에러가 발생했습니다. 관리자에게 문의해 주세요."
-          );
-        });
-    },
-  },
-  components: {
-    JobContainer: JobContainer,
-  },
-  mounted() {
-    this.jobGroup = this.$getDefaultJobGroup().jobGroup;
-    this.selectJobGroup();
-  },
-};
-</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/integrated/AdminManagement.vue (added)
+++ client/views/pages/integrated/AdminManagement.vue
@@ -0,0 +1,730 @@
+<template>
+  <div class="container">
+    <div class="page-titleZone flex justify-between align-center">
+      <p class="main-title flex80">관리자 관리</p>
+      <PageNavigation />
+    </div>
+    <div class="content-wrap">
+      <div class="content content-box flex100">
+        <div class="column-list">
+          <div class="content-titleZone flex justify-between align-center">
+            <p class="box-title">관리자 목록</p>
+            <div class="search-bar">
+              <div class="flex justify-end align-center">
+                <select class="square-select" v-model="search_data.key">
+                  <option :value="null">선택</option>
+                  <option value="ui.user_id">아이디</option>
+                  <option value="ui.user_nm">이름</option>
+                </select>
+                <div class="search-square">
+                  <div class="flex justify-end align-center no-gutter">
+                    <input type="text" class="square-input flex90" placeholder="검색어를 입력해 주세요." v-model="search_data.value" @keyup.enter="fnSelectUserList" />
+                    <button class="square-button blue-btn flex10" @click="fnSelectUserList">
+                      <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon>
+                    </button>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="flex justify-between align-center">
+            <div class="count-zone">
+              <p>총 <span>{{ userList.length }}</span>건 중 <span>{{ userSelectList.length }}</span>건 선택</p>
+            </div>
+            <div class="cunt-selectZone">
+              <select v-model="search.perPage" @change="fnSelectUserList">
+                <option value="10">10개 보기</option>
+                <option value="20">20개 보기</option>
+              </select>
+            </div>
+          </div>
+          <div class="table-zone">
+            <table class="list-table">
+              <colgroup>
+                <col style="width: 5%" />
+                <col style="width: 5%" />
+                <col style="width: 21%" />
+                <col style="width: 21%" />
+                <col style="width: 21%" />
+                <col style="width: 21%" />
+                <col style="width: 6%" />
+              </colgroup>
+              <thead>
+                <tr>
+                  <th>
+                    <input type="checkbox" v-model="isChkAll" @change="fnChkAll()" />
+                  </th>
+                  <th>번호</th>
+                  <th>아이디</th>
+                  <th>이름</th>
+                  <th>이메일</th>
+                  <th>등록날짜</th>
+                  <th>잠김여부</th>
+                </tr>
+              </thead>
+              <tbody>
+                <template v-if="userList.length > 0">
+                  <tr v-for="(item, idx) in userList" :key="idx" @click="fnSelectUser(item.userId)">
+                    <td>
+                      <input type="checkbox" :value="item" v-model="userSelectList" @click.stop="" @change="fnChangeChk" />
+                    </td>
+                    <td>{{ search.totalRows - idx - (search.currentPage - 1) * search.perPage }}</td>
+                    <td>{{ item.userId }}</td>
+                    <td>{{ item.userNm }}</td>
+                    <td>{{ item.userEmail }}</td>
+                    <td>{{ $filters.dateTime(item.creatDt) }}</td>
+                    <td>{{ item.lockAt ? "잠금" : "-" }}</td>
+                  </tr>
+                </template>
+                <tr v-else>
+                  <td colspan="8">등록된 데이터가 없습니다.</td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+          <div class="flex justify-end">
+            <button class="red-border-btn small-btn" @click="fnDeleteUser">선택 삭제</button>
+          </div>
+          <PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" :totalCount="search.totalRows" :maxRange="5" :click="fetchMemberList" />
+        </div>
+        <div class="data-set">
+          <div class="form-box">
+            <div class="content-titleZone">
+              <p class="box-title" v-if="editMode == 'create'">관리자 등록</p>
+              <p class="box-title" v-else>관리자 수정</p>
+            </div>
+            <div class="table-zone">
+              <table class="form-table2">
+                <colgroup>
+                  <col style="width: 10%" />
+                  <col style="width: 40%" />
+                  <col style="width: 10%" />
+                  <col style="width: 40%" />
+                </colgroup>
+                <tbody>
+                  <tr>
+                    <th>아이디</th>
+                    <td style="display: flex">
+                      <input type="text" class="full-input" v-model="currentUser.userId" :disabled="editMode == 'update'" />
+                      <button class="small-btn blue-border-btn" style="flex-grow: 1" v-if="editMode == 'create'" @click="fnDuplicateChk('id')">중복확인</button>
+                    </td>
+                    <th>이름</th>
+                    <td>
+                      <input type="text" class="full-input" v-model="currentUser.userNm" />
+                    </td>
+                  </tr>
+                  <tr v-if="editMode == 'create'">
+                    <th>비밀번호</th>
+                    <td>
+                      <input type="password" class="full-input" style="width: 100%" v-model="currentUser.userPassword" />
+                    </td>
+                    <th>비밀번호 확인</th>
+                    <td>
+                      <input type="password" class="full-input" style="width: 100%" v-model="userPasswordConfirm" />
+                    </td>
+                  </tr>
+                  <tr>
+                    <th>이메일</th>
+                    <td style="display: flex">
+                      <input type="text" class="full-input" v-model="currentUser.userEmail" />
+                      <button class="small-btn blue-border-btn" style="flex-grow: 1" @click="fnDuplicateChk('email')">중복확인</button>
+                    </td>
+                    <template v-if="editMode == 'update'">
+                      <th>잠김여부</th>
+                      <td style="display: flex">
+                        <input type="text" class="full-input" :value="currentUser.lockAt ? '잠금 (사용불가)' : '미잠금 (사용가능)'" readonly>
+                        <button class="blue-border-btn small-btn" style="flex-grow: 1" v-if="currentUser.lockAt" @click="fnUpdateUserLockAt">잠금해제</button>
+                      </td>
+                    </template>
+                    <template v-else>
+                      <th></th>
+                      <td></td>
+                    </template>
+                  </tr>
+                </tbody>
+              </table>
+            </div>
+            <div class="flex justify-end">
+              <button class="blue-border-btn small-btn" v-if="editMode == 'update'" @click="fnOpenModal">비밀번호 변경</button>
+              <button class="blue-btn small-btn" v-if="editMode == 'create'" @click="fnInsertUser">등록</button>
+              <button class="blue-btn small-btn" v-else @click="fnUpdateUser">수정</button>
+              <button class="blue-border-btn small-btn" @click="fnCancel"><span v-if="editMode == 'create'">초기화</span><span v-else>취소</span></button>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <!-- 비밀번호 변경 모달 -->
+  <div v-show="modalOpen" class="modal-wrapper">
+    <div class="modal-container small-modal">
+      <div class="modal-title">
+        <div class="flex justify-between align-center">
+          <h2>비밀번호 변경</h2>
+          <button class="close-btn" @click="fnCloseModal">X</button>
+        </div>
+      </div>
+      <div class="modal-content-monthly">
+        <div class="table-zone">
+          <table class="form-table">
+            <colgroup>
+              <col style="width: 40%" />
+              <col style="width: 60%" />
+            </colgroup>
+            <tbody>
+              <tr>
+                <th>새 비밀번호</th>
+                <td>
+                  <input type="password" class="full-input" v-model="userPassword" />
+                </td>
+              </tr>
+              <tr>
+                <th>새 비밀번호 확인</th>
+                <td>
+                  <input type="password" class="full-input" v-model="userPasswordConfirm" />
+                </td>
+              </tr>
+            </tbody>
+          </table>
+          <div class="modal-end flex justify-between" style="flex-wrap: nowrap;">
+            <button class="blue-btn large-btn" @click="fnUpdateUserPassword">수정</button>
+            <button class="blue-border-btn large-btn" @click="fnCloseModal">취소</button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import axios from "axios";
+// icon용 svg import
+import SvgIcon from "@jamescoyle/vue-icon";
+import { mdiClose, mdiMagnify } from "@mdi/js";
+// 컴포넌트 import
+import PageNavigation from "../../component/PageNavigation.vue";
+import PaginationButton from "../../component/PaginationButton.vue";
+
+export default {
+  components: { SvgIcon, PageNavigation, PaginationButton },
+
+  data() {
+    return {
+      // icon용 svg path
+      closePath: mdiClose,
+      searchPath: mdiMagnify,
+
+      // 검색
+      search: this.$getDefaultSerchVO(),
+      search_data: this.$getDefaultSerchItem(null, "string"),
+
+      // default
+      editMode: 'create',
+
+      memberVO: {},
+      originUser: {},
+      currentUser: {},
+
+      userPassword: null,
+      userPasswordConfirm: null,
+
+      isChkAll: false,
+      userList: [],
+      userSelectList: [],
+
+      deptList: [],
+
+      // 비밀번호 변경
+      modalOpen: false,
+
+      // 중복검사
+      isIdChk: false,
+      isEmailChk: false,
+    };
+  },
+
+  mounted() {
+    this.fnSelectUser(); // 관리자 개별 조회
+    this.fnSelectUserList(); // 관리자 목록 조회
+    this.fnSelectDeptList(); // 부서 목록 조회
+  },
+
+  watch: {
+    //아이디 값 변경 시 중복 검사 false로 변경
+    "currentUser.userId"() {
+      this.isIdChk = false;
+    },
+    //이메일 값 변경 시 중복 검사 false로 변경
+    "currentUser.userEmail"() {
+      this.isEmailChk = false;
+    },
+  },
+
+  methods: {
+    // 관리자 목록 조회
+    fnSelectUserList() {
+      const vm = this;
+      // 데이터 세팅
+      let data = vm.search;
+      data.searchObjectList = []; // 초기화
+      data.searchObjectList.push(vm.search_data);
+      // 실행
+      axios({
+        url: "/member/list/ROLE_ADMIN",
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: data,
+      })
+        .then(response => {
+          if (response.data != null) {
+            vm.userList = response.data.resultData.members;
+            vm.search = response.data.resultData.searchVO;
+          } else {
+            this.$showAlert("관리자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("관리자 관리", "목록 불러오기 오류, 관리자에게 문의바랍니다.");
+        });
+    },
+    // 관리자 목록 전체 선택
+    fnChkAll() {
+      if (this.isChkAll) {
+        this.userSelectList = this.userList;
+      } else {
+        this.userSelectList = [];
+      }
+    },
+    // 관리자 목록 개별 선택
+    fnChangeChk() {
+      if (this.userSelectList.length == this.userList.length) {
+        this.isChkAll = true;
+      } else {
+        this.isChkAll = false;
+      }
+    },
+    // 관리자 선택 삭제
+    async fnDeleteUser() {
+      const vm = this;
+      // 선택 목록 확인
+      if (vm.userSelectList.length === 0) {
+        vm.$showAlert("관리자 관리", "선택한 관리자가 없습니다.");
+        return;
+      }
+      // 삭제 확인
+      if (!(await vm.$showConfirm("관리자 관리", "선택한 관리자를 삭제하시겠습니까?"))) {
+        return;
+      }
+
+      // 실행
+      axios({
+        url: "/member",
+        method: "delete",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: vm.userSelectList,
+      })
+        .then(response => {
+          if (response.data.checkMessage.status === 200) {
+            vm.$showAlert("관리자 관리", "선택한 관리자가 삭제되었습니다.");
+
+            // 삭제 후 작업
+            vm.isChkAll = false; // 체크 박스 리셋
+            vm.userSelectList = []; // 관리자 선택 목록 초기화
+            vm.fnSelectUserList(); // 전체 재조회
+          } else {
+            vm.$showAlert("관리자 관리", response.data.checkMessage.message);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("관리자 관리", "처리 중 오류가 발생했습니다. 관리자에게 문의바랍니다.");
+        });
+    },
+
+    // 부서 목록 조회
+    fnSelectDeptList() {
+      const vm = this;
+      // 데이터 세팅팅
+      let search = Object.assign({}, this.$getDefaultSerchVO());
+      search.currentPage = 0;
+      search.perPage = 0;
+      // 실행
+      axios({
+        url: "/department/departments",
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: search,
+      })
+        .then(response => {
+          if (response.data != null) {
+            vm.deptList = response.data.resultData.selectDeptList;
+          } else {
+            this.$showAlert("관리자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("관리자 관리", "목록 불러오기 오류, 관리자에게 문의바랍니다.");
+        });
+    },
+
+    // 관리자 등록
+    fnInsertUser() {
+      const vm = this;
+      // 유효성 검사
+      if (!vm.insertValidation()) {
+        return;
+      }
+      // 데이터 세팅
+      vm.currentUser.author = 'ROLE_ADMIN'
+      // 실행
+      axios({
+        url: "/member",
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: vm.currentUser,
+      })
+        .then(response => {
+          if (response.data.checkMessage.status === 200) {
+            vm.$showAlert("관리자 관리", "관리자 등록이 완료되었습니다.");
+            vm.currentUser = Object.assign({}, vm.memberVO); // 초기화
+            vm.fnSelectUserList();
+          } else {
+            vm.$showAlert("관리자 관리", response.data.checkMessage.message);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("관리자 관리", "관리자 등록에 실패했습니다. 다시 시도해주세요.");
+        });
+    },
+
+    // 관리자 개별 조회
+    fnSelectUser(userId) {
+      const vm = this;
+      // 데이터 세팅
+      let url = null;
+      if (vm.$isEmpty(userId)) {
+        url = "/member/selectUser";
+      } else {
+        url = "/member/selectUser/" + userId;
+      }
+      // 실행
+      axios({
+        url: url,
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+      })
+        .then(response => {
+          if (vm.$isEmpty(userId)) {
+            vm.memberVO = response.data;
+          } else {
+            vm.editMode = 'update';
+            vm.originUser = response.data;
+            vm.currentUser = Object.assign({}, response.data);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("관리자 관리", "불러오기 오류, 관리자에게 문의바랍니다.");
+        });
+    },
+
+    // 관리자 수정
+    fnUpdateUser() {
+      const vm = this;
+      // 유효성 검사
+      if (!vm.updateValidation()) {
+        return;
+      }
+      // 실행
+      axios({
+        url: "/member",
+        method: "put",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: vm.currentUser
+      })
+        .then(response => {
+          if (response.data.checkMessage.status === 200) {
+            vm.$showAlert("관리자 관리", "관리자 정보가 수정되었습니다.");
+            vm.originUser = Object.assign({}, vm.memberVO); // 초기화
+            vm.currentUser = Object.assign({}, vm.memberVO); // 초기화
+            vm.editMode = 'create';
+            vm.fnSelectUserList();
+          } else {
+            vm.$showAlert("관리자 관리", response.data.checkMessage.message);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("관리자 관리", "수정 오류, 관리자에게 문의해주세요.");
+        });
+    },
+
+    // 중복확인 버튼 동작
+    fnDuplicateChk(type) {
+      if (type == 'id') {
+        this.idDuplicateChk();
+      } else if (type == 'email') {
+        this.emailDuplicateChk();
+      }
+    },
+    // 아이디 중복 검사
+    idDuplicateChk() {
+      const vm = this;
+      // 유효성 검사
+      if (!vm.$idCheck(vm.currentUser.userId)) {
+        vm.$showAlert("관리자 관리", "아이디 형식이 올바르지 않습니다. (5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용가능)");
+        return false;
+      }
+      // 실행
+      axios({
+        url: "/member/" + vm.currentUser.userId,
+        method: "get",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+      })
+        .then(response => {
+          if (response.data.resultData.checkDuplicateUserId) {
+            vm.isIdChk = false;
+            vm.$showAlert("관리자 관리", "사용중인 아이디입니다.");
+          } else {
+            vm.isIdChk = true;
+            vm.$showAlert("관리자 관리", "사용할 수 있는 아이디입니다.");
+          }
+        })
+        .catch(error => {
+          this.$showAlert("관리자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
+        });
+    },
+    // 이메일 중복 검사
+    emailDuplicateChk() {
+      const vm = this;
+      // 유효성 검사
+      if (!vm.validationEmail()) {
+        return;
+      }
+      // 실행
+      axios({
+        url: "/member/email",
+        method: "get",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: vm.currentUser.userEmail,
+      })
+        .then(response => {
+          if (response.data.resultData.result) {
+            vm.$showAlert("관리자 관리", "사용중인 이메일입니다.");
+            vm.isEmailChk = false;
+          } else {
+            vm.$showAlert("관리자 관리", "사용할 수 있는 이메일입니다.");
+            vm.isEmailChk = true;
+          }
+        })
+        .catch(error => {
+          this.$showAlert("관리자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
+        });
+    },
+
+    // 관리자 잠금 해제
+    fnUpdateUserLockAt() {
+      const vm = this;
+      // 실행
+      axios({
+        url: "/member/updateUser/LockAt/" + vm.currentUser.userId,
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+      })
+        .then(response => {
+          if (response.data.checkMessage.status === 200) {
+            vm.$showAlert("관리자 관리", "관리자 잠금이 해제되었습니다.");
+            vm.fnSelectUser(vm.currentUser.userId); // 관리자 개별 재조회
+          } else {
+            vm.$showAlert("관리자 관리", response.data.checkMessage.message);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("관리자 관리", "수정 오류, 관리자에게 문의해주세요.");
+        });
+    },
+
+    // 관리자 비밀번호 변경 모달 열기
+    fnOpenModal() {
+      this.userPassword = null;
+      this.userPasswordConfirm = null;
+
+      this.modalOpen = true;
+    },
+    // 관리자 비밀번호 변경 모달 열기
+    fnCloseModal() {
+      this.modalOpen = false;
+    },
+    // 관리자 비밀번호 변경
+    fnUpdateUserPassword() {
+      const vm = this;
+      // 유효성 검사
+      vm.currentUser.userPassword = vm.userPassword;
+      if (!vm.validationPassword()) {
+        return;
+      }
+      // 실행
+      axios({
+        url: "/member",
+        method: "patch",
+        headers: {
+          "Content-Type": "application/json",
+        },
+        data: {
+          userId: vm.currentUser.userId,
+          userPassword: vm.userPassword,
+        },
+      })
+        .then(response => {
+          if (response.data.resultData.result) {
+            vm.$showAlert("비밀번호 변경", "비밀번호 변경에 성공했습니다.");
+            vm.modalOpen = false;
+          } else {
+            vm.$showAlert("비밀번호 변경", "비밀번호 변경에 실패했습니다. 다시 시도해주세요.");
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("비밀번호 변경", "비밀번호 변경에 실패했습니다. 다시 시도해주세요.");
+        });
+    },
+
+    // 관리자 등록 취소
+    fnCancel() {
+      if (this.editMode == 'update') {
+        this.editMode = 'create';
+      }
+      // 초기화
+      this.userPassword = null;
+      this.userPasswordConfirm = null;
+      this.currentUser = Object.assign({}, this.memberVO);
+    },
+
+    // #유효성 검사
+    // 등록용 유효성 검사
+    insertValidation() {
+      // 아이디 유효성 검사
+      if (!this.validationId()) {
+        return false;
+      }
+      // 아이디 중복 검사 여부
+      if (!this.isIdChk) {
+        this.$showAlert("관리자 관리", "아이디 중복 확인 후 시도해주세요.");
+        return false;
+      }
+
+      // 이름 유효성 검사
+      if (!this.validationName()) {
+        return false;
+      }
+
+      // 비밀번호 유효성 검사
+      if (!this.validationPassword()) {
+        return false;
+      }
+
+      // 이메일 유효성 검사
+      if (!this.validationEmail()) {
+        return false;
+      }
+      // 이메일 중복 검사 여부
+      if (!this.isEmailChk) {
+        this.$showAlert("관리자 관리", "이메일 중복확인 후 등록해주세요.");
+        return false;
+      }
+
+      return true;
+    },
+    // 수정용 유효성 검사
+    updateValidation() {
+      if (JSON.stringify(this.currentUser) === JSON.stringify(this.originUser)) {
+        this.$showAlert("관리자 관리", "수정된 정보가 없습니다.");
+        return;
+      }
+
+      // 이름 유효성 검사
+      if (!this.validationName()) {
+        return false;
+      }
+
+      // 이메일 유효성 검사
+      if (!this.validationEmail()) {
+        return false;
+      }
+
+      // 이메일 중복 검사 여부
+      if (!this.isEmailChk) {
+        this.$showAlert("관리자 관리", "이메일 중복확인 후 수정해주세요.");
+        return false;
+      }
+
+      return true;
+    },
+    // 아이디 유효성 검사
+    validationId() {
+      let id = this.currentUser.userId;
+
+      if (this.$isEmpty(id)) {
+        this.$showAlert("관리자 관리", "아이디를 입력해주세요.");
+        return false;
+      }
+
+      if (!this.$idCheck(id)) {
+        this.$showAlert("관리자 관리", "아이디 형식이 올바르지 않습니다. (5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용가능)");
+        return false;
+      }
+
+      return true;
+    },
+    // 이름 유효성 검사
+    validationName() {
+      let name = this.currentUser.userNm;
+
+      if (this.$isEmpty(name)) {
+        this.$showAlert("관리자 관리", "이름을 입력해주세요.");
+        return false;
+      }
+
+      let validateName = /^[가-힣A-Za-z\s]+$/;
+      if (!validateName.test(name)) {
+        this.$showAlert("관리자 관리", "이름에 숫자와 특수문자를 입력할 수 없습니다.");
+        return false;
+      }
+
+      return true;
+    },
+    // 비밀번호 유효성 검사
+    validationPassword() {
+      if (this.$isEmpty(this.currentUser.userPassword)) {
+        this.$showAlert("관리자 관리", "비밀번호를 입력해주세요.");
+        return false;
+      }
+
+      if (!this.$pwCheck(this.currentUser.userPassword)) {
+        this.$showAlert("관리자 관리", "비밀번호 형식이 올바르지 않습니다. (8~16자의 영문 대문자, 소문자, 숫자, 특수문자 사용가능)");
+        return false;
+      }
+
+      if (this.currentUser.userPassword !== this.userPasswordConfirm) {
+        this.$showAlert("관리자 관리", "비밀번호가 일치하지 않습니다. 다시 입력해주세요.");
+        return false;
+      }
+
+      return true;
+    },
+    // 이메일 유효성 검사
+    validationEmail() {
+      let email = this.currentUser.userEmail;
+
+      // 1. null검사
+      if (this.$isEmpty(email)) {
+        this.$showAlert("관리자 관리", "이메일을 입력해주세요.");
+        return false;
+      }
+
+      // 2. 정규식 검사
+      if (!this.$email(email)) {
+        this.$showAlert("관리자 관리", "이메일 형식이 올바르지 않습니다.");
+        return false;
+      }
+
+      return true;
+    },
+  },
+};
+</script>(파일 끝에 줄바꿈 문자 없음)
client/views/pages/integrated/DBConnectionList.vue (Renamed from client/views/pages/integration/DBConnectionList.vue)
--- client/views/pages/integration/DBConnectionList.vue
+++ client/views/pages/integrated/DBConnectionList.vue
No changes
client/views/pages/integrated/DepartmentManagement.vue (Renamed from client/views/pages/integration/DepartmentManagement.vue)
--- client/views/pages/integration/DepartmentManagement.vue
+++ client/views/pages/integrated/DepartmentManagement.vue
@@ -537,11 +537,11 @@
         return false;
       }
 
-      // 3. 상위 부서 검사 null 검사
-      if (vm.$isEmpty(vm.departmentData.upper_dept) || vm.$isEmpty(vm.departmentData.upper_dept_nm)) {
-        vm.$showAlert("부서 등록", "상위 부서를 선택해주세요.");
-        return false;
-      }
+      // // 3. 상위 부서 검사 null 검사
+      // if (vm.$isEmpty(vm.departmentData.upper_dept) || vm.$isEmpty(vm.departmentData.upper_dept_nm)) {
+      //   vm.$showAlert("부서 등록", "상위 부서를 선택해주세요.");
+      //   return false;
+      // }
 
       // 4. 권한 null 검사
       if (vm.$isEmpty(vm.departmentData.author)) {
client/views/pages/integrated/InsertDBConnection.vue (Renamed from client/views/pages/integration/InsertDBConnection.vue)
--- client/views/pages/integration/InsertDBConnection.vue
+++ client/views/pages/integrated/InsertDBConnection.vue
No changes
 
client/views/pages/integrated/UserManagement.vue (added)
+++ client/views/pages/integrated/UserManagement.vue
@@ -0,0 +1,737 @@
+<template>
+  <div class="container">
+    <div class="page-titleZone flex justify-between align-center">
+      <p class="main-title flex80">사용자 관리</p>
+      <PageNavigation />
+    </div>
+    <div class="content-wrap">
+      <div class="content content-box flex100">
+        <div class="column-list">
+          <div class="content-titleZone flex justify-between align-center">
+            <p class="box-title">사용자 목록</p>
+            <div class="search-bar">
+              <div class="flex justify-end align-center">
+                <select class="square-select" v-model="search_data.key">
+                  <option :value="null">선택</option>
+                  <option value="ui.user_id">아이디</option>
+                  <option value="ui.user_nm">이름</option>
+                  <option value="orgnzt_info.dept_nm">부서</option>
+                </select>
+                <div class="search-square">
+                  <div class="flex justify-end align-center no-gutter">
+                    <input type="text" class="square-input flex90" placeholder="검색어를 입력해 주세요." v-model="search_data.value" @keyup.enter="fnSelectUserList" />
+                    <button class="square-button blue-btn flex10" @click="fnSelectUserList">
+                      <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon>
+                    </button>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="flex justify-between align-center">
+            <div class="count-zone">
+              <p>총 <span>{{ userList.length }}</span>건 중 <span>{{ userSelectList.length }}</span>건 선택</p>
+            </div>
+            <div class="cunt-selectZone">
+              <select v-model="search.perPage" @change="fnSelectUserList">
+                <option value="10">10개 보기</option>
+                <option value="20">20개 보기</option>
+              </select>
+            </div>
+          </div>
+          <div class="table-zone">
+            <table class="list-table">
+              <colgroup>
+                <col style="width: 5%" />
+                <col style="width: 5%" />
+                <col style="width: 17%" />
+                <col style="width: 17%" />
+                <col style="width: 17%" />
+                <col style="width: 17%" />
+                <col style="width: 17%" />
+                <col style="width: 5%" />
+              </colgroup>
+              <thead>
+                <tr>
+                  <th>
+                    <input type="checkbox" v-model="isChkAll" @change="fnChkAll()" />
+                  </th>
+                  <th>번호</th>
+                  <th>아이디</th>
+                  <th>이름</th>
+                  <th>이메일</th>
+                  <th>부서</th>
+                  <th>등록날짜</th>
+                  <th>잠김여부</th>
+                </tr>
+              </thead>
+              <tbody>
+                <template v-if="userList.length > 0">
+                  <tr v-for="(item, idx) in userList" :key="idx" @click="fnSelectUser(item.userId)">
+                    <td>
+                      <input type="checkbox" :value="item" v-model="userSelectList" @click.stop="" @change="fnChangeChk" />
+                    </td>
+                    <td>{{ search.totalRows - idx - (search.currentPage - 1) * search.perPage }}</td>
+                    <td>{{ item.userId }}</td>
+                    <td>{{ item.userNm }}</td>
+                    <td>{{ item.userEmail }}</td>
+                    <td>{{ item.deptNm }}</td>
+                    <td>{{ $filters.dateTime(item.creatDt) }}</td>
+                    <td>{{ item.lockAt ? "잠금" : "-" }}</td>
+                  </tr>
+                </template>
+                <tr v-else>
+                  <td colspan="8">등록된 데이터가 없습니다.</td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+          <div class="flex justify-end">
+            <button class="red-border-btn small-btn" @click="fnDeleteUser">선택 삭제</button>
+          </div>
+          <PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" :totalCount="search.totalRows" :maxRange="5" :click="fetchMemberList" />
+        </div>
+        <div class="data-set">
+          <div class="form-box">
+            <div class="content-titleZone">
+              <p class="box-title" v-if="editMode == 'create'">사용자 등록</p>
+              <p class="box-title" v-else>사용자 수정</p>
+            </div>
+            <div class="table-zone">
+              <table class="form-table2">
+                <colgroup>
+                  <col style="width: 10%" />
+                  <col style="width: 40%" />
+                  <col style="width: 10%" />
+                  <col style="width: 40%" />
+                </colgroup>
+                <tbody>
+                  <tr>
+                    <th>아이디</th>
+                    <td style="display: flex">
+                      <input type="text" class="full-input" v-model="currentUser.userId" :disabled="editMode == 'update'" />
+                      <button class="small-btn blue-border-btn" style="flex-grow: 1" v-if="editMode == 'create'" @click="fnDuplicateChk('id')">중복확인</button>
+                    </td>
+                    <th>이름</th>
+                    <td>
+                      <input type="text" class="full-input" v-model="currentUser.userNm" />
+                    </td>
+                  </tr>
+                  <tr v-if="editMode == 'create'">
+                    <th>비밀번호</th>
+                    <td>
+                      <input type="password" class="full-input" style="width: 100%" v-model="currentUser.userPassword" />
+                    </td>
+                    <th>비밀번호 확인</th>
+                    <td>
+                      <input type="password" class="full-input" style="width: 100%" v-model="userPasswordConfirm" />
+                    </td>
+                  </tr>
+                  <tr>
+                    <th>이메일</th>
+                    <td style="display: flex">
+                      <input type="text" class="full-input" v-model="currentUser.userEmail" />
+                      <button class="small-btn blue-border-btn" style="flex-grow: 1" @click="fnDuplicateChk('email')">중복확인</button>
+                    </td>
+                    <th>부서</th>
+                    <td>
+                      <select class="full-select" v-model="currentUser.dept_code">
+                        <option :value="null" disabled>부서를 선택해주세요.</option>
+                        <option v-for="(item, idx) in deptList" :key="idx" :value="item.dept_code"> {{ item.dept_nm }} </option>
+                      </select>
+                    </td>
+                  </tr>
+                  <tr v-if="editMode == 'update'">
+                    <th>잠김여부</th>
+                    <td style="display: flex">
+                      <input type="text" class="full-input" :value="currentUser.lockAt ? '잠금 (사용불가)' : '미잠금 (사용가능)'" readonly>
+                      <button class="blue-border-btn small-btn" style="flex-grow: 1" v-if="currentUser.lockAt" @click="fnUpdateUserLockAt">잠금해제</button>
+                    </td>
+                    <th></th>
+                    <td></td>
+                  </tr>
+                </tbody>
+              </table>
+            </div>
+            <div class="flex justify-end">
+              <button class="blue-border-btn small-btn" v-if="editMode == 'update'" @click="fnOpenModal">비밀번호 변경</button>
+              <button class="blue-btn small-btn" v-if="editMode == 'create'" @click="fnInsertUser">등록</button>
+              <button class="blue-btn small-btn" v-else @click="fnUpdateUser">수정</button>
+              <button class="blue-border-btn small-btn" @click="fnCancel">취소</button>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <!-- 비밀번호 변경 모달 -->
+  <div v-show="modalOpen" class="modal-wrapper">
+    <div class="modal-container small-modal">
+      <div class="modal-title">
+        <div class="flex justify-between align-center">
+          <h2>비밀번호 변경</h2>
+          <button class="close-btn" @click="fnCloseModal">X</button>
+        </div>
+      </div>
+      <div class="modal-content-monthly">
+        <div class="table-zone">
+          <table class="form-table">
+            <colgroup>
+              <col style="width: 40%" />
+              <col style="width: 60%" />
+            </colgroup>
+            <tbody>
+              <tr>
+                <th>새 비밀번호</th>
+                <td>
+                  <input type="password" class="full-input" v-model="userPassword" />
+                </td>
+              </tr>
+              <tr>
+                <th>새 비밀번호 확인</th>
+                <td>
+                  <input type="password" class="full-input" v-model="userPasswordConfirm" />
+                </td>
+              </tr>
+            </tbody>
+          </table>
+          <div class="modal-end flex justify-between" style="flex-wrap: nowrap;">
+            <button class="blue-btn large-btn" @click="fnUpdateUserPassword">수정</button>
+            <button class="blue-border-btn small-btn" @click="fnCancel"><span v-if="editMode == 'create'">초기화</span><span v-else>취소</span></button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import axios from "axios";
+// icon용 svg import
+import SvgIcon from "@jamescoyle/vue-icon";
+import { mdiClose, mdiMagnify } from "@mdi/js";
+// 컴포넌트 import
+import PageNavigation from "../../component/PageNavigation.vue";
+import PaginationButton from "../../component/PaginationButton.vue";
+
+export default {
+  components: { SvgIcon, PageNavigation, PaginationButton },
+
+  data() {
+    return {
+      // icon용 svg path
+      closePath: mdiClose,
+      searchPath: mdiMagnify,
+
+      // 검색
+      search: this.$getDefaultSerchVO(),
+      search_data: this.$getDefaultSerchItem(null, "string"),
+
+      // default
+      editMode: 'create',
+
+      memberVO: {},
+      originUser: {},
+      currentUser: {},
+
+      userPassword: null,
+      userPasswordConfirm: null,
+
+      isChkAll: false,
+      userList: [],
+      userSelectList: [],
+
+      deptList: [],
+
+      // 비밀번호 변경
+      modalOpen: false,
+
+      // 중복검사
+      isIdChk: false,
+      isEmailChk: false,
+    };
+  },
+
+  mounted() {
+    this.fnSelectUser(); // 사용자 개별 조회
+    this.fnSelectUserList(); // 사용자 목록 조회
+    this.fnSelectDeptList(); // 부서 목록 조회
+  },
+
+  watch: {
+    //아이디 값 변경 시 중복 검사 false로 변경
+    "currentUser.userId"() {
+      this.isIdChk = false;
+    },
+    //이메일 값 변경 시 중복 검사 false로 변경
+    "currentUser.userEmail"() {
+      this.isEmailChk = false;
+    },
+  },
+
+  methods: {
+    // 사용자 목록 조회
+    fnSelectUserList() {
+      const vm = this;
+      // 데이터 세팅
+      let data = vm.search;
+      data.searchObjectList = []; // 초기화
+      data.searchObjectList.push(vm.search_data);
+      // 실행
+      axios({
+        url: "/member/list",
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: data,
+      })
+        .then(response => {
+          if (response.data != null) {
+            vm.userList = response.data.resultData.members;
+            vm.search = response.data.resultData.searchVO;
+          } else {
+            this.$showAlert("사용자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("사용자 관리", "목록 불러오기 오류, 관리자에게 문의바랍니다.");
+        });
+    },
+    // 사용자 목록 전체 선택
+    fnChkAll() {
+      if (this.isChkAll) {
+        this.userSelectList = this.userList;
+      } else {
+        this.userSelectList = [];
+      }
+    },
+    // 사용자 목록 개별 선택
+    fnChangeChk() {
+      if (this.userSelectList.length == this.userList.length) {
+        this.isChkAll = true;
+      } else {
+        this.isChkAll = false;
+      }
+    },
+    // 사용자 선택 삭제
+    async fnDeleteUser() {
+      const vm = this;
+      // 선택 목록 확인
+      if (vm.userSelectList.length === 0) {
+        vm.$showAlert("사용자 관리", "선택한 사용자가 없습니다.");
+        return;
+      }
+      // 삭제 확인
+      if (!(await vm.$showConfirm("사용자 관리", "선택한 사용자를 삭제하시겠습니까?"))) {
+        return;
+      }
+
+      // 실행
+      axios({
+        url: "/member",
+        method: "delete",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: vm.userSelectList,
+      })
+        .then(response => {
+          if (response.data.checkMessage.status === 200) {
+            vm.$showAlert("사용자 관리", "선택한 사용자가 삭제되었습니다.");
+
+            // 삭제 후 작업
+            vm.isChkAll = false; // 체크 박스 리셋
+            vm.userSelectList = []; // 사용자 선택 목록 초기화
+            vm.fnSelectUserList(); // 전체 재조회
+          } else {
+            vm.$showAlert("사용자 관리", response.data.checkMessage.message);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("사용자 관리", "처리 중 오류가 발생했습니다. 관리자에게 문의바랍니다.");
+        });
+    },
+
+    // 부서 목록 조회
+    fnSelectDeptList() {
+      const vm = this;
+      // 데이터 세팅팅
+      let search = Object.assign({}, this.$getDefaultSerchVO());
+      search.currentPage = 0;
+      search.perPage = 0;
+      // 실행
+      axios({
+        url: "/department/departments",
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: search,
+      })
+        .then(response => {
+          if (response.data != null) {
+            vm.deptList = response.data.resultData.selectDeptList;
+          } else {
+            this.$showAlert("사용자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("사용자 관리", "목록 불러오기 오류, 관리자에게 문의바랍니다.");
+        });
+    },
+
+    // 사용자 등록
+    fnInsertUser() {
+      const vm = this;
+      // 유효성 검사
+      if (!vm.insertValidation()) {
+        return;
+      }
+      // 실행
+      axios({
+        url: "/member",
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: vm.currentUser,
+      })
+        .then(response => {
+          if (response.data.checkMessage.status === 200) {
+            vm.$showAlert("사용자 관리", "사용자 등록이 완료되었습니다.");
+            vm.currentUser = Object.assign({}, vm.memberVO); // 초기화
+            vm.fnSelectUserList();
+          } else {
+            vm.$showAlert("사용자 관리", response.data.checkMessage.message);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("사용자 관리", "사용자 등록에 실패했습니다. 다시 시도해주세요.");
+        });
+    },
+
+    // 사용자 개별 조회
+    fnSelectUser(userId) {
+      const vm = this;
+      // 데이터 세팅
+      let url = null;
+      if (vm.$isEmpty(userId)) {
+        url = "/member/selectUser";
+      } else {
+        url = "/member/selectUser/" + userId;
+      }
+      // 실행
+      axios({
+        url: url,
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+      })
+        .then(response => {
+          if (vm.$isEmpty(userId)) {
+            vm.memberVO = response.data;
+          } else {
+            vm.editMode = 'update';
+            vm.originUser = response.data;
+            vm.currentUser = Object.assign({}, response.data);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("사용자 관리", "불러오기 오류, 관리자에게 문의바랍니다.");
+        });
+    },
+
+    // 사용자 수정
+    fnUpdateUser() {
+      const vm = this;
+      // 유효성 검사
+      if (!vm.updateValidation()) {
+        return;
+      }
+      // 실행
+      axios({
+        url: "/member",
+        method: "put",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: vm.currentUser
+      })
+        .then(response => {
+          if (response.data.checkMessage.status === 200) {
+            vm.$showAlert("사용자 관리", "사용자 정보가 수정되었습니다.");
+            vm.originUser = Object.assign({}, vm.memberVO); // 초기화
+            vm.currentUser = Object.assign({}, vm.memberVO); // 초기화
+            vm.editMode = 'create';
+            vm.fnSelectUserList();
+          } else {
+            vm.$showAlert("사용자 관리", response.data.checkMessage.message);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("사용자 관리", "수정 오류, 관리자에게 문의해주세요.");
+        });
+    },
+
+    // 중복확인 버튼 동작
+    fnDuplicateChk(type) {
+      if (type == 'id') {
+        this.idDuplicateChk();
+      } else if (type == 'email') {
+        this.emailDuplicateChk();
+      }
+    },
+    // 아이디 중복 검사
+    idDuplicateChk() {
+      const vm = this;
+      // 유효성 검사
+      if (!vm.$idCheck(vm.currentUser.userId)) {
+        vm.$showAlert("사용자 관리", "아이디 형식이 올바르지 않습니다. (5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용가능)");
+        return false;
+      }
+      // 실행
+      axios({
+        url: "/member/" + vm.currentUser.userId,
+        method: "get",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+      })
+        .then(response => {
+          if (response.data.resultData.checkDuplicateUserId) {
+            vm.isIdChk = false;
+            vm.$showAlert("사용자 관리", "사용중인 아이디입니다.");
+          } else {
+            vm.isIdChk = true;
+            vm.$showAlert("사용자 관리", "사용할 수 있는 아이디입니다.");
+          }
+        })
+        .catch(error => {
+          this.$showAlert("사용자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
+        });
+    },
+    // 이메일 중복 검사
+    emailDuplicateChk() {
+      const vm = this;
+      // 유효성 검사
+      if (!vm.validationEmail()) {
+        return;
+      }
+      // 실행
+      axios({
+        url: "/member/email",
+        method: "get",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+        data: vm.currentUser.userEmail,
+      })
+        .then(response => {
+          if (response.data.resultData.result) {
+            vm.$showAlert("사용자 관리", "사용중인 이메일입니다.");
+            vm.isEmailChk = false;
+          } else {
+            vm.$showAlert("사용자 관리", "사용할 수 있는 이메일입니다.");
+            vm.isEmailChk = true;
+          }
+        })
+        .catch(error => {
+          this.$showAlert("사용자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요.");
+        });
+    },
+
+    // 사용자 잠금 해제
+    fnUpdateUserLockAt() {
+      const vm = this;
+      // 실행
+      axios({
+        url: "/member/updateUser/LockAt/" + vm.currentUser.userId,
+        method: "post",
+        headers: { "Content-Type": "application/json; charset=UTF-8" },
+      })
+        .then(response => {
+          if (response.data.checkMessage.status === 200) {
+            vm.$showAlert("사용자 관리", "사용자 잠금이 해제되었습니다.");
+            vm.fnSelectUser(vm.currentUser.userId); // 사용자 개별 재조회
+          } else {
+            vm.$showAlert("사용자 관리", response.data.checkMessage.message);
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("사용자 관리", "수정 오류, 관리자에게 문의해주세요.");
+        });
+    },
+
+    // 사용자 비밀번호 변경 모달 열기
+    fnOpenModal() {
+      this.userPassword = null;
+      this.userPasswordConfirm = null;
+
+      this.modalOpen = true;
+    },
+    // 사용자 비밀번호 변경 모달 열기
+    fnCloseModal() {
+      this.modalOpen = false;
+    },
+    // 사용자 비밀번호 변경
+    fnUpdateUserPassword() {
+      const vm = this;
+      // 유효성 검사
+      vm.currentUser.userPassword = vm.userPassword;
+      if (!vm.validationPassword()) {
+        return;
+      }
+      // 실행
+      axios({
+        url: "/member",
+        method: "patch",
+        headers: {
+          "Content-Type": "application/json",
+        },
+        data: {
+          userId: vm.currentUser.userId,
+          userPassword: vm.userPassword,
+        },
+      })
+        .then(response => {
+          if (response.data.resultData.result) {
+            vm.$showAlert("비밀번호 변경", "비밀번호 변경에 성공했습니다.");
+            vm.modalOpen = false;
+          } else {
+            vm.$showAlert("비밀번호 변경", "비밀번호 변경에 실패했습니다. 다시 시도해주세요.");
+          }
+        })
+        .catch(error => {
+          vm.$showAlert("비밀번호 변경", "비밀번호 변경에 실패했습니다. 다시 시도해주세요.");
+        });
+    },
+
+    // 사용자 등록 취소
+    fnCancel() {
+      if (this.editMode == 'update') {
+        this.editMode = 'create';
+      }
+      // 초기화
+      this.userPassword = null;
+      this.userPasswordConfirm = null;
+      this.currentUser = Object.assign({}, this.memberVO);
+    },
+
+    // #유효성 검사
+    // 등록용 유효성 검사
+    insertValidation() {
+      // 아이디 유효성 검사
+      if (!this.validationId()) {
+        return false;
+      }
+      // 아이디 중복 검사 여부
+      if (!this.isIdChk) {
+        this.$showAlert("사용자 관리", "아이디 중복 확인 후 시도해주세요.");
+        return false;
+      }
+
+      // 이름 유효성 검사
+      if (!this.validationName()) {
+        return false;
+      }
+
+      // 비밀번호 유효성 검사
+      if (!this.validationPassword()) {
+        return false;
+      }
+
+      // 이메일 유효성 검사
+      if (!this.validationEmail()) {
+        return false;
+      }
+      // 이메일 중복 검사 여부
+      if (!this.isEmailChk) {
+        this.$showAlert("사용자 관리", "이메일 중복확인 후 등록해주세요.");
+        return false;
+      }
+
+      return true;
+    },
+    // 수정용 유효성 검사
+    updateValidation() {
+      if (JSON.stringify(this.currentUser) === JSON.stringify(this.originUser)) {
+        this.$showAlert("사용자 관리", "수정된 정보가 없습니다.");
+        return;
+      }
+
+      // 이름 유효성 검사
+      if (!this.validationName()) {
+        return false;
+      }
+
+      // 이메일 유효성 검사
+      if (!this.validationEmail()) {
+        return false;
+      }
+
+      // 이메일 중복 검사 여부
+      if (!this.isEmailChk) {
+        this.$showAlert("사용자 관리", "이메일 중복확인 후 수정해주세요.");
+        return false;
+      }
+
+      return true;
+    },
+    // 아이디 유효성 검사
+    validationId() {
+      let id = this.currentUser.userId;
+
+      if (this.$isEmpty(id)) {
+        this.$showAlert("사용자 관리", "아이디를 입력해주세요.");
+        return false;
+      }
+
+      if (!this.$idCheck(id)) {
+        this.$showAlert("사용자 관리", "아이디 형식이 올바르지 않습니다. (5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용가능)");
+        return false;
+      }
+
+      return true;
+    },
+    // 이름 유효성 검사
+    validationName() {
+      let name = this.currentUser.userNm;
+
+      if (this.$isEmpty(name)) {
+        this.$showAlert("사용자 관리", "이름을 입력해주세요.");
+        return false;
+      }
+
+      let validateName = /^[가-힣A-Za-z\s]+$/;
+      if (!validateName.test(name)) {
+        this.$showAlert("사용자 관리", "이름에 숫자와 특수문자를 입력할 수 없습니다.");
+        return false;
+      }
+
+      return true;
+    },
+    // 비밀번호 유효성 검사
+    validationPassword() {
+      if (this.$isEmpty(this.currentUser.userPassword)) {
+        this.$showAlert("사용자 관리", "비밀번호를 입력해주세요.");
+        return false;
+      }
+
+      if (!this.$pwCheck(this.currentUser.userPassword)) {
+        this.$showAlert("사용자 관리", "비밀번호 형식이 올바르지 않습니다. (8~16자의 영문 대문자, 소문자, 숫자, 특수문자 사용가능)");
+        return false;
+      }
+
+      if (this.currentUser.userPassword !== this.userPasswordConfirm) {
+        this.$showAlert("사용자 관리", "비밀번호가 일치하지 않습니다. 다시 입력해주세요.");
+        return false;
+      }
+
+      return true;
+    },
+    // 이메일 유효성 검사
+    validationEmail() {
+      let email = this.currentUser.userEmail;
+
+      // 1. null검사
+      if (this.$isEmpty(email)) {
+        this.$showAlert("사용자 관리", "이메일을 입력해주세요.");
+        return false;
+      }
+
+      // 2. 정규식 검사
+      if (!this.$email(email)) {
+        this.$showAlert("사용자 관리", "이메일 형식이 올바르지 않습니다.");
+        return false;
+      }
+
+      return true;
+    },
+  },
+};
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/integration/UserManagement.vue (deleted)
--- client/views/pages/integration/UserManagement.vue
@@ -1,845 +0,0 @@
-<template>
-  <div class="container">
-    <div class="page-titleZone flex justify-between align-center">
-      <p class="main-title flex80">사용자 관리</p>
-      <PageNavigation />
-    </div>
-    <div class="content-wrap">
-      <div class="content content-box flex100">
-        <div class="column-list">
-          <div class="content-titleZone flex justify-between align-center">
-            <p class="box-title">사용자 목록</p>
-            <div class="flex justify-end align-center">
-              <select class="square-select" v-model="search_data.key">
-                <option :value="null" disabled>선택</option>
-                <option value="ui.user_id">아이디</option>
-                <option value="ui.user_nm">이름</option>
-                <option value="orgnzt_info.dept_nm">부서</option>
-              </select>
-              <div class="search-square">
-                <input type="text" class="square-input" v-model="search_data.value" placeholder="검색어를 입력해주세요." @keyup.enter="searchUser" />
-                <button class="square-button blue-btn" @click="searchUser">
-                  <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon>
-                </button>
-              </div>
-            </div>
-          </div>
-          <div class="flex justify-between align-center">
-            <div class="count-zone">
-              <p>총 <span>{{ memberList.length }}</span>건 중 <span>{{ selectedMembers.length }}</span>건 선택</p>
-            </div>
-            <div class="cunt-selectZone">
-              <select v-model="selectedPerPage" @change="updatePerPage">
-                <option value="10">10개 보기</option>
-                <option value="20">20개 보기</option>
-              </select>
-            </div>
-          </div>
-          <div class="table-zone">
-            <table class="list-table">
-              <colgroup>
-                <col style="width: 5%" />
-                <col style="width: 5%" />
-                <col style="width: 16%" />
-                <col style="width: 16%" />
-                <col style="width: 16%" />
-                <col style="width: 16%" />
-                <col style="width: 16%" />
-                <col style="width: 5%" />
-              </colgroup>
-              <thead>
-                <tr>
-                  <th>
-                    <input type="checkbox" @click="memberCheckAll" v-model="checkAll" />
-                  </th>
-                  <th>No</th>
-                  <th>아이디</th>
-                  <th>이름</th>
-                  <th>이메일</th>
-                  <th>부서</th>
-                  <th>등록날짜</th>
-                  <th>잠김여부</th>
-                </tr>
-              </thead>
-              <tbody>
-                <tr v-for="(member, index) in memberList" :key="index" @click="loadHostData(member)">
-                  <td>
-                    <input type="checkbox" @click.stop="" v-model="selectedMembers" :value="member.userId" name="memberList" />
-                  </td>
-                  <td>{{ memberIdx - index }}</td>
-                  <td>{{ member.userId }}</td>
-                  <td>{{ member.userNm }}</td>
-                  <td>{{ member.userEmail }}</td>
-                  <td>{{ member.deptNm }}</td>
-                  <td>{{ $filters.dateTime(member.creatDt) }}</td>
-                  <td>{{ member.lockAt == false ? "X" : "Y" }}</td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-          <!-- <div v-if="this.author == 'ROLE_ADMIN'" class="flex justify-end"> -->
-          <PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" :totalCount="search.totalRows" :maxRange="5" :click="fetchMemberList" />
-          <div class="flex justify-end">
-            <button class="red-border-btn small-btn" @click="deleteSelectedMembers">선택 삭제</button>
-          </div>
-        </div>
-        <div class="data-set">
-          <div class="form-box">
-            <div class="content-titleZone">
-              <p class="box-title" v-if="!dataLoaded">사용자 등록</p>
-              <p class="box-title" v-else>사용자 수정</p>
-            </div>
-            <div class="table-zone">
-              <table class="form-table2">
-                <colgroup>
-                  <col style="width: 10%" />
-                  <col style="width: 40%" />
-                  <col style="width: 10%" />
-                  <col style="width: 40%" />
-                </colgroup>
-                <tbody>
-                  <tr>
-                    <th>아이디</th>
-                    <td style="display: flex">
-                      <input type="text" name="" id="userId" class="full-input" v-model="memberData.userId" :disabled="dataLoaded" />
-                      <button @click="checkDuplicate" style="flex-grow: 1" class="small-btn blue-border-btn" v-if="!dataLoaded"> 중복확인 </button>
-                    </td>
-                    <th>이름</th>
-                    <td>
-                      <input type="text" name="" id="userNm" class="full-input" v-model="memberData.userNm" />
-                    </td>
-                  </tr>
-                  <tr v-if="!dataLoaded">
-                    <th>비밀번호</th>
-                    <td>
-                      <input id="userPassword" type="password" class="full-input" style="width: 100%" v-model="memberData.userPassword" />
-                    </td>
-                    <th>비밀번호 변경 확인</th>
-                    <td>
-                      <input id="passwordConfirm" type="password" class="full-input" style="width: 100%" v-model="passwordConfirm" />
-                    </td>
-                  </tr>
-                  <tr>
-                    <th>이메일</th>
-                    <td style="display: flex">
-                      <input type="text" name="" id="email" class="full-input" v-model="memberData.userEmail" />
-                      <button style="flex-grow: 1" class="small-btn blue-border-btn" v-if="
-                        dataLoaded &&
-                        originalmemberData.userEmail !== memberData.userEmail
-                      " @click="mailDuplicateCheck()"> 중복확인 </button>
-                      <button style="flex-grow: 1" class="small-btn blue-border-btn" v-if="!dataLoaded" @click="mailDuplicateCheck()"> 중복확인 </button>
-                    </td>
-                    <th>권한</th>
-                    <td style="display: flex">
-                      <select class="full-select" v-model="memberData.author" @change="changeAuthor">
-                        <option :value="null" disabled>권한을 선택해주세요.</option>
-                        <option v-for="(author, idx) in authorList" :key="idx" :value="author.author">{{ author.author_dc }}</option>
-                      </select>
-                    </td>
-                  </tr>
-                  <tr>
-                    <th>부서</th>
-                    <td>
-                      <select name="" id="deptNm" class="full-select" v-model="memberData.dept_code">
-                        <option :value="null" disabled>부서를 선택해주세요.</option>
-                        <option v-for="(department, idx) in departmentList" :key="idx" :value="department.dept_code"> {{ department.dept_nm }} </option>
-                      </select>
-                    </td>
-                    <th><template v-if="dataLoaded">잠김여부</template></th>
-                    <td style="display: flex">
-                      <template v-if="dataLoaded">
-                        <input type="text" class="full-input" :value="memberData.lockAt ? '사용불가' : '사용가능'" readonly>
-                        <button class="blue-border-btn small-btn" @click="toggleLockAtStatus" style="flex-grow: 1"> {{ memberData.lockAt ? "잠금해제" : "잠금설정" }} </button>
-                      </template>
-                    </td>
-                  </tr>
-                </tbody>
-              </table>
-            </div>
-            <!-- <div v-if="this.author == 'ROLE_ADMIN' || memberData.userId == this.userId" class="flex justify-end"> -->
-            <div class="flex justify-end">
-              <template v-if="dataLoaded">
-                <button class="blue-border-btn small-btn" @click="openModal()">비밀번호 변경</button>
-                <button class="blue-btn small-btn" @click="updateMember()">수정</button>
-                <button class="red-border-btn small-btn" @click="insertForm()">취소</button>
-              </template>
-              <template v-else>
-                <button class="blue-btn small-btn" @click="memberInsert()">등록</button>
-                <button class="darkg-border-btn small-btn" @click="resetForm()">초기화</button>
-              </template>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-  <!-- 비밀번호 변경 모달 -->
-  <div v-show="modalOpen" class="modal-wrapper">
-    <div class="modal-container small-modal">
-      <div class="modal-title text-ct">
-        <h2>비밀번호 변경</h2>
-      </div>
-      <div class="modal-content-monthly">
-        <div class="table-zone">
-          <table class="form-table2">
-            <colgroup>
-              <col style="width: 40%" />
-              <col style="width: 60%" />
-            </colgroup>
-            <tbody>
-              <tr>
-                <th>새 비밀번호</th>
-                <td>
-                  <input type="password" id="pwChange" class="full-input" v-model="pwChange" />
-                </td>
-              </tr>
-              <tr>
-                <th>새 비밀번호 확인</th>
-                <td>
-                  <input type="password" id="pwChangeCheck" class="full-input" v-model="pwChangeCheck" />
-                </td>
-              </tr>
-            </tbody>
-          </table>
-        </div>
-      </div>
-      <div class="modal-end flex justify-between" style="flex-wrap: nowrap;">
-        <button class="blue-btn large-btn" @click="passwordChange()">변경</button>
-        <button class="gray-btn large-btn" @click="closeModal()">취소</button>
-      </div>
-    </div>
-  </div>
-</template>
-<script>
-import PageNavigation from "../../component/PageNavigation.vue";
-import PaginationButton from "../../component/PaginationButton.vue";
-import SvgIcon from "@jamescoyle/vue-icon";
-import { mdiMagnify } from "@mdi/js";
-import axios from "axios";
-import store from "../AppStore";
-
-export default {
-  data() {
-    return {
-      search: this.$getDefaultSerchVO(),
-      search_data: this.$getDefaultSerchItem(null, "String"),
-
-      searchPath: mdiMagnify,
-      inputValue: null,
-
-      memberData: {
-        userId: null,
-        userPassword: null,
-        userNm: null,
-        deptNm: null,
-        userEmail: null,
-        author: null,
-        dept_code: null,
-        lockAt: null,
-      },
-      userId: null,
-      authList: null,
-      author: null,
-      dept_code: null,
-
-      memberList: [],
-      passwordConfirm: null,
-      changePwConfirm: null,
-      changPw: null,
-      departmentList: [],
-      authorList: [],
-      isDuplicateChecked: false,
-      emailDuplicateChecked: false,
-      memberIdx: 0,
-      selectedMembers: [],
-      checkAll: false,
-      //페이지 당 보여줄 수
-      selectedPerPage: "10",
-      //비밀번호 변경 모달창
-      modalOpen: false,
-      pwChange: null,
-      pwChangeCheck: null,
-      changeEmail: null,
-
-      //부서
-      dept_search_data: this.$getDefaultSerchItem(null, "String"),
-      deptSearch: this.$getDefaultSerchVO(),
-    };
-  },
-  methods: {
-    searchInit: function () {
-      this.search.searchObjectList.push(this.search_data);
-    },
-
-    deptSearchInit: function () {
-      this.deptSearch.searchObjectList.push(this.dept_search_data);
-    },
-
-    insertForm: function () {
-      this.dataLoaded = false;
-      this.resetForm();
-    },
-
-    toggleLockAtStatus() {
-      this.memberData.lockAt = !this.memberData.lockAt;
-    },
-
-    //사용자 등록
-    memberInsert: function () {
-      const vm = this;
-
-      if (!vm.memberInsertValidation()) {
-        return;
-      }
-
-      axios({
-        url: "/member",
-        method: "post",
-        headers: {
-          "Content-Type": "application/json; charset=UTF-8",
-        },
-        data: vm.memberData,
-      })
-        .then(function (response) {
-          if (response.data.checkMessage.status === 200) {
-            vm.$showAlert("사용자 등록", "사용자 등록이 완료되었습니다.");
-            vm.fetchMemberList();
-            vm.resetData();
-          } else {
-            vm.$showAlert("사용자 등록", response.data.checkMessage.message);
-          }
-        })
-        .catch(function (error) {
-          vm.$showAlert(
-            "사용자 등록",
-            "사용자 등록에 실패했습니다. 다시 시도해주세요."
-          );
-        });
-    },
-
-    //검색기준 유효성 검사
-    searchUser: function () {
-      if (!this.search_data.key) {
-        this.$showAlert("회원 검색", "검색 기준을 선택하세요.");
-        return;
-      }
-      this.fetchMemberList();
-    },
-
-    //사용자 목록 조회
-    fetchMemberList() {
-      const vm = this;
-      axios({
-        url: "/member/list",
-        method: "post",
-        data: vm.search,
-      })
-        .then(function (response) {
-          if (response.data) {
-            vm.memberList = response.data.resultData.selectMemberList;
-            vm.search.totalRows = response.data.resultData.totalRow;
-            vm.memberIdx =
-              vm.search.totalRows -
-              (vm.search.currentPage - 1) * vm.search.perPage;
-          } else {
-            this.$showAlert(
-              "에러 발생",
-              "에러가 발생했습니다. 관리자에게 문의해 주세요."
-            );
-          }
-        })
-        .catch(function (error) {
-          vm.$showAlert(
-            "회원 목록",
-            "목록 불러오기 오류, 관리자에게 문의바랍니다."
-          );
-        });
-    },
-
-    //사용자 정보 변경
-    updateMember: async function () {
-      const vm = this;
-
-      if (
-        JSON.stringify(vm.memberData) ===
-        JSON.stringify(vm.originalmemberData) &&
-        (vm.changPw === null || vm.changPw === "")
-      ) {
-        vm.$showAlert("사용자 수정", "수정된 정보가 없습니다.");
-        return;
-      }
-
-      if (!vm.updateMemberInfoValidation()) return;
-
-      axios
-        .put("/member", vm.memberData)
-        .then((response) => {
-          if (response.data.checkMessage.status === 200) {
-            vm.$showAlert("사용자 수정", "사용자 정보가 수정되었습니다.");
-            vm.changPw = null;
-            vm.changePwConfirm = null;
-            vm.resetData();
-            vm.fetchMemberList();
-          } else {
-            vm.$showAlert("사용자 수정", response.data.checkMessage.message);
-          }
-        })
-        .catch((error) => {
-          // vm.$showAlert('사용자 수정', '수정 오류, 관리자에게 문의해주세요.');
-        });
-    },
-
-    //사용자 정보 변경용 유효성 검사
-    updateMemberInfoValidation: function () {
-      const vm = this;
-
-      //1.사용자 이름 유효성 검사
-      let validateName = /^[가-힣A-Za-z\s]+$/;
-      if (!validateName.test(vm.memberData.userNm)) {
-        vm.$showAlert(
-          "사용자 수정",
-          "이름에 숫자와 특수문자를 입력할 수 없습니다."
-        );
-        return false;
-      }
-
-      //2.이메일 null 검사
-      if (!vm.memberData.userEmail) {
-        vm.$showAlert("사용자 수정", "이메일을 입력하세요.");
-        document.getElementById("email").focus();
-        return false;
-      }
-      //3.이메일 유효성 검사
-      if (!vm.$email(vm.memberData.userEmail)) {
-        vm.$showAlert("사용자 수정", "이메일 형식이 올바르지 않습니다.");
-        document.getElementById("email").focus();
-        return false;
-      }
-      //4.이메일 중복 검사 여부 체크
-      //이메일을 안바꾼 경우(전처리)
-      if (
-        vm.dataLoaded &&
-        vm.originalmemberData.userEmail === vm.memberData.userEmail
-      ) {
-        vm.emailDuplicateChecked = true;
-      }
-      if (!vm.emailDuplicateChecked) {
-        vm.$showAlert("사용자 수정", "이메일 중복확인 후 등록해주세요.");
-        return false;
-      }
-
-      return true;
-    },
-
-    getAuthorList() {
-      const vm = this;
-      axios({
-        url: "/member/getAuthorInfo",
-        method: "get",
-      })
-        .then(function (response) {
-          vm.authorList = response.data.resultData.getAuthorInfo;
-        })
-        .catch(function (error) {
-          this.$showAlert(
-            "에러 발생",
-            "에러가 발생했습니다. 관리자에게 문의해 주세요."
-          );
-        });
-    },
-
-    //ID중복 검사
-    checkDuplicate() {
-      const vm = this;
-
-      if (!vm.$idCheck(vm.memberData.userId)) {
-        vm.$showAlert(
-          "사용자 등록",
-          "아이디 형식이 올바르지 않습니다. (5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용가능)"
-        );
-        document.getElementById("userId").focus();
-        return false;
-      }
-
-      axios({
-        url: "/member/" + vm.memberData.userId,
-        method: "get",
-        headers: {
-          "Content-Type": "application/json; charset=UTF-8",
-        },
-      })
-        .then((response) => {
-          if (response.data.resultData.checkDuplicateUserId) {
-            vm.$showAlert("아이디 중복확인", "사용중인 아이디입니다.");
-            vm.isDuplicateChecked = false;
-          } else {
-            vm.$showAlert("아이디 중복확인", "사용할 수 있는 아이디입니다.");
-            vm.isDuplicateChecked = true;
-          }
-        })
-        .catch((error) => {
-          this.$showAlert(
-            "에러 발생",
-            "에러가 발생했습니다. 관리자에게 문의해 주세요."
-          );
-        });
-    },
-
-    //사용자 선택 삭제
-    async deleteSelectedMembers() {
-      const vm = this;
-
-      if (vm.selectedMembers.length === 0) {
-        vm.$showAlert("사용자 삭제", "선택한 사용자가 없습니다.");
-        return;
-      }
-
-      if (
-        !(await vm.$showConfirm(
-          "사용자삭제",
-          "선택한 사용자를 삭제하시겠습니까?"
-        ))
-      ) {
-        return;
-      }
-
-      axios({
-        url: "/member",
-        method: "delete",
-        headers: {
-          "Content-Type": "application/json",
-        },
-        data: vm.selectedMembers,
-      })
-        .then(function (response) {
-          if (response.data.checkMessage.status === 200) {
-            vm.$showAlert("사용자 삭제", "선택한 사용자가 삭제되었습니다.");
-            vm.checkAll = false;
-            vm.selectedMembers = [];
-            vm.fetchMemberList();
-          } else {
-            // vm.$showAlert('사용자 삭제','선택한 사용자 삭제에 실패하였습니다. 다시 시도해주세요.')
-            vm.$showAlert("사용자 삭제", response.data.checkMessage.message);
-          }
-        })
-        .catch(function (error) {
-          vm.$showAlert("사용자 삭제", "삭제오류, 관리자에게 문의바랍니다.");
-        });
-    },
-
-    //사용자 등록 유효성 검사
-    memberInsertValidation: function () {
-      const vm = this;
-      //1.ID null 검사
-      if (vm.$isEmpty(vm.memberData.userId)) {
-        vm.$showAlert("사용자 등록", "아이디(ID)를 입력해주세요.");
-        document.getElementById("userId").focus();
-        return false;
-      }
-      //2. ID 중복 검사
-      if (!vm.isDuplicateChecked) {
-        vm.$showAlert("사용자 등록", "아이디 중복확인 후 등록해주세요.");
-        return false;
-      }
-      //3. 이름 null 검사
-      if (vm.$isEmpty(vm.memberData.userNm)) {
-        vm.$showAlert("사용자 등록", "이름을 입력해주세요.");
-        document.getElementById("userNm").focus();
-        return false;
-      }
-      //4. 이름 유효성 검사
-      let validateName = /^[가-힣A-Za-z\s]+$/;
-      if (!validateName.test(vm.memberData.userNm)) {
-        vm.$showAlert(
-          "사용자 등록",
-          "이름에 숫자와 특수문자를 입력할 수 없습니다."
-        );
-        document.getElementById("userNm").focus();
-        return false;
-      }
-      //5. 비밀번호 null 검사
-      if (vm.$isEmpty(vm.memberData.userPassword)) {
-        vm.$showAlert("사용자 등록", "비밀번호를 입력해주세요.");
-        document.getElementById("userPassword").focus();
-        return false;
-      }
-
-      //6. 비밀번호 유효성 검사
-      if (!vm.$pwCheck(vm.memberData.userPassword)) {
-        vm.$showAlert(
-          "사용자 등록",
-          "비밀번호 형식이 올바르지 않습니다. (8~16자의 영문 대문자, 소문자, 숫자, 특수문자 사용가능)"
-        );
-        document.getElementById("userPassword").focus();
-        return false;
-      }
-
-      //7. 비밀번호와 비밀번호 확일 일치여부 검사
-      if (vm.memberData.userPassword !== vm.passwordConfirm) {
-        vm.$showAlert(
-          "사용자 등록",
-          "비밀번호가 일치하지 않습니다. 다시 입력해주세요."
-        );
-        document.getElementById("passwordConfirm").focus();
-        return false;
-      }
-      //8.이메일 null 검사
-      if (!vm.memberData.userEmail) {
-        vm.$showAlert("사용자 등록", "이메일을 입력하세요.");
-        document.getElementById("email").focus();
-        return false;
-      }
-      //9.이메일 유효성 검사
-      if (!vm.$email(vm.memberData.userEmail)) {
-        vm.$showAlert("사용자 등록", "이메일 형식이 올바르지 않습니다.");
-        document.getElementById("email").focus();
-        return false;
-      }
-      //10.이메일 중복검사 여부 확인
-      if (!vm.emailDuplicateChecked) {
-        vm.$showAlert("사용자 등록", "이메일 중복확인 후 등록해주세요.");
-        document.getElementById("email").focus();
-        return false;
-      }
-      //11. 권한 null 검사
-      if (vm.$isEmpty(vm.memberData.author)) {
-        vm.$showAlert("사용자 등록", "권한을 선택해주세요.");
-        document.getElementById("author").focus();
-        return false;
-      }
-
-      return true;
-    },
-
-    resetData() {
-      this.memberData = {}; // 데이터를 초기화합니다.
-      this.dataLoaded = false; // 데이터 로드 상태를 초기화합니다.
-      this.passwordConfirm = null;
-      this.changePwConfirm = null;
-    },
-
-    //사용자 선택 삭제용 선택 기능
-    check: function (member) {
-      this.selectedMembers.push(member.userId);
-    },
-
-    //사용자 선택 삭제용 전체 선택 기능
-    memberCheckAll() {
-      this.checkAll = !this.checkAll;
-
-      if (this.checkAll) {
-        this.memberList.forEach((member) => {
-          this.selectedMembers.push(member.userId);
-        });
-      } else {
-        this.selectedMembers = [];
-      }
-    },
-
-    resetForm() {
-      this.memberData = {
-        userId: null,
-        userPassword: null,
-        userNm: null,
-        deptNm: null,
-        userEmail: null,
-        author: null,
-      };
-      this.passwordConfirm = null;
-      this.changePwConfirm = null;
-    },
-
-    loadHostData(member) {
-      this.memberData = Object.assign({}, member); // 클릭한 호스트의 데이터를 복사하여 저장합니다.
-      this.originalmemberData = Object.assign({}, member);
-      this.changeAuthor();
-      this.dataLoaded = true; // 데이터가 로드되었음을 표시합니다.
-    },
-
-    //10개보기, 20개보기
-    changePerPage: function () {
-      this.search.perPage = this.selectedPerPage;
-      this.fetchMemberList();
-    },
-
-    closeModal: function () {
-      this.modalOpen = false;
-    },
-    //비밀번호 변경 모달 열기
-    openModal: function () {
-      this.modalOpen = true;
-      this.pwChange = null;
-      this.pwChangeCheck = null;
-    },
-
-    //비밀번호 변경 유효성 검사
-    passwordChangeValidation: function () {
-      const vm = this;
-      //1.변경 비밀번호의 null검사
-      if (vm.$isEmpty(vm.pwChange)) {
-        vm.$showAlert("비밀번호 변경", "변경할 비밀번호를 입력하세요.");
-        document.getElementById("pwChange").focus();
-        return false;
-      }
-      //2.변경 비밀번호의 형식검사
-      if (!vm.$pwCheck(vm.pwChange)) {
-        vm.$showAlert("비밀번호 변경", "비밀번호 형식이 올바르지 않습니다.");
-        document.getElementById("pwChange").focus();
-        return false;
-      }
-      //3.변경 비밀번호와 비밀번호 확인의 일치여부 확인
-      if (vm.pwChange !== vm.pwChangeCheck) {
-        vm.$showAlert("비밀번호 변경", "비밀번호 형식이 올바르지 않습니다.");
-        document.getElementById("pwChangeCheck").focus();
-        return false;
-      }
-
-      return true;
-    },
-    //유저 비밀번호 변경
-    passwordChange: function () {
-      const vm = this;
-      if (!vm.passwordChangeValidation()) {
-        return;
-      }
-
-      axios({
-        url: "/member",
-        method: "patch",
-        headers: {
-          "Content-Type": "application/json",
-        },
-        data: {
-          userId: vm.memberData.userId,
-          userPassword: vm.pwChange,
-        },
-      })
-        .then(function (response) {
-          if (response.data.resultData.result) {
-            vm.$showAlert("비밀번호 변경", "비밀번호 변경에 성공하였습니다.");
-            vm.modalOpen = false;
-          } else {
-            vm.$showAlert(
-              "비밀번호 변경",
-              "비밀번호 변경에 실패하였습니다. 다시 시도해주세요."
-            );
-          }
-        })
-        .catch(function (error) {
-          vm.$showAlert(
-            "비밀번호 변경",
-            "비밀번호 변경에 실패하였습니다. 다시 시도해주세요."
-          );
-        });
-    },
-
-    //이메일 중복검사
-    mailDuplicateCheck: function () {
-      const vm = this;
-      if (!vm.mailValidation()) {
-        return;
-      }
-
-      axios({
-        url: "/member/email",
-        method: "post",
-        headers: {
-          "Content-Type": "application/json;",
-        },
-        data: {
-          userEmail: vm.memberData.userEmail,
-        },
-      })
-        .then((response) => {
-          if (response.data.resultData.result) {
-            vm.$showAlert("이메일 중복확인", "사용중인 이메일입니다.");
-            vm.emailDuplicateChecked = false;
-          } else {
-            vm.$showAlert("이메일 중복확인", "사용할 수 있는 이메일입니다.");
-            vm.emailDuplicateChecked = true;
-          }
-        })
-        .catch((error) => {
-          this.$showAlert(
-            "에러 발생",
-            "에러가 발생했습니다. 관리자에게 문의해 주세요."
-          );
-        });
-    },
-
-    //이메일 유효성 검사
-    mailValidation: function () {
-      const vm = this;
-      //1.null검사
-      if (!vm.memberData.userEmail) {
-        vm.$showAlert("사용자 등록", "이메일을 입력하세요.");
-        document.getElementById("email").focus();
-        return false;
-      }
-      //2.정규식 검사
-      if (!vm.$email(vm.memberData.userEmail)) {
-        vm.$showAlert("사용자 등록", "이메일 형식이 올바르지 않습니다.");
-        document.getElementById("email").focus();
-        return false;
-      }
-
-      return true;
-    },
-
-
-    // 권한 변경 시 부서 선택
-    changeAuthor() {
-      const vm = this;
-
-      this.deptSearch.searchObjectList[0].key = 'role_chk';
-      if (vm.memberData.author == 'ROLE_ADMIN') {
-        this.deptSearch.searchObjectList[0].value = 1;
-      } else {
-        this.deptSearch.searchObjectList[0].value = 0;
-      }
-
-      axios({
-        url: "/department/departments",
-        method: "post",
-        data: vm.deptSearch,
-      })
-        .then(function (response) {
-          vm.departmentList = response.data.resultData.selectDeptList;
-          vm.memberData.deptNm = vm.departmentList[0].dept_nm;
-          vm.memberData.dept_code = vm.departmentList[0].dept_code;
-        })
-        .catch(function (error) {
-          vm.$showAlert(
-            "부서 조회",
-            "목록 불러오기 오류, 관리자에게 문의바랍니다."
-          );
-        });
-    }
-  },
-  watch: {
-    //아이디 값 변경 시 중복체크여부 false로 변경
-    "memberData.userId": function (newVal, oldVal) {
-      this.isDuplicateChecked = false;
-    },
-    //이메일 값 변경 시 중복체크여부 false로 변경
-    "memberData.userEmail": function (newVal, oldVal) {
-      this.emailDuplicateChecked = false;
-    },
-  },
-  components: {
-    PageNavigation: PageNavigation,
-    PaginationButton: PaginationButton,
-    SvgIcon: SvgIcon,
-  },
-  mounted() {
-    this.fetchMemberList();
-    this.deptSearchInit();
-    this.getAuthorList();
-    this.searchInit();
-    this.userId = store.state.loginUser.user_id;
-    this.authList = store.state.loginUser.user_auth;
-    this.author = store.state.loginUser.user_auth[0];
-    this.dept_code = store.state.loginUser.dept_code;
-  },
-};
-</script>(파일 끝에 줄바꿈 문자 없음)
package-lock.json
--- package-lock.json
+++ package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "Taken-BI-Manager",
+  "name": "Taken_BI_Manager_renewal",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
Add a comment
List