Selaa lähdekoodia

Callcenter 레이아웃 추가 및 FAQ 기능 추가

gagamel 5 vuotta sitten
vanhempi
commit
135e67dd90

+ 26 - 0
src/main/java/com/style24/front/biz/dao/TsfRendererDao.java

@@ -0,0 +1,26 @@
+package com.style24.front.biz.dao;
+
+import java.util.Collection;
+
+import com.style24.core.support.annotation.ShopDs;
+import com.style24.persistence.domain.CommonCode;
+
+/**
+ * 콤보박스, 체크박스, 라디오버튼 구성 시 필요한 Renderer Dao
+ *
+ * @author gagamel
+ * @since 2021. 1. 29
+ */
+@ShopDs
+public interface TsfRendererDao {
+
+	/**
+	 * 공통코드 목록
+	 * @param commoncode - 공통코드 정보
+	 * @return 공통코드 목록
+	 * @author gagamel
+	 * @since 2021. 1. 29
+	 */
+	Collection<CommonCode> getCommonCodeList(CommonCode commoncode);
+
+}

+ 111 - 0
src/main/java/com/style24/front/biz/service/TsfRendererService.java

@@ -0,0 +1,111 @@
+package com.style24.front.biz.service;
+
+import java.util.Collection;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.style24.front.biz.dao.TsfRendererDao;
+import com.style24.persistence.domain.CommonCode;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 콤보박스, 체크박스, 라디오버튼 구성 시 필요한 Renderer Service
+ *
+ * @author gagamel
+ * @since 2020. 10. 7
+ */
+@Service
+@Slf4j
+public class TsfRendererService {
+
+	@Autowired
+	private TsfRendererDao rendererDao;
+
+	/**
+	 * 공통코드 목록 - 어드민 공통코드 캐시 미적용 - 상품등록시 시즌년도 캐쉬로 인한 정보 오류로 수정 2020.06.02
+	 * @param commoncode - 공통코드 정보
+	 * @return
+	 * @author gagamel
+	 * @since 2021. 1. 29
+	 */
+//	@Cacheable(value = "common", key = "'commoncode-'.concat(#commoncode.cdGb)")
+	public Collection<CommonCode> getCommonCodeList(CommonCode commoncode) {
+		return rendererDao.getCommonCodeList(commoncode);
+	}
+
+	/**
+	 * 공통코드 목록
+	 * @param cdGb - 코드구분
+	 * @return
+	 * @author gagamel
+	 * @since 2021. 1. 29
+	 */
+	public Collection<CommonCode> getCommonCodeList(String cdGb) {
+		CommonCode commoncode = new CommonCode();
+		commoncode.setCdGb(cdGb);
+		return this.getCommonCodeList(commoncode);
+	}
+
+	/**
+	 * 공통코드 목록
+	 * @param grpCodeId - 코드구분
+	 * @param useYn     - 사용여부
+	 * @return
+	 * @author gagamel
+	 * @since 2021. 1. 29
+	 */
+	public Collection<CommonCode> getCommonCodeList(String cdGb, String useYn) {
+		CommonCode commoncode = new CommonCode();
+		commoncode.setCdGb(cdGb);
+		commoncode.setUseYn(useYn);
+		return this.getCommonCodeList(commoncode);
+	}
+
+	/**
+	 * 현재 유효한 공통코드 목록
+	 * @param cdGb - 코드구분
+	 * @return
+	 * @author gagamel
+	 * @since 2021. 1. 29
+	 */
+	public Collection<CommonCode> getAvailCommonCodeList(String cdGb) {
+		return this.getCommonCodeList(cdGb, "Y");
+	}
+
+	/**
+	 * 공통코드 목록
+	 * @param cdGb   -코드구분
+	 * @param useYn  - 사용여부
+	 * @param cdDesc - 코드설명
+	 * @return
+	 * @author gagamel
+	 * @since 2021. 1. 29
+	 */
+	public Collection<CommonCode> getCommonCodeList(String cdGb, String useYn, String cdDesc) {
+		CommonCode commoncode = new CommonCode();
+		commoncode.setCdGb(cdGb);
+		commoncode.setUseYn(useYn);
+		commoncode.setCdDesc(cdDesc);
+		return this.getCommonCodeList(commoncode);
+	}
+
+	/**
+	 * 공통코드 목록
+	 * @param cdGb      -코드구분
+	 * @param useYn     - 사용여부
+	 * @param exceptCds - 제외코드배열
+	 * @return
+	 * @author gagamel
+	 * @since 2021. 1. 29
+	 */
+	public Collection<CommonCode> getCommonCodeList(String cdGb, String useYn, String[] exceptCds) {
+		CommonCode commoncode = new CommonCode();
+		commoncode.setCdGb(cdGb);
+		commoncode.setUseYn(useYn);
+		commoncode.setExceptCds(exceptCds);
+		return this.getCommonCodeList(commoncode);
+	}
+
+}

+ 7 - 0
src/main/java/com/style24/front/biz/web/TsfCallcenterController.java

@@ -15,6 +15,7 @@ import com.style24.core.support.message.TscMessageByLocale;
 import com.style24.front.biz.service.TsfCounselService;
 import com.style24.front.biz.service.TsfFaqService;
 import com.style24.front.biz.service.TsfNoticeService;
+import com.style24.front.biz.service.TsfRendererService;
 import com.style24.front.support.controller.TsfBaseController;
 import com.style24.front.support.security.session.TsfSession;
 import com.style24.persistence.TsfPageRequest;
@@ -50,6 +51,9 @@ public class TsfCallcenterController extends TsfBaseController {
 	@Autowired
 	private TsfCounselService counselService;
 
+	@Autowired
+	private TsfRendererService rendererService;
+
 	/**
 	 * FAQ
 	 * @return
@@ -63,6 +67,9 @@ public class TsfCallcenterController extends TsfBaseController {
 		// FAQ TOP 10 목록
 		mav.addObject("faqTop10List", faqService.getFaqLikesList(TscConstants.Site.STYLE24.value()));
 
+		// FAQ유형
+		mav.addObject("faqTypeList", rendererService.getAvailCommonCodeList("G046"));
+
 		mav.setViewName(super.getDeviceViewName("callcenter/FaqForm"));
 
 		return mav;

+ 28 - 0
src/main/java/com/style24/persistence/domain/CommonCode.java

@@ -0,0 +1,28 @@
+package com.style24.persistence.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 공통코드 Domain
+ * 
+ * @author gagamel
+ * @since 2021. 1. 29
+ */
+@SuppressWarnings("serial")
+@Data
+public class CommonCode extends TscBaseDomain {
+
+	private String cdGb;
+	private String cd;
+	private String cdNm;
+	private String cdDesc;
+	private int dispOrd;
+	private String useYn;
+
+	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+	private String[] exceptCds;
+
+}

+ 34 - 0
src/main/java/com/style24/persistence/mybatis/TsfRenderer.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.style24.front.biz.dao.TsfRendererDao">
+
+	<!-- 공통코드 목록 -->
+	<select id="getCommonCodeList" parameterType="CommonCode" resultType="CommonCode">
+		/* TsfRenderer.getCommonCodeList */
+		SELECT CD
+		     , CD_NM
+		FROM   TB_COMMON_CODE
+		WHERE  1 = 1
+		<if test="useYn != null and useYn != ''">
+		AND    USE_YN = #{useYn}
+		</if>
+		AND    CD_GB = #{cdGb}
+		<if test="cd != null and cd != ''">
+		AND    CD = #{cd}
+		</if>
+		<if test="cdNm != null and cdNm != ''">
+		AND    CD_NM = #{cdNm}
+		</if>
+		<if test="cdDesc != null and cdDesc != ''">
+		AND    CD_DESC = #{cdDesc}
+		</if>
+		<if test="exceptCds != null and exceptCds != ''">
+		AND    CD NOT IN
+		    <foreach collection="exceptCds" item="item" index="index"  open="(" close=")" separator=",">
+		    #{item}
+		    </foreach>
+		</if>
+		ORDER  BY CD_GB, DISP_ORD
+	</select>
+
+</mapper>

+ 185 - 0
src/main/webapp/WEB-INF/views/web/callcenter/FaqFormWeb.html

@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org"
+	xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+	layout:decorator="web/common/layout/CallcenterLayoutWeb">
+<!--
+ *******************************************************************************
+ * @source  : FaqFormWeb.html
+ * @desc    : FAQ Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2020 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.01.29   gagamel     최초 작성
+ *******************************************************************************
+ -->
+<body>
+
+<th:block layout:fragment="content">
+	<div id="container" class="container cs"> 
+		<div class="breadcrumb"> 
+			<ul>
+				<li class="bread_home"><a href="index.html">홈</a></li>
+				<li class="bread_2depth">고객센터</li>
+				<li class="bread_3depth">1:1문의</li>
+			</ul> 
+		</div>
+		<div class="wrap">
+			<div class="content faq">
+				<div class="cont_body">
+					<!-- CONT-BODY -->
+					<div class="lnb">
+						<div class="lnb_tit">
+							<h2>고객센터</h2>
+						</div>
+						<div class="lnb_list">
+							<ul>
+								<li><a href="" class="on">FAQ</a></li>
+								<li><a href="">1:1문의</a></li>
+								<li><a href="">상품문의</a></li>
+								<li><a href="">공지</a></li>
+							</ul>
+						</div>
+						<div class="lnb_foot">
+							<ul>
+								<li><p>고객센터 운영안내</p></li>
+								<li><p>1544-5336</p></li>
+								<li><p>평일 09:00~18:00<br>토,일,공휴일 휴무</p></li>
+							</ul>
+						</div>
+					</div>
+					<div class="cont">
+						<div>
+							<div class="sec_head">
+								<h3>FAQ</h3>
+							</div>
+							<div class="sec_body">
+								<div class="quick_list mb50" th:if="${faqTop10List != null and !faqTop10List.empty}">
+									<h4 class="subH3_eng mb20 c_black">자주 묻는 질문 TOP 10</h4>
+									<ul>
+										<li th:each="oneData, status : ${faqTop10List}" th:value="${oneData.cd}">
+											<a href="#quick_pop1" th:href="${'#quick_pop' + (status.index + 1)}" rel="modal:open" th:text="${oneData.question}">제품을 받았는데<br>반품을 하고 싶습니다.</a>
+										</li>
+									</ul>
+								</div>
+								<div class="search_wrap mb60">
+									<h4 class="subH3_eng mb20 c_black">FAQ SEARCH</h4>
+									<div class="faq_search t_c">
+										<form id="faqForm" name="faqForm" class="search_box" action="#" th:action="@{'/callcenter/faq/list'}">
+											<input type="hidden" name="faqType"/>
+											<input type="hidden" name="pageNo" value ="1"/>
+											<input type="hidden" name="pageSize" value ="5"/>
+											<fieldset>
+												<legend>FAQ 검색</legend>
+												<input type="text" name="searchTxt" placeholder="검색어를 입력해 주세요" class="search_input" title="검색어 입력" maxlength="100" onkeyup="if (window.event.keyCode == 13) { fnGetList(); }"/>
+												<button class="btn_search" onclick="fnGetList();">찾기</button>
+											</fieldset>
+										</form>
+										<p class="t_info">
+											찾으시는 문의 내용이 없으시면 '1:1 문의'를 이용해 주세요.
+										</p>
+									</div>
+								</div>
+								<div class="fold_nav">
+									<ul>
+										<li><a href="#none;" th:href="@{'/callcenter/faq/form'}" class="on">전체</a></li>
+										<li th:if="${faqTypeList != null and !faqTypeList.empty}" th:each="oneData, status : ${faqTypeList}">
+											<a href="#none;" th:href="@{${'/callcenter/faq/form?faqType=' + oneData.cd}}" th:text="${oneData.cdNm}">상품문의</a>
+										</li>
+									</ul>
+								</div>
+								<div class="ui_row" id="ulFaq"> <!-- 데이터 없을시 클래스 nodata 추가 -->
+									<div class="foldGroup case1 mt50">
+										<ul id="liFaq">
+										</ul>
+									</div>
+								</div>
+								<div class="ui_foot">
+									<div class="ui_row">
+										<ul class="pageNav">
+										</ul>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+					<!-- // CONT-BODY -->
+				</div>
+			</div>
+		</div>
+	</div>
+	<!-- // container -->
+
+<script src="/ux/plugins/gaga/gaga.paging.js"></script>
+<script th:inline="javascript">
+/*<![CDATA[*/
+	// 컨텐츠 호출
+	$(document).ready(function() {
+		fnGetList();
+	});
+	
+	let fnGetList = function(faqType, obj) {
+		if (!gagajf.isNull(faqType)) {
+			$li = $(obj).parent('li').parent('ul').find('li>a');
+	
+			$li.each(function(i) {
+				$(this).removeClass('on');
+			});
+	
+			$(obj).addClass('on');
+	
+			$('#faqForm input[name=faqType]').val(faqType);
+		}
+		
+		// Initialize a pagination
+		gagaPaging.init('faqForm', fnGetListCallback, 'pageNav', 10);
+
+		// Load data
+		gagaPaging.load(1);
+	}
+	
+	var fnGetListCallback = function(result) {
+		$('#liFaq').html('');
+
+		if (result.dataList != null && result.dataList.length > 0) {
+			$.each(result.dataList, function(idx, item) {
+				let tag = '<li>\n';
+				tag += '	<div class="fold_head">\n';
+				tag += '		<a href="javascript:void(0)">\n';
+				tag += '			<div>\n';
+				tag += '				<span class="fold_state">' + item.faqTypeNm + '</span>\n';
+				tag += '				<div class="fold_tit">\n';
+				tag += '					<span>' + item.question + '</span>\n';
+				tag += '				</div>\n';
+				tag += '			</div>\n';
+				tag += '		</a>\n';
+				tag += '	</div>\n';
+				tag += '	<div class="fold_cont" style="display: none;">\n';
+				tag += '		<div class="fold_answer">\n';
+				tag += '			<div>' + item.answer + '</div>\n';
+				tag += '		</div>\n';
+				tag += '	</div>\n';
+				tag += '</li>\n';
+
+				$('#liFaq').append(tag);
+			});
+			$('#ulFaq').removeClass('nodata');
+		} else {
+			let tag = '<li>내역이 없습니다.</li>\n';
+			$('#liFaq').append(tag);
+			$('#ulFaq').addClass('nodata');
+		}
+
+		// Create pagination
+		gagaPaging.createPagination(result.paging.pageable);
+	}
+/*]]>*/
+</script>
+
+</th:block>
+
+</body>
+</html>

+ 2 - 0
src/main/webapp/WEB-INF/views/web/common/fragments/HeadWeb.html

@@ -33,6 +33,8 @@
 	<script src="/ux/pc/js/jquery-ui.js"></script>
 	<script th:src="@{'/ux/pc/js/common-ui.js?v=' + ${#calendars.format(#calendars.createNow(), 'yyyyMMddHHmmss')}}" src="/ux/pc/js/common-ui.js"></script>
 	<script src="/ux/plugins/jquery.serializeObject.min.js"></script>
+	<script type="text/javascript" th:src="@{'/ux/plugins/gaga/gaga.common.js?v=' + ${#calendars.format(#calendars.createNow(), 'yyyyMMddHHmmss')}}" src="/ux/plugins/gaga/gaga.common.js"></script>
+	<script type="text/javascript" th:src="@{'/ux/plugins/gaga/gaga.validation.js?v=' + ${#calendars.format(#calendars.createNow(), 'yyyyMMddHHmmss')}}" src="/ux/plugins/gaga/gaga.validation.js"></script>
 
 	<!-- Global site tag (gtag.js) - Google Analytics -->
 <!-- 	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-168660512-1"></script> -->

+ 41 - 0
src/main/webapp/WEB-INF/views/web/common/layout/CallcenterLayoutWeb.html

@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org"
+	xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
+
+<head th:replace="~{web/common/fragments/HeadWeb :: head}"></head>
+
+<body>
+
+<div class="skipComment">
+	<a href="#content">본문 바로가기</a>
+	<a href="#gnb">주메뉴 바로가기</a>
+	<a href="#footer">하단메뉴 바로가기</a>
+</div>
+	
+<th:block th:replace="~{web/common/fragments/VariablesWeb :: variables}"></th:block>
+
+<!-- GNB -->
+<header id="header" th:replace="~{web/common/fragments/GnbWeb :: gnb}"></header>
+<!--// GNB -->
+
+<!-- CONTENT AREA -->
+<th:block layout:fragment="content"></th:block>
+<!-- // CONTENT AREA -->
+
+<!-- Footer -->
+<footer id="footer" th:replace="~{web/common/fragments/FooterWeb :: footer}"></footer>
+
+<!-- <th:block th:replace="~{web/common/fragments/ScriptsWeb :: scripts}"></th:block> -->
+<!-- <th:block th:replace="~{web/common/fragments/MarketingScripts :: mscripts}"></th:block> -->
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	$(document).ready(function() {
+		
+	});
+/*]]>*/
+</script>
+
+</body>
+</html>

+ 59 - 59
src/main/webapp/ux/pc/css/layout.css

@@ -32,7 +32,7 @@ body {min-width:1460px; overflow-x:auto;}
 .breadcrumb ul li:first-of-type a,.breadcrumb ul li:nth-of-type(2){color:#888;}
 .breadcrumb ul li:last-child {color:#222;}
 .breadcrumb ul li:first-of-type::before {content:none;}
-.breadcrumb ul li::before {content:''; display: inline-block; width:6px; height: 11px; padding: 0 12px; background: url('/pc/ux/images/ico_bread_root.png')no-repeat center center;}
+.breadcrumb ul li::before {content:''; display: inline-block; width:6px; height: 11px; padding: 0 12px; background: url('/images/ico_bread_root.png')no-repeat center center;}
 
 
 
@@ -142,7 +142,7 @@ body {min-width:1460px; overflow-x:auto;}
 .item_slide .slick-prev {left:-50px;}
 .item_slide .slick-next {right:-50px;}
 .item_slide .slick-prev::after,
-.item_slide .slick-next::after {content: ''; display:inline-block; width:27.5px; height:50px; background:url(/pc/ux/images/ico_arr_lg.png) no-repeat;}
+.item_slide .slick-next::after {content: ''; display:inline-block; width:27.5px; height:50px; background:url(/images/ico_arr_lg.png) no-repeat;}
 .item_slide .slick-prev::after {background-position:0 50%;}
 .item_slide .slick-next::after {background-position:100% 50%;}
 
@@ -189,7 +189,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.mb input[type="text"],.mb input[type="password"] {padding: 15px 0 15px 18px;}
 	.mb .btn {/*padding: 18px 34px;*/ font-size:18px; font-weight:300}
 	.mb .ui_row {margin-top:40px; margin-bottom:0}
-	.mb .cont_head div h3 {margin-bottom: 0; width:181px; height: 22px; margin: 0 auto; background: url('/pc/ux/images/logo_STYLE24_sub.png') no-repeat 50% 50%; background-size:contain; text-indent: -99999px;}
+	.mb .cont_head div h3 {margin-bottom: 0; width:181px; height: 22px; margin: 0 auto; background: url('/images/logo_STYLE24_sub.png') no-repeat 50% 50%; background-size:contain; text-indent: -99999px;}
 	.mb .form_wrap {text-align:center;}
 	.mb .form_wrap .form_field input::placeholder {color:#888; font-weight:200;}
 	.mb .form_wrap .form_field {margin-top:10px;}
@@ -208,7 +208,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.mb .registration_tap .foldGroup li:first-child a {padding: 60px 0 40px;}
 	.mb .registration_tap .foldGroup li:first-child a {padding: 60px 0 40px;}
 	.mb .registration_tap .foldGroup li .fold_head.on::after {background-repeat: no-repeat; background-position: 0 0%;}
-	.mb .registration_tap .foldGroup li .fold_head::after {background: url(/pc/ux/images/ico_mb_arrow.png)no-repeat; background-position: 0 100%;}
+	.mb .registration_tap .foldGroup li .fold_head::after {background: url(/images/ico_mb_arrow.png)no-repeat; background-position: 0 100%;}
 	.mb .registration_tap .foldGroup li:first-child .fold_head::after {top:62px;}
 
 
@@ -225,7 +225,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.find .fold_cont {display: none;}
 	.find .fold_tit,.find .fold_tit span {width: inherit !important;}
 	.find .fold_head .fold_tit {padding: 0 20px 0 34px;}
-	.find .fold_head .fold_tit::before {content:''; display: inline-block; width:20px; height: 20px; position: absolute; top:2px; left:0; background: url('/pc/ux/images/ico_chk_rdi.png')no-repeat -63px 0px;}
+	.find .fold_head .fold_tit::before {content:''; display: inline-block; width:20px; height: 20px; position: absolute; top:2px; left:0; background: url('/images/ico_chk_rdi.png')no-repeat -63px 0px;}
 	.find .foldGroup.checkcase .fold_head.on .fold_tit::before {background-position: -84px 0;}
 	.find .foldGroup.checkcase .fold_cont {padding: 40px 30px; box-sizing: border-box; background: #f5f5f5; border-top: 1px solid #ddd;}
 	.find .foldGroup.checkcase .fold_cont > div:first-child > p {font-size: 16px; color:#666; font-weight: 200;}
@@ -259,7 +259,7 @@ body {min-width:1460px; overflow-x:auto;}
 	/* mb_idInquiry_6 */
 	.dormant .ui_col_6 {margin: 0;}
 	.dormant .form_wrap .ui_row button {padding: 31px 0 31px 40px; position: relative;}
-	.dormant .form_wrap .ui_row button::before {content:''; position: absolute; width:22px; height: 30px; top:50%; left:70px; transform: translateY(-50%); background: url('/pc/ux/images/ico_join_bg.png')no-repeat;}
+	.dormant .form_wrap .ui_row button::before {content:''; position: absolute; width:22px; height: 30px; top:50%; left:70px; transform: translateY(-50%); background: url('/images/ico_join_bg.png')no-repeat;}
 	.dormant .form_wrap .ui_row div:last-child button::before { width:30px; left:64px; background-position: -30px 0;}
 	.dormant .form_wrap .ui_row button span {font-size: 18px; font-weight: 300;}
 	.dormant .form_wrap .form_summary strong {font-size: 16px; font-weight:500;}
@@ -274,13 +274,13 @@ body {min-width:1460px; overflow-x:auto;}
 	.non_mb_oder .ui_row .ui_col_12 {margin: 0;}
 	.non_mb_oder .ui_row .ui_col_12 span {font-size: 16px;}
 	.non_mb_oder .form_wrap .form_summary p {margin-bottom:10px; font-size: 18px;}
-	.non_mb_oder .form_wrap .form_summary a::after {content:''; display: inline-block; width:7px; height: 13px; margin-left: 7px; background: url('/pc/ux/images/ico_mb_arrow2.png')no-repeat;}
+	.non_mb_oder .form_wrap .form_summary a::after {content:''; display: inline-block; width:7px; height: 13px; margin-left: 7px; background: url('/images/ico_mb_arrow2.png')no-repeat;}
 	.non_mb_oder .form_wrap .form_summary .t_info {display:block; color:#888; font-size:16px}
 
 	/* mb_join_1 */
 	.join1 .form_wrap div p a {color:#222; display: inline-block; width: 100%; font-weight:500;}
 	.join1 .form_wrap .form_sign_up,.join1 .form_wrap .sns_login {position: relative; padding: 40px; border: 1px solid #ddd;}
-	.join1 .form_wrap .form_sign_up::after,.join1 .form_wrap .sns_login::after {content:''; position: absolute; width:10px; height: 18px; top:41px; right: 40px; background: url('/pc/ux/images/ico_mb_arrow3.png')no-repeat;}
+	.join1 .form_wrap .form_sign_up::after,.join1 .form_wrap .sns_login::after {content:''; position: absolute; width:10px; height: 18px; top:41px; right: 40px; background: url('/images/ico_mb_arrow3.png')no-repeat;}
 	.join1 .form_wrap .form_sign_up p,.join1 .form_wrap .sns_login p {font-size:22px; line-height: 1; text-align:left;}
 	.join1 .form_wrap .form_sign_up p:last-of-type,.join1 .form_wrap .sns_login p:last-of-type {margin-top: 15px; font-size: 16px; color:#888; font-weight: 200; }
 	.join1 .form_wrap .form_sign_up p:last-of-type {line-height: 1.5;}
@@ -290,7 +290,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.join1 .form_wrap .sns_login div:last-child ul {display: flex; display: -ms-flexbox; justify-content: center; align-items: center;}
 	.join1 .form_wrap .sns_login div:last-child ul li {margin-right: 50px; text-align: center;}
 	.join1 .form_wrap .sns_login div:last-child ul li:last-child {margin-right: 0;}
-	.join1 .form_wrap .sns_login div:last-child ul li span:first-child {display: block; width:60px; height: 60px; margin-bottom: 12px; background: url('/pc/ux/images/ico_sns_bg.png')no-repeat; text-indent: -9999px;}
+	.join1 .form_wrap .sns_login div:last-child ul li span:first-child {display: block; width:60px; height: 60px; margin-bottom: 12px; background: url('/images/ico_sns_bg.png')no-repeat; text-indent: -9999px;}
 	.join1 .form_wrap .sns_login div:last-child ul li:nth-child(2) span:first-child {background-position: -70px 0;}
 	.join1 .form_wrap .sns_login div:last-child ul li:nth-child(3) span:first-child {background-position: -140px 0;}
 	.join1 .form_wrap .sns_login div:last-child ul li span:last-child {font-size: 14px; font-weight: 300; color:#222;}
@@ -309,11 +309,11 @@ body {min-width:1460px; overflow-x:auto;}
 	.join2 .form_wrap .desc_wrap p em{font-weight:500;}
 	.join2 .form_wrap .desc_wrap p span {border-bottom: 1px solid #ddd;}
 	.join2 .help_block .btn.btn_sm {padding:6px 12px; border-color:#222; font-size:14px;}
-	.join2 .t_err::before {background: url(/pc/ux/images/ico_err2.png) no-repeat right top;}
+	.join2 .t_err::before {background: url(/images/ico_err2.png) no-repeat right top;}
 
 	/* mb_join_3 */
 	.join3 .form_wrap div {text-align: center;}
-	.join3 .form_wrap .form_head::after {content:''; display:block; width:40px; height: 46px; margin:40px auto 22px; background: url('/pc/ux/images/ico_content_find.png')no-repeat;} 
+	.join3 .form_wrap .form_head::after {content:''; display:block; width:40px; height: 46px; margin:40px auto 22px; background: url('/images/ico_content_find.png')no-repeat;} 
 	.join3 .form_wrap .print_bar {padding:34px 0; background: #f5f5f5;}
 	.join3 .form_wrap .print_bar p {font-size:18px;}
 	.join3 .btn_group_md .btn_default {border-color:#a7a7a7}
@@ -328,7 +328,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.login .help_block .captcha ul {display: flex; align-items: center;}
 	.login .help_block .captcha .captcha_box {width:235px; height: 72px; border: 1px solid #ddd; background: chartreuse;}
 	.login .help_block .captcha .captcha_btn_dual {margin: 0 18px 0 10px;}
-	.login .help_block .captcha .captcha_btn_dual button {width:33px; height: 33px; display: block; border:1px solid #ddd; border-radius: 3px; text-indent: -9999px; background: url('/pc/ux/images/ico_captcha_btn.png')no-repeat center 9px;}
+	.login .help_block .captcha .captcha_btn_dual button {width:33px; height: 33px; display: block; border:1px solid #ddd; border-radius: 3px; text-indent: -9999px; background: url('/images/ico_captcha_btn.png')no-repeat center 9px;}
 	.login .help_block .captcha .captcha_btn_dual button:first-child {margin-bottom: 8px;}
 	.login .help_block .captcha .captcha_btn_dual button:last-child {background-position:center -31px;}    
 	.login .help_block .captcha .captcha_area {margin-bottom: -7px;}
@@ -351,7 +351,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.login .form_wrap .sns_wrap div:last-child ul {display: flex; display: -ms-flexbox; justify-content: center; align-items: center;}
 	.login .form_wrap .sns_wrap div:last-child ul li {margin-right: 50px;}
 	.login .form_wrap .sns_wrap div:last-child ul li:last-child {margin-right: 0;}
-	.login .form_wrap .sns_wrap div:last-child ul li span:first-child {display: block; width:60px; height: 60px; margin-bottom: 14px; background: url('/pc/ux/images/ico_sns_bg.png')no-repeat; text-indent: -9999px;}
+	.login .form_wrap .sns_wrap div:last-child ul li span:first-child {display: block; width:60px; height: 60px; margin-bottom: 14px; background: url('/images/ico_sns_bg.png')no-repeat; text-indent: -9999px;}
 	.login .form_wrap .sns_wrap div:last-child ul li:nth-child(2) span:first-child {background-position: -70px 0;}
 	.login .form_wrap .sns_wrap div:last-child ul li:nth-child(3) span:first-child {background-position: -140px 0;}
 	.login .form_wrap .sns_wrap div:last-child ul li span:last-child {font-size:14px; font-weight:300; color:#222;}
@@ -379,7 +379,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.cs .ui_row.nodata {display: inherit; padding-top: 124px; margin-bottom: 0; /*border-top: 1px solid #222222;*/ text-align: center;}
 	.cs .ui_row.nodata .foldGroup {display:none;}
 	.cs .ui_row.nodata + .ui_foot {display:none;}
-	.cs .ui_row.nodata::before {content: ''; display: block; width: 36px; height: 46px; margin:0 auto; background: url('/pc/ux/images/ico_null.png')no-repeat;}
+	.cs .ui_row.nodata::before {content: ''; display: block; width: 36px; height: 46px; margin:0 auto; background: url('/images/ico_null.png')no-repeat;}
 	.cs .ui_row.nodata::after {content: '등록된 문의가 없습니다.'; display: block; padding: 33px 0 160px; font-size: 22px; font-weight: 200; color: #888;}
 
 	/* faq */
@@ -396,7 +396,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.faq .search_wrap .faq_search .search_box {display:inline-block; position:relative; width:600px; padding-right:50px; border-bottom:2px solid #222; box-sizing: border-box; text-align:left;}
 	.faq .search_wrap .faq_search .search_box input[type='text'] {display:inline-block; width:100%; height:50px; padding-left:0; border:none; background:none; color:#222; font-size:30px; font-weight:200; letter-spacing:-0.025em; line-height:1;}
 	.faq .search_wrap .faq_search .search_box input[type='text']::placeholder {color:#888;}
-	.faq .search_wrap .faq_search .search_box .btn_search {display:inline-block; position:absolute; right:0; top:11px; width:28px; height:28px; overflow:hidden; background:url('/pc/ux/images/ico_search_faq.png') no-repeat 50% 50%; font-size:1px; text-indent:-9999px; z-index:2}
+	.faq .search_wrap .faq_search .search_box .btn_search {display:inline-block; position:absolute; right:0; top:11px; width:28px; height:28px; overflow:hidden; background:url('/images/ico_search_faq.png') no-repeat 50% 50%; font-size:1px; text-indent:-9999px; z-index:2}
 	.faq .search_wrap .faq_search .t_info {width:600px; margin:17px auto 0; font-weight:200; text-align:left;}
 	.faq .fold_nav {width:100%;}
 	.faq .fold_nav ul {display: flex; display: -ms-flexbox; flex-wrap: wrap; margin-top:-12px}
@@ -451,7 +451,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.contactUs_my .ck_box {padding:10px 20px}
 	.contactUs_my .ck_box input[type="checkbox"] + label {font-size:16px; font-weight:200;}
 	.contactUs_my .t_err {font-weight:200}
-	.contactUs_my .t_err::before {background-image:url('/pc/ux/images/ico_err2.png');}
+	.contactUs_my .t_err::before {background-image:url('/images/ico_err2.png');}
 	.contactUs_my .info_addfile {margin-top:20px; color:#666; font-size:14px; line-height:24px; font-weight:200;}
 	.contactUs_my .sec_foot {margin-top:60px}
 	.contactUs_my .sec_foot .btn.btn_md {margin:0px 5px; font-weight:300; padding:15px 90px;}
@@ -487,7 +487,7 @@ body {min-width:1460px; overflow-x:auto;}
 		position: absolute; 
 		width:12px; 
 		height: 10px; 
-		background: url(/pc/ux/images/ico_filter.png)no-repeat;
+		background: url(/images/ico_filter.png)no-repeat;
 		top: 44%; 
 		left: 0; 
 		transform: translateY(-50%);
@@ -510,7 +510,7 @@ body {min-width:1460px; overflow-x:auto;}
     background-position: center center;
     background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAAXNSR0IArs4c6QAAA3hJREFUaAXlm8+K00Acx7MiCIJH/yw+gA9g25O49SL4AO3Bp1jw5NvktC+wF88qevK4BU97EmzxUBCEolK/n5gp3W6TTJPfpNPNF37MNsl85/vN/DaTmU6PknC4K+pniqeKJ3k8UnkvDxXJzzy+q/yaxxeVHxW/FNHjgRSeKt4rFoplzaAuHHDBGR2eS9G54reirsmienDCTRt7xwsp+KAoEmt9nLaGitZxrBbPFNaGfPloGw2t4JVamSt8xYW6Dg1oCYo3Yv+rCGViV160oMkcd8SYKnYV1Nb1aEOjCe6L5ZOiLfF120EjWhuBu3YIZt1NQmujnk5F4MgOpURzLfAwOBSTmzp3fpDxuI/pabxpqOoz2r2HLAb0GMbZKlNV5/Hg9XJypguryA7lPF5KMdTZQzHjqxNPhWhzIuAruOl1eNqKEx1tSh5rfbxdw7mOxCq4qS68ZTjKS1YVvilu559vWvFHhh4rZrdyZ69Vmpgdj8fJbDZLJpNJ0uv1cnr/gjrUhQMuI+ANjyuwftQ0bbL6Erp0mM/ny8Fg4M3LtdRxgMtKl3jwmIHVxYXChFy94/Rmpa/pTbNUhstKV+4Rr8lLQ9KlUvJKLyG8yvQ2s9SBy1Jb7jV5a0yapfF6apaZLjLLcWtd4sNrmJUMHyM+1xibTjH82Zh01TNlhsrOhdKTe00uAzZQmN6+KW+sDa/JD2PSVQ873m29yf+1Q9VDzfEYlHi1G5LKBBWZbtEsHbFwb1oYDwr1ZiF/2bnCSg1OBE/pfr9/bWx26UxJL3ONPISOLKUvQza0LZUxSKyjpdTGa/vDEr25rddbMM0Q3O6Lx3rqFvU+x6UrRKQY7tyrZecmD9FODy8uLizTmilwNj0kraNcAJhOp5aGVwsAGD5VmJBrWWbJSgWT9zrzWepQF47RaGSiKfeGx6Szi3gzmX/HHbihwBser4B9UJYpFBNX4R6vTn3VQnez0SymnrHQMsRYGTr1dSk34ljRqS/EMd2pLQ8YBp3a1PLfcqCpo8gtHkZFHKkTX6fs3MY0blKnth66rKCnU0VRGu37ONrQaA4eZDFtWAu2fXj9zjFkxTBOo8F7t926gTp/83Kyzzcy2kZD6xiqxTYnHLRFm3vHiRSwNSjkz3hoIzo8lCKWUlg/YtGs7tObunDAZfpDLbfEI15zsEIY3U/x/gHHc/G1zltnAgAAAABJRU5ErkJggg==);
     z-index: 98;
-    background-image: url(/pc/ux/images/ico_pop_cls.png);
+    background-image: url(/images/ico_pop_cls.png);
 	}
 	.filter_content .sort#tap01 > ul {position: relative;}
 	.filter_content .sort#tap01 > ul > li {width: 170px; margin-bottom: 20px;}
@@ -687,7 +687,7 @@ body {min-width:1460px; overflow-x:auto;}
 		right: 0;
 		bottom: 0;
 		left: 0;
-		background: rgba(0,0,0,0.2) url(/pc/ux/images/ico_color_check.png) no-repeat 50% 50%;
+		background: rgba(0,0,0,0.2) url(/images/ico_color_check.png) no-repeat 50% 50%;
 		border-radius: 50%;
 		z-index: 2;
 	}
@@ -703,7 +703,7 @@ body {min-width:1460px; overflow-x:auto;}
 		transform: translateY(-50%);
 		width:13px; 
 		height: 13px; 
-		background: url(/pc/ux/images/ico_filter_reset.png)no-repeat;
+		background: url(/images/ico_filter_reset.png)no-repeat;
 	}
 	.container .count_wrap {padding: 60px 0 30px;}
 	.container .count_wrap div:first-child {float: left;}
@@ -756,7 +756,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.dp_best .ui_row .ui_col_12 .select {width:180px;}
 
 	/* dp_hotdeal */
-	.dp_hotdeal .hotdeal {position: relative; width:100%; height: 838px; margin-bottom: 120px; background: url(/pc/ux/images/thumb/hotdeal_bg.png)no-repeat center center;}
+	.dp_hotdeal .hotdeal {position: relative; width:100%; height: 838px; margin-bottom: 120px; background: url(/images/thumb/hotdeal_bg.png)no-repeat center center;}
 	#countdown{
 		text-align: center;
 		margin: auto;
@@ -847,7 +847,7 @@ body {min-width:1460px; overflow-x:auto;}
 		transform: translateY(-50%);
 		width:13px; 
 		height: 13px; 
-		background: url(/pc/ux/images/ico_filter_reset.png)no-repeat;
+		background: url(/images/ico_filter_reset.png)no-repeat;
 	}
 	.dp_Exhibition .ui_row .ui_col_12 .btn_group .dropdown_menu .ui_row button {width:92px;}
 	.dp_Exhibition .ui_row .ui_col_12 .btn_group .dropdown_menu .ui_row button:last-child {background: #222;}
@@ -864,18 +864,18 @@ body {min-width:1460px; overflow-x:auto;}
 	
 	/* dp_Bulletship */
 	.Bulletship {padding-bottom: 120px;}
-	.Bulletship .Bulletship_head {width:1780px; height: 813px; background: url(/pc/ux/images/thumb/bullet_bg1.png)no-repeat center center;}
+	.Bulletship .Bulletship_head {width:1780px; height: 813px; background: url(/images/thumb/bullet_bg1.png)no-repeat center center;}
 	.Bulletship .Bulletship_body {text-align: center; padding: 60px 0 72px;}
 	.Bulletship .Bulletship_body > p {margin-top: 30px;}
 	.Bulletship .Bulletship_body > p:first-child {position: relative; margin-bottom: 26px; padding-top: 38px;}
-	.Bulletship .Bulletship_body > p:first-child::before {position: absolute; content: ''; width:63px; height: 31px; top:0; left:50%; transform: translateX(-50%); background: url(/pc/ux/images/ico_home.png)no-repeat;}
+	.Bulletship .Bulletship_body > p:first-child::before {position: absolute; content: ''; width:63px; height: 31px; top:0; left:50%; transform: translateX(-50%); background: url(/images/ico_home.png)no-repeat;}
 	.Bulletship .Bulletship_body > p:nth-child(2) {margin-bottom: 46px;}
 	.Bulletship .Bulletship_body > p:nth-child(2) span {color: #fd4802;}
 	.Bulletship .Bulletship_body > p:nth-child(3) {margin-top: 30px;}
-	.Bulletship .Bulletship_foot {width:1780px; height: 393px; background: url(/pc/ux/images/thumb/bullet_bg2.png)no-repeat center center;}
+	.Bulletship .Bulletship_foot {width:1780px; height: 393px; background: url(/images/thumb/bullet_bg2.png)no-repeat center center;}
 	.Bulletship .Bulletship_body .search {position: relative; width:720px; height: 80px; margin: 0 auto; border: 3px solid #fd4802;}
 	.Bulletship .Bulletship_body .search .area,.Bulletship .Bulletship_body .search form,.Bulletship .Bulletship_body .search fieldset{height: 100%;}
-	.Bulletship .Bulletship_body .search .ico_search:before {width:35px; height: 36px; background: url(/pc/ux/images/ico_search_bullet.png)no-repeat;}
+	.Bulletship .Bulletship_body .search .ico_search:before {width:35px; height: 36px; background: url(/images/ico_search_bullet.png)no-repeat;}
 	.Bulletship .Bulletship_body .search input {width:100%; height: 100%; border: none; padding: 22px 30px;}
 	.Bulletship .Bulletship_body .search button {position: absolute; top:20px; right:19px;}
 	.Bulletship .Bulletship_body .bullet_able,.Bulletship .Bulletship_body  .normal_able {width:720px; padding: 26px 112px; margin-bottom: 30px; box-sizing: border-box; background: #f5f5f5;}
@@ -893,7 +893,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.modal.ship_pop {padding: 60px; max-width:580px; height: 490px; text-align: center;}
 	.modal.ship_pop .modal-header {margin-bottom: 30px;}
 	.modal.ship_pop .modal-header p:first-child {position: relative; margin-bottom: 14px; padding-top: 38px;}
-	.modal.ship_pop .modal-header p:first-child::before {position: absolute; content: ''; width:63px; height: 31px; top:0; left:50%; transform: translateX(-50%); background: url(/pc/ux/images/ico_home.png)no-repeat;}
+	.modal.ship_pop .modal-header p:first-child::before {position: absolute; content: ''; width:63px; height: 31px; top:0; left:50%; transform: translateX(-50%); background: url(/images/ico_home.png)no-repeat;}
 	.modal.ship_pop .modal-header p span {color:#fd4802;}
 	.modal.ship_pop .modal-body {background: #f5f5f5; padding: 30px 34px;}
 	.modal.ship_pop .modal-footer {margin-top: 30px;}
@@ -901,9 +901,9 @@ body {min-width:1460px; overflow-x:auto;}
 	/* dp_Bulletship_pop */
 
 	/* dp_detail_case1 */
-	.dp .wide .cont_head div div {position: absolute; width:28px; height: 30px; top:0; right:70px; background: url(/pc/ux/images/ico_sns_share.png)no-repeat;}
+	.dp .wide .cont_head div div {position: absolute; width:28px; height: 30px; top:0; right:70px; background: url(/images/ico_sns_share.png)no-repeat;}
 	.dp .wide .cont_head div div a {display: inline-block; width:100%; height: 100%; text-indent: -9999px;}
-	.dp .wide .cont_body .coner_content .coner_front .big_banner {width:100%; height: 1378px; background: url(/pc/ux/images/thumb/detail_case_bg.png)no-repeat;}
+	.dp .wide .cont_body .coner_content .coner_front .big_banner {width:100%; height: 1378px; background: url(/images/thumb/detail_case_bg.png)no-repeat;}
 	.dp .wide .cont_body .coner_content .coner_item01 {padding: 120px 0 60px;}
 	.dp .wide .cont_body .coner_content .coner_item01 .dp_listItems_wrap > div:first-child {margin-bottom: 54px; text-align: center;}
 	.dp .wide .cont_body .coner_content .coner_item01 .dp_listItems_wrap > div:first-child p {font-size: 30px; line-height: 1;}
@@ -921,8 +921,8 @@ body {min-width:1460px; overflow-x:auto;}
 	.dp .wide .dp_listItems_info .dp_listItems_price del {margin: 0 8px;}
 	.dp .wide .dp_listItems_info .dp_listItems_price .percent{color:#fd4802;}
 	.dp .wide .dp_lookbook_case1 {position: relative;}
-	.dp .wide .dp_lookbook_case1 .slick-prev{display:block; position:absolute; left:50px; top:50%; width:26px; height:50px; background:url(/pc/ux/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
-	.dp .wide .dp_lookbook_case1 .slick-next{display:block; position:absolute; right:50px; top:50%; width:26px; height:50px; background:url(/pc/ux/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.dp .wide .dp_lookbook_case1 .slick-prev{display:block; position:absolute; left:50px; top:50%; width:26px; height:50px; background:url(/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.dp .wide .dp_lookbook_case1 .slick-next{display:block; position:absolute; right:50px; top:50%; width:26px; height:50px; background:url(/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
 	.dp .wide .dp_lookbook_case1 .slick-dots{position:absolute; left:0; bottom:-40px; width:100%; text-align:center; z-index:150;}
 	.dp .wide .dp_lookbook_case1 .slick-dots li{display:inline-block; width:10px; height:10px; margin:0 5px; text-align:center;}
 	.dp .wide .dp_lookbook_case1 .slick-dots li button{display:inline-block; width:10px; height:10px; background:#ddd; border-radius: 50%; text-indent:-9999em;}
@@ -968,9 +968,9 @@ body {min-width:1460px; overflow-x:auto;}
 	}
 	.dp_coupon_list .dp_coupon p:first-child {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
 	.dp_coupon_list .dp_coupon p:last-of-type {margin-top: 22px; font-size: 40px; line-height: 1; color:#fd4802;}
-	.dp_coupon_list .dp_coupon button {position: absolute; width:50px; height: 50px; top:-16px; right: -16px; background: url(/pc/ux/images/ico_down_btn.png)no-repeat;}
+	.dp_coupon_list .dp_coupon button {position: absolute; width:50px; height: 50px; top:-16px; right: -16px; background: url(/images/ico_down_btn.png)no-repeat;}
 	.dp_coupon_tip {max-width: 1580px; margin: 0 auto; padding: 60px 60px 0 60px; box-sizing: border-box; display: flex;  border-top: 1px solid #ddd;}
-	.dp_coupon_tip .dp_coupon_notice::before {content:''; display: block; width:36px; height: 46px; margin: 0 auto; background: url(/pc/ux/images/ico_null.png)no-repeat;}
+	.dp_coupon_tip .dp_coupon_notice::before {content:''; display: block; width:36px; height: 46px; margin: 0 auto; background: url(/images/ico_null.png)no-repeat;}
 	.dp_coupon_tip .dp_coupon_notice::after {content:'유의사항'; display: inline-block; margin-top: 20px; color:#888;}
 	.dp_coupon_tip ul {margin-left: 90px;}
 	.dp_coupon_tip ul li {position: relative; padding-left: 12px; margin-bottom: 12px; color:#888;}
@@ -979,12 +979,12 @@ body {min-width:1460px; overflow-x:auto;}
 	.dp .wide .coner_visual .dp_banner_slide {padding-bottom: 170px;}
 	.dp .wide .coner_visual .dp_banner_slide .slide_head {position: relative; width:810px; margin: 0 auto; padding:60px 0; text-align: center;}
 	.dp .wide .coner_visual .dp_banner_slide .slide_head p {font-size: 30px; line-height: 1;}
-	.dp .wide .coner_visual .dp_banner_slide .slide_head a {position: absolute; top:50%; right:0; transform: translateY(-50%); padding-right: 16px; color:#888; background: url(/pc/ux/images/ico_bread_root.png)no-repeat center right;}
+	.dp .wide .coner_visual .dp_banner_slide .slide_head a {position: absolute; top:50%; right:0; transform: translateY(-50%); padding-right: 16px; color:#888; background: url(/images/ico_bread_root.png)no-repeat center right;}
 	.dp .wide .coner_visual .dp_lookbook_case2 {width:810px; margin: 0 auto;}
 	.dp .wide .coner_visual .dp_lookbook_case2 .slider .slick-list {margin:0 -10px;}
 	.dp .wide .coner_visual .dp_lookbook_case2 .slick-slide {margin:0 10px;}
-	.dp .wide .dp_lookbook_case2 .slick-prev{display:block; position:absolute; left:-65px; top:40%; width:26px; height:50px; background:url(/pc/ux/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
-	.dp .wide .dp_lookbook_case2 .slick-next{display:block; position:absolute; right:-65px; top:40%; width:26px; height:50px; background:url(/pc/ux/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.dp .wide .dp_lookbook_case2 .slick-prev{display:block; position:absolute; left:-65px; top:40%; width:26px; height:50px; background:url(/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.dp .wide .dp_lookbook_case2 .slick-next{display:block; position:absolute; right:-65px; top:40%; width:26px; height:50px; background:url(/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
 	.dp .wide .dp_lookbook_case2 .slick-dots{position:absolute; left:0; bottom:-20px; width:100%; text-align:center; z-index:150;}
 	.dp .wide .dp_lookbook_case2 .slick-dots li{display:inline-block; width:10px; height:10px; margin:0 5px; text-align:center;}
 	.dp .wide .dp_lookbook_case2 .slick-dots li button{display:inline-block; width:10px; height:10px; background:#ddd; border-radius: 50%; text-indent:-9999em;}
@@ -997,13 +997,13 @@ body {min-width:1460px; overflow-x:auto;}
 	.foot_banner_slide {/*width:1640px;*/ margin: 0 auto;padding:0 80px;}
 	.foot_banner_slide > div:first-child {position: relative; text-align: center; padding: 60px 0;}
 	.foot_banner_slide > div:first-child p {font-size: 30px; line-height: 1;}
-	.foot_banner_slide > div:first-child a {position: absolute; top:50%; right:0; transform: translateY(-50%); padding-right: 16px; color:#888; background: url(/pc/ux/images/ico_bread_root.png)no-repeat center right;}
+	.foot_banner_slide > div:first-child a {position: absolute; top:50%; right:0; transform: translateY(-50%); padding-right: 16px; color:#888; background: url(/images/ico_bread_root.png)no-repeat center right;}
 	.foot_banner_slide .dp_lookbook_case3 .dp_lookbook_item > div {width:312px;}
 	.foot_banner_slide .dp_lookbook_case3 .dp_lookbook_item > div:last-child {padding: 22px 0 104px;}
 	.foot_banner_slide .dp_lookbook_case3 .slider .slick-list {margin:0 -10px;}
 	.foot_banner_slide .dp_lookbook_case3 .slick-slide {margin:0 10px;}
-	.foot_banner_slide .dp_lookbook_case3 .slick-prev{display:block; position:absolute; left:-65px; top:31%; width:26px; height:50px; background:url(/pc/ux/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
-	.foot_banner_slide .dp_lookbook_case3 .slick-next{display:block; position:absolute; right:-65px; top:31%; width:26px; height:50px; background:url(/pc/ux/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.foot_banner_slide .dp_lookbook_case3 .slick-prev{display:block; position:absolute; left:-65px; top:31%; width:26px; height:50px; background:url(/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.foot_banner_slide .dp_lookbook_case3 .slick-next{display:block; position:absolute; right:-65px; top:31%; width:26px; height:50px; background:url(/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
 
 	/* dp_detail_casePOPUP */
 	.modal.dp_coupon_pop {max-width: 600px; padding: 60px;}
@@ -1020,22 +1020,22 @@ body {min-width:1460px; overflow-x:auto;}
 
 	/* dp_detail_case3 */
 	.dp .wide .dp_lookbook_case4 {position: relative;}
-	.dp .wide .dp_lookbook_case4 .slick-prev{display:block; position:absolute; left:120px; top:50%; width:26px; height:50px; background:url(/pc/ux/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
-	.dp .wide .dp_lookbook_case4 .slick-next{display:block; position:absolute; right:120px; top:50%; width:26px; height:50px; background:url(/pc/ux/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.dp .wide .dp_lookbook_case4 .slick-prev{display:block; position:absolute; left:120px; top:50%; width:26px; height:50px; background:url(/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.dp .wide .dp_lookbook_case4 .slick-next{display:block; position:absolute; right:120px; top:50%; width:26px; height:50px; background:url(/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
 	.dp .wide .dp_lookbook_case4 .slick-dots{position:absolute; left:0; bottom:40px; width:100%; text-align:center; z-index:150;}
 	.dp .wide .dp_lookbook_case4 .slick-dots li{display:inline-block; width:10px; height:10px; margin:0 5px; text-align:center;}
 	.dp .wide .dp_lookbook_case4 .slick-dots li button{display:inline-block; width:10px; height:10px; background:#ddd; border-radius: 50%; text-indent:-9999em;}
 	.dp .wide .dp_lookbook_case4 .slick-dots li.slick-active button{background:#fd4802;}
 	.coner_item03 .slide_head {position: relative; width:1640px; margin: 0 auto; text-align: center; padding:0 0 60px;}
 	.coner_item03 .slide_head p {font-size: 30px;}
-	.coner_item03 .slide_head a {position: absolute; top:0; right:0; padding-right: 16px; color:#888; background: url(/pc/ux/images/ico_bread_root.png)no-repeat center right;}
+	.coner_item03 .slide_head a {position: absolute; top:0; right:0; padding-right: 16px; color:#888; background: url(/images/ico_bread_root.png)no-repeat center right;}
 	.dp .wide .coner_item03 {padding-top: 120px;}
 	.dp .wide .coner_item03 .dp_lookbook_case5 {width:1640px; margin: 0 auto;}
 	.dp .wide .coner_item03 .dp_lookbook_case5 .slider .slick-list {margin:0 -10px;}
 	.dp .wide .coner_item03 .dp_lookbook_case5 .slick-slide {margin:0 10px;}
 	.dp .wide .coner_item03 .dp_lookbook_case5 .dp_lookbook_item > div:last-child {text-align: left;}
-	.dp .wide .dp_lookbook_case5 .slick-prev{display:block; position:absolute; left:-65px; top:40%; width:26px; height:50px; background:url(/pc/ux/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
-	.dp .wide .dp_lookbook_case5 .slick-next{display:block; position:absolute; right:-65px; top:40%; width:26px; height:50px; background:url(/pc/ux/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.dp .wide .dp_lookbook_case5 .slick-prev{display:block; position:absolute; left:-65px; top:40%; width:26px; height:50px; background:url(/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.dp .wide .dp_lookbook_case5 .slick-next{display:block; position:absolute; right:-65px; top:40%; width:26px; height:50px; background:url(/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
 	.dp .wide .dp_lookbook_case5 .slick-dots{position:absolute; left:0; bottom:-20px; width:100%; text-align:center; z-index:150;}
 	.dp .wide .dp_lookbook_case5 .slick-dots li{display:inline-block; width:10px; height:10px; margin:0 5px; text-align:center;}
 	.dp .wide .dp_lookbook_case5 .slick-dots li button{display:inline-block; width:10px; height:10px; background:#ddd; border-radius: 50%; text-indent:-9999em;}
@@ -1161,7 +1161,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.od .od_side .area_salecode {margin-top:35px}
 	.od .od_side .area_salecode input {font-size:14px; font-weight:200;}
 	.od .od_side .area_salecode .btn {padding:14px 20px; height:50px; box-sizing:border-box; font-size:14px; font-weight:200}
-	.od .od_side .area_salecode .coupon_code {width:320px; height:156px; margin-top:10px; padding:50px 0 0 88px; background:url('/pc/ux/images/bg_coupon_code.jpg') no-repeat 50% 50%; box-sizing:border-box; font-weight:200; line-height:1.3;}
+	.od .od_side .area_salecode .coupon_code {width:320px; height:156px; margin-top:10px; padding:50px 0 0 88px; background:url('/images/bg_coupon_code.jpg') no-repeat 50% 50%; box-sizing:border-box; font-weight:200; line-height:1.3;}
 	.od .od_side .area_salecode .coupon_code .salecode_num {color:#888; font-size:12px;}
 	.od .od_side .area_salecode .coupon_code .salecondition {margin-top:5px; color:#fd4802; font-size:14px;}
 	.od .od_side .area_saleitem {margin-top:40px}
@@ -1320,7 +1320,7 @@ body {min-width:1460px; overflow-x:auto;}
 		transform: translateY(-50%);
 		width:18px;
 		height: 18px;
-		background: url(/pc/ux/images/ico_chk_rdi.png) no-repeat;
+		background: url(/images/ico_chk_rdi.png) no-repeat;
 		background-position: -21px -1px;
 	}
 	.od .order li:nth-child(4) .info_fix p::after {display: none;}
@@ -1339,7 +1339,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.od .clearance .row .form_field input:last-of-type:checked ~ .s_info {display: block;}
 	.od .clearance .row .form_field .s_info {display: none; margin-top: 12px;}
 	.od .clearance .bottom_info {margin-top: 30px; padding: 40px; border:1px solid #ddd; box-sizing: border-box;}
-	.od .clearance .bottom_info strong {display: block; margin-bottom: 30px; padding-left: 30px; background: url(/pc/ux/images/ico_mark.png)no-repeat center left; color:#666;}
+	.od .clearance .bottom_info strong {display: block; margin-bottom: 30px; padding-left: 30px; background: url(/images/ico_mark.png)no-repeat center left; color:#666;}
 	.od .clearance .bottom_info p {position: relative; padding-left: 13px;}
 	.od .clearance .bottom_info p::before {content:''; position: absolute; top:50%; left:0; transform: translateY(-50%); width:3px; height: 3px; background: #666;}
 	.od .clearance .bottom_info p:first-of-type {margin-bottom: 10px;}
@@ -1400,7 +1400,7 @@ body {min-width:1460px; overflow-x:auto;}
 		border: 1px solid #ccc;
 		border-radius: 100%;
 		box-sizing: border-box;
-		background: url(/pc/ux/images/ico_chk_rdi.png) no-repeat;
+		background: url(/images/ico_chk_rdi.png) no-repeat;
 		background-position: -64px -1px;
 	}
 	.od .paymethod_wrap input[type="radio"]:checked + label:after,.od .paymethod_wrap .form_field input[type="radio"]:checked + label:after {
@@ -1412,7 +1412,7 @@ body {min-width:1460px; overflow-x:auto;}
 		width: 20px;
 		height: 20px;
 		background-color: #fd4800;
-		background: url(/pc/ux/images/ico_chk_rdi.png) no-repeat;
+		background: url(/images/ico_chk_rdi.png) no-repeat;
 		background-position: -84px 0px;
 	}
 	.od .privacy_consent p:first-child {margin-bottom: 12px;}
@@ -1443,8 +1443,8 @@ body {min-width:1460px; overflow-x:auto;}
 	.od .paymethod_list .paymethod .paymethod_body .add_card { align-items: center; width:100%; height: 214px;}
 	.od .od_slide_wrap .od_card_slide .slick-slide {margin: 0 80px;}
 	.od .od_slide_wrap .od_card_slide .post {width:340px; height: 214px;}
-	.od .od_slide_wrap .od_card_slide .slick-prev{display:block; position:absolute; left:245px; top:50%; width:26px; height:50px; background:url(/pc/ux/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
-	.od .od_slide_wrap .od_card_slide .slick-next{display:block; position:absolute; right:245px; top:50%; width:26px; height:50px; background:url(/pc/ux/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.od .od_slide_wrap .od_card_slide .slick-prev{display:block; position:absolute; left:245px; top:50%; width:26px; height:50px; background:url(/images/slide_prev.png) no-repeat left; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
+	.od .od_slide_wrap .od_card_slide .slick-next{display:block; position:absolute; right:245px; top:50%; width:26px; height:50px; background:url(/images/slide_next.png) no-repeat right; text-indent:-9999px; z-index:500; transform:translateY(-50%);}
 	.od .paymethod_list .paymethod .paymethod_body .add_card .enrollment {text-align: center; margin-top: 20px;}
 	.od .paymethod_list .paymethod .paymethod_text {padding: 30px 0; margin-top: 30px; border-top: 1px solid #ddd;}
 	.od .paymethod_list .paymethod .paymethod_text p {margin-bottom: 10px;}
@@ -1501,7 +1501,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.nonMBorder .cont_body .form_field.txt_area + .form_field .ui_row {margin-bottom: 0;}
 	.nonMBorder .cont_body .form_field .ui_row [class^='ui_col_'] {margin-left:0;}
 	.nonMBorder .cont_body .form_info {display: flex; justify-content: space-between;}
-	.nonMBorder .cont_body .form_info a {padding-right: 17px; color:#fd4802; background: url(/pc/ux/images/ico_mb_arrow2.png)no-repeat 100% 47%;}
+	.nonMBorder .cont_body .form_info a {padding-right: 17px; color:#fd4802; background: url(/images/ico_mb_arrow2.png)no-repeat 100% 47%;}
 
 	/* pd_공통 */
 	.pd,
@@ -1591,7 +1591,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.my .mem_rank {position: relative; padding-left: 73px; float:left;}
 	.my .mem_rank .rank_icon {width: 60px; height: 60px; line-height: 64px; position: absolute; left: 0; top: 0; font-size: 30px; border-radius: 50%; background: #000; color: #fff; text-align: center;}
 	.my .mem_rank .rank_txt01 {font-size: 25px; height: 25px; line-height: 27px; color: #fd4801; margin-bottom: 14px;}
-	.my .mem_rank .rank_txt02 a {display: inline-block; font-size: 12px; padding-right: 13px; margin-right: 20px; background: url(/pc/ux/images/ico_mysm_arrow.png) no-repeat right 4px;}
+	.my .mem_rank .rank_txt02 a {display: inline-block; font-size: 12px; padding-right: 13px; margin-right: 20px; background: url(/images/ico_mysm_arrow.png) no-repeat right 4px;}
 	.my .mem_info .mem_box {float:right;}
 	.my .mem_info .mem_box > div {float:left; position: relative; margin-right: 70px;}
 	.my .mem_info .mem_box > .mem_coupon .coupon_txt02 {font-size: 15px;}
@@ -1601,14 +1601,14 @@ body {min-width:1460px; overflow-x:auto;}
 	.my .mem_info .mem_box > div a, .my .mem_info .mem_box > div .coupon_txt01 {font-size: 15px; color: #000;}
 	.my .mem_info .mem_box > div .tit {font-size: 15px; padding-left: 30px; margin-bottom: 20px;}
 	.my .mem_info .mem_box > div .big_txt {display: inline-block; font-size: 23px; padding-right: 3px;} 
-	.my .mem_info .mem_box > .mem_coupon .tit {background: url(/pc/ux/images/ico_mycoupon.png) no-repeat left 1px;}
-	.my .mem_info .mem_box > .mem_point .tit {background: url(/pc/ux/images/ico_point02.png) no-repeat left 0;}
-	.my .mem_info .mem_box > .mem_gift .tit {background: url(/pc/ux/images/ico_gift.png) no-repeat left 1px;}
+	.my .mem_info .mem_box > .mem_coupon .tit {background: url(/images/ico_mycoupon.png) no-repeat left 1px;}
+	.my .mem_info .mem_box > .mem_point .tit {background: url(/images/ico_point02.png) no-repeat left 0;}
+	.my .mem_info .mem_box > .mem_gift .tit {background: url(/images/ico_gift.png) no-repeat left 1px;}
 	.my .order_info {background: #f5f5f5; padding: 50px 80px; margin-bottom: 60px;}
 	.my .order_info > ul {float:left; margin-top: 15px; position: relative;}
 	.my .order_info > ul:after {content:''; position: absolute; top: 5px; right: -70px; width: 1px; height: 60px; background: #888;}
 	.my .order_info > ul > li {float:left; text-align: center; margin-right: 120px; position: relative;}
-	.my .order_info > ul > li:after {content:''; position: absolute; top: 50%; right: -70px; width: 17px; height: 31px; background: url(/pc/ux/images/ico_myinfo_arrow.png) no-repeat center; transform:translateY(-50%);}
+	.my .order_info > ul > li:after {content:''; position: absolute; top: 50%; right: -70px; width: 17px; height: 31px; background: url(/images/ico_myinfo_arrow.png) no-repeat center; transform:translateY(-50%);}
 	.my .order_info > ul > li:last-child {margin-right: 0;}
 	.my .order_info > ul > li:last-child:after {display: none;}
 	.my .order_info > ul > li .or_p {font-size: 15px; color: #666; margin-bottom: 16px;}
@@ -1629,7 +1629,7 @@ body {min-width:1460px; overflow-x:auto;}
 	.my .order_sch_filter .btn {padding:10px 20px; margin-left: 10px;}
 	.my .order_row {margin-top: 60px;}
 	.my .tbl_tit {position: relative; margin-bottom: 15px;}
-	.my .tbl_tit .detail_btn {position: absolute; top: 0; right: 0; color: #8d8d8d; padding-right: 14px; background: url(/pc/ux/images/ico_mysm_arrow.png) no-repeat right 3px;}
+	.my .tbl_tit .detail_btn {position: absolute; top: 0; right: 0; color: #8d8d8d; padding-right: 14px; background: url(/images/ico_mysm_arrow.png) no-repeat right 3px;}
 	.my .order_row .order_table {border-top: 1px solid #010101; }
 	.my .order_row .order_table td {text-align: center; border-right:1px solid #dcdcdc; height: 210px; border-bottom: 1px solid #dcdcdc;}
 	.my .order_row .order_table td.product {text-align: left;}
@@ -1689,7 +1689,7 @@ body {min-width:1460px; overflow-x:auto;}
 
 	.my .com_info_txt {padding:40px; border:1px solid #dcdcdc;}
 	.my .com_info_txt .tit {position: relative; font-size: 16px; color: #626262; padding-left: 30px; margin-bottom: 30px;}
-	.my .com_info_txt .tit:after {content:''; position: absolute; top: 0; left: 0; width: 20px; height: 20px; background: url(/pc/ux/images/ico_null02.png) no-repeat center}
+	.my .com_info_txt .tit:after {content:''; position: absolute; top: 0; left: 0; width: 20px; height: 20px; background: url(/images/ico_null02.png) no-repeat center}
 	.my .com_info_txt ul li {position: relative; font-size: 14px; color: #858585; padding-left: 15px; margin-bottom: 10px;}
 	.my .com_info_txt ul li:last-child {margin-bottom: 0;}
 	.my .com_info_txt ul li:after {content:''; position: absolute; top: 7px; left: 0; background: #858585; width: 3px; height: 3px;}

+ 379 - 0
src/main/webapp/ux/plugins/gaga/gaga.common.js

@@ -0,0 +1,379 @@
+/*
+ * Common Java Script written by gagamel.
+ *
+ * Copyright (c) 2010 gagamel
+ * Dual licensed under GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2010-05-19 $
+ */
+
+/**
+ * @type   : prototype_function
+ * @access : public
+ * @desc   : 자바스크립트의 내장 객체인 String 객체에 trim 메소드를 추가한다. trim 메소드는 스트링의 앞과 뒤에
+ *           있는 white space 를 제거한다.
+ * <pre>
+ *     var str = " abcde "
+ *     str = str.trim();
+ * </pre>
+ * 위의 예에서 str는 "abede"가 된다.
+ * @return : trimed String.
+ * @author : gagamel
+ */
+String.prototype.trim = function() {
+	return this.replace(/(^\s*)|(\s*$)/g, "");
+};
+
+/**
+ * @type   : prototype_function
+ * @access : public
+ * @desc   : 자바스크립트의 내장 객체인 String 객체에 replaceAll 메소드를 추가한다. replaceAll 메소드는
+ *           스트링 내에 있는 특정 스트링을 다른 스트링으로 모두 변환한다. String 객체의 replace 메소드를 확장한 것이다.
+ * <pre>
+ *     var str = "abcde"
+ *     str = str.replaceAll("cd", "xx");
+ * </pre>
+ * 위의 예에서 str는 "abxxe"가 된다.
+ * @sig    : oldStr, newStr
+ * @param  : oldStr required 바뀌어야 될 기존의 스트링
+ * @param  : newStr required 바뀌어질 새로운 스트링
+ * @return : replaced String.
+ * @author : gagamel
+ */
+String.prototype.replaceAll = function(oldStr, newStr) {
+	var rStr = oldStr;
+
+	rStr = rStr.replace(/\\/g, "\\\\");
+	rStr = rStr.replace(/\^/g, "\\^");
+	rStr = rStr.replace(/\$/g, "\\$");
+	rStr = rStr.replace(/\*/g, "\\*");
+	rStr = rStr.replace(/\+/g, "\\+");
+	rStr = rStr.replace(/\?/g, "\\?");
+	rStr = rStr.replace(/\./g, "\\.");
+	rStr = rStr.replace(/\(/g, "\\(");
+	rStr = rStr.replace(/\)/g, "\\)");
+	rStr = rStr.replace(/\|/g, "\\|");
+	rStr = rStr.replace(/\,/g, "\\,");
+	rStr = rStr.replace(/\{/g, "\\{");
+	rStr = rStr.replace(/\}/g, "\\}");
+	rStr = rStr.replace(/\[/g, "\\[");
+	rStr = rStr.replace(/\]/g, "\\]");
+	rStr = rStr.replace(/\-/g, "\\-");
+
+	var re = new RegExp(rStr, "g");
+
+	return this.replace(re, newStr);
+};
+
+/**
+ * @type   : prototype_function
+ * @access : public
+ * @desc   : 자바스크립트의 내장 객체인 String 객체에 toDate 메소드를 추가한다. toDate 메소드는 날짜를 표현하는
+ *           스트링 값을 자바스크립트의 내장 객체인 Date 객체로 변환한다.
+ * <pre>
+ *     var date = "20020305".toDate();
+ *     or
+ *     var date = "20020305".toDate("YYYYMMDD");
+ *     or
+ *     var date = "2002.03.05".toDate("YYYY.MM.DD");
+ * </pre>
+ * 위의 예에서 date 변수는 실제로 2002년 3월 5일을 표현하는 Date 오브젝트를 가르킨다.
+ * @sig    : [pattern]
+ * @param  : pattern optional Date를 표현하고 있는 현재의 String을 pattern으로 표현한다. (default : YYYYMMDD)
+ * <pre>
+ *     # syntax
+ *
+ *       YYYY : year(4자리)
+ *       YY   : year(2자리)
+ *       MM   : month in year(number)
+ *       DD   : day in month
+ *       HH   : hour in day (0~23)
+ *       mm   : minute in hour
+ *       ss   : second in minute
+ *       SS   : millisecond in second
+ *
+ *     <font color=red>주의)</font> YYYY(YY)는 반드시 있어야 한다. YYYY(YY) 만 사용할 경우는 1월 1일을 기준으로
+ *     하고 YYYY와 MM 만사용할 경우는 1일을 기준으로 한다.
+ * </pre>
+ * @return : 변환된 Date Object.
+ * @author : gagamel
+ */
+String.prototype.toDate = function(pattern) {
+	var index = -1;
+	var year;
+	var month;
+	var day;
+	var hour = 0;
+	var min  = 0;
+	var sec  = 0;
+	var ms   = 0;
+	var newDate;
+
+	if (pattern == null) {
+		pattern = "YYYYMMDD";
+	}
+
+	if ((index = pattern.indexOf("YYYY")) == -1 ) {
+		index = pattern.indexOf("YY");
+		year = "20" + this.substr(index, 2);
+	} else {
+		year = this.substr(index, 4);
+	}
+
+	if ((index = pattern.indexOf("MM")) != -1 ) {
+		month = this.substr(index, 2);
+	} else {
+		month = 1;
+	}
+
+	if ((index = pattern.indexOf("DD")) != -1 ) {
+		day = this.substr(index, 2);
+	} else {
+		day = 1;
+	}
+
+	if ((index = pattern.indexOf("HH")) != -1 ) {
+		hour = this.substr(index, 2);
+	}
+
+	if ((index = pattern.indexOf("mm")) != -1 ) {
+		min = this.substr(index, 2);
+	}
+
+	if ((index = pattern.indexOf("ss")) != -1 ) {
+		sec = this.substr(index, 2);
+	}
+
+	if ((index = pattern.indexOf("SS")) != -1 ) {
+		ms = this.substr(index, 2);
+	}
+
+	newDate = new Date(year, month - 1, day, hour, min, sec, ms);
+
+	if (month > 12) {
+		newDate.setFullYear(year + 1);
+	} else {
+		newDate.setFullYear(year);
+	}
+
+	return newDate;
+};
+
+/**
+ * @type   : prototype_function
+ * @object : Date
+ * @access : public
+ * @desc   : 자바스크립트의 내장 객체인 Date 객체에 format 메소드를 추가한다. format 메소드는 Date 객체가 가진 날짜를
+ *           지정된 포멧의 스트링으로 변환한다.
+ * <pre>
+ *     var dateStr = new Date().format("YYYYMMDD");
+ *
+ *     참고 : Date 오브젝트 생성자들 - dateObj = new Date()
+ *                                   - dateObj = new Date(dateVal)
+ *                                   - dateObj = new Date(year, month, date[, hours[, minutes[, seconds[,ms]]]])
+ * </pre>
+ * 위의 예에서 오늘날짜가 2002년 3월 5일이라면 dateStr의 값은 "20020305"가 된다.
+ * default pattern은 "YYYYMMDD"이다.
+ * @sig    : [pattern]
+ * @param  : pattern optional 변환하고자 하는 패턴 스트링. (default : YYYYMMDD)
+ * <pre>
+ *     # syntax
+ *
+ *       YYYY : hour in am/pm (1~12)
+ *       MM   : month in year(number)
+ *       MON  : month in year(text)  예) "January"
+ *       mon  : short month in year(text)  예) "Jan"
+ *       DD   : day in month
+ *       DAY  : day in week  예) "Sunday"
+ *       day  : short day in week  예) "Sun"
+ *       hh   : hour in am/pm (1~12)
+ *       HH   : hour in day (0~23)
+ *       mm   : minute in hour
+ *       ss   : second in minute
+ *       SS   : millisecond in second
+ *       a    : am/pm  예) "AM"
+ * </pre>
+ * @return : Date를 표현하는 변환된 String.
+ * @author : gagamel
+ */
+Date.prototype.format = function(pattern) {
+	var GLB_MONTH_IN_YEAR = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
+	var GLB_DAY_IN_WEEK   = new Array("Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday");
+
+	var year      = this.getFullYear();
+	var month     = this.getMonth() + 1;
+	var day       = this.getDate();
+	var dayInWeek = this.getDay();
+	var hour24    = this.getHours();
+	var hour12    = (hour24 > 12) ? (hour24 - 12) : hour24;
+	var min       = this.getMinutes();
+	var sec       = this.getSeconds();
+	var YYYY = "" + year;
+	var YY   = YYYY.substr(2);
+	var MM   = (("" + month).length == 1) ? "0" + month : "" + month;
+	var MON  = GLB_MONTH_IN_YEAR[month-1];
+	var DD   = (("" + day).length == 1) ? "0" + day : "" + day;
+	var DAY  = GLB_DAY_IN_WEEK[dayInWeek];
+	var HH   = (("" + hour24).length == 1) ? "0" + hour24 : "" + hour24;
+	var hh   = (("" + hour12).length == 1) ? "0" + hour12 : "" + hour12;
+	var mm   = (("" + min).length == 1) ? "0" + min : "" + min;
+	var ss   = (("" + sec).length == 1) ? "0" + sec : "" + sec;
+	var a    = (a == 0) ? "AM" : "PM";
+
+	var dateStr;
+
+	if (typeof(pattern) == "undefined") {
+		dateStr = "YYYYMMDD";
+	} else {
+		dateStr = pattern;
+	}
+
+	dateStr = dateStr.replace(/a/g,    a);
+	dateStr = dateStr.replace(/YYYY/g, YYYY);
+	dateStr = dateStr.replace(/YY/g,   YY);
+	dateStr = dateStr.replace(/MM/g,   MM);
+	dateStr = dateStr.replace(/MON/g,  MON);
+	dateStr = dateStr.replace(/DD/g,   DD);
+	dateStr = dateStr.replace(/DAY/g,  DAY);
+	dateStr = dateStr.replace(/hh/g,   hh);
+	dateStr = dateStr.replace(/HH/g,   HH);
+	dateStr = dateStr.replace(/mm/g,   mm);
+	dateStr = dateStr.replace(/ss/g,   ss);
+
+	return dateStr;
+};
+
+/**
+ * @type   : prototype_function
+ * @object : Date
+ * @access : public
+ * @desc   : 현재 Date 객체의 날짜보다 이후날짜를 가진 Date 객체를 리턴한다.
+ *           예를 들어 내일 날짜를 얻으려면 다음과 같이 하면 된다.
+ * <pre>
+ *     var oneDayAfter = new Date.after(0, 0, 1);
+ * </pre>
+ * @sig    : [years[, months[, days[, hours[, minutes[, seconds[, mss]]]]]]]
+ * @param  : years   optional 이후 년수
+ * @param  : months  optional 이후 월수
+ * @param  : days   optional 이후 일수
+ * @param  : hours   optional 이후 시간수
+ * @param  : minutes optional 이후 분수
+ * @param  : seconds optional 이후 초수
+ * @param  : mss     optional 이후 밀리초수
+ * @return : 이후날짜를 표현하는 Date 객체
+ * @author : gagamel
+ */
+Date.prototype.after = function(years, months, days, hours, miniutes, seconds, mss) {
+	if (years == null) years = 0;
+	if (months == null) months = 0;
+	if (days == null) days = 0;
+	if (hours == null) hours = 0;
+	if (miniutes == null) miniutes = 0;
+	if (seconds == null) seconds = 0;
+	if (mss == null) mss = 0;
+	return new Date(this.getFullYear() + years,
+			this.getMonth() + months,
+			this.getDate() + days,
+			this.getHours() + hours,
+			this.getMinutes() + miniutes,
+			this.getSeconds() + seconds,
+			this.getMilliseconds() + mss
+	);
+};
+
+/**
+ * @type   : prototype_function
+ * @object : Date
+ * @access : public
+ * @desc   : 현재 Date 객체의 날짜보다 이전날짜를 가진 Date 객체를 리턴한다.
+ *           예를 들어 어제 날짜를 얻으려면 다음과 같이 하면 된다.
+ * <pre>
+ *     var oneDayBefore = new Date.before(0, 0, 1);
+ * </pre>
+ * @sig    : [years[, months[, days[, hours[, minutes[, seconds[, mss]]]]]]]
+ * @param  : years   optional 이전으로 돌아갈 년수
+ * @param  : months  optional 이전으로 돌아갈 월수
+ * @param  : days   optional 이전으로 돌아갈 일수
+ * @param  : hours   optional 이전으로 돌아갈 시간수
+ * @param  : minutes optional 이전으로 돌아갈 분수
+ * @param  : seconds optional 이전으로 돌아갈 초수
+ * @param  : mss     optional 이전으로 돌아갈 밀리초수
+ * @return : 이전날짜를 표현하는 Date 객체
+ * @author : gagamel
+ */
+Date.prototype.before = function(years, months, days, hours, miniutes, seconds, mss) {
+	if (years == null) years = 0;
+	if (months == null) months = 0;
+	if (days == null) days = 0;
+	if (hours == null) hours = 0;
+	if (miniutes == null) miniutes = 0;
+	if (seconds == null) seconds  = 0;
+	if (mss == null) mss = 0;
+	return new Date(this.getFullYear() - years,
+			this.getMonth() - months,
+			this.getDate() - days,
+			this.getHours() - hours,
+			this.getMinutes() - miniutes,
+			this.getSeconds() - seconds,
+			this.getMilliseconds() - mss
+	);
+};
+
+/**
+ * @type   : function
+ * @access : public
+ * @desc   : 자바스크립트의 내장 객체인 Number 객체에 addComma 메소드를 추가한다.
+ *           값에서 콤마(,)를 추가한다.
+ * <pre>
+ *     -12345678.123.addComma();
+ * </pre>
+ * @return : 콤마(,)가 추가된 값
+ * @since  : 2014/10/15
+ * @author : gagamel
+ */
+Number.prototype.addComma = function(decimalPosition) {
+	var num = this;
+
+	if (typeof(decimalPosition) == 'undefined') {
+		return num.toLocaleString();
+	} else {
+		return num.toLocaleString("ko-KR", {maximumFractionDigits:decimalPosition});
+	}
+}
+
+/**
+ * @type   : function
+ * @access : public
+ * @desc   : 자바스크립트의 내장 객체인 String 객체에 addComma 메소드를 추가한다.
+ *           스트링에서 콤마(,)를 추가한다.
+ * <pre>
+ *     "-12345678.123".addComma();
+ * </pre>
+ * @return : 콤마(,)가 추가된 값
+ * @since  : 2014/10/15
+ * @author : gagamel
+ */
+String.prototype.addComma = function(decimalPosition) {
+	var num = Number(this);
+
+	if (typeof(decimalPosition) == 'undefined') {
+		return num.addComma();
+	} else {
+		return num.addComma(decimalPosition);
+	}
+}
+
+/**
+ * @type   : prototype_function
+ * @access : public
+ * @desc   : 자바스크립트의 내장 객체인 String 객체에 removeComma 메소드를 추가한다.
+ *           스트링에서 콤마(,)를 제거한다.
+ * <pre>
+ *     "-123,456,789.123".removeComma();
+ * </pre>
+ * @return : 콤마(,)가 제거된 스트링
+ * @author : gagamel
+ */
+String.prototype.removeComma = function() {
+	return this.replace(/,/gi,"");
+}

+ 223 - 0
src/main/webapp/ux/plugins/gaga/gaga.paging.js

@@ -0,0 +1,223 @@
+/*
+ * Pagination Common Java Script written by gagamel.
+ *
+ * Copyright (c) 2019 gagamel
+ * Dual licensed under GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2019-07-21 $
+ * 
+ * 사용 예)
+ * 		// HTML 태그는 다음과 같은 구조로 되어 있어야 한다.
+ * 		<div class="tablePaging" id="pagination">
+ * 			<a href="#pageNo=1">1</a>
+ * 			<a href="#pageNo=2">2</a>
+ * 			...
+ * 		</div>
+ * 
+ * 		// Import할 자바스크립트 파일
+ * 		<script type="text/javascript" src="/ux/plugins/gaga/gaga.paging.js"></script>
+ * 
+ * 		<script type="text/javascript">
+ * 			// Initialize a pagination
+ * 			gagaPaging.init('searchForm', fnSearchGoodsQnaCallback, 'pagination');
+ * 			
+ *			// Load data
+ * 			gagaPaging.load($('#searchForm input[name=pageNo]').val(), $('#searchForm select[name=pageSize]').val());
+ * 
+ * 			var fnSearchGoodsQnaCallback = function(result) {
+ * 				// Handle Data
+ * 				...
+ * 				
+ * 				// Create pagination
+ * 				gagaPaging.createPagination(result.goodsAsk.pageable);
+ * 			}
+ *		</script>
+ */
+
+var gagaPaging = {
+
+	oFormId : '',
+	oCallbackFn : '',
+	oPaginationId : '',
+	nPageSize : 50,
+	nPageUnit : 10,
+	
+	/**
+	 * Initialize a pagination
+	 * @param formId - Form ID. 검색조건 폼 ID
+	 * @param callbackFn - Callback function. 데이터 조회 후 처리하는 콜백함수
+	 * @param paginationId - Pagination ID. 페이징을 구성하는 div 태그 ID
+	 * @param pageSize - 조회할 데이터 row수. 옵션
+	 * @param pageUnit - 그룹핑 페이지 단위. 옵션
+	 * 사용 예)
+	 * 		// Initialize a pagination
+	 * 		gagaPaging.init('searchForm', fnSearchGoodsQnaCallback, 'pagination');
+	 * 		or
+	 * 		gagaPaging.init('searchForm', fnSearchGoodsQnaCallback, 'pagination', 50);
+	 * 		or
+	 * 		gagaPaging.init('searchForm', fnSearchGoodsQnaCallback, 'pagination', 50, 10);
+	 */
+	init : function(formId, callbackFn, paginationId, pageSize, pageUnit) {
+		oFormId = formId;
+		oCallbackFn = callbackFn;
+		oPaginationId = paginationId;
+		if (typeof(pageSize) != 'undefined') nPageSize = pageSize;
+		if (typeof(pageUnit) != 'undefined') nPageUnit = pageUnit;
+	},
+	
+	/**
+	 * Create a pagination
+	 * @param pageable - page 정보
+	 */
+	createPagination : function(pageable) {
+		// Generate pagination
+		var html;
+		if (gagajf.isNull(pageable.generatedPagination)) {
+			html = gagaPaging.generatedPagination(pageable);
+		} else {
+			html = pageable.generatedPagination;
+		}
+		$('#' + oPaginationId).html(html);
+		// Bind event
+		gagaPaging.bind();
+	},
+	
+	/**
+	 * Bind the pagination's event
+	 * Paging 처리 시 다음과 같이 지정
+	 * 사용 예)
+	 * 		// HTML 태그는 다음과 같은 구조로 되어 있어야 한다.
+	 * 		<div class="tablePaging" id="pagination">
+	 * 			<a href="#pageNo=1">1</a>
+	 * 			<a href="#pageNo=2">2</a>
+	 * 			...
+	 * 		</div>
+	 */
+	bind : function() {
+		$('#' + oPaginationId + ' a').on('click', function(e) {
+			var params = $(this).attr('href');
+			params = params.replace(/^.*#/, '');
+			
+			var pageNo = 1;
+			
+			if (!gagajf.isNull(params)) {
+				pageNo = params.split("=")[1];
+			}
+			
+			gagaPaging.load(pageNo);
+			
+			return false;
+		});
+	},
+	
+	/**
+	 * Load data and call a callback function
+	 * JSON 형태로 보내고 받는 후 콜백함수에서 데이터를 처리한다.
+	 * @param pageNo - 조회할 페이지번호
+	 */
+	load : function(pageNo) {
+		$('#' + oFormId + ' input[name=pageNo]').val(pageNo);
+		$('#' + oFormId + ' input[name=pageSize]').val(nPageSize);
+		
+		// comma(,) 제거
+		gagajf.removeCommaAtNumberFormattedInput('#' + oFormId);
+		var jsonData = JSON.stringify($('#' + oFormId).serializeObject());
+		
+		$.ajax({
+			type : 'POST',
+			url : $('#' + oFormId).prop('action'),
+			data : jsonData,
+			dataType : 'JSON',
+			beforeSend : function(xhr, settings) {
+				// dataType: "json"일 때
+				xhr.setRequestHeader('Accept', 'application/json');
+				xhr.setRequestHeader('Content-Type', 'application/json');
+				
+				// Button disabled & progressBar creation
+				gagajf.showProgressbar(true);
+			},
+			complete : function() {
+				// Button abled & progressBar remove
+				gagajf.showProgressbar(false);
+			},
+			success : function(result) {
+				try {
+					if (!gagajf.isNull(result.error.message)) {
+						mcxDialog.alert(result.error.message);
+						return;
+					}
+				} catch(e) {
+					// Do nothing
+				}
+				
+				if (typeof(oCallbackFn) == 'function') {
+					oCallbackFn.call(this, result);
+				}
+			},
+			error : function(result) {
+				console.log(result);
+				mcxDialog.alert('오류로 인해 처리되지 않았습니다.');
+			}
+		});
+	},
+	
+	generatedPagination : function (pageable) {
+		let pageNo = pageable.pageNo;
+		let pageSize = pageable.pageSize;
+		let pageUnit = pageable.pageUnit;
+		let totalCount = pageable.totalCount;
+		let firstCount = (getPageGroup() - 1) * pageable.pageUnit + 1;
+		let loopCount = firstCount + pageUnit;
+		if (loopCount > getTotalPage()) {
+			loopCount = Number(getTotalPage() + 1);
+		}
+		
+		let pageTag = '';
+		if (!(firstCount == 1 && loopCount == 1)) {
+			if (pageNo == 1) {
+				pageTag += '<li class="disabled"><a href="#" alt="맨처음">«</a></li>\n';
+			} else {
+				pageTag += '<li><a href="#pageNo=1" alt="맨처음">«</a></li>\n';
+			}
+
+			if (getPageGroup() == 1) {
+				pageTag += '<li class="prev disabled"><a href="#" alt="이전페이지">‹</a></li>\n';
+			} else {
+				pageTag += '<li class="prev"><a href="#pageNo=' + (getPageGroup()-1) * pageUnit + '" alt="이전페이지">‹</a></li>\n';
+			}
+
+			for (let i = firstCount; i < loopCount; i++) {
+				if (pageNo == i) {
+					pageTag += '<li class="active"><a href="#">' + i + '</a></li>\n';
+				} else {
+					pageTag += '<li><a href="#pageNo=' + i + '">' + i + '</a></li>\n';
+				}
+			}
+			
+			if (loopCount <= (Number(getTotalPage() + 1))) {
+				if (getTotalPage() > loopCount) {
+					pageTag += '<li class="next"><a href="#pageNo=' + (getPageGroup() * pageUnit + 1) + '" alt="다음페이지">›</a></li>\n';
+				} else {
+					pageTag += '<li class="next"><a href="#pageNo=' + getTotalPage + '" alt="다음페이지">›</a></li>\n';
+				}
+				pageTag += '<li><a href="#pageNo=' + getTotalPage() + '" alt="맨마지막">»</a></li>\n';
+			}
+		}
+
+		function getPageGroup() {
+			return parseInt((pageNo-1) / pageUnit + 1 );
+		}
+
+		function getTotalPage() {
+			let totalPage = parseInt(totalCount / pageSize);
+			if (totalCount % pageSize > 0) {
+				totalPage++;
+			}
+			return totalPage;
+		}
+
+		return pageTag;
+	}
+
+}
+

+ 1198 - 0
src/main/webapp/ux/plugins/gaga/gaga.validation.js

@@ -0,0 +1,1198 @@
+/*
+ * Form Validation Java Script written by gagamel
+ *
+ * Copyright (c) 2017 gagamel
+ * Dual licensed under GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2017-09-20 $
+ * $Modify: 2019-03-07 $
+ *
+ * Using)
+ * 		1. Add "data-valid-type" and "data-valid-name" attribute to Elements of form
+ * 			ex) <input type="text" name="userNm" data-valid-type="alpahNumeric" data-valid-name="User Name"/>
+ *
+ * 		2. data-valid-type
+ * 			numeric, alphaNumeric, email, cellPhone, ipAddress
+ *
+ * 		3. When submit a form, call "validation()" function.
+ * 			ex)
+ * 				if (!$('#aForm').validation())
+ * 					return;
+ */
+(function($) {
+	/**
+	 * Spring Security를 사용하는 경우 Default로 CSRF(Cross Site Request Forgery)가 활성화 되어 있다.
+	 * 이 때문에 $.ajax 함수를 호출 시 404 에러가 발생한다. 이는 다음과 같이 해결한다.
+	 *
+	 * 		1. SecurityConfig에 csrf().disable() 설정. <= CSRF(Cross Site Request Forgery) 해제
+	 * 		또는
+	 * 		2. Thymeleaf에서는 csrf 토큰이 hidden input에 자동으로 추가되어 있음으로 아래와 같이 ajax 호출 시 토큰을 Header에 설정한다.
+	 */
+	/*var token = $("meta[name='_csrf']").attr("content");
+	var header = $("meta[name='_csrf_header']").attr("content");
+	$.ajaxSend(function(e, xhr, options) {
+		xhr.setRequestHeader(header, token);
+	});*/
+});
+
+var gagajf = {
+	/**
+	 * @type   : function
+	 * @access : public
+	 * @desc   : 값이 null 이거나 white space 문자로만 이루어진 경우 true를 리턴한다.
+	 * <pre>
+	 *     gagajf.isNull("  ");
+	 * </pre>
+	 * 위와같이 사용했을 경우 true를 리턴한다.
+	 * @param  : value - 필수 입력 값
+	 * @return : boolean. null(혹은 white space) 여부
+	 * @author : gagamel
+	 */
+	isNull : function(value) {
+		if (value == null || (typeof(value) == "string" && value.trim() == ""))
+			return true;
+
+		return false;
+	},
+
+	/**
+	 * @type   : function
+	 * @access : public
+	 * @desc   : 값이 null str로 true를 리턴한다.
+	 * <pre>
+	 *     gagajf.convNull(item.value, '');
+	 * </pre>
+	 * 위와같이 사용했을 경우 item.value 가 null일경우 ''을 리턴한다.
+	 * @param  : value - 필수 입력 값
+	 * @param  : str - 필수 입력 값
+	 * @return : value or str
+	 * @author : gagamel
+	 */
+	convNull : function(value, str) {
+		if (value == null)
+			return str;
+
+		return value;
+	},
+
+	/**
+	 * 유효한 이벤트 키코드인지 체크
+	 * @return : 유효한 이벤트 키코드이면 키코드 값, 아니면 -1
+	 * @since  : 2017/09/20
+	 * @author : gagamel
+	 */
+	getKeyCode : function() {
+		// 이벤트 객체와 문자 코드를 호환 가능한 방식으로 얻는다.
+		var e = event || window.event; // 키 이벤트 객체
+		var keyCode = e.charCode || e.keyCode; // 어떤 키가 눌러졌는가?
+//		console.log('keyCode: ' + keyCode);
+
+		// Ctrl 키나 Alt 키, ASCII 제어문자, 화살표 등 skip
+		if (e.ctrlKey || e.altkey || keyCode < 47) {
+			return -1;
+		}
+
+		return keyCode;
+	},
+
+	/**
+	 * 값이 정규표현식에 부합하는지는 체크한다.
+	 * @param  : el - 엘리먼트
+	 * @param  : regexp - 정규표현식
+	 * @param  : type - 엘리먼트 type
+	 * @return : 부합하는 경우 true, 그 외 false
+	 * @since  : 2017/09/21
+	 * @author : gagamel
+	 */
+	testRegexp : function(el, regexp, type) {
+		var val = $(el).val();
+
+		if (type == 'integer' || type == 'real') {
+			// 콤마(,) 제거
+			val = val.removeComma();
+		}
+
+		if (!regexp.test(val)) {
+			mcxDialog.alertC($(el).data('validName') + '의 형식이 잘못되었습니다.', {
+				sureBtnText: "확인",
+				sureBtnClick: function() {
+					$(el).select();
+					$(el).focus();
+				}
+			});
+			return false;
+		}
+
+		return true;
+	},
+
+	/**
+	 * alert 메시지
+	 * @param  : el - 엘리먼트
+	 *           mgsType - 메시지유형(input, select)
+	 * @since  : 2017/09/21
+	 * @author : gagamel
+	 */
+	alertMessage : function(el, mgsType) {
+		var validNm = $(el).data('validName');
+
+		if (mgsType == 'input') {
+			mcxDialog.alertC(validNm + '을(를) 입력해 주세요.', {
+				sureBtnText: "확인",
+				sureBtnClick: function() {
+					$(el).focus();
+				}
+			});
+		} else if (mgsType == 'select') {
+			mcxDialog.alertC(validNm + '을(를) 선택해 주세요.', {
+				sureBtnText: "확인",
+				sureBtnClick: function() {
+					$(el).focus();
+				}
+			});
+		}
+	},
+
+	/**
+	 * 체크박스와 라디오버튼을 선택한 것이 있는지 체크한다.
+	 * @param  : el - 엘리먼트
+	 *           mgsType - 메시지유형(input, select)
+	 * @since  : 2017/09/21
+	 * @author : gagamel
+	 */
+	isCheckedCheckbox : function(el) {
+		$(el).each(function(idx) {
+			if ($(el).eq(idx).is(':checked')) {
+				return true;
+			} else {
+				return false;
+			}
+		});
+	},
+
+	/**
+	 * 비밀번호 체크
+	 * 		1.영문대문자, 영문소문자, 특수문자, 숫자로만 구성
+	 * 		2.이 중에 3가지 이상으로 구성 시 8자 이상, 2가지 이상으로 구성 시 10자 이상
+	 * @param  : el - 엘리먼트
+	 * @since  : 2017/09/21
+	 * @author : gagamel
+	 */
+	checkPassword : function(el) {
+		var passwd = $(el).val();
+		var cnt = 0;
+		if (/[a-z]{1,}/.test(passwd)) cnt++;
+		if (/[A-Z]{1,}/.test(passwd)) cnt++;
+		if (/[0-9]{1,}/.test(passwd)) cnt++;
+		if (/[\~,\!,\@,\#,\$,\%,\^,\&,\*,\(,\),\_,\?,\{,\},\[,\]]{1,}/.test(passwd)) cnt++;
+
+		if (cnt >= 3) {
+			if (passwd.length < 8) {
+				mcxDialog.alertC('3가지 이상으로 구성 시 8 자리 이상으로 입력해 주세요.', {
+					sureBtnText: "확인",
+					sureBtnClick: function() {
+						$(el).select();
+						$(el).focus();
+					}
+				});
+				return false;
+			}
+		} else if (cnt >= 2) {
+			if (passwd.length < 10) {
+				mcxDialog.alertC('2가지 이상으로 구성 시 10 자리 이상으로 입력해 주세요.', {
+					sureBtnText: "확인",
+					sureBtnClick: function() {
+						$(el).select();
+						$(el).focus();
+					}
+				});
+				return false;
+			}
+		} else {
+			mcxDialog.alertC('대/소문자, 특수문자, 숫자로 구성해 주세요.', {
+				sureBtnText: "확인",
+				sureBtnClick: function() {
+					$(el).select();
+					$(el).focus();
+				}
+			});
+			return false;
+		}
+
+		return true;
+	},
+
+	/**
+	 * 필수입력항목 엘리먼트를 체크해서 alert를 표시한다.
+	 */
+	checkRequired : function(oForm) {
+		var isInvalid = true;
+
+		$(oForm).find(':input').each(function(idx, el) {
+			if ($(el).attr('required') != 'required')
+				return true;
+
+			var type = $(el).attr('type');
+			if (!type) type = 'select';
+//			var msg = $(el).data('validName');
+
+			switch (type) {
+				case 'text':
+				case 'password':
+				case 'textarea':
+//				case 'select-one':
+					var value = $(el).val();
+					if (!gagajf.isNull(value))
+						return true;
+
+					gagajf.alertMessage($(el), 'input');
+					isInvalid = false;
+					return false;
+				case 'select':
+					var value = $(el).val();
+					if (!gagajf.isNull(value))
+						return true;
+
+					gagajf.alertMessage($(el), 'select');
+					isInvalid = false;
+					return false;
+				case 'checkbox':
+				case 'radio':
+					if (gagajf.isCheckedCheckbox($(el)))
+						return true;
+
+					gagajf.alertMessage($(el), 'select');
+					isInvalid = false;
+					return false;
+				case 'file':
+					var value = $(el).val();
+					if (!gagajf.isNull(value))
+						return true;
+
+					gagajf.alertMessage($(el), 'select');
+					isInvalid = false;
+					return false;
+			}
+		});
+
+		return isInvalid;
+	},
+
+	/**
+	 * 값이 형식에 맞는지 패턴을 체크한다.
+	 */
+	checkPattern : function(oForm) {
+		var isInvalid = true;
+
+		$(oForm).find('input').each(function(idx, el) {
+			if (gagajf.isNull($(el).val()))
+				return true;
+
+			var validType = $(el).data('validType');
+
+			// data-valid-type이 지정되지 않은 엘리먼트는 skip
+			if (!validType) return true;
+
+			// 값이 없으면 skip
+			if (gagajf.isNull($(el).val())) return true;
+
+			switch (validType) {
+				case 'numeric': // 숫자
+					if (gagajf.testRegexp($(el), /^[0-9]+$/))
+						return true;
+
+					isInvalid = false;
+					return false;
+				case 'integer': // 정수
+					if (gagajf.testRegexp($(el), /(^-?[0-9]+\d*$)|(^-$)/, 'integer'))
+						return true;
+
+					isInvalid = false;
+					return false;
+				case 'real': // 실수
+					if (gagajf.testRegexp($(el), /^-?(([0-9]+\.?)|(\.?))\d*$/, 'real'))
+						return true;
+
+					isInvalid = false;
+					return false;
+				case 'alphaNumeric': // 알파벳+숫자
+					if (gagajf.testRegexp($(el), /^[a-zA-Z0-9]+$/))
+						return true;
+
+					isInvalid = false;
+					return false;
+				case 'email': // 이메일
+					if (gagajf.testRegexp($(el), /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/))
+						return true;
+					isInvalid = false;
+					return false;
+				case 'password': // 이메일
+					if (gagajf.checkPassword($(el)))
+						return true;
+					isInvalid = false;
+					return false;
+				case 'cellPhone': // 휴대전화번호
+					if (gagajf.testRegexp($(el), /^(01(?:0|1|[6-9])-(?:\d{3}|\d{4})-\d{4})$/))
+						return true;
+
+					isInvalid = false;
+					return false;
+				case 'phone': // 일반전화번호
+					if (gagajf.testRegexp($(el), /^\d{2,3}-\d{3,4}-\d{4}$/))
+						return true;
+
+					isInvalid = false;
+					return false;
+				case 'ipAddress': // IP주소
+					if (gagajf.testRegexp($(el), /^(([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3}))$/))
+						return true;
+
+					isInvalid = false;
+					return false;
+			}
+		});
+
+		return isInvalid;
+	},
+
+	checkValue : function(oForm){
+		var isInvalid = true;
+
+		$(oForm).find('input').each(function(idx, el) {
+
+			var validType = $(el).data('validType');
+
+			// data-valid-type이 지정되지 않은 엘리먼트는 skip
+			if (!validType) return true;
+
+			// 값이 없으면 skip
+			if (gagajf.isNull($(el).val())) return true;
+
+			switch (validType) {
+				case 'numeric': // 숫자
+					//최대값
+					if ($(el).attr("max")) {
+						if ($(el).val() > $(el).attr("max")) {
+							mcxDialog.alertC($(el).data('validName') + '은(는) 최대 ' + $(el).attr("max") + '보다 작아야 합니다.', {
+								sureBtnText: "확인",
+								sureBtnClick: function() {
+									$(el).focus();
+								}
+							});
+							isInvalid = false;
+						}
+					}
+					//최소값
+					if ($(el).attr("min")) {
+						if ($(el).val() < $(el).attr("min")) {
+							mcxDialog.alertC($(el).data('validName') + '은(는) 최소 ' + $(el).attr("min") + '보다 커야 합니다.', {
+								sureBtnText: "확인",
+								sureBtnClick: function() {
+									$(el).focus();
+								}
+							});
+							isInvalid = false;
+						}
+					}
+
+				case 'integer': // 정수
+					//최대값
+					if ($(el).attr("max")) {
+						if ($(el).val() > $(el).attr("max")) {
+							mcxDialog.alertC($(el).data('validName') + '은(는) 최대 ' + $(el).attr("max") + '보다 작아야 합니다.', {
+								sureBtnText: "확인",
+								sureBtnClick: function() {
+									$(el).focus();
+								}
+							});
+							isInvalid = false;
+						}
+					}
+					//최소값
+					if ($(el).attr("min")) {
+						if ($(el).val() < $(el).attr("min")) {
+							mcxDialog.alertC($(el).data('validName') + '은(는) 최소 ' + $(el).attr("min") + '보다 커야 합니다.', {
+								sureBtnText: "확인",
+								sureBtnClick: function() {
+									$(el).focus();
+								}
+							});
+							isInvalid = false;
+						}
+					}
+
+				case 'real': // 실수
+					//최대값
+					if ($(el).attr("max")) {
+						if ($(el).val() > $(el).attr("max")) {
+							mcxDialog.alertC($(el).data('validName') + '은(는) 최대 ' + $(el).attr("max") + '보다 작아야 합니다.', {
+								sureBtnText: "확인",
+								sureBtnClick: function() {
+									$(el).focus();
+								}
+							});
+							isInvalid = false;
+						}
+					}
+					//최소값
+					if ($(el).attr("min")) {
+						if ($(el).val() < $(el).attr("min")) {
+							mcxDialog.alertC($(el).data('validName') + '은(는) 최소 ' + $(el).attr("min") + '보다 커야 합니다.', {
+								sureBtnText: "확인",
+								sureBtnClick: function() {
+									$(el).focus();
+								}
+							});
+							isInvalid = false;
+						}
+					}
+			}
+		});
+		
+		return isInvalid;
+	},
+
+	/**
+	 * form을 validation 한다.
+	 * 예)
+	 * 		if (gagajf.validation('#registerForm');
+	 */
+	validation : function(formId) {
+		var $form = $(formId);
+
+		if (!this.checkRequired($form))
+			return false;
+
+		if (!this.checkPattern($form))
+			return false;
+
+		if(!this.checkValue($form))
+			return false;
+
+		return true;
+	},
+
+	/**
+	 * formId의 input의 data-valid-type이 integer, real인 경우에 값에 comma(,)를 자동으로 붙여 표시한다.
+	 * 사용) gagajf.addCommaAtNumberFormattedInput('#registerForm');
+	 */
+	addCommaAtNumberFormattedInput : function(formId) {
+		$(formId).find('input').each(function(idx, el) {
+			if ($(el).data('validType') == 'integer' || $(el).data('validType') == 'real') {
+				$(el).val($(el).val().removeComma().addComma());
+			}
+		});
+	},
+
+	/**
+	 * formId의 input의 data-valid-type이 integer, real, numeric 인 경우에 값에 comma(,)를 자동으로 제거한다.
+	 * 사용) gagajf.removeCommaAtNumberFormattedInput('#registerForm');
+	 */
+	removeCommaAtNumberFormattedInput : function(formId) {
+		$(formId).find('input').each(function(idx, el) {
+			if ($(el).data('validType') == 'integer' || $(el).data('validType') == 'real' || $(el).data('validType') == 'numeric') {
+				$(el).val($(el).val().removeComma());
+			}
+		});
+	},
+
+	/**
+	 * Progress bar
+	 */
+	showProgressbar : function(isLoading) {
+		if (isLoading) {
+			// Button disabled & progressBar creation
+			//$('.btn').each(function(idx) { $(this).attr('disabled', true); });
+			var load_AjaxSubmit = '<div id="load_AjaxSubmit" style="'
+				+ 'background: url(/ux/plugins/gaga/loader.gif); border-style: none; background-repeat: no-repeat; '
+				+ 'position: absolute; top: 45%; left: 50%; width: auto; '
+				+ 'z-index: 101; padding: 16px; margin: 5px;'
+				+ '"></div>';
+			$('#content').append(load_AjaxSubmit);
+		} else {
+			// Button activated & progressBar remove
+			//$('.btn').each(function(idx) { $(this).attr('disabled', false); });
+			$('#load_AjaxSubmit').remove();
+		}
+	},
+
+	/**
+	 * form의 데이터를 json으로 변환 후 ajax 방식으로 submit 한다.
+	 * 모든 form의 ajax 처리는 이것으로 진행한다.
+	 * <pre>
+	 *     ajaxFormSubmit('/rest/commoncode/create', '#registerForm', jfRegisterSaveCallback);
+	 * </pre>
+	 * @param actionUrl - Request URL
+	 * @param formId - form ID
+	 * @param callbackFn - Callback function
+	 * @author gagamel
+	 * @since 2019. 4. 8
+	 */
+	ajaxFormSubmit : function(actionUrl, formId, callbackFn) {
+		// comma(,) 제거
+		gagajf.removeCommaAtNumberFormattedInput(formId);
+
+		var jsonData = JSON.stringify($(formId).serializeObject());
+		
+		$.ajax({
+			type : 'POST',
+			url : actionUrl,
+			data : jsonData,
+			dataType : 'json',
+			beforeSend : function(xhr, settings) {
+				// AJAX call
+				xhr.setRequestHeader("AJAX", "true");
+
+				// dataType: "json"일 때
+				xhr.setRequestHeader('Accept', 'application/json');
+				xhr.setRequestHeader('Content-Type', 'application/json');
+
+				// Button disabled & progressBar creation
+				gagajf.showProgressbar(true);
+			},
+			complete : function(xhr) {
+				// Button abled & progressBar remove
+				gagajf.showProgressbar(false);
+
+				// 세션이 없다. 로그인 페이지로 이동
+				if (xhr.status == 901) {
+					mcxDialog.alertC('세션이 없습니다. 로그인 페이지로 이동합니다.', {
+						sureBtnText: "확인",
+						sureBtnClick: function() {
+							document.location.href = "/error/noSession";
+						}
+					});
+				}
+			},
+			success : function(result) {
+				if (typeof(result.status) == 'undefined' || result.status == 200) { // 성공
+					if (!gagajf.isNull(result.message)) {
+						mcxDialog.alertC(result.message, {
+							sureBtnText: "확인",
+							sureBtnClick: function() {
+								if (typeof(callbackFn) == "function") {
+									callbackFn.call(this, result);
+								}
+							}
+						});
+					} else {
+						if (typeof(callbackFn) == "function") {
+							callbackFn.call(this, result);
+						}
+					}
+				} else { // 실패
+					if (!gagajf.isNull(result.error.message)) {
+						mcxDialog.alert(result.error.message);
+					}
+
+					return;
+				}
+			},
+			error : function(result) {
+				console.log(result);
+				mcxDialog.alert('오류로 인해 처리되지 않았습니다.');
+			}
+		});
+	},
+
+	/**
+	 * json 데이터를 가지고 ajax 방식으로 submit 한다.
+	 * 모든 ajax 처리는 이것으로 진행한다.
+	 * <pre>
+	 *     gagajf.removeCommaAtNumberFormattedInput('#registerForm'); // comma(,) 제거
+	 *     var jsonData = JSON.stringify($('#registerForm').serializeObject());
+	 *     gagajf.ajaxJsonSubmit('/rest/commoncode/create', jsonData, jfRegisterSaveCallback);
+	 * </pre>
+	 * @param actionUrl - Request URL
+	 * @param jsonData - Data of json format
+	 * @param callbackFn - Callback function
+	 * @author gagamel
+	 * @since 2019. 4. 8
+	 */
+	ajaxJsonSubmit : function(actionUrl, jsonData, callbackFn) {
+		$.ajax({
+			type : 'POST',
+			url : actionUrl,
+			data : jsonData,
+			dataType : 'json',
+			beforeSend : function(xhr, settings) {
+				// AJAX call
+				xhr.setRequestHeader("AJAX", "true");
+
+				// dataType: "json"일 때
+				xhr.setRequestHeader('Accept', 'application/json');
+				xhr.setRequestHeader('Content-Type', 'application/json');
+
+				// Button disabled & progressBar creation
+				gagajf.showProgressbar(true);
+			},
+			complete : function(xhr) {
+				// Button abled & progressBar remove
+				gagajf.showProgressbar(false);
+
+				// 세션이 없다. 로그인 페이지로 이동
+				if (xhr.status == 901) {
+					mcxDialog.alertC('세션이 없습니다. 로그인 페이지로 이동합니다.', {
+						sureBtnText: "확인",
+						sureBtnClick: function() {
+							document.location.href = "/error/noSession";
+						}
+					});
+				}
+			},
+			success : function(result) {
+				if (typeof(result.status) == 'undefined' || result.status == 200) { // 성공
+					if (!gagajf.isNull(result.message)) {
+						mcxDialog.alertC(result.message, {
+							sureBtnText: "확인",
+							sureBtnClick: function() {
+								if (typeof(callbackFn) == "function") {
+									callbackFn.call(this, result);
+								}
+							}
+						});
+					} else {
+						if (typeof(callbackFn) == "function") {
+							callbackFn.call(this, result);
+						}
+					}
+				} else { // 실패
+					if (!gagajf.isNull(result.error.message)) {
+						mcxDialog.alert(result.error.message);
+					}
+
+					return;
+				}
+			},
+			error : function(result) {
+				console.log(result);
+				mcxDialog.alert('오류로 인해 처리되지 않았습니다.');
+			}
+		});
+	},
+
+	/**
+	 * ajax 방식으로 파일을 업로드 한다.
+	 * <pre>
+	 *     gagajf.ajaxFileUpload('/common/file/upload?subDir=notice', this.files[0], jfCallback);
+	 * </pre>
+	 * @param actionUrl - Request URL
+	 * @param file - A file to upload
+	 * @param callbackFn - Callback function
+	 * @param policy - Upload policy
+	 * @author gagamel
+	 * @since 2019. 7. 9
+	 */
+	ajaxFileUpload : function(actionUrl, file, callbackFn, policy) {
+		var formData = new FormData();
+		formData.append("file", file);
+
+		if (typeof policy != 'undefined') {
+			formData.append("policy", policy);
+		}
+
+		$.ajax({
+			type : 'POST',
+			url : actionUrl,
+			data : formData,
+			dataType: 'json',
+			processData : false, // true: data의 파일 형태가 query String으로 전송. false : non-processed data
+			contentType : false, // multipart/form-data 형태로 전송되기 위한 옵션 값
+			beforeSend : function(xhr, settings) {
+				// AJAX call
+				xhr.setRequestHeader("AJAX", "true");
+
+				// Button disabled & progressBar creation
+				gagajf.showProgressbar(true);
+			},
+			complete : function(xhr) {
+				// Button abled & progressBar remove
+				gagajf.showProgressbar(false);
+
+				// 세션이 없다. 로그인 페이지로 이동
+				if (xhr.status == 901) {
+					mcxDialog.alertC('세션이 없습니다. 로그인 페이지로 이동합니다.', {
+						sureBtnText: "확인",
+						sureBtnClick: function() {
+							document.location.href = "/error/noSession";
+						}
+					});
+				}
+			},
+			success : function(result) {
+				if (typeof(result.status) == 'undefined' || result.status == 200) { // 성공
+					if (!gagajf.isNull(result.message)) {
+						mcxDialog.alertC(result.message, {
+							sureBtnText: "확인",
+							sureBtnClick: function() {
+								if (typeof(callbackFn) == "function") {
+									callbackFn.call(this, result);
+								}
+							}
+						});
+					} else {
+						if (typeof(callbackFn) == "function") {
+							callbackFn.call(this, result);
+						}
+					}
+				} else { // 실패
+					if (!gagajf.isNull(result.error.message)) {
+						mcxDialog.alert(result.error.message);
+					}
+
+					return;
+				}
+			},
+			error: function(result) {
+				console.log(result);
+				mcxDialog.alert('오류로 인해 처리되지 않았습니다.');
+			}
+		});
+	},
+
+	/**
+	 * 대용량 json 데이터를 가지고 ajax 방식으로 submit 한다.
+	 * <pre>
+	 *     gagajf.removeCommaAtNumberFormattedInput('#registerForm'); // comma(,) 제거
+	 *     var jsonData = JSON.stringify($('#registerForm').serializeObject());
+	 *     gagajf.ajaxJsonBatchSubmit('/rest/commoncode/create', jsonData, 1, 3, jfRegisterSaveCallback);
+	 * </pre>
+	 * @param actionUrl - Request URL
+	 * @param jsonData - Data of json format
+	 * @param callIdx - 호출인덱스(실제 호출한 횟수)
+	 * @param callCnt - 호출해야할횟수(몇 번 호출해야 하는지)
+	 * @param callbackFn - Callback function
+	 * @author gagamel
+	 * @since 2019. 4. 8
+	 */
+	ajaxJsonBatchSubmit : function(actionUrl, jsonData, callIdx, callCnt, callbackFn) {
+		$.ajax({
+			type : 'POST',
+			url : actionUrl,
+			data : jsonData,
+			dataType : 'json',
+			beforeSend : function(xhr, settings) {
+				// AJAX call
+				xhr.setRequestHeader("AJAX", "true");
+
+				// dataType: "json"일 때
+				xhr.setRequestHeader('Accept', 'application/json');
+				xhr.setRequestHeader('Content-Type', 'application/json');
+
+				// Button disabled & progressBar creation
+				if (callIdx == 1) { // 첫번째 호출이면
+					gagajf.showProgressbar(true);
+				}
+			},
+			complete : function(xhr) {
+				// Button abled & progressBar remove
+				if (callIdx == callCnt) { // 마지막 호출이면
+					gagajf.showProgressbar(false);
+				}
+
+				// 세션이 없다. 로그인 페이지로 이동
+				if (xhr.status == 901) {
+					mcxDialog.alertC('세션이 없습니다. 로그인 페이지로 이동합니다.', {
+						sureBtnText: "확인",
+						sureBtnClick: function() {
+							document.location.href = "/error/noSession";
+						}
+					});
+				}
+			},
+			success : function(result) {
+				if (callIdx == callCnt) { // 마지막 호출이면
+					mcxDialog.alertC('성공적으로 처리되었습니다.', {
+						sureBtnText: "확인",
+						sureBtnClick: function() {
+							if (typeof(callbackFn) == "function") {
+								callbackFn.call(this, result);
+							}
+						}
+					});
+				} else {
+					if (typeof(callbackFn) == "function") {
+						callbackFn.call(this, result);
+					}
+				}
+			},
+			error : function(result) {
+				console.log(result);
+				mcxDialog.alert('오류로 인해 처리되지 않았습니다.');
+			}
+		});
+	},
+
+	/**
+	 * JQuery를 이용한 비동기 submit 처리
+	 * 파라미터의 명칭은 쿼리문과 동일하게 작성해야 한다.
+	 * <pre>
+	 *     var params = new Object();
+	 *     params.cdGb = "G900";
+	 *     params.cd = "0202";
+	 *
+	 *     gagajf.ajaxSubmit("/rest/commoncode/create", "json", jfCallback, params);
+	 *
+	 *     or
+	 *
+	 *     gagajf.ajaxSubmit("/rest/commoncode/create", "json", jfCallback);
+	 * </pre>
+	 * @param  : actionUrl - action url. 필수
+	 *           type - 처리결과 형식(text, html, xml, json). 필수
+	 *           callback - type이 text, xml, json 일 때는 콜백함수명
+	 *                      type이 html일 때는 target명. 필수
+	 *           params - 파라미터 오브젝트. 옵션
+	 * @author gagamel
+	 * @since 2019. 4. 8
+	 */
+	ajaxSubmit : function(actionUrl, type, callback, params) {
+		$.ajaxSetup({
+			beforeSend: function(xhr, settings) {
+				// AJAX call
+				xhr.setRequestHeader("AJAX", "true");
+
+				// type: "json"일 때
+				if (type == "json") {
+					xhr.setRequestHeader('Accept', 'application/json');
+					xhr.setRequestHeader('Content-Type', 'application/json');
+				}
+			},
+			complete: function(xhr) {
+				// 세션이 없다. 로그인 페이지로 이동
+				if (xhr.status == 901) {
+					mcxDialog.alertC('세션이 없습니다. 로그인 페이지로 이동합니다.', {
+						sureBtnText: "확인",
+						sureBtnClick: function() {
+							document.location.href = "/error/noSession";
+						}
+					});
+				}
+			}
+		});
+
+		if (!params) params = new Object();
+
+		var paramData = $.param(params);
+
+		// dataType: "json"일 때
+		if (type == "json") {
+			paramData = JSON.stringify(params);
+		}
+
+		$.post(actionUrl
+			, paramData
+			, function(result) {
+				if (type == "html") {
+					if (!gagajf.isNull(callback))
+						$(document.getElementById(callback)).html(result);
+				} else {
+					// Callback 함수 호출
+					if (typeof(callback) == "function")
+						callback.call(this, result);
+				}
+			}
+			, type);
+	},
+
+	/**
+	 * @type   : function
+	 * @access : public
+	 * @desc   : 기간의 시작일자와 종료일자를 설정한다.
+	 * <pre>
+	 *     gagajf.setDate($('#sellStdt'), $('#sellEddt'), 't');
+	 * </pre>
+	 * @param  : fromObj - 시작일자 오브젝트
+	 * @param  : toObj - 종료일자 오브젝트
+	 * @param  : type - 유형(오늘: t, 어제: y, 최근한주: 7d, 이번주: tw, 지난주: pw, 최근한달: 1m, 이번달: tm, 지난달: pm, 최근3개월: 3m
+	 * @since  : 2019/08/09
+	 * @author : gagamel
+	 */
+	setDate : function(tgtId, fromObj, toObj, type) {
+		var date = new Date();
+
+		if (type == '') { // 기간 X
+			$(tgtId +' #' + fromObj).val('');
+			$(tgtId +' #' + toObj).val('');
+		} else if (type == 't') { // 오늘
+			$(tgtId +' #' + fromObj).val(date.format("YYYY-MM-DD"));
+			$(tgtId +' #' + toObj).val(date.format("YYYY-MM-DD"));
+		} else if (type == 'y') { // 어제
+			$(tgtId +' #' + fromObj).val(date.before(0, 0, 1).format("YYYY-MM-DD"));
+			$(tgtId +' #' + toObj).val(date.before(0, 0, 1).format("YYYY-MM-DD"));
+		} else if (type == '7d') { // 최근한주
+			$(tgtId +' #' + fromObj).val(date.before(0, 0, 6).format("YYYY-MM-DD"));
+			$(tgtId +' #' + toObj).val(date.format("YYYY-MM-DD"));
+		} else if (type == 'tw') { // 이번주
+			var wdays = date.getDate() - date.getDay();
+			$(tgtId +' #' + fromObj).val((date.format('YYYY-MM-') + '01').toDate('YYYY-MM-DD').after(0, 0, wdays).format("YYYY-MM-DD"));
+			$(tgtId +' #' + toObj).val((date.format('YYYY-MM-') + '01').toDate('YYYY-MM-DD').after(0, 0, wdays + 6).format("YYYY-MM-DD"));
+		} else if (type == 'pw') { // 지난주
+			var wdays = date.getDate() - date.getDay();
+			$(tgtId +' #' + fromObj).val((date.format('YYYY-MM-') + '01').toDate('YYYY-MM-DD').after(0, 0, wdays - 7).format("YYYY-MM-DD"));
+			$(tgtId +' #' + toObj).val((date.format('YYYY-MM-') + '01').toDate('YYYY-MM-DD').after(0, 0, wdays - 1).format("YYYY-MM-DD"));
+		} else if (type == '1m') { // 최근한달
+			$(tgtId +' #' + fromObj).val(date.before(0, 1, 0).after(0, 0, 1).format("YYYY-MM-DD"));
+			$(tgtId +' #' + toObj).val(date.format("YYYY-MM-DD"));
+		} else if (type == 'tm') { // 이번달
+			$(tgtId +' #' + fromObj).val(date.format("YYYY-MM-") + '01');
+			$(tgtId +' #' + toObj).val((date.format('YYYY-MM-') + '01').toDate('YYYY-MM-DD').after(0, 1, 0).before(0, 0, 1).format("YYYY-MM-DD"));
+		} else if (type == 'pm') { // 지난달
+			$(tgtId +' #' + fromObj).val(date.before(0, 1, 0).format("YYYY-MM-")  + '01');
+			$(tgtId +' #' + toObj).val((date.format('YYYY-MM-') + '01').toDate('YYYY-MM-DD').before(0, 0, 1).format("YYYY-MM-DD"));
+		} else if (type == '3m') { // 최근3개월
+			$(tgtId +' #' + fromObj).val(date.before(0, 3, 0).after(0, 0, 1).format("YYYY-MM-DD"));
+			$(tgtId +' #' + toObj).val(date.format("YYYY-MM-DD"));
+		}
+	},
+
+	/**
+	 * @type   : function
+	 * @access : public
+	 * @desc   : Set Cookie
+	 * <pre>
+	 *     gagajf.setCookie("COOKIE_TODAY_PROD", "HUE00C105GE", 1);
+	 * </pre>
+	 * @param  : name - 쿠키명
+	 * @param  : value - 쿠키 값
+	 * @param  : expiredays - 만료기간
+	 * @return : None
+	 * @since  : 2019/07/01
+	 * @author : gagamel
+	 */
+	setCookie : function(name, value, expiredays) {
+		var todayDate = new Date();
+		todayDate.setDate(todayDate.getDate() + expiredays);
+		document.cookie = name + "=" + escape(value) + "; path=/; expires=" + todayDate.toGMTString() + ";";
+	},
+
+	/**
+	 * @type   : function
+	 * @access : public
+	 * @desc   : Get Cookie
+	 * <pre>
+	 *     gagajf.getCookie("COOKIE_TODAY_PROD");
+	 * </pre>
+	 * @param  : name - 쿠키명
+	 * @return : None
+	 * @since  : 2019/07/01
+	 * @author : gagamel
+	 */
+	getCookie : function(name) {
+		var nameOfCookie = name + "=";
+		var x = 0;
+		while (x <= document.cookie.length) {
+			var y = (x+nameOfCookie.length);
+			if (document.cookie.substring(x, y) == nameOfCookie) {
+				if ((endOfCookie=document.cookie.indexOf(";", y)) == -1) endOfCookie = document.cookie.length;
+				return unescape(document.cookie.substring(y, endOfCookie));
+			}
+			x = document.cookie.indexOf(" ", x) + 1;
+			if (x == 0) break;
+		}
+
+		return "";
+	},
+	
+	/**
+	 * 데이터를 배열로 변환
+	 * 예)
+	 * 		convertToArray({cd: "KNE", cdNm: "KNE"});
+	 * @param  : data - 데이터
+	 * @param  : isCodeDisplay - 코드표시여부(true/false). default false
+	 * @author : gagamel
+	 * @since  : 2019. 6. 7
+	 */
+	convertToArray : function(data, isCodeDisplay) {
+		if (data.length == 0)
+			return [];
+
+		if (typeof(isCodeDisplay) == 'undefined')
+			isCodeDisplay = false;
+
+		var arrValue = {};
+
+		$.each(data, function(idx, item) {
+			arrValue[item.cd] = (isCodeDisplay ? '[' + item.cd + '] ' : '') + item.cdNm;
+		});
+
+		return arrValue;
+	}
+};
+
+/**
+ * @type   : function
+ * @access : document
+ * @desc   : <input> 태그에 대한 키눌림에 대해 validation을 체크한다.
+ *           data-valid-type="numeric" : 숫자. 속성 지정시 숫자만 입력 가능
+ *           data-valid-type="integer" : 정수. 속성 지정시 숫자와 +, - 만 입력 가능
+ *           data-valid-type="real" : 실수. 속성 지정시 숫자와 +, -, . 만 입력 가능
+ *           data-valid-type="alphaNumeric" : 알파벳과 숫자. 속성 지정 시 영문과 숫자만 형식에 맞게 입력 가능
+ *           data-valid-type="date" : 숫자와 / 만 입력 가능
+ *           data-valid-type="korean" : 한글. 속성 지정 시 한글만 형식에 맞게 입력 가능
+ *           data-valid-type="email" : 이메일
+ *           data-valid-type="password" : 비밀번호
+ *           data-valid-type="cellPhone" : 휴대전화번호
+ *           data-valid-type="phone" : 일반전화번호
+ *           data-valid-type="ipAddress" : IP주소
+ *           data-valid-type="bizRegNo" : 사업자등록번호
+ * <pre>
+ *     <input type="text" data-valid-type="numeric" />
+ *     <input type="text" data-valid-type="integer" />
+ *     <input type="text" data-valid-type="real" />
+ *     <input type="text" data-valid-type="alphaNumeric" />
+ *     <input type="text" data-valid-type="date" />
+ *     <input type="text" data-valid-type="korean" />
+ *     <input type="text" data-valid-type="email" />
+ *     <input type="text" data-valid-type="password" />
+ *     <input type="text" data-valid-type="cellPhone" />
+ *     <input type="text" data-valid-type="phone" />
+ *     <input type="text" data-valid-type="ipAddress" />
+ *     <input type="text" data-valid-type="bizRegNo" />
+ * </pre>
+ * @author : gagamel
+ * @since  : 2017/09/20
+ */
+$(document).on("keyup", "[data-valid-type=numeric]", function() { $(this).val($(this).val().replace(/[^0-9]/gi,"")); });
+$(document).on("keydown", "[data-valid-type=numeric]", function() {
+	var value = $(this).val();
+
+	var keyCode = gagajf.getKeyCode();
+	if (keyCode == -1)
+		return true;
+
+	if (!((keyCode >= 48 && keyCode <= 57 && !event.shiftKey) // 0 ~ 9
+		|| (keyCode >= 96 && keyCode <= 105) // 0 ~ 9 (Num Lock)
+		)) {
+		$(this).val(value);
+		event.returnValue = false;
+	}
+});
+$(document).on("blur", "[data-valid-type=integer]", function() { $(this).val($(this).val().removeComma().addComma()); });
+$(document).on("click", "[data-valid-type=integer]", function() { $(this).val($(this).val().removeComma()); });
+$(document).on("keyup", "[data-valid-type=integer]", function() { $(this).val($(this).val().replace(/[^0-9-\+]/gi,"")); });
+$(document).on("keydown", "[data-valid-type=integer]", function() {
+	var value = $(this).val();
+
+	var keyCode = gagajf.getKeyCode();
+	if (keyCode == -1)
+		return true;
+
+	if (!((keyCode >= 48 && keyCode <= 57 && !event.shiftKey) // 0 ~ 9
+		|| (keyCode >= 96 && keyCode <= 105) // 0 ~ 9 (Num Lock)
+		|| (keyCode == 187 && event.shiftKey) // Shift 하고 +
+		|| (keyCode == 107) // + (Num Lock)
+		|| (keyCode == 189 && !event.shiftKey) // Shift 없이 -
+		|| (keyCode == 109) // - (Num Lock)
+		)) {
+		$(this).val(value);
+		event.returnValue = false;
+	}
+});
+$(document).on("blur", "[data-valid-type=real]", function() { $(this).val($(this).val().removeComma().addComma()); });
+$(document).on("click", "[data-valid-type=real]", function() { $(this).val($(this).val().removeComma()); });
+$(document).on("keyup", "[data-valid-type=real]", function() { $(this).val($(this).val().replace(/[^0-9-\+\.]/gi,"")); });
+$(document).on("keydown", "[data-valid-type=real]", function() {
+	var value = $(this).val();
+
+	var keyCode = gagajf.getKeyCode();
+	if (keyCode == -1)
+		return true;
+
+	if (!((keyCode >= 48 && keyCode <= 57 && !event.shiftKey) // 0 ~ 9
+		|| (keyCode >= 96 && keyCode <= 105) // 0 ~ 9 (Num Lock)
+		|| (keyCode == 187 && event.shiftKey) // Shift 하고 +
+		|| (keyCode == 107) // + (Num Lock)
+		|| (keyCode == 189 && !event.shiftKey) // Shift 없이 -
+		|| (keyCode == 109) // - (Num Lock)
+		|| (keyCode == 190 && !event.shiftKey) // .
+		)) {
+		$(this).val(value);
+		event.returnValue = false;
+	}
+});
+$(document).on("keyup", "[data-valid-type=alphaNumeric]", function() { $(this).val($(this).val().replace(/[^a-zA-Z0-9]/gi, "")); });
+$(document).on("keyup", "[data-valid-type=date]", function() { $(this).val($(this).val().replace(/[^0-9\/]/gi,"")); });
+$(document).on("keyup", "[data-valid-type=calendar]", function() { $(this).val($(this).val().replace(/[^0-9\/]/gi,"")); });
+$(document).on("blur", "[data-valid-type=calendar]", function() {
+	var val = $(this).val();
+	if(val==''){
+		return;
+	}
+	val = val.replace(/-/gi, "");
+	var temp = val.substring(0, 4)+" ";
+	if(Number(val.substring(4, 6))>12){
+		temp += "12";
+	}else if(Number(val.substring(4, 6))==0){
+		temp += "1";
+	}else{
+		temp += Number(val.substring(4, 6));
+	}
+	temp += " ";
+	if(Number(val.substring(6, 8))>31){
+		temp += "31";
+	}else if(Number(val.substring(6, 8))==0){
+		temp += "1";
+	}else{
+		temp += Number(val.substring(6, 8));
+	}
+	
+	var date = new Date(temp);
+	var yyyy = date.getFullYear().toString();
+	var mm = (date.getMonth() + 1).toString();
+	var dd = date.getDate().toString();
+	$(this).val(yyyy + '-' + (mm[1] ? mm : '0'+mm[0])+ '-'  + (dd[1] ? dd : '0'+dd[0]));
+});
+$(document).on("keyup", "[data-valid-type=korean]", function() { $(this).val($(this).val().replace(/[^가-힣]/gi, "")); });
+$(document).on("keyup", "[data-valid-type=email]", function() { $(this).val($(this).val().replace(/[^a-zA-Z0-9\@\+\_\.\@\-]/gi, "")); });
+$(document).on("keyup", "[data-valid-type=password]", function() { $(this).val($(this).val().replace(/[^a-zA-Z0-9\~\!\@\#\$\%\^\&\*\?\(\)\_\+\{\}\[\]]/gi, "")); });
+$(document).on("keyup", "[data-valid-type=cellPhone]", function() { $(this).val($(this).val().replace(/[^\d-]/gi, "")); });
+$(document).on("keydown", "[data-valid-type=cellPhone]", function() {
+	var value = $(this).val();
+
+	var keyCode = gagajf.getKeyCode();
+	if (keyCode == -1)
+		return true;
+
+	if (!((keyCode >= 48 && keyCode <= 57 && !event.shiftKey) // 0 ~ 9
+		|| (keyCode >= 96 && keyCode <= 105) // 0 ~ 9 (Num Lock)
+		|| (keyCode == 189 && !event.shiftKey) // Shift 없이 -
+		|| (keyCode == 109) // - (Num Lock)
+		)) {
+		$(this).val(value);
+		event.returnValue = false;
+	}
+});
+$(document).on("keyup", "[data-valid-type=phone]", function() { $(this).val($(this).val().replace(/[^\d-]/gi, "")); });
+$(document).on("keydown", "[data-valid-type=phone]", function() {
+	var value = $(this).val();
+
+	var keyCode = gagajf.getKeyCode();
+	if (keyCode == -1)
+		return true;
+
+	if (!((keyCode >= 48 && keyCode <= 57 && !event.shiftKey) // 0 ~ 9
+		|| (keyCode >= 96 && keyCode <= 105) // 0 ~ 9 (Num Lock)
+		|| (keyCode == 189 && !event.shiftKey) // Shift 없이 -
+		|| (keyCode == 109) // - (Num Lock)
+		)) {
+		$(this).val(value);
+		event.returnValue = false;
+	}
+});
+$(document).on("keyup", "[data-valid-type=ipAddress]", function() { $(this).val($(this).val().replace(/[^\d\.]/gi, "")); });
+$(document).on("keydown", "[data-valid-type=ipAddress]", function() {
+	var value = $(this).val();
+
+	var keyCode = gagajf.getKeyCode();
+	if (keyCode == -1)
+		return true;
+
+	if (!((keyCode >= 48 && keyCode <= 57 && !event.shiftKey) // 0 ~ 9
+		|| (keyCode >= 96 && keyCode <= 105) // 0 ~ 9 (Num Lock)
+		|| (keyCode == 190 && !event.shiftKey) // .
+		)) {
+		$(this).val(value);
+		event.returnValue = false;
+	}
+});
+$(document).on("keyup", "[data-valid-type=bizRegNo]", function() { $(this).val($(this).val().replace(/[^0-9\-]/gi,"")); });

BIN
src/main/webapp/ux/plugins/gaga/loader.gif