Browse Source

first commit

JUSEUNG 5 years ago
commit
a8a7c52d0a
50 changed files with 3401 additions and 0 deletions
  1. 16 0
      .gitignore
  2. BIN
      lib/gagaframework-web-core-1.7.1-RELEASE.jar
  3. BIN
      lib/gagaframework-web-parameter-1.7-RELEASE.jar
  4. BIN
      lib/gagaframework-web-rest-1.7-RELEASE.jar
  5. BIN
      lib/gagaframework-web-security-1.7.1-RELEASE.jar
  6. BIN
      lib/gagaframework-web-util-1.7-RELEASE.jar
  7. 54 0
      pom.xml
  8. 43 0
      src/main/java/META-INF/MANIFEST.MF
  9. 39 0
      src/main/java/com/style24/core/biz/dao/SsgDirectMessageDao.java
  10. 33 0
      src/main/java/com/style24/core/biz/dao/TscAnswerPhaseDao.java
  11. 24 0
      src/main/java/com/style24/core/biz/dao/TscClauseDao.java
  12. 24 0
      src/main/java/com/style24/core/biz/dao/TscEnvsetDao.java
  13. 46 0
      src/main/java/com/style24/core/biz/service/TscAnswerPhaseService.java
  14. 41 0
      src/main/java/com/style24/core/biz/service/TscClauseService.java
  15. 215 0
      src/main/java/com/style24/core/biz/service/TscEnvsetService.java
  16. 209 0
      src/main/java/com/style24/core/biz/thirdparty/DataGoKrApi.java
  17. 117 0
      src/main/java/com/style24/core/biz/thirdparty/NaverLowestPriceApi.java
  18. 178 0
      src/main/java/com/style24/core/biz/thirdparty/SafetyKoreaApi.java
  19. 252 0
      src/main/java/com/style24/core/biz/thirdparty/SsgKakaoSender.java
  20. 19 0
      src/main/java/com/style24/core/support/annotation/ShopDs.java
  21. 19 0
      src/main/java/com/style24/core/support/annotation/WmsDs.java
  22. 43 0
      src/main/java/com/style24/core/support/config/TscJndiShopConfig.java
  23. 43 0
      src/main/java/com/style24/core/support/config/TscJndiWmsConfig.java
  24. 52 0
      src/main/java/com/style24/core/support/config/TscLocaleMessageConfig.java
  25. 92 0
      src/main/java/com/style24/core/support/config/TscRedisCacheConfig.java
  26. 189 0
      src/main/java/com/style24/core/support/controller/TscBaseController.java
  27. 30 0
      src/main/java/com/style24/core/support/controller/TscCustomErrorController.java
  28. 475 0
      src/main/java/com/style24/core/support/env/TscConstants.java
  29. 42 0
      src/main/java/com/style24/core/support/exception/TscNoSessionException.java
  30. 38 0
      src/main/java/com/style24/core/support/message/TscMessageByLocale.java
  31. 45 0
      src/main/java/com/style24/core/support/session/TscSession.java
  32. 174 0
      src/main/java/com/style24/core/support/util/MaskingUtils.java
  33. 279 0
      src/main/java/com/style24/core/support/util/StyleImageUtils.java
  34. 44 0
      src/main/java/com/style24/persistence/TscBaseDomain.java
  35. 25 0
      src/main/java/com/style24/persistence/domain/Alarm.java
  36. 21 0
      src/main/java/com/style24/persistence/domain/AlarmReceiver.java
  37. 24 0
      src/main/java/com/style24/persistence/domain/AnswerPhase.java
  38. 28 0
      src/main/java/com/style24/persistence/domain/BatchLog.java
  39. 25 0
      src/main/java/com/style24/persistence/domain/Clause.java
  40. 36 0
      src/main/java/com/style24/persistence/domain/DataGoKr.java
  41. 35 0
      src/main/java/com/style24/persistence/domain/Envset.java
  42. 37 0
      src/main/java/com/style24/persistence/domain/KCResultData.java
  43. 23 0
      src/main/java/com/style24/persistence/domain/KCertifyNo.java
  44. 21 0
      src/main/java/com/style24/persistence/domain/KCertifyNoOnly.java
  45. 46 0
      src/main/java/com/style24/persistence/domain/NaverLowestPrice.java
  46. 34 0
      src/main/java/com/style24/persistence/domain/SsgDirectMessage.java
  47. 100 0
      src/main/java/com/style24/persistence/mybatis/shop/SsgDirectMessage.xml
  48. 27 0
      src/main/java/com/style24/persistence/mybatis/shop/TscAnswerPhase.xml
  49. 17 0
      src/main/java/com/style24/persistence/mybatis/shop/TscClause.xml
  50. 27 0
      src/main/java/com/style24/persistence/mybatis/shop/TscEnvset.xml

+ 16 - 0
.gitignore

@@ -0,0 +1,16 @@
+target/
+.settings/
+.classpath
+/bin/
+/target/
+.project
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### MacOS ###
+.DS_Store
+META-INF/context.xml

BIN
lib/gagaframework-web-core-1.7.1-RELEASE.jar


BIN
lib/gagaframework-web-parameter-1.7-RELEASE.jar


BIN
lib/gagaframework-web-rest-1.7-RELEASE.jar


BIN
lib/gagaframework-web-security-1.7.1-RELEASE.jar


BIN
lib/gagaframework-web-util-1.7-RELEASE.jar


+ 54 - 0
pom.xml

@@ -0,0 +1,54 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.style24</groupId>
+		<artifactId>root</artifactId>
+		<version>0.0.1-SNAPSHOT</version>
+	</parent>
+	<groupId>com.style24.core</groupId>
+	<artifactId>style24.core</artifactId>
+	<packaging>jar</packaging>
+	<name>style24.core</name>
+	<description>STYLE24 Core</description>
+	
+	<dependencies>
+		<!-- /// WEB-INF lib -->
+		<dependency>
+			<groupId>com.gagaframework</groupId>
+			<artifactId>gagaframework-web-core</artifactId>
+			<version>1.7.1-RELEASE</version>
+			<scope>system</scope>
+			<systemPath>${basedir}/lib/gagaframework-web-core-1.7.1-RELEASE.jar</systemPath>
+		</dependency>
+		<dependency>
+			<groupId>com.gagaframework</groupId>
+			<artifactId>gagaframework-web-security</artifactId>
+			<version>1.7.1-RELEASE</version>
+			<scope>system</scope>
+			<systemPath>${basedir}/lib/gagaframework-web-security-1.7.1-RELEASE.jar</systemPath>
+		</dependency>
+		<dependency>
+			<groupId>com.gagaframework</groupId>
+			<artifactId>gagaframework-web-parameter</artifactId>
+			<version>1.7-RELEASE</version>
+			<scope>system</scope>
+			<systemPath>${basedir}/lib/gagaframework-web-parameter-1.7-RELEASE.jar</systemPath>
+		</dependency>
+		<dependency>
+			<groupId>com.gagaframework</groupId>
+			<artifactId>gagaframework-web-rest</artifactId>
+			<version>1.7.1-RELEASE</version>
+			<scope>system</scope>
+			<systemPath>${basedir}/lib/gagaframework-web-rest-1.7-RELEASE.jar</systemPath>
+		</dependency>
+		<dependency>
+			<groupId>com.gagaframework</groupId>
+			<artifactId>gagaframework-web-util</artifactId>
+			<version>1.7-RELEASE</version>
+			<scope>system</scope>
+			<systemPath>${basedir}/lib/gagaframework-web-util-1.7-RELEASE.jar</systemPath>
+		</dependency>
+		<!-- \\\ WEB-INF lib -->
+	</dependencies>
+</project>

+ 43 - 0
src/main/java/META-INF/MANIFEST.MF

@@ -0,0 +1,43 @@
+Manifest-Version: 1.0
+Main-Class: 
+Class-Path: spring-data-redis-2.3.3.RELEASE.jar spring-boot-autoconfigur
+ e-2.3.3.RELEASE.jar spring-boot-starter-web-services-2.3.3.RELEASE.jar 
+ xmlbeans-2.6.0.jar logback-classic-1.2.3.jar stax-ex-1.8.3.jar spring-a
+ op-5.2.8.RELEASE.jar log4j-to-slf4j-2.13.3.jar saaj-impl-1.5.2.jar jack
+ son-databind-2.11.2.jar slf4j-api-1.7.30.jar netty-codec-4.1.51.Final.j
+ ar spring-boot-starter-web-2.3.3.RELEASE.jar spring-boot-starter-loggin
+ g-2.3.3.RELEASE.jar hibernate-validator-6.1.5.Final.jar spring-core-5.2
+ .8.RELEASE.jar poi-3.17.jar gagaframework-web-util-1.7-RELEASE.jar comm
+ ons-codec-1.14.jar jakarta.activation-1.2.2.jar jackson-module-paramete
+ r-names-2.11.2.jar spring-boot-starter-jdbc-2.3.3.RELEASE.jar lettuce-c
+ ore-5.3.3.RELEASE.jar gagaframework-web-rest-1.7-RELEASE.jar spring-boo
+ t-starter-2.3.3.RELEASE.jar jakarta.xml.soap-api-1.4.2.jar netty-buffer
+ -4.1.51.Final.jar curvesapi-1.04.jar jackson-annotations-2.11.2.jar jak
+ arta.annotation-api-1.3.5.jar poi-ooxml-schemas-3.17.jar httpcore-4.4.1
+ 3.jar mybatis-spring-boot-starter-2.1.3.jar gson-2.8.6.jar jackson-data
+ type-jsr310-2.11.2.jar spring-boot-starter-json-2.3.3.RELEASE.jar jakar
+ ta.activation-api-1.2.2.jar mybatis-3.5.5.jar spring-expression-5.2.8.R
+ ELEASE.jar spring-jcl-5.2.8.RELEASE.jar spring-ws-core-3.0.9.RELEASE.ja
+ r spring-data-commons-2.3.3.RELEASE.jar gagaframework-web-security-1.7.
+ 1-RELEASE.jar commons-lang3-3.10.jar snakeyaml-1.26.jar mybatis-spring-
+ 2.0.5.jar reactor-core-3.3.9.RELEASE.jar spring-boot-starter-validation
+ -2.3.3.RELEASE.jar commons-collections4-4.1.jar spring-session-data-red
+ is-2.3.0.RELEASE.jar spring-context-5.2.8.RELEASE.jar gagaframework-web
+ -parameter-1.7-RELEASE.jar spring-data-keyvalue-2.3.3.RELEASE.jar jacks
+ on-core-2.11.2.jar jakarta.xml.bind-api-2.3.3.jar reactive-streams-1.0.
+ 3.jar netty-resolver-4.1.51.Final.jar lombok-1.18.12.jar netty-transpor
+ t-4.1.51.Final.jar spring-context-support-5.2.8.RELEASE.jar jackson-dat
+ atype-jdk8-2.11.2.jar netty-handler-4.1.51.Final.jar stax-api-1.0.1.jar
+  mybatis-spring-boot-autoconfigure-2.1.3.jar httpclient-4.5.12.jar spri
+ ng-boot-starter-data-redis-2.3.3.RELEASE.jar spring-xml-3.0.9.RELEASE.j
+ ar HikariCP-3.4.5.jar spring-boot-starter-cache-2.3.3.RELEASE.jar log4j
+ -api-2.13.3.jar spring-beans-5.2.8.RELEASE.jar netty-common-4.1.51.Fina
+ l.jar commons-pool2-2.8.1.jar spring-webmvc-5.2.8.RELEASE.jar spring-we
+ b-5.2.8.RELEASE.jar gagaframework-web-core-1.7.1-RELEASE.jar spring-ses
+ sion-core-2.3.0.RELEASE.jar jakarta.validation-api-2.0.2.jar jboss-logg
+ ing-3.4.1.Final.jar spring-jdbc-5.2.8.RELEASE.jar spring-oxm-5.2.8.RELE
+ ASE.jar logback-core-1.2.3.jar spring-boot-2.3.3.RELEASE.jar jakarta.xm
+ l.ws-api-2.3.3.jar jul-to-slf4j-1.7.30.jar spring-tx-5.2.8.RELEASE.jar 
+ classmate-1.5.1.jar jakarta.el-3.0.3.jar poi-ooxml-3.17.jar jakarta.jws
+ -api-2.1.0.jar
+

+ 39 - 0
src/main/java/com/style24/core/biz/dao/SsgDirectMessageDao.java

@@ -0,0 +1,39 @@
+package com.style24.core.biz.dao;
+
+import com.style24.core.support.annotation.ShopDs;
+import com.style24.persistence.domain.SsgDirectMessage;
+
+/**
+ * Direct Message(SMS, LMS, Kakao 등) Dao
+ * 
+ * @author gagamel
+ * @since 2020. 11. 9
+ */
+@ShopDs
+public interface SsgDirectMessageDao {
+
+	/**
+	 * SMS발송 생성
+	 * @param dm - Direct message 정보
+	 * @author gagamel
+	 * @since 2020. 11. 9
+	 */
+	void createSms(SsgDirectMessage dm);
+
+	/**
+	 * LMS발송 생성
+	 * @param dm - Direct message 정보
+	 * @author gagamel
+	 * @since 2020. 11. 9
+	 */
+	void createLms(SsgDirectMessage dm);
+
+	/**
+	 * 카카오알림톡발송 생성
+	 * @param dm - Direct message 정보
+	 * @author gagamel
+	 * @since 2020. 11. 9
+	 */
+	void createKakao(SsgDirectMessage dm);
+
+}

+ 33 - 0
src/main/java/com/style24/core/biz/dao/TscAnswerPhaseDao.java

@@ -0,0 +1,33 @@
+package com.style24.core.biz.dao;
+
+import com.style24.core.support.annotation.ShopDs;
+import com.style24.persistence.domain.AnswerPhase;
+
+/**
+ * 답변문구 Dao
+ * 
+ * @author gagamel
+ * @since 2020. 10. 29
+ */
+@ShopDs
+public interface TscAnswerPhaseDao {
+
+	/**
+	 * 답변문구 조회
+	 * @param ansSq - 답변일련번호
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 29
+	 */
+	AnswerPhase getAnswerPhase(Integer ansSq);
+
+	/**
+	 * 문의용 답변문구 조회
+	 * @param ansPhase - 답변문구 정보
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 29
+	 */
+	AnswerPhase getQnaAnswerPhase(AnswerPhase ansPhase);
+
+}

+ 24 - 0
src/main/java/com/style24/core/biz/dao/TscClauseDao.java

@@ -0,0 +1,24 @@
+package com.style24.core.biz.dao;
+
+import com.style24.core.support.annotation.ShopDs;
+import com.style24.persistence.domain.Clause;
+
+/**
+ * 약관 Dao
+ *
+ * @author gagamel
+ * @since 2020. 10. 29
+ */
+@ShopDs
+public interface TscClauseDao {
+
+	/**
+	 * 약관 조회
+	 * @param clause - 약관 정보
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 29
+	 */
+	String getClause(Clause clause);
+
+}

+ 24 - 0
src/main/java/com/style24/core/biz/dao/TscEnvsetDao.java

@@ -0,0 +1,24 @@
+package com.style24.core.biz.dao;
+
+import com.style24.core.support.annotation.ShopDs;
+import com.style24.persistence.domain.Envset;
+
+/**
+ * 환경설정 Dao
+ *
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@ShopDs
+public interface TscEnvsetDao {
+
+	/**
+	 * 환경설정 조회
+	 * @param envset - 환경설정 정보
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 5
+	 */
+	Envset getEnvset(Envset envset);
+
+}

+ 46 - 0
src/main/java/com/style24/core/biz/service/TscAnswerPhaseService.java

@@ -0,0 +1,46 @@
+package com.style24.core.biz.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.style24.core.biz.dao.TscAnswerPhaseDao;
+import com.style24.persistence.domain.AnswerPhase;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 답변문구 Service
+ *
+ * @author gagamel
+ * @since 2020. 10. 29
+ */
+@Service
+@Slf4j
+public class TscAnswerPhaseService {
+
+	@Autowired
+	private TscAnswerPhaseDao ansPhaseDao;
+
+	/**
+	 * 답변문구 조회
+	 * @param ansSq - 답변일련번호
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 29
+	 */
+	public AnswerPhase getAnswerPhase(Integer ansSq) {
+		return ansPhaseDao.getAnswerPhase(ansSq);
+	}
+
+	/**
+	 * 문의용 답변문구 조회
+	 * @param ansPhase - 답변문구 정보
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 29
+	 */
+	public AnswerPhase getQnaAnswerPhase(AnswerPhase ansPhase) {
+		return ansPhaseDao.getQnaAnswerPhase(ansPhase);
+	}
+
+}

+ 41 - 0
src/main/java/com/style24/core/biz/service/TscClauseService.java

@@ -0,0 +1,41 @@
+package com.style24.core.biz.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import com.style24.core.biz.dao.TscClauseDao;
+import com.style24.persistence.domain.Clause;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 약관 Service
+ * 
+ * @author gagamel
+ * @since 2020. 10. 29
+ */
+@Service
+@Slf4j
+public class TscClauseService {
+
+	@Autowired
+	private TscClauseDao clauseDao;
+
+	/**
+	 * 약관 조회
+	 * @param siteCd - 사이트코드
+	 * @param clauseType - 약관유형
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 29
+	 */
+	@Cacheable(value = "common", key = "'clause-'.concat(#clauseType)")
+	public String getClause(String siteCd, String clauseType) {
+		Clause clause = new Clause();
+		clause.setSiteCd(siteCd);
+		clause.setClauseType(clauseType);
+		return clauseDao.getClause(clause);
+	}
+
+}

+ 215 - 0
src/main/java/com/style24/core/biz/service/TscEnvsetService.java

@@ -0,0 +1,215 @@
+package com.style24.core.biz.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.style24.core.biz.dao.TscEnvsetDao;
+import com.style24.persistence.domain.Envset;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 환경설정 Service
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@Service
+@Slf4j
+public class TscEnvsetService {
+
+	@Autowired
+	private TscEnvsetDao policyDao;
+
+	/**
+	 * 사이트별 환경설정유형에 따른 환경설정 정보
+	 * 정책은 중요한 정보로서 캐싱 문제 발생 시 심각해질 수 있으므로 캐싱처리 안 함(2020.10.5. gagamel)
+	 * @param siteCd - 사이트코드
+	 * @param envsetType - 환경설정유형
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 5
+	 */
+//	@Cacheable(value = "common", key = "'envset-'.concat(#siteCd).concat('-').concat(#envsetType)")
+	public Envset getEnvset(String siteCd, String envsetType) {
+		Envset params = new Envset();
+		params.setSiteCd(siteCd);
+		params.setEnvsetType(envsetType);
+
+		Envset envset = policyDao.getEnvset(params);
+
+//		if (envsetType.equals("C10")) {
+//			if (StringUtils.isNotBlank(envset.getStrSetVal1())) {
+//				envset.setStrSetNm1(marketingDao.getCouponName(envset.getStrSetVal1()));
+//			}
+//			if (StringUtils.isNotBlank(envset.getStrSetVal2())) {
+//				envset.setStrSetNm2(marketingDao.getCouponName(envset.getStrSetVal2()));
+//			}
+//			if (StringUtils.isNotBlank(envset.getStrSetVal3())) {
+//				envset.setStrSetNm3(marketingDao.getCouponName(envset.getStrSetVal3()));
+//			}
+//			if (StringUtils.isNotBlank(envset.getStrSetVal4())) {
+//				envset.setStrSetNm4(marketingDao.getCouponName(envset.getStrSetVal4()));
+//			}
+//		}
+
+		return envset;
+	}
+
+	/**
+	 * 자사상품정상PC포인트율 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public float getSelfGoodsPcPointRate10(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C15");
+		return (envset == null) ? 0.0f : Float.parseFloat(envset.getStrSetVal1());
+	}
+
+	/**
+	 * 자사상품정상모바일포인트율 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public float getSelfGoodsMobPointRate10(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C15");
+		return (envset == null) ? 0.0f : Float.parseFloat(envset.getStrSetVal2());
+	}
+
+	/**
+	 * 자사상품이월PC포인트율 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public float getSelfGoodsPcPointRate20(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C15");
+		return (envset == null) ? 0.0f : Float.parseFloat(envset.getStrSetVal3());
+	}
+
+	/**
+	 * 자사상품이월모바일포인트율 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public float getSelfGoodsMobPointRate20(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C15");
+		return (envset == null) ? 0.0f : Float.parseFloat(envset.getStrSetVal4());
+	}
+
+	/**
+	 * 입점상품정상PC포인트율 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public float getEntrGoodsPcPointRate10(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C15");
+		return (envset == null) ? 0.0f : Float.parseFloat(envset.getStrSetVal5());
+	}
+
+	/**
+	 * 입점상품정상모바일포인트율 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public float getEntrGoodsMobPointRate10(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C15");
+		return (envset == null) ? 0.0f : Float.parseFloat(envset.getStrSetVal6());
+	}
+
+	/**
+	 * 입점상품이월PC포인트율 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public float getEntrGoodsPcPointRate20(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C15");
+		return (envset == null) ? 0.0f : Float.parseFloat(envset.getStrSetVal7());
+	}
+
+	/**
+	 * 입점상품이월모바일포인트율 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public float getEntrGoodsMobPointRate20(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C15");
+		return (envset == null) ? 0.0f : Float.parseFloat(envset.getStrSetVal8());
+	}
+
+	/**
+	 * 텍스트상품평포인트 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public int getTextReviewPoint(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C16");
+		return (envset == null) ? 0 : Integer.parseInt(envset.getStrSetVal3());
+	}
+
+	/**
+	 * 포토상품평포인트 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public int getPhotoReviewPoint(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C16");
+		return (envset == null) ? 0 : Integer.parseInt(envset.getStrSetVal4());
+	}
+
+	/**
+	 * 최초텍스트상품평포인트 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public int getFirstTextReviewPoint(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C16");
+		return (envset == null) ? 0 : Integer.parseInt(envset.getStrSetVal5());
+	}
+
+	/**
+	 * 최초포토상품평포인트 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public int getFirstPhotoReviewPoint(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C16");
+		return (envset == null) ? 0 : Integer.parseInt(envset.getStrSetVal6());
+	}
+
+	/**
+	 * 베스트상품평포인트 가져오기
+	 * @param siteCd - 사이트코드
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 10. 21
+	 */
+	public int getBestReviewPoint(String siteCd) {
+		Envset envset = this.getEnvset(siteCd, "C16");
+		return (envset == null) ? 0 : Integer.parseInt(envset.getStrSetVal7());
+	}
+
+}

+ 209 - 0
src/main/java/com/style24/core/biz/thirdparty/DataGoKrApi.java

@@ -0,0 +1,209 @@
+package com.style24.core.biz.thirdparty;
+
+import java.io.StringReader;
+import java.net.URI;
+
+import javax.annotation.PostConstruct;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import com.style24.persistence.domain.DataGoKr;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 공공데이터포털을 이용한 통신판매사업자정보 조회
+ * 
+ * @author gagamel
+ * @since 2020. 11. 9
+ */
+@Component
+@Slf4j
+public class DataGoKrApi {
+
+	// 공공데이터포털 URL
+	private String apiUrl = "http://apis.data.go.kr/1130000/openapi/service/MllInfoService";
+
+	// 서비스키
+	private String serviceKey = "";
+
+	@Autowired
+	private RestTemplate restTemplate;
+
+	@PostConstruct
+	public void init() {
+		log.debug("\n\n---- DataGoKrApi initialization started ----");
+		log.debug("apiUrl: [{}]", apiUrl);
+		log.debug("serviceKey: [{}]", serviceKey);
+		log.debug("\n--- DataGoKrApi initialization completed ----\n");
+	}
+
+	/**
+	 * 사업자등록번호로 통신판매사업자 정보 조회
+	 * @param bizNo - 사업자등록번호
+	 * @return 통신판매사업자 정보
+	 * @throws Exception
+	 * @author gagamel
+	 * @since 2020. 11. 18
+	 */
+	public DataGoKr getMllBizRNoInfo(String bizNo) throws Exception {
+		DataGoKr dataGoKr = new DataGoKr();
+
+		// Parameter
+		MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
+		params.add("ServiceKey", serviceKey);
+		params.add("wrkrNo", bizNo);
+		log.info("params: {}", params);
+
+		// Header
+		HttpHeaders headers = new HttpHeaders();
+		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+		HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(params, headers);
+		URI url = URI.create(apiUrl + "/" + "getMllBizRNoInfo");
+
+		// POST방식으로 호출
+		ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
+		log.info("responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
+
+		String responseXml = responseEntity.getBody();
+		log.info("responseEntity.getBody(): {}", responseXml);
+
+//		<response>
+//			<header>
+//				<resultCode>00</resultCode>
+//				<resultMsg>NORMAL SERVICE.</resultMsg>
+//			</header>
+//			<body>
+//				<items>
+//					<item>
+//						<bupNm>(유)아이에스피</bupNm>
+//						<dmnNm>www.cjlion.kr</dmnNm>
+//						<mngStateCode>01</mngStateCode>
+//						<permYmd>20111228</permYmd>
+//						<repsntNm>김은령</repsntNm>
+//						<seq>26</seq>
+//					</item>
+//				</items>
+//				<numOfRows>10</numOfRows>
+//				<pageNo>1</pageNo>
+//				<totalCount>1</totalCount>
+//			</body>
+//		</response>
+
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		DocumentBuilder builder = factory.newDocumentBuilder();
+		Document document = builder.parse(new InputSource(new StringReader(responseXml)));
+		NodeList nodeList = document.getElementsByTagName("items");
+
+		if (nodeList.getLength() > 0) {
+			NamedNodeMap nodeMap = nodeList.item(0).getAttributes();
+
+			dataGoKr.setSeq(nodeMap.getNamedItem("seq").getTextContent());
+			dataGoKr.setBupNm(nodeMap.getNamedItem("bupNm").getTextContent());
+			dataGoKr.setRepsntNm(nodeMap.getNamedItem("repsntNm").getTextContent());
+			dataGoKr.setSidoNm(nodeMap.getNamedItem("sidoNm").getTextContent());
+			dataGoKr.setDmnNm(nodeMap.getNamedItem("dmnNm").getTextContent());
+			dataGoKr.setMngStateCode(nodeMap.getNamedItem("mngStateCode").getTextContent());
+			dataGoKr.setPermYmd(nodeMap.getNamedItem("permYmd").getTextContent());
+
+			this.getMllInfoDetail(dataGoKr);
+		}
+
+		return dataGoKr;
+	}
+
+	/**
+	 * 통신판매사업자 상세 정보 조회
+	 * @param dataGoKr - 통신판매사업자 정보
+	 * @return 통신판매사업자 상세 정보
+	 * @throws Exception
+	 * @author gagamel
+	 * @since 2020. 11. 18
+	 */
+	private void getMllInfoDetail(DataGoKr dataGoKr) throws Exception {
+		// Parameter
+		MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
+		params.add("ServiceKey", serviceKey);
+		params.add("seq", dataGoKr.getSeq());
+		log.info("params: {}", params);
+
+		// Header
+		HttpHeaders headers = new HttpHeaders();
+		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+		HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(params, headers);
+		URI url = URI.create(apiUrl + "/" + "getMllInfoDetail");
+
+		// POST방식으로 호출
+		ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
+		log.info("responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
+
+		String responseXml = responseEntity.getBody();
+		log.info("responseEntity.getBody(): {}", responseXml);
+
+//		<response>
+//			<header>
+//				<resultCode>00</resultCode>
+//				<resultMsg>NORMAL SERVICE.</resultMsg>
+//			</header>
+//			<body>
+//				<items>
+//					<item>
+//						<addr>광주광역시 서구 동천동 235번지 **********</addr>
+//						<apvPermMgtNo>2011-광주서구-00485</apvPermMgtNo>
+//						<bupNm>(유)아이에스피</bupNm>
+//						<bupYn>0</bupYn>
+//						<dmnNm>www.cjlion.kr</dmnNm>
+//						<mngStateCode>01</mngStateCode>
+//						<permYmd>20111228</permYmd>
+//						<repsntNm>김은령</repsntNm>
+//						<seq>26</seq>
+//						<silMet>02</silMet>
+//						<treArtcl>0608</treArtcl>
+//						<wrkrNo>4108654518</wrkrNo>
+//					</item>
+//				</items>
+//				<numOfRows>10</numOfRows>
+//				<pageNo>1</pageNo>
+//				<totalCount>1</totalCount>
+//			</body>
+//		</response>
+
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		DocumentBuilder builder = factory.newDocumentBuilder();
+		Document document = builder.parse(new InputSource(new StringReader(responseXml)));
+		NodeList nodeList = document.getElementsByTagName("items");
+
+		if (nodeList.getLength() > 0) {
+			NamedNodeMap nodeMap = nodeList.item(0).getAttributes();
+			log.info("{}", nodeMap);
+
+			dataGoKr.setNewaddr(nodeMap.getNamedItem("newaddr").getTextContent());
+			dataGoKr.setBupRegNo(nodeMap.getNamedItem("bup_reg_no").getTextContent());
+			dataGoKr.setWrkrNo(nodeMap.getNamedItem("wrkr_no").getTextContent());
+			dataGoKr.setOrgAndTeamNm(nodeMap.getNamedItem("org_and_team_nm").getTextContent());
+			dataGoKr.setRepTelno(nodeMap.getNamedItem("rep_telno").getTextContent());
+			dataGoKr.setTreArtcl(nodeMap.getNamedItem("tre_artcl").getTextContent());
+			dataGoKr.setSilMet(nodeMap.getNamedItem("sil_met").getTextContent());
+			dataGoKr.setBupYn(nodeMap.getNamedItem("bup_yn").getTextContent());
+			dataGoKr.setApvPermMgtNo(nodeMap.getNamedItem("apv_perm_mgt_no").getTextContent());
+			dataGoKr.setHostSrvAddr(nodeMap.getNamedItem("host_srv_addr").getTextContent());
+		}
+	}
+
+}

+ 117 - 0
src/main/java/com/style24/core/biz/thirdparty/NaverLowestPriceApi.java

@@ -0,0 +1,117 @@
+package com.style24.core.biz.thirdparty;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+import com.google.gson.Gson;
+import com.style24.persistence.domain.NaverLowestPrice;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 네이버 최저가 조회 API
+ * 
+ * @author gagamel
+ * @since 2020. 12. 3
+ */
+@Component
+@Slf4j
+public class NaverLowestPriceApi {
+
+	// URL
+	private String apiUrl = "https://openapi.naver.com/v1/search/shop.json";
+
+	// Client ID
+	private String clientId = "x5FGDO3Q9kNZVG9SnDY6";
+
+	// Client Secret
+	private String clientSecret = "tRRng56dgN";
+
+	@Autowired
+	private RestTemplate restTemplate;
+
+	@PostConstruct
+	public void init() {
+		log.debug("\n\n---- NaverLowestPriceApi initialization started ----");
+		log.debug("apiUrl: [{}]", apiUrl);
+		log.debug("clientId: [{}]", clientId);
+		log.debug("clientSecret: [{}]", clientSecret);
+		log.debug("\n--- NaverLowestPriceApi initialization completed ----\n");
+	}
+
+	/**
+	 * 상품의 최저가 조회
+	 * @param goodsCd - 상품코드
+	 * @return 상품의 최저가 정보
+	 * @throws Exception
+	 * @author gagamel
+	 * @since 2020. 12. 3
+	 */
+	public NaverLowestPrice getLowestPrice(String goodsCd) throws Exception {
+		// Header
+		HttpHeaders headers = new HttpHeaders();
+		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+		headers.add("X-Naver-Client-Id", clientId);
+		headers.add("X-Naver-Client-Secret", clientSecret);
+
+		String requestUrl = apiUrl + "?query=" + URLEncoder.encode(goodsCd, "UTF-8") + "&display=1&sort=asc";
+		log.info("requestUrl: {}", requestUrl);
+		URI url = URI.create(requestUrl);
+
+		// GET방식으로 호출
+		HttpEntity<String> request = new HttpEntity<String>(headers);
+		ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, request, String.class);
+		log.info("responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
+
+		String responseJson = responseEntity.getBody();
+		log.info("responseEntity.getBody(): {}", responseJson);
+
+		if (!responseEntity.getStatusCode().equals(HttpStatus.OK)) {
+			return null;
+		}
+
+		Gson gson = new Gson();
+		return gson.fromJson(responseJson, NaverLowestPrice.class);
+	}
+
+	/**
+	 * 상품의 최저가 조회
+	 * @param goodsCdList - 상품코드 목록
+	 * @return 상품의 최저가 목록
+	 * @throws Exception
+	 * @author gagamel
+	 * @since 2020. 12. 3
+	 */
+	public Collection<NaverLowestPrice> getLowestPriceList(Collection<String> goodsCdList) throws Exception {
+		if (goodsCdList == null || goodsCdList.isEmpty()) {
+			throw new IllegalStateException("조회할 상품코드 정보가 없습니다.");
+		}
+
+		Collection<NaverLowestPrice> lpriceList = new ArrayList<>();
+
+		for (String goodsCd : goodsCdList) {
+			log.info("[getLowestPriceList] goodsCd = {}", goodsCd);
+			NaverLowestPrice lprice = this.getLowestPrice(goodsCd);
+			if (lprice != null) {
+				lpriceList.add(lprice);
+			}
+		}
+
+		return lpriceList;
+	}
+
+}

+ 178 - 0
src/main/java/com/style24/core/biz/thirdparty/SafetyKoreaApi.java

@@ -0,0 +1,178 @@
+package com.style24.core.biz.thirdparty;
+
+import java.net.URI;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+import com.google.gson.Gson;
+import com.style24.persistence.domain.KCertifyNo;
+import com.style24.persistence.domain.KCertifyNoOnly;
+
+import lombok.extern.slf4j.Slf4j;
+
+import com.gagaframework.web.parameter.GagaMap;
+
+/**
+ * KC인증번호 조회 (www.safetykorea.kr open API)
+ *
+ * @author gagamel
+ * @since 2020. 12. 1
+ */
+@Component
+@Slf4j
+public class SafetyKoreaApi {
+
+	// URL
+	private String apiUrl = "http://www.safetykorea.kr/openapi/api/cert/certificationList.json";
+
+	private String apiDetailUrl = "http://www.safetykorea.kr/openapi/api/cert/certificationDetail.json";
+
+	// 인증키
+	private String authKey = "34fa9888-a2fb-4c02-adf4-18f018bb936d";
+
+	@Autowired
+	private RestTemplate restTemplate;
+
+	@PostConstruct
+	public void init() {
+		log.debug("\n\n---- SafetyKoreaApi initialization started ----");
+		log.debug("apiUrl: [{}]", apiUrl);
+		log.debug("apiDetailUrl: [{}]", apiDetailUrl);
+		log.debug("authKey: [{}]", authKey);
+		log.debug("\n--- SafetyKoreaApi initialization completed ----\n");
+	}
+
+	/**
+	 * KC인증번호 정보 조회
+	 * @param goodsCd - 상품코드
+	 * @return 인증번호
+	 * @throws Exception
+	 * @author gagamel
+	 * @since 2020. 12. 1
+	 */
+	public GagaMap getKoreaCertifyNo(String goodsCd) throws Exception {
+
+		GagaMap result = new GagaMap();
+
+		String requestUrl = apiUrl + "?conditionKey=all&conditionValue=" + goodsCd;
+		log.info("requestUrl: {}", requestUrl);
+		URI url = URI.create(requestUrl);
+
+		String responseJson = getExtracted( url);
+
+		Gson gson = new Gson();
+		KCertifyNo kcNo = gson.fromJson(responseJson, KCertifyNo.class);
+
+		if (kcNo.getResultCode() != null && "2000".equals(kcNo.getResultCode())) { // 성공
+			result.set("certNum", kcNo.getResultData().iterator().next().getCertNum());
+			result.set("certDiv", kcNo.getResultData().iterator().next().getCertDiv());
+			result.set("certState", kcNo.getResultData().iterator().next().getCertState());
+			result.set("certDt", kcNo.getResultData().iterator().next().getCertDate());
+			return result;
+		}
+
+		return result;
+	}
+
+
+	/**
+	 * KC인증번호로 조회
+	 * @param certNum - 인증번호
+	 * @return
+	 * @throws Exception
+	 * @author eskim
+	 * @since 2020. 12. 07
+	 */
+	public GagaMap getKoreaCertifyDetail(String certNum) throws Exception {
+
+		GagaMap result = new GagaMap();
+
+		String requestUrl = apiDetailUrl + "?certNum=" + certNum;
+		URI url = URI.create(requestUrl);
+
+		String responseJson = getExtracted( url);
+
+		Gson gson = new Gson();
+		KCertifyNoOnly kcNo = gson.fromJson(responseJson, KCertifyNoOnly.class);
+
+		if (kcNo.getResultCode() != null && "2000".equals(kcNo.getResultCode())) { // 성공
+			result.set("certNum", kcNo.getResultData().getCertNum());
+			result.set("certDiv", kcNo.getResultData().getCertDiv());
+			result.set("certState", kcNo.getResultData().getCertState());
+			result.set("certDt", kcNo.getResultData().getCertDate());
+			return result;
+		}
+
+		return result;
+
+	}
+
+	/**
+	 * KC인증정보 조회
+	 * @param url - KC인증 URL
+	 * @return
+	 * @throws Exception
+	 * @author eskim
+	 * @since 2020. 12. 07
+	 */
+	private String getExtracted( URI url) {
+
+		String responseJson = "";
+		// Header
+		HttpHeaders headers = new HttpHeaders();
+		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+		headers.add("AuthKey", authKey);
+
+		// GET방식으로 호출
+		HttpEntity<String> request = new HttpEntity<String>(headers);
+		ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, request, String.class);
+		log.info("responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
+
+		responseJson = responseEntity.getBody();
+		log.info("responseEntity.getBody(): {}", responseJson);
+
+//		{
+//		    "resultCode": "2000",
+//		    "resultMsg": "Success",
+//		    "resultData": [
+//		        {
+//		            "certUid": 4675807,
+//		            "certOrganName": "FITI시험연구원(FITI)",
+//		            "certNum": "CB015R0919-8001",
+//		            "certState": "적합",
+//		            "certDiv": "어린이제품 특별법 대상>안전확인 대상",
+//		            "certDate": "20180703",
+//		            "certChgDate": null,
+//		            "certChgReason": "",
+//		            "firstCertNum": null,
+//		            "productName": "유아용 섬유제품",
+//		            "brandName": "",
+//		            "modelName": "MNW1BQKP20",
+//		            "categoryName": "어린이>유아용 섬유제품",
+//		            "importDiv": "수입",
+//		            "makerName": "INWOO",
+//		            "makerCntryName": "인도네시아",
+//		            "importerName": "(주)아은",
+//		            "remark": "",
+//		            "signDate": "20200629",
+//		            "derivationModels": null,
+//		            "certificationImageUrls": null,
+//		            "factories": null,
+//		            "similarCertifications": null
+//		        }
+//		    ]
+//		}
+
+		return responseJson;
+	}
+
+}

+ 252 - 0
src/main/java/com/style24/core/biz/thirdparty/SsgKakaoSender.java

@@ -0,0 +1,252 @@
+package com.style24.core.biz.thirdparty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.style24.core.biz.dao.SsgDirectMessageDao;
+import com.style24.core.biz.dao.TscAnswerPhaseDao;
+import com.style24.core.support.env.TscConstants;
+import com.style24.persistence.domain.AnswerPhase;
+import com.style24.persistence.domain.SsgDirectMessage;
+
+import lombok.extern.slf4j.Slf4j;
+
+import com.gagaframework.web.parameter.GagaMap;
+import com.gagaframework.web.util.GagaStringUtil;
+
+/**
+ * 신세계아이앤씨 SSG 모듈을 이용한 카카오알림톡 Sender
+ * 
+ * @author gagamel
+ * @since 2020. 11. 9
+ */
+@Component
+@Slf4j
+public class SsgKakaoSender {
+
+	// 발신프로필키
+	private String profile = "95ed449aa61c05fb613253e740cceb7d3b5d0a64";
+
+	// 발신자전화번호
+	private String callbackTelNo;
+
+	private String domainUrl;
+
+	@Autowired
+	private Environment env;
+
+	@Autowired
+	private TscAnswerPhaseDao ansPhaseDao;
+
+	@Autowired
+	private SsgDirectMessageDao dmDao;
+
+	// 알림톡 답변일련번호
+	public enum KakaoAnswerSq {
+		JoinCongrat(1010),			// 회원가입축하 안내
+		CertNoSend(1011),			// 인증번호발송 안내
+		TempPasswd(1012),			// 임시비밀번호발급 안내
+		OtoAnswer(1013),			// 1:1문의답변등록 안내
+		DormantExpect(1014),		// 휴면계정전환예정 안내
+
+		CardOrderComplete(1020),	// 주문완료-신용카드 안내
+		BtOrderComplete(1021),		// 주문완료-계좌이체 안내
+		VaOrderComplete(1022),		// 주문완료-무통장 안내
+		VaDepositRequest(1023),		// 무통장입금요청 안내
+		VaDepositConfirm(1024),		// 무통장입금확인 안내
+		CardCancelRefund(1025),		// 주문취소 및 환불 안내-신용카드
+		AtCancelRefund(1026),		// 주문취소 및 환불 안내-계좌이체
+		VaCancelRefund(1027),		// 주문취소 및 환불 안내-무통장
+
+		SoldoutExpect(1030),		// 품절예정안내
+		CardCancelBySoldout(1031),	// 품절에 의한 주문취소 안내-신용카드
+		AtCancelBySoldout(1032),	// 품절에 의한 주문취소 안내-계좌이체
+		VaCancelBySoldout(1033),	// 품절에 의한 주문취소 안내-무통장
+
+		GoodsSend(1040),			// 상품 발송 안내
+		ExchGoodsSend(1041),		// 교환 상품 발송 안내
+
+		ExchRequestComplete(1050),	// 교환 신청 완료 안내
+		RtnRequestCompleted(1051),	// 반품 신청 완료 안내
+		WithdrawDelay(1060),		// 회수처리 지연 안내
+		ReviewWrite(1070),			// 상품평 작성 안내
+		BasicLms(1071);				// 기본안내
+
+		private Integer value;
+
+		private KakaoAnswerSq(Integer value) {
+			this.value = value;
+		}
+
+		public Integer value() {
+			return value;
+		}
+	}
+
+	@PostConstruct
+	public void init() {
+		domainUrl = env.getProperty("domain.front");
+		callbackTelNo = TscConstants.CALLCENTER_TEL_NO;
+
+		log.debug("\n\n---- SsgKakaoSender initialization started ----");
+		log.debug("profile: [{}]", profile);
+		log.debug("callbackTelNo: [{}]", callbackTelNo);
+		log.debug("domainUrl: [{}]", domainUrl);
+		log.debug("\n--- SsgKakaoSender initialization completed ----\n");
+	}
+
+	/**
+	 * 카카오알림톡 발송
+	 * @param ansSq - 답변일련번호
+	 * @param dm - 메시지 정보
+	 * @param replaceInfo - 메시지내용 중 대체할 정보
+	 * @author gagamel
+	 * @since 2020. 11. 9
+	 */
+	@Transactional("shopTxnManager")
+	public void send(Integer ansSq, SsgDirectMessage dm, GagaMap replaceInfo) {
+		// 답변문구 조회
+		AnswerPhase ansPhase = this.getAnswerPhase(ansSq, replaceInfo);
+
+		dm.setFyellowid(profile);
+		dm.setFkkosubject(ansPhase.getAnsTitle());
+		dm.setFtemplatekey(String.valueOf(ansSq));
+		dm.setFmessage(ansPhase.getAnsContent());
+
+		// kkoresendtype(재발송유형)이 "SMS"일 때만 kkoresendmsg(재발송메시지)에 값 설정
+		// "LMS"일 때는 fmessage(메시지본문) 값으로 발송되며 kkoresendmsg(재발송메시지)에는 값을 넣으면 안 된다.
+		if (dm.getFkkoresendtype().equals("SMS")) {
+			dm.setFkkoresendmsg(ansPhase.getAnsContent());
+		}
+
+		dm.setFcallback(callbackTelNo);
+
+		// 버튼생성
+//		if (StringUtils.isNotBlank(dm.getButtonNm())) {
+//			JSONObject button = new JSONObject();
+//			button.put("name", dm.getButtonNm());
+//			button.put("type", "WL");
+//			button.put("url_mobile", domainUrl + dm.getButtonUrl());
+//
+//			JSONObject jsonData = new JSONObject();
+//			jsonData.put("button", button);
+//
+//			JSONArray jsonArray = new JSONArray();
+//			jsonArray.add(button);
+//
+//			dm.setFkkobutton(jsonArray.toString());
+//		}
+
+		// 카카오 알림톡 발송
+		dmDao.createKakao(dm);
+	}
+
+	/**
+	 * SMS 발송
+	 * @param ansSq - 답변일련번호
+	 * @param dm - 메시지 정보
+	 * @param replaceInfo - 메시지내용 중 대체할 정보
+	 * @author gagamel
+	 * @since 2020. 11. 9
+	 */
+	@Transactional("shopTxnManager")
+	public void sendSms(Integer ansSq, SsgDirectMessage dm, GagaMap replaceInfo) {
+		// 답변문구 조회
+		AnswerPhase ansPhase = this.getAnswerPhase(ansSq, replaceInfo);
+		dm.setFmessage(ansPhase.getAnsContent());
+		dm.setFcallback(callbackTelNo);
+		dmDao.createSms(dm);
+	}
+
+	/**
+	 * LMS 발송
+	 * @param ansSq - 답변일련번호
+	 * @param dm - 메시지 정보
+	 * @param replaceInfo - 메시지내용 중 대체할 정보
+	 * @author gagamel
+	 * @since 2020. 11. 9
+	 */
+	@Transactional("shopTxnManager")
+	public void sendLms(Integer ansSq, SsgDirectMessage dm, GagaMap replaceInfo) {
+		// 답변문구 조회
+		AnswerPhase ansPhase = this.getAnswerPhase(ansSq, replaceInfo);
+		dm.setFsubject(ansPhase.getAnsTitle());
+		dm.setFmessage(ansPhase.getAnsContent());
+		dm.setFcallback(callbackTelNo);
+		dmDao.createLms(dm);
+	}
+
+	/**
+	 * 답변문구 조회
+	 * @param ansSq - 답변일련번호
+	 * @param replaceInfo - 메시지내용 중 대체할 정보
+	 * @return
+	 * @author gagamel
+	 * @since 2020. 11. 9
+	 */
+	@Cacheable(value = "common", key = "'answerPhase-'.concat(#ansSq)")
+	public AnswerPhase getAnswerPhase(Integer ansSq, GagaMap replaceInfo) {
+		AnswerPhase ansPhase = ansPhaseDao.getAnswerPhase(ansSq);
+		ansPhase.setAnsContent(GagaStringUtil.replace(this.mergeData(ansPhase.getAnsContent(), replaceInfo), "&gt;", ">"));
+		return ansPhase;
+	}
+
+	/**
+	 * 메시지 문자열 중에 '#{'로 시작하고 '}'로 끝나는 부분을 대체할 정보(replaceInfo)로 대체해 반환한다.
+	 * @param message - 메시지 문자열
+	 * @param replaceInfo - 알림톡 메시지 중 대체할 정보
+	 * @return
+	 * @author gagamel
+	 * @date 2018. 1. 21.
+	 */
+	private String mergeData(String message, GagaMap replaceInfo) {
+		List<String> keyList = getKeyList(message, "#{", "}");
+
+		String key = "";
+		String value = "";
+
+		if (!keyList.isEmpty()) {
+			for (int i = 0; i < keyList.size(); i++) {
+				key = keyList.get(i);
+				value = replaceInfo.getString(key);
+				message = message.replace("#{" + key + "}", value);
+			}
+		}
+
+		return message;
+	}
+
+	/**
+	 * 입력 문자열로부터 시작 태그와 종료 태그 안의 key 목록을 반환한다.
+	 * @param inputStr - 입력 문자열
+	 * @param startTag - 시작 태그
+	 * @param endTag - 종료 태그
+	 * @return
+	 * @author gagamel
+	 * @date 2018. 1. 21.
+	 */
+	private List<String> getKeyList(String inputStr, String startTag, String endTag) {
+		List<String> keyList = new ArrayList<>();
+
+		String targetStr = inputStr;
+
+		while (targetStr.indexOf(startTag) > -1) {
+			int startPos = targetStr.indexOf(startTag) + startTag.length();
+			int endPos = targetStr.indexOf(endTag, startPos);
+
+			keyList.add(targetStr.substring(startPos, endPos));
+			targetStr = targetStr.substring(endPos + endTag.length());
+		}
+
+		return keyList;
+	}
+
+}

+ 19 - 0
src/main/java/com/style24/core/support/annotation/ShopDs.java

@@ -0,0 +1,19 @@
+package com.style24.core.support.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * DataSource를 여러 개로 구성 시 DAO를 구성하는 interface를 명시적으로 지정하기 위해 만든 Custom Annotation
+ * jdbc/shopDs JNDI DataSource와 매핑
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ShopDs{
+
+}

+ 19 - 0
src/main/java/com/style24/core/support/annotation/WmsDs.java

@@ -0,0 +1,19 @@
+package com.style24.core.support.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * DataSource를 여러 개로 구성 시 DAO를 구성하는 interface를 명시적으로 지정하기 위해 만든 Custom Annotation
+ * jdbc/wmsDs JNDI DataSource와 매핑
+ * 
+ * @author gagamel
+ * @since 2020. 11. 26
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface WmsDs{
+
+}

+ 43 - 0
src/main/java/com/style24/core/support/config/TscJndiShopConfig.java

@@ -0,0 +1,43 @@
+package com.style24.core.support.config;
+
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.gagaframework.web.core.config.GagaJndiBaseConfig;
+
+/**
+ * Shop Transaction Manager 설정
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@Configuration
+@Lazy
+@EnableTransactionManagement
+public class TscJndiShopConfig extends GagaJndiBaseConfig {
+
+	/**
+	 * destroyMethod = "close" 속성은 apache commons DBCP와 BasicDataSource 등에서
+	 * 즉시 DataSource를 종료하고자 할 때에 사용하는 것으로 DriverManagerDataSource에서는 필요하지 않다.
+	 */
+	@Override
+//	@Bean(name = "defaultDataSource", destroyMethod = "close")
+	@Bean(name = "shopDataSource")
+	public DataSource dataSource() throws IllegalArgumentException, NamingException {
+		return super.getDataSource("jdbc/shopDs");
+	}
+
+	@Override
+	@Bean(name = "shopTxnManager")
+	public PlatformTransactionManager transactionManager(@Qualifier("shopDataSource") DataSource dataSource) throws NamingException {
+		return super.getTransactionManager(dataSource);
+	}
+
+}

+ 43 - 0
src/main/java/com/style24/core/support/config/TscJndiWmsConfig.java

@@ -0,0 +1,43 @@
+package com.style24.core.support.config;
+
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.gagaframework.web.core.config.GagaJndiBaseConfig;
+
+/**
+ * WMS Transaction Manager 설정
+ * 
+ * @author gagamel
+ * @since 2020. 11. 26
+ */
+@Configuration
+@Lazy
+@EnableTransactionManagement
+public class TscJndiWmsConfig extends GagaJndiBaseConfig {
+
+	/**
+	 * destroyMethod = "close" 속성은 apache commons DBCP와 BasicDataSource 등에서
+	 * 즉시 DataSource를 종료하고자 할 때에 사용하는 것으로 DriverManagerDataSource에서는 필요하지 않다.
+	 */
+	@Override
+	//	@Bean(name = "defaultDataSource", destroyMethod = "close")
+	@Bean(name = "wmsDataSource")
+	public DataSource dataSource() throws IllegalArgumentException, NamingException {
+		return super.getDataSource("jdbc/wmsDs");
+	}
+
+	@Override
+	@Bean(name = "wmsTxnManager")
+	public PlatformTransactionManager transactionManager(@Qualifier("wmsDataSource") DataSource dataSource) throws NamingException {
+		return super.getTransactionManager(dataSource);
+	}
+
+}

+ 52 - 0
src/main/java/com/style24/core/support/config/TscLocaleMessageConfig.java

@@ -0,0 +1,52 @@
+package com.style24.core.support.config;
+
+import java.util.Locale;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.MessageSource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.ReloadableResourceBundleMessageSource;
+import org.springframework.core.env.Environment;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
+
+/**
+ * Locale Message Configuration
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@Configuration
+public class TscLocaleMessageConfig implements WebMvcConfigurer {
+
+	@Autowired
+	private Environment env;
+
+	@Bean(name = "localeResolver")
+	public LocaleResolver localeResolver() {
+		SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
+		sessionLocaleResolver.setDefaultLocale(Locale.KOREA);
+		return sessionLocaleResolver;
+	}
+
+	@Bean
+	public MessageSource messageSource() {
+		ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
+		messageSource.setBasename(env.getProperty("spring.messages.basename"));
+		messageSource.setDefaultEncoding(env.getProperty("spring.messages.encoding"));
+		messageSource.setCacheSeconds(new Integer(env.getProperty("spring.messages.cache-duration")));
+		return messageSource;
+	}
+
+	@Override
+	public void addInterceptors(InterceptorRegistry registry) {
+		LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
+		localeChangeInterceptor.setParamName("language");
+		registry.addInterceptor(localeChangeInterceptor);
+	}
+
+}

+ 92 - 0
src/main/java/com/style24/core/support/config/TscRedisCacheConfig.java

@@ -0,0 +1,92 @@
+package com.style24.core.support.config;
+
+import java.time.Duration;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.CacheKeyPrefix;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+/**
+ * Redis Cache Configuration
+ *
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@Configuration
+public class TscRedisCacheConfig {
+
+	@Value("${spring.redis.host}")
+	private String host;
+
+	@Value("${spring.redis.port}")
+	private int port;
+
+	@Value("${spring.redis.password}")
+	private String password;
+
+	@Bean
+	public RedisConnectionFactory redisConnectionFactory() {
+		RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(host, port);
+		redisStandaloneConfiguration.setDatabase(5); // 프론트와 어드민을 동일한 DATABASE 로 세팅
+		if (StringUtils.isNotBlank(password)) {
+			redisStandaloneConfiguration.setPassword(password);
+		}
+		return new LettuceConnectionFactory(redisStandaloneConfiguration);
+	}
+
+	@Bean
+	public ObjectMapper objectMapper() {
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+		mapper.registerModules(new JavaTimeModule(), new Jdk8Module());
+		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+		return mapper;
+	}
+
+	/**
+	 * CacheManager 설정
+	 * 캐싱 처리 시 @Cacheable, @CacheEvict 등의 애노테이션을 사용할 수 있음
+	 * @param connectionFactory - RedisConnectionFactory
+	 * @return
+	 */
+	@Bean
+	public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
+		RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
+//			.disableCachingNullValues()
+			.entryTtl(Duration.ofSeconds(30 * 60L))
+			.computePrefixWith(CacheKeyPrefix.simple())
+			.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
+			.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper())));
+
+//		Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
+//
+//		cacheConfigurations.put("redis", RedisCacheConfiguration.defaultCacheConfig()
+//				.disableCachingNullValues()
+//				.entryTtl(Duration.ofSeconds(30 * 60L))
+//				.computePrefixWith(CacheKeyPrefix.simple())
+//				.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
+//				.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())));
+
+		return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory)
+			.cacheDefaults(configuration)
+//			.withInitialCacheConfigurations(cacheConfigurations)
+			.build();
+	}
+
+}

+ 189 - 0
src/main/java/com/style24/core/support/controller/TscBaseController.java

@@ -0,0 +1,189 @@
+package com.style24.core.support.controller;
+
+import java.nio.file.AccessDeniedException;
+import java.sql.SQLException;
+import java.sql.SQLRecoverableException;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.ibatis.binding.BindingException;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.propertyeditors.StringTrimmerEditor;
+import org.springframework.core.env.Environment;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.style24.core.support.exception.TscNoSessionException;
+import com.style24.core.support.message.TscMessageByLocale;
+
+import lombok.extern.slf4j.Slf4j;
+
+import com.gagaframework.web.rest.exception.GagaRestException;
+import com.gagaframework.web.rest.server.GagaResponse;
+import com.gagaframework.web.rest.server.GagaResponseStatus;
+
+/**
+ * Controller Advice
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@ControllerAdvice
+@Slf4j
+public class TscBaseController {
+
+	@Autowired
+	private Environment env;
+
+	@Autowired
+	private TscMessageByLocale message;
+
+	/**
+	 * Json data 형식 외의 모든 문자열의 앞, 뒤 공백 제거
+	 * Json data 형식의 모든 문자열의 앞, 뒤 공백 제거 시는 TsaStringTrim에서 처리 (@RequestBody annotation 이용 시)
+	 * 
+	 * @param binder
+	 */
+	@InitBinder
+	public void initBinder(WebDataBinder binder) {
+		StringTrimmerEditor stringtrimmer = new StringTrimmerEditor(true);
+//		stringtrimmer.getAsText().replaceAll("<", "&lt;").replaceAll(">", "&gt;");
+		binder.registerCustomEditor(String.class, stringtrimmer);
+	}
+
+	@ModelAttribute("env")
+	public Environment getEnvironment() {
+		return env;
+	}
+
+	@ResponseBody
+	public GagaResponse ok() {
+		return GagaResponse.of(GagaResponseStatus.SUCCESS.getCode(), "SUCCESS");
+	}
+
+	@ResponseBody
+	public GagaResponse ok(String message) {
+		return GagaResponse.of(GagaResponseStatus.SUCCESS.getCode(), message);
+	}
+
+	@ResponseBody
+	public GagaResponse error(String message) {
+		return GagaResponse.error(GagaResponseStatus.FAIL.getCode(), message);
+	}
+
+	@ExceptionHandler(AccessDeniedException.class)
+	@ResponseBody
+	public GagaResponse handleForbidden(Exception ex) {
+		return GagaResponse.error(GagaResponseStatus.FORBIDDEN.getCode(), ex.getMessage());
+	}
+
+	@ExceptionHandler(TypeMismatchException.class)
+	@ResponseBody
+	public GagaResponse handleBadRequestException(Exception ex) {
+		errorLogging(ex);
+		return GagaResponse.error(GagaResponseStatus.BAD_REQUEST.getCode(), ex.getMessage());
+	}
+
+	@ExceptionHandler(MissingServletRequestParameterException.class)
+	@ResponseBody
+	public GagaResponse handleRequestParameterException(MissingServletRequestParameterException ex) {
+		errorLogging(ex);
+		return GagaResponse.error(GagaResponseStatus.BAD_REQUEST.getCode(), ex.getMessage());
+	}
+
+	/**
+	 * HttpRequestMethodNotSupportedException Handler
+	 * 
+	 * @param e - HttpRequestMethodNotSupportedException, SQLRecoverableException
+	 * @return forwarding URI
+	 */
+	@ExceptionHandler({HttpRequestMethodNotSupportedException.class, SQLRecoverableException.class})
+	public String handleException(HttpRequestMethodNotSupportedException ex) {
+		return "forward:/error/500";
+	}
+
+	@ExceptionHandler(Throwable.class)
+	@ResponseBody
+	public GagaResponse handleException(Throwable throwable) {
+		errorLogging(throwable);
+
+		Throwable rootCause = ExceptionUtils.getRootCause(throwable);
+
+		if (rootCause != null) {
+			throwable = rootCause;
+		}
+
+		if (throwable instanceof SQLException || throwable instanceof BindingException
+			|| throwable instanceof JsonMappingException) {
+			String message = String.format("데이터 처리중 에러가 발생하였습니다. 시스템 관리자에게 문의하세요.");
+			return GagaResponse.error(GagaResponseStatus.INTERNAL_SERVER_ERROR.getCode(), message);
+		}
+
+		return GagaResponse.error(GagaResponseStatus.INTERNAL_SERVER_ERROR.getCode(), throwable.getMessage());
+	}
+
+	private void errorLogging(Throwable throwable) {
+		if (log.isErrorEnabled()) {
+			Throwable rootCause = ExceptionUtils.getRootCause(throwable);
+
+			if (rootCause != null) {
+				throwable = rootCause;
+			}
+
+			if (throwable.getMessage() != null) {
+				log.error(throwable.getMessage(), throwable);
+			} else {
+				log.error("ERROR", throwable);
+			}
+		}
+	}
+
+	@ExceptionHandler(MethodArgumentNotValidException.class)
+	@ResponseBody
+	public Object processValidationError(MethodArgumentNotValidException ex) {
+		FieldError fieldError = ex.getBindingResult().getFieldErrors().get(0);
+		GagaResponse error = GagaResponse.error(GagaResponseStatus.INTERNAL_SERVER_ERROR.getCode(), fieldError.getDefaultMessage());
+		error.getError().setRequiredKey(fieldError.getField());
+		return error;
+	}
+
+	/**
+	 * Custom Validation using group class
+	 * 
+	 * @param domain - Domain to validate
+	 * @param groupClass - Group class to validate
+	 */
+	public void customValidation(Object clazz, Class<?> groupClass) {
+		Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+
+		Set<ConstraintViolation<Object>> violations = validator.validate(clazz, groupClass);
+
+		for (ConstraintViolation<?> violation : violations) {
+			String validationMessage = violation.getMessage();
+			validationMessage = StringUtils.removeStart(validationMessage, "{");
+			validationMessage = StringUtils.removeEnd(validationMessage, "}");
+			throw new GagaRestException(GagaResponseStatus.FAIL.getCode(), message.getMessage(validationMessage));
+		}
+	}
+
+	@ExceptionHandler(TscNoSessionException.class)
+	public String noSessionException(TscNoSessionException ex) {
+		return "forward:/error/noSession";
+	}
+
+}

+ 30 - 0
src/main/java/com/style24/core/support/controller/TscCustomErrorController.java

@@ -0,0 +1,30 @@
+package com.style24.core.support.controller;
+
+import org.springframework.boot.web.servlet.error.ErrorController;
+import org.springframework.stereotype.Controller;
+
+/**
+ * Custom Error Controller
+ * 1. Disabling the Whitelabel Error Page
+ * - application.yml 파일에 다음을 추가
+ * server.error.whitelabel.enabled=false
+ * or
+ * - ~Application.java 파일에 다음을 추가
+ * 
+ * @EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
+ * 2. Create a Custom ErrorController
+ * you have to create a class that implements the ErrorController interface.
+ * And overrides its getErrorPath() to return a custom path to call when an error occurred.
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@Controller
+public class TscCustomErrorController implements ErrorController {
+
+	@Override
+	public String getErrorPath() {
+		return "/error";
+	}
+
+}

+ 475 - 0
src/main/java/com/style24/core/support/env/TscConstants.java

@@ -0,0 +1,475 @@
+package com.style24.core.support.env;
+
+/**
+ * 변경될 소지가 있는 변수 값을 정의
+ *
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+public class TscConstants {
+
+	// 기본 패키지
+	public static final String BASE_PACKAGE = "com.style24";
+
+	// DOMAIN 패키지
+	public static final String DOMAIN_PACKAGE = "com.style24.persistence";
+
+	// Mybatis Mapper 경로
+	public static final String MAPPER_LOCATION_PATH = "classpath:com/style24/persistence/mybatis";
+
+	// 콜센터전화번호
+	public static final String CALLCENTER_TEL_NO = "1544-5336";
+
+	// 대표 이메일
+	public static final String REP_EMAIL = "help@style24.com";
+
+	// 프론트 URL
+	public static final String FRONT_URL = "www.style24.com";
+
+	// 사이트
+	public enum Site {
+		STYLE24("G000_10");
+
+		private String value;
+
+		private Site(String value) {
+			this.value = value;
+		}
+
+		public String value() {
+			return value;
+		}
+	}
+
+	// 접촉방법
+	public enum ContactMethod {
+		SMS("G055_10"),
+		LMS("G055_11"),
+		KAKAOTALK("G055_12"),
+		EMAIL("G055_20");
+
+		private String value;
+
+		private ContactMethod(String value) {
+			this.value = value;
+		}
+
+		public String value() {
+			return value;
+		}
+	}
+
+//	// 외부몰벤더ID
+//	public enum VendorId {
+//		PASTEL("V001"),
+//		FLYINGTIGER("V002");
+//
+//		private String value;
+//
+//		private VendorId(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 자사몰 매장코드
+//	public enum SelfSellStoreCd {
+//		T003("T3000"),
+//		T004("F3000"),
+//		T007("P3000"),
+//		T009("S3000"),
+//		P001("A3000"),
+//		P002("B3000"),
+//		P004("D3000"),
+//		P005("H3000"),
+//		P006("P3000");
+//
+//		private String value;
+//
+//		private SelfSellStoreCd(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 주문상태
+//	public enum OrderStat {
+//		DEPOSIT_WAIT("10"),				// 입금대기
+//		PAYMENT_COMPLETE("20"),			// 결제완료
+//		GOODS_PREPARE("30"),			// 상품준비중
+//		DELIVERY_PREPARE("40"),			// 배송준비중
+//		SHIPPING("50"),					// 배송중
+//		SHIP_COMPLETE("55"),			// 출고완료
+//		DELIVERY_COMPLETE("60"),		// 배송완료
+//		PAYMENT_BEFORE_CANCEL("98"),	// 결제전주문취소
+//		PAYMENT_AFTER_CANCEL("99");		// 결제후주문취소
+//
+//		private String value;
+//
+//		private OrderStat(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 주문상세상태
+//	public enum OrderDetailStat {
+//		DEPOSIT_WAIT("10"),				// 입금대기
+//		DELIVERY_DEPOSIT_WAIT("17"),	// 출고처예정(입금대기)
+//		ORDER_WAIT_PRICE("18"),			// 발주대기-가격차이
+//		ORDER_WAIT_POST("19"),			// 발주대기-우편번호상이
+//		PAYMENT_COMPLETE("20"),			// 결제완료
+//		EXCHANGE_WAIT("25"),			// 교환대기
+//		DELIVERY_EXCHANGE_WAIT("26"),	// 교환출고처 지정대기
+//		GOODS_PREPARE("30"),			// 상품준비중
+//		DELIVERY_LOC_ASSIGN_WAIT("34"),	// 출고처예정
+//		DELIVERY_LOC_ASSIGN("35"),		// 출고처지정
+//		DELIVERY_PREPARE("40"),			// 배송준비중
+//		SHIPPING("50"),					// 배송중
+//		SHIP_COMPLETE("55"),			// 출고완료
+//		DELIVERY_COMPLETE("60"),		// 배송완료
+//		PURCHASE_CONFIRM("70"),			// 구매확정
+//		PAYMENT_BEFORE_CANCEL("98"),	// 결제전주문취소
+//		PAYMENT_AFTER_CANCEL("99");		// 결제후주문취소
+//
+//		private String value;
+//
+//		private OrderDetailStat(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 주문변경요청구분
+//	public enum OrderChangeGb {
+//		PAYMENT_BEFORE_CANCEL("10"),	// 결제전취소
+//		CANCEL("20"),					// 취소요청
+//		RETURN("30"),					// 반품요청
+//		EXCHANGE("40");					// 교환요청
+//
+//		private String value;
+//
+//		private OrderChangeGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 주문변경사유(취소)
+//	public enum OrderCancelReason {
+//		CHANGE_CUSTOMER("10"),			// 고객변심
+//		EXCHANGE_SIZE("30"),			// 사이즈교환
+//		SOLDOUT("60"),					// 품절
+//		SOLDOUT_MEMO("품절 취소");
+//
+//		private String value;
+//
+//		private OrderCancelReason(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 주문변경요청처리상태
+//	public enum OrderChangeStat {
+//		PAYMENT_BEFORE_CANCEL("10"),	// 결제전취소
+//		CANCEL("20"),					// 취소요청
+//		CANCEL_COMPLETE("21"),			// 취소완료
+//
+//		EXCHANGE("30"),					// 교환요청
+//		EXCHANGE_CANCEL("31"),			// 교환요청 취소
+//		EXCHANGE_COMPLETE("32"),		// 교환완료
+//
+//		RETURN("40"),					// 반품요청
+//		RETURN_CANCEL("41"),			// 반품요청 취소
+//		RETURN_COMPLETE("42");			// 반품완료
+//
+//		private String value;
+//
+//		private OrderChangeStat(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 결제상태
+//	public enum PaymentStat {
+//		PAYMENT_WAIT("00"),				// 결제대기
+//		PAYMENT_COMPLETE("30"),			// 결제완료
+//		DB_FAIL("97"),					// 결제성공후DB실패
+//		PAYMENT_CANCEL("99");			// 결제취소
+//
+//		private String value;
+//
+//		private PaymentStat(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+
+	// 결제수단
+	public enum PayMeans {
+		ACCOUNT_TRANSFER("G014_10"),	// 실시간계좌이체
+		BANK_DEPOSIT("G014_20"),		// 무통장입금
+		CREDIT_CARD("G014_30"),			// 신용카드
+		POINT("G014_40"),				// 포인트
+		COUPON("G014_50"),				// 쿠폰
+		CELL_PHONE("G014_60"),			// 휴대전화
+		EXTMALL("G014_90");				// 외부몰입금
+
+		private String value;
+
+		private PayMeans(String value) {
+			this.value = value;
+		}
+
+		public String value() {
+			return value;
+		}
+	}
+
+//	// 배송비구분
+//	public enum DeliveryFeeGb {
+//		ORIGIN_DELIVERY_FEE("10"),		// 원주문배송비
+//		REPAYMENT_DELIVERY_FEE("20"),	// 재결제배송비
+//		EXCHANGE_DELIVERY_FEE("30"),	// 교환배송비
+//		RETURN_DELIVERY_FEE("40");		// 반품배송비
+//
+//		private String value;
+//
+//		private DeliveryFeeGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 정산구분
+//	public enum UsacGb {
+//		SELL("10"),						// 판매
+//		PURCHASE_RETURN("20");			// 환입
+//
+//		private String value;
+//
+//		private UsacGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 환입구분
+//	public enum PurchaseReturnGb {
+//		CANCEL("10"),					// 취소
+//		SOLDOUT("20"),					// 품절
+//		RETURN("30");					// 반품
+//
+//		private String value;
+//
+//		private PurchaseReturnGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 출고수락거부구분
+//	public enum DeliveryAgreeGb {
+//		WAIT("P"),						// 대기
+//		ACCEPT("Y"),					// 수락
+//		REJECT("N");					// 거부
+//
+//		private String value;
+//
+//		private DeliveryAgreeGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 출고처분류
+//	public enum DeliveryClassification {
+//		WARE_HOUSE("10"),				// 물류창고
+//		NORMAL_STORE("20"),				// 일반매장
+//		DIRECT_STORE("21"),				// 직송매장
+//		SUPPLY_COMPANY("30");			// 입점업체
+//
+//		private String value;
+//
+//		private DeliveryClassification(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 판매구분
+//	public enum StockSellGb {
+//		ORDER("10"),					// 주문
+//		ORDER_CANCEL("11"),				// 주문취소
+//		EXCHANGE("20"),					// 교환신청
+//		EXCHANGE_CANCEL("21");			// 교환취소
+//
+//		private String value;
+//
+//		private StockSellGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 포인트발생구분
+//	public enum PointOccurGb {
+//		USE_POINT("10"),				// 포인트사용
+//		USE_POINT_CANCEL("11"),			// 포인트사용취소
+//		EXPECT_POINT("12"),				// 예정포인트적립
+//		EXPECT_POINT_CANCEL("13"),		// 예정포인트적립취소
+//		REVIEW_POINT("20"),				// 상품평포인트승인
+//		REVIEW_POINT_CANCEL("21"),		// 상품평포인트승인취소
+//		EVENT_POINT("30"),				// 온라인이벤트
+//		JOIN_POINT("31"),				// 회원가입축하
+//		BIRTH_POINT("32"),				// 생일축하
+//		ETC_POINT("90"),				// 기타
+//		EXPIRE_POINT("99");				// 소멸포인트
+//
+//		private String value;
+//
+//		private PointOccurGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 포인트발생상태
+//	public enum PointOccurStat {
+//		APPLY_EXPECT("10"),				// 반영예정
+//		BEFORE_APPLY_CANCEL("20"),		// 반영전취소
+//		APPLY_COMPLETE("30"),			// 반영완료
+//		AFTER_APPLY_CANCEL("40");		// 반영완료취소
+//
+//		private String value;
+//
+//		private PointOccurStat(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	public enum StoreCode {
+//		GWANGJU("MZ0134"),				//광주물류
+//		B2B("");
+//
+//		private String value;
+//
+//		private StoreCode(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 몰구분
+//	public enum MallGb {
+//		SELFMALL("10"),					// 자사몰
+//		EXTMALL("20");					// 외부몰
+//
+//		private String value;
+//
+//		private MallGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	//PG사구분
+//	public enum PgGb {
+//		INICIS("INICIS"),				// 이니시스
+//		KAKAO("KAKAO"),					// 카카오페이
+//		NAVER("NAVER"),					// 네이버페이
+//		NICE("NICE"),					// 나이스
+//		PAYCO("PAYCO");					// 페이코
+//
+//		private String value;
+//
+//		private PgGb(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+//
+//	// 회사 정보
+//	public enum PastelInfomation {
+//		COMPANY_NAME("(주)트라이본즈"),
+//		CEO_NAME("이성연"),
+//		SECURITY_NAME("나정호"),
+//		EMAIL_ADDRESS("pastelmall@tribons.co.kr"),
+//		BIZ_NO("220-87-60976"),
+//		REPORT_NO("2015-서울강남-00835"),
+//		ADDRESS("서울 강남구 논현로 323 (역삼동, MTU빌딩)"),
+//		CALLCENTER_TEL("1544-8116"),
+//		SITE_NAME("파스텔몰");
+//
+//		private String value;
+//
+//		private PastelInfomation(String value) {
+//			this.value = value;
+//		}
+//
+//		public String value() {
+//			return value;
+//		}
+//	}
+
+}

+ 42 - 0
src/main/java/com/style24/core/support/exception/TscNoSessionException.java

@@ -0,0 +1,42 @@
+package com.style24.core.support.exception;
+
+import com.gagaframework.web.core.exception.GagaRuntimeException;
+
+/**
+ * 세션이 없을 경우 발생시키는 예외
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@SuppressWarnings("serial")
+public class TscNoSessionException extends GagaRuntimeException {
+
+	/**
+	 * Constructor
+	 * 
+	 * @param msg the detail message
+	 */
+	public TscNoSessionException(String msg) {
+		super(msg);
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 * @param msg the detail message
+	 * @param cause the root cause
+	 */
+	public TscNoSessionException(String msg, Throwable cause) {
+		super(msg, cause);
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 * @param cause the root cause
+	 */
+	public TscNoSessionException(Throwable cause) {
+		super(cause);
+	}
+
+}

+ 38 - 0
src/main/java/com/style24/core/support/message/TscMessageByLocale.java

@@ -0,0 +1,38 @@
+package com.style24.core.support.message;
+
+import java.util.Locale;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.style24.core.support.config.TscLocaleMessageConfig;
+
+/**
+ * 메시지 처리
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@Component
+public class TscMessageByLocale {
+
+	@Autowired
+	private TscLocaleMessageConfig localeMessageConfig;
+
+	public String getMessage(String id) {
+		return this.getMessage(id, Locale.KOREA);
+	}
+
+	public String getMessage(String id, Locale locale) {
+		return this.getMessage(id, null, locale);
+	}
+
+	public String getMessage(String id, Object[] object) {
+		return localeMessageConfig.messageSource().getMessage(id, object, Locale.KOREA);
+	}
+
+	public String getMessage(String id, Object[] object, Locale locale) {
+		return localeMessageConfig.messageSource().getMessage(id, object, locale);
+	}
+
+}

+ 45 - 0
src/main/java/com/style24/core/support/session/TscSession.java

@@ -0,0 +1,45 @@
+package com.style24.core.support.session;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import lombok.extern.slf4j.Slf4j;
+
+import com.gagaframework.web.security.GagaSession;
+
+/**
+ * Session
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@Slf4j
+public class TscSession extends GagaSession {
+
+	/**
+	 * 세션 설정
+	 * @param name - 명칭
+	 * @param value - 값
+	 * @return HttpServletResponse
+	 */
+	public static void setAttribute(String name, String value) {
+		HttpServletRequest request = getHttpServletRequest();
+		request.getSession(true).setAttribute(name, value);
+	}
+
+	/**
+	 * 세션 값 조회
+	 * @return 세션 값
+	 */
+	public static String getAttribute(String name) {
+		HttpServletRequest request = getHttpServletRequest();
+		HttpSession session = request.getSession(true);
+
+		if (session != null && session.getAttribute(name) != null) {
+			return (String)session.getAttribute(name);
+		}
+
+		return "";
+	}
+
+}

+ 174 - 0
src/main/java/com/style24/core/support/util/MaskingUtils.java

@@ -0,0 +1,174 @@
+package com.style24.core.support.util;
+
+import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 개인정보 마스킹 처리 Util Class
+ * @author gagamel
+ * @since 2020. 12. 29
+ */
+@Slf4j
+public class MaskingUtils {
+
+	private static final char DEFAULT_REPLACE = '*';
+
+	/**
+	 * ID 3자 이후 전체 마스킹 처리
+	 * <pre>
+	 * 		예)
+	 * 		abc1234 => abc****
+	 * </pre>
+	 * @param str - 입력문자열
+	 * @return
+	 */
+	public static String id(String str) {
+		String replaceString = str;
+
+		Matcher matcher = Pattern.compile("^(...)(.*)$").matcher(str);
+
+		if (matcher.matches()) {
+			replaceString = "";
+			int gCnt = matcher.groupCount();
+
+			for (int i = 1; i <= gCnt; i++) {
+				String replaceTarget = matcher.group(i);
+
+				if (i == 2) {
+					char[] c = new char[replaceTarget.length()];
+					Arrays.fill(c, DEFAULT_REPLACE);
+					replaceString = replaceString + String.valueOf(c);
+				} else {
+					replaceString = replaceString + replaceTarget;
+				}
+			}
+		}
+
+		return replaceString;
+	}
+
+	/**
+	 * 이름 첫글자와 마지막글자 외 모든 글자 마스킹 처리
+	 * <pre>
+	 * 		예)
+	 * 		환희 => 환*
+	 * 		홍길동 => 홍*동
+	 * 		남궁길동 => 남**동
+	 * </pre>
+	 * @param str - 입력문자열
+	 * @return
+	 */
+	public static String name(String str) {
+		String regex = "^(.)(.+)(.)$";
+		if (str.length() == 2) {
+			regex = "^(.)(.+)$";
+		}
+
+		Matcher matcher = Pattern.compile(regex).matcher(str);
+
+		if (matcher.find()) {
+			String replaceTarget = matcher.group(2);
+			char[] c = new char[replaceTarget.length()];
+			Arrays.fill(c, DEFAULT_REPLACE);
+			return str.replace(replaceTarget, String.valueOf(c));
+		}
+
+		return str;
+	}
+
+	/**
+	 * 성별 전체 문자열로 마스킹 처리
+	 * <pre>
+	 * 		예)
+	 * 		남 => *
+	 * </pre>
+	 * @param str - 입력문자열
+	 * @return
+	 */
+	public static String sex(String str) {
+		return all(str);
+	}
+
+	/**
+	 * 전화번호 중간번호 4자리 마스킹 처리
+	 * <pre>
+	 * 		예)
+	 * 		010-1234-5678 => 010-****-5678
+	 *		01012345678 => 010****5678
+	 * </pre>
+	 * @param str - 입력문자열
+	 * @return
+	 */
+	public static String phoneNo(String str) {
+		Matcher matcher = Pattern.compile("^(\\d{3})-?(\\d{3,4})-?(\\d{4})$").matcher(str);
+
+		if (matcher.find()) {
+			String replaceTarget = matcher.group(2);
+			char[] c = new char[replaceTarget.length()];
+			Arrays.fill(c, DEFAULT_REPLACE);
+			return str.replace(replaceTarget, String.valueOf(c));
+		}
+
+		return str;
+	}
+
+	/**
+	 * 이메일 3자 ~ @전 아이디에 대해 마스킹 처리
+	 * <pre>
+	 * 		예) abc123@style24.com => abc***@style24.com
+	 * </pre>
+	 * @param str - 입력문자열
+	 * @return
+	 */
+	public static String email(String str) {
+		Matcher matcher = Pattern.compile("^(...)(.*)([@]{1})(.*)$").matcher(str);
+
+		if (matcher.find()) {
+			String replaceTarget = matcher.group(2);
+			char[] c = new char[replaceTarget.length()];
+			Arrays.fill(c, DEFAULT_REPLACE);
+			return str.replace(replaceTarget, String.valueOf(c));
+		}
+
+		return str;
+	}
+
+	/**
+	 * 상세주소 전체 문자열로 마스킹 처리
+	 * <pre>
+	 * 		예)
+	 * 		일신빌딩 5,6층 => *********
+	 * </pre>
+	 * @param str - 입력문자열
+	 * @return
+	 */
+	public static String address(String str) {
+		return all(str);
+	}
+
+	/**
+	 * 전체 문자열 마스킹 처리
+	 * <pre>
+	 * 		예)
+	 * 		스타일24 프로젝트 마스킹 => ***************
+	 * </pre>
+	 * @param str - 입력문자열
+	 * @return
+	 */
+	public static String all(String str) {
+		Matcher matcher = Pattern.compile("^(.*)$").matcher(str);
+
+		if (matcher.find()) {
+			String replaceTarget = matcher.group(1);
+			char[] c = new char[replaceTarget.length()];
+			Arrays.fill(c, DEFAULT_REPLACE);
+			return str.replace(replaceTarget, String.valueOf(c));
+		}
+
+		return str;
+	}
+
+}

+ 279 - 0
src/main/java/com/style24/core/support/util/StyleImageUtils.java

@@ -0,0 +1,279 @@
+package com.style24.core.support.util;
+
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.PixelGrabber;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.annotation.PostConstruct;
+import javax.imageio.ImageIO;
+import javax.swing.ImageIcon;
+
+import org.springframework.stereotype.Component;
+
+import lombok.extern.slf4j.Slf4j;
+
+import com.gagaframework.web.util.GagaFileUtil;
+
+@Component
+@Slf4j
+public class StyleImageUtils {
+
+	public static final int RATIO = 0;
+	public static final int SAME = -1;
+
+	private static String resizeSizes;
+
+//	@Value("${goods.thumnbnail.image.size}")
+//	private String goodsSizes;
+
+	@PostConstruct
+	public void init() {
+		StyleImageUtils.resizeSizes = null; //this.goodsSizes;
+	}
+
+//	/**
+//	 * 웹에디터 썸네일
+//	 * @param src 			원본소스 이미지 파일
+//	 * @param dest			제작할 이미지 파일
+//	 * @param width			썸네일 가로크기
+//	 * @param height		썸네일 세로크기
+//	 * @throws IOException	파일입출력 예외사항
+//	 */
+//	public static void thumbnail(File src, File dest, int width) throws IOException {
+//		Image srcImg = getImageObject(src);
+//		int srcWidth = srcImg.getWidth(null);
+//
+//		if (srcWidth > width) {
+//			log.debug("resize 처리: {}", src);
+//			GagaFileUtil.copyFile(src, dest);
+//			resize(src, src, width, RATIO);
+//		}
+//	}
+//
+//	public static void thumbnailArticle(File src, File dest, int width, String targetfolder) throws IOException {
+//		Image srcImg = getImageObject(src);
+//		int srcWidth = srcImg.getWidth(null);
+//
+//		if (srcWidth > width) {
+//			log.debug("resize 처리한다: {}", src);
+//
+//			if (!targetfolder.equals("")) {
+//				File newfolder = new File(targetfolder);
+//				if (!newfolder.exists() || !newfolder.isDirectory())
+//					newfolder.mkdirs();
+//			}
+//
+//			GagaFileUtil.copyFile(src, dest);
+//			resize(src, src, width, RATIO);
+//		}
+//	}
+
+	public static Image getImageObject(File f) throws IOException {
+		Image objImg = null;
+		String suffix = f.getName().substring(f.getName().lastIndexOf('.') + 1).toLowerCase();
+
+		if (suffix.equals("bmp") || suffix.equals("png") || suffix.equals("gif") || suffix.equals("jpg")) {
+			objImg = ImageIO.read(f);
+		} else {
+			// ImageIcon을 활용해서 Image 생성
+			// 이렇게 하는 이유는 getScaledInstance를 통해 구한 이미지를
+			// PixelGrabber.grabPixels로 리사이즈 할 때 빠르게 처리하기 위함이다.
+			objImg = new ImageIcon(f.toURI().toURL()).getImage();
+		}
+
+		return objImg;
+	}
+
+	/**
+	 * 상품이미지 리사이징
+	 * @param path - 경로
+	 * @param filename - 파일명
+	 * @return 리사이징된 파일 목록
+	 * @throws IOException
+	 * @author gagamel
+	 * @since 2019. 6. 28
+	 */
+	public static List<File> resizeGoodsImage(String path, String filename) throws IOException {
+		List<File> fileList = new ArrayList<File>();
+
+		// 리사이즈할 상품이미지 사이즈
+		StringTokenizer goodsSizes = new StringTokenizer(resizeSizes, ",");
+		log.debug("Size count to resize: {}", goodsSizes.countTokens());
+
+		int index = 0;
+
+		while (goodsSizes.hasMoreTokens()) {
+			String goodsSize = goodsSizes.nextToken();
+			log.debug("goodsSize: {}", goodsSize);
+
+			String[] arrProdSize = goodsSize.split("-");
+			int width = Integer.parseInt(arrProdSize[0]);
+			int height = Integer.parseInt(arrProdSize[1]);
+
+			File resizeFile = new File(GagaFileUtil.getConcatenationPath(path, "type" + (index++ + 2), filename));
+			fileList.add(resizeFile);
+
+			thumbnail(new File(GagaFileUtil.getConcatenationPath(path, filename))
+					, resizeFile, height, width);
+		}
+
+		return fileList;
+	}
+
+	/**
+	 * 리사이징된 상품이미지 삭제
+	 * @param path - 경로
+	 * @param filename - 파일명
+	 * @throws IOException
+	 * @author gagamel
+	 * @since 2019. 7. 1
+	 */
+	public static void deleteResizedGoodsImage(String path, String filename) throws IOException {
+		// 리사이즈된 상품이미지 사이즈
+		StringTokenizer goodsSizes = new StringTokenizer(resizeSizes, ",");
+
+		int index = 0;
+
+		while (goodsSizes.hasMoreTokens()) {
+			goodsSizes.nextToken();
+			log.debug("Resized file to delete: {}", GagaFileUtil.getConcatenationPath(path, "type" + (index++ + 2), filename));
+			GagaFileUtil.deleteFile(GagaFileUtil.getConcatenationPath(path, "type" + (index++ + 2), filename));
+		}
+	}
+
+	/**
+	 * 이미지 리사이즈, 주로 썸네일 제작에 사용
+	 * @param src 			원본소스 이미지 파일
+	 * @param dest			제작할 이미지 파일
+	 * @param width			썸네일 가로크기
+	 * @param height		썸네일 세로크기
+	 * @throws IOException	파일입출력 예외사항
+	 */
+	public static void thumbnail(File src, File dest, int height, int width) throws IOException {
+		Image srcImg = getImageObject(src);
+		int srcWidth = srcImg.getWidth(null);
+		int srcHeight = srcImg.getHeight(null);
+
+		if (srcWidth > width || srcHeight > height) {
+			if (srcWidth > srcHeight) {
+				height = RATIO;
+			} else if (srcWidth < srcHeight) {
+				//width = RATIO;
+			} else {
+				if (width > height) {
+					width = RATIO;
+				} else {
+					height = RATIO;
+				}
+			}
+		} else {
+			width = SAME;
+			height = SAME;
+		}
+
+		resize(src, dest, width, height);
+	}
+
+
+	/**
+	 * 이미지 리사이즈, 주로 썸네일 제작에 사용
+	 * @param src 			원본소스 이미지 파일
+	 * @param dest			제작할 이미지 파일
+	 * @param width			이미지 가로크기(변경할 크기 or RATIO or SAME)
+	 * @param height		이미지 세로크기(변경할 크기 or RATIO or SAME)
+	 * @throws IOException	파일입출력 예외사항
+	 */
+	public static void resize(File src, File dest, int width, int height) throws IOException {
+		Image srcImg = getImageObject(src);
+		int srcWidth = srcImg.getWidth(null);
+		int srcHeight = srcImg.getHeight(null);
+
+		int destWidth = -1, destHeight = -1;
+
+		if (width == SAME) {
+			destWidth = srcWidth;
+		} else if (width > 0) {
+			destWidth = width;
+		}
+
+		if (height == SAME) {
+			destHeight = srcHeight;
+		} else if (height > 0) {
+			destHeight = height;
+		}
+
+//		if (width == RATIO && height == RATIO) {
+//			destWidth = srcWidth;
+//			destHeight = srcHeight;
+//		} else if (width == RATIO) {
+//			double ratio = ((double)destHeight) / ((double)srcHeight);
+//			destWidth = (int)((double)srcWidth * ratio);
+//		} else if (height == RATIO) {
+//			double ratio = ((double)destWidth) / ((double)srcWidth);
+//			destHeight = (int)((double)srcHeight * ratio);
+//		}
+
+		/**
+		 * static int SCALE_AREA_AVERAGING
+		 * 		Area Averaging 이미지 슬캘링 알고리즘을 사용합니다.
+		 * static int SCALE_DEFAULT
+		 * 		디폴트의 이미지 슬캘링 알고리즘을 사용합니다.
+		 * static int SCALE_FAST
+		 * 		슬캘링 후의 이미지의 매끄러움보다 슬캘링 속도에 높은 우선 순위를 주는 이미지 슬캘링 알고리즘을 선택합니다.
+		 * static int SCALE_REPLICATE
+		 * 		ReplicateScaleFilter 클래스에서 구체화된 이미지 슬캘링 알고리즘을 사용합니다.
+		 * static int SCALE_SMOOTH
+		 * 		슬캘링 속도보다 이미지의 매끄러움에 높은 우선 순위를 주는 이미지 슬캘링 알고리즘을 선택합니다.
+		 */
+		Image imgTarget = srcImg.getScaledInstance(destWidth, destHeight, Image.SCALE_SMOOTH);
+		int pixels[] = new int[destWidth * destHeight];
+		PixelGrabber pg = new PixelGrabber(imgTarget, 0, 0, destWidth, destHeight, pixels, 0, destWidth);
+		try {
+			pg.grabPixels();
+		} catch (InterruptedException e) {
+			throw new IOException(e.getMessage());
+		}
+		BufferedImage destImg = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_4BYTE_ABGR_PRE);
+		destImg.setRGB(0, 0, destWidth, destHeight, pixels, 0, destWidth);
+		ImageIO.write(destImg, "png", dest);
+	}
+
+//	/**
+//	 * 회원가입시 인증번호를 넣은 이미지 생성
+//	 * @param src			원본 배경이미지 파일
+//	 * @param dest			배경이미지에 인증번호를 넣어서 만들 파일
+//	 * @param authNumber	인증번호(5자리가 최적 : 1 2 3 4 5)
+//	 * @throws IOException	파일입출력 예외사항
+//	 */
+//	public static void drawNumber(File src, File dest, String authNumber) throws IOException {
+//		Image srcImg = getImageObject(src);
+//		int destWidth = srcImg.getWidth(null);
+//		int destHeight = srcImg.getHeight(null);
+//
+//		Image imgTarget = srcImg.getScaledInstance(destWidth, destHeight, Image.SCALE_SMOOTH);
+//		int pixels[] = new int[destWidth * destHeight];
+//		PixelGrabber pg = new PixelGrabber(imgTarget, 0, 0, destWidth, destHeight, pixels, 0, destWidth);
+//		try {
+//			pg.grabPixels();
+//		} catch (InterruptedException e) {
+//			throw new IOException(e.getMessage());
+//		}
+//		BufferedImage destImg = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
+//		destImg.setRGB(0, 0, destWidth, destHeight, pixels, 0, destWidth);
+//
+//		Graphics2D destGD = destImg.createGraphics();
+//		destGD.drawString(authNumber, 20, 20);
+//
+//		ImageIO.write(destImg, "jpg", dest);
+//	}
+//
+//	public static void saveThumbnailImg(String path, String fileNm, int height, int width, String target) throws IOException {
+//		thumbnail(new File(path + fileNm), new File(path + target + fileNm), height, width);
+//	}
+
+}

+ 44 - 0
src/main/java/com/style24/persistence/TscBaseDomain.java

@@ -0,0 +1,44 @@
+package com.style24.persistence;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import lombok.Data;
+
+/**
+ * Domain의 기본 Super class
+ * Domain 클래스 생성 시 이 클래스를 상속받아서 처리한다.
+ *
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@SuppressWarnings("serial")
+@Data
+public class TscBaseDomain implements Serializable {
+
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private Integer regNo;
+
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private String regNm;
+
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private String regDt;
+
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private Integer updNo;
+
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private String updNm;
+
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private String updDt;
+
+	// 등록/수정화면 제어용(N:신규, U:상세/수정, C:복사)
+	private String mode;
+
+	// CRUD
+	private String crud;
+
+}

+ 25 - 0
src/main/java/com/style24/persistence/domain/Alarm.java

@@ -0,0 +1,25 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 알람 Domain
+ * 
+ * @author gagamel
+ * @since 2020. 11. 13
+ */
+@SuppressWarnings("serial")
+@Data
+public class Alarm extends TscBaseDomain {
+
+	private String alarmId;		// 알람ID
+	private String alarmTitle;	// 알람제목
+	private String alarmMsg;	// 알람메시지
+	private String useYn;		// 사용여부
+
+	private String fuserid;		// 사용자계정
+	private String fcallback;	// 발신자전화번호(회신번호)
+
+}

+ 21 - 0
src/main/java/com/style24/persistence/domain/AlarmReceiver.java

@@ -0,0 +1,21 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 알람수신자 Domain
+ * 
+ * @author gagamel
+ * @since 2020. 11. 13
+ */
+@SuppressWarnings("serial")
+@Data
+public class AlarmReceiver extends TscBaseDomain {
+
+	private String alarmId;		// 알람ID
+	private String cellPhnno;	// 휴대전화번호
+	private String receiverNm;	// 수신자명
+
+}

+ 24 - 0
src/main/java/com/style24/persistence/domain/AnswerPhase.java

@@ -0,0 +1,24 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 답변문구 Domain
+ * 
+ * @author gagamel
+ * @since 2020. 10. 29
+ */
+@SuppressWarnings("serial")
+@Data
+public class AnswerPhase extends TscBaseDomain {
+
+	private Integer ansSq;
+	private String siteCd;
+	private String ansClsf;
+	private String ansTitle;
+	private String ansContent;
+	private String useYn;
+
+}

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

@@ -0,0 +1,28 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 배치로그 Domain
+ *
+ * @author gagamel
+ * @since 2020. 12. 2
+ */
+@SuppressWarnings("serial")
+@Data
+public class BatchLog extends TscBaseDomain {
+
+	private Integer batchLogSq;	// 배치로그일련번호
+	private String batchId;		// 배치ID
+	private String batchStdt;	// 배치시작일시
+	private String batchEddt;	// 배치종료일시
+	private String batchStat;	// 배치상태
+
+	private String batchNm;		// 배치명
+	private String bizGb;		// 업무구분
+	private String batchFrq;	// 배치주기
+	private int runTime;		// 수행시간(초)
+
+}

+ 25 - 0
src/main/java/com/style24/persistence/domain/Clause.java

@@ -0,0 +1,25 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 약관 Domain
+ * 
+ * @author gagamel
+ * @since 2020. 10. 29
+ */
+@SuppressWarnings("serial")
+@Data
+public class Clause extends TscBaseDomain {
+
+	private Integer clauseSq;
+	private String siteCd;
+	private String clauseType;
+	private String clauseTitle;
+	private String clauseContent;
+	private String effectDt;
+	private String dispYn;
+
+}

+ 36 - 0
src/main/java/com/style24/persistence/domain/DataGoKr.java

@@ -0,0 +1,36 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 공공데이터포털을 이용한 통신판매사업자정보
+ * 
+ * @author gagamel
+ * @since 2020. 11. 18
+ */
+@SuppressWarnings("serial")
+@Data
+public class DataGoKr extends TscBaseDomain {
+
+	private String seq;				// 번호
+	private String bupNm;			// 상호명
+	private String repsntNm;		// 대표자명
+	private String sidoNm;			// 시도명
+	private String dmnNm;			// 도메인
+	private String mngStateCode;	// 영업상태코드(01:통신판매업신고, 02:통신판매업휴업, 03:통신판매업폐업, 04:직권취소, 05:타시군구이관, 06:타시군구전입, 07:직권말소, 08:영업재개)
+	private String permYmd;			// 신고일자
+
+	private String newaddr;			// 도로명주소
+	private String bupRegNo;		// 법인등록번호
+	private String wrkrNo;			// 사업자등록번호
+	private String orgAndTeamNm;	// 신고기관명
+	private String repTelno;		// 신고기관대표연락처
+	private String treArtcl;		// 취급품목(01:종합몰, 02:교육/도서/완구/오락, 03:가전, 04:컴퓨터/사무용품, 05:가구/수납용품, 06:의류/패션/잡화/뷰티, 07:레저/여행/공연, 08:건강/식품, 09:성인/성인용품, 10:자동차/자동차용품, 11:상품권, 12:기타)
+	private String silMet;			// 판매방식(01:TV홈쇼핑, 02:인터넷, 03:카탈로그, 04:신문잡지, 05:기타)
+	private String bupYn;			// 법인여부(0:개인, 1:법인)
+	private String apvPermMgtNo;	// 통신판매번호
+	private String hostSrvAddr;		// 호스트서버소재지
+
+}

+ 35 - 0
src/main/java/com/style24/persistence/domain/Envset.java

@@ -0,0 +1,35 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 환경설정 Domain
+ * 
+ * @author gagamel
+ * @since 2020. 10. 5
+ */
+@SuppressWarnings("serial")
+@Data
+public class Envset extends TscBaseDomain {
+
+	private Integer envsetSq;
+	private String siteCd;
+	private String envsetType;
+	private String envsetNm;
+	private String strSetVal1;
+	private String strSetVal2;
+	private String strSetVal3;
+	private String strSetVal4;
+	private String strSetVal5;
+	private String strSetVal6;
+	private String strSetVal7;
+	private String strSetVal8;
+
+	private String strSetNm1;
+	private String strSetNm2;
+	private String strSetNm3;
+	private String strSetNm4;
+
+}

+ 37 - 0
src/main/java/com/style24/persistence/domain/KCResultData.java

@@ -0,0 +1,37 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * KC인증번호
+ *
+ * @author gagamel
+ * @since 2020. 12. 2
+ */
+@SuppressWarnings("serial")
+@Data
+public class KCResultData extends TscBaseDomain {
+
+		private String certUid;
+		private String certOrganName;
+		private String certNum;
+		private String certState;
+		private String certDiv;
+		private String certDate;
+		private String certChgDate;
+		private String certChgReason;
+		private String firstCertNum;
+		private String productName;
+		private String brandName;
+		private String modelName;
+		private String categoryName;
+		private String importDiv;
+		private String makerName;
+		private String makerCntryName;
+		private String importerName;
+		private String remark;
+		private String signDate;
+
+}

+ 23 - 0
src/main/java/com/style24/persistence/domain/KCertifyNo.java

@@ -0,0 +1,23 @@
+package com.style24.persistence.domain;
+
+import java.util.Collection;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * KC인증번호
+ *
+ * @author gagamel
+ * @since 2020. 12. 2
+ */
+@SuppressWarnings("serial")
+@Data
+public class KCertifyNo extends TscBaseDomain {
+
+	private String resultCode;
+	private String resultMsg;
+	private Collection<KCResultData> resultData;
+
+}

+ 21 - 0
src/main/java/com/style24/persistence/domain/KCertifyNoOnly.java

@@ -0,0 +1,21 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * KC인증번호
+ *
+ * @author gagamel
+ * @since 2020. 12. 2
+ */
+@SuppressWarnings("serial")
+@Data
+public class KCertifyNoOnly extends TscBaseDomain {
+
+	private String resultCode;
+	private String resultMsg;
+	private KCResultData resultData;
+
+}

+ 46 - 0
src/main/java/com/style24/persistence/domain/NaverLowestPrice.java

@@ -0,0 +1,46 @@
+package com.style24.persistence.domain;
+
+import java.util.Collection;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 네이버 최저가 도메인
+ * 
+ * @author gagamel
+ * @since 2020. 12. 3
+ */
+@SuppressWarnings("serial")
+@Data
+public class NaverLowestPrice extends TscBaseDomain {
+
+	private String title;
+	private String link;
+	private String description;
+	private String lastBuildDate;
+	private int total;
+	private int start;
+	private int display;
+	private Collection<Item> items;
+
+	@Data
+	public class Item {
+		private String title;
+		private String link;
+		private String image;
+		private int lprice;
+		private int hprice;
+		private String mallName;
+		private String productId;
+		private String productType;
+		private String brand;
+		private String maker;
+		private String category1;
+		private String category2;
+		private String category3;
+		private String category4;
+	}
+
+}

+ 34 - 0
src/main/java/com/style24/persistence/domain/SsgDirectMessage.java

@@ -0,0 +1,34 @@
+package com.style24.persistence.domain;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * Direct Message(SMS, LMS, Kakao 등) Domain (신세계아이앤씨 SSG 모듈)
+ * 
+ * @author gagamel
+ * @since 2020. 11. 9
+ */
+@SuppressWarnings("serial")
+@Data
+public class SsgDirectMessage extends TscBaseDomain {
+
+	private String fuserid;			// 사용자계정
+	private String fsectioncode;	// 계층코드(SINC로부터 부여받은 코드값)
+	private String fcampcode;		// 캠페인코드(CRM전송 등에 이용)
+	private String fyellowid;		// KKO발신프로필키(카카오 전송을 위해 승인받은 프로필키)
+	private String fsubject;		// 메시지제목(LMS용)
+	private String fkkosubject;		// KKO친구툭전용제목
+	private String ftemplatekey;	// KKO템플릿키
+	private String fkkobutton;		// KKO버튼(링크기능, JSON 이용)
+	private String fmessage;		// 메시지본문
+	private String fkkoresendtype;	// KKO/KKF재발송메시지타입(SMS/LMS)
+	private String fkkoresendmsg;	// KKO/KKF재발송메시지내용
+	private String fdestine;		// 수신자전화번호
+	private String fcallback;		// 발신자전화번호(회신번호)
+
+	private String buttonNm;		// 버튼명
+	private String buttonUrl;		// 버튼 클릭 시 이동할 URL
+
+}

+ 100 - 0
src/main/java/com/style24/persistence/mybatis/shop/SsgDirectMessage.xml

@@ -0,0 +1,100 @@
+<?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.core.biz.dao.SsgDirectMessageDao">
+
+	<!-- SMS발송 생성 -->
+	<insert id="createSms" parameterType="SsgDirectMessage">
+		/* SsgDirectMessage.createSms */
+		INSERT INTO SSG_SEND_TRAN_SMS (
+		       FSEQ
+		     , FUSERID
+		     , FSECTIONCODE
+		     , FCAMPCODE
+		     , FMSGTYPE
+		     , FMESSAGE
+		     , FSENDDATE
+		     , FDESTINE
+		     , FCALLBACK
+		)
+		VALUES (
+		       NULL
+		     , #{fuserid}
+		     , #{fsectioncode}
+		     , #{fcampcode}
+		     , '0'
+		     , #{fmessage}
+		     , NOW()
+		     , #{fdestine}
+		     , #{fcallback}
+		)
+	</insert>
+	
+	<!-- LMS발송 생성 -->
+	<insert id="createLms" parameterType="SsgDirectMessage">
+		/* SsgDirectMessage.createLms */
+		INSERT INTO SSG_SEND_TRAN_MMS (
+		       FSEQ
+		     , FUSERID
+		     , FSECTIONCODE
+		     , FCAMPCODE
+		     , FMSGTYPE
+		     , FSUBJECT
+		     , FMESSAGE
+		     , FSENDDATE
+		     , FDESTINE
+		     , FCALLBACK
+		)
+		VALUES (
+		       NULL
+		     , #{fuserid}
+		     , #{fsectioncode}
+		     , #{fcampcode}
+		     , '2'
+		     , #{fsubject}
+		     , #{fmessage}
+		     , NOW()
+		     , #{fdestine}
+		     , #{fcallback}
+		)
+	</insert>
+	
+	<!-- 카카오알림톡발송 생성 -->
+	<insert id="createKakao" parameterType="SsgDirectMessage">
+		/* SsgDirectMessage.createKakao */
+		INSERT INTO SSG_SEND_TRAN_KKO (
+		       FSEQ            --메시지SEQ
+		     , FUSERID         --사용자계정
+		     , FSECTIONCODE    --계층코드(SINC로부터 부여받은 코드값)
+		     , FCAMPCODE       --캠페인코드(CRM전송 등에 이용)
+		     , FYELLOWID       --KKO발신프로필키(카카오 전송을 위해 승인받은 프로필키)
+		     , FKKOSUBJECT     --KKO친구툭전용제목
+		     , FTEMPLATEKEY    --KKO템플릿키
+		     , FKKOBUTTON      --KKO버튼(링크기능, JSON 이용)
+		     , FMSGTYPE        --메시지타입(4:KKO)
+		     , FMESSAGE        --메시지본문
+		     , FSENDDATE       --메시지발송시간(예약메시지인경우 해당 예약일시)
+		     , FKKORESENDTYPE  --KKO/KKF재발송메시지타입(SMS/LMS)
+		     , FKKORESENDMSG   --KKO/KKF재발송메시지내용
+		     , FDESTINE        --수신자전화번호
+		     , FCALLBACK       --발신자전화번호(회신번호)
+		)
+		VALUES (
+		       NULL
+		     , #{fuserid}
+		     , #{fsectioncode}
+		     , #{fcampcode}
+		     , #{fyellowid}
+		     , #{fkkosubject}
+		     , #{ftemplatekey}
+		     , #{fkkobutton}
+		     , '4'
+		     , #{fmessage}
+		     , NOW()
+		     , #{fkkoresendtype}
+		     , #{fkkoresendmsg}
+		     , #{fdestine}
+		     , #{fcallback}
+		)
+	</insert>
+
+</mapper>

+ 27 - 0
src/main/java/com/style24/persistence/mybatis/shop/TscAnswerPhase.xml

@@ -0,0 +1,27 @@
+<?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.admin.biz.dao.TsaAnswerPhaseDao">
+
+	<!-- 답변문구 조회 -->
+	<select id="getAnswerPhase" parameterType="Integer" resultType="AnswerPhase">
+		/* TsaAnswerPhase.getAnswerPhase */
+		 SELECT ANS_TITLE   --답변제목
+		      , ANS_CONTENT --답변내용
+		FROM    TB_ANS_PHASE
+		WHERE   ANS_SQ = #{ansSq}
+		AND     USE_YN = 'Y'
+	</select>
+
+	<!-- 문의용 답변문구 조회 -->
+	<select id="getQnaAnswerPhase" parameterType="AnswerPhase" resultType="AnswerPhase">
+		/* TsaAnswerPhase.getQnaAnswerPhase */
+		SELECT ANS_SQ      --답변일련번호
+		     , ANS_TITLE   --답변제목
+		     , ANS_CONTENT --답변내용
+		FROM   TB_ANS_PHASE
+		WHERE  ANS_SQ = #{ansSq}
+		AND    ANS_CLSF = #{ansClsf}
+		AND    USE_YN = 'Y'
+	</select>
+
+</mapper>

+ 17 - 0
src/main/java/com/style24/persistence/mybatis/shop/TscClause.xml

@@ -0,0 +1,17 @@
+<?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.core.biz.dao.TscClauseDao">
+
+	<!-- 약관 정보  -->
+	<select id="getClause" parameterType="Clause" resultType="String">
+		/* TscClause.getClause */
+		SELECT CLAUSE_CONTENT
+		FROM   TB_CLAUSE A
+		WHERE  CLAUSE_SQ = (SELECT MAX(CLAUSE_SQ)
+		                    FROM   TB_CLAUSE
+		                    WHERE  SITE_CD = #{siteCd}
+		                    AND    CLAUSE_TYPE = #{clauseType}
+		                   )
+	</select>
+
+</mapper>

+ 27 - 0
src/main/java/com/style24/persistence/mybatis/shop/TscEnvset.xml

@@ -0,0 +1,27 @@
+<?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.core.biz.dao.TscEnvsetDao">
+
+	<!-- 환경설정 정보 -->
+	<select id="getEnvset" parameterType="Envset" resultType="Envset">
+		/* TscEnvset.getEnvset */
+		SELECT SITE_CD
+		     , ENVSET_TYPE
+		     , ENVSET_NM
+		     , STR_SET_VAL1
+		     , STR_SET_VAL2
+		     , STR_SET_VAL3
+		     , STR_SET_VAL4
+		     , STR_SET_VAL5
+		     , STR_SET_VAL6
+		     , STR_SET_VAL7
+		     , STR_SET_VAL8
+		FROM   TB_ENVSET
+		WHERE  ENVSET_SQ = (SELECT MAX(ENVSET_SQ)
+		                    FROM   TB_ENVSET
+		                    WHERE  SITE_CD = #{siteCd}
+		                    AND    ENVSET_TYPE = #{envsetType}
+		                   )
+	</select>
+
+</mapper>