이호영 이호영 2025-03-25
Merge branch '4786' into advc
@10fb1c7542f8290760360e1702ff380197e85def
pom.xml
--- pom.xml
+++ pom.xml
@@ -144,11 +144,12 @@
 			<version>1.1.2</version>
 		</dependency>
 
-		<dependency>
-			<groupId>cglib</groupId>
-			<artifactId>cglib</artifactId>
-			<version>3.1</version>
-		</dependency>
+        <!-- https://mvnrepository.com/artifact/cglib/cglib -->
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+            <version>3.3.0</version>
+        </dependency>
 
 		<dependency>
 			<groupId>org.antlr</groupId>
src/main/java/itn/com/cmm/util/MsgSendUtils.java
--- src/main/java/itn/com/cmm/util/MsgSendUtils.java
+++ src/main/java/itn/com/cmm/util/MsgSendUtils.java
@@ -23,6 +23,7 @@
 import itn.com.cmm.OptimalMsgResultDTO;
 import itn.let.mail.service.StatusResponse;
 import itn.let.mjo.event.service.MjonEventVO;
+import itn.let.mjo.mjocommon.MjonCommon;
 import itn.let.mjo.msg.service.MjonMsgVO;
 import itn.let.mjo.msgagent.service.MjonMsgAgentStsVO;
 import itn.let.mjo.spammsg.web.ComGetSpamStringParser;
@@ -55,26 +56,6 @@
 	// 이벤트 최저 잔액
 	public static final double MIN_EVENT_REMAIN_CASH = 7.5; // 이벤트 최소 잔액
 	
-	/** 
-	 * @methodName	: getSmsTxtBytes 
-	 * @author		: 이호영
-	 * @date		: 2024.09.23 
-	 * @description	: sms 텍스트 바이트 계산 후 return;
-	 * @param smsTxt
-	 * @return
-	 * @throws UnsupportedEncodingException 
-	 */
-	public static int getSmsTxtBytes(String smsTxt) throws UnsupportedEncodingException {        	//문자열 길이 체크 해주기
-		int smsBytes = 0;
-		//문자 바이트 계산에 필요한 캐릭터 셋 : 한글 2Byte로 계산
-		String charset = "euc-kr"; 						
-		if(StringUtils.isNotEmpty(smsTxt)) {
-			String smsCont = smsTxt.replace("\r\n", "\n");
-			smsBytes = smsCont.getBytes(charset).length;
-		}
-//		log.info(" + smsBytes :: [{}]", smsBytes);
-		return smsBytes;
-	}
 
 	/** 
 	 * @methodName	: getMsgType 
@@ -96,7 +77,7 @@
 		//	    msgType = "4";
 		//	}
 			
-		int smsTxtByte = getSmsTxtBytes(p_smsTxt);
+		int smsTxtByte = MjonCommon.getSmsTxtBytes(p_smsTxt);
 		String msgType = SHORT_MSG_TYPE;
 	
 		// 1. 2000 Byte 초과는 에러 처리
@@ -648,7 +629,7 @@
 			// 각 가격을 합산
 			totalPrice += Float.parseFloat(eachPrice);
 		}
-
+		mjonMsgVO.setTotalPrice(totalPrice);
 		
 	}
 	
 
src/main/java/itn/com/cmm/util/SlackMessageFormatUtil.java (added)
+++ src/main/java/itn/com/cmm/util/SlackMessageFormatUtil.java
@@ -0,0 +1,144 @@
+package itn.com.cmm.util;
+
+import org.apache.commons.lang3.StringUtils;
+
+import itn.let.kakao.kakaoComm.KakaoVO;
+import itn.let.mjo.msg.service.MjonMsgVO;
+
+public class SlackMessageFormatUtil {
+	
+	private static final String PREFIX_SMISHING = "[스미싱의심]";
+	private static final String PREFIX_RESERVE = "[예약]";
+	private static final String PREFIX_IMAGE = "그림문자 ";
+
+	/**
+	 * 일반 SMS 메시지 텍스트 포맷팅
+	 */
+	public static String formatSmsText(MjonMsgVO mjonMsgVO) {
+		String smsTxt = mjonMsgVO.getSmsTxt();
+		String reserveYn = safeGetString(mjonMsgVO.getReserveYn());
+		String delayYn = safeGetString(mjonMsgVO.getDelayYn());
+		String smishingYn = safeGetString(mjonMsgVO.getSmishingYn());
+		
+		// 공통 텍스트 포맷팅 로직 적용
+		smsTxt = formatMessagePrefix(smsTxt, reserveYn, 
+					"Y".equals(smishingYn) || "Y".equals(delayYn));
+		
+		// 그림 문자 처리 (SMS 전용 로직)
+		int fileCount = parseIntOrDefault(mjonMsgVO.getFileCnt(), 0);
+		if ("6".equals(mjonMsgVO.getMsgType()) && fileCount > 0 && StringUtils.isEmpty(smsTxt)) {
+		    smsTxt = "그림문자 " + smsTxt;
+		}
+		
+		return smsTxt;
+	}
+	
+	/**
+	 * 카카오톡 메시지 텍스트 포맷팅
+	 */
+	public static String formatKakaoText(KakaoVO kakaoVO) {
+		String smsTxt = kakaoVO.getTemplateContent();
+		String reserveYn = safeGetString(kakaoVO.getReserveYn());
+		String atDelayYn = safeGetString(kakaoVO.getAtDelayYn());
+		
+		// 공통 텍스트 포맷팅 로직 적용
+		return formatMessagePrefix(smsTxt, reserveYn, "Y".equals(atDelayYn));
+	}
+	
+	
+	public static String formatSandName(MjonMsgVO mjonMsgVO) {
+		String userId = mjonMsgVO.getUserId();
+		String callFrom = mjonMsgVO.getCallFrom();
+		String msgType = getMessageTypeLabel(mjonMsgVO.getMsgType(), mjonMsgVO.getFileCnt());
+		return String.format("[%s][%s]%s", userId, callFrom, msgType);
+	}
+	
+	/**
+	 * 메시지 접두사 포맷팅 공통 로직 (예약 및 스미싱 의심 접두사 처리)
+	 * 
+	 * @param messageText 원본 메시지 텍스트
+	 * @param reserveYn   예약 여부
+	 * @param isSmishing  스미싱 의심 여부
+	 * @return 포맷팅된 메시지 텍스트
+	 */
+	public static String formatMessagePrefix(String messageText, String reserveYn, boolean isSmishing) {
+		if ("Y".equals(reserveYn)) {
+			return isSmishing ? PREFIX_SMISHING + PREFIX_RESERVE + messageText : PREFIX_RESERVE + messageText;
+		} else if (isSmishing) {
+			return PREFIX_SMISHING + messageText;
+		}
+		return messageText;
+	}
+
+	/**
+	 * @카카오톡용 sandName 포맷팅 메서드
+	 */
+	public static String formatKakaoSandName(KakaoVO kakaoVO) {
+		String userId = kakaoVO.getUserId();
+		String callFrom = kakaoVO.getCallFrom();
+		String msgType = getKakaoMessageTypeLabel(kakaoVO.getMsgType());
+		return String.format("[%s][%s]%s", userId, callFrom, msgType);
+	}
+	
+	/**
+	 * 메시지 타입 레이블 반환 (SMS 전용)
+	 * 
+	 * @param msgType 메시지 타입
+	 * @param fileCnt 파일 개수
+	 * @return 메시지 타입 레이블
+	 */
+	public static String getMessageTypeLabel(String msgType, String fileCnt) {
+		int fileCount = parseIntOrDefault(fileCnt, 0);
+
+		switch (msgType) {
+			case "4":
+				return "[단문]";
+			case "6":
+				return fileCount == 0 ? "[장문]" : "[그림]";
+			default:
+				return "";
+		}
+	}
+
+	/**
+	 * 카카오톡 메시지 타입 레이블 반환
+	 * 
+	 * @param msgType 메시지 타입
+	 * @return 메시지 타입 레이블
+	 */
+	public static String getKakaoMessageTypeLabel(String msgType) {
+		switch (msgType) {
+			case "8":
+				return "[알림톡]";
+			case "9":
+				return "[친구톡]";
+			default:
+				return "";
+		}
+	}
+
+	/**
+	 * 정수로 변환, 변환 실패 시 기본값 반환
+	 * 
+	 * @param value        변환할 문자열
+	 * @param defaultValue 기본값
+	 * @return 변환된 정수 또는 기본값
+	 */
+	public static int parseIntOrDefault(String value, int defaultValue) {
+		try {
+			return Integer.parseInt(value);
+		} catch (NumberFormatException e) {
+			return defaultValue;
+		}
+	}
+
+	/**
+	 * 안전하게 문자열 가져오기 (null 체크)
+	 * 
+	 * @param value 원본 문자열
+	 * @return 원본 문자열 또는 빈 문자열
+	 */
+	public static String safeGetString(String value) {
+		return value == null ? "" : value;
+	}
+}
src/main/java/itn/let/kakao/kakaoComm/KakaoButtonVO.java
--- src/main/java/itn/let/kakao/kakaoComm/KakaoButtonVO.java
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoButtonVO.java
@@ -1,5 +1,9 @@
 package itn.let.kakao.kakaoComm;
 
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
 /**
 * @FileName : KakaoButtonVO.java
 * @Project : mjon
@@ -8,6 +12,9 @@
 
 * @프로그램 설명 : button, quickReplies 변수
 */
+@ToString
+@Getter
+@Setter
 public class KakaoButtonVO {
 	
 	private String name = "";		// 버튼명 - linkType “AC” 선택 시 버튼명은 “채널추가” 로 고정
@@ -17,49 +24,5 @@
 	private String linkMo = "";		// 모바일 웹 링크 주소 (WL 사용시 필수)
 	private String linkPc = "";		// PC 웹 링크 주소 (WL 사용시 선택)
 	private String pluginId = "";	// 플러그인 ID (P1, P2, P3 사용시 필수)
-	
-	public String getName() {
-		return name;
-	}
-	public void setName(String name) {
-		this.name = name;
-	}
-	public String getLinkType() {
-		return linkType;
-	}
-	public void setLinkType(String linkType) {
-		this.linkType = linkType;
-	}
-	public String getLinkAnd() {
-		return linkAnd;
-	}
-	public void setLinkAnd(String linkAnd) {
-		this.linkAnd = linkAnd;
-	}
-	public String getLinkIos() {
-		return linkIos;
-	}
-	public void setLinkIos(String linkIos) {
-		this.linkIos = linkIos;
-	}
-	public String getLinkMo() {
-		return linkMo;
-	}
-	public void setLinkMo(String linkMo) {
-		this.linkMo = linkMo;
-	}
-	public String getLinkPc() {
-		return linkPc;
-	}
-	public void setLinkPc(String linkPc) {
-		this.linkPc = linkPc;
-	}
-	public String getPluginId() {
-		return pluginId;
-	}
-	public void setPluginId(String pluginId) {
-		this.pluginId = pluginId;
-	}
-	
 	
 }
src/main/java/itn/let/kakao/kakaoComm/KakaoCommentVO.java
--- src/main/java/itn/let/kakao/kakaoComm/KakaoCommentVO.java
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoCommentVO.java
@@ -3,6 +3,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
 /**
 * @FileName : KakaoCommentVO.java
 * @Project : mjon
@@ -11,6 +15,9 @@
 
 * @프로그램 설명 : comment 변수
 */
+@ToString
+@Getter
+@Setter
 public class KakaoCommentVO {
 	
 	private String content = "";		// 댓글 본분
@@ -26,60 +33,4 @@
 	private String originalFileName = "";
 	
 	private String filePath = "";
-
-	public String getContent() {
-		return content;
-	}
-
-	public void setContent(String content) {
-		this.content = content;
-	}
-
-	public String getCreatedAt() {
-		return createdAt;
-	}
-
-	public void setCreatedAt(String createdAt) {
-		this.createdAt = createdAt;
-	}
-
-	public String getStatus() {
-		return status;
-	}
-
-	public void setStatus(String status) {
-		this.status = status;
-	}
-
-	public String getUserName() {
-		return userName;
-	}
-
-	public void setUserName(String userName) {
-		this.userName = userName;
-	}
-
-	public String getOriginalFileName() {
-		return originalFileName;
-	}
-
-	public void setOriginalFileName(String originalFileName) {
-		this.originalFileName = originalFileName;
-	}
-
-	public String getFilePath() {
-		return filePath;
-	}
-
-	public void setFilePath(String filePath) {
-		this.filePath = filePath;
-	}
-
-	public List<KakaoCommentVO> getAttachFileList() {
-		return attachFileList;
-	}
-
-	public void setAttachFileList(List<KakaoCommentVO> attachFileList) {
-		this.attachFileList = attachFileList;
-	}
 }
src/main/java/itn/let/kakao/kakaoComm/KakaoReturnVO.java
--- src/main/java/itn/let/kakao/kakaoComm/KakaoReturnVO.java
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoReturnVO.java
@@ -4,6 +4,9 @@
 import java.util.List;
 
 import itn.com.cmm.ComDefaultVO;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
 
 /**
 * @FileName : KakaoReturnVO.java
@@ -13,6 +16,9 @@
 
 * @프로그램 설명 : 카카오톡 리턴 변수 목록
 */
+@Getter
+@Setter
+@ToString
 public class KakaoReturnVO extends ComDefaultVO{
 	
 	private static final long serialVersionUID = 1L;
@@ -130,415 +136,4 @@
 	
 	private String businessType = "";					//카카오톡 채널 비즈니스 인증 타입
 	
-	public static long getSerialversionuid() {
-		return serialVersionUID;
-	}
-
-	public String getBizReturnMsg() {
-		return bizReturnMsg;
-	}
-
-	public void setBizReturnMsg(String bizReturnMsg) {
-		this.bizReturnMsg = bizReturnMsg;
-	}
-
-	public String getBizReturnCode() {
-		return bizReturnCode;
-	}
-
-	public void setBizReturnCode(String bizReturnCode) {
-		this.bizReturnCode = bizReturnCode;
-	}
-
-	public String getProfileId() {
-		return profileId;
-	}
-
-	public void setProfileId(String profileId) {
-		this.profileId = profileId;
-	}
-
-	public String getTotalCount() {
-		return totalCount;
-	}
-
-	public void setTotalCount(String totalCount) {
-		this.totalCount = totalCount;
-	}
-
-	public String getTotalPage() {
-		return totalPage;
-	}
-
-	public void setTotalPage(String totalPage) {
-		this.totalPage = totalPage;
-	}
-
-	public String getCurrentPage() {
-		return currentPage;
-	}
-
-	public void setCurrentPage(String currentPage) {
-		this.currentPage = currentPage;
-	}
-
-	public String getSenderKey() {
-		return senderKey;
-	}
-
-	public void setSenderKey(String senderKey) {
-		this.senderKey = senderKey;
-	}
-
-	public String getSenderKeyType() {
-		return senderKeyType;
-	}
-
-	public void setSenderKeyType(String senderKeyType) {
-		this.senderKeyType = senderKeyType;
-	}
-
-	public String getTemplateCode() {
-		return templateCode;
-	}
-
-	public void setTemplateCode(String templateCode) {
-		this.templateCode = templateCode;
-	}
-
-	public String getTemplateName() {
-		return templateName;
-	}
-
-	public void setTemplateName(String templateName) {
-		this.templateName = templateName;
-	}
-
-	public String getCategoryCode() {
-		return categoryCode;
-	}
-
-	public void setCategoryCode(String categoryCode) {
-		this.categoryCode = categoryCode;
-	}
-
-	public String getCreatedAt() {
-		return createdAt;
-	}
-
-	public void setCreatedAt(String createdAt) {
-		this.createdAt = createdAt;
-	}
-
-	public String getModifiedAt() {
-		return modifiedAt;
-	}
-
-	public void setModifiedAt(String modifiedAt) {
-		this.modifiedAt = modifiedAt;
-	}
-
-	public String getServiceStatus() {
-		return serviceStatus;
-	}
-
-	public void setServiceStatus(String serviceStatus) {
-		this.serviceStatus = serviceStatus;
-	}
-
-	public List<KakaoReturnVO> getTemplatList() {
-		return templatList;
-	}
-
-	public void setTemplatList(List<KakaoReturnVO> templatList) {
-		this.templatList = templatList;
-	}
-
-	public String getUuid() {
-		return uuid;
-	}
-
-	public void setUuid(String uuid) {
-		this.uuid = uuid;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public String getStatus() {
-		return status;
-	}
-
-	public void setStatus(String status) {
-		this.status = status;
-	}
-
-	public boolean isBlock() {
-		return block;
-	}
-
-	public void setBlock(boolean block) {
-		this.block = block;
-	}
-
-	public boolean isDormant() {
-		return dormant;
-	}
-
-	public void setDormant(boolean dormant) {
-		this.dormant = dormant;
-	}
-
-	public String getTitle() {
-		return title;
-	}
-
-	public void setTitle(String title) {
-		this.title = title;
-	}
-
-	public String getDescription() {
-		return description;
-	}
-
-	public void setDescription(String description) {
-		this.description = description;
-	}
-
-	public String getImageUrl() {
-		return imageUrl;
-	}
-
-	public void setImageUrl(String imageUrl) {
-		this.imageUrl = imageUrl;
-	}
-
-	public String getListTitle() {
-		return listTitle;
-	}
-
-	public void setListTitle(String listTitle) {
-		this.listTitle = listTitle;
-	}
-
-	public String getListDescription() {
-		return listDescription;
-	}
-
-	public void setListDescription(String listDescription) {
-		this.listDescription = listDescription;
-	}
-
-	public String getSumTitle() {
-		return sumTitle;
-	}
-
-	public void setSumTitle(String sumTitle) {
-		this.sumTitle = sumTitle;
-	}
-
-	public String getSumDescription() {
-		return sumDescription;
-	}
-
-	public void setSumDescription(String sumDescription) {
-		this.sumDescription = sumDescription;
-	}
-
-	public String getProfileStatus() {
-		return profileStatus;
-	}
-
-	public void setProfileStatus(String profileStatus) {
-		this.profileStatus = profileStatus;
-	}
-
-	public boolean isAlimtalk() {
-		return alimtalk;
-	}
-
-	public void setAlimtalk(boolean alimtalk) {
-		this.alimtalk = alimtalk;
-	}
-
-	public boolean isBizchat() {
-		return bizchat;
-	}
-
-	public void setBizchat(boolean bizchat) {
-		this.bizchat = bizchat;
-	}
-
-	public boolean isBrandtalk() {
-		return brandtalk;
-	}
-
-	public void setBrandtalk(boolean brandtalk) {
-		this.brandtalk = brandtalk;
-	}
-
-	public String getCommittalCompanyName() {
-		return committalCompanyName;
-	}
-
-	public void setCommittalCompanyName(String committalCompanyName) {
-		this.committalCompanyName = committalCompanyName;
-	}
-
-	public String getChannelKey() {
-		return channelKey;
-	}
-
-	public void setChannelKey(String channelKey) {
-		this.channelKey = channelKey;
-	}
-
-	public boolean isBusinessProfile() {
-		return businessProfile;
-	}
-
-	public void setBusinessProfile(boolean businessProfile) {
-		this.businessProfile = businessProfile;
-	}
-
-	public String getBusinessType() {
-		return businessType;
-	}
-
-	public void setBusinessType(String businessType) {
-		this.businessType = businessType;
-	}
-
-	public String getTemplateMessageType() {
-		return templateMessageType;
-	}
-
-	public void setTemplateMessageType(String templateMessageType) {
-		this.templateMessageType = templateMessageType;
-	}
-
-	public String getTemplateEmphasizeType() {
-		return templateEmphasizeType;
-	}
-
-	public void setTemplateEmphasizeType(String templateEmphasizeType) {
-		this.templateEmphasizeType = templateEmphasizeType;
-	}
-
-	public String getTemplateContent() {
-		return templateContent;
-	}
-
-	public void setTemplateContent(String templateContent) {
-		this.templateContent = templateContent;
-	}
-
-	public String getTemplateExtra() {
-		return templateExtra;
-	}
-
-	public void setTemplateExtra(String templateExtra) {
-		this.templateExtra = templateExtra;
-	}
-	
-	public String getTemplateAd() {
-		return templateAd;
-	}
-
-	public void setTemplateAd(String templateAd) {
-		this.templateAd = templateAd;
-	}
-
-	public String getTemplateImageName() {
-		return templateImageName;
-	}
-
-	public void setTemplateImageName(String templateImageName) {
-		this.templateImageName = templateImageName;
-	}
-
-	public String getTemplateImageUrl() {
-		return templateImageUrl;
-	}
-
-	public void setTemplateImageUrl(String templateImageUrl) {
-		this.templateImageUrl = templateImageUrl;
-	}
-
-	public String getTemplateTitle() {
-		return templateTitle;
-	}
-
-	public void setTemplateTitle(String templateTitle) {
-		this.templateTitle = templateTitle;
-	}
-
-	public String getTemplateSubtitle() {
-		return templateSubtitle;
-	}
-
-	public void setTemplateSubtitle(String templateSubtitle) {
-		this.templateSubtitle = templateSubtitle;
-	}
-
-	public String getTemplateHeader() {
-		return templateHeader;
-	}
-
-	public void setTemplateHeader(String templateHeader) {
-		this.templateHeader = templateHeader;
-	}
-
-	public Boolean getSecurityFlag() {
-		return securityFlag;
-	}
-
-	public void setSecurityFlag(Boolean securityFlag) {
-		this.securityFlag = securityFlag;
-	}
-
-	public String getInspectionStatus() {
-		return inspectionStatus;
-	}
-
-	public void setInspectionStatus(String inspectionStatus) {
-		this.inspectionStatus = inspectionStatus;
-	}
-
-	public List<KakaoButtonVO> getButtonList() {
-		return buttonList;
-	}
-
-	public void setButtonList(List<KakaoButtonVO> buttonList) {
-		this.buttonList = buttonList;
-	}
-
-	public List<KakaoButtonVO> getQuickReplyList() {
-		return quickReplyList;
-	}
-
-	public void setQuickReplyList(List<KakaoButtonVO> quickReplyList) {
-		this.quickReplyList = quickReplyList;
-	}
-
-	public List<KakaoCommentVO> getCommentList() {
-		return commentList;
-	}
-
-	public void setCommentList(List<KakaoCommentVO> commentList) {
-		this.commentList = commentList;
-	}
-
-	public List<KakaoItemVO> getItemList() {
-		return itemList;
-	}
-
-	public void setItemList(List<KakaoItemVO> itemList) {
-		this.itemList = itemList;
-	}
 }
 
src/main/java/itn/let/kakao/kakaoComm/KakaoSendAdvcVO.java (added)
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoSendAdvcVO.java
@@ -0,0 +1,116 @@
+package itn.let.kakao.kakaoComm;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+* @FileName : KakaoSendVO.java
+* @Project : mjon
+* @Date : 2025. 3. 25.
+* @작성자 :  이호영
+
+* @프로그램 설명 : 문자온 발송부분만 ADVC
+*/
+@Getter
+@Setter
+public class KakaoSendAdvcVO implements Serializable {
+
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 343099046833205405L;
+
+	// =====
+	// Insert 데이터
+	private String msgId;				// 문자ID
+	private String msgGroupId;			// 전송그룹ID
+	private String msgGroupCnt;			// 전송그룹ID
+	private String userId;				// 사용자ID
+	private String agentCode;			// 전송사코드
+	private String senderKey;			// 발신프로필 키
+	private String templateCode;		// 템플릿 코드
+	private String callTo;				// 수신번호
+	private String callFrom;			// 발신번호
+	private String msgType;				// 메시지 타입
+	private String templateContent;		// 템플릿 내용
+	private String templateTitle;		// 템플릿 제목
+	List<KakaoButtonVO> buttonList;		// 템플릿 버튼 리스트
+	private String subMsgSendYn;		// 대체문자 전송 여부
+	private String subMsgTxt;			// 대체문자 내용
+	private String subMsgType;			// 대체문자 타입
+	private String reqDate;				// 예약일시
+	
+	private String jsonStr;				// jsonStr
+
+	// =====
+	// =====
+
+	private String eachPrice;		// sms 단가
+	private String smsPrice;		// sms 단가
+	private String mmsPrice;		// mms 단가
+	private String totPrice;		// mms 단가
+	private String befCash;		// mms 단가
+	private String befPoint;		// mms 단가
+	private String kakaoAtPrice;	// 카카오 알림톡 단가
+	private String bizJsonName;	// 카카오 알림톡 단가
+	private String reserveYn;	// 카카오 알림톡 단가
+	private String atDelayYn;	// 카카오 알림톡 단가
+	private String bizKakaoResendOrgnlTxt;	// 카카오 알림톡 단가
+	private String bizKakaoResendType;	// 카카오 알림톡 단가
+	
+	
+	
+	
+	
+	
+	@Override
+	public String toString() {
+		return "MsgSendVO[" +
+			"\n msgId=[" + msgId + "]" +
+			"\n , msgGroupId=[" + msgGroupId + "]" +
+			"\n , msgGroupCnt=[" + msgGroupCnt + "]" +
+			"\n , userId=[" + userId + "]" +
+			"\n , agentCode=[" + agentCode + "]" +
+			"\n , senderKey=[" + senderKey + "]" +
+			"\n , templateCode=[" + templateCode + "]" +
+			"\n , callTo=[" + callTo + "]" +
+			"\n , callFrom=[" + callFrom + "]" +
+			"\n , msgType=[" + msgType + "]" +
+			"\n , templateContent=[" + templateContent + "]" +
+			"\n , templateTitle=[" + templateTitle + "]" +
+			"\n , buttonList=[" + buttonList.toString() + "]" +
+			"\n , subMsgSendYn=[" + subMsgSendYn + "]" +
+			"\n , subMsgTxt=[" + subMsgTxt + "]" +
+			"\n , subMsgType=[" + subMsgType + "]" +
+			"\n , reqDate=[" + reqDate + "]" +
+			"\n , jsonStr=[" + jsonStr + "]" +
+			"\n , ==== MJ_MSG_DATA INSERT DATA END =======" +
+			"\n " +
+			"\n , eachPrice=[" + eachPrice + "]" +
+			"\n , smsPrice=[" + smsPrice + "]" +
+			"\n , mmsPrice=[" + mmsPrice + "]" +
+			"\n , totPrice=[" + totPrice + "]" +
+			"\n , befCash=[" + befCash + "]" +
+			"\n , befPoint=[" + befPoint + "]" +
+			"\n , kakaoAtPrice=[" + kakaoAtPrice + "]" +
+			"\n , bizJsonName=[" + bizJsonName + "]" +
+			"\n , reserveYn=[" + reserveYn + "]" +
+			"\n , atDelayYn=[" + atDelayYn + "]" +
+			"\n , bizKakaoResendOrgnlTxt=[" + bizKakaoResendOrgnlTxt + "]" +
+			"\n , bizKakaoResendType=[" + bizKakaoResendType + "]" +
+			"\n ]";
+	}
+
+
+
+
+
+
+
+	
+}
src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java
--- src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java
@@ -1,21 +1,38 @@
 package itn.let.kakao.kakaoComm;
 
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.annotation.Resource;
 
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Component;
 
+import egovframework.rte.fdl.idgnr.EgovIdGnrService;
 import itn.com.cmm.util.StringUtil;
 import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiJsonSave;
+import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiTemplate;
+import itn.let.mail.service.StatusResponse;
+import itn.let.mjo.mjocommon.MjonCommon;
 import itn.let.mjo.msg.service.MjonMsgVO;
 import itn.let.mjo.msgdata.service.MjonMsgDataService;
 import itn.let.mjo.spammsg.web.ComGetSpamStringParser;
+import itn.let.module.base.PriceAndPoint;
 import itn.let.sym.site.service.JoinSettingVO;
 import itn.let.uss.umt.service.MberManageVO;
+import lombok.extern.slf4j.Slf4j;
 
+@Slf4j
 @Component
 public class KakaoSendUtil {
 
@@ -24,6 +41,374 @@
 	
 	@Resource(name = "MjonMsgDataService")
 	private MjonMsgDataService mjonMsgDataService;
+	
+	@Autowired
+	KakaoApiTemplate kakaoApiTemplate;
+
+	@Autowired
+	private PriceAndPoint priceAndPoint;
+
+	@Autowired
+	private MjonCommon mjonCommon;
+	
+	// 클래스 수준에서 정적 Pattern 정의 (성능 최적화)
+	private static final Pattern REPLACEMENT_PATTERN = Pattern.compile("#\\{[^}]+\\}");
+
+	private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+	// 단문 메세지 타입
+	public static final String SHORT_MSG_TYPE = "SMS";
+	// 장문 메세지 타입
+	public static final String LONG_MSG_TYPE = "MMS";
+	
+	/**
+	 * @methodName	: populateSendLists _advc
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 7.
+	 * @description	: 기존 kakaoSendPrice 개선
+	 * @return : KakaoVO
+	 * @param kakaoVO
+	 * @param statusResponse
+	 * @return
+	 * @throws Exception
+	 * 
+	 */
+	public List<KakaoSendAdvcVO> populateSendLists(KakaoVO kakaoVO, boolean isNotified, StatusResponse statusResponse) throws Exception {
+		
+		//사용자 현재 보유 금액 불러오기(문자 발송 금액 차감 이전 금액)
+//		String befCash = kakaoVO.getBefCash();
+		
+
+		
+		
+		log.info(" +kakaoVO.getVarListMap().size() :: [{}]", kakaoVO.getVarListMap().size()); 
+		
+		List<KakaoSendAdvcVO> kakaoSendAdvcListVO = new ArrayList<>();
+		Calendar calendar = setupBaseDate(kakaoVO, isNotified);
+
+		
+		
+		KakaoReturnVO templateDetail = kakaoApiTemplate.selectKakaoApiTemplateDetail(kakaoVO);
+		String templateContent = templateDetail.getTemplateContent(); // 알림톡 템플릿
+		kakaoVO.setTemplateContent(templateContent);
+		String templateTitle = templateDetail.getTemplateTitle();
+		
+		
+//		log.info(" + templateDetail :: [{}]", templateDetail);
+//		templateDetail.getButtonList().forEach(t->log.info(" + ButtonList :: [{}]", t.toString()));
+		
+		Boolean hasContentReplacement = this.replBooleanStrChecker(templateContent);
+		Boolean hasTitleReplacement = this.replBooleanStrChecker(templateTitle);
+		Boolean hasButtonReplacement = this.needsButtonReplacement(templateDetail.getButtonList());
+
+		/** @jsonStr 필요유무 */
+		boolean hasTitleOrButtons = StringUtils.isNotEmpty(templateTitle)  
+				|| CollectionUtils.isNotEmpty(templateDetail.getButtonList());
+		
+		/** @jsonStr 반복유무 */
+		boolean needsJsonReplacement = hasTitleReplacement || hasButtonReplacement;
+		String sharedJsonStr = null;
+
+		String subMsgTxt = kakaoVO.getSubMsgTxt(); // 실패 대체 문자
+		
+		// 시스템 기본 단가 정보 불러오기
+		JoinSettingVO sysJoinSetVO = mjonMsgDataService.selectJoinSettingInfo();
+		// 사용자 개인 단가 정보 불러오기
+		MberManageVO mberManageVO = mjonMsgDataService.selectMberManageInfo(kakaoVO.getUserId());
+		
+		
+		
+
+		/** @MSGID KEY값 */
+		List<String> idList = mjonCommon.getNextCustomMsgCId(kakaoVO.getVarListMap().size());
+//		for (int i = 0; i < kakaoSendAdvcListVO.size(); i++) {
+//			kakaoSendAdvcListVO.get(i).setMsgId(idList.get(i));
+//			kakaoSendAdvcListVO.get(i).setBizJsonName(idList.get(i));
+//		}
+		
+		
+		
+		// 분할 건수 카운터
+		int counter = 0;  
+/** @Map에 총 갯수가 수신자 갯수와 동일함 */
+		List<Map<String, String>> varList = kakaoVO.getVarListMap();
+		for (int i = 0; i < varList.size(); i++) {
+//		for(Map<String, String> variables : kakaoVO.getVarListMap()) {
+			// 치환 데이터
+			Map<String, String> variables = varList.get(i);
+			
+/** @공통 기본값 */		
+			KakaoSendAdvcVO sendVO = createSendVO(kakaoVO);
+			String msgId = idList.get(i);
+			sendVO.setMsgId(msgId);
+
+			// step1
+			// Step 1-1: 값 치환 및 수신번호 셋팅
+			// Step 1-2: 수신자 정보 설정 (callToList는 항상 설정).
+			if (variables.containsKey("callToList")) {
+				sendVO.setCallTo(variables.get("callToList"));
+				variables.remove("callToList"); // 사용 후 제거.
+			}
+
+/** @Step1-3: 템플릿 치환데이터 설정 */		
+			if (hasContentReplacement) {
+				templateContent = mjonCommon.ATReplaceTemplateVariables(templateContent, variables);
+				if(hasTitleReplacement) {
+					templateTitle = mjonCommon.ATReplaceTemplateVariables(templateTitle, variables);
+				}
+			}
+/** @버튼 치환 */			// 버튼 리스트가 있으면 치환 수행, 항상 sendVO에 설정
+			List<KakaoButtonVO> buttonList = templateDetail.getButtonList();
+			if(hasButtonReplacement) {
+				buttonList = replaceButtonLinks(buttonList, variables);
+			}
+			sendVO.setButtonList(buttonList);
+			
+			sendVO.setTemplateTitle(templateTitle);
+			sendVO.setTemplateContent(templateContent);
+
+
+			// Step 1-4: 실패 대체 문자 치환데이터 설정
+			if("Y".equals(kakaoVO.getSubMsgSendYn())) { // 대체문자가 있나?
+				if ("Y".equals(kakaoVO.getSubMsgTxtReplYn())) { // 치환데이터가 있나?
+					subMsgTxt = mjonCommon.ATReplaceTemplateVariables(subMsgTxt, variables);
+				}
+				sendVO.setSubMsgTxt(subMsgTxt);// 실패 
+			}
+			sendVO.setSubMsgSendYn(kakaoVO.getSubMsgSendYn()); 
+			
+			
+			/*
+						log.info("kakaoSendAdvcVO Details: [callTo={}\n, templateContent=\n{}\n, subMsgTxt=\n{}]\n\n\n\n",
+								kakaoSendAdvcVO.getCallTo(),
+								kakaoSendAdvcVO.getTemplateContent(),
+								kakaoSendAdvcVO.getSubMsgTxt()
+								);
+			*/
+
+			// Step1 END
+
+			
+// step3
+// 바이트 수 체크 및 금액설정
+			
+			
+			Float kakaoAtPrice = mberManageVO.getKakaoAtPrice();
+			// 유효한 단가 계산
+			float shortPrice = getValidPrice(mberManageVO.getShortPrice(), sysJoinSetVO.getShortPrice());
+			float longPrice = getValidPrice(mberManageVO.getLongPrice(), sysJoinSetVO.getLongPrice());
+			
+			
+			String shortPStr = Float.toString(shortPrice);
+			String mmsPStr = Float.toString(longPrice);
+			
+			// 공통 가격 설정
+			sendVO.setSmsPrice(shortPStr);
+			sendVO.setMmsPrice(mmsPStr);
+			
+			
+			if("Y".equals(kakaoVO.getSubMsgSendYn())) {
+				int smsTxtByte = mjonCommon.getSmsTxtBytes(sendVO.getSubMsgTxt());
+				String sendType = getMsgType(smsTxtByte);
+				sendVO.setSubMsgType(sendType);
+
+				if ("INVALID".equals(sendType)) {
+					statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "전송 문자 길이를 초과하였습니다.");return kakaoSendAdvcListVO;
+				}
+	
+				boolean isMms = "MMS".equals(sendType);
+				sendVO.setEachPrice(isMms ? mmsPStr : shortPStr);
+				
+				
+			} else {
+				kakaoAtPrice = getValidPrice(mberManageVO.getKakaoAtPrice(), sysJoinSetVO.getKakaoAtPrice());
+				sendVO.setEachPrice( Float.toString(kakaoAtPrice) );
+			}
+			
+			
+			
+			// step4
+			// 예약 시간 설정 및 분할 데이터 설정
+			if ("Y".equalsIgnoreCase(kakaoVO.getReserveYn())  
+				&& "Y".equalsIgnoreCase(kakaoVO.getDivideChk())  
+				&& counter == Integer.parseInt(kakaoVO.getDivideCnt())) 
+			{
+				counter = 0;
+				calendar.add(Calendar.MINUTE, Integer.parseInt(kakaoVO.getDivideTime()));
+			}
+			counter++;
+			// 즉시 발송인경우 현재 시간 
+			// 예약인 경우 위에 설정한 시간 입력
+			sendVO.setReqDate(DATE_FORMATTER.format(calendar.getTime())); 
+			
+			
+			
+/** @step5 전송 메세지 설정 json파일 만들기*/
+			// 타이틀과 버튼이 있고
+			if(hasTitleOrButtons) {
+				// 버튼과 타이틀에 치환데이터가 있으면 json String을 계속 생성
+				if(needsJsonReplacement) {
+					sharedJsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail);
+					sendVO.setBizJsonName(msgId);
+					sendVO.setJsonStr(sharedJsonStr);
+				} else if (StringUtils.isEmpty(sharedJsonStr)) {
+					// 치환 데이터가 없고 아직 생성되지 않았으면 한 번만 생성
+					sharedJsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail);
+					sendVO.setBizJsonName(idList.get(0));
+					sendVO.setJsonStr(sharedJsonStr);
+				}else {
+					sendVO.setBizJsonName(idList.get(0));
+				}
+				
+			}
+			kakaoSendAdvcListVO.add(sendVO);
+		}
+		
+		
+		return kakaoSendAdvcListVO;
+	}
+	
+	private Calendar setupBaseDate(KakaoVO kakaoVO, boolean isNotified) throws ParseException {
+		// 예약 시간 기본값 설정
+		Date now = new Date();
+		// ReqDate가 비어 있으면 현재 시간으로 설정, 그렇지 않으면 ReqDate로 설정
+		// 화면에서 예약문자면 예약시간을 regDate로 설정한다.
+		Date baseDate;
+		if (StringUtils.isEmpty(kakaoVO.getReqDate())) {
+			kakaoVO.setReqDate(DATE_FORMATTER.format(now));  // ReqDate에 현재 시간 설정
+		    baseDate = now;
+		} else {
+		    baseDate = DATE_FORMATTER.parse(kakaoVO.getReqDate()); // ReqDate를 baseDate로 설정
+		}
+		
+		// 시간 성정
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(baseDate);  // calendar에 baseDate 설정
+		
+		// 지연 여부 처리
+		// 알림톡 스미싱의심 + 공휴일알림 조건이 맞으면 30분 delay
+		if ( "Y".equalsIgnoreCase(kakaoVO.getAtSmishingYn())
+				&& isNotified) {
+			calendar.add(Calendar.MINUTE, 30); // 모든 시간을 30분 뒤로 미룸
+		}
+		return calendar;
+	}
+
+	/**
+	 * @methodName	: createSendVO 
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 19.
+	 * @description	:  populateSendLists 반복에 필요한 공통생성 부분
+	 * @return : KakaoSendAdvcVO
+	 * @param kakaoVO
+	 * @return
+	 * 
+	 */
+	private KakaoSendAdvcVO createSendVO(KakaoVO kakaoVO) {
+		KakaoSendAdvcVO sendVO = new KakaoSendAdvcVO();
+		sendVO.setMsgType("8");
+		sendVO.setSenderKey(kakaoVO.getSenderKey());
+		sendVO.setTemplateCode(kakaoVO.getTemplateCode());
+		sendVO.setUserId(kakaoVO.getUserId());
+		sendVO.setCallFrom(kakaoVO.getCallFrom());
+		sendVO.setAgentCode("04");
+		return sendVO;
+	}
+	
+	private List<KakaoButtonVO> replaceButtonLinks(List<KakaoButtonVO> buttonList,
+			Map<String, String> variables) {
+
+		if (buttonList != null) {
+			for (KakaoButtonVO button : buttonList) {
+				// 각 링크 필드에 대해 치환 수행
+				if (button.getLinkAnd() != null) {
+					button.setLinkAnd(mjonCommon.ATReplaceTemplateVariables(button.getLinkAnd(), variables));
+				}
+				if (button.getLinkIos() != null) {
+					button.setLinkIos(mjonCommon.ATReplaceTemplateVariables(button.getLinkIos(), variables));
+				}
+				if (button.getLinkMo() != null) {
+					button.setLinkMo(mjonCommon.ATReplaceTemplateVariables(button.getLinkMo(), variables));
+				}
+				if (button.getLinkPc() != null) {
+					button.setLinkPc(mjonCommon.ATReplaceTemplateVariables(button.getLinkPc(), variables));
+				}
+			}
+			// 치환된 버튼 리스트를 sendVO에 반영
+//			sendVO.setButtonList(buttonList); // KakaoSendAdvcVO에 setButtonList가 있다고 가정
+		}
+		
+		return buttonList;
+	}
+
+	/**
+	 * 버튼 리스트에 치환 패턴(#{...})이 있는지 확인합니다.
+	 * @param buttonList 버튼 리스트 (null 가능)
+	 * @return 치환 패턴이 있으면 true, 없으면 false
+	 */
+	private boolean needsButtonReplacement(List<KakaoButtonVO> buttonList) {
+		if (buttonList == null) {
+			return false;
+		}
+		return buttonList.stream().anyMatch(button -> 
+			replBooleanStrChecker(button.getLinkAnd()) ||
+			replBooleanStrChecker(button.getLinkIos()) ||
+			replBooleanStrChecker(button.getLinkMo()) ||
+			replBooleanStrChecker(button.getLinkPc())
+		);
+	}
+
+	/**
+	 * 입력 문자열에 치환 패턴(#{...})이 있는지 확인합니다.
+	 * @param input 확인할 문자열 (null 가능)
+	 * @return 치환 패턴이 있으면 true, 없으면 false
+	 */
+	private boolean replBooleanStrChecker(String input) {
+		// #{...} 패턴을 확인하는 정규 표현식
+		if (input == null) {
+			return false;
+		}
+		Matcher matcher = REPLACEMENT_PATTERN.matcher(input);
+		return matcher.find();
+	}
+
+
+	public Float getValidPrice(Float personalPrice, Float defaultPrice) {
+		return (personalPrice != null && personalPrice > 0) ? personalPrice : defaultPrice;
+	}
+
+
+	/**
+	 * @methodName	: getMsgType 
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 12.
+	 * @description	: 메세지 타입 구하기
+	 * @return : String
+	 * @param smsTxtByte
+	 * @return
+	 * 
+	 */
+	private String getMsgType(int smsTxtByte) {
+		// TODO Auto-generated method stub
+
+		String msgType = SHORT_MSG_TYPE;
+
+		// 1. 2000 Byte 초과는 에러 처리
+		if (smsTxtByte > 2000) {
+			return "INVALID";
+		}
+
+		// 2. 문자 길이에 따라 메시지 타입 설정 (90 Byte 초과는 장문)
+		if (smsTxtByte > 90) {
+			msgType = LONG_MSG_TYPE;
+		}
+		
+		return msgType;
+	}
+
+
+
+	
 	
 	
 	/**
@@ -34,13 +419,11 @@
 	*/
 	public KakaoVO kakaoSendPrice(KakaoVO kakaoVO) throws Exception {
 		
-		//사용자 현재 보유 금액 불러오기(문자 발송 금액 차감 이전 금액)
-		String befCash = kakaoVO.getBefCash();
+		System.out.println(" :: kakaoSendPrice :: ");
 		
-		//VO에서 현재 보유금액이 없으면 디비에서 조회해서 불러옴
-		if("".equals(befCash) || befCash == null) {
-			
-		}
+		//사용자 현재 보유 금액 불러오기(문자 발송 금액 차감 이전 금액)
+//		String befCash = kakaoVO.getBefCash();
+		
 		MjonMsgVO mjonMsgVO = new MjonMsgVO();
 		mjonMsgVO.setUserId(kakaoVO.getUserId());
 		String userMoney = mjonMsgDataService.selectBeforeCashData(mjonMsgVO);
@@ -55,6 +438,7 @@
 		
 		/** 대체문자 여부 체크(있으면 대체문자 가격으로 없으면 카카오톡 가격으로) */
 		//대체문자 발송 여부 확인
+		System.out.println(" :: kakaoVO.getSubMsgSendYn() :: "+ kakaoVO.getSubMsgSendYn());
 		if(kakaoVO.getSubMsgSendYn().equals("Y")) {
 			
 			
@@ -401,6 +785,107 @@
 						varValInfo = kakaoVO.getVarValList().get(count);
 					}
 					String jsonFileName = kakaoApiJsonSave.kakaoApiJsonSave(kakaoVO, varValInfo);
+					setSendMsgVO.setBizJsonName(jsonFileName); //json 파일명
+				}
+				
+				kakaoSendList.add(setSendMsgVO);
+			}
+			kakaoVO.setKakaoSendList(kakaoSendList);
+			
+		} catch (Exception e) {
+			System.out.println(e.toString());
+			e.printStackTrace();
+		}
+		
+		return kakaoVO;
+	}
+	
+	/**
+	 * @methodName	: kakaoSendMsg_advc 
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 13.
+	 * @description	: kakaoSendMsg 개선
+	 * @return : KakaoVO
+	 * @param kakaoVO
+	 * @return
+	 * @throws Exception
+	 * 
+	 */
+	public KakaoVO kakaoSendMsg_advc(KakaoVO kakaoVO) throws Exception {
+		List<KakaoVO> kakaoSendList = new ArrayList<KakaoVO>();
+		//전체 받는사람 수량만큼 반복 확인
+		int callToCnt = kakaoVO.getCallToList().length;	
+		try {
+			for(int count =0; count < callToCnt; count++) {
+				
+				KakaoVO setSendMsgVO = new KakaoVO();
+				
+				setSendMsgVO.setDestPhone(kakaoVO.getCallToList()[count]); // 수신 번호
+				// 카카오 전송내용 설정
+				// 변환문자 포함(Y), 미포함(N)
+				if(kakaoVO.getTxtReplYn().equals("Y")) {
+					
+					String templateContent = kakaoSubMagTxtRepl(kakaoVO.getTemplateContent(), kakaoVO, count);
+					setSendMsgVO.setTemplateContent(templateContent);
+					
+					if(kakaoVO.getTemplateEmphasizeType().equals("TEXT")) {
+						
+						String title = kakaoSubMagTxtRepl(kakaoVO.getTemplateTitle(), kakaoVO, count);
+						String subTitle = kakaoVO.getTemplateSubtitle();
+//						title = title +"§§"+ subTitle;
+						setSendMsgVO.setTemplateEmphasizeType(kakaoVO.getTemplateEmphasizeType());
+						setSendMsgVO.setTemplateTitle(title);
+					}
+					
+				}else {
+					
+					if(kakaoVO.getTemplateEmphasizeType().equals("TEXT")) {
+						
+						String title = kakaoSubMagTxtRepl(kakaoVO.getTemplateTitle(), kakaoVO, count);
+						String subTitle = kakaoVO.getTemplateSubtitle();
+//						title = title +"§§"+ subTitle;
+						setSendMsgVO.setTemplateEmphasizeType(kakaoVO.getTemplateEmphasizeType());
+						setSendMsgVO.setTemplateTitle(title);
+					}
+					
+					// 템플릿 내용 설정
+					setSendMsgVO.setTemplateContent(kakaoVO.getTemplateContent());
+				}
+				
+				//대체문자 포함(Y), 미포함(N)
+				if(kakaoVO.getSubMsgSendYn().equals("Y")) {
+					
+					String charset = "euc-kr";	//문자 바이트 계산에 필요한 캐릭터 셋 : 한글 2Byte로 계산
+					
+					String tempSubMagTxt = kakaoVO.getSubMsgTxt().replace("\r\n", "\n");
+					kakaoVO.setKakaoSubMagOrgnlTxt(tempSubMagTxt);
+					if(kakaoVO.getSubMsgTxtReplYn().equals("Y")) {
+						tempSubMagTxt = kakaoSubMagTxtRepl(tempSubMagTxt, kakaoVO, count);
+					}
+					System.out.println("@@  대체문자내용 : " + tempSubMagTxt);
+					setSendMsgVO.setSubMsgTxt(tempSubMagTxt);
+					
+					int FrBytes = tempSubMagTxt.getBytes(charset).length;
+					System.out.println("@@  대체문자길이 : " + FrBytes);
+					//메세지 길이가 90Byte가 초과시 MMS
+					if(FrBytes > 90) {
+						setSendMsgVO.setSubMsgType("MMS");
+					}else {// 아니면 SMS
+						setSendMsgVO.setSubMsgType("SMS");
+					}
+					
+					System.out.println("@@  대체문자타입 : " + setSendMsgVO.getSubMsgType());
+				}
+				
+				if(kakaoVO.getBizJsonYn().equals("Y")) {
+					kakaoVO.setDestPhone(kakaoVO.getCallToList()[count]); // 수신 번호
+					
+					String[] varValInfo = null;
+					if( kakaoVO.getVarValList().size() != 0) {
+						varValInfo = kakaoVO.getVarValList().get(count);
+					}
+					String jsonFileName = kakaoApiJsonSave.kakaoApiJsonSave(kakaoVO, varValInfo);
+//					String jsonFileName = kakaoApiJsonSave.kakaoApiJsonSave_advc(kakaoVO, varValInfo);
 //					String jsonFileName = kakaoApiJsonSave.kakaoApiJsonSave(kakaoVO, kakaoVO.getVarValList().get(count));
 					setSendMsgVO.setBizJsonName(jsonFileName); //json 파일명
 				}
@@ -509,6 +994,7 @@
 	
 	
 	public String kakaoSubMagTxtRepl(String tempSubMagTxt, KakaoVO kakaoVO, int count) {
+		System.out.println("tempSubMagTxt : "+ tempSubMagTxt);
 		
 //		String tempSubMagTxt = kakaoVO.getSubMsgTxt().replace("\r\n", "\n");
 //		String tempSubMagTxt = msgTxt;
@@ -550,6 +1036,7 @@
 		}
 		return tempSubMagTxt;
 	}
+	
 	
 	public String kakaoFTSubMagTxtRepl(String tempSubMagTxt, KakaoVO kakaoVO, int count) throws Exception{
 
@@ -704,5 +1191,10 @@
 		//}
 		return "";
 	}
-	
+
+	public static void statusResponseSet (StatusResponse statusResponse, HttpStatus httpStatus, String msg ) {
+		statusResponse.setStatus(httpStatus);
+		statusResponse.setMessage(msg);
+		
+	}
 }
src/main/java/itn/let/kakao/kakaoComm/KakaoVO.java
--- src/main/java/itn/let/kakao/kakaoComm/KakaoVO.java
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoVO.java
@@ -2,8 +2,11 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import itn.let.mjo.msg.service.MjonMsgVO;
+import lombok.Getter;
+import lombok.Setter;
 
 /**
 * @FileName : KakaoVO.java
@@ -13,6 +16,8 @@
 
 * @프로그램 설명 : 카카오톡 요청 변수 목록 (문자온VO를 상속 받음)
 */
+@Getter
+@Setter
 public class KakaoVO extends MjonMsgVO{
 
 	private static final long serialVersionUID = 536382850588307019L;
@@ -255,1030 +260,60 @@
 	private String msgResendAllTmpKey;
 	private String msgResendAllYellowId;
 
-	public String getSuccessDay() {
-		return successDay;
-	}
+	private List<Map<String, String>> varListMap;
 
-	public void setSuccessDay(String successDay) {
-		this.successDay = successDay;
-	}
-
-	public String getSuccessMonth() {
-		return successMonth;
-	}
-
-	public void setSuccessMonth(String successMonth) {
-		this.successMonth = successMonth;
-	}
-
-	public String getSuccessYear() {
-		return successYear;
-	}
-
-	public void setSuccessYear(String successYear) {
-		this.successYear = successYear;
-	}
-	
-	public String getSuccessCntDay() {
-		return successCntDay;
-	}
-
-	public void setSuccessCntDay(String successCntDay) {
-		this.successCntDay = successCntDay;
-	}
-
-	public String getSuccessCntMonth() {
-		return successCntMonth;
-	}
-
-	public void setSuccessCntMonth(String successCntMonth) {
-		this.successCntMonth = successCntMonth;
-	}
-
-	public String getSuccessCntYear() {
-		return successCntYear;
-	}
-
-	public void setSuccessCntYear(String successCntYear) {
-		this.successCntYear = successCntYear;
-	}
-	
-	public static long getSerialversionuid() {
-		return serialVersionUID;
-	}
-
-	public String getCategoryDepth() {
-		return categoryDepth;
-	}
-
-	public void setCategoryDepth(String categoryDepth) {
-		this.categoryDepth = categoryDepth;
-	}
-
-	public String getCategoryType() {
-		return categoryType;
-	}
-
-	public void setCategoryType(String categoryType) {
-		this.categoryType = categoryType;
-	}
-
-	public String getCategoryCode() {
-		return categoryCode;
-	}
-
-	public void setCategoryCode(String categoryCode) {
-		this.categoryCode = categoryCode;
-	}
-
-	public String getCategoryGroupName() {
-		return categoryGroupName;
-	}
-
-	public void setCategoryGroupName(String categoryGroupName) {
-		this.categoryGroupName = categoryGroupName;
-	}
-
-	public String getCategoryName() {
-		return categoryName;
-	}
-
-	public void setCategoryName(String categoryName) {
-		this.categoryName = categoryName;
-	}
-
-	public String getCategoryInclusion() {
-		return categoryInclusion;
-	}
-
-	public void setCategoryInclusion(String categoryInclusion) {
-		this.categoryInclusion = categoryInclusion;
-	}
-
-	public String getCategoryExclusion() {
-		return categoryExclusion;
-	}
-
-	public void setCategoryExclusion(String categoryExclusion) {
-		this.categoryExclusion = categoryExclusion;
-	}
-
-	public String getBizUrl() {
-		return bizUrl;
-	}
-	
-	public void setBizUrl(String bizUrl) {
-		this.bizUrl = bizUrl;
-	}
-
-	public String getBizReturnMsg() {
-		return bizReturnMsg;
-	}
-	
-	public void setBizReturnMsg(String bizReturnMsg) {
-		this.bizReturnMsg = bizReturnMsg;
-	}
-
-	public String getBizReturnCode() {
-		return bizReturnCode;
-	}
-	
-	public void setBizReturnCode(String bizReturnCode) {
-		this.bizReturnCode = bizReturnCode;
-	}
-
-	public String getPhoneNumber() {
-		return phoneNumber;
-	}
-	
-	public void setPhoneNumber(String phoneNumber) {
-		this.phoneNumber = phoneNumber;
-	}
-
-	public String getYellowId() {
-		return yellowId;
-	}
-	
-	public void setYellowId(String yellowId) {
-		this.yellowId = yellowId;
-	}
-
-	public String getBizJsonName() {
-		return bizJsonName;
-	}
-
-	public void setBizJsonName(String bizJsonName) {
-		this.bizJsonName = bizJsonName;
-	}
-
-	public String getToken() {
-		return token;
-	}
-
-	public void setToken(String token) {
-		this.token = token;
-	}
-
-	public String getSenderKey() {
-		return senderKey;
-	}
-
-	public void setSenderKey(String senderKey) {
-		this.senderKey = senderKey;
-	}
-
-	public String getProfileId() {
-		return profileId;
-	}
-
-	public void setProfileId(String profileId) {
-		this.profileId = profileId;
-	}
-
-	public String getUserId() {
-		return userId;
-	}
-
-	public void setUserId(String userId) {
-		this.userId = userId;
-	}
-
-	public String getImgTitle() {
-		return imgTitle;
-	}
-
-	public void setImgTitle(String imgTitle) {
-		this.imgTitle = imgTitle;
-	}
-
-	public String getImageType() {
-		return imageType;
-	}
-
-	public void setImageType(String imageType) {
-		this.imageType = imageType;
-	}
-
-	public String getImgLink() {
-		return imgLink;
-	}
-
-	public void setImgLink(String imgLink) {
-		this.imgLink = imgLink;
-	}
-
-	public String getTemplateName() {
-		return templateName;
-	}
-
-	public void setTemplateName(String templateName) {
-		this.templateName = templateName;
-	}
-
-	public String getTemplateMessageType() {
-		return templateMessageType;
-	}
-
-	public void setTemplateMessageType(String templateMessageType) {
-		this.templateMessageType = templateMessageType;
-	}
-
-	public String getTemplateEmphasizeType() {
-		return templateEmphasizeType;
-	}
-
-	public void setTemplateEmphasizeType(String templateEmphasizeType) {
-		this.templateEmphasizeType = templateEmphasizeType;
-	}
-
-	public String getTemplateContent() {
-		return templateContent;
-	}
-
-	public void setTemplateContent(String templateContent) {
-		this.templateContent = templateContent;
-	}
-
-	public String getTemplateExtra() {
-		return templateExtra;
-	}
-
-	public void setTemplateExtra(String templateExtra) {
-		this.templateExtra = templateExtra;
-	}
-
-	public String getTamplateAd() {
-		return tamplateAd;
-	}
-
-	public void setTamplateAd(String tamplateAd) {
-		this.tamplateAd = tamplateAd;
-	}
-
-	public String getTemplateImageName() {
-		return templateImageName;
-	}
-
-	public void setTemplateImageName(String templateImageName) {
-		this.templateImageName = templateImageName;
-	}
-
-	public String getTemplateImageUrl() {
-		return templateImageUrl;
-	}
-
-	public void setTemplateImageUrl(String templateImageUrl) {
-		this.templateImageUrl = templateImageUrl;
-	}
-
-	public String getTemplateTitle() {
-		return templateTitle;
-	}
-
-	public void setTemplateTitle(String templateTitle) {
-		this.templateTitle = templateTitle;
-	}
-
-	public String getTemplateSubtitle() {
-		return templateSubtitle;
-	}
-
-	public void setTemplateSubtitle(String templateSubtitle) {
-		this.templateSubtitle = templateSubtitle;
-	}
-
-	public String getTemplateHeader() {
-		return templateHeader;
-	}
-
-	public void setTemplateHeader(String templateHeader) {
-		this.templateHeader = templateHeader;
-	}
-
-	public Boolean getSecurityFlag() {
-		return securityFlag;
-	}
-
-	public void setSecurityFlag(Boolean securityFlag) {
-		this.securityFlag = securityFlag;
-	}
-
-	public List<KakaoButtonVO> getButtonVOList() {
-		return buttonVOList;
-	}
-
-	public void setButtonVOList(List<KakaoButtonVO> buttonVOList) {
-		this.buttonVOList = buttonVOList;
-	}
-
-	public String getButtonName() {
-		return buttonName;
-	}
-
-	public void setButtonName(String buttonName) {
-		this.buttonName = buttonName;
-	}
-
-	public String getButtonLinkType() {
-		return buttonLinkType;
-	}
-
-	public void setButtonLinkType(String buttonLinkType) {
-		this.buttonLinkType = buttonLinkType;
-	}
-
-	public String getButtonLinkAnd() {
-		return buttonLinkAnd;
-	}
-
-	public void setButtonLinkAnd(String buttonLinkAnd) {
-		this.buttonLinkAnd = buttonLinkAnd;
-	}
-
-	public String getButtonLinkIos() {
-		return buttonLinkIos;
-	}
-
-	public void setButtonLinkIos(String buttonLinkIos) {
-		this.buttonLinkIos = buttonLinkIos;
-	}
-
-	public String getButtonLinkMo() {
-		return buttonLinkMo;
-	}
-
-	public void setButtonLinkMo(String buttonLinkMo) {
-		this.buttonLinkMo = buttonLinkMo;
-	}
-
-	public String getButtonLinkPc() {
-		return buttonLinkPc;
-	}
-
-	public void setButtonLinkPc(String buttonLinkPc) {
-		this.buttonLinkPc = buttonLinkPc;
-	}
-
-	public String getButtonPluginId() {
-		return buttonPluginId;
-	}
-
-	public void setButtonPluginId(String buttonPluginId) {
-		this.buttonPluginId = buttonPluginId;
-	}
-
-	public String getQuickName() {
-		return quickName;
-	}
-
-	public void setQuickName(String quickName) {
-		this.quickName = quickName;
-	}
-
-	public String getQuickLinkType() {
-		return quickLinkType;
-	}
-
-	public void setQuickLinkType(String quickLinkType) {
-		this.quickLinkType = quickLinkType;
-	}
-
-	public String getQuickLinkAnd() {
-		return quickLinkAnd;
-	}
-
-	public void setQuickLinkAnd(String quickLinkAnd) {
-		this.quickLinkAnd = quickLinkAnd;
-	}
-
-	public String getQuickLinkIos() {
-		return quickLinkIos;
-	}
-
-	public void setQuickLinkIos(String quickLinkIos) {
-		this.quickLinkIos = quickLinkIos;
-	}
-
-	public String getQuickLinkMo() {
-		return quickLinkMo;
-	}
-
-	public void setQuickLinkMo(String quickLinkMo) {
-		this.quickLinkMo = quickLinkMo;
-	}
-
-	public String getQuickLinkPc() {
-		return quickLinkPc;
-	}
-
-	public void setQuickLinkPc(String quickLinkPc) {
-		this.quickLinkPc = quickLinkPc;
-	}
-
-	public String getSenderKeyType() {
-		return senderKeyType;
-	}
-
-	public void setSenderKeyType(String senderKeyType) {
-		this.senderKeyType = senderKeyType;
-	}
-
-	public String getDeleteYn() {
-		return deleteYn;
-	}
-
-	public void setDeleteYn(String deleteYn) {
-		this.deleteYn = deleteYn;
-	}
-
-	public String getTemplateCode() {
-		return templateCode;
-	}
-
-	public void setTemplateCode(String templateCode) {
-		this.templateCode = templateCode;
-	}
-
-	public String getNewTemplateCode() {
-		return newTemplateCode;
-	}
-
-	public void setNewTemplateCode(String newTemplateCode) {
-		this.newTemplateCode = newTemplateCode;
-	}
-
-	public String[] getArrTemplateCode() {
-		return arrTemplateCode;
-	}
-
-	public void setArrTemplateCode(String[] arrTemplateCode) {
-		this.arrTemplateCode = arrTemplateCode;
-	}
-
-	public String getTemplateStatus() {
-		return templateStatus;
-	}
-
-	public void setTemplateStatus(String templateStatus) {
-		this.templateStatus = templateStatus;
-	}
-
-	public String getKeyword() {
-		return keyword;
-	}
-
-	public void setKeyword(String keyword) {
-		this.keyword = keyword;
-	}
-
-	public String getSendPhone() {
-		return sendPhone;
-	}
-
-	public void setSendPhone(String sendPhone) {
-		this.sendPhone = sendPhone;
-	}
-
-	public String getDestPhone() {
-		return destPhone;
-	}
-
-	public void setDestPhone(String destPhone) {
-		this.destPhone = destPhone;
-	}
-
-	public String getSubMsgSendYn() {
-		return subMsgSendYn;
-	}
-
-	public void setSubMsgSendYn(String subMsgSendYn) {
-		this.subMsgSendYn = subMsgSendYn;
-	}
-
-	public String getCount() {
-		return count;
-	}
-
-	public void setCount(String count) {
-		this.count = count;
-	}
-
-	public String getPage() {
-		return page;
-	}
-
-	public void setPage(String page) {
-		this.page = page;
-	}
-
-	public String getBizUmid() {
-		return bizUmid;
-	}
-
-	public void setBizUmid(String bizUmid) {
-		this.bizUmid = bizUmid;
-	}
-
-	public List<String> getVarNmList() {
-		return varNmList;
-	}
-
-	public void setVarNmList(List<String> varNmList) {
-		this.varNmList = varNmList;
-	}
-
-	public List<String[]> getVarValList() {
-		return varValList;
-	}
-
-	public void setVarValList(List<String[]> varValList) {
-		this.varValList = varValList;
-	}
-
-	public String getFormListType() {
-		return formListType;
-	}
-
-	public void setFormListType(String formListType) {
-		this.formListType = formListType;
-	}
-
-	public String getSubMsgTxt() {
-		return subMsgTxt;
-	}
-
-	public void setSubMsgTxt(String subMsgTxt) {
-		this.subMsgTxt = subMsgTxt;
-	}
-
-	public String getBizJsonYn() {
-		return bizJsonYn;
-	}
-
-	public void setBizJsonYn(String bizJsonYn) {
-		this.bizJsonYn = bizJsonYn;
-	}
-
-	public String getSendType() {
-		return sendType;
-	}
-
-	public void setSendType(String sendType) {
-		this.sendType = sendType;
-	}
-
-	public String getAdFlag() {
-		return adFlag;
-	}
-
-	public void setAdFlag(String adFlag) {
-		this.adFlag = adFlag;
-	}
-
-	public List<KakaoVO> getKakaoSendList() {
-		return kakaoSendList;
-	}
-
-	public void setKakaoSendList(List<KakaoVO> kakaoSendList) {
-		this.kakaoSendList = kakaoSendList;
-	}
-
-	public String getSubMsgTxtReplYn() {
-		return subMsgTxtReplYn;
-	}
-
-	public void setSubMsgTxtReplYn(String subMsgTxtReplYn) {
-		this.subMsgTxtReplYn = subMsgTxtReplYn;
-	}
-	
-	public String getSubMsgType() {
-		return subMsgType;
-	}
-
-	public void setSubMsgType(String subMsgType) {
-		this.subMsgType = subMsgType;
-	}
-	public List<String[]> varValPaser(String[] varValList){
-		
-		List<String[]> returnVarVal = new ArrayList<>();
-		
-		for(String varVal : varValList)
-		{
-			String[] strList = varVal.split("§");
-			returnVarVal.add(strList);
+	@Override
+	public String toString() {
+		String varListMapString = "[";
+		if (varListMap != null && !varListMap.isEmpty()) {
+			StringBuilder sb = new StringBuilder();
+			for (Map<String, String> map : varListMap) {
+				if (sb.length() > 0)
+					sb.append(", ");
+				if (map == null) {
+					sb.append("null");
+				} else {
+					sb.append("{");
+					String prefix = "";
+					for (Map.Entry<String, String> entry : map.entrySet()) {
+						sb.append(prefix).append(entry.getKey()).append("=").append(entry.getValue());
+						prefix = ", ";
+					}
+					sb.append("}");
+				}
+			}
+			varListMapString += sb.toString();
 		}
+		varListMapString += "]";
 		
-		return returnVarVal;
-	}
-
-	public String getMenuTopTab() {
-		return menuTopTab;
-	}
-
-	public void setMenuTopTab(String menuTopTab) {
-		this.menuTopTab = menuTopTab;
-	}
-
-	public String getMenuSubTab() {
-		return menuSubTab;
-	}
-
-	public void setMenuSubTab(String menuSubTab) {
-		this.menuSubTab = menuSubTab;
-	}
-
-	public String getSearchCondition2() {
-		return searchCondition2;
-	}
-
-	public void setSearchCondition2(String searchCondition2) {
-		this.searchCondition2 = searchCondition2;
-	}
-
-	public String getKakaoResendSuccCount() {
-		return kakaoResendSuccCount;
-	}
-
-	public void setKakaoResendSuccCount(String kakaoResendSuccCount) {
-		this.kakaoResendSuccCount = kakaoResendSuccCount;
-	}
-
-	public String getKakaoResendFailCount() {
-		return kakaoResendFailCount;
-	}
-
-	public void setKakaoResendFailCount(String kakaoResendFailCount) {
-		this.kakaoResendFailCount = kakaoResendFailCount;
-	}
-
-	public String getAtSuccessCount() {
-		return atSuccessCount;
-	}
-
-	public void setAtSuccessCount(String atSuccessCount) {
-		this.atSuccessCount = atSuccessCount;
-	}
-
-	public String getFtSuccessCount() {
-		return ftSuccessCount;
-	}
-
-	public void setFtSuccessCount(String ftSuccessCount) {
-		this.ftSuccessCount = ftSuccessCount;
-	}
-
-	public String getAtFailCount() {
-		return atFailCount;
-	}
-
-	public void setAtFailCount(String atFailCount) {
-		this.atFailCount = atFailCount;
-	}
-
-	public String getFtFailCount() {
-		return ftFailCount;
-	}
-
-	public void setFtFailCount(String ftFailCount) {
-		this.ftFailCount = ftFailCount;
-	}
-
-	public String getAtSuccPrice() {
-		return atSuccPrice;
-	}
-
-	public void setAtSuccPrice(String atSuccPrice) {
-		this.atSuccPrice = atSuccPrice;
-	}
-
-	public String getFtSuccPrice() {
-		return ftSuccPrice;
-	}
-
-	public void setFtSuccPrice(String ftSuccPrice) {
-		this.ftSuccPrice = ftSuccPrice;
-	}
-
-	public String getAtFailPrice() {
-		return atFailPrice;
-	}
-
-	public void setAtFailPrice(String atFailPrice) {
-		this.atFailPrice = atFailPrice;
-	}
-
-	public String getFtFailPrice() {
-		return ftFailPrice;
-	}
-
-	public void setFtFailPrice(String ftFailPrice) {
-		this.ftFailPrice = ftFailPrice;
-	}
-
-	public String getKakaoResendSuccPrice() {
-		return kakaoResendSuccPrice;
-	}
-
-	public void setKakaoResendSuccPrice(String kakaoResendSuccPrice) {
-		this.kakaoResendSuccPrice = kakaoResendSuccPrice;
-	}
-
-	public String getKakaoResendFailPrice() {
-		return kakaoResendFailPrice;
-	}
-
-	public void setKakaoResendFailPrice(String kakaoResendFailPrice) {
-		this.kakaoResendFailPrice = kakaoResendFailPrice;
-	}
-
-	public String getAtSuccCntSum() {
-		return atSuccCntSum;
-	}
-
-	public void setAtSuccCntSum(String atSuccCntSum) {
-		this.atSuccCntSum = atSuccCntSum;
-	}
-
-	public String getFtSuccCntSum() {
-		return ftSuccCntSum;
-	}
-
-	public void setFtSuccCntSum(String ftSuccCntSum) {
-		this.ftSuccCntSum = ftSuccCntSum;
-	}
-
-	public String getAtFailCntSum() {
-		return atFailCntSum;
-	}
-
-	public void setAtFailCntSum(String atFailCntSum) {
-		this.atFailCntSum = atFailCntSum;
-	}
-
-	public String getFtFailCntSum() {
-		return ftFailCntSum;
-	}
-
-	public void setFtFailCntSum(String ftFailCntSum) {
-		this.ftFailCntSum = ftFailCntSum;
-	}
-
-	public String getKakaoResenSuccSum() {
-		return kakaoResenSuccSum;
-	}
-
-	public void setKakaoResenSuccSum(String kakaoResenSuccSum) {
-		this.kakaoResenSuccSum = kakaoResenSuccSum;
-	}
-
-	public String getKakaoResenFailSum() {
-		return kakaoResenFailSum;
-	}
-
-	public void setKakaoResenFailSum(String kakaoResenFailSum) {
-		this.kakaoResenFailSum = kakaoResenFailSum;
-	}
-
-	public String getAtSuccPriceSum() {
-		return atSuccPriceSum;
-	}
-
-	public void setAtSuccPriceSum(String atSuccPriceSum) {
-		this.atSuccPriceSum = atSuccPriceSum;
-	}
-
-	public String getFtSuccPriceSum() {
-		return ftSuccPriceSum;
-	}
-
-	public void setFtSuccPriceSum(String ftSuccPriceSum) {
-		this.ftSuccPriceSum = ftSuccPriceSum;
-	}
-
-	public String getAtFailPriceSum() {
-		return atFailPriceSum;
-	}
-
-	public void setAtFailPriceSum(String atFailPriceSum) {
-		this.atFailPriceSum = atFailPriceSum;
-	}
-
-	public String getFtFailPriceSum() {
-		return ftFailPriceSum;
-	}
-
-	public void setFtFailPriceSum(String ftFailPriceSum) {
-		this.ftFailPriceSum = ftFailPriceSum;
-	}
-
-	public String getKakaoResendSuccPriceSum() {
-		return kakaoResendSuccPriceSum;
-	}
-
-	public void setKakaoResendSuccPriceSum(String kakaoResendSuccPriceSum) {
-		this.kakaoResendSuccPriceSum = kakaoResendSuccPriceSum;
-	}
-
-	public String getKakaoResendFailPriceSum() {
-		return kakaoResendFailPriceSum;
-	}
-
-	public void setKakaoResendFailPriceSum(String kakaoResendFailPriceSum) {
-		this.kakaoResendFailPriceSum = kakaoResendFailPriceSum;
-	}
-
-	public String getFriendId() {
-		return friendId;
-	}
-
-	public void setFriendId(String friendId) {
-		this.friendId = friendId;
-	}
-
-	public String getImageTitle() {
-		return imageTitle;
-	}
-
-	public void setImageTitle(String imageTitle) {
-		this.imageTitle = imageTitle;
-	}
-
-	public String getImageLink() {
-		return imageLink;
-	}
-
-	public void setImageLink(String imageLink) {
-		this.imageLink = imageLink;
-	}
-
-	public String getJsonText() {
-		return jsonText;
-	}
-
-	public void setJsonText(String jsonText) {
-		this.jsonText = jsonText;
-	}
-
-	public String getImageFileName() {
-		return imageFileName;
-	}
-
-	public void setImageFileName(String imageFileName) {
-		this.imageFileName = imageFileName;
-	}
-
-	public String getSbscrbDe() {
-		return sbscrbDe;
-	}
-
-	public void setSbscrbDe(String sbscrbDe) {
-		this.sbscrbDe = sbscrbDe;
-	}
-
-	public String getMoblphonNo() {
-		return moblphonNo;
-	}
-
-	public void setMoblphonNo(String moblphonNo) {
-		this.moblphonNo = moblphonNo;
-	}
-
-	public String getDept() {
-		return dept;
-	}
-
-	public void setDept(String dept) {
-		this.dept = dept;
-	}
-
-	public String getAtchFileId() {
-		return atchFileId;
-	}
-
-	public void setAtchFileId(String atchFileId) {
-		this.atchFileId = atchFileId;
-	}
-
-	public String getWorkAtchFileId() {
-		return workAtchFileId;
-	}
-
-	public void setWorkAtchFileId(String workAtchFileId) {
-		this.workAtchFileId = workAtchFileId;
-	}
-
-	public String getFileSn() {
-		return fileSn;
-	}
-
-	public void setFileSn(String fileSn) {
-		this.fileSn = fileSn;
-	}
-
-	public String getFileCn() {
-		return fileCn;
-	}
-
-	public void setFileCn(String fileCn) {
-		this.fileCn = fileCn;
-	}
-
-	public String getFileStreCours() {
-		return fileStreCours;
-	}
-
-	public void setFileStreCours(String fileStreCours) {
-		this.fileStreCours = fileStreCours;
-	}
-
-	public String getOrignlFileNm() {
-		return orignlFileNm;
-	}
-
-	public void setOrignlFileNm(String orignlFileNm) {
-		this.orignlFileNm = orignlFileNm;
-	}
-
-	public String getStreFileNm() {
-		return streFileNm;
-	}
-
-	public void setStreFileNm(String streFileNm) {
-		this.streFileNm = streFileNm;
-	}
-
-	public String getFileExtsn() {
-		return fileExtsn;
-	}
-
-	public void setFileExtsn(String fileExtsn) {
-		this.fileExtsn = fileExtsn;
-	}
-
-	public String getFileSize() {
-		return fileSize;
-	}
-
-	public void setFileSize(String fileSize) {
-		this.fileSize = fileSize;
-	}
-
-	public int getStartCount() {
-		return startCount;
-	}
-
-	public void setStartCount(int startCount) {
-		this.startCount = startCount;
-	}
-
-	public int getEndCount() {
-		return endCount;
-	}
-
-	public void setEndCount(int endCount) {
-		this.endCount = endCount;
-	}
-
-	public String getPhmType() {
-		return phmType;
-	}
-
-	public void setPhmType(String phmType) {
-		this.phmType = phmType;
-	}
-
-	public String getMsgResendAllFlag() {
-		return msgResendAllFlag;
-	}
-
-	public void setMsgResendAllFlag(String msgResendAllFlag) {
-		this.msgResendAllFlag = msgResendAllFlag;
-	}
-
-	public String getMsgResendAllGroupId() {
-		return msgResendAllGroupId;
-	}
-
-	public void setMsgResendAllGroupId(String msgResendAllGroupId) {
-		this.msgResendAllGroupId = msgResendAllGroupId;
-	}
-
-	public String getMsgResendAllTmpKey() {
-		return msgResendAllTmpKey;
-	}
-
-	public void setMsgResendAllTmpKey(String msgResendAllTmpKey) {
-		this.msgResendAllTmpKey = msgResendAllTmpKey;
-	}
-
-	public String getMsgResendAllYellowId() {
-		return msgResendAllYellowId;
-	}
-
-	public void setMsgResendAllYellowId(String msgResendAllYellowId) {
-		this.msgResendAllYellowId = msgResendAllYellowId;
+		return "KakaoSendAdvcVO[" +
+			"\n senderKey=[" + senderKey + "]" +
+			"\n , subMsgTxtReplYn=[" + subMsgTxtReplYn + "]" +
+			"\n , subMsgSendYn=[" + subMsgSendYn + "]" +
+			"\n , reserveYn=[" + getReserveYn() + "]" +
+			"\n , divideCnt=[" + getDivideCnt() + "]" +
+			"\n , bizJsonYn=[" + bizJsonYn + "]" +
+			"\n , templateEmphasizeType=[" + templateEmphasizeType + "]" +
+			"\n , templateSubtitle=[" + templateSubtitle + "]" +
+			"\n , txtReplYn=[" + getTxtReplYn() + "]" +
+			"\n , callFrom=[" + getCallFrom() + "]" +
+			"\n , templateCode=[" + templateCode + "]" +
+			"\n , divideTime=[" + getDivideTime() + "]" +
+			"\n , reqDate=[" + getReqDate() + "]" +
+			"\n , atSmishingYn=[" + getAtSmishingYn() + "]" +
+			"\n , menuTopTab=[" + menuTopTab + "]" +
+			"\n , templateContent=[" + templateContent + "]" +
+			"\n , templateTitle=[" + templateTitle + "]" +
+			"\n , subMsgTxt=[" + subMsgTxt + "]" +
+			"\n , divideChk=[" + getDivideChk() + "]" +
+			"\n , sendType=[" + sendType + "]" +
+			"\n , msgType=[" + getMsgType() + "]" +
+			"\n , userId=[" + userId + "]" +
+			"\n , varListMap=[" + varListMapString + "]" +
+			"\n , befCash=[" + getBefCash() + "]" +
+			"\n , befPoint=[" + getBefPoint() + "]" +
+			"\n ]";
 	}
-	
 	
 	
 }
src/main/java/itn/let/kakao/kakaoComm/kakaoApi/KakaoApiJsonSave.java
--- src/main/java/itn/let/kakao/kakaoComm/kakaoApi/KakaoApiJsonSave.java
+++ src/main/java/itn/let/kakao/kakaoComm/kakaoApi/KakaoApiJsonSave.java
@@ -8,6 +8,7 @@
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
@@ -18,6 +19,7 @@
 import itn.com.cmm.util.StringUtil;
 import itn.let.kakao.kakaoComm.KakaoButtonVO;
 import itn.let.kakao.kakaoComm.KakaoReturnVO;
+import itn.let.kakao.kakaoComm.KakaoSendAdvcVO;
 import itn.let.kakao.kakaoComm.KakaoVO;
 
 @Component
@@ -32,7 +34,57 @@
 	
 	static String json;
 	
-	@SuppressWarnings("unchecked")
+	public String kakaoApiJsonSave_advc(KakaoSendAdvcVO sendVO, KakaoReturnVO templateDetail) {
+		
+		// 버튼리스트 JSON 생성
+		JSONArray buttonList = new JSONArray();
+		for(KakaoButtonVO buttonInfoVO : sendVO.getButtonList()) {
+			JSONObject buttonInfo = new JSONObject();
+			
+			buttonInfo.put("name", buttonInfoVO.getName());
+			buttonInfo.put("type", buttonInfoVO.getLinkType());
+			
+			if(buttonInfoVO.getLinkType().equals("WL")) {
+				buttonInfo.put("url_mobile", buttonInfoVO.getLinkMo());
+				buttonInfo.put("url_pc", buttonInfoVO.getLinkPc());
+			}else if(buttonInfoVO.getLinkType().equals("AL")) {
+				buttonInfo.put("scheme_ios", buttonInfoVO.getLinkIos());
+				buttonInfo.put("scheme_android", buttonInfoVO.getLinkAnd());
+			}else if(buttonInfoVO.getLinkType().equals("BC")) {
+				// 상담톡 진행시 등록해야함
+			}else if(buttonInfoVO.getLinkType().equals("BT")) {
+				// 봇 전환 시 전달
+			}
+			buttonList.add(buttonInfo);
+		}
+		
+		// 강조유형 JSON 생성
+		JSONObject templateDetailInfo = new JSONObject();
+		String emphasizeType = templateDetail.getTemplateEmphasizeType();
+		
+		
+		if(emphasizeType.equals("TEXT")) {
+			templateDetailInfo.put("title", sendVO.getTemplateTitle());
+		}else if(emphasizeType.equals("IMAGE")) {
+			templateDetailInfo.put("msg_type", "ai");
+		}
+		
+		
+		JSONObject jo = new JSONObject();
+		
+		if(buttonList.size() != 0) {
+			jo.put("button", buttonList);
+		}
+		if(templateDetailInfo.size() != 0) {
+			jo.put("extra", templateDetailInfo);
+		}
+		
+		// 입력 json 데이터를 파일로 변경
+		String jsonStr = jo.toString();
+		
+		return jsonStr;
+	}
+	
 	public String kakaoApiJsonSave(KakaoVO kakaoVO, String[] varValInfo) {
 		// json파일 저장
 		
@@ -109,12 +161,12 @@
 					for(int i=0; i < varNm.length; i++) {
 						for(int j=0; j < varValInfo.length; j++) {
 							if (templateTitle.indexOf(varNm[i]) > -1) {
-				 				if(varValInfo[j] != null) {
-				 					templateTitle = templateTitle.replaceAll(varNm[i] , StringUtil.getString(varValInfo[j]));
-				 				}else {
-				 					templateTitle = templateTitle.replaceAll(varNm[i] , "");
-				 				}
-				 			}
+								if(varValInfo[j] != null) {
+									templateTitle = templateTitle.replaceAll(varNm[i] , StringUtil.getString(varValInfo[j]));
+								}else {
+									templateTitle = templateTitle.replaceAll(varNm[i] , "");
+								}
+							}
 						}
 					}
 					
@@ -140,8 +192,8 @@
 			
 			// 입력 json 데이터를 파일로 변경
 			String jsonStr = jo.toString();
-			System.out.println("jsonFileName  : "+jsonFileName);
-		
+//			System.out.println("jsonFileName  : "+jsonFileName);
+			
 			File outPut = new File(jsonFileName);
 			outPut.createNewFile();
 			
src/main/java/itn/let/kakao/user/kakaoAt/service/KakaoAlimTalkService.java
--- src/main/java/itn/let/kakao/user/kakaoAt/service/KakaoAlimTalkService.java
+++ src/main/java/itn/let/kakao/user/kakaoAt/service/KakaoAlimTalkService.java
@@ -2,7 +2,11 @@
 
 import java.util.List;
 
+import javax.servlet.http.HttpServletRequest;
+
+import itn.let.kakao.kakaoComm.KakaoSendAdvcVO;
 import itn.let.kakao.kakaoComm.KakaoVO;
+import itn.let.mail.service.StatusResponse;
 import itn.let.mjo.msgdata.service.MjonMsgReturnVO;
 
 public interface KakaoAlimTalkService {
@@ -24,5 +28,7 @@
 	
 	//카카오 친구톡 전송 실패 환불리스트 조회
 	public void selectKakaoFtSentRefundList() throws Exception;
+
+	StatusResponse insertKakaoAtSandAjax_advc(KakaoVO kakaoVO, HttpServletRequest request) throws Exception;
 	
 }
src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkDAO.java
--- src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkDAO.java
+++ src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkDAO.java
@@ -6,6 +6,7 @@
 import org.springframework.stereotype.Repository;
 
 import egovframework.rte.psl.dataaccess.EgovAbstractDAO;
+import itn.let.kakao.kakaoComm.KakaoSendAdvcVO;
 import itn.let.kakao.kakaoComm.KakaoVO;
 
 @Repository("kakaoAlimTalkDAO")
@@ -39,15 +40,6 @@
 		} catch (Exception e) {
 			System.out.println("++++++++++++++++++++ selectDeleteProfileInfo DAO Error !!! " + e);
 		}
-		
-		return result;
-	}
-	
-	public int insertKakaoAtDataInfo(List<KakaoVO> kakaoAtSandList) throws Exception{
-		
-		int result = 0;
-		
-		result = update("kakaoAlimTalkDAO.insertKakaoAtDataInfo", kakaoAtSandList);
 		
 		return result;
 	}
@@ -94,4 +86,26 @@
 	public void updateKakaoFtNotSend(KakaoVO kakaoVO) {
 		select("kakaoAlimTalkDAO.updateKakaoFtNotSend", kakaoVO);
 	}
+	
+	public int insertKakaoAtDataInfo(List<KakaoVO> kakaoAtSandList) throws Exception{
+		
+		int result = 0;
+		
+		result = update("kakaoAlimTalkDAO.insertKakaoAtDataInfo", kakaoAtSandList);
+		
+		return result;
+	}
+
+	public int insertKakaoAtDataInfo_advc(List<KakaoSendAdvcVO> kakaoSendAdvcVOList) {
+		
+		return update("kakaoAlimTalkDAO.insertKakaoAtDataInfo_advc", kakaoSendAdvcVOList);
+	}
+
+	public void insertKakaoAtDataJsonInfo_advc(List<KakaoSendAdvcVO> kakaoSendAdvcVOList) {
+		insert("kakaoAlimTalkDAO.insertKakaoAtDataJsonInfo_advc", kakaoSendAdvcVOList);
+	}
+
+	public void insertKakaoGroupDataTb_advc(KakaoSendAdvcVO sendVO) {
+		insert("kakaoAlimTalkDAO.insertKakaoGroupDataTb_advc", sendVO);
+	}
 }
src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java
--- src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java
+++ src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java
@@ -1,19 +1,40 @@
 package itn.let.kakao.user.kakaoAt.service.impl;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
+import java.time.Duration;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
 
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
 
 import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
 import egovframework.rte.fdl.idgnr.EgovIdGnrService;
+import egovframework.rte.fdl.security.userdetails.util.EgovUserDetailsHelper;
+import itn.com.cmm.LoginVO;
+import itn.com.cmm.MjonMsgSendVO;
+import itn.com.utl.fcc.service.EgovStringUtil;
+import itn.let.kakao.kakaoComm.KakaoSendAdvcVO;
+import itn.let.kakao.kakaoComm.KakaoSendUtil;
 import itn.let.kakao.kakaoComm.KakaoVO;
 import itn.let.kakao.user.kakaoAt.service.KakaoAlimTalkService;
+import itn.let.mail.service.StatusResponse;
+import itn.let.mjo.mjocommon.MjonCommon;
 import itn.let.mjo.mjocommon.MjonHolidayApi;
 import itn.let.mjo.msg.service.MjonMsgVO;
 import itn.let.mjo.msg.service.impl.MjonMsgDAO;
@@ -24,9 +45,14 @@
 import itn.let.mjo.msgholiday.service.impl.MsgHolidayDAO;
 import itn.let.mjo.pay.service.MjonPayService;
 import itn.let.mjo.pay.service.MjonPayVO;
+import itn.let.module.base.PriceAndPoint;
 import itn.let.sym.site.service.JoinSettingVO;
 import itn.let.sym.site.service.impl.SiteManagerDAO;
+import itn.let.uss.umt.service.EgovUserManageService;
+import itn.let.uss.umt.service.UserManageVO;
+import lombok.extern.slf4j.Slf4j;
 
+@Slf4j
 @Service("kakaoAlimTalkService")
 public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements KakaoAlimTalkService{
 
@@ -47,12 +73,28 @@
 	
 	@Resource(name = "egovMjonMsgIdGnrService")
 	private EgovIdGnrService idgenMsgId;
+
+	@Resource(name = "egovMjonMsgGroupIdGnrService")
+	private EgovIdGnrService idgenMjonMsgGroupId;
 	
 	@Resource(name = "mjonPayService")
 	private MjonPayService mjonPayService;
 	
 	@Resource(name = "egovMjonCashIdGnrService")
 	private EgovIdGnrService idgenMjonCashId;
+
+	/** userManageService */
+	@Resource(name = "userManageService")
+	private EgovUserManageService userManageService;
+	
+	@Autowired
+	KakaoSendUtil kakaoSendUtil;
+
+	@Autowired
+	private MjonCommon mjonCommon;
+	
+	@Autowired
+	private PriceAndPoint priceAndPoint;
 	
 	//발신프로필 상태값 변경(삭제/복구 기능)
 	@Override
@@ -816,4 +858,341 @@
 			}
 		}
 	}
+
+	@Override
+	public StatusResponse insertKakaoAtSandAjax_advc(KakaoVO kakaoVO, HttpServletRequest request) throws Exception {
+
+		log.info(" :: [{}]", kakaoVO.toString());
+
+		
+		// 측정할 메소드 호출 전 시간 기록
+		Instant start = Instant.now();
+//		KakaoSendAdvcVO
+		
+		Map<String, Object> returnMap = new HashMap<>();
+
+		LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()
+				? (LoginVO) EgovUserDetailsHelper.getAuthenticatedUser()
+				: null;
+		String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
+
+		if (userId.equals("")) {
+			return new StatusResponse(HttpStatus.BAD_REQUEST, "로그인 후 이용이 가능합니다.");
+		}
+		
+		kakaoVO.setUserId(userId);
+
+		/**
+		 * 회원 정지된 상태이면 문자 발송이 안되도록 처리함 현재 로그인 세션도 만료 처리함
+		 */
+		boolean mberSttus = userManageService.selectUserStatusInfo(userId);
+		if (!mberSttus) {
+			request.getSession().invalidate();
+			// UNAUTHORIZED : 인증되지 않은 사용자가 접근하려고 할 때
+			return new StatusResponse(HttpStatus.UNAUTHORIZED,
+					"현재 고객님께서는 문자온 서비스 이용이 정지된 상태로 알림톡을 발송하실 수 없습니다. 이용정지 해제를 원하시면 고객센터로 연락주시기 바랍니다.");
+		}
+		
+
+		StatusResponse statusResponse = new StatusResponse();
+
+/** @isHolidayNotified 
+ * @false : 알림 X
+ * @true  : 알림 O */
+		boolean isNotified = mjonCommon.processUserAndCheckAT(kakaoVO);
+		
+		
+/** @LETTNGNRLMBER 사용자 정보 -> 스미싱의심 여부 */
+		UserManageVO userManageVO = mjonCommon.getUserManageInfo(userId);
+		kakaoVO.setAtSmishingYn(userManageVO.getAtSmishingYn());
+		
+/** @카카오톡 전송 list 셋팅 -------------------------------------------*/
+		List<KakaoSendAdvcVO> kakaoSendAdvcListVO = kakaoSendUtil.populateSendLists(kakaoVO, isNotified, statusResponse);
+		if (statusResponse.getStatus() != null && !statusResponse.getStatus().equals(HttpStatus.OK)) {
+			log.error(" + populateSendLists 처리 중 오류 발생: {}", statusResponse.getMessage());
+			return statusResponse;
+		}
+
+		
+		
+/** @전송금액 확인 --------------------------------------------------*/
+		if (!isCashSufficient(userId, kakaoSendAdvcListVO)) {
+			log.error("Insufficient balance for message sending.");
+			return new StatusResponse(HttpStatus.BAD_REQUEST, "문자 발송에 필요한 보유 잔액이 부족 합니다.");
+		}
+
+		
+		
+		Map<String, List<KakaoSendAdvcVO>> priceGroupedMessages = kakaoSendAdvcListVO.stream()
+				.collect(Collectors.groupingBy(KakaoSendAdvcVO::getEachPrice));
+		
+
+		// instTotalCnt : 화면에서 보여줄 총 발송건수
+		int instTotalCnt = 0;
+		// 임시
+		List<String> nextMsgGroupIdA = new ArrayList<>();
+			// 대안: entrySet() 직접 사용
+		for (Map.Entry<String, List<KakaoSendAdvcVO>> entry : priceGroupedMessages.entrySet()) {
+			    // entry 사용
+
+			List<KakaoSendAdvcVO> groupedMsgList = entry.getValue(); // 해당 가격의 메시지 리스트
+
+			String nextMsgGroupId = idgenMjonMsgGroupId.getNextStringId();
+			groupedMsgList.forEach(t -> t.setMsgGroupId(nextMsgGroupId));
+			
+
+			// 발송 데이터 삽입
+			int instCnt = this.insertKakaoData_advc(groupedMsgList);
+//			int instCnt = 6;
+			
+			if(instCnt > 0) {
+
+				instTotalCnt += instCnt;
+
+				KakaoSendAdvcVO sendVO = groupedMsgList.get(0);
+
+/** @groupData 테이블 insert */
+				this.insertKakaoGroupDataTb_advc(instCnt, kakaoVO, sendVO);
+
+
+/** @biz_kakao_price에 insert (대체문자 환불관련 테이블)*/ 
+				kakaoVO.setMsgGroupId(sendVO.getMsgGroupId());
+				kakaoVO.setKakaoAtPrice(Float.parseFloat(sendVO.getEachPrice()));
+				kakaoVO.setSmsPrice(Float.parseFloat(sendVO.getSmsPrice()));
+				kakaoVO.setMmsPrice(Float.parseFloat(sendVO.getMmsPrice()));
+				
+				kakaoAlimTalkDAO.insertKakaoSendPrice(kakaoVO);
+				
+				
+				priceAndPoint.insertCashAndPoint(kakaoVO.getUserId()
+						, -Float.parseFloat(sendVO.getTotPrice())
+						, "카카오 알림톡 총 "+groupedMsgList.size()+"건 중 " + instCnt + "건 발송"
+						, nextMsgGroupId
+					);
+
+
+/** @SLACK발송 */ 
+				/** @발송조건이되면 발송 */ 
+				if(isNotified) {
+					mjonCommon.getAdminKakaoAtSendSlack(kakaoVO);
+				}else if("Y".equals(kakaoVO.getAtSmishingYn())){
+				/** @발송조건이 안되면 DB INSERT */ 
+					mjonMsgDAO.insertSpamPassMsgData(MjonMsgVO.builder()
+							.msgGroupId(nextMsgGroupId)
+							.userId(kakaoVO.getUserId())
+							.reqDate(kakaoVO.getReqDate())
+							.smsTxt(groupedMsgList.get(0).getTemplateContent())
+							.totalCallCnt(instCnt)
+							.callFrom(kakaoVO.getCallFrom())
+							.msgType("8")
+							.reserveYn(kakaoVO.getReserveYn())
+							.build()
+						);
+				}
+				
+				nextMsgGroupIdA.add(nextMsgGroupId);
+				
+			}
+			
+		}
+
+		returnMap.put("resultSts", instTotalCnt);
+		returnMap.put("reserYn", kakaoVO.getReserveYn());
+		returnMap.put("groupIds", nextMsgGroupIdA);
+		
+		
+		// 측정할 메소드 호출 후 시간 기록
+		Instant end = Instant.now();
+
+		log.info(" + start :: [{}]", start);
+		// 실행 시간 계산 (나노초, 밀리초, 초)
+		long seconds = Duration.between(start, end).getSeconds();
+		System.out.println("메소드 실행 시간 (초): " + seconds + " s");
+		double minutes = seconds / 60.0; // 소수점 포함을 위해 60.0으로 나눔
+
+		returnMap.put("second", seconds+" s");
+		returnMap.put("minutes", minutes+" min");
+		
+
+//		System.out.println("메소드 실행 시간 (분): " + minutes + " min");
+		
+		
+		
+		
+//		priceAndPoint.getBefCash(userId);
+		
+		
+		
+
+		statusResponse.setStatus(HttpStatus.OK);
+		statusResponse.setObject(returnMap);
+		
+		return statusResponse;
+	}
+	
+	
+
+
+	private void insertKakaoGroupDataTb_advc(int instCnt, KakaoVO kakaoVO, KakaoSendAdvcVO sendVO) throws Exception {
+		// TODO Auto-generated method stub
+
+//		log.info(" + insertKakaoGroupDataTb_advc kakaoVO :: \n[{}]", kakaoVO.toString());;
+//		log.info(" + insertKakaoGroupDataTb_advc kakaoSendAdvcVOList :: \n[{}]", sendVO.toString());
+		
+		sendVO.setMsgGroupCnt(Integer.toString(instCnt));
+		sendVO.setReserveYn(kakaoVO.getReserveYn());
+		sendVO.setBefCash(priceAndPoint.getBefCash(sendVO.getUserId()));
+		sendVO.setBefPoint(priceAndPoint.getBefPoint(sendVO.getUserId()));
+		
+		Float eachPrice = Float.parseFloat(sendVO.getEachPrice());
+
+		Float totPrice = eachPrice * instCnt;
+		sendVO.setTotPrice(String.format("%.1f", totPrice));
+		
+		sendVO.setAtDelayYn(kakaoVO.getAtSmishingYn()); 
+		sendVO.setBizKakaoResendOrgnlTxt(kakaoVO.getSubMsgTxt());
+		sendVO.setBizKakaoResendType(sendVO.getSubMsgType());
+		
+		kakaoAlimTalkDAO.insertKakaoGroupDataTb_advc(sendVO);
+		
+	}
+
+	/**
+	 * @methodName	: insertKakaoData_advc 
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 20.
+	 * @description	: 카카오 batch 발송 => mj_msg_data
+	 * @return : int
+	 * @param kakaoSendAdvcVOList
+	 * @param parentLoopCount
+	 * @param isJsonNotEmpty
+	 * @param isJsonNameAllSame
+	 * @return
+	 * 
+	 */
+	private int insertKakaoData_advc(List<KakaoSendAdvcVO> kakaoSendAdvcVOList) {
+
+
+		// 시작 시간 측정
+		long totalStartTime = System.currentTimeMillis();
+
+		int totalSize = kakaoSendAdvcVOList.size(); // 총 데이터 개수
+		// Batch 크기 설정 (고정값)
+//		int batchSize = 10000; 465
+		int batchSize = 50000; // 9분 18초
+
+		log.info("총 데이터 개수 :: [{}] ", totalSize);
+		log.info("설정된 Batch 크기 :: [{}] ", batchSize);
+
+		// 총 insert 카운트
+		int instCnt = 0;
+		int batchCount = 0;
+
+		// 각 배치별 실행 시간 기록
+		List<Double> batchExecutionTimes = new ArrayList<>();
+
+	
+		// 첫 번째 배치에서만 삽입했는지 추적하는 플래그
+		for (int i = 0; i < totalSize; i += batchSize) {
+			// Batch 시작 시간 측정
+			long batchStartTime = System.currentTimeMillis();
+
+			// Batch 리스트 생성
+			List<KakaoSendAdvcVO> batchList = kakaoSendAdvcVOList.subList(i, Math.min(i + batchSize, totalSize));
+			System.out.println("Batch 시작 인덱스: " + i);
+
+			// mj_msg_data 테이블 insert
+			int insertedCount = kakaoAlimTalkDAO.insertKakaoAtDataInfo_advc(batchList);
+			
+			/** @kakaoSendUtil.populateSendLists  
+			 * 하단에서 
+			 * getJsonStr 데이터 처리 후 활용
+			 *  */
+			batchList.removeIf(t -> StringUtils.isBlank(t.getJsonStr()));
+			if(batchList.size() > 0) {
+				kakaoAlimTalkDAO.insertKakaoAtDataJsonInfo_advc(batchList);
+			}
+			instCnt += insertedCount;
+
+			// Batch 종료 시간 측정 및 실행 시간 계산
+			long batchEndTime = System.currentTimeMillis();
+			double batchExecutionTimeInSeconds = (batchEndTime - batchStartTime) / 1000.0;
+
+			// 실행 시간 기록
+			batchExecutionTimes.add(batchExecutionTimeInSeconds);
+			batchCount++;
+		}
+
+		// 종료 시간 측정
+		long totalEndTime = System.currentTimeMillis();
+
+		// 총 실행 시간 계산 (밀리초 -> 초로 변환)
+		double totalExecutionTimeInSeconds = (totalEndTime - totalStartTime) / 1000.0;
+
+		// 실행 시간 출력
+		log.info("총 배치 실행 횟수 :: [{}] ", batchCount);
+		log.info("batchSize :: [{}] ", batchSize);
+		log.info("총 실행 시간 :: [{}] ", totalExecutionTimeInSeconds + "초");
+		log.info("총 삽입 건수 :: [{}] ", instCnt);
+
+		// 각 배치별 실행 시간 출력
+		for (int k = 0; k < batchExecutionTimes.size(); k++) {
+			System.out.println("배치 " + (k + 1) + " 실행 시간 :: " + batchExecutionTimes.get(k) + "초");
+		}
+
+		return instCnt;
+		
+	}
+
+	// 보유 금액이 충분한지 확인하는 메서드
+	private boolean isCashSufficient(String userId, List<KakaoSendAdvcVO> kakaoSendAdvcListVO) throws Exception {
+		
+		
+		String userMoney = priceAndPoint.getBefCash(userId);
+		// 쉼표 제거
+		userMoney = userMoney.replace(",", "");
+
+		// 사용자 보유 금액 BigDecimal 변환 (HALF_EVEN 적용)
+		BigDecimal befCash = new BigDecimal(userMoney).setScale(2, RoundingMode.HALF_EVEN);
+		
+		// 총 메시지 금액 계산 (HALF_EVEN 적용)
+		BigDecimal totalEachPrice = kakaoSendAdvcListVO.stream()
+			.map(msg -> new BigDecimal(String.valueOf(msg.getEachPrice()))) // 변환 오류 방지
+			.reduce(BigDecimal.ZERO, BigDecimal::add)
+			.setScale(2, RoundingMode.HALF_EVEN); // 일관성 유지
+
+		// 비교 수행
+		return befCash.compareTo(totalEachPrice) >= 0;
+	}
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
 }
src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java
--- src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java
+++ src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java
@@ -35,9 +35,11 @@
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.ModelMap;
 import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -59,6 +61,7 @@
 import itn.com.cmm.util.StringUtil;
 import itn.com.utl.fcc.service.EgovStringUtil;
 import itn.let.kakao.kakaoComm.KakaoReturnVO;
+import itn.let.kakao.kakaoComm.KakaoSendAdvcVO;
 import itn.let.kakao.kakaoComm.KakaoSendUtil;
 import itn.let.kakao.kakaoComm.KakaoVO;
 import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiJsonSave;
@@ -67,6 +70,7 @@
 import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiTemplate;
 import itn.let.kakao.kakaoComm.kakaoApi.service.KakaoApiService;
 import itn.let.kakao.user.kakaoAt.service.KakaoAlimTalkService;
+import itn.let.mail.service.StatusResponse;
 import itn.let.mjo.mjocommon.MjonCommon;
 import itn.let.mjo.mjocommon.MjonHolidayApi;
 import itn.let.mjo.msgdata.service.MjonMsgDataService;
@@ -239,6 +243,8 @@
 		
 		
 		return "web/kakao/msgdata/at/KakaoAlimtalkMsgDataView";
+//		return "web/kakao/msgdata/at/KakaoAlimtalkMsgDataView_advcbackup_20250310";
+									
 	}
 	
 	
@@ -1079,6 +1085,16 @@
 		return modelAndView;
 	}
 	
+	@RequestMapping(value= {"/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax_advc.do"}, method = RequestMethod.POST)
+	public ResponseEntity<StatusResponse> kakaoAlimTalkMsgSendAjax_advc(
+			@RequestBody KakaoVO kakaoVO,
+			HttpServletRequest request
+			) throws Exception {
+
+		System.out.println(" + kakaoAlimTalkMsgSendAjax_advc + ");
+		return ResponseEntity.ok().body(kakaoAlimTalkService.insertKakaoAtSandAjax_advc(kakaoVO, request)) ;
+	}
+	
 	@RequestMapping(value= {"/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax.do"}, method = RequestMethod.POST)
 //	@ResponseBody
 	public ModelAndView kakaoAlimTalkMsgSendAjax(
@@ -1086,6 +1102,10 @@
 			HttpServletRequest request,
 			@ModelAttribute("kakaoVO")  KakaoVO kakaoVO
 		) throws Exception {
+		// 시작 시간
+        long startTime = System.currentTimeMillis();
+		
+		System.out.println(" :: kakaoAlimTalkMsgSendAjax :: ");
 		ModelAndView modelAndView = new ModelAndView();		
 		modelAndView.setViewName("jsonView");
 		
@@ -1410,7 +1430,7 @@
 						
 						if(!smishingAlarmPassSts) {//평일,주말, 공휴일 알림설정 시간에 포함되지 않는 경우 슬랙 알림 발송
 							
-							mjonCommon.getAdminKakaoAtSandSlack(kakaoVO);
+							mjonCommon.getAdminKakaoAtSendSlack(kakaoVO);
 							
 						}
 						
@@ -1422,6 +1442,17 @@
 		} catch (Exception e) {
 			throw new Exception("++++++++++++++++++++++ getAdminPhoneSendMsgData Error !!! " + e);
 		}
+		// 종료 시간
+		long endTime = System.currentTimeMillis();
+		
+// 실행 시간 계산 (초 단위)
+		double executionTimeSeconds = (endTime - startTime) / 1000.0;
+		
+		System.out.println("실행 시간: " + String.format("%.3f", executionTimeSeconds) + "초");
+		
+		
+		String returnTxt = String.format("%.3f", executionTimeSeconds) + "초";
+		modelAndView.addObject("seconds", returnTxt);
 		
 		return modelAndView;
 	}
src/main/java/itn/let/kakao/user/kakaoFt/web/KakaoFriendsTalkSendController.java
--- src/main/java/itn/let/kakao/user/kakaoFt/web/KakaoFriendsTalkSendController.java
+++ src/main/java/itn/let/kakao/user/kakaoFt/web/KakaoFriendsTalkSendController.java
@@ -663,7 +663,7 @@
 						if(!smishingAlarmPassSts) {//평일,주말, 공휴일 알림설정 시간에 포함되지 않는 경우 슬랙 알림 발송
 							
 							MjonCommon comm = new MjonCommon();
-							comm.getAdminKakaoAtSandSlack(kakaoVO);
+							comm.getAdminKakaoAtSendSlack(kakaoVO);
 							
 						}
 						
src/main/java/itn/let/mjo/mjocommon/MjonCommon.java
--- src/main/java/itn/let/mjo/mjocommon/MjonCommon.java
+++ src/main/java/itn/let/mjo/mjocommon/MjonCommon.java
@@ -1,10 +1,12 @@
 package itn.let.mjo.mjocommon;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 import javax.annotation.Resource;
 
@@ -14,13 +16,17 @@
 import org.apache.commons.httpclient.methods.PostMethod;
 import org.json.simple.JSONObject;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Service;
 
 import com.mysql.jdbc.StringUtils;
 
+import egovframework.com.idgen.CustomIdGnrService;
+import egovframework.rte.fdl.cmmn.exception.FdlException;
 import itn.com.cmm.MjonMsgSendVO;
 import itn.com.cmm.OptimalMsgResultDTO;
 import itn.com.cmm.util.MsgSendUtils;
+import itn.com.cmm.util.SlackMessageFormatUtil;
 import itn.let.kakao.kakaoComm.KakaoVO;
 import itn.let.mail.service.StatusResponse;
 import itn.let.mjo.event.service.MjonEventService;
@@ -36,7 +42,7 @@
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
-@Service("MjonCommon")
+@Component
 public class MjonCommon {
 	
 
@@ -60,11 +66,14 @@
 	/** xpedite 솔루션 ID*/
 	@Value("#{globalSettings['Globals.slack.channel.name']}")
 	private String SLACK_CHANNEL;
-	
+
+	@Resource(name = "egovMjonMsgIdCGnrService")
+	private CustomIdGnrService idgenMsgCId;
+
 	
 
 	/** 
-	 * @methodName	: getAdminMsgSandSlack 
+	 * @methodName	: getAdminSandSlack 
 	 * @author		: 이호영
 	 * @date		: 2024.12.04 
 	 * @description	: 기존 메소드 리펙토링
@@ -120,8 +129,8 @@
 	
 		try {
 			// 메시지 내용 설정
-			String smsTxt = formatSmsText(mjonMsgVO);
-			String sandName = formatSandName(mjonMsgVO);
+			String smsTxt = SlackMessageFormatUtil.formatSmsText(mjonMsgVO);
+			String sandName = SlackMessageFormatUtil.formatSandName(mjonMsgVO);
 		
 			// Slack 메시지 생성
 			JSONObject json = new JSONObject();
@@ -150,94 +159,49 @@
 		}
 	}
 	
-	/**
-	* @throws Exception 
-	 * @Method Name : getAdminSlackSand
-	* @작성일 : 2022. 12. 6.
-	* @작성자 :  WYH
-	* @Method 설명 : slack 메시지 전송
-	*/
-	/*public void getAdminMsgSandSlack(MjonMsgVO mjonMsgVO) {
-		
+	public void getAdminKakaoAtSendSlack(KakaoVO kakaoVO) {
 		HttpClient client = new HttpClient();
-		PostMethod post = new PostMethod(url);
-		JSONObject json = new JSONObject();
+		PostMethod post = new PostMethod(SLACK_URL);
+
 		try {
- 
-			String reserveYn = mjonMsgVO.getReserveYn();
-			String delayYn = mjonMsgVO.getDelayYn();
-			String smsTxt = mjonMsgVO.getSmsTxt();
-			String smishingYn = mjonMsgVO.getSmishingYn();
-			String reservSmsTxt = "";
-			String smisingSmsTxt = "";
-			//예약문자를 발송하는 경우 문자 내용 앞에 "[예약]" 표시되도록 처리
+			// 메시지 내용 설정
+			String smsTxt = SlackMessageFormatUtil.formatKakaoText(kakaoVO);
+			String sandName = SlackMessageFormatUtil.formatKakaoSandName(kakaoVO);
 			
-			if(reserveYn.equals("Y")) {
-				
-				if(smishingYn.equals("Y") || delayYn.equals("Y")) {
-					reservSmsTxt = "[스미싱의심][예약]" + smsTxt;
-				}else {
-					reservSmsTxt = "[예약]" + smsTxt;
-				}
-				
-				smsTxt = reservSmsTxt;
-				System.out.println("smishingYn : "+ smishingYn);
-				System.out.println("delayYn : "+ delayYn);
-			}else if(smishingYn.equals("Y") || delayYn.equals("Y")) {
-				
-				smisingSmsTxt = "[스미싱의심]" + smsTxt;
-				smsTxt = smisingSmsTxt;
-			}
-			
-			String sandName = mjonMsgVO.getCallFrom();
-			String userId = mjonMsgVO.getUserId();
-			String msgType = "";
-			int fileCount = Integer.parseInt(mjonMsgVO.getFileCnt());//그림 이미지 갯수
-			if(mjonMsgVO.getMsgType().equals("4")) {	//단문 금액
-				msgType = "[단문]";
-			}else if(mjonMsgVO.getMsgType().equals("6")){
-				if(fileCount == 0) {
-					msgType = "[장문]";	
-				}else {
-					msgType = "[그림]";
-					// 2022.12.21 JSP => 텍스트없는 그림문자만 발송시 슬랙알림 안됨
-					if (StringUtils.isNullOrEmpty(smsTxt)) {
-						smsTxt = "그림문자 " + smsTxt;
-					}
-				}
-			}
-//			sandName = "[" + userId + "]" + "[" + sandName + "]" + msgType;
-			sandName = "[개발테스트]"+"[" + userId + "]" + "[" + sandName + "]" + msgType;
-			
-			json.put("channel", "mjon메시지");
+			// Slack 메시지 생성
+			JSONObject json = new JSONObject();
+			json.put("channel", SLACK_CHANNEL);
 			json.put("text", smsTxt);
 			json.put("username", sandName);
 			
-			
+			// Slack 요청
 			post.addParameter("payload", json.toString());
-			// 처음에 utf-8로 content-type안넣어주니까 한글은 깨져서  content-type넣어줌
 			post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
+		
+			// Slack 응답 처리
 			int responseCode = client.executeMethod(post);
-			String response = post.getResponseBodyAsString();
-			if (responseCode != HttpStatus.SC_OK) { 
-				System.out.println("Response: " + response);
+			if (responseCode != HttpStatus.SC_OK) {
+				log.warn("Slack 메시지 전송 실패. Response: {}", post.getResponseBodyAsString());
 			}
 		} catch (IllegalArgumentException e) {
-			System.out.println("IllegalArgumentException posting to Slack " + e);
-		} 
-		catch (IOException e) {
-			System.out.println("IOException posting to Slack " + e);
-		} 
-		catch (Exception e) {
-			System.out.println("Exception posting to Slack " + e);
-			e.printStackTrace();
+			log.error("Slack 메시지 전송 중 IllegalArgumentException 발생", e);
+		} catch (IOException e) {
+			log.error("Slack 메시지 전송 중 IOException 발생", e);
+		} catch (Exception e) {
+			log.error("Slack 메시지 전송 중 Exception 발생", e);
 		} finally {
 			post.releaseConnection();
 		}
-		
-	}*/
+	}
 	
+	private String formatKakaoSandName(KakaoVO kakaoVO) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
 	
+
+
 	/**
 	* @Method Name : sendSimpleSlackMsg
 	* @작성일 : 2022. 12. 9
@@ -384,7 +348,7 @@
 		
 		return mjonMsgVO;
 	}
-	
+	/*
 	@SuppressWarnings("unchecked")
 	public void getAdminKakaoAtSandSlack(KakaoVO kakaoVO) {
 		
@@ -448,7 +412,7 @@
 		}
 		
 	}
-	
+	*/
 	
 	public String getCreateMsgUserIdgen(String subUserId, String lastId) throws Exception{
 		
@@ -485,27 +449,6 @@
 
 
 
-private String formatSmsText(MjonMsgVO mjonMsgVO) {
-    String smsTxt = mjonMsgVO.getSmsTxt();
-    String reserveYn = safeGetString(mjonMsgVO.getReserveYn());
-    String delayYn = safeGetString(mjonMsgVO.getDelayYn());
-    String smishingYn = safeGetString(mjonMsgVO.getSmishingYn());
-
-    // 예약 문자와 스미싱 의심 처리
-    if ("Y".equals(reserveYn)) {
-        smsTxt = ("Y".equals(smishingYn) || "Y".equals(delayYn)) ? "[스미싱의심][예약]" + smsTxt : "[예약]" + smsTxt;
-    } else if ("Y".equals(smishingYn) || "Y".equals(delayYn)) {
-        smsTxt = "[스미싱의심]" + smsTxt;
-    }
-
-    // 그림 문자 처리
-    int fileCount = parseIntOrDefault(mjonMsgVO.getFileCnt(), 0);
-    if ("6".equals(mjonMsgVO.getMsgType()) && fileCount > 0 && StringUtils.isNullOrEmpty(smsTxt)) {
-        smsTxt = "그림문자 " + smsTxt;
-    }
-
-    return smsTxt;
-}
 
 private String formatSandName(MjonMsgVO mjonMsgVO) {
     String userId = mjonMsgVO.getUserId();
@@ -542,7 +485,18 @@
 	
 	
 
-	// 전체 로직 처리 (한 번에 모든 필요한 정보 반환)
+	/**
+	 * @methodName	: processUserAndCheckSms 
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 25.
+	 * @description	: SMS 알림 전체 로직 처리 (한 번에 모든 필요한 정보 반환)
+	 * @return : boolean
+	 * @param mjonMsgVO
+	 * @param userId
+	 * @return
+	 * @throws Exception
+	 * 
+	 */
 	public boolean processUserAndCheckSms(MjonMsgVO mjonMsgVO, String userId) throws Exception {
 		UserManageVO userManageVO = getUserManageInfo(userId);
 
@@ -556,9 +510,39 @@
 			mjonMsgVO.setSmishingYn(smishingYn); // MjonMsgVO에 스미싱 정보 설정
 
 			// 스미싱 알림 처리
-			return handleSmishingAlert(mjonMsgVO); // 알림 처리 결과 반환
+			return handleSmishingAlert(); // 알림 처리 결과 반환
 		}
 
+		return false; // 알림 처리되지 않음
+	}
+	
+	/**
+	 * @methodName	: processUserAndCheckAT 
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 25.
+	 * @description	: SMS 알림 전체 로직 처리 (한 번에 모든 필요한 정보 반환)
+	 * @return : boolean
+	 * @param mjonMsgVO
+	 * @param userId
+	 * @return
+	 * @throws Exception
+	 * 
+	 */
+	public boolean processUserAndCheckAT(KakaoVO kakaoVO) throws Exception {
+		UserManageVO userManageVO = getUserManageInfo(kakaoVO.getUserId());
+		
+		// 기본값 처리된 사용자 정보와 문자 상태
+		String adminSmsNoticeYn = userManageVO.getAdminSmsNoticeYn();
+		String atSmishingYn = userManageVO.getAtSmishingYn();
+		
+		// 조건 체크
+		if ("Y".equals(adminSmsNoticeYn) || "Y".equals(atSmishingYn)) {
+			kakaoVO.setAtSmishingYn(atSmishingYn); // MjonMsgVO에 스미싱 정보 설정
+			
+			// 스미싱 알림 처리
+			return handleSmishingAlert(); // 알림 처리 결과 반환
+		}
+		
 		return false; // 알림 처리되지 않음
 	}
 
@@ -572,18 +556,28 @@
 	}
 
 	// 스미싱 알림 처리
-	public boolean handleSmishingAlert(MjonMsgVO mjonMsgVO) throws Exception {
+	public boolean handleSmishingAlert() throws Exception {
+		/**
+		 * MJ_MBER_SETTING => 기본 시스템 알림 여부
+		 * 슬랙 Y
+		 * 야간스미싱알림 Y
+		 * 등등
+		 *
+		 */
 		JoinSettingVO joinSettingVO = egovSiteManagerService.selectAdminNotiDetail();
 		
+/** @시스템 설정에 야간스미싱 알림 || 슬랙알림이 N이면 false*/
 		if (joinSettingVO == null || !"Y".equals(joinSettingVO.getHoliSmishingNoti()) || 
 			!"Y".equals(joinSettingVO.getSlackNoti())) {
 			return false; // 알림 조건 미충족
 		}
 
-		// 알림 조건 충족 시 추가 작업
+/** @MJ_SPAMPASS_ALARM : 현재 활성화된 알림 SELECT */ 
 		List<MsgAlarmSetVO> alarmList = getAlarmSettings();
+/** @MJ_HOLIDAY 시스템에 등록된 공휴일 설정 */
 		List<MsgHolidayVO> holidayList = getHolidayList();
-		boolean isNotificationAllowed = new MjonHolidayApi().getHolidaySmishingPassStatus(alarmList, holidayList);
+/** @MJ_HOLIDAY 시스템에 등록된 공휴일 설정 */
+		boolean isNotificationAllowed = new MjonHolidayApi().getHolidaySmishingPassStatus_advc(alarmList, holidayList);
 
 		return !isNotificationAllowed; // 알림 발송 조건 미충족
 	}
@@ -699,9 +693,55 @@
 	
 
 
+	public List<String> getNextCustomMsgCId (int cnt) throws FdlException {
+
+		List<String> idList = idgenMsgCId.getNextStringId(cnt);
+		return idList;
+		
+	}
 	
 	
-	
+	/** 
+	 * @methodName	: getSmsTxtBytes 
+	 * @author		: 이호영
+	 * @date		: 2024.09.23 
+	 * @description	: sms 텍스트 바이트 계산 후 return;
+	 * @param smsTxt
+	 * @return
+	 * @throws UnsupportedEncodingException 
+	 */
+	public static int getSmsTxtBytes(String smsTxt) throws UnsupportedEncodingException {        	//문자열 길이 체크 해주기
+		int smsBytes = 0;
+		//문자 바이트 계산에 필요한 캐릭터 셋 : 한글 2Byte로 계산
+		String charset = "euc-kr"; 						
+		if(org.apache.commons.lang3.StringUtils.isNotEmpty(smsTxt)) {
+			String smsCont = smsTxt.replace("\r\n", "\n");
+			smsBytes = smsCont.getBytes(charset).length;
+		}
+//		log.info(" + smsBytes :: [{}]", smsBytes);
+		return smsBytes;
+	}
+
+
+	/**
+	 * @methodName	: replaceTemplateVariables 
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 12.
+	 * @description	: 헬퍼 메서드: 템플릿 변수 치환
+	 * @return : String
+	 * @param content
+	 * @param variables
+	 * @return
+	 */
+	public static String ATReplaceTemplateVariables(String content, Map<String, String> variables) {
+		String result = content;
+		for (Map.Entry<String, String> entry : variables.entrySet()) {
+			String placeholder = entry.getKey();
+			String value = entry.getValue();
+			result = result.replace(placeholder, value);
+		}
+		return result;
+	}
 	
 	
 	
src/main/java/itn/let/mjo/mjocommon/MjonHolidayApi.java
--- src/main/java/itn/let/mjo/mjocommon/MjonHolidayApi.java
+++ src/main/java/itn/let/mjo/mjocommon/MjonHolidayApi.java
@@ -231,4 +231,71 @@
 		return smishingAlarmPassSts;
 	}
 	
+	/**
+	 * @methodName	: getHolidaySmishingPassStatus_advc
+	 * @author		: 이호영
+	 * @date		: 2025. 3. 19.
+	 * @description	: getHolidaySmishingPassStatus 개선 버전
+	 * @return : boolean
+	 * @param resultAlarmList
+	 * @param resultHolidayList
+	 * @return
+	 * @throws Exception
+	 * 
+	 */
+	public boolean getHolidaySmishingPassStatus_advc(List<MsgAlarmSetVO> alarmList, List<MsgHolidayVO> holidayList) throws Exception{
+		
+		Date now = new Date(); // 현재 시스템 시간
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 날짜-시간 포맷 (예: 2025-03-18 14:30)
+		
+		// 현재 날짜와 요일 계산
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(now);
+		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1(일요일) ~ 7(토요일)
+		// 오늘 날짜를 "yyyy-MM-dd" 형식으로 포맷팅 (mj_holiday.HOLIDAY_DATE와 비교용)
+		String today = String.format("%d-%02d-%02d", 
+		    cal.get(Calendar.YEAR), 
+		    cal.get(Calendar.MONTH) + 1, // Calendar.MONTH는 0부터 시작하므로 +1
+		    cal.get(Calendar.DATE));
+	
+		// 공휴일 여부 확인
+		// mj_holiday 테이블의 HOLIDAY_DATE와 오늘 날짜가 일치하는지 체크
+		// HOLIDAY_DATE는 'yyyy-MM-dd' 형식으로 저장됨 (예: '2025-01-01')
+		boolean isHoliday = holidayList.stream()
+				.anyMatch(holiday -> today.equals(holiday.getHolidayDate()));
+	
+		// 알람 설정 순회
+		// alarmList는 MsgAlarmSetVO 객체의 리스트로, 알람 타입과 시작/종료 시간을 포함
+		for (MsgAlarmSetVO alarm : alarmList) {
+			String alarmType = alarm.getAlarmType(); // 알람 유형: 'W'(평일), 'E'(주말), 'H'(공휴일)
+			// 오늘 날짜에 알람 시작/종료 시간을 붙여 Date 객체로 변환
+			Date start = sdf.parse(today + " " + alarm.getAlarmStart()); // 예: "2025-03-18 09:00"
+			Date end = sdf.parse(today + " " + alarm.getAlarmEnd());     // 예: "2025-03-18 18:00"
+		
+			// 현재 시간이 알람 시작~종료 시간 범위 내에 있는지 확인
+			boolean isWithinTime = now.after(start) && now.before(end);
+			if (!isWithinTime) continue; // 시간 범위 밖이면 다음 알람으로
+		
+			// 평일 체크 (월~금: dayOfWeek 2~6)
+			// alarmType 'W'는 평일에만 적용
+			if (dayOfWeek > 1 && dayOfWeek < 7 && alarmType.equals("W")) {
+				return true; // 평일이고, 시간이 맞고, 타입이 'W'면 스미싱 알람 통과
+			}
+			// 주말 체크 (일:1, 토:7)
+			// alarmType 'E'는 주말에만 적용
+			else if ((dayOfWeek == 1 || dayOfWeek == 7) && alarmType.equals("E")) {
+				return true; // 주말이고, 시간이 맞고, 타입이 'E'면 스미싱 알람 통과
+			}
+			// 공휴일 체크
+			// alarmType 'H'는 mj_holiday에 등록된 공휴일에 적용
+			// HOLIDAY_TYPE(1:법정, 2:임시, 3:기타)과 관계없이 날짜만 확인
+			else if (isHoliday && alarmType.equals("H")) {
+				return true; // 공휴일이고, 시간이 맞고, 타입이 'H'면 스미싱 알람 통과
+			}
+		}
+		
+		// 모든 조건에 부합하지 않으면 false 반환 (스미싱 알람 비활성화)
+		return false;
+	}
+	
 }
src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java
--- src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java
+++ src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java
@@ -7,12 +7,18 @@
 
 import itn.com.cmm.ComDefaultVO;
 import itn.com.cmm.MjonMsgSendVO;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Getter;
+import lombok.NoArgsConstructor;
 import lombok.Setter;
 
 @JsonIgnoreProperties(ignoreUnknown = true)
 @Getter
 @Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
 public class MjonMsgVO extends ComDefaultVO{
 	
 	private static final long serialVersionUID = 1L;
src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java
--- src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java
+++ src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java
@@ -4061,7 +4061,7 @@
 
 		System.out.println("================================");
 		// 스팸 및 스미싱 의심이면 slack 알림
-		boolean isHolidayNotified = mjonCommon.handleSmishingAlert(mjonMsgVO);
+		boolean isHolidayNotified = mjonCommon.handleSmishingAlert();
 		
 		
 		// 스팸관련 키워드 select
@@ -4095,7 +4095,9 @@
 		MsgSendUtils.setPriceforVO(mjonMsgVO, mjonMsgSendVOList, sysJoinSetVO, mberManageVO);
 
 		// msg_id 대량 생성
-		List<String> idList = idgenMsgCId.getNextStringId(mjonMsgSendVOList.size());
+		
+//		List<String> idList = idgenMsgCId.getNextStringId(mjonMsgSendVOList.size());
+		List<String> idList = mjonCommon.getNextCustomMsgCId(mjonMsgSendVOList.size());
 		for (int i = 0; i < mjonMsgSendVOList.size(); i++) {
 			mjonMsgSendVOList.get(i).setMsgId(idList.get(i));
 		}
@@ -4136,7 +4138,6 @@
 		int instTotalCnt = 0;
 		// Step 2: 그룹화 된 데이터를 그룹별로 insert 처리
 		for (Map.Entry<String, List<MjonMsgSendVO>> entry : priceGroupedMessages.entrySet()) {
-			String price = entry.getKey(); // 가격 (String)
 			List<MjonMsgSendVO> groupedMsgList = entry.getValue(); // 해당 가격의 메시지 리스트
 			
 			// msgGroupId 생성
@@ -4172,7 +4173,7 @@
 			// 수신거부 목록 업데이트
 //			returnMap.put("resultSts", instCnt);
 
-			log.debug("가격 [{}]의 총 갯수: [{}]", price, groupedMsgList.size());
+			log.debug("가격 [{}]의 총 갯수: [{}]", entry.getKey(), groupedMsgList.size());
 
 		}
 
src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java
--- src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java
+++ src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java
@@ -2090,16 +2090,8 @@
 	    		
 	    	}
 
-	        long startTime = System.currentTimeMillis(); // 시작 시간 측정
-	        
 	    	List<AddrVO> resultAddrList = mjonMsgDataService.selectMsgAddrListAjax(addrVO);
 
-	        long endTime = System.currentTimeMillis(); // 종료 시간 측정
-
-	        long elapsedTime = endTime - startTime; // 소요 시간 계산
-	        System.out.println("소요 시간: " + elapsedTime + " 밀리초");
-	        
-	        
 	    	
 	    	modelAndView.addObject("resultAddrList", resultAddrList);
 	    	modelAndView.addObject("result", "success");
src/main/resources/egovframework/sqlmap/let/mjo/kakao/Kakao_AT_SQL_Mysql.xml
--- src/main/resources/egovframework/sqlmap/let/mjo/kakao/Kakao_AT_SQL_Mysql.xml
+++ src/main/resources/egovframework/sqlmap/let/mjo/kakao/Kakao_AT_SQL_Mysql.xml
@@ -4,9 +4,10 @@
   =========     =======    =================================================
   2023.02.02       우영두	
 -->
-<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
+<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
 <sqlMap namespace="kakaoAlimTalk">
 	<typeAlias  alias="kakaoVO" type="itn.let.kakao.kakaoComm.KakaoVO"/>
+	<typeAlias  alias="kakaoSendAdvcVO" type="itn.let.kakao.kakaoComm.KakaoSendAdvcVO"/>
 	
 	<insert id="kakaoAlimTalkDAO.insertKakaoAtDataInfo" parameterClass="java.util.List">
 		INSERT INTO MJ_MSG_DATA
@@ -54,6 +55,119 @@
 		</iterate>
 	</insert>
 	
+	<insert id="kakaoAlimTalkDAO.insertKakaoAtDataInfo_advc" parameterClass="java.util.List">
+		INSERT INTO MJ_MSG_DATA
+		(
+			MSG_ID
+			, MSG_GROUP_ID
+			, USER_ID
+			, AGENT_CODE
+			, CUR_STATE
+			
+			, MSG_NOTICETALK_SENDER_KEY
+			, MSG_NOTICETALK_TMP_KEY
+			, CALL_TO
+			, CALL_FROM
+			, MSG_TYPE
+			
+			, SMS_TXT
+			, BIZ_KAKAO_TITLE
+			
+			, BIZ_KAKAO_RESEND_YN
+			, BIZ_KAKAO_RESEND_DATA
+			, BIZ_KAKAO_RESEND_TYPE
+			, BIZ_KAKAO_JSON_FILE
+			, REQ_DATE
+		)VALUES
+		<iterate conjunction=",">
+		(
+			#[].msgId#
+			, #[].msgGroupId#
+			, #[].userId#
+			, #[].agentCode#
+			, 0
+			
+			, #[].senderKey#
+			, #[].templateCode#
+			, #[].callTo#
+			, #[].callFrom#
+			, #[].msgType#
+			
+			, #[].templateContent#
+			, #[].templateTitle#
+			
+			, #[].subMsgSendYn#
+			, #[].subMsgTxt#
+			, #[].subMsgType#
+			, #[].bizJsonName#
+			, #[].reqDate#
+		)
+		</iterate>
+	</insert>
+	<insert id="kakaoAlimTalkDAO.insertKakaoAtDataJsonInfo_advc" parameterClass="java.util.List">
+		INSERT INTO BIZ_ATTACHMENTS
+		(
+			MSG_KEY
+			, TYPE
+			, CONTENTS
+		)VALUES
+		<iterate conjunction=",">
+		(
+			#[].msgId#
+			, 'JSON'
+			, #[].jsonStr#
+		)
+		</iterate>
+	</insert>
+	
+	<insert id="kakaoAlimTalkDAO.insertKakaoGroupDataTb_advc" parameterClass="kakaoSendAdvcVO">
+		INSERT INTO MJ_MSG_GROUP_DATA
+		(
+            MSG_GROUP_ID,
+            USER_ID,
+            CALL_FROM,
+            SMS_TXT,
+            
+            REQ_DATE,
+            MSG_GROUP_CNT,
+            MSG_TYPE,
+            
+            AGENT_CODE,
+            EACH_PRICE,
+            RESERVE_YN,
+            BEF_CASH,
+            BEF_POINT,
+            
+            TOT_PRICE,
+            
+            AT_DELAY_YN,
+            BIZ_KAKAO_RESEND_ORGNL_TXT,
+            BIZ_KAKAO_RESEND_TYPE
+		)VALUES
+		(
+           #msgGroupId#,
+           #userId#,
+           #callFrom#,
+           #templateContent#,
+
+           #reqDate#,
+           #msgGroupCnt#,
+           #msgType#,
+
+           #agentCode#,
+           #eachPrice#,
+           #reserveYn#,
+           #befCash#,
+           #befPoint#,
+
+           #totPrice#,
+           
+           #atDelayYn#,
+           #bizKakaoResendOrgnlTxt#,
+           #bizKakaoResendType#
+		)
+	</insert>
+	
 	<insert id="kakaoAlimTalkDAO.insertKakaoSendPrice" parameterClass="kakaoVO">
 		INSERT INTO BIZ_KAKAO_PRICE
 		(
src/main/resources/egovframework/sqlmap/let/uss/umt/EgovUserManage_SQL_Mysql.xml
--- src/main/resources/egovframework/sqlmap/let/uss/umt/EgovUserManage_SQL_Mysql.xml
+++ src/main/resources/egovframework/sqlmap/let/uss/umt/EgovUserManage_SQL_Mysql.xml
@@ -1315,6 +1315,7 @@
 			ADMIN_SMS_NOTICE_YN 		AS adminSmsNoticeYn
 			,PRE_PAYMENT_YN				AS prePaymentYn
 			,SMISHING_YN				AS smishingYn
+            ,AT_SMISHING_YN             AS atSmishingYn
 			,AUTO_CASH					AS autoCash
 			,IFNULL(BLINE_CODE, 'N')	AS blineCode
 			,IFNULL(RECOMMEND_ID, '')	AS recommendId
src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp
--- src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp
+++ src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp
@@ -7,6 +7,8 @@
 
 <!-- <script src="/publish/js/content.js"></script> -->
 <!-- 주소록관련 js -->
+
+
 <script type="text/javascript" defer src="<c:out value='/js/kakao/at/init.js' />"></script>
 <script type="text/javascript" src="<c:out value='/js/kakao/at/tabulator.js' />"></script>
 <script type="text/javascript" src="<c:out value='/js/kakao/at/addr.js' />"></script>
@@ -15,7 +17,6 @@
 <script type="text/javascript" src="<c:out value='/js/common/popup.js' />"></script>
 <script type="text/javascript">
 var loginVO = '${loginVO}';
-
 // 체크박스 동적 바인딩
 $(document).on('click','.wrap01C', function(){
 	var total = $(".wrap01C").length;
@@ -87,28 +88,52 @@
 	
 	//선택삭제 버튼 클릭 이벤트
 	$("#select_del").on('click', function(){
-		
-		if($('.wrap01C:checkbox:checked').length < 1)
-		{
-			alert("삭제할 연락처를 선택해주세요.!!");
+
+
+		if(tableL == null || tableL == ""){
+			
+			alert("받는사람을 추가해 주세요.");
 			return false;
+		
 		}
 		
-		$('.wrap01C').each(function(index, item){
-			if($(item).is(':checked'))
-				$(item).parent().parent().remove();
-		});
-		updateTotCnt();
+		var selectedData = tableL.getSelectedRows();
+		
+		if(selectedData == "" || selectedData == null){
+			
+			alert("삭제할 연락처를 선택해주세요.");
+			return false;
+			
+			// 선택한 Row 데이터 삭제하기
+		}else if(confirm("선택하신 받는 사람을 삭제하시겠습니까?")){
+				
+			// 선택 데이터 삭제
+			selectedData.forEach(row => row.delete());
+			
+			
+			totRows = tableL.getRows().length;
+			updateTotCnt(totRows);
+			
+			var smsTxtArea = $('#smsTxtArea').val();
+			
+			//일괄변환 문구 결제금액 처리
+			
+		}
+		
 	});
 
 	//선택삭제 버튼 클릭 이벤트
  	$("#all_del").on('click', function(){
-		
+
+        
 		if(!confirm("받는사람 목록을 모두 삭제하시겠습니까?"))
 			return false;
 		
 		$('#wrap01_body .list_body').remove();
 
+		tableL.clearData();
+		
+		
 		$('#rowTotCnt').text(0);
 		$('#rowDupCnt').text(0);
 	});
@@ -509,19 +534,13 @@
 		return false;
 	}
 	
-	//수신자 목록 체크
-	if($('.phoneArea').length < 1)
-	{
-		alert('받는 사람 입력 후 발송해 주세요');
-		return false;
-	}
 	
 	//수신자 목록 체크
-	if($('.phoneArea').length > 500)
+	/* if($('.phoneArea').length > 500)
 	{
 		alert("최대 발송 건수는 500건 입니다.");
 		return false;
-	}
+	} */
 	
 
 	if($('#errorChk').val() === 'N' 
@@ -550,7 +569,7 @@
 	
 	// 초기화
 	$('.varValList').remove();
-	$('#bizForm #varNmList').val('');
+// 	$('#bizForm #varNmList').val('');
 
 
 	// 대체문자 전송 확인
@@ -613,133 +632,227 @@
 	}else{
 		$('#bizForm #reqDate').val("");
 	}
-	
+
+    var dataList = [];
 	// 치환문자 있는 데이터 파씽
 	if($('#bizForm #txtReplYn').val() === 'Y'){
-		fn_excelDataTransParsing();
+		// fn_excelDataTransParsing();
 		// 치환문자 있는 수신자 리스트 
-		fn_transCallToListParsing();
+		dataList = fn_transCallToListParsing();
 	}else{
-		// 치환문자 없는 수신자 리스트 
-		fn_callToListParsing();
+		// 치환문자 없는 수신자 리스트
+		dataList = fn_callToListParsing();
 	}
 
-	$('#bizForm #senderKey').val($('#selectKakaoProfileList').val());
-	$('#bizForm #templateCode').val($('#selectTemplateList').val());
 	
+
+    //수신자 목록 체크
+    if(dataList.length < 1)
+    {
+        alert('받는 사람 입력 후 발송해 주세요');
+        return false;
+    }
+	
+	
+	// 채널 ID
+	$('#bizForm #senderKey').val($('#selectKakaoProfileList').val());
+    // 채널 > 템플릿
+	$('#bizForm #templateCode').val($('#selectTemplateList').val());
 	// 발신번호
 	$('#bizForm #callFrom').val(removeDash($('#callFromList option:selected').val()));
 	
-	if(confirm("알림톡을 발송하시겠습니까?")){
-		var spamChk = true;
-		//2023.09.06 알림톡 스팸체크 기능 제거요청으로 인한 주석처리
-		/*var spamChk = false;
-		var spmData = new FormData(document.bizForm);
-		$.ajax({
-			type: "POST"
-			, url: "/web/mjon/alimtalk/selectSpamKakaoAlimtalkMsgChkAjax.do"
-			, data: spmData
-			, dataType:'json'
-			, async: false
-			, processData: false
-			, contentType: false
-			, cache: false
-			, success: function (returnData, status) {
-				if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나
-					
-					if("fail" == returnData.result){
-						alert(returnData.message);
-						return false;
-					}else if("loginFail" == returnData.result){
-						alert(returnData.message);
-						return false;
-					}else if("spams" == returnData.result){
-						alert("전송 내용에  스팸문구가 포함되어 있습니다.")
-						return false;
-					}else{
-						spamChk = true;
-						return false;
-					}
-					
-				} else if(status== 'fail'){
-					alert(returnData.message);
-					return false;
-				}
-			}
-			, error: function (e) {
-				alert("문자 발송에 실패하였습니다.");
-				console.log("ERROR : ", e);
-				return false;
-			}
-		}); */
-		
-		if(spamChk){
-			var data = new FormData(document.bizForm);
-			$.ajax({
-				type: "POST"
-				, url: "/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax.do"
-				, data: data
-				, dataType: 'json'
-				, async: true
-				, processData: false
-				, contentType: false
-				, cache: false
-				, success: function (returnData, status) {
-					if(status == 'success'){
-						if("loginFail" == returnData.result){
-							
-							alert(returnData.message);
-							return false;
-							
-						}else  if('fail' == returnData.result){
-							
-							alert(returnData.message);
-							return false;
-							
-						}else if('authFail' == returnData.result){
-							
-							alert(returnData.message);
-							location.reload();
-							
-						} else if(status == 'success'){
-							
-							var kakaoSendCnt = returnData.resultSts;
-							
-							$('.pop_msg_success').css({'display':'block','opacity':'1','left':'50%','top':'50%','transform':'translate(-50%,-50%)'});
-							
-							//예약발송 건의 경우 결과 팝업 문구 변경
-							if(reserYn == 'Y'){
-								$('.pop_msg_success .msg_text').html("예약 성공 : <strong>"+ kakaoSendCnt + "</strong>건의<br>알림톡이 예약 되었습니다.");
-							}else{
-								$('.pop_msg_success .msg_text').html("발송 성공 : <strong>"+ kakaoSendCnt + "</strong>건의<br>알림톡이 발송 되었습니다.");
-							}
-							
-							$('.mask').addClass('on');
-						}
-					}
-				}
-				,beforeSend : function(xmlHttpRequest) {
-					//로딩창 show
-					$('.loading_layer').addClass('active');
-				}
-				,complete : function(xhr, textStatus) {
-					//로딩창 hide
-					$('.loading_layer').removeClass('active');
-				}
-				,error: function (e) {
-					console.log("ERROR : ", e);
-					alert("카카오 알림톡 전송에 실패하였습니다.");
-				}
-			}); 
+	// 폼 데이터를 배열로 직렬화
+	var form = $('#bizForm');
+	var formDataArray = form.serializeArray();
+	
+	// 배열을 객체로 변환
+	var formData = {};
+	$.each(formDataArray, function(index, field) {
+	    formData[field.name] = field.value;
+	});
+	
+	// 빈 값 제거 (참고 코드 기반)
+	for (var key in formData) {
+		if (formData[key] === '' || formData[key] === null || formData[key] === undefined) {
+		    delete formData[key];
 		}
 	}
+	
+// 	delete formData['varNmList'];
+	
+	// 선택된 데이터 추가 (varListMap)
+	formData["varListMap"] = dataList;
+	console.log('formData : ', formData);
+	
+	if(confirm("알림톡을 발송하시겠습니까?")){
+
+	// 프로그래스파 시간을 위한 계산
+	var estimtedTime = calculateEstimatedTime(dataList.length);
+
+	$.ajax({
+		type: "POST",
+		url: "/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax_advc.do",
+		data: JSON.stringify(formData),
+		contentType: 'application/json',
+		dataType: 'json',
+		success: function (data) {
+				console.log('data : ', data);
+				
+				
+
+				var status = data.status;
+				if("OK" == status){
+					var resultSts = data.object.resultSts;
+					var reserYn = data.object.reserYn;
+					var resText = (reserYn === 'Y') ? '예약' : '발송';
+						
+					$('.pop_msg_success').css({'display':'block','opacity':'1','left':'50%','top':'50%','transform':'translate(-50%,-50%)'});
+					$('.pop_msg_success .msg_text').html(resText+" 성공 : <strong>"+ resultSts + "</strong>건의<br>알림톡이 " + resText + " 되었습니다.");
+					
+				}else if("UNAUTHORIZED" == status){
+					alert(data.message);
+				    location.reload();
+				}else{
+					alert(data.message);
+					return false;
+				}
+				
+				
+// 				if(data == 'success'){
+					/* if("loginFail" == returnData.result){
+						
+						alert(returnData.message);
+						return false;
+						
+					}else  if('fail' == returnData.result){
+						
+						alert(returnData.message);
+						return false;
+						
+					}else if('authFail' == returnData.result){
+						
+						alert(returnData.message);
+						location.reload();
+						
+					} else if(status == 'success'){
+						
+						var kakaoSendCnt = returnData.resultSts;
+						
+						$('.pop_msg_success').css({'display':'block','opacity':'1','left':'50%','top':'50%','transform':'translate(-50%,-50%)'});
+						
+						//예약발송 건의 경우 결과 팝업 문구 변경
+						if(reserYn == 'Y'){
+							$('.pop_msg_success .msg_text').html("예약 성공 : <strong>"+ kakaoSendCnt + "</strong>건의<br>알림톡이 예약 되었습니다.");
+						}else{
+							$('.pop_msg_success .msg_text').html("발송 성공 : <strong>"+ kakaoSendCnt + "</strong>건의<br>알림톡이 발송 되었습니다.");
+						}
+						
+						$('.mask').addClass('on');
+					} */
+// 				}
+			}
+			,beforeSend : function(xmlHttpRequest) {
+				//로딩창 show
+// 				$('.loading_layer').addClass('active');
+				// 프로그래스 바 실행
+				progressStart(estimtedTime);
+			}
+			,complete : function(xhr, textStatus) {
+				//로딩창 hide
+// 				$('.loading_layer').removeClass('active');
+
+				// 프로그래스 바 종료
+				progressComplete();;
+			}
+			,error: function (e) {
+				console.log("ERROR : ", e);
+				alert("카카오 알림톡 전송에 실패하였습니다.");
+			}
+		}); 
+	}
+}
+//선택된 데이터의 길이에 따라 예상 시간 계산 함수
+function calculateEstimatedTime(selectedCount) {
+    //기준값
+    // const processTimePerBatch = 130; // 130초
+    
+    
+    // 30만건 기준 10분으로 기준을 잡아서 
+    // 시간계산함
+    const processTimePerBatch = 600;
+    const batchSize = 300000;
+    
+    // 1건당 처리 시간
+    const timePerRecord = processTimePerBatch / batchSize;
+
+    // 예상 시간 계산
+    const estimatedTimeInSeconds = selectedCount * timePerRecord;
+
+    return estimatedTimeInSeconds.toFixed(2);
+}
+
+
+//프로그레스바 
+var start, change;
+var progressInterval = null; // 전역 변수로 타이머 ID 관리
+function progressStart(time) {
+    // 기존 타이머 정지 및 초기화
+    if (progressInterval !== null) {
+        clearInterval(progressInterval); // 이전 타이머 정지
+        progressInterval = null; // 타이머 ID 초기화
+    }
+    resetProgressBar(); // 프로그레스바 초기화
+
+    // 프로그레스바 보이기
+    $(".progress_bar_wrap").css("display", "flex");
+
+    // 프로그레스바 요소 가져오기
+    var timeText = document.querySelector(".time_text");
+    var bar = document.querySelector(".change_bar");
+
+    // 초기 상태 설정
+    var width = 1;
+    var totalTime = time * 1000; // 총 실행 시간 (밀리초)
+    var cmpWid = totalTime / 100; // width 증가 간격 (밀리초)
+
+    // 새 타이머 시작
+    progressInterval = setInterval(changeWidth, cmpWid);
+
+    function changeWidth() {
+        if (width >= 100) {
+            // 프로그레스바 100% 도달
+            clearInterval(progressInterval); // 타이머 종료
+            progressInterval = null; // 타이머 ID 초기화
+
+            timeText.innerHTML = "100%";
+
+            setTimeout(function () {
+                // 100% 표시 후 "잠시만 기다려주세요" 변경
+                timeText.innerHTML = "잠시만 기다려주세요...";
+                $(".time_text").addClass("animation");
+            }, 1000);
+        } else {
+            // 프로그레스바 진행
+            width++;
+            bar.style.width = width + "%";
+            timeText.innerHTML = width + "%";
+        }
+    }
+}
+
+
+//프로그레스바 완료
+function progressComplete() {
+ // var width = parseInt($(".time_text").text().replace('%', '')) || 0; // 현재 width 가져오기
+
+ $(".progress_bar_wrap").hide();
 }
 
 /*
  *	치환문자 있는 수신자 목록 파씽
  */
 function fn_transCallToListParsing(){
-	var callToList = [];
+/* 	var callToList = [];
 	// excel body
 	$('.excelBody').each(function(indexBody, itemBody){
 		$(itemBody).find('.list_table_name').each(function(indexRow, itemRow){
@@ -750,7 +863,31 @@
 		});
 	});
 	$('#bizForm #callToList').val(callToList);
+ */
 
+	var dataList = [];
+	
+	var headers = [];
+	$('#excelHead .list_table_name').each(function() {
+	  headers.push($(this).text().trim());
+	});
+	
+	$('.excelBody').each(function() {
+		var row = {};
+		$(this).find('.list_table_name').each(function(index) {
+			var key = headers[index];
+			var value = $(this).text().trim();
+			if (index === 0) {
+			    row["callToList"] = value; // 수신번호는 별도로 처리
+			} else {
+			    row[key] = value; // 
+			}
+		});
+		console.log(row)
+		dataList.push(row);
+	});
+
+	return dataList;
 }
 
 /*
@@ -758,13 +895,28 @@
  */
 function fn_callToListParsing(){
 
-	var callToList = [];
-	// excel body
-	$('.phoneArea').each(function(index, item){
-			callToList.push($(item).text().replaceAll('\\t', ''));
+    var dataList = [];
+	
+/* 	$('.phoneArea').each(function(index, item){
+        var row = {};
+        var value = $(item).text().replaceAll('\\t', '')
+        row["callToList"] = value; // 수신번호는 별도로 처리
+        dataList.push(row);
+    });
+	 */
+	   
+	// Tabulator 테이블의 데이터 가져오기
+	var tableData = tableL.getData(); 
+	
+	tableData.forEach(function(row){
+		var dataRow = {};
+		dataRow["callToList"] = row.phone; // phone 필드 값을 callToList로 저장
+		dataList.push(dataRow);
 	});
 	
-	$('#bizForm #callToList').val(callToList);
+	return dataList;
+
+	
 
 }
 
@@ -777,9 +929,8 @@
 	// title 배열
 	var varHead = [];
 	// 값 배열
-	var varVal = [];
+// 	var varVal = [];
 	
-	var inputTag = '<input type="hidden" class="varValList" name="varValList[$INDEX$]" value="$VAL$">';
 	
 	// excel title
 	$('#excelHead').find('div').each(function(index, item){
@@ -803,7 +954,7 @@
 		$("#bizForm").append(inputTag.replace('$VAL$',varValTemp ).replace('$INDEX$',index ));
 	}); */
 	
-	$('.excelBody').each(function(index, item){
+/* 	$('.excelBody').each(function(index, item){
 		
 		var valLeng = $('#excelHead').find('.list_table_name').length-1;
 		varValTemp = '';
@@ -821,7 +972,7 @@
 		console.log('varValTemp : ',varValTemp);
 		varVal.push(varValTemp);
 	});
-	$('#bizForm #varValList').val(varVal);
+	$('#bizForm #varValList').val(varVal); */
 }
 
 
@@ -881,9 +1032,9 @@
 	$('#smsLen').val(conLeng);
 	
 	
+	$('#msgLeng').html(conLeng + " / ");
 	if(conLeng > 90){
 		
-		$('#msgLeng').html(conLeng + " / ");
 		$('#limitLeng').html("2000");
 		$('.msg_com').html("장문");
 		$('#msgType').val("6"); // 메세지 타입 설정
@@ -897,7 +1048,6 @@
 		
 	}else{
 		
-		$('#msgLeng').html(conLeng + " / ");
 		$('#limitLeng').html("90");
 		$('.msg_com').html("단문");
 		$('#msgType').val("4"); // 메세지 타입 설정
@@ -910,7 +1060,7 @@
 	}
 		
 	//수신목록 전체 데이터 갯수 구하기
-	updateTotCnt(totRows);
+	//updateTotCnt(totRows);
 }
 
 /**
@@ -1141,6 +1291,17 @@
 		</div>
 	</div>
 	
+    <div class="progress_bar_wrap">
+        <div class="progress_box">
+            <p class="time_text">0%</p>
+            <div class="bar">
+                <span class="change_bar"></span>
+            </div>
+        </div>
+        <div class="btn_wrap">
+        </div>
+
+    </div>
 	<!-- 기업회원 이동 팝업 -->
 	<div class="tooltip-wrap cvt_member_popup_wrap">
 	    <div class="popup-com cvt_member_layer" tabindex="0" data-tooltip-con="cvt_member_layer" data-focus="cvt_member_layer" data-focus-prev="cvt_member_layer-close">
@@ -1192,8 +1353,8 @@
 		<input type="hidden" id="divideTime" name="divideTime" value="">				<!--전송일자-->
 		
 		<input type="hidden" id="callFrom" name="callFrom" value="">					<!--완  보내는사람 -->	
-		<input type="hidden" id="callToList" name="callToList" value="">				<!--완  받는사람 리스트-->
-		<input type="hidden" id="varNmList" name="varNmList" value="">					<!--완  변수 이름  리스트-->
+<!-- 		<input type="hidden" id="callToList" name="callToList" value="">				완  받는사람 리스트 -->
+<!-- 		<input type="hidden" id="varNmList" name="varNmList" value="">					완  변수 이름  리스트 -->
 		<input type="hidden" id="varValList" name="varValList" value="">				<!--완  변수 리스트-->
 		
 		<input type="hidden" id="atSmishingYn" name="atSmishingYn" value="${atSmishingYn}">		<!--알림톡 스미싱 여부-->
@@ -1354,25 +1515,25 @@
 													</span>
 												</div>
 												<div class="receipt_num_midde">
-													<div class="listType list01" >
-														<div class="list_table list_head">
+													<div class="listType list01 callList_box_P">
+														<!-- <div class="list_table list_head">
 															<div class="cb_wrap">
 																<label for="select_all" class="label"></label>
 																<input type="checkbox" id="select_all">
 															</div>
 															<div class="list_table_num">
 																<p>휴대폰</p>
-<!--                                                                 <img src="/publish/images/sortUp.png"> -->
-<!--                                                                 <img src="/publish/images/sortDown.png"> -->
+                                                                <img src="/publish/images/sortUp.png">
+                                                                <img src="/publish/images/sortDown.png">
 															</div>
-<!-- 															<div class="list_table_name"> -->
-<!-- 																<p>이름</p> -->
-<!--                                                                 <img src="/publish/images/sortUp.png"> -->
-<!--                                                                 <img src="/publish/images/sortDown.png"> -->
-<!-- 															</div> -->
+															<div class="list_table_name">
+																<p>이름</p>
+                                                                <img src="/publish/images/sortUp.png">
+                                                                <img src="/publish/images/sortDown.png">
+															</div>
 														</div>
 														<div class="list_body_wrap" id="wrap01_body">
-														</div>
+														</div> -->
 													</div>
 													<div class="put_right">
 														<div class="btn_popup_wrap spc_wrap">
@@ -1684,7 +1845,9 @@
 							<!--// table -->
 						</div>
 						<div class="popup_btn_wrap2">
-							<button type="button" onClick="javascript:addrToList(); return false;">추가</button>
+							<button type="button" onClick="javascript:addrToList_advc('all'); return false;">전체추가</button>
+							<button type="button" onClick="javascript:addrToList_advc('select'); return false;">선택추가</button>
+<!-- 							<button type="button" onClick="javascript:addrToList(); return false;">추가</button> -->
 							<button type="button" onClick="javascript:addrClose(); return false;">닫기</button>
 						</div>
 						<%-- 주소록 레이어 팝업 닫기 실행 코드 --%>
@@ -1773,6 +1936,7 @@
 
 
 
+
 <!-- 엑셀 불러오기 -->
 <form id="excelToolTipForm" name="excelToolTipForm" method="post">
 	<div class="tooltip-wrap">
 
src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView_advcbackup_20250310.jsp (added)
+++ src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView_advcbackup_20250310.jsp
@@ -0,0 +1,1773 @@
+<%@ 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" %>
+<%@ page import="itn.com.cmm.LoginVO" %>
+
+<!-- <script src="/publish/js/content.js"></script> -->
+<!-- 주소록관련 js -->
+<script type="text/javascript" defer src="<c:out value='/js/kakao/at/init.js' />"></script>
+<script type="text/javascript" src="<c:out value='/js/kakao/at/tabulator.js' />"></script>
+<script type="text/javascript" src="<c:out value='/js/kakao/at/addr.js' />"></script>
+<script type="text/javascript" src="<c:out value='/js/kakao/at/alimtalkExcel.js' />"></script>
+<script type="text/javascript" src="<c:out value='/js/kakao/at/priceClclt.js' />"></script>
+<script type="text/javascript" src="<c:out value='/js/common/popup.js' />"></script>
+<script type="text/javascript">
+var loginVO = '${loginVO}';
+
+// 체크박스 동적 바인딩
+$(document).on('click','.wrap01C', function(){
+	var total = $(".wrap01C").length;
+	var checked = $(".wrap01C:checked").length;
+	if(total != checked) $("#select_all").prop("checked", false);
+	else $("#select_all").prop("checked", true);
+});
+
+$(document).ready(function(){
+
+	//채널 ID change function
+	$("#selectKakaoProfileList").on("change", function(){
+		
+		if(usrDeptChk()){
+			
+			$("#selectTemplateList option").remove();
+			selectTemplateList();
+			
+		}else {
+			
+			$("#selectKakaoProfileList option:eq(0)").prop("selected", true);
+			
+		}
+		
+	});
+	
+	//템플릿 change function
+	$("#selectTemplateList").on("change", function(){
+		selectTemplateInfo($(this).val());
+		fn_viewDataInit02();
+		priceInit(); // 발송금액 라인 text / 금액 초기화
+	});
+	
+	$("#fileClick").click(function(){
+		if($('#selectTemplateList').val() == '')
+		{
+			alert('템플릿을 선택 후 진행해 주세요.');
+			return false;
+		}
+		if($("#tpButtonTypeDs").val() == "DS"){
+			alert("템플릿 내용에 배송조회 버튼이 포함되어 있습니다. \n운송장 번호는 숫자만 등록해주세요")
+		}
+		$('#excelFile').val('');
+		$("#excelFile").click();
+	});
+
+	//즉시 발송 라디오 버튼 선택시 숨김처리
+	$("#reserYnN").on('click', function(){
+		$('.rev_selected').hide();
+		$('.send_rev .send_content').css('padding-bottom','108px');
+		$('.send_btn .btnType:first-child').html('발송하기');
+		$('#bizForm #reserveYn').val($(this).val());
+	});
+
+	//예약 발송 라디오 버튼 선택시 숨김 해제처리
+	$("#reserYnY").on('click', function(){
+		$('.rev_selected').show();
+		$('.send_rev .send_content').css('padding-bottom','0');
+		$('.send_btn .btnType:first-child').html('예약하기');
+		$('#bizForm #reserveYn').val($(this).val());
+	});
+
+	//전체선색 버튼 이벤트
+	$("#select_all").on('click', function(){
+		if($("#select_all").is(":checked")) $(".wrap01C").prop("checked", true);
+		else $(".wrap01C").prop("checked", false);
+		
+	});
+	
+	//선택삭제 버튼 클릭 이벤트
+	$("#select_del").on('click', function(){
+		
+		if($('.wrap01C:checkbox:checked').length < 1)
+		{
+			alert("삭제할 연락처를 선택해주세요.!!");
+			return false;
+		}
+		
+		$('.wrap01C').each(function(index, item){
+			if($(item).is(':checked'))
+				$(item).parent().parent().remove();
+		});
+		updateTotCnt();
+	});
+
+	//선택삭제 버튼 클릭 이벤트
+ 	$("#all_del").on('click', function(){
+		
+		if(!confirm("받는사람 목록을 모두 삭제하시겠습니까?"))
+			return false;
+		
+		$('#wrap01_body .list_body').remove();
+
+		$('#rowTotCnt').text(0);
+		$('#rowDupCnt').text(0);
+	});
+
+	/* 
+	* 오류 검사
+	*/
+	$('#check_validity').click(function(){
+		var regExp_ctn = /^(01[016789]{1}|02|0[3-9]{1}[0-9]{1})([0-9]{3,4})([0-9]{4})$/;
+		// 치환문자 있는 데이터
+		if($('#bizForm #txtReplYn').val() === 'N'){
+
+			if($('.phoneArea').length < 1){
+				alert("등록된 연락처가 없습니다.")
+				return false;
+			}
+
+			$('.phoneArea').each(function(index, item){
+				var phoneVal = $(item).text().trim();
+				if(phoneVal.length==11 || phoneVal.length==10) 
+				{
+					if(!regExp_ctn.test(phoneVal))
+					{
+						alert(phoneVal+"는 유효하지 않은 전화번호 입니다.");
+						return false;
+					}
+				}
+				else
+				{
+					alert("유효하지 않은 전화번호 입니다.");
+					return false;
+				}
+			});
+			alert("오류 데이터가 없습니다.");
+		}
+	});
+	
+	/**
+	* 템플릿 재선택 버튼 function
+	*/
+	$('#reSelectBtn').click(function(){
+		var senderKey = $('#selectKakaoProfileList option:selected').val();
+
+		if(!senderKey)
+		{
+			alert("채널ID를 선택하고 다시 시도해 주세요.");
+			return false;
+		}
+			
+			
+		var url = "";
+		var windowTargetName = "KakaoAlimtalkTemplateListPopupAjax";
+// 		var features = "width=930, height=860, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=yes";
+		// 2.POST로 데이터 전달
+		document.templateListPopup.senderKey.value=$('#selectKakaoProfileList option:selected').val();
+		document.templateListPopup.yellowId.value=$('#selectKakaoProfileList option:selected').text();
+		document.templateListPopup.target=windowTargetName;
+		showPopup2('',windowTargetName ,'930','860');
+		document.templateListPopup.submit();
+	
+	});
+	
+	
+
+	$("#send_fail_check").change(function(){
+		if($("#send_fail_check").is(":checked")){
+
+			
+			if(loginVO == "" || loginVO == null){
+				alert("로그인 후 사용 가능한 기능입니다.");
+				location.href="<c:url value='/web/user/login/login.do'/>";
+				return false;
+				
+				$("#send_fail_check").prop("checked", false);
+			}
+			
+			if($('#callFromList').val() === ''){
+				
+				if(confirm('대체문자 전송을 위한 발신번호가 등록되지 않았습니다. \n대체문자 발신번호를 지금 등록하시겠습니까?')){
+					window.location="<c:out value='/web/user/sendNumberManage.do' />";
+				}
+				$("#send_fail_check").prop("checked", false);
+				
+			}else if($('#selectTemplateList').val() == '')
+			{
+				alert('템플릿을 선택 후 진행해 주세요.');
+				$("#send_fail_check").prop("checked", false);
+				return false;
+			}else{
+				// 에러버튼 체크 초기화
+				fn_insertErrorYN('N');
+				
+				$('#smsTxtArea').val('');
+// 				// 미리보기 텍스트를 가져와 줄바꿈 처리 후 대체문자 내용으로 입력
+				var template_text = $('.template_text').html().trim();
+				template_text = XSSChange(template_text);
+				$('#smsTxtArea').val(template_text);
+
+// 				//문자 내용 입력시 바이트수 계산하기
+				
+				$(".replace_send_wrap").slideDown(400);
+				thisFnByteString($('#smsTxtArea').val());
+			}
+		}else{
+			$(".replace_send_wrap").slideUp(400);
+			// 초기화 버튼 클릭
+			$('#failCheckInit').click();
+			$('.send_top .send_right .phone').css({'top': '0','transition': 'top .4s linear'});
+		}
+
+		// 금액 계산 fn 호출
+		fn_priceClclt();
+	});
+	
+	// 대체문자 내용 수정
+	$('#smsTxtArea').keyup(function(){
+		// 금액 계산 fn 호출
+		fn_priceClclt();
+		// 문자 바이트수 체크
+		thisFnByteString($('#smsTxtArea').val());
+		// 에러버튼 체크 초기화
+		fn_insertErrorYN('N');
+		
+	});
+});
+function sendFailCheckInit(){
+	
+	$("#send_fail_check").prop("checked", false);
+	
+}
+
+function fnTemplateReg(){
+	if(loginVO == "" || loginVO == null){
+		alert("신규 템플릿 등록 서비스는 로그인 후 이용 가능합니다.");
+		location.href="<c:url value='/web/user/login/login.do'/>";
+		return false;
+	}
+	if(usrDeptChk()){
+		
+		if(confirm('신규 템플릿 등록 화면으로 이동하시겠습니까?')){
+			location.href="<c:url value='/web/mjon/kakao/template/selectKaKaoTemplateList.do'/>";
+		}
+	}
+	
+}
+
+/*
+ * 탬플릿 재선택 팝업에서 실행하는 function
+ */
+function call_templateChange(templateId){
+	
+	$('#selectTemplateList').val(templateId).prop('selected', true);
+	selectTemplateInfo(templateId);
+// 	$('#selectTemplateList').val('bizp_2023021711142018819557746').prop('selected', true);
+}
+
+
+/**
+ * 먼저 불러온 DATA가 있으면 삭제
+ * !! 화면에 보이는 data만 삭제 !!
+ * 치환 데이터 
+ */
+function fn_viewDataInit01(){
+
+	// excel Data (치환 문자 table) 비우기
+	$('#excelHead').empty();
+	$('.excelBody').remove();
+	$('#excelNm01').val('');
+	// 치환문자 없을 경우
+// 	$('#wrap01_body .list_body').remove();
+}
+
+/**
+ * 먼저 불러온 DATA가 있으면 삭제
+ * !! 화면에 보이는 data만 삭제 !!
+ * 총건수, 중복건수 데이터 0으로 초기화
+ * 엑셀 불러오기 데이터 
+ */
+function fn_viewDataInit02(){
+	$('.excelBody').remove();
+	$('#excelHead').empty();
+	$('#rowTotCnt').text("0");
+	$('#rowDupCnt').text("0");
+}
+
+/*
+ *변수 다운로드 excel show function
+ */
+function variableWrapShow(){
+	$(".receiver_wrap02").attr("style","display: block !important;");
+	$(".receiver_wrap01").attr("style","display: none !important;");
+	$(".variable_wrap").show();
+	$('#bizForm #txtReplYn').val('Y');
+	
+}
+
+/*
+ * 변수 다운로드 excel hide function
+ */
+function variableWrapHide(){
+	$(".receiver_wrap01").attr("style","display: block !important;");
+	$(".receiver_wrap02").attr("style","display: none !important;");
+	$(".variable_wrap").hide();
+	$('#bizForm #txtReplYn').val('N');
+	
+}
+
+
+/*
+ * 등록된 발신 탬플릿 목록 조회 function
+ */
+function selectTemplateList(){
+	var selectAgentCode = $("select[name='selectKakaoProfileList']").val();
+	$.ajax({
+		type: "POST"
+		, url: "<c:out value ='/web/mjon/kakao/alimtalk/selectKakaoApiTemplateAjax.do' />"
+		, data:{ "senderKey":selectAgentCode, "pageType":"notityTalk"}
+		, dataType:'json'
+		, cache: false
+		, async: false
+		, timeout: 600000
+		, success: function (returnData, status) {
+			if(status == 'success'){
+				
+				$("#selectTemplateList option").remove();
+				$("#selectTemplateList").append("<option value=''>알림톡 템플릿 선택</option>");
+				
+				var list =  returnData.kakaoTemplateList;
+				for(var i=0; i < list.templatList.length; i++){
+					$("#selectTemplateList").append("<option value='"+list.templatList[i].templateCode+"'>"+list.templatList[i].templateName+"</option>");
+				}
+				
+			} else if(status== 'fail'){
+				alert(returnData.message);
+			}
+		}
+		,error: function (e) {
+			console.log("ERROR : ", e);
+			alert("관리자에게 문의해 주세요");
+		}
+	});
+}
+
+/*
+ * 템플릿 선택하여 정보 가져오는 function
+ */
+function selectTemplateInfo(id){
+	
+	var selectAgentCode = $("select[name='selectKakaoProfileList']").val();
+	
+	$("#alimtalkTemplate").empty();
+	
+	// 우측 본문내용 만들기
+	$("#alimtalkTemplate").load("/web/mjon/kakao/template/selectKakaoApiTemplateDataViewLoadAjax.do"
+	, {
+		"senderKey":selectAgentCode
+		, "templateCode" : id
+	},function(){
+		
+
+		// =================== 대체문자 숨김 / html 초기화
+		$(".replace_send_wrap").slideUp(400);
+		// 초기화 버튼 클릭
+		$('#failCheckInit').click();
+		$('.send_top .send_right .phone').css({'top': '0','transition': 'top .4s linear'});
+		$("#send_fail_check").prop("checked", false);
+		// //=================== 대체문자 숨김 / html 초기화
+		
+		
+		// 미리보기에 채널ID 노출 
+		$('#prev_p_top').text($('#selectKakaoProfileList option:selected').text());
+		
+		
+		var tpTemplateContent = $('#tpTemplateContent').val();
+		$("#senderKeyInfo").val(selectAgentCode);
+		$("#templateCodeInfo").val($('#tpTemplateCode').val());
+			
+		//엑셀 샘플 정보 - 내용만 변수처리하기
+		$("#excelTemplateContent").val(tpTemplateContent);
+		$("#excelTemplateSubtitle").val($('#tpTemplateSubtitle').val());
+		$("#excelTemplateTitle").val($('#tpTemplateTitle').val());
+		
+		if(($('#tpTemplateEmphasizeType').val() != "NONE") || $('#tpBottonListSize').val() != "0"){
+			$('#bizForm #bizJsonYn').val('Y');
+		}else{
+			$('#bizForm #bizJsonYn').val('N');
+		}
+		
+		
+		if($('#tpTemplateEmphasizeType').val() == "TEXT"){
+			$("#templateEmphasizeType").val($('#tpTemplateEmphasizeType').val());
+			$("#templateTitle").val($('#tpTemplateTitle').val());
+			$("#templateSubtitle").val($('#tpTemplateSubtitle').val());
+		}
+		
+		$("#bizForm  #templateContent").val(tpTemplateContent);
+		templateChange();
+	
+	});
+}
+
+/*
+ * 알림톡 변수가 있는지 체크해서 변수 다운로드 excel show / hide 하는 function
+ */
+function templateChange(){
+	var varList = $("#excelTemplateContent").val().match(/#\{([^}]+)\}/g);
+	if(varList == null)
+		variableWrapHide();
+	else
+		variableWrapShow();
+	
+}
+//엑셀 업로드 양식 다운로드 받기
+function excelDownload(){
+	
+	if(loginVO == "" || loginVO == null){
+		alert("변수설정 엑셀파일 다운로드는 서비스는 로그인 후 이용 가능합니다.");
+		location.href="<c:url value='/web/user/login/login.do'/>";
+		return false;
+	}
+	
+	var profile = $("#selectKakaoProfileList").val();
+	var template = $("#selectTemplateList").val();
+	
+	if(profile == ''){
+		
+		alert("채널ID를 선택해주세요.");
+		return false;
+		
+	}
+	
+	if(template == ''){
+		
+		alert("알림톡 템플릿을 선택해주세요.");
+		return false;
+		
+	}
+	
+	//합친 내용에서 변수 문자열 뽑기 - #과{}미포함
+	var fullVarList = $("#excelTemplateContent").val().match(/(?<=\#\{)(.*?)(?=\})/g);
+	$('#excelForm #varNmList').val(fullVarList);
+	$('#excelForm').submit();
+	
+}
+
+function checkConf() {
+	var confCheck = false;
+	
+	$.ajax({
+		type: "POST",
+		url: "/web/mjon/conf/selectMjonMsgUseConfAjax.do",
+		data: {},
+		dataType:'json',
+		async: false,
+		success: function (returnData, status) {
+			if(returnData.result == "fail") {
+				console.log(returnData.message);
+			}else if(returnData.result == "success"){
+				confCheck = true;
+			}
+		}
+		,error: function (e) {console.log("ERROR : ", e); }
+	});	
+	
+	return confCheck;
+}
+
+/*
+ *	등록된 발신 탬플릿 카카오톡 전송 
+ */
+function sendTemplateInfo(){
+
+	if(!checkConf()){	//문자온 conf-check
+		alert("현재 알림톡 발송하기 기능 점검 중입니다.\n\n1분 후 다시 시도해주세요.");
+		return false;
+	}
+	
+	if(loginVO == "" || loginVO == null){
+		alert("카카오톡 발송 서비스는 로그인 후 이용 가능합니다.");
+		location.href="<c:url value='/web/user/login/login.do'/>";
+		return false;
+	}
+	
+	if(!usrDeptChk()){
+		return false;
+	}
+	
+	//채널ID / 템플릿 선택
+	if(!$('#selectKakaoProfileList').val())
+	{
+		alert('채널ID를 선택 후 발송해 주세요');
+		return false;
+	}
+	
+	if(!$('#selectTemplateList').val() )
+	{
+		alert('템플릿을 선택 후 발송해 주세요');
+		return false;
+	}
+	
+	//수신자 목록 체크
+	if($('.phoneArea').length < 1)
+	{
+		alert('받는 사람 입력 후 발송해 주세요');
+		return false;
+	}
+	
+	//수신자 목록 체크
+	if($('.phoneArea').length > 500)
+	{
+		alert("최대 발송 건수는 500건 입니다.");
+		return false;
+	}
+	
+
+	if($('#errorChk').val() === 'N' 
+			&& $("#send_fail_check").is(":checked")
+			&& $('#txtReplYn').val() === 'Y'
+	)
+	{
+		alert('대체문자 전송을 원하시면 오류검사 버튼을 확인해 주세요.');
+		return false;
+	}
+	
+	// 금액 확인
+	// 사용자 금액
+	var userMoney = $('#oriUserMoney').val();
+	// 발송 금액
+	var totalPriceTxt = $('#totalPriceTxt').text();
+	// 금액 확인
+	var resutlPrice = parseFloat(userMoney)-parseFloat(totalPriceTxt);
+
+	// 음수면 -1 값
+	if(Math.sign(resutlPrice) < 0)
+	{
+		alert("발송에 필요한 회원님의 보유 잔액이 부족 합니다.");
+		return false;
+	}
+	
+	// 초기화
+	$('.varValList').remove();
+	$('#bizForm #varNmList').val('');
+
+
+	// 대체문자 전송 확인
+	if($('#send_fail_check').is(':checked')){
+		$('#bizForm #subMsgSendYn').val("Y");
+		$('#bizForm #subMsgTxt').val($("#smsTxtArea").val());
+		
+		var subMsgTxt = $("#smsTxtArea").val().match(/#\{([^}]+)\}/g);
+		if(subMsgTxt == null){
+			$('#bizForm #subMsgTxtReplYn').val("N");
+		}else{
+			$('#bizForm #subMsgTxtReplYn').val("Y");
+		}
+	}else{
+		$('#bizForm #subMsgSendYn').val("N");
+	}
+	
+	// 예약문자 및 분할전송 확인
+	var reserYn = $("input[name=reserYn]:checked").val(); // 예약 발송 여부 확인
+	$('#bizForm #reserveYn').val(reserYn);
+	if(reserYn == 'Y'){
+		
+		var date = $(".resDate").val();//form.msgResDate.value;
+		var hour = $("select[name='msgResHour']").val();
+		var min = $("select[name='msgResMin']").val();
+		
+		if(date == ""){
+			alert("예약전송 날짜를 선택해 주세요.");
+			return false;
+			
+		}else{
+			
+			var now = new Date();
+			var reqDate = date + " " + hour + ":" + min + ":00";
+			var gapDate = getGapDayTime(date, hour, min);
+			
+			if(gapDate < 0){ // 음수이면 이전날짜, 크면 이후 날짜.
+				alert("예약 날짜는 현재 시간 이후의 날짜 및 시간을 선택해 주세요.");
+				return false;
+			}else{
+				$('#bizForm #reqDate').val(reqDate);
+			}
+		}
+		
+		var divideChk =  "";
+		if($('#inputDivideChk').is(':checked')){
+			divideChk = "Y";
+		}else{
+			divideChk = "N"
+		}
+		
+		//var divideCnt = $("select[name='frmDivideCnt']").val();
+		var divideCnt = $('#frmDivideCnt').val();
+		var divideTime = $("select[name='divideTime']").val();
+		
+		$('#bizForm #divideChk').val(divideChk);
+		$('#bizForm #divideCnt').val(divideCnt);
+		$('#bizForm #divideTime').val(divideTime);
+		
+	}else{
+		$('#bizForm #reqDate').val("");
+	}
+	
+	// 치환문자 있는 데이터 파씽
+	if($('#bizForm #txtReplYn').val() === 'Y'){
+		fn_excelDataTransParsing();
+		// 치환문자 있는 수신자 리스트 
+		fn_transCallToListParsing();
+	}else{
+		// 치환문자 없는 수신자 리스트 
+		fn_callToListParsing();
+	}
+
+	$('#bizForm #senderKey').val($('#selectKakaoProfileList').val());
+	$('#bizForm #templateCode').val($('#selectTemplateList').val());
+	
+	// 발신번호
+	$('#bizForm #callFrom').val(removeDash($('#callFromList option:selected').val()));
+	
+	if(confirm("알림톡을 발송하시겠습니까?")){
+		var spamChk = true;
+		//2023.09.06 알림톡 스팸체크 기능 제거요청으로 인한 주석처리
+		/*var spamChk = false;
+		var spmData = new FormData(document.bizForm);
+		$.ajax({
+			type: "POST"
+			, url: "/web/mjon/alimtalk/selectSpamKakaoAlimtalkMsgChkAjax.do"
+			, data: spmData
+			, dataType:'json'
+			, async: false
+			, processData: false
+			, contentType: false
+			, cache: false
+			, success: function (returnData, status) {
+				if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나
+					
+					if("fail" == returnData.result){
+						alert(returnData.message);
+						return false;
+					}else if("loginFail" == returnData.result){
+						alert(returnData.message);
+						return false;
+					}else if("spams" == returnData.result){
+						alert("전송 내용에  스팸문구가 포함되어 있습니다.")
+						return false;
+					}else{
+						spamChk = true;
+						return false;
+					}
+					
+				} else if(status== 'fail'){
+					alert(returnData.message);
+					return false;
+				}
+			}
+			, error: function (e) {
+				alert("문자 발송에 실패하였습니다.");
+				console.log("ERROR : ", e);
+				return false;
+			}
+		}); */
+		
+		if(spamChk){
+			var data = new FormData(document.bizForm);
+			$.ajax({
+				type: "POST"
+				, url: "/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax.do"
+//				, url: "/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax_advc.do"
+				, data: data
+				, dataType: 'json'
+				, async: true
+				, processData: false
+				, contentType: false
+				, cache: false
+				, success: function (returnData, status) {
+					console.log('returnData : ', returnData);
+					if(status == 'success'){
+						/* if("loginFail" == returnData.result){
+							
+							alert(returnData.message);
+							return false;
+							
+						}else  if('fail' == returnData.result){
+							
+							alert(returnData.message);
+							return false;
+							
+						}else if('authFail' == returnData.result){
+							
+							alert(returnData.message);
+							location.reload();
+							
+						} else if(status == 'success'){
+							
+							var kakaoSendCnt = returnData.resultSts;
+							
+							$('.pop_msg_success').css({'display':'block','opacity':'1','left':'50%','top':'50%','transform':'translate(-50%,-50%)'});
+							
+							//예약발송 건의 경우 결과 팝업 문구 변경
+							if(reserYn == 'Y'){
+								$('.pop_msg_success .msg_text').html("예약 성공 : <strong>"+ kakaoSendCnt + "</strong>건의<br>알림톡이 예약 되었습니다.");
+							}else{
+								$('.pop_msg_success .msg_text').html("발송 성공 : <strong>"+ kakaoSendCnt + "</strong>건의<br>알림톡이 발송 되었습니다.");
+							}
+							
+							$('.mask').addClass('on');
+						} */
+					}
+				}
+				,beforeSend : function(xmlHttpRequest) {
+					//로딩창 show
+					$('.loading_layer').addClass('active');
+				}
+				,complete : function(xhr, textStatus) {
+					//로딩창 hide
+					$('.loading_layer').removeClass('active');
+				}
+				,error: function (e) {
+					console.log("ERROR : ", e);
+					alert("카카오 알림톡 전송에 실패하였습니다.");
+				}
+			}); 
+		}
+	}
+}
+
+/*
+ *	치환문자 있는 수신자 목록 파씽
+ */
+function fn_transCallToListParsing(){
+	var callToList = [];
+	// excel body
+	$('.excelBody').each(function(indexBody, itemBody){
+		$(itemBody).find('.list_table_name').each(function(indexRow, itemRow){
+			if(indexRow == 0)
+			{
+				callToList.push($(itemRow).text().replaceAll('\\t', ''));
+			}
+		});
+	});
+	$('#bizForm #callToList').val(callToList);
+
+}
+
+/*
+ *	치환문자 없는 수신자 목록 파씽
+ */
+function fn_callToListParsing(){
+
+	var callToList = [];
+	// excel body
+	$('.phoneArea').each(function(index, item){
+			callToList.push($(item).text().replaceAll('\\t', ''));
+	});
+	
+	$('#bizForm #callToList').val(callToList);
+
+}
+
+/*
+ *	받는사람 excel data 파씽
+ */
+function fn_excelDataTransParsing(){
+
+	
+	// title 배열
+	var varHead = [];
+	// 값 배열
+	var varVal = [];
+	
+	var inputTag = '<input type="hidden" class="varValList" name="varValList[$INDEX$]" value="$VAL$">';
+	
+	// excel title
+	$('#excelHead').find('div').each(function(index, item){
+		if(index != 0)
+			varHead.push($(item).text().replaceAll('\\t', ''));
+	});
+	$('#bizForm #varNmList').val(varHead);
+	
+	// excel body
+/* 	$('.excelBody').each(function(index, item){
+		varValTemp = [];
+		$(item).find('.list_table_name').each(function(index, item){
+			if(index != 0){
+				if(index == 1){
+					varValTemp = $(item).text().replaceAll('\\t', '');
+				}else
+					varValTemp += ","+$(item).text().replaceAll('\\t', '');
+			}
+		});
+		
+		$("#bizForm").append(inputTag.replace('$VAL$',varValTemp ).replace('$INDEX$',index ));
+	}); */
+	
+	$('.excelBody').each(function(index, item){
+		
+		var valLeng = $('#excelHead').find('.list_table_name').length-1;
+		varValTemp = '';
+		
+		$(item).find('.list_table_name').each(function(index, item){
+			if(index != 0)
+			{
+				var itemText = $(item).text().replaceAll('\\t', '');
+				if(index !== 1)
+					varValTemp += '§'+itemText.replaceAll(',', 'Ï');
+				else
+					varValTemp += itemText.replaceAll(',', 'Ï');
+			}
+		});
+		console.log('varValTemp : ',varValTemp);
+		varVal.push(varValTemp);
+	});
+	$('#bizForm #varValList').val(varVal);
+}
+
+
+
+//주소록 불러오기 버튼 클릭시
+$('.popupAddr').click(function(){
+	
+	if(loginVO == "" || loginVO == null){
+		alert("주소록 불러오기 서비스는 로그인 후 이용 가능합니다.");
+		location.href="<c:url value='/web/user/login/login.do'/>";
+		return false;
+	}
+	
+	$("#addrGroupLoad").load("/web/mjon/msgdata/selectAddrGroupListAjax.do", "" ,function(response, status, xhr){
+		//리스트 스크롤 처리해주기
+		$(".adr_pop_list").mCustomScrollbar({
+			axis: 'y',
+			scrollbarPosition: "outside",
+			theme: "dark",
+			autoHideScrollbar: false
+		});
+	});
+	
+});
+
+
+//알림톡 상세보기 화면 호출
+function fnTemplateDetail(templateCode){
+	var form = document.templateForm;
+	var selectAgentCode = $("select[name='selectKakaoProfileList']").val();				// 선택 채널ID
+	
+	form.senderKey.value = selectAgentCode;
+	form.templateCode.value = templateCode;
+	form.target='_blank';
+	form.action="/web/mjon/kakao/template/requestKakaoApiTemplateDetail.do";
+	form.submit();
+	
+}
+
+
+//문자 바이트수 계산하기 함수
+function thisFnByteString(contents){
+	var totalByte = 0; 
+	//var content = contents;
+	var adverYn = $("input[name='send_adYn']:checked").val();
+	var adTxtLeng = 0;
+	var denyTxtLeng = 0;
+
+	$('#msgLeng').html("");
+	$('#limitLeng').html("");
+	var conLeng = conByteLeng(contents); // 내용 문자 입력 바이트 수 계산하기
+	
+		
+	$('#msgLeng').text(conLeng);
+	
+	//문자 길이 변수에 저장해주기
+	$('#smsLen').val(conLeng);
+	
+	
+	if(conLeng > 90){
+		
+		$('#msgLeng').html(conLeng + " / ");
+		$('#limitLeng').html("2000");
+		$('.msg_com').html("장문");
+		$('#msgType').val("6"); // 메세지 타입 설정
+		
+		$('.msg_com').removeClass("msg_short"); //단문 클래스 삭제하고
+		$('.put_left').removeClass("short"); //내용 입력 박스 클래스 삭제
+		$('.msg_com').addClass("msg_long"); // 장문 클래스 삽입
+// 		$('.put_left').addClass("long");  // 내용 입력 박스에 클래스 삽입
+// 		$('.msg_title').addClass('active');
+		//document.getElementById("mmsSubject").disabled = false;
+		
+	}else{
+		
+		$('#msgLeng').html(conLeng + " / ");
+		$('#limitLeng').html("90");
+		$('.msg_com').html("단문");
+		$('#msgType').val("4"); // 메세지 타입 설정
+		$('.msg_com').removeClass("msg_long"); //단문 클래스 삭제하고
+		$('.put_left').removeClass("long"); //내용 입력 박스 클래스 삭제
+		$('.msg_com').addClass("msg_short"); // 장문 클래스 삽입
+// 		$('.put_left').addClass("short");  // 내용 입력 박스에 클래스 삽입
+// 		$('.msg_title, .title_wrap .textbox').removeClass('active');
+		
+	}
+		
+	//수신목록 전체 데이터 갯수 구하기
+	updateTotCnt(totRows);
+}
+
+/**
+ * @description 대체문자 오류체크 funciton
+ */
+function fn_errorChk(){
+
+	// 대체문자가 없을 시 return false;
+	if($('#txtReplYn').val() === 'N')
+	{
+		alert('오류가 없습니다.');
+		return false;
+	}
+
+	// 치환 부분 변수명만 추출 = 배열
+	var varList = $("#excelTemplateContent").val().match(/#\{([^}]+)\}/g);
+	
+	var smsTxt = $('#smsTxtArea').val();
+	for(var i=0; i < varList.length; i++){
+		if(smsTxt.indexOf(varList[i]) < 0){
+			if(confirm(varList[i] + '값이 없습니다. 치환문자 없이 진행하시겠습니까?')){
+				fn_insertErrorYN('Y');
+			};
+			return false;
+		}
+		smsTxt = smsTxt.replace(varList[i], '');
+	};
+	alert('오류가 없습니다.');
+	fn_insertErrorYN('Y');
+}
+
+
+function fn_insertErrorYN(val){
+	$('#errorChk').val(val);
+}
+
+function msgResultLink(){
+	var reserYn = $("input[name=reserYn]:checked").val(); // 예약 발송 여부 확인
+	if(reserYn == 'Y'){
+		
+		location.href="/web/mjon/reservmsg/selectReservKaKaoView.do";
+		
+	}else{
+		location.href="/web/kakao/sent/selectKakaoSentView.do";
+	}
+}
+
+function msgSuccessClose(obj){
+	$(obj).closest('.pop_msg_success').attr('style','');
+	location.reload(true);
+	$('html').scrollTop(0);
+}
+
+function goToKakaoTestPopUp(){
+	
+	if(loginVO == "" || loginVO == null){
+		alert("테스트 발송 서비스는 로그인 후 이용 가능합니다.");
+		location.href="<c:url value='/web/user/login/login.do'/>";
+		return false;
+	}
+	
+	//기업회원 체크
+	if(!usrDeptChk()){
+		return false;
+	}
+	
+	var form = document.kakaoAtDataTestPopupForm;
+	var selectAgentCode = $("select[name='selectKakaoProfileList']").val();
+	var selectTemplateCode = $("select[name='selectTemplateList']").val();
+	var selectAgentTxt = $('#selectKakaoProfileList option:selected').text()
+	var txtRepYn =  $('#bizForm #txtReplYn').val();
+	var tpTemplateContent = $('#tpTemplateContent').val();
+	var jsonYn = $('#bizForm #bizJsonYn').val();
+	
+	if(selectAgentCode == '') {
+		alert("채널ID를 선택하고 다시 시도해 주세요.");
+		return false;
+	}
+	
+	if(selectTemplateCode == ''){
+		alert('템플릿을 선택 후 진행해 주세요.');
+		return false;
+	}
+
+	// 치환문자 있는 데이터 파씽
+	if($('#bizForm #txtReplYn').val() === 'Y'){
+		
+		//수신자 목록 체크
+		if($('.phoneArea').length < 1){
+			alert('받는 사람 입력 후 발송해 주세요');
+			return false;
+		}
+		
+		// title 배열
+		var varHead = [];
+		// 값 배열
+		var varVal = [];
+		
+		// excel title
+		$('#excelHead').find('div').each(function(index, item){
+			if(index != 0)
+				varHead.push($(item).text().replaceAll('\\t', ''));
+		});
+		form.varNmList.value = varHead;
+		
+		$('.excelBody').each(function(index, item){
+			varValTemp = '';
+			
+			if(index == 0){
+				$(item).find('.list_table_name').each(function(index, item){
+					if(index != 0)
+					{
+						if(index !== 1)
+							varValTemp += '§'+$(item).text().replaceAll('\\t', '');
+						else
+							varValTemp += $(item).text().replaceAll('\\t', '');
+					}
+				});
+				varVal.push(varValTemp);
+			}
+		});
+		form.varValList.value = varVal;
+	}
+	
+	form.senderKey.value = selectAgentCode;
+	form.templateCode.value = selectTemplateCode;
+	form.agentCodeTxt.value = selectAgentTxt;
+	form.txtReplYn.value = txtRepYn;
+	form.templateContent.value = tpTemplateContent;
+	form.bizJsonYn.value = jsonYn;
+	
+	form.method = "post"; 
+	window.open("about:blank", 'testSendPop', 'width=770, height=850, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=1');
+	form.target = "testSendPop";
+	form.action = "/web/mjon/kakao/alimtalk/selectKakaoAlimtalkTemplateDataTestPopup.do";
+	form.submit();
+}
+
+function goToReservKaKaoView(){
+	location.href="/web/mjon/reservmsg/selectReservKaKaoView.do";
+}
+
+function goToSendKaKaoView(){
+	location.href="/web/kakao/sent/selectKakaoSentView.do";
+}
+function goToPayUserKaKaoView(){
+	location.href="/web/member/pay/PayUserWithKakaoList.do";
+}
+
+function checkNumber(event) {
+	var divideCnt = $('#frmDivideCnt').val();
+	if(!(event.key >= 0 && event.key <= 9)) {
+		return false;
+	}
+	
+	var totCnt = divideCnt + "" + event.key;
+	if(Number(totCnt) > 5000){
+		alert("분할전송 건수는 5,000건을 초과할 수 없습니다.");
+		$('#frmDivideCnt').val("20");
+		return false;
+	}
+  
+  return true;
+}
+
+</script>
+
+	<div class="loading_layer">
+		<div class="loading_container">
+			<div class="bar"></div>
+			<div class="text">Loading</div>
+		</div>
+	</div>
+	
+	<!-- 기업회원 이동 팝업 -->
+	<div class="tooltip-wrap cvt_member_popup_wrap">
+	    <div class="popup-com cvt_member_layer" tabindex="0" data-tooltip-con="cvt_member_layer" data-focus="cvt_member_layer" data-focus-prev="cvt_member_layer-close">
+	       <div class="popup_heading">
+	           <p>알림</p>
+	           <button type="button" class="tooltip-close" data-focus="cvt_member_layer-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+	       </div>
+	       <div class="layer_in">
+	           <p>카카오톡 알림톡은 기업회원만 전송 가능합니다.<br>기업회원 전환 페이지로 이동하시겠습니까?</p>
+	           <div class="popup_btn_wrap2">
+	           	<button type="button" onclick="location.href='/web/user/membershipChange.do'">확인</button>
+	               	<button type="button" class="tooltip-close" data-focus="cvt_member_layer-close" data-focus-next="cvt_member_layer">취소</button>
+	            </div>
+	        </div>
+	    </div>
+	</div>
+	<button type="button" id="btnDeptPop" data-tooltip="cvt_member_layer" style="display: none;"></button>
+		
+
+	<!-- 템플릿 설정 디테일을 위한 FORM -->
+	<form id="templateForm" name="templateForm" method="post">
+		<input type="hidden" name="senderKey" value=""/>
+		<input type="hidden" name="templateCode" value=""/>
+		<input type="hidden" name="arrTemplateCode" value=""/>
+	</form>
+
+	<form id="bizForm" name="bizForm" method="post">
+		<input type="hidden" id="menuTopTab" name="menuTopTab" value="tabAlim">
+		<input type="hidden" id="senderKey" name="senderKey" value="">					<!-- 카카오 보내는 사람 Key -->
+		<input type="hidden" id="templateCode" name="templateCode" value="">			<!-- 카카오 전송 templat Code -->
+		
+		<input type="hidden" id="templateEmphasizeType" name="templateEmphasizeType" value="">		<!-- 카카오 전송 templateEmphasizeType 타입 -->
+		
+		<input type="hidden" id="templateContent" name="templateContent" value="">		<!-- 카카오 전송 templat내용 -->
+		<input type="hidden" id="templateTitle" name="templateTitle" value="">			<!-- 카카오 전송 templat 타이틀 -->
+		<input type="hidden" id="templateSubtitle" name="templateSubtitle" value="">	<!-- 카카오 전송 templat 서브 타이틀 -->
+		
+		<input type="hidden" id="subMsgTxtReplYn" name="subMsgTxtReplYn" value="">		<!-- 대체문자 전송내용에 변환문자가 있는지-->
+		<input type="hidden" id="subMsgSendYn" name="subMsgSendYn" value="">			<!-- 대체문자 전송여부 - 알림톡 전송 실패 시 문자 전송-->  
+		<input type="hidden" id="subMsgTxt" name="subMsgTxt" value="">					<!-- 대체문자 전송내용 -->
+		<input type="hidden" id="txtReplYn" name="txtReplYn" value="N">					<!-- 완 치환문자 여부 - --> 	
+		<input type="hidden" id="bizJsonYn" name="bizJsonYn" value="">					<!-- JSON 생성 여부 -->
+		
+		<input type="hidden" id="reserveYn" name="reserveYn" value="">					<!-- 예약문자 여부 - 예약 선택 여부 // 아래 하단 화면 노출 여부도 같이-->	
+		<input type="hidden" id="reqDate" name="reqDate" value="">						<!--전송일자-->
+		
+		<input type="hidden" id="divideChk" name="divideChk" value="">					<!--전송일자-->
+		<input type="hidden" id="divideCnt" name="divideCnt" value="">					<!--전송일자-->
+		<input type="hidden" id="divideTime" name="divideTime" value="">				<!--전송일자-->
+		
+		<input type="hidden" id="callFrom" name="callFrom" value="">					<!--완  보내는사람 -->	
+		<input type="hidden" id="callToList" name="callToList" value="">				<!--완  받는사람 리스트-->
+		<input type="hidden" id="varNmList" name="varNmList" value="">					<!--완  변수 이름  리스트-->
+		<input type="hidden" id="varValList" name="varValList" value="">				<!--완  변수 리스트-->
+		
+		<input type="hidden" id="atSmishingYn" name="atSmishingYn" value="${atSmishingYn}">		<!--알림톡 스미싱 여부-->
+	</form>
+
+	<form id="excelForm" name="excelForm" action="<c:url value='/web/mjon/alimtalk/kakaoApiNotityTalkSampleExcelDownload.do'/>">
+		<input type="hidden" id="excelTemplateContent" name="excelTemplateContent" value="">
+		<input type="hidden" id="excelTemplateSubtitle" name="excelTemplateSubtitle" value="">
+		<input type="hidden" id="excelTemplateTitle" name="excelTemplateTitle" value="">
+		<input type="hidden" id="varNmList" name="varNmList" value="">
+		<input type="hidden" id="varValList" name="varValList[]" value="">
+	</form>
+
+<%-- 	<form id="templateListPopup" name="templateListPopup" action="<c:url value='/web/mjon/kakao/template/selectKakaoAlimtalkTemplateListPopupAjax.do'/>" method="post"> --%>
+	<form id="templateListPopup" name="templateListPopup" action="<c:url value='/web/mjon/kakao/template/selectKakaoAlimtalkTemplateListPopupAjax.do'/>" method="post">
+		<input type="hidden" id="senderKey" name="senderKey" value="">
+		<input type="hidden" id="yellowId" name="yellowId" value="">
+		<input type="hidden" id="page" name="page" value="1">
+		<input type="hidden" id="formListType" name="formListType" value="thumbnail">
+		<input type="hidden" id="templateStatus" name="templateStatus" value="ACT"> <!-- 기본값 ACT:정상  -->
+	</form>
+	
+	<!-- 테스트 전송 FORM -->
+	<form id="kakaoAtDataTestPopupForm" name="kakaoAtDataTestPopupForm" method="post">
+		<input type="hidden" id="senderKey" name="senderKey" value="">					<!-- 카카오 보내는 사람 Key -->
+		<input type="hidden" id="templateCode" name="templateCode" value="">			<!-- 카카오 전송 templat Code -->
+		<input type="hidden" id="templateContent" name="templateContent" value="">		<!-- 카카오 전송 templat내용 -->
+		<input type="hidden" id="agentCodeTxt" name="agentCodeTxt" value="">			<!-- 카카오 전송 templat Code -->
+		<input type="hidden" id="txtReplYn" name="txtReplYn" value="N">					<!-- 치환문자 여부 - -->
+		<input type="hidden" id="varNmList" name="varNmList" value="">					<!-- 변수 이름  리스트-->
+		<input type="hidden" id="varValList" name="varValList" value="">				<!-- 변수 리스트-->
+		<input type="hidden" id="bizJsonYn" name="bizJsonYn" value="">				<!-- 변수 리스트-->
+	</form>
+	
+	<!-- 유저 보유잔액 -->
+	<input type="hidden" id="oriUserMoney" value="<c:out value='${userMoney }' />">
+	
+	<!-- 각 금액 단가  -->
+	<input type="hidden" id="kakaoAtPrice" value="<c:out value='${sendPrice.kakaoAtPrice }' />"> <!-- 알림톡 단가  -->
+	<input type="hidden" id="longPrice" value="<c:out value='${sendPrice.longPrice }' />"> <!-- mms 단가  -->
+	<input type="hidden" id="shortPrice" value="<c:out value='${sendPrice.shortPrice }' />"> <!-- sms 단가  -->
+
+	<!-- 각 금액 단가  -->
+	<input type="hidden" id="errorChk" value="N"> <!-- sms 단가  -->
+	
+
+	<div class="tooltip-wrap">
+		<!-- 문자발송 성공 레이어팝업 -->
+		<div class="popup-com pop_msg_success">
+			<div class="popup_heading">
+				<p>알림톡 전송 결과</p>
+				<button type="button" class="tooltip-close" onclick="msgSuccessClose(this);"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+			</div>
+			<div class="layer_in">
+				<div class="msg_text">발송 성공 : <strong>1</strong> 건,수신거부 : <span>0</span>건의<br>알림톡이 발송 되었습니다.</div>
+			</div>
+			<div class="popup_btn">
+				<button type="button" onclick="msgResultLink(); return false;">알림톡 발송결과 바로가기</button>
+				<button type="button" class="tooltip-close" onclick="msgSuccessClose(this);">확인</button>
+			</div>
+		</div>
+	</div>
+	<div class="tooltip-wrap">
+		<!-- 문자발송 실패 레이어팝업 -->
+		<div class="popup-com pop_msg_fails">
+			<div class="popup_heading">
+				<p>문자 전송 결과</p>
+				<button type="button" class="tooltip-close" onclick="msgFailsClose(this);"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+			</div>
+			<div class="layer_in">
+				<div class="msg_text">발송 성공 : <strong>1</strong> 건,수신거부 : <span>0</span>건의<br>문자가 발송 되었습니다.</div>
+			</div>
+			<div class="popup_btn">
+				<button type="button" class="tooltip-close" onclick="msgFailsClose(this);">확인</button>
+			</div>
+		</div>
+	</div>
+	<div class="tooltip-wrap">
+		<!-- 문자발송 스팸 이용정지 레이어팝업 -->
+		<div class="popup-com pop_msg_spam">
+			<div class="popup_heading">
+				<p>문자 전송 결과</p>
+				<button type="button" class="tooltip-close" onclick="msgSpamClose(this);"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+			</div>
+			<div class="layer_in">
+				<div class="msg_text"></div>
+			</div>
+			<div class="popup_btn">
+				<button type="button" class="tooltip-close" onclick="msgSpamClose(this);">확인</button>
+			</div>
+		</div>
+	</div>
+	<div class="inner">
+			<!-- send top -->
+			<div class="send_top">
+				<!-- tab button -->
+				<%@include file="/WEB-INF/jsp/web/kakao/include/KaKaoAlimtalkTopMenuTap.jsp" %>
+				<!--// tab button -->
+				<!-- 카카오톡 설정 - 알림톡 템플릿 등록/관리 - 내템플릿 -->
+				<div class="top_content kakaotalksend_cont current pay_tab_wrap">
+					<div class="send_general kakao_wrap">
+						<div class="send_left">
+							<table class="tType1">
+								<colgroup>
+									<col style="width: 90px;">
+									<col style="width: auto;">
+								</colgroup>
+								<tbody>
+									<tr>
+										<th>채널ID</th>
+										<td>
+											<label for="selectKakaoProfileList" class="채널ID 선택"></label>
+											<select class="select_gray_type" id="selectKakaoProfileList" name="selectKakaoProfileList">
+												<option value="">채널ID 선택</option>
+												<c:forEach var="kakaoProfileInfo" items="${kakaoProfileList}" varStatus="status">
+													<option value="${kakaoProfileInfo.senderKey}"><c:out value='${kakaoProfileInfo.yellowId}'/></option>
+												</c:forEach>
+											</select>
+											
+										</td>
+									</tr>
+									<tr>
+										<th>템플릿</th>
+										<td>
+											<select class="select_gray_type" id="selectTemplateList" name="selectTemplateList">
+<!--                                             <select name="" id="" class="select_gray_type"> -->
+												<option value="">알림톡 템플릿 선택</option>
+											</select>
+<!--                                             <button type="button" class="btnType btnType6" onclick="window.open('popup_allimtalk_template_choice.html','_blank','width=930, height=860, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=yes')">템플릿 선택</button> -->
+											<button type="button" class="btnType btnType6"  onclick="javascript:fnTemplateReg(); return false;">템플릿 등록</button>
+											<div class="variable_wrap">
+												<ul>
+													<li>* 변수명 설정파일을 다운로드 받으신 후 전송대상과 변수를 입력 후 업로드해주세요.</li>
+													<li>* 엑셀서식은 반드시 <span>텍스트 서식으로 등록</span>해주세요.</li>
+													<li>* 한번에 전송가능한 <span>최대 발송건은 500건</span>입니다.</li>
+													<li>* 배송조회시 운송장 번호는 <span>숫자만 등록</span>해주세요.</li>
+												</ul>
+												<button type="button" class="excel_btn" onclick="excelDownload();"><i></i> <c:out value="#"/>{변수명} 설정 파일 다운로드</button>
+<!--                                                 <button type="button" class="excel_btn"><i></i> 변수명 설정 파일 다운로드</button> -->
+											</div>
+										</td>
+									</tr>
+									<tr>
+										<th>받는사람</th>
+										<td class="putText">
+											<div class="clearfix receipt_num receiver_wrap01">
+												<div class="receipt_num_top">
+													<label for="callTo" class="label">받는 번호입력</label>
+													<input type="text" id="callTo" name="callTo" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*)\./g, '$1');"  placeholder="번호를 입력하세요" onfocus="this.placeholder=''" onblur="this.placeholder='번호를 입력하세요'" style="width:340px;">
+													<button type="button" class="btnType btnType6 addCallToF">번호추가</button>
+													</br>
+													<span>
+														<span class="vMiddle">*</span> 중복번호는 한번만 발송됩니다.
+													</span>
+													</br>
+													<span>
+														<span class="vMiddle">*</span> 한번에 전송가능한 최대 발송건은 500건 입니다.
+													</span>
+												</div>
+												<div class="receipt_num_midde">
+													<div class="listType list01" >
+														<div class="list_table list_head">
+															<div class="cb_wrap">
+																<label for="select_all" class="label"></label>
+																<input type="checkbox" id="select_all">
+															</div>
+															<div class="list_table_num">
+																<p>휴대폰</p>
+<!--                                                                 <img src="/publish/images/sortUp.png"> -->
+<!--                                                                 <img src="/publish/images/sortDown.png"> -->
+															</div>
+<!-- 															<div class="list_table_name"> -->
+<!-- 																<p>이름</p> -->
+<!--                                                                 <img src="/publish/images/sortUp.png"> -->
+<!--                                                                 <img src="/publish/images/sortDown.png"> -->
+<!-- 															</div> -->
+														</div>
+														<div class="list_body_wrap" id="wrap01_body">
+														</div>
+													</div>
+													<div class="put_right">
+														<div class="btn_popup_wrap spc_wrap">
+															<button type="button" data-tooltip="popup06" class="btnType btnType7 popupAddr">주소록 불러오기</button>
+														</div>
+														<div class="btn_popup_wrap">
+															<button type="button" data-tooltip="popup02" class="btnType btnType7">엑셀 불러오기</button>
+														</div>
+														<div class="btn_popup_wrap">
+															<button type="button" data-tooltip="popup03" class="btnType btnType7 tab1">최근 전송내역</button>
+														</div>
+														<div class="btn_popup_wrap">
+															<button type="button" data-tooltip="popup03" class="btnType btnType7 tab2">자주보내는 번호</button>
+														</div>
+														<div class="btn_popup_wrap check_validity_wrap">
+															<button type="button" class="btnType btnType7" id="check_validity">오류검사 <i class="qmMark"></i></button>
+															<div class="error_hover_cont send_hover_cont">
+																<p>휴대폰 번호 입력 시 해당 휴대폰 번호에 대한 형식이 어긋나거나 휴대폰 번호에 오류가 있는지 등을 검사하는 기능</p>
+																<span>(예시) 010-1234-0001(O) / 010-123-0001(X)</span>
+															</div>
+														</div>
+													</div>
+												</div>
+												<div class="list_bottom clearfix">
+													<div class="remove_btnWrap">
+														<button type="button" class="btnType15" id="all_del"><i class="remove_img"></i>전체삭제</button>
+														<button type="button" class="btnType15" id="select_del"><i class="remove_img"></i>선택삭제</button>
+													</div>
+													<div class="list_bottom_right">
+														<p>총 <span class="c_e40000" id="rowTotCnt">0</span>건 / 중복 <span class="c_002c9a" id="rowDupCnt">0</span>건</p>
+<!-- 														<button type="button" class="address_reg2">주소록에 등록</button> -->
+													</div>
+												</div>
+											</div>
+											<div class="clearfix receipt_num receiver_wrap02">
+												<div class="receipt_num_top">
+													<input type="text" placeholder="선택된 파일이 없습니다." onfocus="this.placeholder=''" onblur="this.placeholder='번호를 입력하세요'" style="width:340px;">
+													<button type="button" class="btnType btnType6" id="fileClick"/>파일선택</button>
+													<input type="file" id="excelFile" accept=".xls, .xlsx" onchange="excelExportVarAjax(event); return false;" style="display:none"/>
+													<!-- <input type="file" id="excelFile" accept=".xls, .xlsx" onchange="excelExport02(event); return false;" style="display:none"/> -->
+												</div>
+												<div class="receipt_num_midde">
+													<div class="listType list01" id="wrap02">
+														<!-- /publish/kakao_allimtalk_send.html 참고 -->
+														<div class="list_table list_head" id="excelHead">
+														</div>
+														<div class="list_body_wrap" id="excelBody02">
+														</div>
+													</div>
+												</div>
+											</div>
+										</td>
+									</tr>
+									<tr>
+										<th colspan="2" class="billingAmount">
+											<div>
+												<div class="final_pay">
+													<div class="pay_info_list">
+														<p>발송금액 :</p>
+                                                        <div class="info" id="repPriceTxt" style="display: none;">
+<!-- 														<div class="info" id="repPriceTxt"> -->
+<!-- 															단문 : <strong>20</strong>건<span>/</span> -->
+<!-- 															장문 :<strong>150</strong>건<span>/</span> -->
+<!-- 															그림문자 :<strong>30</strong>건 -->
+														</div>
+													</div>
+													<p class="price"><span id="repPriceTxt"></span><span id="totalPriceTxt">0.0</span> 원<span></span></p>
+												</div>
+												<div class="pay_type clearfix">
+								  					<fmt:formatNumber type="number" maxFractionDigits="3" value="${userMoney}" var="commaPrice" />
+													<div>
+														<input type="radio" id="radio_bill_1" name="radio_bill" checked="checked">
+														<label for="radio_bill_1">보유잔액</label>
+														<label for="userMoney" class="la bel">보유잔액</label>
+														<input type="text" id="userMoney" name="userMoney" value="<c:out value='${commaPrice}'/>" readonly>
+														<span class="won">원</span>
+														<button type="button" class="btnType btnType21" onclick="location.href='/web/member/pay/PayView.do'">충전</button>
+													</div>
+													<div></div>
+												</div>
+											</div>
+										</th>
+									</tr>
+									<tr>
+										<th colspan="2" class="replace_send_th">
+											<div class="title_th"><p>대체문자</p> 
+												<input type="checkbox" id="send_fail_check" style="margin: 0 8px 0 0;"><label for="send_fail_check">알림톡 전송 실패 시 문자 전송</label>
+											</div>
+											<div class="replace_send_wrap">
+<!--                                             <div class="replace_send_wrap"  style="display: block;"> -->
+												<table class="tType1">
+													<colgroup>
+														<col style="width: 90px;">
+														<col style="width: auto;">
+													</colgroup>
+													<tbody>
+														<tr>
+															<th>발신번호</th>
+															<td class="put_num">
+																<label for="callFromList" class="label"></label>
+																<select id="callFromList" name="callFromList" class="sel_number">
+																	<c:choose>
+																		<c:when test="${not empty resultPhonList}">
+																			<c:forEach var="phonList" items="${resultPhonList}" varStatus="status">
+																				<option value="${phonList}">${phonList}</option>
+																			</c:forEach>
+																		</c:when>
+																		<c:otherwise>
+																			<option value="">등록된 발신 번호가 없습니다.</option>
+																		</c:otherwise>
+																	</c:choose>
+																</select>
+																<button type="button" class="btnType btnType6" onclick="location.href='/web/user/sendNumberManage.do'">번호등록</button>
+															</td>
+														</tr>
+														<tr>
+															<th>내용</th>
+															<td class="putText">
+																<div class="clearfix">
+																	<div class="put_left short">
+																		<!-- 업로드한 이미지의 썸네일 영역 -->
+																		<ul class="thumb_wrap liOnImg ui-sortable"></ul>
+																		<!-- //업로드한 이미지의 썸네일 영역 -->
+																		<label for="smsTxtArea" class="label"></label>
+																		<textarea id="smsTxtArea" name="smsTxtArea" class="put_text"></textarea>
+																		<div class="text_length">
+																			<div name="afterDeny" id="afterDeny">
+																				<p>
+																					<span class="fwMd" id="msgLeng">0 /
+																					</span>
+																					<span class="c_002c9a fwMd" id="limitLeng">90</span>byte
+																				</p>
+																				<span
+																					class="msg_com msg_short">단문</span>
+																			</div>
+																		</div>
+																	</div>
+																	<div class="put_right">
+																		<button type="button" class="btnType btnType9" id="failCheckInit">초기화</button>
+                                                                        <button type="button" class="btnType btnType7" onclick="javascript:fn_errorChk(); return false;">오류검사<i class="qmMark"></i></button>
+<!--                                                                         <button type="button" class="btnType btnType8" onclick="showPotoediter();">이미지 불러오기</button> -->
+<!--                                                                         <div class="send_btnWrap"> -->
+<!--                                                                             <button type="button" class="btnType btnType9">문자저장</button> -->
+<!-- 																		</div> -->
+																	</div>
+
+																</div>
+<!--                                                                 <p id="lowText">* 현재 [<span id="nowMsgType">단문</span>] <span class="c_e40000 fwBold nowMsgCnt">0</span>건 발송 가능합니다.</p> -->
+															</td>
+														</tr>
+													</tbody>
+												</table>
+											</div>
+										</th>
+									</tr>
+								</tbody>
+							</table>
+						</div>
+						<div class="send_right">
+							<div class="phone">
+								<div class="phoneIn">
+									<p class="prev_p" id="prev_p_top"><img src="/publish/images/content/kakao_prev_icon.png" alt=""></p>
+									<!-- 텍스트 미리보기 -->
+									<div class="text_preview">
+										<div class="allimtalk_title">
+											<img src="/publish/images/content/icon_allimtalk.png" alt="">알림톡 도착
+										</div>
+										<div class="allimtalk_content" id="alimtalkTemplate">
+											<p class="emphasis_side_text">템플릿을 선택해 주세요</p>
+										</div>
+									</div>
+									<!-- //텍스트 미리보기 -->
+									<div class="template_info_wrap">
+										<div class="template_byte">
+<!--                                             <p><span class="fwMd" id="msgLeng">50 / </span><span class="c_002c9a fwMd" id="limitLeng">2000</span>byte</p> -->
+										</div>
+										<button type="button" class="btn_template_choice" id="reSelectBtn">템플릿 재선택</button>
+									</div>
+								</div>
+								<p class="addText">※ 단말기 설정에 따라 다르게 보일 수 있습니다<p>
+							</div>
+							<div class="phone_bottom">
+								<div class="send_rev">
+									<div class="send_content" style="padding-bottom: 0;">
+										<div class="rev_radio">
+											<ul>
+												<li>
+													<input type="radio" id="reserYnN" name="reserYn" value="N" checked="checked"><label for="reserYnN">즉시</label>
+												</li>
+												<li>
+													<input type="radio" id="reserYnY" name="reserYn" value="Y"><label for="reserYnY">예약</label>
+												</li>
+											</ul>
+										</div>
+										<div class="send_btn">
+											<button type="button" class="btnType btnType11" onclick="javascript:sendTemplateInfo(); return false;">발송하기</button>
+											<button type="button" class="btnType btnType10" onclick="javascript:goToKakaoTestPopUp(); return false;">테스트발송</button>
+										</div>
+									</div>
+									<div class="rev_selected">
+										<div class="rev_top">
+											<span>날짜 :</span>
+											<div class="calendar_wrap">
+												<input type="text" class="startDate2 inp resDate calendar picker__input picker__input--active" title="검색 시작일" id="startDate2" name="startDate2" value="" data-datecontrol="true" readonly="" aria-haspopup="true" aria-expanded="true" aria-readonly="false" aria-owns="startDate2_root">
+											</div>
+											<label for="msgResHour" class="label">시 선택</label>
+											<div class="selBox">
+												<select class="selType1" id="msgResHour" name="msgResHour">
+													<c:forEach  var="hour"  begin="0" end="23" step="1" varStatus="status">
+														<c:choose>
+															<c:when test="${hour < 10}">
+																<option value="0${hour}">0${hour}시</option>
+															</c:when>
+															<c:otherwise>
+																<option value="${hour}">${hour}시</option>
+															</c:otherwise>
+														</c:choose>
+													</c:forEach>
+												</select>
+												<label for="msgResMin" class="label">분 선택</label>
+												<select class="selType1" id="msgResMin" name="msgResMin">
+													<c:forEach var="min" begin="0" end="55" step="5">
+														<c:choose>
+															<c:when test="${min < 10}">
+																<option value="0${min}">0${min}분</option>
+															</c:when>
+															<c:otherwise>
+																<option value="${min}">${min}분</option>
+															</c:otherwise>
+														</c:choose>
+													</c:forEach>
+												</select>
+											</div>
+										</div>
+										<div class="rev_bottom">
+											<input type="checkbox" id="inputDivideChk" name="inputDivideChk">
+											<label for="inputDivideChk">분할전송</label>
+											<input type="text" class="dividType1" id="frmDivideCnt" name="frmDivideCnt" value="20" onkeypress='return checkNumber(event)' maxlength="4"/>
+     		            					<label for="frmDivideCnt">건씩</label>
+											<select class="selType1" id="divideTime" name="divideTime">
+						 						<option value="5">05분</option>
+						 						<option value="10">10분</option>
+						 						<option value="15">15분</option>
+						 						<option value="20">20분</option>
+						 						<option value="30">30분</option>
+						 					</select>
+						 					<label for="divideTime">간격</label>
+										</div>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<!--// send top -->
+		
+<!-- 주소록 불러오기 -->
+<div class="tooltip-wrap">
+	<div class="popup-com import_layer popup06" tabindex="0" data-tooltip-con="popup06" data-focus="popup06" data-focus-prev="popup06-close" style="width: 1000px">
+		<div class="popup_heading">
+			<p><span>주소록 불러오기</p>
+			<button type="button" onClick="javascript:addrClose(); return false;">
+			<img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+		</div>
+		<div class="layer_in">
+			<div class="titBox titBox_pad">
+				<p>- 주소록 수정 및 변경은 <span>[주소록 관리]</span>에서만 가능합니다.</p>
+				<button type="button" class="adr_admin" onClick="location.href='/web/mjon/addr/selectAddrList.do'">주소록 관리</button>
+			</div>
+			<div class="adr_wrap">
+				<form id="searchAddrGrpForm" name="searchAddrGrpForm" method="post" style="display: flex; justify-content: space-between;">
+					<input type="hidden" id="searchAddrGrpId" name="searchAddrGrpId" value=""/>
+					<input type="hidden" id="type" name="type" value="all"/>
+					<input type="hidden" id="searchKeyword" name="searchKeyword" value=""/>
+					<input type="hidden" name="searchCondition" id="searchCondition" value="0" />
+					<div class="adr_pop_left">
+						<div class="adr_left_search">
+							<label for="searchGrpKeyword" class="label">그룹명 검색</label>
+							<input type="text" name="searchGrpKeyword" id="searchGrpKeyword"  placeholder="그룹명 검색" onfocus="this.placeholder=''" onblur="this.placeholder='그룹명 검색'" class="inputLight">
+							<button type="button" onClick="javascrit:fnAddrGrpSearch(); return false;"><img src="/publish/images/popup/search.png" alt="검색"></button>
+						</div>
+						<div class="adr_pop_box">
+							<div id="addrGroupLoad">
+							</div>
+						</div>
+						<!-- <div class="popup_btn">
+							<button type="button" class="btnType" onClick="javascript:fnSelectAddrGrpList(); return false;">선택 그룹 추가</button>
+						</div> -->
+					</div>
+					<div class="adr_pop_right">
+						<div class="clearfix">
+							<div class="btnWrap_last">
+								<label for="searchAddrCondition" class="label">카테고리 선택</label>
+								<select id="searchAddrCondition" name="searchAddrCondition" class="selType2">
+									<option value='0'>전체</option>
+									<option value='1'>그룹명</option>
+									<option value='2'>이름</option>
+									<option value='3'>핸드폰번호</option>
+								</select>
+								<label for="searchAddrKeyword" class="label">검색어 입력</label>
+								<input type="text" id="searchAddrKeyword" name="searchAddrKeyword" placeholder="검색어를 입력하세요"  onfocus="this.placeholder=''" onblur="this.placeholder='검색어를 입력하세요'" >
+								<button type="button" class="btnType btnType17"  onClick="javascrit:fnAddrSearch(); return false;">검색</button>
+							</div>
+							<!-- table -->
+							<div class="adr_excel adr_pop_list2 callAddr_box">
+							</div>
+							<!--// table -->
+						</div>
+						<div class="popup_btn_wrap2">
+							<button type="button" onClick="javascript:addrToList(); return false;">추가</button>
+							<button type="button" onClick="javascript:addrClose(); return false;">닫기</button>
+						</div>
+						<%-- 주소록 레이어 팝업 닫기 실행 코드 --%>
+						<input type="hidden" name="btnAddrClose" id="btnAddrClose" class="tooltip-close closeAddr" data-focus="popup06-close" />         
+					</div>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>
+<!--// 주소록 불러오기 -->
+
+<!-- 최근 전송 내역 -->
+<div class="tooltip-wrap">
+	<div class="popup-com history_layer popup03" tabindex="0" data-tooltip-con="popup03" data-focus="popup03" data-focus-prev="popup03-close">
+		<div class="popup_heading">
+			<p><span>전송내역</p>
+			<button type="button" class="tooltip-close" data-focus="popup03-close" id="btnLatestAddPhoneClose"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+		</div>
+		<div class="layer_in">
+			<!-- tab button -->
+			<ul class="tabType6"> 
+				<li class="tab active"><button type="button" onclick="TabType(this,'1');">최근 전송내역</button></li>
+				<li class="tab"><button type="button" onclick="TabType(this,'2');">자주보내는 번호</button></li>
+			</ul><!--// tab button -->
+			<!-- 최근 전송내역 -->
+			<div class="history_cont hascont current">
+				<div class="histroy_trans latestMsgArea" id="latestMsgArea">
+					<ul id="latestMsgUl">
+						<c:choose>
+							<c:when test="${not empty resultLatestMsgList}">
+								<c:forEach var="latestMsgList" items="${resultLatestMsgList}" varStatus="status">
+									<li id="latestLi">
+										<input type="checkbox" id="addrChk_${status.count}" name="latAddrChk" value="<c:out value='${latestMsgList.callTo}'/>">
+										<label for="addrChk_${status.count}" class="label">최근 전송내역</label>
+										<p><c:out value="${latestMsgList.callTo}"/></p>
+										<button type="button" id="latestAddrDel"><img src="/publish/images/popup/close3.png"  alt="전화번호 삭제"></button>
+									</li>
+								</c:forEach>
+							</c:when>
+							<c:otherwise>
+								<li>
+									<p>최근 발송 내역이 없습니다.</p>
+								</li>
+							</c:otherwise>
+						</c:choose>
+					</ul>
+				</div>
+				<div class="popup_btn_wrap2 hisroy_btn">
+					<button type="button" id="latestAddPhone">선택추가</button>
+					<button type="button" id="latestCancelPhone">선택취소</button>
+				</div>
+			</div><!--// 최근 전송내역 -->
+			<!-- 자주보내는 번호 -->
+			<div class="history_cont hascont">
+				<div class="histroy_trans" id="bookMarkMsgArea">
+					<ul id="bookMsgUl">
+						<c:choose>
+							<c:when test="${not empty resultBookMarkMsgList}">
+								<c:forEach var="bookMarkMsgList" items="${resultBookMarkMsgList}" varStatus="status">
+									<li id="bookMarkLi">
+										<input type="checkbox" id="bokAddrChk_${status.count}" name="bookAddrChk" value="<c:out value='${bookMarkMsgList.addrPhoneNo}'/>">
+										<label for="addrChk_${status.count}" class="label">최근 전송내역</label>
+										<p><c:out value="${bookMarkMsgList.addrPhoneNo}"/></p>
+										<button type="button" id="bookMarkAddrDel"><img src="/publish/images/popup/close3.png"  alt="전화번호 삭제"></button>
+									</li>
+								</c:forEach>
+							</c:when>
+							<c:otherwise>
+								<li>
+									<p>등록된 자주 보내는 번호 내역이 없습니다.</p>
+								</li>
+							</c:otherwise>
+						</c:choose>
+					</ul> 
+				</div>
+				<div class="popup_btn_wrap2 hisroy_btn">
+					<button type="button" id="bookMarkAddPhone">선택추가</button>
+					<button type="button" id="bookMarkCancelPhone">선택취소</button>                      
+				</div>
+			</div><!--// 자주보내는 번호  -->         
+		</div>
+	</div>
+</div>
+<!--// 전송내역 팝업 -->
+
+
+
+<!-- 엑셀 불러오기 -->
+<form id="excelToolTipForm" name="excelToolTipForm" method="post">
+	<div class="tooltip-wrap">
+		<div class="popup-com import_layer popup02" tabindex="0" data-tooltip-con="popup02" data-focus="popup02" data-focus-prev="popup02-close">
+			<div class="popup_heading">
+				<p><span>엑셀</span> 불러오기</p>
+				<button type="button" class="tooltip-close" data-focus="popup02-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+			</div>
+			<div class="layer_in">
+				<!-- 엑셀파일 불러오기 -->
+				<div class="hascont">
+					<div class="titBox">
+						<p>- 최대 2만 건까지 등록할 수 있습니다.</p>
+						<p>- [엑셀 불러오기]시 문서의 A, B열을 불러옵니다.(지원하는 파일 형식 : xls, xlsx)</p>
+						<p>- 휴대폰 항목은 숫자, 하이픈(-)만 인식하며, 번호 앞에 0이 생략되어도 정상 등록됩니다.
+						</p>
+						<!-- <button type="button" class="excel_btn" onclick="location.href='/cmm/fms/FileDown.do?atchFileId=FILE_000000000011651&fileSn=1'"><i></i>샘플파일 다운로드</button> -->
+						<button type="button" class="excel_btn" onclick="location.href='/download/msg/알림톡_엑셀주소록_등록양식.xlsx'"><i class="downroad"></i>샘플파일 다운로드</button>
+					</div>
+					<div class="attachedFile">
+						<label for="excelNm01" class="attachedFile_label">첨부파일</label>
+						<input type="text" id="excelNm01" value="" readonly>
+						<input type="file" id="excelFile01" accept=".xls, .xlsx" onchange="excelExportAjax(event); return false;" style="display:none"/>
+						<!-- <input type="file" id="excelFile01" accept=".xls, .xlsx" onchange="excelExport01(event); return false;" style="display:none"/> -->
+						<button type="button" class="btnType btnType6 c1">찾아보기</button>
+<!-- 						<p><span class="vMiddle">*</span> 첨부된 파일은 <span class="c_e40000">[추가]버튼을 클릭</span>하셔야 받는 사람에 등록됩니다.</p> -->
+						<p><span class="vMiddle">*</span> 첨부된 파일은 <span class="c_e40000">[추가]버튼을 클릭</span>하셔야 받는 사람에 등록됩니다.</p>
+					</div>
+				</div><!--// 엑셀파일 불러오기 -->
+				<div class="popup_btn_wrap2">
+					<button type="button" class="tooltip-close" data-focus="popup02-close"  data-focus-next="popup02" onclick="excelAddAjax()">추가</button>
+					<!-- <button type="button" class="tooltip-close" data-focus="popup02-close"  data-focus-next="popup02" onclick="excelAdd()">추가</button> -->
+					<button type="button" class="tooltip-close" data-focus="popup02-close"  data-focus-next="popup02">닫기</button>                      
+				</div>
+			</div>
+		</div>
+	</div><!--// 엑셀 불러오기 -->
+</form>
+<form id="excelVarFileForm" name="excelVarFileForm" method="post">
+	<input type="hidden" id="excelVarCnt" name="excelVarCnt" value="0"/>
+	<input type="hidden" id="excelVarList" name="excelVarList" value=""/>
+	
+</form>
+
+<form id="msgResendForm" name="msgResendForm" method="post">
+	<input name="msgResendFlag" type="hidden" value="N"/>
+	<input name="msgSeqList" type="hidden" value=""/>
+</form>
+<form id="moveAddrForm" name="moveAddrForm" method="post">
+	<input name="moveAddrFlag" type="hidden" value="N"/>
+	<input name="addrIdList" type="hidden" value=""/>
+</form>
src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp
--- src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp
+++ src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp
@@ -18,8 +18,6 @@
 
 $(document).ready(function(){
 
-	
-	console.log(": MsgDataSMLView :");
 
 // 	console.log(' + $(#tabDision).val() : ',$('#tabDision').val())
 // 	if($('#tabDision').val() == 'tab02'){
src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp
--- src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp
+++ src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp
@@ -71,8 +71,6 @@
             </div>
         </div>
         <div class="btn_wrap">
-            <!-- <button type="button" class="btnType btnType2" style="margin:50px 0;" onclick="progressStart(10,'완료되었습니다.');">시작</button>
-            <button type="button" class="btnType btnType2" style="margin:50px 0;" onclick="progressComplete('완료되었습니다.');return false;">멈춤</button> -->
         </div>
 
     </div>
src/main/webapp/js/MJUtill.js
--- src/main/webapp/js/MJUtill.js
+++ src/main/webapp/js/MJUtill.js
@@ -200,6 +200,8 @@
 
 //숫자 천단위 콤마 찍어주기
 function numberWithCommas(x) { 
+    console.log(' + typeof x : ',typeof x);
+    console.log(' + x : ',x);
 	return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 
 }
 
@@ -1030,6 +1032,17 @@
 }
 
 
+function setAllCntData(result){
+
+    console.log('result :: ', result);
+    // 합쳐진 데이터를 tableL에 설정합니다.
+    tableL.setData(result.uniqueArray);
+    // 중복데이터 건수 입력
+    setRowDupCnt(result.duplicateCount);
+         
+    $('#rowTotCnt').text(result.uniqueCount)
+}
+
 function validateRowLimit(totalRows, limit = 300000) {
 	// 값과 타입 확인
 
src/main/webapp/js/kakao/at/addr.js
--- src/main/webapp/js/kakao/at/addr.js
+++ src/main/webapp/js/kakao/at/addr.js
@@ -101,6 +101,7 @@
 }
 
 //주소록 불러오기에서 수신자 리스트 추가해 주기
+/*
 function addrToList(){
 	
 	var selectedData = tableAddr.getSelectedRows();
@@ -114,10 +115,10 @@
 	}else{ // 선택한 Row 데이터 저장해주기
 		
 		// 선택한 Row 데이터 저장해주기
-		if(selectedData.length > 500){
-			alert("최대 발송 건수는 500 입니다.");
-			return false;
-		}else{
+//		if(selectedData.length > 500){
+//			alert("최대 발송 건수는 500 입니다.");
+//			return false;
+//		}else{
 			for(var i=0; i < selectedData.length; i++){
 				
 				//좌측 받는사람 리스트를 담아둔 배열에 데이터를 추가해 준다.
@@ -137,9 +138,67 @@
 			
 			//주소록 레이어 팝업의 Tabulator 데이터 지워주기
 			tableAddr.clearData();
-		}
+//		}
 	}
 	
+}
+*/
+
+//주소록 불러오기에서 수신자 리스트 추가해 주기
+function addrToList_advc(type){
+
+
+    // 선택된 데이터 또는 전체 데이터 변수 초기화
+    let selectedData = type === 'select' ? tableAddr.getSelectedRows() : tableAddr.getData();
+    
+    // 데이터가 비어있으면 경고 후 종료
+    if (!selectedData || selectedData.length < 1) {
+        
+        if(tableAddr.getDataCount() < 1){
+            alert("주소록을 선택해 주세요.");
+        }else{
+            alert("전화번호를 선택해 주세요.");
+        }
+        
+        return false;
+    }
+
+
+    // 데이터 변환 로직
+    const addrData = selectedData.map(row => {
+        const rowData = type === 'select' ? row.getData() : row; // 'select'는 행 객체에서 데이터 추출
+        return {
+            phone: removeDash(rowData.phone),
+        };
+    })
+    .filter(row => checkHpNum(row.phone)); // 유효한 번호만 필터링;
+
+
+    // 기존 tableL의 데이터를 가져옵니다.
+    var existingData = tableL.getData();
+    // 기존 데이터와 새로운 데이터를 합칩니다.
+    var combinedData = existingData.concat(addrData);
+
+    // @ phone을 기준으로 중복 제거 및 갯수 계산
+    const result = removeDuplicatesAndCount(combinedData, 'phone');
+
+
+
+    // 총 30만건이 넘으면 false
+    if (!validateRowLimit(result.uniqueCount)) {
+        return false;
+    }
+
+    setAllCntData(result);
+
+
+    // 미리보기 버튼 활성화
+
+
+    $(".closeAddr").trigger("click");
+    //주소록 레이어 팝업의 Tabulator 데이터 지워주기
+    tableAddr.clearData();
+    fn_priceClclt();
 }
 
 function loadAddrList(){
@@ -150,7 +209,8 @@
 	*/
 	var data = $("#searchAddrGrpForm").serialize();	 
 
-	var url = "/web/mjon/msgdata/selectMsgAddrListAjax.do";
+	// var url = "/web/mjon/msgdata/selectMsgAddrListAjax.do";
+    var url = "/web/mjon/msgdata/selectMsgAddrListAjax_advc.do";
 	
 	$.ajax({
         type: "POST",
@@ -159,43 +219,36 @@
         dataType:'json',
         async: false,
         cache: false,
-        success: function (returnData, status) {
-			console.log('returnData : ', returnData);
-			if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나
-				if(returnData.result == "success"){
-					
-					var addrList = returnData.resultAddrList;
-					var tableData = [];
-					
-					if(addrList.length == 0){
-						
-						alert("주소록 정보가 없습니다.");
-						tableAddr.setData(tableData);
-						return false;
-					}
-					
-					//받는사람 리스트를 담아둔 배열에 신규 추가 데이터를 추가해 준다.
-					for(var i=0; i < addrList.length; i++){
-						
-						tableData.push({addrGroupNm: addrList[i].addrGrpNm, addrPhone: removeDash(addrList[i].addrPhoneNo) , addrName: addrList[i].addrNm, addrRep1: addrList[i].addrInfo1, addrRep2: addrList[i].addrInfo2, addrRep3: addrList[i].addrInfo3, addrRep4: addrList[i].addrInfo4});
-						
-					}
-					
-					//우측 주소록 리스트 Tabulator에 입력해주기
-					tableAddr.setData(tableData);
-					
-				}else{
-					
-					alert(returnData.message);
-					return false;
-					
-				}
-				
-			} else if(status== 'fail'){
-				alert("주소록 불러오기에 실패하였습니다. !!");
-			}
-		},
-        error: function (e) { alert("주소록 불러오기에 실패하였습니다."); console.log("ERROR : ", e); }
+        success: function (data) {
+        console.log('data : ', data);
+        if(data.status == "OK"){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나
+            
+                var addrList = data.object;
+                
+                if(addrList.length == 0){
+                    
+                    alert("주소록 정보가 없습니다.");
+//                    tableAddr.setData([]);
+                    return false;
+                }
+                tableAddr.setData(addrList);
+        } 
+        else
+        {
+            alert("주소록 불러오기에 실패하였습니다. !!");
+        }
+        },
+        error: function (e) {
+             alert("주소록 불러오기에 실패하였습니다."); console.log("ERROR : ", e); 
+         }
+        , beforeSend : function(xmlHttpRequest) {
+                    //로딩창 show
+            $('.loading_layer').addClass('active');             
+        }
+        , complete : function(xhr, textStatus) {
+            //로딩창 hide
+            $('.loading_layer').removeClass('active');
+        }
     });
 	
 }
src/main/webapp/js/kakao/at/alimtalkExcel.js
--- src/main/webapp/js/kakao/at/alimtalkExcel.js
+++ src/main/webapp/js/kakao/at/alimtalkExcel.js
@@ -198,6 +198,7 @@
  * 
  * */
 function excelExportVarAjax(){
+    console.log(' :: excelExportVarAjax ::')
 	
 	var data = document.getElementById('excelFile').files;
 	
@@ -245,7 +246,7 @@
         //timeout: 600000,
         success: function (returnData, status) {
 			if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나
-				
+				console.log('returnData : ', returnData);
 				if(returnData.success){
 					
 					var data = returnData.data;
@@ -290,10 +291,10 @@
 						
 						var totalDuplCnt = $('#rowDupCnt').text();//중복 건수 정보
 						var $excelBody = $('#excelBody02');
-						var bodyData;
 						var addDiv = "";
 						var phoneNum;
 
+                        var msgCnt = 0;
 						//입력데이터를 역정렬해준다.
 						data.reverse();
 
@@ -337,6 +338,7 @@
 									
 									if(lengthCheck){
 										addDiv += excelBody;
+                                        msgCnt++;
 									}
 									
 								}
@@ -359,6 +361,9 @@
 						
 						//화면에 수신번호 및 변수 데이터 추가해 주기
 						$excelBody.append(addDiv);
+                        
+                        // 총 금액 계산
+                        fn_priceClclt(msgCnt);
 
 					}
 					
src/main/webapp/js/kakao/at/init.js
--- src/main/webapp/js/kakao/at/init.js
+++ src/main/webapp/js/kakao/at/init.js
@@ -12,6 +12,8 @@
  * 
  * 
  */
+
+
 $(document).ready(function(){
 
 
src/main/webapp/js/kakao/at/priceClclt.js
--- src/main/webapp/js/kakao/at/priceClclt.js
+++ src/main/webapp/js/kakao/at/priceClclt.js
@@ -70,8 +70,6 @@
 		fn_priceClclt();
 	});
 
-	
-
 
 	// 대상 노드에 감시자 전달
 	observer_wrap01.observe(target01, option);
@@ -85,18 +83,24 @@
 /**
  * @description 금액 계산 function
  */
-function fn_priceClclt(){
+function fn_priceClclt(phoneSu = 0){
 
-	// 미리보기 텍스트
-	var templateHtml = $('#smsTxtArea').val();
-	// var templateHtml = $('.template_text').html();
-	
-	// 수신 번호 개수
-	var phoneSu = $('.phoneArea').length;
+    console.log(":: at fn_priceClclt :: ");
+    // 미리보기 텍스트
+    var templateHtml = $('#smsTxtArea').val();
+    // var templateHtml = $('.template_text').html();
+    
+    // 치환문자 여부 확인
+    var txtReplYn = $('#txtReplYn').val()
+    console.log('txtReplYn : ', txtReplYn);
+    
+    // 수신 번호 개수
+    if(phoneSu == 0 && txtReplYn == 'Y')
+    	phoneSu = $('.phoneArea').length;
+    if(phoneSu == 0 && txtReplYn == 'N')
+    	phoneSu = tableL.getData().length;
 	// 대체문자 있는지 확인
 	var isSendFailChecked = $("#send_fail_check").is(":checked");
-	// 치환문자 여부 확인
-	var txtReplYn = $('#txtReplYn').val()
 	// 대체문자 하위에 장문 / 단문 select
 	var msgTypeText = $('.msg_com').text().trim();
 
@@ -212,8 +216,8 @@
 	if(msgTypeText == '단문') price = SHORT_PRICE * phoneSu;
 	else if(msgTypeText == '장문') price = LONG_PRICE * phoneSu;
 	else  price = KAKAO_AT_PRICE * phoneSu; // 카카오
-
-	$('#totalPriceTxt').text((price).toFixed(1));
+    
+	$('#totalPriceTxt').text(numberWithCommas((price).toFixed(1)));
 }
 
 
src/main/webapp/js/kakao/at/tabulator.js
--- src/main/webapp/js/kakao/at/tabulator.js
+++ src/main/webapp/js/kakao/at/tabulator.js
@@ -12,83 +12,41 @@
  * 
  * 
  */
-
+var tableL = null;
 $(document).ready(function (){
-	/**
 	//받는사람 연락처 내용 처리
 	//Tabulator AJAX Data Loading
-	tableL = new Tabulator(".callList_box", {
+	tableL = new Tabulator(".callList_box_P", {
 		height:"255px",
-	    layout:"fitColumns",
-	    //data:tabledata,
-	    //autoColumns:true,
+        layout:"fitColumns",
+        headerHozAlign:"center",
+        validationMode:"highlight",
 	    headerHozAlign:"center",
 	    validationMode:"highlight",
-	    //clipboard:false,
-	    //clipboardCopySelector:"table",
-	    //clipboardPasteAction:"insert", // insert, update, replace
 	    placeholder:"복사(Ctrl+C)한 내용을 여기에 붙여넣기(Ctrl+V) 해주세요.", //fit columns to width of table (optional)
 	    resizableColumns:false,
+        columnDefaults:{ // 공통설정
+            hozAlign: "center",
+            headerHozAlign: "center",
+            editor: "input",
+            editor: false
+        },
 	 	columns:[ //Define Table Columns
-	 		{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", headerSort:false, cellClick:function(e, cell){
+	 		{formatter:"rowSelection", titleFormatter:"rowSelection", width:60, clipboard:false, hozAlign:"center", headerSort:false, cellClick:function(e, cell){
 	 	        cell.getRow().toggleSelect();
 		 	}}, 
-		 	{title:"이름", hozAlign:"center", field:"name", editor:"input", validator:["maxLength:12"], cellEdited:function(cell){
-		 	    //cell - cell component
-		 	    fnReplCell();
-		    }},
-		 	{title:"휴대폰", hozAlign:"center", field:"phone", editor:"input", width:100, validator:["required","minLength:10", "maxLength:12"], cellEdited:function(cell){
+//		 	{title:"이름", hozAlign:"center", field:"name", editor:"input", validator:["maxLength:12"], cellEdited:function(cell){
+//		 	    //cell - cell component
+//		 	    fnReplCell();
+//		    }},
+		 	{title:"휴대폰", hozAlign:"center", field:"phone", editor:"input", validator:["required","minLength:10", "maxLength:12"], cellEdited:function(cell){
 		 	    //cell - cell component
 		 	    fnDuplPhone();
 		    }},
-		 	{title:"[*1*]", hozAlign:"center", field:"rep1", editor:"input", minWidth:60, validator:["maxLength:40"], cellEdited:function(cell){
-		 	    //cell - cell component
-		 	    fnReplCell();
-		    }},
-		 	{title:"[*2*]", hozAlign:"center", field:"rep2", editor:"input", minWidth:60, validator:["maxLength:40"], cellEdited:function(cell){
-		 	    //cell - cell component
-		 		fnReplCell();
-		    }},
-		 	{title:"[*3*]", hozAlign:"center", field:"rep3", editor:"input", minWidth:60, validator:["maxLength:40"], cellEdited:function(cell){
-		 	    //cell - cell component
-		 		fnReplCell();
-		    }},
-		 	{title:"[*4*]", hozAlign:"center", field:"rep4", editor:"input", minWidth:60, validator:["maxLength:40"], cellEdited:function(cell){
-		 	    //cell - cell component
-		 		fnReplCell();
-		    }},
-		 	
-	 	],
-	 	validationFailed:function(cell, value, parameters){ // 유효성 체크 함수 - 아직 잘 모르겠음 
-	        //take action on validation fail
-	 		var valid = cell.isValid();
-	 		var fieldNm = cell.getField();
-	 		var cellVal = cell.getValue();
-	 		var returnVal = "";
-	 		if(!valid){
-	 			
-	 			if(fieldNm == "name"){
-	 				alert("받는사람 이름은 최대 12글자까지만 입력 가능합니다.");
-	 				cell.setValue(strMaxLengthSubstring(cellVal, 11)); //스크립트 함수가 0부터 시작이므로 원하는 글자수 -1을 해줘야한다.
-	 				cell.clearValidation();
-	 			}else if(fieldNm == "phone"){
-	 				alert("휴대폰번호는 하이픈(-)을 제외한 숫자만 정확히 입력해 주세요.");
-	 			}else{
-		 			alert("치환문자를 정확히 입력해 주세요. 40글자 이내로 입력 가능합니다.");
-		 			cell.setValue(strMaxLengthSubstring(cellVal, 39));
-		 			cell.clearValidation();
-	 			}
-	 			
-	 			//해당 셀 데이터 삭제
-	 			//cell.setValue("");
-	 			
-	 		}
-	 		return value % parameters.phone;
-	    },
+	 	]
 
 	});
 	
-	 */
 	//주소록 불러오기 팝업 내용
 	//Tabulator AJAX Data Loading
 	tableAddr = new Tabulator(".callAddr_box", {
@@ -99,13 +57,13 @@
 	    placeholder:"주소록 그룹을 선택해 주세요.", //fit columns to width of table (optional)
 	    resizableColumns:false,
 	 	columns:[ //Define Table Columns
-	 		{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", headerSort:false, cellClick:function(e, cell){
+	 		{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", headerSort:false, width: 50, cellClick:function(e, cell){
 	 	        cell.getRow().toggleSelect();
 		 		}
 		 	}, 
-		 	{title:"그룹명", hozAlign:"center", field:"addrGroupNm", editor:"input", width:120, validator:["required","minLength:2", "maxLength:40"]},
-		 	{title:"이름", hozAlign:"center", field:"addrName", editor:"input",  width:120, validator:["maxLength:12"]},
-		 	{title:"휴대폰번호", hozAlign:"center", field:"addrPhone", editor:"input", width:120, validator:["required","minLength:10", "maxLength:11"]},
+		 	{title:"그룹명", hozAlign:"center", field:"addrGroupNm", widthGrow: 3, editor:"input", validator:["required","minLength:2", "maxLength:40"]},
+		 	{title:"이름", hozAlign:"center", field:"name", widthGrow: 2, editor:"input", validator:["maxLength:12"]},
+		 	{title:"휴대폰번호", hozAlign:"center", field:"phone", widthGrow: 3, editor:"input", validator:["required","minLength:10", "maxLength:11"]},
 		 	
 	 	],
 	 	validationFailed:function(cell, value, parameters){ // 유효성 체크 함수 - 아직 잘 모르겠음 
@@ -132,53 +90,32 @@
 	//받는사람 번호 버튼 클릭시 Tabulator에 데이터 넣어주기
 	$('.addCallToF').click(function(){ 
 		
-		var callToNum = $('#callTo').val();
-		if(callToNum == null || callToNum == ""){
-			
-			alert("받는사람 번호를 입력해 주세요.");
-			return false;
-			
-		}else if(!checkHpNum(callToNum)){	
-			
-			alert("올바른 전화번호를 입력해 주세요.");
-			$('#callTo').val("");
-			return false;
-		}
-		
-		//핸드폰 번호에 '-' 문자 제거하기
-		callToNum = removeDash(callToNum);
+        // checkHpNum(callToNum)
+        
+        
 
-		  var dpCnt = 0;
-		$(".phoneArea p").each(function(index, item){
-			if(this.textContent == callToNum){
-				
-				dpCnt++;
-				
-				alert("받는사람 리스트에 동일한 연락처가 있습니다.");
-		    	$('#callTo').val("");
-		    	return false;
-			}
-		});
-		
-		if(dpCnt > 0){
-			alert("받는사람 리스트에 동일한 연락처가 있습니다.");
-			$('#callTo').val("");
-			return false;
-		}else{
-			// fn_displayJsonToHtmlTable 재사용을 위한
-			// 파라미터 형변환
-			var data =[];
-			data.push({ phone: callToNum, name: ''});
-			fn_displayJsonToHtmlTable(data);
-			
-			/*
-			 * 토탈 카운트 화면에 노출
-			 */ 
-			updateTotCnt();	
-			
-			// 번호 추가란 초기화
-			$('#callTo').val('');
-		}
+        var textarea = $('#callTo');
+        const numbers = textarea.val().split('\n')
+                                .map(num => removeDash(num.trim()))
+                                .filter(num => num !== "")
+                                .filter(num => checkHpNum(num)); // 유효한 번호만 필터링;
+                                
+                                
+        
+        const formattedData = numbers.map(num => ({phone: num}));
+
+        // 기존 tableL의 데이터를 가져옵니다.
+        var existingData = tableL.getData();
+        // 기존 데이터와 새로운 데이터를 합칩니다.
+        var combinedData = existingData.concat(formattedData);
+
+        // @ phone을 기준으로 중복 제거 및 갯수 계산
+        const result = removeDuplicatesAndCount(combinedData, 'phone');
+        
+        setAllCntData(result);
+        
+        textarea.val('');
+        fn_priceClclt();
 	});
 	
 	
@@ -442,9 +379,9 @@
 * 토탈 카운트 화면에 노출
 * 변수 없는 리스트만 체크
 */ 
-function updateTotCnt(){
+function updateTotCnt(cnt){
 	
-	$("#rowTotCnt").text($('#wrap01_body .list_body').length);
+	$("#rowTotCnt").text(cnt);
 
 }
 
@@ -456,10 +393,10 @@
 		return;
 	}
 	
-	if(taData.length  > 500){
-		alert("최대 발송 건수는 500건 입니다.");
-		return;
-	}
+//	if(taData.length  > 500){
+//		alert("최대 발송 건수는 500건 입니다.");
+//		return;
+//	}
 	
 	
 	/*
src/main/webapp/js/web/msgdata/msgDataView.js
--- src/main/webapp/js/web/msgdata/msgDataView.js
+++ src/main/webapp/js/web/msgdata/msgDataView.js
@@ -1269,8 +1269,6 @@
 	
 	var url = "/web/mjon/msgdata/sendMsgDataAjax_advc.do";
 	 // 시작 시간
-	const startTime = new Date();
-	 
 	
 	 // 프로그래스파 시간을 위한 계산
 	var estimtedTime = calculateEstimatedTime($selectedData.length);
Add a comment
List