이호영 이호영 2025-03-21
알림톡 발송개선 진행중
@11e32cd532ba4bdd8ff2e7f0c3d2508593955814
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/KakaoSendAdvcVO.java
--- src/main/java/itn/let/kakao/kakaoComm/KakaoSendAdvcVO.java
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoSendAdvcVO.java
@@ -38,6 +38,7 @@
 	private String msgType;				// 메시지 타입
 	private String templateContent;		// 템플릿 내용
 	private String templateTitle;		// 템플릿 제목
+	List<KakaoButtonVO> buttonList;		// 템플릿 버튼 리스트
 	private String subMsgSendYn;		// 대체문자 전송 여부
 	private String subMsgTxt;			// 대체문자 내용
 	private String subMsgType;			// 대체문자 타입
@@ -48,9 +49,11 @@
 	// =====
 	// =====
 
-	private float smsPrice;		// sms 단가
-	private float mmsPrice;		// mms 단가
-	private float kakaoAtPrice;	// 카카오 알림톡 단가
+	private String eachPrice;		// sms 단가
+	private String smsPrice;		// sms 단가
+	private String mmsPrice;		// mms 단가
+	private String kakaoAtPrice;	// 카카오 알림톡 단가
+	private String bizJsonName;	// 카카오 알림톡 단가
 	
 	
 	
@@ -69,6 +72,7 @@
 			"\n , msgType=[" + msgType + "]" +
 			"\n , templateContent=[" + templateContent + "]" +
 			"\n , templateTitle=[" + templateTitle + "]" +
+			"\n , buttonList=[" + buttonList.toString() + "]" +
 			"\n , subMsgSendYn=[" + subMsgSendYn + "]" +
 			"\n , subMsgTxt=[" + subMsgTxt + "]" +
 			"\n , subMsgType=[" + subMsgType + "]" +
@@ -76,9 +80,11 @@
 			"\n , jsonStr=[" + jsonStr + "]" +
 			"\n , ==== MJ_MSG_DATA INSERT DATA END =======" +
 			"\n " +
+			"\n , eachPrice=[" + eachPrice + "]" +
 			"\n , smsPrice=[" + smsPrice + "]" +
 			"\n , mmsPrice=[" + mmsPrice + "]" +
 			"\n , kakaoAtPrice=[" + kakaoAtPrice + "]" +
+			"\n , bizJsonName=[" + bizJsonName + "]" +
 			"\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,5 +1,6 @@
 package itn.let.kakao.kakaoComm;
 
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -11,11 +12,13 @@
 
 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;
@@ -38,7 +41,7 @@
 	
 	@Resource(name = "MjonMsgDataService")
 	private MjonMsgDataService mjonMsgDataService;
-
+	
 	@Autowired
 	KakaoApiTemplate kakaoApiTemplate;
 
@@ -48,7 +51,10 @@
 	@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";
@@ -67,43 +73,41 @@
 	 * @throws Exception
 	 * 
 	 */
-	public List<KakaoSendAdvcVO> populateSendLists(KakaoVO kakaoVO, StatusResponse statusResponse) throws Exception {
+	public List<KakaoSendAdvcVO> populateSendLists(KakaoVO kakaoVO, boolean isHolidayNotified, 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, isHolidayNotified);
+
 		
-
-		// 예약 시간 기본값 설정
-		Date now = new Date();
-		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
-		// ReqDate가 비어 있으면 현재 시간으로 설정, 그렇지 않으면 ReqDate로 설정
-		// 화면에서 예약문자면 예약시간을 regDate로 설정한다.
-		Date baseDate;
-		if (StringUtils.isEmpty(kakaoVO.getReqDate())) {
-			kakaoVO.setReqDate(sdf.format(now));  // ReqDate에 현재 시간 설정
-		    baseDate = now;
-		} else {
-		    baseDate = sdf.parse(kakaoVO.getReqDate()); // ReqDate를 baseDate로 설정
-		}
-
-		Calendar calendar = Calendar.getInstance();
-		calendar.setTime(baseDate);  // calendar에 baseDate 설정
-
 		
 		KakaoReturnVO templateDetail = kakaoApiTemplate.selectKakaoApiTemplateDetail(kakaoVO);
-		log.info(" + templateDetail :: [{}]", templateDetail.toString());
 		String templateContent = templateDetail.getTemplateContent(); // 알림톡 템플릿
+		kakaoVO.setTemplateContent(templateContent);
 		String templateTitle = templateDetail.getTemplateTitle();
-		log.info(" + templateTitle :: [{}]",templateTitle);
 		
-		kakaoVO.setTxtReplYn(replYnChecker(templateContent+" "+templateTitle));
+		
+//		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(); // 실패 대체 문자
 		
@@ -113,19 +117,31 @@
 		MberManageVO mberManageVO = mjonMsgDataService.selectMberManageInfo(kakaoVO.getUserId());
 		
 		
-		int counter = 0;  // 분할 건수 카운터
-		// Map에 총 갯수가 수신자 갯수와 동일함
-		for(Map<String, String> variables : kakaoVO.getVarListMap()) {
+		
+
+		/** @MSGID KEY값 */
+		log.info("idList ===================================================== ");
+		List<String> idList = mjonCommon.getNextCustomMsgCId(kakaoVO.getVarListMap().size());
+		log.info("+ idList:: [{}]", idList.toArray().toString());
+//		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 = new KakaoSendAdvcVO();
-			
-// 공통 기본값
-			sendVO.setMsgType("8");
-			sendVO.setSenderKey(kakaoVO.getSenderKey());
-			sendVO.setTemplateCode(kakaoVO.getTemplateCode());
-			sendVO.setUserId(kakaoVO.getUserId()); // 수신자
-			sendVO.setCallFrom(kakaoVO.getCallFrom()); // 발신자
-			sendVO.setAgentCode("04"); // 발신자
+/** @공통 기본값 */		
+			KakaoSendAdvcVO sendVO = createSendVO(kakaoVO);
+
 
 			// step1
 			// Step 1-1: 값 치환 및 수신번호 셋팅
@@ -135,14 +151,20 @@
 				variables.remove("callToList"); // 사용 후 제거.
 			}
 
-			// Step 1-3: 템플릿 치환데이터 설정
-			// TxtReplYn이 "Y"일 때만 치환 수행
-			if ("Y".equals(kakaoVO.getTxtReplYn())) {
+/** @Step1-3: 템플릿 치환데이터 설정 */		
+			if (hasContentReplacement) {
 				templateContent = mjonCommon.ATReplaceTemplateVariables(templateContent, variables);
-				if("TEXT".equals(templateDetail.getTemplateEmphasizeType())) {
+				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);
 
@@ -154,6 +176,8 @@
 				}
 				sendVO.setSubMsgTxt(subMsgTxt);// 실패 
 			}
+			
+			
 			/*
 						log.info("kakaoSendAdvcVO Details: [callTo={}\n, templateContent=\n{}\n, subMsgTxt=\n{}]\n\n\n\n",
 								kakaoSendAdvcVO.getCallTo(),
@@ -174,9 +198,13 @@
 			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(shortPrice);
-			sendVO.setMmsPrice(longPrice);
+			sendVO.setSmsPrice(shortPStr);
+			sendVO.setMmsPrice(mmsPStr);
 			
 			
 			if("Y".equals(kakaoVO.getSubMsgSendYn())) {
@@ -189,44 +217,48 @@
 				}
 	
 				boolean isMms = "MMS".equals(sendType);
-//				kakaoAtPrice = isMms ? longPrice : shortPrice;
-//				sendVO.setKakaoAtPrice(getValidPrice(mberManageVO.getKakaoAtPrice(), sysJoinSetVO.getKakaoAtPrice()));
-				sendVO.setKakaoAtPrice(isMms ? longPrice : shortPrice);
+				sendVO.setEachPrice(isMms ? mmsPStr : shortPStr);
 				
 				
 			} else {
 				kakaoAtPrice = getValidPrice(mberManageVO.getKakaoAtPrice(), sysJoinSetVO.getKakaoAtPrice());
-				sendVO.setKakaoAtPrice(kakaoAtPrice);
+				sendVO.setEachPrice( Float.toString(kakaoAtPrice) );
 			}
 			
 			
 			
 			// step4
 			// 예약 시간 설정 및 분할 데이터 설정
-			if ("Y".equalsIgnoreCase(kakaoVO.getReserveYn())) {
-				// 분할 발송일 경우
-				if ("Y".equalsIgnoreCase(kakaoVO.getDivideChk())) {
-					if (counter == Integer.parseInt(kakaoVO.getDivideCnt()))  { // 지정된 건수마다 간격 추가
-						counter = 0;
-						calendar.add(Calendar.MINUTE, Integer.parseInt(kakaoVO.getDivideTime()));
-					}
-					counter++;
-				}
-				// 예약 시간 설정
+			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(sdf.format(calendar.getTime())); 
+			sendVO.setReqDate(DATE_FORMATTER.format(calendar.getTime())); 
 			
 			
-			// step5
-			// 전송 메세지 설정 json파일 만들기
-			if("Y".equals(kakaoVO.getBizJsonYn())) {
-				String jsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail);
-				sendVO.setJsonStr(jsonStr);
+/** @step5 전송 메세지 설정 json파일 만들기*/
+			// 타이틀과 버튼이 있고
+			String msgId = idList.get(i);
+			sendVO.setMsgId(msgId);
+			if(hasTitleOrButtons) {
+				// 버튼과 타이틀에 치환데이터가 있으면 json String을 계속 생성
+				if(needsJsonReplacement) {
+					sharedJsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail);
+					sendVO.setBizJsonName(msgId);
+				} else if (StringUtils.isEmpty(sharedJsonStr)) {
+					// 치환 데이터가 없고 아직 생성되지 않았으면 한 번만 생성
+					sharedJsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail);
+					sendVO.setBizJsonName(idList.get(0));
+				}
+				sendVO.setJsonStr(sharedJsonStr);
+				
 			}
-//			log.info(" + sendVO :: [{}]", sendVO.toString());
-			
 			kakaoSendAdvcListVO.add(sendVO);
 		}
 		
@@ -234,15 +266,108 @@
 		return kakaoSendAdvcListVO;
 	}
 	
-	
-	private String replYnChecker(String input) {
-		// #{...} 패턴을 확인하는 정규 표현식
-		String regex = "#\\{[^}]+\\}";
-		Pattern pattern = Pattern.compile(regex);
-		Matcher matcher = pattern.matcher(input);
+	private Calendar setupBaseDate(KakaoVO kakaoVO, boolean isHolidayNotified) 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로 설정
+		}
 		
-		// 패턴이 존재하면 "Y", 없으면 "N" 반환
-		return matcher.find() ? "Y" : "N";
+		// 시간 성정
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(baseDate);  // calendar에 baseDate 설정
+		
+		// 지연 여부 처리
+		// 알림톡 스미싱의심 + 공휴일알림 조건이 맞으면 30분 delay
+		if ( "Y".equalsIgnoreCase(kakaoVO.getAtSmishingYn())
+				&& isHolidayNotified) {
+			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();
 	}
 
 
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
@@ -38,7 +38,7 @@
 		
 		// 버튼리스트 JSON 생성
 		JSONArray buttonList = new JSONArray();
-		for(KakaoButtonVO buttonInfoVO : templateDetail.getButtonList()) {
+		for(KakaoButtonVO buttonInfoVO : sendVO.getButtonList()) {
 			JSONObject buttonInfo = new JSONObject();
 			
 			buttonInfo.put("name", buttonInfoVO.getName());
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,22 @@
 	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);
+	}
 }
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
@@ -11,10 +11,14 @@
 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;
@@ -23,6 +27,7 @@
 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;
@@ -44,6 +49,7 @@
 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
@@ -67,6 +73,9 @@
 	
 	@Resource(name = "egovMjonMsgIdGnrService")
 	private EgovIdGnrService idgenMsgId;
+
+	@Resource(name = "egovMjonMsgGroupIdGnrService")
+	private EgovIdGnrService idgenMjonMsgGroupId;
 	
 	@Resource(name = "mjonPayService")
 	private MjonPayService mjonPayService;
@@ -77,7 +86,7 @@
 	/** userManageService */
 	@Resource(name = "userManageService")
 	private EgovUserManageService userManageService;
-
+	
 	@Autowired
 	KakaoSendUtil kakaoSendUtil;
 
@@ -855,6 +864,9 @@
 
 		log.info(" :: [{}]", kakaoVO.toString());
 
+		
+		// 측정할 메소드 호출 전 시간 기록
+		Instant start = Instant.now();
 //		KakaoSendAdvcVO
 		
 		Map<String, Object> returnMap = new HashMap<>();
@@ -884,59 +896,85 @@
 
 		StatusResponse statusResponse = new StatusResponse();
 
+/** @isHolidayNotified 
+ * @false : 알림 X
+ * @true  : 알림 O */
+		boolean isHolidayNotified = mjonCommon.handleSmishingAlert();
+
+/** @LETTNGNRLMBER 사용자 정보 -> 스미싱의심 여부 */
+		UserManageVO userManageVO = mjonCommon.getUserManageInfo(userId);
+		kakaoVO.setAtSmishingYn(userManageVO.getAtSmishingYn());
 		
-/** 카카오톡 전송 설정 -------------------------------------------*/
-		List<KakaoSendAdvcVO> kakaoSendAdvcListVO = kakaoSendUtil.populateSendLists(kakaoVO, statusResponse);
+/** @카카오톡 전송 list 셋팅 -------------------------------------------*/
+		List<KakaoSendAdvcVO> kakaoSendAdvcListVO = kakaoSendUtil.populateSendLists(kakaoVO, isHolidayNotified, statusResponse);
 		if (statusResponse.getStatus() != null && !statusResponse.getStatus().equals(HttpStatus.OK)) {
 			log.error(" + populateSendLists 처리 중 오류 발생: {}", statusResponse.getMessage());
 			return statusResponse;
 		}
 
-		// 측정할 메소드 호출 전 시간 기록
-		Instant start = Instant.now();
-/** 전송금액 확인 --------------------------------------------------*/
+		
+		
+/** @전송금액 확인 --------------------------------------------------*/
 		if (!isCashSufficient(userId, kakaoSendAdvcListVO)) {
 			log.error("Insufficient balance for message sending.");
 			return new StatusResponse(HttpStatus.BAD_REQUEST, "문자 발송에 필요한 보유 잔액이 부족 합니다.");
 		}
 
-		// 측정할 메소드 호출 후 시간 기록
-		Instant end = Instant.now();
-		
-		log.info(" + start :: [{}]", start);
-		// 실행 시간 계산 (나노초, 밀리초, 초)
-		System.out.println("메소드 실행 시간 (초): " + Duration.between(start, end).getSeconds() + " s");
-		System.out.println("메소드 실행 시간 (Nano): " + Duration.between(start, end).getNano() + " Nano");
-		
-		
-		
 		
 		
 		start = Instant.now();
-		List<String> idList = mjonCommon.getNextCustomMsgCId(kakaoSendAdvcListVO.size());
-		for (int i = 0; i < kakaoSendAdvcListVO.size(); i++) {
-			kakaoSendAdvcListVO.get(i).setMsgId(idList.get(i));
+		Map<String, List<KakaoSendAdvcVO>> priceGroupedMessages = kakaoSendAdvcListVO.stream()
+				.collect(Collectors.groupingBy(KakaoSendAdvcVO::getEachPrice));
+		
+		// json Str이 있는지 확인
+		Boolean isJsonNotEmpty = StringUtils.isNotEmpty(kakaoSendAdvcListVO.get(0).getJsonStr());
+		// json Str 값이 list에서 다른지 확인
+		Boolean isJsonNameAllSame = false;
+		if(isJsonNotEmpty) {
+			String firstBizJsonName = kakaoSendAdvcListVO.get(0).getBizJsonName();
+			isJsonNameAllSame = kakaoSendAdvcListVO.stream()
+				.allMatch(t -> Objects.equals(t.getBizJsonName(), firstBizJsonName));
 		}
 		
+
+		// instTotalCnt : 화면에서 보여줄 총 발송건수
+		int instTotalCnt = 0;
+		List<Map.Entry<String, List<KakaoSendAdvcVO>>> entryList = new ArrayList<>(priceGroupedMessages.entrySet());
+		// 기본 for문으로 반복 카운트를 사용하기 위해 foreach -> for 수정
+		for (int i = 0; i < entryList.size(); i++) {
+			Map.Entry<String, List<KakaoSendAdvcVO>> entry = entryList.get(i);
+
+			List<KakaoSendAdvcVO> groupedMsgList = entry.getValue(); // 해당 가격의 메시지 리스트
+
+			String nextMsgGroupId = idgenMjonMsgGroupId.getNextStringId();
+			groupedMsgList.forEach(t -> t.setMsgGroupId(nextMsgGroupId));
+			
+
+			// 발송 데이터 삽입
+//			int instCnt = this.insertKakaoData_advc(groupedMsgList, i, isJsonNotEmpty, isJsonNameAllSame);
+			int instCnt = 6;
+			
+			if(instCnt > 0) {
+
+				instTotalCnt += instCnt;
+//				this.insertMsgGroupDataTb_advc(instCnt, mjonMsgVO, groupedMsgList);
+				this.insertKakaoGroupDataTb_advc(instCnt, kakaoVO, groupedMsgList);
+			}
+			
+			
+		}
+		
+		
 		// 측정할 메소드 호출 후 시간 기록
-		end = Instant.now();
+		Instant end = Instant.now();
 
 		log.info(" + start :: [{}]", start);
 		// 실행 시간 계산 (나노초, 밀리초, 초)
 		System.out.println("메소드 실행 시간 (초): " + Duration.between(start, end).getSeconds() + " s");
 		System.out.println("메소드 실행 시간 (Nano): " + Duration.between(start, end).getNano() + " Nano");
-		kakaoSendAdvcListVO.forEach(t-> log.info(" + t.toString() :: [{}]", t.toString()) );
+		kakaoSendAdvcListVO.forEach(t-> log.info(" + t.toString() :: [{}]", t.toString()) );		
 		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
+//		idgenMjonMsgGroupId.getNextStringId();
 		
 		
 		
@@ -956,6 +994,133 @@
 	
 	
 
+
+	private void insertKakaoGroupDataTb_advc(int instCnt, KakaoVO kakaoVO, List<KakaoSendAdvcVO> kakaoSendAdvcVOList) {
+		// TODO Auto-generated method stub
+
+		log.info(" + insertKakaoGroupDataTb_advc kakaoVO :: \n[{}]", kakaoVO.toString());;
+		log.info(" + insertKakaoGroupDataTb_advc kakaoSendAdvcVOList :: \n[{}]", kakaoSendAdvcVOList.get(0).toString());
+		
+		
+		/*
+		#msgGroupId#,
+		#userId#,
+		#callFrom#,
+		#smsTxt#,	mjonMsgVO.setSmsTxt(kakaoVO.getTemplateContent());
+		// #mmsSubject#,
+		
+		#reqDate#,
+		#msgGroupCnt#,
+		// #conectMthd#,
+		#msgType#,
+		// #msgKind#,
+		
+		#agentCode#,
+		#eachPrice#,
+		#reserveYn#,
+		#befCash#,
+		#befPoint#,
+		
+		// #recommId#,
+		// #fileCnt#,
+		#totPrice#,
+		// #eventYn#,
+		// #delayYn#,
+
+		#atDelayYn#,
+		#kakaoSubMagOrgnlTxt#
+		*/
+	}
+
+	/**
+	 * @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, int parentLoopCount, Boolean isJsonNotEmpty, Boolean isJsonNameAllSame) {
+
+
+		// 시작 시간 측정
+		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<>();
+
+	
+		// 첫 번째 배치에서만 삽입했는지 추적하는 플래그
+		boolean isJsonInserted = false;
+		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);
+			if (isJsonNotEmpty) {
+				if (!isJsonNameAllSame) {
+					// BizJsonName이 동일하지 않으면 매번 삽입
+					kakaoAlimTalkDAO.insertKakaoAtDataJsonInfo_advc(batchList);
+				} else if (parentLoopCount==0) {
+					// BizJsonName이 동일하면 첫 번째 배치에서만 삽입
+					kakaoAlimTalkDAO.insertKakaoAtDataJsonInfo_advc(batchList);
+					isJsonInserted = true; // 삽입 완료 플래그 설정
+				}
+			}
+			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 {
 		
@@ -969,7 +1134,7 @@
 
 		// 총 메시지 금액 계산 (HALF_EVEN 적용)
 		BigDecimal totalEachPrice = kakaoSendAdvcListVO.stream()
-			.map(msg -> new BigDecimal(String.valueOf(msg.getKakaoAtPrice()))) // 변환 오류 방지
+			.map(msg -> new BigDecimal(String.valueOf(msg.getEachPrice()))) // 변환 오류 방지
 			.reduce(BigDecimal.ZERO, BigDecimal::add)
 			.setScale(2, RoundingMode.HALF_EVEN); // 일관성 유지
 
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
@@ -563,7 +563,7 @@
 			mjonMsgVO.setSmishingYn(smishingYn); // MjonMsgVO에 스미싱 정보 설정
 
 			// 스미싱 알림 처리
-			return handleSmishingAlert(mjonMsgVO); // 알림 처리 결과 반환
+			return handleSmishingAlert(); // 알림 처리 결과 반환
 		}
 
 		return false; // 알림 처리되지 않음
@@ -579,18 +579,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; // 알림 발송 조건 미충족
 	}
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/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
@@ -4138,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 생성
@@ -4173,7 +4172,7 @@
 			// 수신거부 목록 업데이트
 //			returnMap.put("resultSts", instCnt);
 
-			log.debug("가격 [{}]의 총 갯수: [{}]", price, groupedMsgList.size());
+			log.debug("가격 [{}]의 총 갯수: [{}]", entry.getKey(), groupedMsgList.size());
 
 		}
 
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,71 @@
 		</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.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
Add a comment
List