diff --git a/src/main/webapp/js/kakao/ft/ftPriceClclt.js b/src/main/webapp/js/kakao/ft/ftPriceClclt.js
new file mode 100644
index 00000000..aad451e5
--- /dev/null
+++ b/src/main/webapp/js/kakao/ft/ftPriceClclt.js
@@ -0,0 +1,315 @@
+/**
+ *
+ * @author : 우영두
+ * @fileName : ftPriceClclt.js
+ * @date : 2024.01.12
+ * @description : 친구톡 및 대체문자 금액 연산.js
+ * ===========================================================
+ * DATE AUTHOR NOTE
+ * ----------------------------------------------------------- *
+ * 2024.01.12 우영두 최초 생성
+ *
+ *
+ *
+ */
+
+
+/**
+ *
+ * @param {*} totRows 수신자 수
+ * @description 금액 계산 function
+ * 대체 문자 X
+ * 카카오 금액 * 수신자 수 계산
+ */
+function totalFtPriceSum(totRows){
+
+ var collNumCnt = parseInt(totRows); //받는사람 건수
+ var price = $("#kakaoFtPrice").val(); //개별 건수 금액
+ var totalPrice = 0; //전체 금액
+ var totalStr = "0"; //전체 합계 금액
+ var userMoney = $('#hdUserMoney').text(); //헤더 영역 보유 금액 불러오기
+
+ if(!userMoney > 0){
+
+ userMoney = 0;
+
+ }
+ //헤더 영역 보유 금액 콤마 문자 제거
+ if(userMoney != ''){
+
+ userMoney = userMoney.replaceAll("," , "");
+
+ }
+
+ totalPrice = price * collNumCnt;
+
+ // 소수점 첫째자리 까지 표시
+ totalPrice = totalPrice.toFixed(1);
+
+ if(totalPrice > 0){
+
+ //totalStr = totalPrice.toFixed(2);
+ totalStr = totalPrice;
+
+ }
+
+ //개별 문자 단가 파라미터에 입력
+ $('#eachPrice').val(numberWithCommas(price));
+
+ //결제금액 합계 파라이터에 입력
+ $('#totPrice').val(numberWithCommas(totalStr));
+
+ //결제금액 합계 화면에 표시
+ $('#totalPriceTxt').text(numberWithCommas(totalStr));
+
+ $('#repPriceTxt').hide();
+
+ return totalStr;
+
+}
+
+
+
+/*
+ * ======================================================================================================================
+ *
+ * */
+
+//카카오 mms sms 단가 셋팅
+var KAKAO_FT_PRICE = '';
+var SHORT_PRICE = '';
+var LONG_PRICE = '';
+
+/*$(document).ready(function(){
+
+ // 카카오 mms sms 단가 셋팅
+ KAKAO_FT_PRICE = $('#kakaoFtPrice').val();
+ SHORT_PRICE = $('#shortPrice').val();
+ LONG_PRICE = $('#longPrice').val();
+
+ ///////////////////////////////////////// Mutation Observer
+ // 감시 대상 node 선택
+ // 변수X 수신자 목록
+ let target01 = document.getElementById('wrap01_body');
+ // 변수O 수신자 목록
+ let target02 = document.getElementById('wrap02');
+ // 대체 문자 단문 장문 텍스트 노드
+ let target03 = document.getElementById('afterDeny');
+
+ // 감시자의 설정
+ let option = {
+ subtree : true // 대상 노드의 자식 요소뿐만 아니라 후손 요소의 변화까지 감지
+ , childList : true // 대상 노드의 자식 요소(텍스트 포함)의 변화 감지
+ , attributes : true // 해당 노드의 attribute 속성
+
+ // , characterData: true // 대상 노드의 데이터 변화 감지
+ };
+
+
+ // wrap01 감시자 인스턴스 만들기
+ let observer_wrap01 = new MutationObserver((mutations) => {
+ // 노드가 변경 됐을 때의 작업
+ fn_priceClclt();
+ });
+
+ // wrap02 감시자 인스턴스 만들기
+ let observer_wrap02 = new MutationObserver((mutations) => {
+ // 노드가 변경 됐을 때의 작업
+ fn_priceClclt();
+ });
+
+ // wrap03 감시자 인스턴스 만들기
+ let observer_wrap03 = new MutationObserver((mutations) => {
+ // 노드가 변경 됐을 때의 작업
+ fn_priceClclt();
+ });
+
+
+
+
+ // 대상 노드에 감시자 전달
+ observer_wrap01.observe(target01, option);
+ observer_wrap02.observe(target02, option);
+ observer_wrap03.observe(target03, option);
+
+ ///////////////////////////////////////// //Mutation Observer
+
+});*/
+
+/**
+ * @description 금액 계산 function
+ */
+function fn_priceClclt(){
+
+ // 미리보기 텍스트
+ var templateHtml = $('#smsTxtArea').val();
+ // var templateHtml = $('.template_text').html();
+
+ // 수신 번호 개수
+ var phoneSu = $('.phoneArea').length;
+ // 대체문자 있는지 확인
+ var isSendFailChecked = $("#send_fail_check").is(":checked");
+ // 치환문자 여부 확인
+ var txtReplYn = $('#txtReplYn').val()
+ // 대체문자 하위에 장문 / 단문 select
+ var msgTypeText = $('.msg_com').text().trim();
+
+ if(typeof templateHtml == 'undefined') return false;
+ else if(isSendFailChecked && txtReplYn=='Y') fn_sendFailCheckedAndTxtRepl_Y(templateHtml, msgTypeText, phoneSu); // 대체문자 체크 & 치환문자 Y
+ else if(isSendFailChecked && txtReplYn=='N') fn_sendFailCheckedAndTxtRepl_N(msgTypeText, phoneSu); // 대체문자 체크 & 치환문자 N
+ else fn_sendFailUnChecked(phoneSu);
+
+}
+
+/**
+ *
+ * @param {*} phoneSu 수신자 수
+ * @description 금액 계산 function
+ * 대체 문자 X
+ * 카카오 금액 * 수신자 수 계산
+ */
+function fn_sendFailUnChecked(phoneSu){
+
+ // 카카오 금액 * 수신자 수
+ // fn_writePriceText() 첫 파라미터가 null이면 카카오 전송으로 인식
+ fn_writePriceText('', phoneSu);
+ // $('#totalPriceTxt').text((KAKAO_AT_PRICE * phoneSu).toFixed(1));
+ fn_priceText('알림톡', phoneSu);
+}
+
+/**
+ *
+ * @param {*} templateHtml 템플릿html
+ * @param {*} msgTypeText 발송 타입
+ * @param {*} phoneSu 수신자 수
+ * @description 금액 계산 function
+ * 대체 문자 O
+ * 치환 문자 O
+ */
+function fn_sendFailCheckedAndTxtRepl_Y(templateHtml, msgTypeText, phoneSu){
+
+ // 대체문자 하위에 html 그대로의 byte 계산이 단문일 경우에만 치환 후 장문이 있는지 확인
+ if(msgTypeText == '단문'){
+ msgTypeText = fn_transHtml(msgTypeText, templateHtml);
+ }
+
+ fn_writePriceText(msgTypeText, phoneSu);
+ fn_priceText(msgTypeText, phoneSu);
+
+
+
+}
+
+/**
+ *
+ * @param {*} msgTypeText 발송 타입
+ * @param {*} phoneSu 수신자 수
+ * @description 금액 계산 function
+ * 대체 문자 O
+ * 치환 문자 X
+ */
+function fn_sendFailCheckedAndTxtRepl_N(msgTypeText, phoneSu){
+
+ fn_priceText(msgTypeText, phoneSu);
+ fn_writePriceText(msgTypeText, phoneSu);
+}
+
+
+/**
+ *
+ * @param {*} msgTypeText 발송 타입
+ * @param {*} phoneSu 수신자 수
+ * @returns
+ * @description 발송 금액 계산 / 노출
+ */
+function fn_priceText(msgTypeText, phoneSu){
+
+ // $("#repPriceTxt").is(":visible") => 발송 금액 show hide 여부
+ if(phoneSu === 0){
+
+ $('#repPriceTxt').empty();
+ $('#repPriceTxt').hide();
+ return false;
+ }
+ // 텍스트 초기화
+ $('#repPriceTxt').show();
+ $('#repPriceTxt').empty();
+
+ var priceText = '$SENDTYPE$ :$SU$건';
+ priceText = priceText.replace('$SENDTYPE$', msgTypeText).replace('$SU$', phoneSu);
+
+ $('#repPriceTxt').append(priceText);
+}
+
+/**
+ * @description 발송금액 라인 text / 금액 초기화
+ */
+function priceInit(){
+ if($("#repPriceTxt").is(":visible")){
+ $('#repPriceTxt').empty();
+ $('#repPriceTxt').hide();
+ }
+ $('#totalPriceTxt').text(0.0);
+
+}
+
+/**
+ *
+ * @param {*} msgTypeText 발송 타입
+ * @param {*} phoneSu 수신자 수
+ * @description 발송 금액 '발송타입:00건' 노출
+ */
+function fn_writePriceText(msgTypeText, phoneSu){
+
+ var price;
+ msgTypeText = msgTypeText.trim();
+ if(msgTypeText == '단문') price = SHORT_PRICE * phoneSu;
+ else if(msgTypeText == '장문') price = LONG_PRICE * phoneSu;
+ else price = KAKAO_AT_PRICE * phoneSu; // 카카오
+
+ $('#totalPriceTxt').text((price).toFixed(1));
+}
+
+
+/**
+ *
+ * @param {*} msgTypeText 발송 타입 : 단문
+ * @param {*} templateHtml 템플릿 html
+ * @returns msgTypeText : 단문 or 장문
+ * @description 치환 데이터 있는 경우 단문일 경우만 호출
+ * 치환 후 장문 데이터일경우 'returns 장문'으로 끝남
+ */
+function fn_transHtml(msgTypeText, templateHtml){
+
+ // 템플릿
+ templateHtml = templateHtml.trim().replace(/(
|
|
)/g, '\n');
+ // 치환 부분 '#{내용}'만 추출
+ var varList = $("#excelTemplateContent").val().match(/#\{([^}]+)\}/g);
+ // 템플릿을 반복할때마다 담는 temp 선언
+ var tempTemplateHtml;
+ // 치환 데이터 담는 변수 선언
+ var replaceStr;
+
+ // excelBody 부분 반복 시작
+ $('.excelBody').each(function(i, t){
+ tempTemplateHtml = templateHtml;
+
+ $(this).find('.transData').each(function(index, item){
+ // console.log('item text :: ', $(item).text().trim());
+ replaceStr = $(item).text().trim();
+ tempTemplateHtml = tempTemplateHtml.replace(varList[index], replaceStr);
+ });
+ // 치환 후 byte 계산
+ // 장문이면 break;
+ if(90 < conByteLeng(tempTemplateHtml))
+ {
+ msgTypeText = '장문';
+ return false;
+ }
+ });
+
+
+ return msgTypeText;
+}
+
+
\ No newline at end of file