hehih 2024-09-19
문자전송 > 엑셀 불러오기 || 주소록 > 엑셀 불러오기 -> 오류수정 번호 빈값 안나오게 처리
@4f5a47756190cd6ac5c7e9f2226239c08aca6200
src/main/webapp/WEB-INF/jsp/web/addr/AddrList.jsp
--- src/main/webapp/WEB-INF/jsp/web/addr/AddrList.jsp
+++ src/main/webapp/WEB-INF/jsp/web/addr/AddrList.jsp
@@ -1,869 +1,868 @@
-<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-
-<script type="text/javascript">
-	var currentTime = new Date().getTime(); // 현재 시간을 밀리초로 가져옵니다.
-</script>
-
-<script type="text/javascript" src="<c:url value='/publish/js/content.js'/>"></script>
-<script type="text/javascript" src="https://oss.sheetjs.com/sheetjs/xlsx.full.min.js"></script>
-<script type="text/javascript" src="<c:url value='/js/web/addr/init.js'/>?v="+currentTime></script>
-<script type="text/javascript" src="<c:url value='/js/web/addr/event.js'/>?v="+currentTime></script>
-<script type="text/javascript" src="<c:url value='/js/web/addr/utils.js'/>?v="+currentTime></script>
-<script type="text/javascript" src="<c:url value='/js/web/addr/cmn.js?date=202409021440'/>"></script>
-
-
-<script type="text/javascript">
-
-$(document).ready(function(){
-	listAddrGrp();
-	addrLoadAjax();
-
-	// 엑셀 중복번호 버튼
-	$("#tableExcelDupliBtn").hide();
-// 	$("#btnAddrMassSaveDupli").hide();
-	// 주소록 대량등록
-// 	addrMassTab(1);	
-	
-	// 중복 휴대폰번호 버튼 노출여부
-	
-	
-	// excel 오류정보 테스트
-	$('#errorExcelBtn').click(function(){
-		if($tableError.getDataCount()<1){
-			alert('오류 정보가 없습니다.');
-			return false;
-		}
-		$tableError.download("xlsx", "error_data.xlsx");
-	});
-}); 
-
-// 메인 화면 좌측메뉴 최신화
-function listAddrGrp(){
-	var sendData = $(document.searchAddrGrpForm).serializeArray() ;
-	$("#adr1_left").load("/web/addr/selectAddrGroupListAjax.do", sendData ,function(response, status, xhr){});
-}
-
-
-function addrGroupLoadAjax(){
-	$("#addrRegistSelect").load("/web/addr/selectAddrGroupAjax.do", function(response, status, xhr){});
-	$("#funcAddrGroupSelect").load("/web/addr/selectAddrGroupAjax.do", function(response, status, xhr){});
-}
-
-function addrLoadAjax(){
-	$("#adr1_right").load("/web/mjon/addr/selectAddrAjax.do",  function(response, status, xhr){tableAllChk();});
-	addrGroupLoadAjax();
-}
-
-function insertAddrGroupAjax() {
-	var form = document.addrGrpInsertForm;
-	if(form.addrGrpNm.value == "") {
-		alert("주소록 그룹명을 입력해주세요.");
-		return;
-	}
-	if(!confirm("주소록 그룹을 추가하시겠습니까?")) {
-		return;
-	}
-	var data = new FormData(form);
-	
-	$.ajax({
-		cache : false,
-		url : "<c:url value='/web/addr/insertAddrGroupAjax.do' />", 
-		type : 'POST', 
-		data : data,
-		dataType:'json',
-		processData: false,
-		contentType: false,
-		success : function(returnData, status){
-			if(status == "success") {
-				if("fail"==returnData.result){
-					alert(returnData.message);
-					return;
-				} else if("dupl"==returnData.result) {
-					alert("중복된 그룹명입니다.");
-					return;
-				}
-				alert("등록되었습니다.");
-				listAddrGrp();
-				addrGroupLoadAjax();
-				
-			}else{ alert("ERROR!");return;} 
-		},
-		error: function (e) { alert("저장에 실패하였습니다."); console.log("ERROR : ", e); }
-	});
-	
-}
-
-
-// 주소록그룹 콤보박스 유지
-function setSelectSetting(selectVal) {
-	$("#addrRegistSelect").val(selectVal).prop("selected", true);	
-}
-	
-function linkPage(pageNo){
-	if ($('#searchKeywordAddr').val() != "" && $('#searchKeywordAddr').val() != null && $('#searchKeywordAddr').val() != undefined) {
-		// 문자전송 검색용
-		$("#msgStartKeyword").val("");
-	}
-
-	var searchForm = document.searchAddrForm;
-	searchForm.pageIndex.value = pageNo;
-	searchForm.pageUnit.value = $('#pageUnit').val();
-	searchForm.searchCondition.value = $('#searchConditionAddr').val();
-	searchForm.searchKeyword.value = $('#searchKeywordAddr').val();
-	searchForm.startKeyword.value = $("#msgStartKeyword").val();
-	
-	var sendData = $(document.searchAddrForm).serializeArray();
-	$("#adr1_right").load("/web/mjon/addr/selectAddrAjax.do", sendData, function(response, status, xhr){tableAllChk();});
-	addrGroupLoadAjax();
-}
-
-function moveTab(type){
-	if(type == "addr") 			location.href="/web/mjon/addr/selectAddrList.do";
-	if(type == "fax") 			location.href="/web/mjon/fax/addr/selectFaxAddrList.do";
-	if(type == "block") 		location.href="/web/mjon/addrBlock/selectBlockList.do";
-	if(type == "addrMob") 		location.href="/web/mjon/addr/addrMobGuide.do";
-	if(type == "addrApply") 	location.href="/web/mjon/addragency/selectAddrAgencyList.do";
-}
-
-
-
-//#############################################################################################
-//Tabulator
-//#############################################################################################
-
-$(document).ready(function(){
-	
-
-
-	
-	// 오류검사 항목 중복제거
-	function SetTableErrorDupliCheck(sVal) {
-		var isDuplicate = false;
-		if (tableErrorCheckData.length == 0) {
-			tableErrorCheckData.push(sVal);
-		}
-		else {
-			for (var i = 0; i < tableErrorCheckData.length; i++)
-			{
-				if (tableErrorCheckData[i] == sVal) {
-					isDuplicate = true;
-				}
-			}
-			
-			if (isDuplicate) {
-				return;
-			}
-			else {
-				tableErrorCheckData.push(sVal);
-			}
-		}
-	}	
-	
-	
-	// 오류검사 항목 중복제거
-	function SetTableErrorDupliCheck(sVal) {
-		var isDuplicate = false;
-		if (tableErrorCheckData.length == 0) {
-			tableErrorCheckData.push(sVal);
-		}
-		else {
-			for (var i = 0; i < tableErrorCheckData.length; i++)
-			{
-				if (tableErrorCheckData[i] == sVal) {
-					isDuplicate = true;
-				}
-			}
-			
-			if (isDuplicate) {
-				return;
-			}
-			else {
-				tableErrorCheckData.push(sVal);
-			}
-		}
-	}	
-	
-	
-
-	
-});
-
-
-
-//#############################################################################################
-//등록
-//#############################################################################################
-
-//등록
-$(document).on('click', '#btnAddrMassReg', function() {
-	// 저장
-	SetAddrMassSave();
-});
-
-$(document).on('click', '#btnAddrMassClose', function() {
-	// 대량등록 닫기
-	setAddrMassClose();
-});
-
-// 대량등록 닫기
-function setAddrMassClose() {
-	var $objTabul = fn_utils_getTabulator();
-	$objTabul.clearData();
-	
-	fn_rowDataClear();
-	
-	
-	$("#rowTotCnt").text(0); //총건수 수정
-	$("#rowDupCnt").text(0); //중복건수 수정
-	$("#rowErrorCnt").text(0); //중복건수 수정
-	
-	
-	
-	dupliPhoneDataRealList.length = 0;	// 중복 휴대폰번호 초기화
-	addrMassDupliSaveList = null;
-
-	$("#btnAddrMassDupli").hide();
-	$("#btnAddrMassSaveDupli").hide();
-	
-	//location.reload();
-	listAddrGrp();
-	addrGroupLoadAjax();
-	addrLoadAjax();		
-	fn_errorPopClean(); // 에러 팝업 초기화
-}
-
-// 주소록 탭마다 돌면서 총, 중복, 오류 건수 초기화
-function fn_rowDataClear(){
-
-	// 모든 .tab 요소를 선택하여 반복
-	$('#tbTabl .tab').each(function() {
-	    // 현재 반복 중인 요소
-	    var tab = $(this);
-
-	    // data-tabul 값 가져오기
-	    var tabulNm = tab.data('tabul');
-		var tabluC = '.'+tabulNm
-
-	    // 중복 카운트
-	    $(tabluC+" #rowTotCnt").text(0);
-	    // 에러 카운트
-	    $(tabluC+" #rowDupCnt").text(0);
-	    // 
-	    $(tabluC+" #rowErrorCnt").text(0);
-		
-		
-	});
-}
-
-
-
-// 주소록 그룹 중복체크
-function getAddrGroupDuplCheckAjax(addrGrpNm) {
-	var isReturn = true;
-	
-	$.ajax({
-		url : "<c:url value='/web/addr/getAddrGroupDuplCheckAjax.do' />", 
-		type : 'POST', 
-		data : {"addrGrpNm" : addrGrpNm},
-		dataType:'json',
-		async: false,			// 동기
-		success : function(data, status){
-			if(data.isSuccess == true) {
-				if(data.isDupl == true) {
-					//alert("중복된 그룹명입니다.");
-					isReturn = false;
-				}
-			} 
-			else {
-				//alert("Message : " + msg);
-			}			
-		},
-		error: function (e) {
-			//alert("주소록 중복체크에 실패했습니다.");
-		}
-	});
-	console.log('isReturn : ', isReturn);
-	
-	return isReturn;	
-}
-
-
-//저장
-function SetAddrMassSave(){
-
-
-	
-	
-	
-	
-	
-	
-	
-	var $objTabul = fn_utils_getTabulator();
-	var tabulNm = fn_utils_getTabulatorNm();
-	var tabluC = '.'+tabulNm
-
-	/* console.log('$objTabul : ', $objTabul.getData());
-	if(tabulNm  == 'tableSelf'){
-		console.log('????');
-		
-		var allRows = $objTabul.getData(); // 테이블의 모든 데이터를 가져옴
-
-		// addrPhoneNo 값이 있는 행만 필터링
-		var rowsWithPhoneNumbers = allRows.filter(function(row) {
-			return row.addrPhoneNo && row.addrPhoneNo.trim() !== ''; // 값이 존재하고 공백이 아닌 경우
-		});
-		$objTabul = rowsWithPhoneNumbers;
-		console.log('rowsWithPhoneNumbers : ', rowsWithPhoneNumbers);
-		console.log('$objTabul : ', $objTabul.getData());
-		return false;
-	} */
-	
-	if($objTabul.getData().length < 1){
-		alert("한 개 이상의 연락처를 입력하세요");
-		return false;
-	}
-	
-	if($objTabul.getData().length > 300000){
-		alert("30만개 까지 등록 가능합니다.");
-		return false;
-	}
-	
-// 	var selectMassVal = $(tabluC+" #addrGrpIdInfo option:selected").val();
-	
-	var loginVO = '${LoginVO}';
-	if(fn_utils_isEmpty(loginVO)){
-		alert("로그인 후 이용이 가능합니다.");
-		return false;
-	}
-	
-	// tableExcel select 요소들을 확인
-	var columns = $objTabul.getColumns();
-	var isAddrPhoneNoSelected = columns.some(column => column.getField() === 'addrPhoneNo');
-	if (!isAddrPhoneNoSelected) {
-//		    isPhoneSelected = true;
-		alert('휴대폰이 선택되지 않았습니다.');
-		return false;
-
-	} 
-	
-	// 주소록이 새로생성이면 새로운 주소록명이 있는지 확인
-	if ($(tabluC+" #addrGrpIdInfo option:selected").val() == "NEW" 
-				&& ($(tabluC+" #addrGrpNm").val() == "" 
-						|| $(tabluC+" #addrGrpNm").val() == null 
-						|| $(tabluC+" #addrGrpNm").val() == undefined)
-						) 
-	{
-		alert("저장할 그룹을 선택하거나 새 그룹명을 입력해주세요.");
-		$(tabluC+" #addrGrpNm").focus();
-		return false;		
-	}
-	
-	// 새 그룹명 중복체크
-	if ($(tabluC+" #addrGrpIdInfo option:selected").val() == "NEW" 
-			&& $(tabluC+" #addrGrpNm").val() != "") 
-	{
-		var addrGrpNm = $(tabluC+" #addrGrpNm").val();
-		console.log('addrGrpNm : ', addrGrpNm);
-		//주소록 중복체크
-		if (getAddrGroupDuplCheckAjax(addrGrpNm) == false) {
-			alert("중복된 그룹명입니다. 새 그룹명을 입력해주세요.");
-			return false;			
-		}
-	}	
-	
-	var confirmMsg = "저장하시겠습니까?\n이름 200byte, [*1*]~[*4*] 200byte, 메모 250byte 초과 글자는 절사됩니다.";
-	if (confirm(confirmMsg)) {	
-		//로딩창 show
-		fn_loadAddActive();				
-
-		setTimeout(setSenderList_advc, 1000);
-// 		setTimeout(setSenderList_old, 1000);
-
-	}
-}
-/* 
-// 주소록 등록 old
-function setSenderList_old(){
-
-	// tab에 해당하는 타블레이터 가져오기
-
-	var tabulNm = fn_utils_getTabulatorNm();
-	var tabluC = '.'+tabulNm
-	  
-    var $objTabul = fn_utils_getTabulator();
-    var dataToSend = $objTabul.getData();
-    var addrGrpIdInfo = $(tabluC+" #addrGrpIdInfo option:selected").val();
-    var addrGrpNmInfo = $(tabluC+" #addrGrpNm").val();
-
-	var updateData = dataToSend.map(row => {
-	    row.addrGrpId = addrGrpIdInfo;
-	    row.addrGrpNm = addrGrpNmInfo;
-	    return row;
-	});
-	
-	console.log('updateData : ', updateData);
-	$.ajax({
-	    type: "POST",
-	    url: "/web/mjon/addr/addrMassInsertByTempAjax_advc.do",
-	    data: JSON.stringify(updateData),
-	    dataType: 'json',
-	    contentType: 'application/json',
-	    async: true,
-	    success: function (data) {
-	    	console.log('data : ', data);
-	    	
-
-			if (data.status == 'OK') {  
-				alert(data.message);
-				// 데이터 비우기
-				SetClear($objTabul);		
-				setAddrMassClose();
-				var selectMassVal = $("#addrGrpIdInfo option:selected").val();
-			} 
-			else {
-				alert("오류 알림 :  :: "+data.message);
-			}
-		},
-		error: function (e) { 
-			alert("저장에 실패하였습니다."); 
-			alert("ERROR : " + JSON.stringify(e)); 
-		},
-		beforeSend : function(xmlHttpRequest) {
-			//로딩창 show
-			$('.loading_layer').addClass('active');				
-		},	        	        
-		complete : function(xhr, textStatus) {
-			//로딩창 hide
-			$('.loading_layer').removeClass('active');
-		}
-	});
-}
- */
-
-function setSenderList_advc(){
-
-	var tabulNm = fn_utils_getTabulatorNm();
-	var tabluC = '.'+tabulNm
-	  
-    var $objTabul = fn_utils_getTabulator();
-    var dataToSend = $objTabul.getData();
-    console.log('dataToSend : ', dataToSend);
-    var addrGrpIdInfo = $(tabluC+" #addrGrpIdInfo option:selected").val();
-    var addrGrpNmInfo = $(tabluC+" #addrGrpNm").val();
-
-    var batchSize = 30000; // 배치 크기
-    var totalBatches = Math.ceil(dataToSend.length / batchSize); // 총 배치 수
-    var currentBatch = 0; // 현재 배치 인덱스
-
-
-	fn_loadAddActive();
-
-    function sendBatch() {
-        if (currentBatch < totalBatches) {
-        	fn_loadAddActive();
-            var start = currentBatch * batchSize;
-            var end = Math.min(start + batchSize, dataToSend.length);
-            var batchData = dataToSend.slice(start, end);
-
-            var updateData = batchData.map(row => {
-                row.addrGrpId = addrGrpIdInfo;
-                row.addrGrpNm = addrGrpNmInfo;
-                return row;
-            });
-            
-            $.ajax({
-                type: "POST",
-                url: "/web/mjon/addr/addrMassInsertByTempAjax_advc.do",
-                data: JSON.stringify(updateData),
-                dataType: 'json',
-                contentType: 'application/json',
-                async: true,
-                success: function (data) {
-                	
-
-            		fn_loadRemoveActive();
-                	
-                    console.log('Batch ' + (currentBatch + 1) + ' success: ', data);
-                    if (data.status == 'OK') {
-                        if (currentBatch === totalBatches - 1) {
-                            alert("모든 데이터가 성공적으로 저장되었습니다.");
-                            // 데이터 비우기
-                            SetClear($objTabul);
-                            setAddrMassClose();
-                        } else {
-                            currentBatch++;
-                            // 새로만든 그룹ID나 기존 ID를 넣어줌
-                            // 그룹추가 시 배치별로 똑같은 그룹을 생성해서 방지차원으로 넣어줌 
-                            addrGrpIdInfo = data.object;
-                            sendBatch(); // 다음 배치 전송
-                        }
-                    } else {
-                        alert("오류 알림 : " + data.message);
-                    }
-                },
-                error: function (e) {
-                    alert("배치 전송에 실패하였습니다."); 
-                    console.error("ERROR: ", JSON.stringify(e));
-                },
-                beforeSend: function(xmlHttpRequest) {
-                },
-                complete: function(xhr, textStatus) {
-                    if (currentBatch === totalBatches - 1) {
-                    	$('#lodingTxt').text('Loading');
-                    } else {
-                    	$('#lodingTxt').text(end+'...');
-                    }
-                }
-            });
-        }
-    }
-    // 첫 번째 배치 전송 시작
-    sendBatch();
-}
-
-
- 
-//주소록그룹 콤보박스 유지
-function setSelectMassSetting(selectMassVal) {
-	$("#addrGrpIdInfo").val(selectMassVal).prop("selected", true);	
-}
-
-
-//데이터 비우기
-function SetClear($objTabul) {
-	
-
-	var tabulNm = fn_utils_getTabulatorNm();
-	var tabluC = '.'+tabulNm
-	
-	$(tabluC+" #addrGrpNm").val(""); //	새그룹명 Clear;
-	// 주소록 그룹정보 불러오기
-	getAddrGroupList();	
-
-
-
-	if (tabulNm === 'tableSelf') {
-		var tableData = [];
-		for (var i = 0; i < 1000; i++) {
-			tableData.push({addrNm: "", addrPhoneNo: "", addrInfo1: "", addrInfo2: "", addrInfo3: "", addrInfo4: "", addrComment: ""});
-		}
-		console.log(tableData); // 데이터 출력 확인
-		fn_selfmakeTable()
-	}else{
-	 	$objTabul.clearData(); // clearData는 동기 방식이므로 바로 실행
-		
-	}
-// 	console.log('tabulNm : ', tabulNm);
-// 	console.log('tabulNm : ', tabulNm.trim());
-
-	
-	$(tabluC+" #rowTotCnt").text(0); //총건수 수정
-	$(tabluC+" #rowDupCnt").text(0); //중복건수 수정
-
-	// popup 영역
-	fn_errorPopClean();
-}
-
-// 주소 대량등록 버튼 클릭 
-// AddrListAjax.jsp에서 호출
-$(document).on('click', '#btnAddrMassRegCall', function() {
-	getAddrGroupList();
-});
-
-
-// 주소록 그룹정보 불러오기
-function getAddrGroupList() {
-	$.ajax({
-		type : "POST",
-		async : false,
-		url : "/web/mjon/addr/addrGroupListAjax.do",
-		data : {},
-		dataType:'json',
-		success : function(data) {
-			//alert(JSON.stringify(data.addrGroupList));
-
-			// Show Html
-			getAddrGroupListShow(data.addrGroupList);
-		},
-		error : function(xhr, status, error) {
-			alert(error);
-			return false;
-		}
-	});	    	
-}
-
-
-
-	
-// 그룹데이터 노출
-function getAddrGroupListShow(jsonList) {
-	var sHtml = "";
-	sHtml += "<option value='NEW'>그룹추가</option>";
-	sHtml += "<option value='0'>그룹미지정</option>";
-	sHtml += "<option value='bookmark'>자주보내는 번호</option>";
-	for (var j = 0; j < jsonList.length; j++) {
-		sHtml += "	<option value='" + $.trim(jsonList[j].addrGrpId) + "' />" + $.trim(jsonList[j].addrGrpNm) + "</option>";
-	}
-
-	var tabulNm = fn_utils_getTabulatorNm();
-	var tabluC = '.'+tabulNm
-	$(tabluC+" #addrGrpIdInfo").html(sHtml);
-}
-
-$(document).on('change', '#addrGrpIdInfo', function() {
-	if ($("#addrGrpIdInfo option:selected").val() != "NEW") {
-		$("#addrGrpNm").val(""); //	새그룹명 Clear;
-	}
-});
-
-//#############################################################################################
-//파일 불러오기
-//#############################################################################################
-
-//체크박스 전체선택/해제
-$(document).on("click", "#chkAll", function(e) {
-	var isChecked = $(this).is(":checked");
-	$("input[name=addrCheck]:checkbox").prop("checked", isChecked);
-});
-
-$(document).on("click", "#duplicationChkAll", function(e) {
-	var isChecked = $(this).is(":checked");
-	$("input[name=addrCheck]:checkbox").prop("checked", isChecked);
-});	
-
-//팝업 텍스트 더보기 클릭 시 펼쳐지고 숨겨짐
-function popMore(e){
-	$(e).closest(".pop_more_cont").toggleClass("pop_more_click");
-	
-	if($(e).closest(".pop_more_cont").is(".pop_more_click")){
-		$(e).html('숨기기');
-		$(e).append('<i></i>');
-	}else {
-		$(e).html('더보기');
-		$(e).append('<i></i>');
-	}
-}
-
-/* 윈도우팝업 열기 */
-function infoPop(pageUrl){
-	document.popForm.pageType.value = pageUrl;
-	document.popForm.action = "/web/pop/infoPop.do";
-	document.popForm.method = "post"; 
-	window.open("about:blank", 'infoPop', 'width=790, height=430, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=1');
-	document.popForm.target = "infoPop";
-	document.popForm.submit();
-}
-
-// 중복 연락처
-function GetAddrMassDupli() {
-	var sHtml = "";
-	sHtml += "<div class='' style='overflow-x:auto; height:350px;'>";
-	sHtml += "<table class='tType4'>";
-	sHtml += "		<colgroup>";
-	sHtml += "			<col style='width:auto' />";
-	sHtml += "		</colgroup>";
-	sHtml += "		<thead>";
-	sHtml += "			<tr>";
-	sHtml += "				<th>중복 휴대폰번호 (" + numberWithCommas(dupliPhoneDataRealList.length) + "개)</th>";
-	sHtml += "			</tr>";
-	sHtml += "		</thead>";
-	sHtml += "		<tbody>";
-	for (var i = 0; i < dupliPhoneDataRealList.length; i++) {
-		sHtml += "		<tr>";
-		sHtml += "			<td>" + dupliPhoneDataRealList[i] + "</td>";
-		sHtml += "		</tr>";
-	}
-	sHtml += "		</tbody>";
-	sHtml += "	</table>";
-	sHtml += "	</div>";
-	
-	$("#addrMassDupli_layer").html(sHtml);
-}
-
-//중복 연락처 => 저장시
-function GetAddrMassSaveDupli() {
-	var sHtml = "";
-	sHtml += "<div class='' style='overflow-x:auto; height:350px;'>";
-	sHtml += "<table class='tType4'>";
-	sHtml += "		<colgroup>";
-	sHtml += "			<col style='width:auto' />";
-	sHtml += "		</colgroup>";
-	sHtml += "		<thead>";
-	sHtml += "			<tr>";
-	sHtml += "				<th>중복 휴대폰번호 (" + numberWithCommas(addrMassDupliSaveList.length) + "개)</th>";
-	sHtml += "			</tr>";
-	sHtml += "		</thead>";
-	sHtml += "		<tbody>";
-	for (var i = 0; i < addrMassDupliSaveList.length; i++) {
-		sHtml += "		<tr>";
-		sHtml += "			<td>" + addrMassDupliSaveList[i].addrPhoneNo + "</td>";
-		sHtml += "		</tr>";
-	}
-	sHtml += "		</tbody>";
-	sHtml += "	</table>";
-	sHtml += "	</div>";
-	
-	$("#addrMassSaveDupli_layer").html(sHtml);
-}
-
-
-// function fn_tabToggle('1')
-function fn_tabToggle(tabNum){
-	var tabId = '#tab'+tabNum;
-	$('.tab_c').hide();
-	$(tabId).show();
-	getAddrGroupList();
-}
-
-
-</script>
-
-<div class="loading_layer">
-	<div class="loading_container">
-		<div class="bar"></div>
-		<div class="text" id="lodingTxt">
-		Loading
-		</div>
-	</div>
-</div>
-
-<div id="adrPopup_tab1">
-
-
-<!-- 수신거부 대량등록  data-tooltip:adr_popup01 -->
-	<form id="addrMassForm" name="addrMassForm" method="post">
-		<input type="hidden" id="phoneList" name="phoneList" value=""/>
-		<input type="hidden" id="nameList" name="nameList" value=""/>
-		<input type="hidden" id="info1List" name="info1List" value=""/>
-		<input type="hidden" id="info2List" name="info2List" value=""/>
-		<input type="hidden" id="info3List" name="info3List" value=""/>
-		<input type="hidden" id="info4List" name="info4List" value=""/>
-		<input type="hidden" id="memoList" name="memoList" value=""/>
-		<input type="hidden" id="addrGrpId" name="addrGrpId" value=""/>
-		<div class="tooltip-wrap" id="addrMassLoad">
-			<div class="popup-com adr_layer adr_popup01" tabindex="0" data-tooltip-con="adr_popup01" data-focus="adr_popup01" data-focus-prev="adr_popup01-close" style="width: 1000px;">
-				<div class="popup_heading">
-					<p>주소록 대량등록</p>
-					<button type="button" class="tooltip-close" data-focus="adr_popup01-close" onclick="setAddrMassClose();"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
-			   </div>
-				<div class="layer_in" style="padding: 25px 30px;">
-				   <div class="list_tab_wrap2">
-					   <!-- tab button -->
-					   <ul class="list_tab" id="tbTabl"> 
-						   <li class="tab active" data-tabul="tableExcel"><button type="button" onclick="popupTab(this,'1'); fn_tabToggle('1');">엑셀입력</button></li>
-						   <li class="tab" data-tabul="tableClip"><button type="button" onclick="popupTab(this,'2'); fn_tabToggle('2');">붙여넣기</button></li>
-						   <li class="tab" data-tabul="tableSelf"><button type="button" onclick="popupTab(this,'3'); fn_tabToggle('3');">직접입력</button></li>
-					   </ul><!--// tab button -->
-				   </div>
-					<div id="tab1" class="tab_c tableExcel">
-				  		<%@include file="/WEB-INF/jsp/web/addr/include/addrListforExcel.jsp" %>
-					</div>
-					<div id="tab2" class="tab_c tableClip" style="display: none;">
-				  		<%@include file="/WEB-INF/jsp/web/addr/include/addrListforClipboard.jsp" %>
-					</div>
-					<div id="tab3" class="tab_c tableSelf" style="display: none;">
-				  		<%@include file="/WEB-INF/jsp/web/addr/include/addrListforSelf.jsp" %>
-					</div>
-					<div class="popup_btn_wrap2" style="margin: 0 auto 30px auto;">
-						<button type="button" id="btnAddrMassReg">등록</button>
-						<button type="button" id="btnAddrMassClose" class="tooltip-close" data-focus="adr_popup01-close"  data-focus-next="popup02">닫기</button>                      
-					</div>
-				
-				</div>
-			</div>
-		</div>
-	</form>
-	
-
-
-<!-- 주소록 상세 결과 팝업 data-tooltip:adr_popup14 -->
-	<div class="tooltip-wrap">
-		<div class="popup-com adr_layer adr_popup14" tabindex="0" data-tooltip-con="adr_popup14" data-focus="adr_popup14" data-focus-prev="adr_popu14-close" style="width: 450px;">
-			<div class="popup_heading">
-				<p>주소록 상세 결과</p>
-				<button type="button" class="tooltip-close" data-focus="adr_popup14-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
-			</div>
-			<div class="layer_in" style="padding:30px 20px;">
-				<div class="table_top">
-					<p>
-						총 <span class="c_e40000" id="errorPopTotCnt">0</span>건 
-						/ 중복 <span class="c_002c9a" id="errorPopDupCnt">0</span>건
-						/ 오류 <span class="c_002c9a" id="errorPopErrorCnt">0</span>건</p>
-						<button type="button" class="excel_btn btnType" id="errorExcelBtn"><i class="downroad"></i>엑셀 다운로드</button>
-				</div>
-				<div class="tb_wrap adr_list" id="tabulator_error">
-				<!-- $tableError 참고  -->
-                </div>
-                <ul class="cf_text_ul">
-                    <li>*중복번호는 하나의 번호만 등록됩니다.</li>
-                    <li>*휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.</li>
-                    <li>ex) 발송불가 특수문자, 자릿수 오류 등</li>
-                </ul>
-                <div class="popup_btn_wrap2">
-<!--                     <button type="button">저장</button> -->
-                    <button type="button" class="tooltip-close" data-focus="adr_popup14-close" data-focus-next="adr_popup14">닫기</button>                      
-                </div>
-			</div>
-		</div>
-	</div>
-
-</div>
-<!--// 주소록 대량등록 팝업 -->
-
-<div class="inner">
-	<!-- send top -->
-	<div class="send_top">
-		<!-- tab button -->
-		<ul class="tabType4">
-			<li class="tab active"><button type="button" onclick="TabType5(this,'1'); moveTab('addr');">주소록관리</button></li>
-			<li class="tab"><button type="button" onclick="TabType5(this,'2'); moveTab('fax');">팩스 주소록관리</button></li>
-			<li class="tab"><button type="button" onclick="TabType5(this,'3'); moveTab('block');">수신거부</button></li>
-			<li class="tab"><button type="button" onclick="TabType5(this,'4'); moveTab('addrMob');">폰주소록 등록</button></li>
-			<li class="tab"><button type="button" onclick="TabType5(this,'5'); moveTab('addrApply');">주소록 입력 대행(무료)</button></li>
-		</ul><!--// tab button -->
-		<!-- 주소록 관리 - 주소록 관리 -->
-		<div class="adr_cont current" id="tab5_1">
-			<div class="heading">
-				<h2>주소록 관리</h2>
-				<button type="button" class="button info" onclick="infoPop('selectAddrList');">사용안내</button>
-			</div>
-			<%--<div class="titBox">
-				<p>- 연락처를 그룹별로 분류하여 간편하고 편리하게 관리할 수 있습니다(최대 100,000개까지 등록 가능)</p>
-				<p>- 그룹은 그룹 간 이동, 병합 및 복사가 가능합니다.</p>
-				<p>- 주소록은 중복검사가 가능하며 중복된 연락처를 삭제할 수 있습니다. 단, 데이터 양에 따라 시간이 소요될 수 있습니다.</p>
-				<p>- 주소록 관리에서 그룹 또는 연락처를 선택하여 문자를 바로 발송할 수 있습니다.</p>
-				<p>- 주소록 내보내기를 통해 다른 ID로 주소록을 복사할 수 있습니다(그룹 전송만 가능, 보낸 주소록 결과는 최대 90일까지 보관)</p>
-				<p>- 주소록 내보내기 시에는 개인정보보호를 위해 추가 휴대폰 인증을 실시하며, 휴대폰 인증은 등록된 발신번호로만 인증 가능합니다.</p>
-				<p>- 고객님께서 보유하신 엑셀파일이나 텍스트파일 등으로 작성된 주소록을 대량 등록할 수 있습니다.</p>
-				<p>- 주소록 등록이 어려우신 경우에는 주소록 입력대행 메뉴를 이용하시면 됩니다.</p>
-				<p>- 주소록 무료대행은 신규 그룹으로 생성됩니다(기존 그룹 수정 불가)</p>
-			</div>--%>
-			
-			<div class="adr1">
-				<!-- 왼쪽 영역 -->
-				<div class="adr1_left" id="adr1_left"></div>
-				<!-- 오른쪽 영역 -->
-				<div class="adr1_right" id="adr1_right">
-				</div>
-			</div>
-		</div>
-	</div><!--// 주소록 관리 - 주소록 관리 -->
-</div><!--// send top -->
-
-
-
-<!--===================================================================  -->
-
-
-<form name="popForm" id="popForm" method="post">
-	<input type="hidden" name="pageType" id="pageType" value=""/> 
-</form>
-
-<form name="msgAddrForm2" id="msgAddrForm2" method="post">
-	<input name="msgStartKeyword" id="msgStartKeyword" type="hidden" />
+<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+
+<script type="text/javascript">
+</script>
+
+<script type="text/javascript" src="<c:url value='/publish/js/content.js'/>"></script>
+<script type="text/javascript" src="https://oss.sheetjs.com/sheetjs/xlsx.full.min.js"></script>
+<script type="text/javascript" src="<c:url value='/js/web/addr/init.js'/>?v=20240919"></script>
+<script type="text/javascript" src="<c:url value='/js/web/addr/event.js'/>?v=20240919"></script>
+<script type="text/javascript" src="<c:url value='/js/web/addr/utils.js'/>?v=20240919"></script>
+<script type="text/javascript" src="<c:url value='/js/web/addr/cmn.js?date=202409021440'/>"></script>
+
+
+<script type="text/javascript">
+
+$(document).ready(function(){
+	listAddrGrp();
+	addrLoadAjax();
+
+	// 엑셀 중복번호 버튼
+	$("#tableExcelDupliBtn").hide();
+// 	$("#btnAddrMassSaveDupli").hide();
+	// 주소록 대량등록
+// 	addrMassTab(1);	
+	
+	// 중복 휴대폰번호 버튼 노출여부
+	
+	
+	// excel 오류정보 테스트
+	$('#errorExcelBtn').click(function(){
+		if($tableError.getDataCount()<1){
+			alert('오류 정보가 없습니다.');
+			return false;
+		}
+		$tableError.download("xlsx", "error_data.xlsx");
+	});
+}); 
+
+// 메인 화면 좌측메뉴 최신화
+function listAddrGrp(){
+	var sendData = $(document.searchAddrGrpForm).serializeArray() ;
+	$("#adr1_left").load("/web/addr/selectAddrGroupListAjax.do", sendData ,function(response, status, xhr){});
+}
+
+
+function addrGroupLoadAjax(){
+	$("#addrRegistSelect").load("/web/addr/selectAddrGroupAjax.do", function(response, status, xhr){});
+	$("#funcAddrGroupSelect").load("/web/addr/selectAddrGroupAjax.do", function(response, status, xhr){});
+}
+
+function addrLoadAjax(){
+	$("#adr1_right").load("/web/mjon/addr/selectAddrAjax.do",  function(response, status, xhr){tableAllChk();});
+	addrGroupLoadAjax();
+}
+
+function insertAddrGroupAjax() {
+	var form = document.addrGrpInsertForm;
+	if(form.addrGrpNm.value == "") {
+		alert("주소록 그룹명을 입력해주세요.");
+		return;
+	}
+	if(!confirm("주소록 그룹을 추가하시겠습니까?")) {
+		return;
+	}
+	var data = new FormData(form);
+	
+	$.ajax({
+		cache : false,
+		url : "<c:url value='/web/addr/insertAddrGroupAjax.do' />", 
+		type : 'POST', 
+		data : data,
+		dataType:'json',
+		processData: false,
+		contentType: false,
+		success : function(returnData, status){
+			if(status == "success") {
+				if("fail"==returnData.result){
+					alert(returnData.message);
+					return;
+				} else if("dupl"==returnData.result) {
+					alert("중복된 그룹명입니다.");
+					return;
+				}
+				alert("등록되었습니다.");
+				listAddrGrp();
+				addrGroupLoadAjax();
+				
+			}else{ alert("ERROR!");return;} 
+		},
+		error: function (e) { alert("저장에 실패하였습니다."); console.log("ERROR : ", e); }
+	});
+	
+}
+
+
+// 주소록그룹 콤보박스 유지
+function setSelectSetting(selectVal) {
+	$("#addrRegistSelect").val(selectVal).prop("selected", true);	
+}
+	
+function linkPage(pageNo){
+	if ($('#searchKeywordAddr').val() != "" && $('#searchKeywordAddr').val() != null && $('#searchKeywordAddr').val() != undefined) {
+		// 문자전송 검색용
+		$("#msgStartKeyword").val("");
+	}
+
+	var searchForm = document.searchAddrForm;
+	searchForm.pageIndex.value = pageNo;
+	searchForm.pageUnit.value = $('#pageUnit').val();
+	searchForm.searchCondition.value = $('#searchConditionAddr').val();
+	searchForm.searchKeyword.value = $('#searchKeywordAddr').val();
+	searchForm.startKeyword.value = $("#msgStartKeyword").val();
+	
+	var sendData = $(document.searchAddrForm).serializeArray();
+	$("#adr1_right").load("/web/mjon/addr/selectAddrAjax.do", sendData, function(response, status, xhr){tableAllChk();});
+	addrGroupLoadAjax();
+}
+
+function moveTab(type){
+	if(type == "addr") 			location.href="/web/mjon/addr/selectAddrList.do";
+	if(type == "fax") 			location.href="/web/mjon/fax/addr/selectFaxAddrList.do";
+	if(type == "block") 		location.href="/web/mjon/addrBlock/selectBlockList.do";
+	if(type == "addrMob") 		location.href="/web/mjon/addr/addrMobGuide.do";
+	if(type == "addrApply") 	location.href="/web/mjon/addragency/selectAddrAgencyList.do";
+}
+
+
+
+//#############################################################################################
+//Tabulator
+//#############################################################################################
+
+$(document).ready(function(){
+	
+
+
+	
+	// 오류검사 항목 중복제거
+	function SetTableErrorDupliCheck(sVal) {
+		var isDuplicate = false;
+		if (tableErrorCheckData.length == 0) {
+			tableErrorCheckData.push(sVal);
+		}
+		else {
+			for (var i = 0; i < tableErrorCheckData.length; i++)
+			{
+				if (tableErrorCheckData[i] == sVal) {
+					isDuplicate = true;
+				}
+			}
+			
+			if (isDuplicate) {
+				return;
+			}
+			else {
+				tableErrorCheckData.push(sVal);
+			}
+		}
+	}	
+	
+	
+	// 오류검사 항목 중복제거
+	function SetTableErrorDupliCheck(sVal) {
+		var isDuplicate = false;
+		if (tableErrorCheckData.length == 0) {
+			tableErrorCheckData.push(sVal);
+		}
+		else {
+			for (var i = 0; i < tableErrorCheckData.length; i++)
+			{
+				if (tableErrorCheckData[i] == sVal) {
+					isDuplicate = true;
+				}
+			}
+			
+			if (isDuplicate) {
+				return;
+			}
+			else {
+				tableErrorCheckData.push(sVal);
+			}
+		}
+	}	
+	
+	
+
+	
+});
+
+
+
+//#############################################################################################
+//등록
+//#############################################################################################
+
+//등록
+$(document).on('click', '#btnAddrMassReg', function() {
+	// 저장
+	SetAddrMassSave();
+});
+
+$(document).on('click', '#btnAddrMassClose', function() {
+	// 대량등록 닫기
+	setAddrMassClose();
+});
+
+// 대량등록 닫기
+function setAddrMassClose() {
+	var $objTabul = fn_utils_getTabulator();
+	$objTabul.clearData();
+	
+	fn_rowDataClear();
+	
+	
+	$("#rowTotCnt").text(0); //총건수 수정
+	$("#rowDupCnt").text(0); //중복건수 수정
+	$("#rowErrorCnt").text(0); //중복건수 수정
+	
+	
+	
+	dupliPhoneDataRealList.length = 0;	// 중복 휴대폰번호 초기화
+	addrMassDupliSaveList = null;
+
+	$("#btnAddrMassDupli").hide();
+	$("#btnAddrMassSaveDupli").hide();
+	
+	//location.reload();
+	listAddrGrp();
+	addrGroupLoadAjax();
+	addrLoadAjax();		
+	fn_errorPopClean(); // 에러 팝업 초기화
+}
+
+// 주소록 탭마다 돌면서 총, 중복, 오류 건수 초기화
+function fn_rowDataClear(){
+
+	// 모든 .tab 요소를 선택하여 반복
+	$('#tbTabl .tab').each(function() {
+	    // 현재 반복 중인 요소
+	    var tab = $(this);
+
+	    // data-tabul 값 가져오기
+	    var tabulNm = tab.data('tabul');
+		var tabluC = '.'+tabulNm
+
+	    // 중복 카운트
+	    $(tabluC+" #rowTotCnt").text(0);
+	    // 에러 카운트
+	    $(tabluC+" #rowDupCnt").text(0);
+	    // 
+	    $(tabluC+" #rowErrorCnt").text(0);
+		
+		
+	});
+}
+
+
+
+// 주소록 그룹 중복체크
+function getAddrGroupDuplCheckAjax(addrGrpNm) {
+	var isReturn = true;
+	
+	$.ajax({
+		url : "<c:url value='/web/addr/getAddrGroupDuplCheckAjax.do' />", 
+		type : 'POST', 
+		data : {"addrGrpNm" : addrGrpNm},
+		dataType:'json',
+		async: false,			// 동기
+		success : function(data, status){
+			if(data.isSuccess == true) {
+				if(data.isDupl == true) {
+					//alert("중복된 그룹명입니다.");
+					isReturn = false;
+				}
+			} 
+			else {
+				//alert("Message : " + msg);
+			}			
+		},
+		error: function (e) {
+			//alert("주소록 중복체크에 실패했습니다.");
+		}
+	});
+	console.log('isReturn : ', isReturn);
+	
+	return isReturn;	
+}
+
+
+//저장
+function SetAddrMassSave(){
+
+
+	
+	
+	
+	
+	
+	
+	
+	var $objTabul = fn_utils_getTabulator();
+	var tabulNm = fn_utils_getTabulatorNm();
+	var tabluC = '.'+tabulNm
+
+	/* console.log('$objTabul : ', $objTabul.getData());
+	if(tabulNm  == 'tableSelf'){
+		console.log('????');
+		
+		var allRows = $objTabul.getData(); // 테이블의 모든 데이터를 가져옴
+
+		// addrPhoneNo 값이 있는 행만 필터링
+		var rowsWithPhoneNumbers = allRows.filter(function(row) {
+			return row.addrPhoneNo && row.addrPhoneNo.trim() !== ''; // 값이 존재하고 공백이 아닌 경우
+		});
+		$objTabul = rowsWithPhoneNumbers;
+		console.log('rowsWithPhoneNumbers : ', rowsWithPhoneNumbers);
+		console.log('$objTabul : ', $objTabul.getData());
+		return false;
+	} */
+	
+	if($objTabul.getData().length < 1){
+		alert("한 개 이상의 연락처를 입력하세요");
+		return false;
+	}
+	
+	if($objTabul.getData().length > 300000){
+		alert("30만개 까지 등록 가능합니다.");
+		return false;
+	}
+	
+// 	var selectMassVal = $(tabluC+" #addrGrpIdInfo option:selected").val();
+	
+	var loginVO = '${LoginVO}';
+	if(fn_utils_isEmpty(loginVO)){
+		alert("로그인 후 이용이 가능합니다.");
+		return false;
+	}
+	
+	// tableExcel select 요소들을 확인
+	var columns = $objTabul.getColumns();
+	var isAddrPhoneNoSelected = columns.some(column => column.getField() === 'addrPhoneNo');
+	if (!isAddrPhoneNoSelected) {
+//		    isPhoneSelected = true;
+		alert('휴대폰이 선택되지 않았습니다.');
+		return false;
+
+	} 
+	
+	// 주소록이 새로생성이면 새로운 주소록명이 있는지 확인
+	if ($(tabluC+" #addrGrpIdInfo option:selected").val() == "NEW" 
+				&& ($(tabluC+" #addrGrpNm").val() == "" 
+						|| $(tabluC+" #addrGrpNm").val() == null 
+						|| $(tabluC+" #addrGrpNm").val() == undefined)
+						) 
+	{
+		alert("저장할 그룹을 선택하거나 새 그룹명을 입력해주세요.");
+		$(tabluC+" #addrGrpNm").focus();
+		return false;		
+	}
+	
+	// 새 그룹명 중복체크
+	if ($(tabluC+" #addrGrpIdInfo option:selected").val() == "NEW" 
+			&& $(tabluC+" #addrGrpNm").val() != "") 
+	{
+		var addrGrpNm = $(tabluC+" #addrGrpNm").val();
+		console.log('addrGrpNm : ', addrGrpNm);
+		//주소록 중복체크
+		if (getAddrGroupDuplCheckAjax(addrGrpNm) == false) {
+			alert("중복된 그룹명입니다. 새 그룹명을 입력해주세요.");
+			return false;			
+		}
+	}	
+	
+	var confirmMsg = "저장하시겠습니까?\n이름 200byte, [*1*]~[*4*] 200byte, 메모 250byte 초과 글자는 절사됩니다.";
+	if (confirm(confirmMsg)) {	
+		//로딩창 show
+		fn_loadAddActive();				
+
+		setTimeout(setSenderList_advc, 1000);
+// 		setTimeout(setSenderList_old, 1000);
+
+	}
+}
+/* 
+// 주소록 등록 old
+function setSenderList_old(){
+
+	// tab에 해당하는 타블레이터 가져오기
+
+	var tabulNm = fn_utils_getTabulatorNm();
+	var tabluC = '.'+tabulNm
+	  
+    var $objTabul = fn_utils_getTabulator();
+    var dataToSend = $objTabul.getData();
+    var addrGrpIdInfo = $(tabluC+" #addrGrpIdInfo option:selected").val();
+    var addrGrpNmInfo = $(tabluC+" #addrGrpNm").val();
+
+	var updateData = dataToSend.map(row => {
+	    row.addrGrpId = addrGrpIdInfo;
+	    row.addrGrpNm = addrGrpNmInfo;
+	    return row;
+	});
+	
+	console.log('updateData : ', updateData);
+	$.ajax({
+	    type: "POST",
+	    url: "/web/mjon/addr/addrMassInsertByTempAjax_advc.do",
+	    data: JSON.stringify(updateData),
+	    dataType: 'json',
+	    contentType: 'application/json',
+	    async: true,
+	    success: function (data) {
+	    	console.log('data : ', data);
+	    	
+
+			if (data.status == 'OK') {  
+				alert(data.message);
+				// 데이터 비우기
+				SetClear($objTabul);		
+				setAddrMassClose();
+				var selectMassVal = $("#addrGrpIdInfo option:selected").val();
+			} 
+			else {
+				alert("오류 알림 :  :: "+data.message);
+			}
+		},
+		error: function (e) { 
+			alert("저장에 실패하였습니다."); 
+			alert("ERROR : " + JSON.stringify(e)); 
+		},
+		beforeSend : function(xmlHttpRequest) {
+			//로딩창 show
+			$('.loading_layer').addClass('active');				
+		},	        	        
+		complete : function(xhr, textStatus) {
+			//로딩창 hide
+			$('.loading_layer').removeClass('active');
+		}
+	});
+}
+ */
+
+function setSenderList_advc(){
+
+	var tabulNm = fn_utils_getTabulatorNm();
+	var tabluC = '.'+tabulNm
+	  
+    var $objTabul = fn_utils_getTabulator();
+    var dataToSend = $objTabul.getData();
+    console.log('dataToSend : ', dataToSend);
+    var addrGrpIdInfo = $(tabluC+" #addrGrpIdInfo option:selected").val();
+    var addrGrpNmInfo = $(tabluC+" #addrGrpNm").val();
+
+    var batchSize = 30000; // 배치 크기
+    var totalBatches = Math.ceil(dataToSend.length / batchSize); // 총 배치 수
+    var currentBatch = 0; // 현재 배치 인덱스
+
+
+	fn_loadAddActive();
+
+    function sendBatch() {
+        if (currentBatch < totalBatches) {
+        	fn_loadAddActive();
+            var start = currentBatch * batchSize;
+            var end = Math.min(start + batchSize, dataToSend.length);
+            var batchData = dataToSend.slice(start, end);
+
+            var updateData = batchData.map(row => {
+                row.addrGrpId = addrGrpIdInfo;
+                row.addrGrpNm = addrGrpNmInfo;
+                return row;
+            });
+            
+            $.ajax({
+                type: "POST",
+                url: "/web/mjon/addr/addrMassInsertByTempAjax_advc.do",
+                data: JSON.stringify(updateData),
+                dataType: 'json',
+                contentType: 'application/json',
+                async: true,
+                success: function (data) {
+                	
+
+            		fn_loadRemoveActive();
+                	
+                    console.log('Batch ' + (currentBatch + 1) + ' success: ', data);
+                    if (data.status == 'OK') {
+                        if (currentBatch === totalBatches - 1) {
+                            alert("모든 데이터가 성공적으로 저장되었습니다.");
+                            // 데이터 비우기
+                            SetClear($objTabul);
+                            setAddrMassClose();
+                        } else {
+                            currentBatch++;
+                            // 새로만든 그룹ID나 기존 ID를 넣어줌
+                            // 그룹추가 시 배치별로 똑같은 그룹을 생성해서 방지차원으로 넣어줌 
+                            addrGrpIdInfo = data.object;
+                            sendBatch(); // 다음 배치 전송
+                        }
+                    } else {
+                        alert("오류 알림 : " + data.message);
+                    }
+                },
+                error: function (e) {
+                    alert("배치 전송에 실패하였습니다."); 
+                    console.error("ERROR: ", JSON.stringify(e));
+                },
+                beforeSend: function(xmlHttpRequest) {
+                },
+                complete: function(xhr, textStatus) {
+                    if (currentBatch === totalBatches - 1) {
+                    	$('#lodingTxt').text('Loading');
+                    } else {
+                    	$('#lodingTxt').text(end+'...');
+                    }
+                }
+            });
+        }
+    }
+    // 첫 번째 배치 전송 시작
+    sendBatch();
+}
+
+
+ 
+//주소록그룹 콤보박스 유지
+function setSelectMassSetting(selectMassVal) {
+	$("#addrGrpIdInfo").val(selectMassVal).prop("selected", true);	
+}
+
+
+//데이터 비우기
+function SetClear($objTabul) {
+	
+
+	var tabulNm = fn_utils_getTabulatorNm();
+	var tabluC = '.'+tabulNm
+	
+	$(tabluC+" #addrGrpNm").val(""); //	새그룹명 Clear;
+	// 주소록 그룹정보 불러오기
+	getAddrGroupList();	
+
+
+
+	if (tabulNm === 'tableSelf') {
+		var tableData = [];
+		for (var i = 0; i < 1000; i++) {
+			tableData.push({addrNm: "", addrPhoneNo: "", addrInfo1: "", addrInfo2: "", addrInfo3: "", addrInfo4: "", addrComment: ""});
+		}
+		console.log(tableData); // 데이터 출력 확인
+		fn_selfmakeTable()
+	}else{
+	 	$objTabul.clearData(); // clearData는 동기 방식이므로 바로 실행
+		
+	}
+// 	console.log('tabulNm : ', tabulNm);
+// 	console.log('tabulNm : ', tabulNm.trim());
+
+	
+	$(tabluC+" #rowTotCnt").text(0); //총건수 수정
+	$(tabluC+" #rowDupCnt").text(0); //중복건수 수정
+
+	// popup 영역
+	fn_errorPopClean();
+}
+
+// 주소 대량등록 버튼 클릭 
+// AddrListAjax.jsp에서 호출
+$(document).on('click', '#btnAddrMassRegCall', function() {
+	getAddrGroupList();
+});
+
+
+// 주소록 그룹정보 불러오기
+function getAddrGroupList() {
+	$.ajax({
+		type : "POST",
+		async : false,
+		url : "/web/mjon/addr/addrGroupListAjax.do",
+		data : {},
+		dataType:'json',
+		success : function(data) {
+			//alert(JSON.stringify(data.addrGroupList));
+
+			// Show Html
+			getAddrGroupListShow(data.addrGroupList);
+		},
+		error : function(xhr, status, error) {
+			alert(error);
+			return false;
+		}
+	});	    	
+}
+
+
+
+	
+// 그룹데이터 노출
+function getAddrGroupListShow(jsonList) {
+	var sHtml = "";
+	sHtml += "<option value='NEW'>그룹추가</option>";
+	sHtml += "<option value='0'>그룹미지정</option>";
+	sHtml += "<option value='bookmark'>자주보내는 번호</option>";
+	for (var j = 0; j < jsonList.length; j++) {
+		sHtml += "	<option value='" + $.trim(jsonList[j].addrGrpId) + "' />" + $.trim(jsonList[j].addrGrpNm) + "</option>";
+	}
+
+	var tabulNm = fn_utils_getTabulatorNm();
+	var tabluC = '.'+tabulNm
+	$(tabluC+" #addrGrpIdInfo").html(sHtml);
+}
+
+$(document).on('change', '#addrGrpIdInfo', function() {
+	if ($("#addrGrpIdInfo option:selected").val() != "NEW") {
+		$("#addrGrpNm").val(""); //	새그룹명 Clear;
+	}
+});
+
+//#############################################################################################
+//파일 불러오기
+//#############################################################################################
+
+//체크박스 전체선택/해제
+$(document).on("click", "#chkAll", function(e) {
+	var isChecked = $(this).is(":checked");
+	$("input[name=addrCheck]:checkbox").prop("checked", isChecked);
+});
+
+$(document).on("click", "#duplicationChkAll", function(e) {
+	var isChecked = $(this).is(":checked");
+	$("input[name=addrCheck]:checkbox").prop("checked", isChecked);
+});	
+
+//팝업 텍스트 더보기 클릭 시 펼쳐지고 숨겨짐
+function popMore(e){
+	$(e).closest(".pop_more_cont").toggleClass("pop_more_click");
+	
+	if($(e).closest(".pop_more_cont").is(".pop_more_click")){
+		$(e).html('숨기기');
+		$(e).append('<i></i>');
+	}else {
+		$(e).html('더보기');
+		$(e).append('<i></i>');
+	}
+}
+
+/* 윈도우팝업 열기 */
+function infoPop(pageUrl){
+	document.popForm.pageType.value = pageUrl;
+	document.popForm.action = "/web/pop/infoPop.do";
+	document.popForm.method = "post"; 
+	window.open("about:blank", 'infoPop', 'width=790, height=430, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=1');
+	document.popForm.target = "infoPop";
+	document.popForm.submit();
+}
+
+// 중복 연락처
+function GetAddrMassDupli() {
+	var sHtml = "";
+	sHtml += "<div class='' style='overflow-x:auto; height:350px;'>";
+	sHtml += "<table class='tType4'>";
+	sHtml += "		<colgroup>";
+	sHtml += "			<col style='width:auto' />";
+	sHtml += "		</colgroup>";
+	sHtml += "		<thead>";
+	sHtml += "			<tr>";
+	sHtml += "				<th>중복 휴대폰번호 (" + numberWithCommas(dupliPhoneDataRealList.length) + "개)</th>";
+	sHtml += "			</tr>";
+	sHtml += "		</thead>";
+	sHtml += "		<tbody>";
+	for (var i = 0; i < dupliPhoneDataRealList.length; i++) {
+		sHtml += "		<tr>";
+		sHtml += "			<td>" + dupliPhoneDataRealList[i] + "</td>";
+		sHtml += "		</tr>";
+	}
+	sHtml += "		</tbody>";
+	sHtml += "	</table>";
+	sHtml += "	</div>";
+	
+	$("#addrMassDupli_layer").html(sHtml);
+}
+
+//중복 연락처 => 저장시
+function GetAddrMassSaveDupli() {
+	var sHtml = "";
+	sHtml += "<div class='' style='overflow-x:auto; height:350px;'>";
+	sHtml += "<table class='tType4'>";
+	sHtml += "		<colgroup>";
+	sHtml += "			<col style='width:auto' />";
+	sHtml += "		</colgroup>";
+	sHtml += "		<thead>";
+	sHtml += "			<tr>";
+	sHtml += "				<th>중복 휴대폰번호 (" + numberWithCommas(addrMassDupliSaveList.length) + "개)</th>";
+	sHtml += "			</tr>";
+	sHtml += "		</thead>";
+	sHtml += "		<tbody>";
+	for (var i = 0; i < addrMassDupliSaveList.length; i++) {
+		sHtml += "		<tr>";
+		sHtml += "			<td>" + addrMassDupliSaveList[i].addrPhoneNo + "</td>";
+		sHtml += "		</tr>";
+	}
+	sHtml += "		</tbody>";
+	sHtml += "	</table>";
+	sHtml += "	</div>";
+	
+	$("#addrMassSaveDupli_layer").html(sHtml);
+}
+
+
+// function fn_tabToggle('1')
+function fn_tabToggle(tabNum){
+	var tabId = '#tab'+tabNum;
+	$('.tab_c').hide();
+	$(tabId).show();
+	getAddrGroupList();
+}
+
+
+</script>
+
+<div class="loading_layer">
+	<div class="loading_container">
+		<div class="bar"></div>
+		<div class="text" id="lodingTxt">
+		Loading
+		</div>
+	</div>
+</div>
+
+<div id="adrPopup_tab1">
+
+
+<!-- 수신거부 대량등록  data-tooltip:adr_popup01 -->
+	<form id="addrMassForm" name="addrMassForm" method="post">
+		<input type="hidden" id="phoneList" name="phoneList" value=""/>
+		<input type="hidden" id="nameList" name="nameList" value=""/>
+		<input type="hidden" id="info1List" name="info1List" value=""/>
+		<input type="hidden" id="info2List" name="info2List" value=""/>
+		<input type="hidden" id="info3List" name="info3List" value=""/>
+		<input type="hidden" id="info4List" name="info4List" value=""/>
+		<input type="hidden" id="memoList" name="memoList" value=""/>
+		<input type="hidden" id="addrGrpId" name="addrGrpId" value=""/>
+		<div class="tooltip-wrap" id="addrMassLoad">
+			<div class="popup-com adr_layer adr_popup01" tabindex="0" data-tooltip-con="adr_popup01" data-focus="adr_popup01" data-focus-prev="adr_popup01-close" style="width: 1000px;">
+				<div class="popup_heading">
+					<p>주소록 대량등록</p>
+					<button type="button" class="tooltip-close" data-focus="adr_popup01-close" onclick="setAddrMassClose();"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+			   </div>
+				<div class="layer_in" style="padding: 25px 30px;">
+				   <div class="list_tab_wrap2">
+					   <!-- tab button -->
+					   <ul class="list_tab" id="tbTabl"> 
+						   <li class="tab active" data-tabul="tableExcel"><button type="button" onclick="popupTab(this,'1'); fn_tabToggle('1');">엑셀입력</button></li>
+						   <li class="tab" data-tabul="tableClip"><button type="button" onclick="popupTab(this,'2'); fn_tabToggle('2');">붙여넣기</button></li>
+						   <li class="tab" data-tabul="tableSelf"><button type="button" onclick="popupTab(this,'3'); fn_tabToggle('3');">직접입력</button></li>
+					   </ul><!--// tab button -->
+				   </div>
+					<div id="tab1" class="tab_c tableExcel">
+				  		<%@include file="/WEB-INF/jsp/web/addr/include/addrListforExcel.jsp" %>
+					</div>
+					<div id="tab2" class="tab_c tableClip" style="display: none;">
+				  		<%@include file="/WEB-INF/jsp/web/addr/include/addrListforClipboard.jsp" %>
+					</div>
+					<div id="tab3" class="tab_c tableSelf" style="display: none;">
+				  		<%@include file="/WEB-INF/jsp/web/addr/include/addrListforSelf.jsp" %>
+					</div>
+					<div class="popup_btn_wrap2" style="margin: 0 auto 30px auto;">
+						<button type="button" id="btnAddrMassReg">등록</button>
+						<button type="button" id="btnAddrMassClose" class="tooltip-close" data-focus="adr_popup01-close"  data-focus-next="popup02">닫기</button>                      
+					</div>
+				
+				</div>
+			</div>
+		</div>
+	</form>
+	
+
+
+<!-- 주소록 상세 결과 팝업 data-tooltip:adr_popup14 -->
+	<div class="tooltip-wrap">
+		<div class="popup-com adr_layer adr_popup14" tabindex="0" data-tooltip-con="adr_popup14" data-focus="adr_popup14" data-focus-prev="adr_popu14-close" style="width: 450px;">
+			<div class="popup_heading">
+				<p>주소록 상세 결과</p>
+				<button type="button" class="tooltip-close" data-focus="adr_popup14-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+			</div>
+			<div class="layer_in" style="padding:30px 20px;">
+				<div class="table_top">
+					<p>
+						총 <span class="c_e40000" id="errorPopTotCnt">0</span>건 
+						/ 중복 <span class="c_002c9a" id="errorPopDupCnt">0</span>건
+						/ 오류 <span class="c_002c9a" id="errorPopErrorCnt">0</span>건</p>
+						<button type="button" class="excel_btn btnType" id="errorExcelBtn"><i class="downroad"></i>엑셀 다운로드</button>
+				</div>
+				<div class="tb_wrap adr_list" id="tabulator_error">
+				<!-- $tableError 참고  -->
+                </div>
+                <ul class="cf_text_ul">
+                    <li>*중복번호는 하나의 번호만 등록됩니다.</li>
+                    <li>*휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.</li>
+                    <li>ex) 발송불가 특수문자, 자릿수 오류 등</li>
+                </ul>
+                <div class="popup_btn_wrap2">
+<!--                     <button type="button">저장</button> -->
+                    <button type="button" class="tooltip-close" data-focus="adr_popup14-close" data-focus-next="adr_popup14">닫기</button>                      
+                </div>
+			</div>
+		</div>
+	</div>
+
+</div>
+<!--// 주소록 대량등록 팝업 -->
+
+<div class="inner">
+	<!-- send top -->
+	<div class="send_top">
+		<!-- tab button -->
+		<ul class="tabType4">
+			<li class="tab active"><button type="button" onclick="TabType5(this,'1'); moveTab('addr');">주소록관리</button></li>
+			<li class="tab"><button type="button" onclick="TabType5(this,'2'); moveTab('fax');">팩스 주소록관리</button></li>
+			<li class="tab"><button type="button" onclick="TabType5(this,'3'); moveTab('block');">수신거부</button></li>
+			<li class="tab"><button type="button" onclick="TabType5(this,'4'); moveTab('addrMob');">폰주소록 등록</button></li>
+			<li class="tab"><button type="button" onclick="TabType5(this,'5'); moveTab('addrApply');">주소록 입력 대행(무료)</button></li>
+		</ul><!--// tab button -->
+		<!-- 주소록 관리 - 주소록 관리 -->
+		<div class="adr_cont current" id="tab5_1">
+			<div class="heading">
+				<h2>주소록 관리</h2>
+				<button type="button" class="button info" onclick="infoPop('selectAddrList');">사용안내</button>
+			</div>
+			<%--<div class="titBox">
+				<p>- 연락처를 그룹별로 분류하여 간편하고 편리하게 관리할 수 있습니다(최대 100,000개까지 등록 가능)</p>
+				<p>- 그룹은 그룹 간 이동, 병합 및 복사가 가능합니다.</p>
+				<p>- 주소록은 중복검사가 가능하며 중복된 연락처를 삭제할 수 있습니다. 단, 데이터 양에 따라 시간이 소요될 수 있습니다.</p>
+				<p>- 주소록 관리에서 그룹 또는 연락처를 선택하여 문자를 바로 발송할 수 있습니다.</p>
+				<p>- 주소록 내보내기를 통해 다른 ID로 주소록을 복사할 수 있습니다(그룹 전송만 가능, 보낸 주소록 결과는 최대 90일까지 보관)</p>
+				<p>- 주소록 내보내기 시에는 개인정보보호를 위해 추가 휴대폰 인증을 실시하며, 휴대폰 인증은 등록된 발신번호로만 인증 가능합니다.</p>
+				<p>- 고객님께서 보유하신 엑셀파일이나 텍스트파일 등으로 작성된 주소록을 대량 등록할 수 있습니다.</p>
+				<p>- 주소록 등록이 어려우신 경우에는 주소록 입력대행 메뉴를 이용하시면 됩니다.</p>
+				<p>- 주소록 무료대행은 신규 그룹으로 생성됩니다(기존 그룹 수정 불가)</p>
+			</div>--%>
+			
+			<div class="adr1">
+				<!-- 왼쪽 영역 -->
+				<div class="adr1_left" id="adr1_left"></div>
+				<!-- 오른쪽 영역 -->
+				<div class="adr1_right" id="adr1_right">
+				</div>
+			</div>
+		</div>
+	</div><!--// 주소록 관리 - 주소록 관리 -->
+</div><!--// send top -->
+
+
+
+<!--===================================================================  -->
+
+
+<form name="popForm" id="popForm" method="post">
+	<input type="hidden" name="pageType" id="pageType" value=""/> 
+</form>
+
+<form name="msgAddrForm2" id="msgAddrForm2" method="post">
+	<input name="msgStartKeyword" id="msgStartKeyword" type="hidden" />
 </form>
(No newline at end of file)
src/main/webapp/WEB-INF/jsp/web/addr/include/addrListforExcel.jsp
--- src/main/webapp/WEB-INF/jsp/web/addr/include/addrListforExcel.jsp
+++ src/main/webapp/WEB-INF/jsp/web/addr/include/addrListforExcel.jsp
@@ -142,134 +142,7 @@
     });
 
 
-    
-	// 오류검사 항목 중복제거
-	function SetTableErrorDupliCheck(sVal) {
-		var isDuplicate = false;
-		if (tableErrorCheckData.length == 0) {
-			tableErrorCheckData.push(sVal);
-		}
-		else {
-			for (var i = 0; i < tableErrorCheckData.length; i++)
-			{
-				if (tableErrorCheckData[i] == sVal) {
-					isDuplicate = true;
-				}
-			}
-			
-			if (isDuplicate) {
-				return;
-			}
-			else {
-				tableErrorCheckData.push(sVal);
-			}
-		}
-	}	
 	
-	
-	// 오류검사 항목 중복제거
-	function SetTableErrorDupliCheck(sVal) {
-		var isDuplicate = false;
-		if (tableErrorCheckData.length == 0) {
-			tableErrorCheckData.push(sVal);
-		}
-		else {
-			for (var i = 0; i < tableErrorCheckData.length; i++)
-			{
-				if (tableErrorCheckData[i] == sVal) {
-					isDuplicate = true;
-				}
-			}
-			
-			if (isDuplicate) {
-				return;
-			}
-			else {
-				tableErrorCheckData.push(sVal);
-			}
-		}
-	}	
-	
-	$('.check_validity').click(function(){
-		tableErrorCheckData.length = 0;	// 오류 번호 배열 초기화
-		
-		var data = $tableExcel.getRows();
-		var invalid = $tableExcel.getInvalidCells();		//오류 데이터 체크
-		var dataLen = $tableExcel.getRows().length;		//연락처 데이터 갯수
-		var totLen = invalid.length;				//오류 데이터 갯수
-		var errMsg = "";							//최종 alert에 표시할 메시지 저장 변수
-		
-		if(dataLen > 0) { //연락처 정보가 있으면 수행
-			if(totLen > 0) { //내용에 오류가 있으면 수행
-				//오류 데이터 값 저장
-				for(var i=0; i < totLen; i++) {
-					var cellValue = invalid[i].getValue();
-					SetTableErrorDupliCheck(cellValue);
-				}
-				
-				for(var i=0; i < dataLen; i++){
-					// 휴대폰번호 체크
-		        	var phone = data[i].getData().phone;
-		        	var valiCheck = checkHpNum(phone);
-		        	if(!valiCheck){
-		        		SetTableErrorDupliCheck(phone);
-		        	}
-				}
-			}
-			else {
-				for(var i=0; i < dataLen; i++){
-					// 휴대폰번호 체크
-		        	var phone = data[i].getData().phone;
-		        	var valiCheck = checkHpNum(phone);
-		        	if(!valiCheck){
-		        		SetTableErrorDupliCheck(phone);
-		        	}
-				}				
-			}
-		}
-		else {
-			alert("연락처를 입력해 주세요.");
-			return false;
-		}
-		
-		if (tableErrorCheckData.length > 0) {
-			for (var i = 0; i < tableErrorCheckData.length; i++)
-			{
-				errMsg += tableErrorCheckData[i];
-				if ((tableErrorCheckData.length - 1) > i) {
-					errMsg += ", ";
-				}
-			}			
-    		alert(errMsg + "의 내용에 오류가 있습니다.");			
-		}
-		else {
-			alert("오류 데이터가 없습니다.");			
-		}
-		
-		return false;		
-	});
-	
-
-
-	//받는사람 중복 삭제
-	$('.duple_del').click(function(){
-		//기존 연락처 모두 불러오기
-	    var data = $tableExcel.getRows();
-	    var tableData = [];
-	    var dpCnt = 0;
-	    var totLen = $tableExcel.getRows().length;
-	    
-	    for(var i=0; i < totLen; i++){
-	    	tableData.push({name: data[i].getData().name.trim(), phone: data[i].getData().phone.trim()});
-	    }
-	    
-	    var removeDuplData = dupliPhoneData(tableData);
-	    $tableExcel.setData(removeDuplData);
-	    
-	    //총 받는사람 수 계산
-	    totRows = $tableExcel.getRows().length;
-	    updateTotCnt(totRows);
-	});	
 	
 	
 });
src/main/webapp/WEB-INF/jsp/web/msgdata/include/msgDataIncludeExcel.jsp
--- src/main/webapp/WEB-INF/jsp/web/msgdata/include/msgDataIncludeExcel.jsp
+++ src/main/webapp/WEB-INF/jsp/web/msgdata/include/msgDataIncludeExcel.jsp
@@ -331,6 +331,14 @@
 
 function excelFileChange(file) {
 	if (file) {
+
+		// 파일 크기 체크 (20MB)
+		const maxSize = 20 * 1024 * 1024; // 20MB in bytes
+		if (file.size > maxSize) {
+			alert('파일 크기는 20MB를 초과할 수 없습니다.');
+			return;
+		}
+		
 		fn_loadAddActive();
 		var reader = new FileReader();
 		var extension = file.name.split('.').pop().toLowerCase();
@@ -500,15 +508,18 @@
 	let duplicateCount = 0; // 중복 번호 개수를 저장할 변수
 	
 	const errors = [];  // 오류 데이터를 저장할 배열
-	const duplicates = [];  // 오류 데이터를 저장할 배열
 	const newData = []; // 유효한 데이터만 저장할 새로운 배열
 	
 	data.forEach((row, index) => {
-		if (index % 10000 === 0) {
-		    console.log('i : ', index);
-		}
 		
 		const number = row.addrPhoneNo;
+		
+		// number가 null, undefined, 빈 문자열이거나 숫자인 경우 처리
+		if (!number || (typeof number === 'string' && !number.trim())){
+			console.log("number : ", number);
+			 return;
+		}
+		
 		const formattedNumber = formatPhoneNumber(number); // 번호 표준화
 		const cleanedNumber = formattedNumber.replace(/[^0-9]/g, ''); // 숫자만 남김
 		
@@ -518,32 +529,24 @@
 		        existingNumbers.add(cleanedNumber); // 추가된 번호를 기존 목록에 추가
 		        newData.push(row); // 유효한 데이터만 새로운 배열에 추가
 		    } else {
-		        // 오류: 유효성 통과 못함
-		        errorCount++;
-		        $tableError.addRow({ 
-		            name: row.addrNm, // 이름
-		            phone: row.addrPhoneNo, // 폰번호
-		            result: "오류" // 결과 메시지 추가
-		        });
-		        errors.push({ 
-		            name: row.addrNm, // 이름
-		            phone: row.addrPhoneNo, // 폰번호
-		            result: "오류" // 결과 메시지 추가
-		        });
+				// 오류: 유효성 통과 못함
+				errorCount++;
+				
+				errors.push({ 
+					name: row.addrNm, // 이름
+					phone: row.addrPhoneNo, // 폰번호
+					result: "오류" // 결과 메시지 추가
+				});
 		    }
 		} else {
-		    // 중복
-		    duplicateCount++; // 중복 번호가 발견될 때마다 카운트를 증가
-		    $tableError.addRow({ 
-		        name: row.addrNm, // 이름
-		        phone: row.addrPhoneNo, // 폰번호
-		        result: "중복" // 결과 메시지 추가
-		    });
-		    duplicates.push({ 
-		       name: row.addrNm, // 이름
-		       phone: row.addrPhoneNo, // 폰번호
-		       result: "중복" // 결과 메시지 추가
-		   });
+			// 중복
+			duplicateCount++;
+			
+			errors.push({ 
+				name: row.addrNm, // 이름
+				phone: row.addrPhoneNo, // 폰번호
+				result: "중복" // 결과 메시지 추가
+			});
 		}
 	});
 	
@@ -561,17 +564,14 @@
 	$("#excelRowErrorCnt").text(errorCount);
 	
 	// popup 영역
+	$("#errorPopTotCnt").text($objTabul.getDataCount());
 	// 중복 카운트
 	$("#errorPopDupCnt").text(duplicateCount);
 	// 에러 카운트
 	$("#errorPopErrorCnt").text(errorCount);
-	// 
-	$("#errorPopTotCnt").text(duplicateCount+errorCount);
 	
 	
-	var errorData = errors.concat(duplicates);
-	 // 오류 및 중복 데이터를 한 번에 추가
-	$tableError.setData(errorData);
+	$tableError.setData(errors);
 	
 	if(errorCount > 0){
 		alert('휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.\nex) 발송불가 특수문자, 자릿수 오류 등');
@@ -711,7 +711,7 @@
 					<!-- 엑셀입력 -->
 					<div class="popCont current pop_more_cont" id="popCont_1">
 						<div class="titBox">
-							<p>- 주소록은 한 번에 최대 30만건까지 등록(EXCEL파일, 최대용량 3MB) 가능합니다. </p>
+							<p>- 주소록은 한 번에 최대 30만건까지 등록(EXCEL파일, 최대용량 20MB) 가능합니다. </p>
 							<p>- 엑셀 파일에 비밀번호 설정, 제한된 보기, 수식 등이 설정되어 있는 경우 업로드가 불가합니다.</p>
 							<p>- 구분선(|), 역슬래시(\, ₩), 큰따옴표(") 등 발송불가 특수문자는 저장되지 않습니다.</p>
 							<p>- 이름 200byte, [*1*]~[*4*] 200byte, 메모 250byte까지 입력 가능합니다.</p>
src/main/webapp/js/web/addr/event.js
--- src/main/webapp/js/web/addr/event.js
+++ src/main/webapp/js/web/addr/event.js
@@ -1,454 +1,453 @@
-
-
-$(document).ready(function(){
-
-	
-	//타이틀 select 선택 이벤트
-	 $('[data-group]').on('change', '.field-selector', function() {
-
-		 fn_loadAddActive();
-		
-		
-		var group = $(this).closest('[data-group]').data('group');
-		var selectedFields = [];
-		var isDuplicate = false;
-		
-
-		// 타불 객체 가져오기
-		var $objTabul = fn_utils_getTabulator();
-
-		console.log('$objTabul : ', $objTabul);
-		
-		if($objTabul.getData().length < 1){
-			alert('데이터 입력 후 선택해 주세요.');
-			$(this).val(""); 
-			fn_loadRemoveActive();
-			return false;
-		}
-		
-		// 중복체크
-		$('[data-group="' + group + '"] .field-selector').each(function() {
-			var selectedField = $(this).val();
-			if (selectedField) {
-				if (selectedFields.includes(selectedField)) {
-					alert("중복된 필드를 선택할 수 없습니다.");
-					$(this).val(""); // 중복 필드를 선택한 경우 빈 값으로 초기화
-					isDuplicate = true;
-					return false; // 반복문 종료
-				}
-				selectedFields.push(selectedField);
-			}
-		});
-
-
-		// 데이터 넣기
-		updateTableFields($objTabul, group);
-		
-		// 필드가 휴대폰이면 열 중복체크
-		if($(this).val() == 'addrPhoneNo'){
-			fn_phoneDupl($objTabul);
-		}
-		fn_loadRemoveActive();
-		
-	});
-
-
-	 /**
-	  * @ 핸드폰 중복 데이터
-	  * */
-	 function fn_phoneDupl($objTabul) {
-		 
-		$tableError.clearData();
-
-		var tabulNm = fn_utils_getTabulatorNm();
-		var tabluC = '.'+tabulNm
-		 
-		var data = $objTabul.getData();
-		var phoneNumberChk = false;
-	    var existingNumbers = new Set(); // 배열에서 Set으로 변경
-
-		let errorCount = 0; // 중복 번호 개수를 저장할 변수
-		let duplicateCount = 0; // 중복 번호 개수를 저장할 변수
-
-		const errors = [];  // 오류 데이터를 저장할 배열
-		const duplicates = [];  // 오류 데이터를 저장할 배열
-		const newData = []; // 유효한 데이터만 저장할 새로운 배열
-
-		data.forEach((row, index) => {
-//		    if (index % 10000 === 0) {
-//		        console.log('i : ', index);
-//		    }
-	
-			const number = row.addrPhoneNo;
-			const formattedNumber = formatPhoneNumber(number); // 번호 표준화
-			const cleanedNumber = formattedNumber.replace(/[^0-9]/g, ''); // 숫자만 남김
-			
-			if (!existingNumbers.has(cleanedNumber)) { // 중복 번호 체크
-				if (isValidPhoneNumber(formattedNumber)) { // 유효성 검사
-					row.addrPhoneNo = formattedNumber;
-					existingNumbers.add(cleanedNumber); // 추가된 번호를 기존 목록에 추가
-					newData.push(row); // 유효한 데이터만 새로운 배열에 추가
-				} else {
-				// 오류: 유효성 통과 못함
-				errorCount++;
-				
-				errors.push({ 
-					name: row.addrNm, // 이름
-					phone: row.addrPhoneNo, // 폰번호
-					result: "오류" // 결과 메시지 추가
-				});
-				}
-			} else {
-				// 중복
-				duplicateCount++;
-				
-				errors.push({ 
-					name: row.addrNm, // 이름
-					phone: row.addrPhoneNo, // 폰번호
-					result: "중복" // 결과 메시지 추가
-				});
-			}
-		});
-
-		// data 배열을 newData 배열로 대체
-		data = newData;
-
-	    // 중복 카운트
-	    $(tabluC+" #rowDupCnt").text(duplicateCount);
-	    // 에러 카운트
-	    $(tabluC+" #rowErrorCnt").text(errorCount);
-
-	    // popup 영역
-	    // 중복 카운트
-	    $("#errorPopDupCnt").text(duplicateCount);
-	    // 에러 카운트
-	    $("#errorPopErrorCnt").text(errorCount);
-	    // 
-//	    $("#errorPopTotCnt").text(duplicateCount+errorCount);
-	    
-		// 수정된 데이터로 테이블 업데이트
-		$objTabul.setData(data);
-
-		// 중복 번호 개수를 #rowDupCnt 요소에 표시
-		$("#rowDupCnt").text(duplicateCount);
-
-	    $(tabluC+" #rowTotCnt").text($objTabul.getDataCount());
-	    $("#errorPopTotCnt").text($objTabul.getDataCount());
-	    
-	    var errorData = errors.concat(duplicates);
-		 // 오류 및 중복 데이터를 한 번에 추가
-	    $tableError.setData(errorData);
-	    
-	    if(errorCount > 0){
-	    	alert('휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.\nex) 발송불가 특수문자, 자릿수 오류 등');
-	    }
-
-	    
-
-	}
-	 /*
-	function fn_phoneDupl_old($objTabul) {
-	    var data = $objTabul.getData();
-	    var uniquePhones = new Set();
-	    var rowsToKeep = [];
-	    var rowsToDelete = [];
-	    var phoneNumberChk = false;
-
-
-		var tabulNm = fn_utils_getTabulatorNm();
-		var tabluC = '.'+tabulNm
-	    
-	    data.forEach((row, index) => {
-
-	        if (!isValidKoreanPhoneNumber(row.addrPhoneNo)) {
-	        	phoneNumberChk = true
-	        	return false;
-	        }
-	    	
-	        if (uniquePhones.has(row.addrPhoneNo)) {
-	            rowsToDelete.push(index); // 중복된 행의 인덱스를 기록
-	        } else {
-	            uniquePhones.add(row.addrPhoneNo);
-	            rowsToKeep.push(row); // 고유한 데이터만 추가
-	        }
-	    });
-	    
-	    if(phoneNumberChk){
-	    	alert('휴대폰 형식에 맞지 않는 데이터가 있습니다.\n 확인해 주세요');
-	    }
-
-
-
-	    // 중복된 행 삭제
-	    rowsToDelete.reverse().forEach(index => {
-	        $objTabul.deleteRow(index);
-	    });
-
-	    // 고유한 데이터만 남기고 테이블 업데이트
-	    $objTabul.setData(rowsToKeep);
-	    $(tabluC+" #rowTotCnt").text(rowsToKeep.length);
-	}*/
-
-	//받는사람 전체삭제 버튼 처리
-	$('.all_del').click(function(){
-
-		var tabulNm = fn_utils_getTabulatorNm();
-		var tabluC = '.'+tabulNm
-		
-		var $objTabul = fn_utils_getTabulator();
-		
-		$objTabul.clearData();
-		fn_rowCntInit();
-
-		// select box 초기화
-		$('.field-selector').each(function() { $(this).val(''); });
-	});
-
-	// 받는사람 선택삭제 버튼 처리해주기
-	$('.select_del').click(function(){
-
-		var tabulNm = fn_utils_getTabulatorNm();
-		var tabluC = '.'+tabulNm
-
-		var $objTabul = fn_utils_getTabulator();
-		
-		$(tabluC+" #rowDupCnt").text(0); //중복건수 수정
-		var selectedData = $objTabul.getSelectedRows();
-		
-		if(selectedData == "" || selectedData == null){
-			alert("삭제할 데이터를 선택해 주세요.");
-			return false;
-		}else{ // 선택한 Row 데이터 삭제하기
-			for(var i=0; i < selectedData.length; i++){
-				selectedData[i].delete();
-			}
-		}
-		
-		totRows = $objTabul.getRows().length;
-	    
-		updateTotCnt(totRows);
-	});
-	
-
-	//받는사람 전체삭제 버튼 처리
-	$('.self_all_del').click(function(){
-
-		var tabulNm = fn_utils_getTabulatorNm();
-		var tabluC = '.'+tabulNm
-		
-		var $objTabul = fn_utils_getTabulator();
-		
-	    // 초기화 및 데이터 추가를 한번에 처리
-	    var newTableData = [];
-	    
-	    // 1000개의 빈 행을 미리 준비
-	    for (var i = 0; i < 1000; i++) {
-	    	newTableData.push({
-				addrNm: "", 
-				addrPhoneNo: "", 
-				addrInfo1: "", 
-				addrInfo2: "", 
-				addrInfo3: "", 
-				addrInfo4: "", 
-				addrComment: ""
-	        });
-	    }
-	    
-	    // 기존 데이터 초기화 후, 새로운 데이터를 한 번에 추가
-	    $objTabul.setData(newTableData);
-	    
-	    // 행 수 초기화 함수 호출
-	    fn_rowCntInit();
-	});
-	
-	// 직접입력 받는사람 선택삭제 버튼 처리해주기
-	$('.self_select_del').click(function(){
-		
-		var tabulNm = fn_utils_getTabulatorNm();
-		var tabluC = '.'+tabulNm
-		
-		var $objTabul = fn_utils_getTabulator();
-		
-		$(tabluC+" #rowDupCnt").text(0); //중복건수 수정
-		var selectedData = $objTabul.getSelectedRows();
-		
-		if(selectedData == "" || selectedData == null){
-			alert("삭제할 데이터를 선택해 주세요.");
-			return false;
-		}else{ // 선택한 Row 데이터 삭제하기
-			for(var i=0; i < selectedData.length; i++){
-				selectedData[i].delete();
-			}
-		}
-	    
-	    // 남은 행 수 계산
-	    var totRows = $objTabul.getRows().length;
-
-	    // 1000개 행이 되도록 나머지 행 생성
-	    for (var i = totRows; i < 1000; i++) {
-	        $objTabul.addRow({addrNm: "", addrPhoneNo: "", addrInfo1: "", addrInfo2: "", addrInfo3: "", addrInfo4: "", addrComment: ""});
-	    }
-
-
-	    var existingNumbers = []; // 중복 번호를 저장할 배열
-		// 모든 행의 'addrPhoneNo' 값을 배열에 추가
-		var allRows = $tableSelf.getData(); // 테이블의 모든 데이터를 가져옴
-		allRows.forEach(function(row) {
-			if (row.addrPhoneNo) {
-				const cleanedExistingNumber = row.addrPhoneNo.replace(/[^0-9]/g, ''); // 숫자만 남김
-				existingNumbers.push(cleanedExistingNumber); // 기존 번호를 배열에 추가
-			}
-		});
-		updateTotCnt(existingNumbers.length);
-	});
-		
-	//전체 데이터 갯수 구하는 함수
-	function updateTotCnt(data){
-
-		var tabulNm = fn_utils_getTabulatorNm();
-		var tabluC = '.'+tabulNm
-		
-		$(tabluC+" #rowTotCnt").text(data);
-
-	}
-		
-	/* 
-	* 타이틀 select 선택할때마다 실행해서         
-	* 데이터테이블 필드값 수정                  
-	*/
-	function updateTableFields($objTabul, group) {
-		// 데이터가져오기
-		var currentData = $objTabul.getData();
-		
-		// 필드 초기 값 셋팅
-		var columns = [
-			{formatter: "rowSelection", titleFormatter: "rowSelection", clipboard: false, hozAlign: "center", headerHozAlign: "center", headerSort: false, cellClick: function(e, cell) {
-				cell.getRow().toggleSelect();
-			}}
-			,{formatter:"rownum", align:"center", title:"No", hozAlign:"center", headerHozAlign:"center", width:40}
-		];
-
-		var fieldMapping = [];
-		// 초기 후 필드 값 셋팅하기
-		$('[data-group="' + group + '"] .field-selector').each(function(index) {
-			var selectedField = $(this).val();
-			//  ASCII 문자 코드 사용 - 65=A, 66=B ...
-			var field = String.fromCharCode(65 + index);
-			if (selectedField) {
-				columns.push({
-					title: field
-					, field: selectedField
-					, hozAlign: "center"
-					, headerHozAlign: "center"
-//					, editor: "input"
-					, editor: false
-					, width: 125
-					, validator: ["maxLength:100", "string"]
-				});
-				fieldMapping.push(selectedField);
-			} else {
-				columns.push({
-					title: field
-					, field: field
-					, hozAlign: "center"
-					, headerHozAlign: "center"
-//					, editor: "input"
-					, editor: false
-					, width: 125
-					, validator: ["maxLength:100", "string"]
-				});
-				fieldMapping.push(field);
-			}
-		});
-
-		// 데이터 셋팅
-		var updatedData = currentData.map(row => {
-			var newRow = {};
-			fieldMapping.forEach((field, index) => {
-				newRow[field] = row[Object.keys(row)[index]] || "";
-			});
-			return newRow;
-		});
-
-		$objTabul.setColumns(columns);
-		$objTabul.setData(updatedData);
-	}
-}); 
-
-
-
-
-// 주소록 에러결과 초기화
-function fn_errorPopClean(){
-
-	var tabulNm = fn_utils_getTabulatorNm();
-	var tabluC = '.'+tabulNm
-
-    // popup 영역
-	$tableError.clearData();
-	
-
-    // 중복 카운트
-    $("#errorPopDupCnt").text(0);
-    // 에러 카운트
-    $("#errorPopErrorCnt").text(0);
-    // 
-    $("#errorPopTotCnt").text(0);
-
-	// select box 초기화
-	$(tabluC+' .field-selector').each(function() { $(this).val(''); });
-	
-}
-
-function fn_rowCntInit(){
-
-	var tabulNm = fn_utils_getTabulatorNm();
-	var tabluC = '.'+tabulNm
-	
-	$(tabluC+" #rowTotCnt").text(0); //총건수 수정
-	$(tabluC+" #rowDupCnt").text(0); //중복건수 수정
-	$(tabluC+" #rowErrorCnt").text(0); //중복건수 수정
-}
-
-
-
-//1. 필드 초기화 함수
-function resetTableFieldsToDefault() {
-
-	// 타불 객체 가져오기
-	var $objTabul = fn_utils_getTabulator();
-	
-	// 필드를 A, B, C, D로 초기화
-	var defaultFields = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
-
-	// 테이블의 기존 데이터를 가져옵니다.
-	var currentData = $objTabul.getData();
-
-	// 초기 필드(A, B, C, D 등)를 위한 열 설정
-	var columns = [
-		{formatter: "rowSelection", titleFormatter: "rowSelection", clipboard: false, hozAlign: "center", headerHozAlign: "center", headerSort: false, cellClick: function(e, cell) {
-			cell.getRow().toggleSelect();
-		}},
-		{formatter:"rownum", align:"center", title:"No", hozAlign:"center", headerHozAlign:"center", width:40}
-	];
-
-	// 기본 필드로 열 구성
-	defaultFields.forEach(field => {
-		columns.push({
-			title: field,
-			field: field,
-			hozAlign: "center",
-			headerHozAlign: "center",
-			editor: false, // 편집 비활성화
-			width: 125,
-			validator: ["maxLength:100", "string"]
-		});
-	});
-
-	// 테이블을 기본 필드로 업데이트
-	$objTabul.setColumns(columns);
-//	$objTabul.setData(updatedData);
-}
-
-
-
+
+
+$(document).ready(function(){
+
+	
+	//타이틀 select 선택 이벤트
+	 $('[data-group]').on('change', '.field-selector', function() {
+
+		 fn_loadAddActive();
+		
+		
+		var group = $(this).closest('[data-group]').data('group');
+		var selectedFields = [];
+		var isDuplicate = false;
+		
+
+		// 타불 객체 가져오기
+		var $objTabul = fn_utils_getTabulator();
+
+		console.log('$objTabul : ', $objTabul);
+		
+		if($objTabul.getData().length < 1){
+			alert('데이터 입력 후 선택해 주세요.');
+			$(this).val(""); 
+			fn_loadRemoveActive();
+			return false;
+		}
+		
+		// 중복체크
+		$('[data-group="' + group + '"] .field-selector').each(function() {
+			var selectedField = $(this).val();
+			if (selectedField) {
+				if (selectedFields.includes(selectedField)) {
+					alert("중복된 필드를 선택할 수 없습니다.");
+					$(this).val(""); // 중복 필드를 선택한 경우 빈 값으로 초기화
+					isDuplicate = true;
+					return false; // 반복문 종료
+				}
+				selectedFields.push(selectedField);
+			}
+		});
+
+
+		// 데이터 넣기
+		updateTableFields($objTabul, group);
+		
+		// 필드가 휴대폰이면 열 중복체크
+		if($(this).val() == 'addrPhoneNo'){
+			fn_phoneDupl($objTabul);
+		}
+		fn_loadRemoveActive();
+		
+	});
+
+
+	 /**
+	  * @ 핸드폰 중복 데이터
+	  * */
+	 function fn_phoneDupl($objTabul) {
+		 
+		$tableError.clearData();
+
+		var tabulNm = fn_utils_getTabulatorNm();
+		var tabluC = '.'+tabulNm
+		 
+		var data = $objTabul.getData();
+		var phoneNumberChk = false;
+	    var existingNumbers = new Set(); // 배열에서 Set으로 변경
+
+		let errorCount = 0; // 중복 번호 개수를 저장할 변수
+		let duplicateCount = 0; // 중복 번호 개수를 저장할 변수
+
+		const errors = [];  // 오류 데이터를 저장할 배열
+		const newData = []; // 유효한 데이터만 저장할 새로운 배열
+
+		data.forEach((row, index) => {
+	
+			const number = row.addrPhoneNo;
+
+	        // number가 null, undefined, 빈 문자열이거나 숫자인 경우 처리
+	        if (!number || (typeof number === 'string' && !number.trim())){
+	        	console.log("number : ", number);
+	        	 return;
+	        }
+			
+			const formattedNumber = formatPhoneNumber(number); // 번호 표준화
+			const cleanedNumber = formattedNumber.replace(/[^0-9]/g, ''); // 숫자만 남김
+			
+			if (!existingNumbers.has(cleanedNumber)) { // 중복 번호 체크
+				if (isValidPhoneNumber(formattedNumber)) { // 유효성 검사
+					row.addrPhoneNo = formattedNumber;
+					existingNumbers.add(cleanedNumber); // 추가된 번호를 기존 목록에 추가
+					newData.push(row); // 유효한 데이터만 새로운 배열에 추가
+				} else {
+					// 오류: 유효성 통과 못함
+					errorCount++;
+					
+					errors.push({ 
+						name: row.addrNm, // 이름
+						phone: row.addrPhoneNo, // 폰번호
+						result: "오류" // 결과 메시지 추가
+					});
+				}
+			} else {
+				// 중복
+				duplicateCount++;
+				
+				errors.push({ 
+					name: row.addrNm, // 이름
+					phone: row.addrPhoneNo, // 폰번호
+					result: "중복" // 결과 메시지 추가
+				});
+			}
+		});
+
+		// data 배열을 newData 배열로 대체
+		data = newData;
+		
+		// 수정된 데이터로 테이블 업데이트
+		$objTabul.setData(data);
+
+	    $(tabluC+" #rowTotCnt").text($objTabul.getDataCount());
+	    // 중복 카운트
+	    $(tabluC+" #rowDupCnt").text(duplicateCount);
+	    // 에러 카운트
+	    $(tabluC+" #rowErrorCnt").text(errorCount);
+
+	    // popup 영역
+	    $("#errorPopTotCnt").text($objTabul.getDataCount());
+	    // 중복 카운트
+	    $("#errorPopDupCnt").text(duplicateCount);
+	    // 에러 카운트
+	    $("#errorPopErrorCnt").text(errorCount);
+	    // 
+//	    $("#errorPopTotCnt").text(duplicateCount+errorCount);
+
+	    
+		 // 오류 및 중복 데이터를 한 번에 추가
+	    $tableError.setData(errors);
+	    
+	    if(errorCount > 0){
+	    	alert('휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.\nex) 발송불가 특수문자, 자릿수 오류 등');
+	    }
+
+	    
+
+	}
+	 /*
+	function fn_phoneDupl_old($objTabul) {
+	    var data = $objTabul.getData();
+	    var uniquePhones = new Set();
+	    var rowsToKeep = [];
+	    var rowsToDelete = [];
+	    var phoneNumberChk = false;
+
+
+		var tabulNm = fn_utils_getTabulatorNm();
+		var tabluC = '.'+tabulNm
+	    
+	    data.forEach((row, index) => {
+
+	        if (!isValidKoreanPhoneNumber(row.addrPhoneNo)) {
+	        	phoneNumberChk = true
+	        	return false;
+	        }
+	    	
+	        if (uniquePhones.has(row.addrPhoneNo)) {
+	            rowsToDelete.push(index); // 중복된 행의 인덱스를 기록
+	        } else {
+	            uniquePhones.add(row.addrPhoneNo);
+	            rowsToKeep.push(row); // 고유한 데이터만 추가
+	        }
+	    });
+	    
+	    if(phoneNumberChk){
+	    	alert('휴대폰 형식에 맞지 않는 데이터가 있습니다.\n 확인해 주세요');
+	    }
+
+
+
+	    // 중복된 행 삭제
+	    rowsToDelete.reverse().forEach(index => {
+	        $objTabul.deleteRow(index);
+	    });
+
+	    // 고유한 데이터만 남기고 테이블 업데이트
+	    $objTabul.setData(rowsToKeep);
+	    $(tabluC+" #rowTotCnt").text(rowsToKeep.length);
+	}*/
+
+	//받는사람 전체삭제 버튼 처리
+	$('.all_del').click(function(){
+
+		var tabulNm = fn_utils_getTabulatorNm();
+		var tabluC = '.'+tabulNm
+		
+		var $objTabul = fn_utils_getTabulator();
+		
+		$objTabul.clearData();
+		fn_rowCntInit();
+
+		// select box 초기화
+		$('.field-selector').each(function() { $(this).val(''); });
+	});
+
+	// 받는사람 선택삭제 버튼 처리해주기
+	$('.select_del').click(function(){
+
+		var tabulNm = fn_utils_getTabulatorNm();
+		var tabluC = '.'+tabulNm
+
+		var $objTabul = fn_utils_getTabulator();
+		
+		$(tabluC+" #rowDupCnt").text(0); //중복건수 수정
+		var selectedData = $objTabul.getSelectedRows();
+		
+		if(selectedData == "" || selectedData == null){
+			alert("삭제할 데이터를 선택해 주세요.");
+			return false;
+		}else{ // 선택한 Row 데이터 삭제하기
+			for(var i=0; i < selectedData.length; i++){
+				selectedData[i].delete();
+			}
+		}
+		
+		totRows = $objTabul.getRows().length;
+	    
+		updateTotCnt(totRows);
+	});
+	
+
+	//받는사람 전체삭제 버튼 처리
+	$('.self_all_del').click(function(){
+
+		var tabulNm = fn_utils_getTabulatorNm();
+		var tabluC = '.'+tabulNm
+		
+		var $objTabul = fn_utils_getTabulator();
+		
+	    // 초기화 및 데이터 추가를 한번에 처리
+	    var newTableData = [];
+	    
+	    // 1000개의 빈 행을 미리 준비
+	    for (var i = 0; i < 1000; i++) {
+	    	newTableData.push({
+				addrNm: "", 
+				addrPhoneNo: "", 
+				addrInfo1: "", 
+				addrInfo2: "", 
+				addrInfo3: "", 
+				addrInfo4: "", 
+				addrComment: ""
+	        });
+	    }
+	    
+	    // 기존 데이터 초기화 후, 새로운 데이터를 한 번에 추가
+	    $objTabul.setData(newTableData);
+	    
+	    // 행 수 초기화 함수 호출
+	    fn_rowCntInit();
+	});
+	
+	// 직접입력 받는사람 선택삭제 버튼 처리해주기
+	$('.self_select_del').click(function(){
+		
+		var tabulNm = fn_utils_getTabulatorNm();
+		var tabluC = '.'+tabulNm
+		
+		var $objTabul = fn_utils_getTabulator();
+		
+		$(tabluC+" #rowDupCnt").text(0); //중복건수 수정
+		var selectedData = $objTabul.getSelectedRows();
+		
+		if(selectedData == "" || selectedData == null){
+			alert("삭제할 데이터를 선택해 주세요.");
+			return false;
+		}else{ // 선택한 Row 데이터 삭제하기
+			for(var i=0; i < selectedData.length; i++){
+				selectedData[i].delete();
+			}
+		}
+	    
+	    // 남은 행 수 계산
+	    var totRows = $objTabul.getRows().length;
+
+	    // 1000개 행이 되도록 나머지 행 생성
+	    for (var i = totRows; i < 1000; i++) {
+	        $objTabul.addRow({addrNm: "", addrPhoneNo: "", addrInfo1: "", addrInfo2: "", addrInfo3: "", addrInfo4: "", addrComment: ""});
+	    }
+
+
+	    var existingNumbers = []; // 중복 번호를 저장할 배열
+		// 모든 행의 'addrPhoneNo' 값을 배열에 추가
+		var allRows = $tableSelf.getData(); // 테이블의 모든 데이터를 가져옴
+		allRows.forEach(function(row) {
+			if (row.addrPhoneNo) {
+				const cleanedExistingNumber = row.addrPhoneNo.replace(/[^0-9]/g, ''); // 숫자만 남김
+				existingNumbers.push(cleanedExistingNumber); // 기존 번호를 배열에 추가
+			}
+		});
+		updateTotCnt(existingNumbers.length);
+	});
+		
+	//전체 데이터 갯수 구하는 함수
+	function updateTotCnt(data){
+
+		var tabulNm = fn_utils_getTabulatorNm();
+		var tabluC = '.'+tabulNm
+		
+		$(tabluC+" #rowTotCnt").text(data);
+
+	}
+		
+	/* 
+	* 타이틀 select 선택할때마다 실행해서         
+	* 데이터테이블 필드값 수정                  
+	*/
+	function updateTableFields($objTabul, group) {
+		// 데이터가져오기
+		var currentData = $objTabul.getData();
+		
+		// 필드 초기 값 셋팅
+		var columns = [
+			{formatter: "rowSelection", titleFormatter: "rowSelection", clipboard: false, hozAlign: "center", headerHozAlign: "center", headerSort: false, cellClick: function(e, cell) {
+				cell.getRow().toggleSelect();
+			}}
+			,{formatter:"rownum", align:"center", title:"No", hozAlign:"center", headerHozAlign:"center", width:40}
+		];
+
+		var fieldMapping = [];
+		// 초기 후 필드 값 셋팅하기
+		$('[data-group="' + group + '"] .field-selector').each(function(index) {
+			var selectedField = $(this).val();
+			//  ASCII 문자 코드 사용 - 65=A, 66=B ...
+			var field = String.fromCharCode(65 + index);
+			if (selectedField) {
+				columns.push({
+					title: field
+					, field: selectedField
+					, hozAlign: "center"
+					, headerHozAlign: "center"
+//					, editor: "input"
+					, editor: false
+					, width: 125
+					, validator: ["maxLength:100", "string"]
+				});
+				fieldMapping.push(selectedField);
+			} else {
+				columns.push({
+					title: field
+					, field: field
+					, hozAlign: "center"
+					, headerHozAlign: "center"
+//					, editor: "input"
+					, editor: false
+					, width: 125
+					, validator: ["maxLength:100", "string"]
+				});
+				fieldMapping.push(field);
+			}
+		});
+
+		// 데이터 셋팅
+		var updatedData = currentData.map(row => {
+			var newRow = {};
+			fieldMapping.forEach((field, index) => {
+				newRow[field] = row[Object.keys(row)[index]] || "";
+			});
+			return newRow;
+		});
+
+		$objTabul.setColumns(columns);
+		$objTabul.setData(updatedData);
+	}
+}); 
+
+
+
+
+// 주소록 에러결과 초기화
+function fn_errorPopClean(){
+
+	var tabulNm = fn_utils_getTabulatorNm();
+	var tabluC = '.'+tabulNm
+
+    // popup 영역
+	$tableError.clearData();
+	
+
+    // 중복 카운트
+    $("#errorPopDupCnt").text(0);
+    // 에러 카운트
+    $("#errorPopErrorCnt").text(0);
+    // 
+    $("#errorPopTotCnt").text(0);
+
+	// select box 초기화
+	$(tabluC+' .field-selector').each(function() { $(this).val(''); });
+	
+}
+
+function fn_rowCntInit(){
+
+	var tabulNm = fn_utils_getTabulatorNm();
+	var tabluC = '.'+tabulNm
+	
+	$(tabluC+" #rowTotCnt").text(0); //총건수 수정
+	$(tabluC+" #rowDupCnt").text(0); //중복건수 수정
+	$(tabluC+" #rowErrorCnt").text(0); //중복건수 수정
+}
+
+
+
+//1. 필드 초기화 함수
+function resetTableFieldsToDefault() {
+
+	// 타불 객체 가져오기
+	var $objTabul = fn_utils_getTabulator();
+	
+	// 필드를 A, B, C, D로 초기화
+	var defaultFields = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
+
+	// 테이블의 기존 데이터를 가져옵니다.
+	var currentData = $objTabul.getData();
+
+	// 초기 필드(A, B, C, D 등)를 위한 열 설정
+	var columns = [
+		{formatter: "rowSelection", titleFormatter: "rowSelection", clipboard: false, hozAlign: "center", headerHozAlign: "center", headerSort: false, cellClick: function(e, cell) {
+			cell.getRow().toggleSelect();
+		}},
+		{formatter:"rownum", align:"center", title:"No", hozAlign:"center", headerHozAlign:"center", width:40}
+	];
+
+	// 기본 필드로 열 구성
+	defaultFields.forEach(field => {
+		columns.push({
+			title: field,
+			field: field,
+			hozAlign: "center",
+			headerHozAlign: "center",
+			editor: false, // 편집 비활성화
+			width: 125,
+			validator: ["maxLength:100", "string"]
+		});
+	});
+
+	// 테이블을 기본 필드로 업데이트
+	$objTabul.setColumns(columns);
+//	$objTabul.setData(updatedData);
+}
+
+
+
src/main/webapp/js/web/addr/init.js
--- src/main/webapp/js/web/addr/init.js
+++ src/main/webapp/js/web/addr/init.js
@@ -158,7 +158,6 @@
 	$tableExcel.on("columnWidth",function(column){
 		var titleIndex = titleArray.indexOf(column._column.definition.title);
 		titleIndex += 1;
-		console.log(titleIndex)
 		if(titleIndex != 0){
 			$('.tableExcel .select_adr_hd>div').eq(titleIndex).css('width', column._column.width);
 		}else{
@@ -181,7 +180,6 @@
 	$tableClip.on("columnWidth",function(column){
 		var titleIndex = titleArray.indexOf(column._column.definition.title);
 		titleIndex += 1;
-		console.log(titleIndex)
 		if(titleIndex != 0){
 			$('.tableClip .select_adr_hd>div').eq(titleIndex).css('width', column._column.width);
 		}else{
Add a comment
List