Index: vue/src/assets/images/devops/DevSupport/github.png
===================================================================
diff -u -r85d9a4380809352c2b0a2a99085e7eafd684c4b3 -r5a34cf7075d157859697e867740930437194775f
--- vue/src/assets/images/devops/DevSupport/github.png	(.../github.png)	(revision 85d9a4380809352c2b0a2a99085e7eafd684c4b3)
+++ vue/src/assets/images/devops/DevSupport/github.png	(.../github.png)	(revision 5a34cf7075d157859697e867740930437194775f)
@@ -1595,6 +1595,56 @@
 	border-right: 2px solid #515256;
 }
 
+#reqDataTable .reqTable {
+	cursor: default;
+}
+
+#reqDataTable .reqTable th.version,
+#reqDataTable .reqTable th.category,
+#reqDataTable .reqTable th.id,
+#reqDataTable .reqTable th.status,
+#reqDataTable .reqTable th.priority,
+#reqDataTable .reqTable th.difficulty,
+#reqDataTable .reqTable th.createDate,
+#reqDataTable .reqTable th.startDate,
+#reqDataTable .reqTable th.endDate,
+#reqDataTable .reqTable th.progress {
+	cursor: pointer;
+}
+
+#reqDataTable .reqTable td.content {
+	cursor: text;
+}
+
+#reqDataTable .reqTable th.version:after,
+#reqDataTable .reqTable th.category:after,
+#reqDataTable .reqTable th.id:after,
+#reqDataTable .reqTable th.status:after,
+#reqDataTable .reqTable th.priority:after,
+#reqDataTable .reqTable th.difficulty:after,
+#reqDataTable .reqTable th.createDate:after,
+#reqDataTable .reqTable th.startDate:after,
+#reqDataTable .reqTable th.endDate:after,
+#reqDataTable .reqTable th.progress:after {
+	content: "";
+	display: inline-block;
+	width: 19px;
+	height: 19px;
+	margin-left: 10px;
+	vertical-align: middle;
+	background-repeat: no-repeat;
+	background-position: center;
+	background-image: url(../img/datatable/sort_both.png);
+}
+
+#reqDataTable .reqTable th.asc:after {
+	background-image: url(../img/datatable/sort_asc.png);
+}
+
+#reqDataTable .reqTable th.desc:after {
+	background-image: url(../img/datatable/sort_desc.png);
+}
+
 /* cost 분석 */
 
 /* 비용 입력 */
@@ -1603,7 +1653,8 @@
 	/*padding-left: 20px;*/
 }
 
-.cost-version, .cost-input-complete {
+.cost-version,
+.cost-input-complete {
 	margin-right: 10px;
 	padding: 3px 7px;
 	font-size: 11px;
@@ -1621,16 +1672,18 @@
 	margin: 0;
 }
 
-.cost-version:hover, .cost-input-complete:hover {
-	background-color: #39393b
+.cost-version:hover,
+.cost-input-complete:hover {
+	background-color: #39393b;
 }
 
-.cost-input-version, .cost-input-manpower {
+.cost-input-version,
+.cost-input-manpower {
 	margin-bottom: 20px;
 	border-radius: 3px;
 	padding: 5px;
 	margin-bottom: 30px;
-	background: rgba(51,51,51,.425);
+	background: rgba(51, 51, 51, 0.425);
 	color: #f8f8f8;
 }
 
@@ -1646,7 +1699,8 @@
 	padding-top: 10px;
 }
 
-.cost-input, .salary-input {
+.cost-input,
+.salary-input {
 	color: black;
 	width: 30%;
 	text-align: center;
@@ -1660,10 +1714,11 @@
 	width: 70%;
 }
 
-select[name="version-cost_length"], select[name="manpower-annual-income_length"] {
+select[name="version-cost_length"],
+select[name="manpower-annual-income_length"] {
 	color: black;
 }
 
 .dt-center {
 	text-align: center;
-}
\ No newline at end of file
+}
Index: arms/img/datatable/sort_asc.png
===================================================================
diff -u
Binary files differ
Index: arms/img/datatable/sort_both.png
===================================================================
diff -u
Binary files differ
Index: arms/img/datatable/sort_desc.png
===================================================================
diff -u
Binary files differ
Index: arms/js/reqAdd.js
===================================================================
diff -u -r52fe9bd98378c944f9d6eb334283306b5a36439d -r5a34cf7075d157859697e867740930437194775f
--- arms/js/reqAdd.js	(.../reqAdd.js)	(revision 52fe9bd98378c944f9d6eb334283306b5a36439d)
+++ arms/js/reqAdd.js	(.../reqAdd.js)	(revision 5a34cf7075d157859697e867740930437194775f)
@@ -58,8 +58,7 @@
 			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/pdfmake.min.js"
 		],
 		// 추가적인 플러그인 그룹들을 이곳에 추가하면 됩니다.
-		["js/reqAddTable.js",
-		 "css/jiraServerCustom.css"]
+		["js/reqAddTable.js", "css/jiraServerCustom.css"]
 	];
 
 	loadPluginGroupsParallelAndSequential(pluginGroups)
@@ -1284,7 +1283,7 @@
 
 	//예상 일정 초기화
 	$("#my_modal1 #req_plan_time").val(null);
-	
+
 	//리뷰어 셋팅
 	$.ajax({
 		url: "/auth-user/api/arms/pdService/getNodeWithVersionOrderByCidDesc.do?c_id=" + $("#selected_pdService").val(),
@@ -1437,9 +1436,7 @@
 		console.log(
 			"save_req :: popup_req_state  -> " + $("#popup_req_state input[name='popup_req_state_options']:checked").val()
 		);
-		console.log(
-			"save_req :: popup_req_plan_time  -> " + $("#popup_req_plan_time").val()
-		);
+		console.log("save_req :: popup_req_plan_time  -> " + $("#popup_req_plan_time").val());
 		let selectedReqPriorityLink = $("#popup_req_priority input[name='popup_req_priority_options']:checked").val();
 		let selectedReqDifficultLink = $("#popup_req_difficulty input[name='popup_req_difficulty_options']:checked").val();
 		let selectedReqStateLink = $("#popup_req_state input[name='popup_req_state_options']:checked").val();
@@ -1537,13 +1534,14 @@
 			"click_btn_for_req_update :: editview_req_state  -> " +
 				$("#editview_req_state input[name='editview_req_state_options']:checked").val()
 		);
-		console.log(
-			"click_btn_for_req_update :: editview_req_plan_time  -> " +
-				$("#editview_req_plan_time").val()
-		);
+		console.log("click_btn_for_req_update :: editview_req_plan_time  -> " + $("#editview_req_plan_time").val());
 
-		let selectedEditReqPriorityLink = $("#editview_req_priority input[name='editview_req_priority_options']:checked").val();
-		let selectedEditReqDifficultyLink = $("#editview_req_difficulty input[name='editview_req_difficulty_options']:checked").val();
+		let selectedEditReqPriorityLink = $(
+			"#editview_req_priority input[name='editview_req_priority_options']:checked"
+		).val();
+		let selectedEditReqDifficultyLink = $(
+			"#editview_req_difficulty input[name='editview_req_difficulty_options']:checked"
+		).val();
 		let selectedEditReqStateLink = $("#editview_req_state input[name='editview_req_state_options']:checked").val();
 		let selectedEditReqPlanTime = $("#editview_req_plan_time").val();
 
@@ -1579,7 +1577,6 @@
 				}
 			}
 		});
-
 	});
 }
 
@@ -1905,7 +1902,8 @@
 }
 
 function tableSelect(id) {
-	makeTable("reqDataTable", {
+	makeTable({
+		wrapper: "reqDataTable",
 		id,
 		onGetData: async function (id) {
 			return await $.ajax({
Index: arms/js/reqAddTable.js
===================================================================
diff -u -r83ad418edefb4880f535790d3f2de5260cc72655 -r5a34cf7075d157859697e867740930437194775f
--- arms/js/reqAddTable.js	(.../reqAddTable.js)	(revision 83ad418edefb4880f535790d3f2de5260cc72655)
+++ arms/js/reqAddTable.js	(.../reqAddTable.js)	(revision 5a34cf7075d157859697e867740930437194775f)
@@ -31,12 +31,54 @@
 		return document.createElement(name);
 	}
 
+	sortData(key, type) {
+		if (["id", "progress"].includes(key)) {
+			type === "asc" && this.$data.sort((a, b) => a[key] - b[key]);
+			type === "desc" && this.$data.sort((a, b) => b[key] - a[key]);
+		} else if (["createDate", "startDate", "endDate"].includes(key)) {
+			type === "asc" && this.$data.sort((a, b) => (a[key] ? (b[key] ? new Date(a[key]) - new Date(b[key]) : -1) : 1));
+			type === "desc" && this.$data.sort((a, b) => (a[key] ? (b[key] ? new Date(b[key]) - new Date(a[key]) : -1) : 1));
+		} else {
+			type === "asc" &&
+				this.$data.sort((a, b) => (a[`_${key}`] ? (b[`_${key}`] ? a[`_${key}`] - b[`_${key}`] : -1) : 1));
+			type === "desc" &&
+				this.$data.sort((a, b) => (a[`_${key}`] ? (b[`_${key}`] ? b[`_${key}`] - a[`_${key}`] : -1) : 1));
+		}
+
+		const $tbody = document.getElementById("req_tbody");
+		$tbody.replaceChildren();
+		this.makeRow(this.$data, "td").forEach((r) => $tbody.append(r));
+	}
+
+	handleSorting(e, key) {
+		[...e.target.parentNode.childNodes]
+			.filter((node) => !node.classList.contains(key))
+			.forEach((node) => {
+				node.classList.remove("asc");
+				node.classList.remove("desc");
+			});
+
+		if (e.target.classList.contains("asc")) {
+			e.target.classList.remove("asc");
+			e.target.classList.add("desc");
+
+			this.sortData(key, "desc");
+		} else {
+			e.target.classList.remove("desc");
+			e.target.classList.add("asc");
+
+			this.sortData(key, "asc");
+		}
+	}
+
 	makeRow(rows, tag) {
 		return rows.reduce((acc, cur) => {
 			const $tr = this.makeElement("tr");
 			$tr.setAttribute("data-id", cur.id);
 
 			Object.keys(this.options.content).forEach((key) => {
+				if ([`_${key}`].includes(key)) return;
+
 				const $col = this.makeElement(tag);
 				$col.className = key;
 
@@ -57,19 +99,7 @@
 			return [...acc, $tr];
 		}, []);
 	}
-	makeHead() {
-		const $thead = this.makeElement("thead");
-		this.makeRow([this.options.content], "th").forEach((r) => $thead.append(r));
 
-		return $thead;
-	}
-	makeBody() {
-		const $tbody = this.makeElement("tbody");
-		this.makeRow(this.$data, "td").forEach((r) => $tbody.append(r));
-
-		return $tbody;
-	}
-
 	getOriginData(id) {
 		return origin;
 	}
@@ -91,29 +121,26 @@
 				c_req_reviewer05
 			}
 		} = this.$data.find((item) => item.id === Number(id));
+		const params = {
+			c_id,
+			c_title,
+			c_req_pdservice_versionset_link,
+			c_req_priority_link: reqPriorityEntity?.c_id ?? null, // 5 - 중간
+			c_req_difficulty_link: reqDifficultyEntity?.c_id ?? null, // 5 - 보통
+			c_req_state_link: reqStateEntity?.c_id ?? null, //10 - 열림
+			c_req_update_date: new Date(),
+			c_req_reviewer01,
+			c_req_reviewer02,
+			c_req_reviewer03,
+			c_req_reviewer04,
+			c_req_reviewer05,
+			c_req_status: "ChangeReq",
+			c_req_contents
+		};
 
-		this.options.onUpdate(
-			this.options.id,
-			Object.assign(
-				{
-					c_id,
-					c_title,
-					c_req_pdservice_versionset_link,
-					c_req_priority_link: reqPriorityEntity?.c_id ?? null, // 5 - 중간
-					c_req_difficulty_link: reqDifficultyEntity?.c_id ?? null, // 5 - 보통
-					c_req_state_link: reqStateEntity?.c_id ?? null, //10 - 열림
-					c_req_update_date: new Date(),
-					c_req_reviewer01,
-					c_req_reviewer02,
-					c_req_reviewer03,
-					c_req_reviewer04,
-					c_req_reviewer05,
-					c_req_status: "ChangeReq",
-					c_req_contents
-				},
-				obj
-			)
-		);
+		if (Object.keys(obj).every((k) => obj[k] === params[k])) return;
+
+		this.options.onUpdate(this.options.id, Object.assign(params, obj));
 	}
 
 	addInput(node) {
@@ -180,11 +207,14 @@
 		node.parentElement.appendChild($ul);
 	}
 
-	makeSection(rowData, name, col) {
-		const $el = this.makeElement(name);
-		$el.className = name;
-		this.makeRow(rowData, col).forEach((r) => $el.append(r));
+	bindHeadEvent($el) {
+		$el.addEventListener("click", (e) => {
+			!["manager", "depth1", "depth2", "depth3", "content"].includes(e.target.className) &&
+				this.handleSorting(e, e.target.classList.item(0));
+		});
+	}
 
+	bindBodyEvent($el) {
 		$el.addEventListener("click", (e) => {
 			const { tagName, classList, parentElement } = e.target;
 			// input
@@ -198,20 +228,36 @@
 				tagName === "I" && this.addSelect(parentElement);
 			}
 		});
+	}
 
+	makeSection(rowData, name, col) {
+		const $el = this.makeElement(name);
+		$el.id = `req_${name}`;
+		$el.className = name;
+		this.makeRow(rowData, col).forEach((r) => $el.append(r));
+
+		if ("thead" === name) this.bindHeadEvent($el);
+		else this.bindBodyEvent($el);
+
 		return $el;
 	}
 
-	get template() {
+	makeTable() {
 		this.$table.className = "reqTable";
 		this.$table.appendChild(this.makeSection([this.options.content], "thead", "th"));
 		this.$table.appendChild(this.makeSection(this.$data, "tbody", "td"));
 		return this.$table;
 	}
+
+	rendering() {
+		const $wrapper = document.getElementById(this.options.wrapper);
+		$wrapper.innerHTML = "";
+		$wrapper.appendChild(this.makeTable());
+	}
 }
 
 const getDate = (stamp) => {
-	if (!stamp || stamp < 0) return "-";
+	if (!stamp || stamp < 0) return "";
 	const time = new Date(stamp);
 	return `${time.getFullYear()}-${addZero(time.getMonth() + 1)}-${addZero(time.getDate())}`;
 };
@@ -275,7 +321,10 @@
 					startDate: getDate(c_req_start_date),
 					endDate: getDate(c_req_end_date),
 					progress: c_req_plan_progress || 0,
-					origin: cur
+					origin: cur,
+					_status: reqStateEntity?.c_id,
+					_priority: reqPriorityEntity?.c_id,
+					_difficulty: reqDifficultyEntity?.c_id
 				}
 			];
 		}, []);
@@ -297,10 +346,13 @@
 // 	});
 // };
 
-const makeTable = async (wrapper, options) => {
+const makeTable = async (options) => {
 	const res = await options.onGetData(options.id);
-	const $wrapper = document.getElementById(wrapper);
+	// const $wrapper = document.getElementById(wrapper);
 	const table = new Table(options, setTableData(res));
 
-	$wrapper.appendChild(table.template);
+	table.rendering();
+
+	// $wrapper.innerHTML = "";
+	// $wrapper.appendChild(table.template);
 };