yjryu / pohang_tp star
Stormen123 2024-01-17
240117 김성훈 back-end 최초커밋
@ce5aa8853bda0e7b6a39356b173f3fed909259fa
 
.gitignore (added)
+++ .gitignore
@@ -0,0 +1,37 @@
+HELP.md
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
 
build.gradle (added)
+++ build.gradle
@@ -0,0 +1,56 @@
+plugins {
+	id 'java'
+	id 'org.springframework.boot' version '3.2.1'
+	id 'io.spring.dependency-management' version '1.1.4'
+}
+
+group = 'com.takensoft'
+version = '0.0.1-SNAPSHOT'
+
+java {
+	sourceCompatibility = '17'
+}
+
+repositories {
+	mavenCentral()
+}
+
+dependencies {
+	// postgresql jdbc
+	implementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0'
+	// 오라클 jdbc
+	implementation group: 'com.oracle.database.jdbc', name: 'ojdbc11', version: '21.8.0.0'
+	// 마리아 jdbc
+	implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '3.3.2'
+	// mysql jdbc
+	implementation group: 'com.mysql', name: 'mysql-connector-j', version: '8.0.33'
+	// mssql jdbc
+	implementation group: 'com.microsoft.sqlserver', name: 'mssql-jdbc', version: '12.4.2.jre11'
+
+	// mybatis
+	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
+
+	//lombok 라이브러리
+	compileOnly 'org.projectlombok:lombok'
+	annotationProcessor 'org.projectlombok:lombok'
+	testCompileOnly 'org.projectlombok:lombok'
+	testAnnotationProcessor 'org.projectlombok:lombok'
+	
+	// https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple
+	implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1'
+	// https://mvnrepository.com/artifact/org.json/json
+	implementation group: 'org.json', name: 'json', version: '20231013'
+	// https://mvnrepository.com/artifact/org.springframework.security/spring-security-crypto
+	implementation group: 'org.springframework.security', name: 'spring-security-crypto', version: '6.2.1'	
+	// https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api
+	//compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1'
+
+	// 기본
+	implementation 'org.springframework.boot:spring-boot-starter-web'
+	testImplementation 'org.springframework.boot:spring-boot-starter-test'
+
+}
+
+tasks.named('test') {
+	useJUnitPlatform()
+}
 
gradle/wrapper/gradle-wrapper.jar (Binary) (added)
+++ gradle/wrapper/gradle-wrapper.jar
Binary file is not shown
 
gradle/wrapper/gradle-wrapper.properties (added)
+++ gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Dec 27 17:54:29 KST 2023
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
 
gradlew (added)
+++ gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+#     and any embedded shellness will be escaped.
+#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+#     treated as '${Hostname}' itself on the command line.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
 
gradlew.bat (added)
+++ gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
 
settings.gradle (added)
+++ settings.gradle
@@ -0,0 +1,1 @@
+rootProject.name = 'taken_bi_manager'
 
src/main/java/com/takensoft/taken_bi_manager/DBConnectTest.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/DBConnectTest.java
@@ -0,0 +1,76 @@
+package com.takensoft.taken_bi_manager;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import com.takensoft.taken_bi_manager.common.connection.db.util.DBConnectionUtil;
+import com.takensoft.taken_bi_manager.common.connection.db.util.DataTypeUtil;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.ConnectionDB;
+import com.takensoft.taken_bi_manager.common.vo.CheckMessage;
+import com.takensoft.taken_bi_manager.common.vo.SystemCode.DatabaseType;
+import com.takensoft.taken_bi_manager.data.vo.ColumnData;
+import com.takensoft.taken_bi_manager.data.vo.DataTable;
+import com.takensoft.taken_bi_manager.data.vo.Dataset;
+
+public class DBConnectTest {
+	public static void main(String[] args) throws Exception {
+		
+		
+		DBConnectionUtil dbc = new DBConnectionUtil();
+		ConnectionDB cdb = new ConnectionDB();
+		
+		cdb.setDatabaseNm("crosswalks");
+		cdb.setDatabaseType(DatabaseType.POSTGRESQL);
+		cdb.setConectIp("210.180.118.83");
+		cdb.setConectPort("5432");
+		cdb.setConectNm("테스트 DB");
+		cdb.setUserId("takensoft");
+		cdb.setSchemaNm("crosswalk");
+	//	cdb.setUserPassword("Ts2020kr!@#");
+		cdb.setUserPassword("tts64103165!@");
+		
+		
+		dbc.createDatabaseDAO(cdb);				
+		CheckMessage checkMessage = dbc.dbConnectionCheck(cdb);				
+		List<Dataset>  datasets = dbc.getDBConnectionTableList(cdb);
+		
+		
+		for(Dataset temp  : datasets) {
+			System.out.println(temp.getTableNm());
+			System.out.println("---------------------------------------------------");
+			DataTable dt = new DataTable(temp);					
+			dbc.setDataTableByDBConnectionTable(cdb, dt);
+			for(List<Object> item : dt.getRowData()) {				
+				for(Object data : item) {					
+					System.out.println(data);
+				}
+			}
+		
+			 
+			/*
+			
+			cd = DataTypeUtil.convertDataTypeDbtoJavaList(cd, cdb.getDatabaseType());
+			for(ColumnData it: cd) {
+				System.out.println("컬럼명 : " + it.getColumnNm());
+				System.out.println("타입 : " +it.getDbDataType() + ": " + it.getDataTy());
+				System.out.println("길이 : " +it.getDataSize());
+				
+				if(it.getColumnNm().equals("cmmn_code_group")) {
+					
+				}
+			}			
+			System.out.println("---------------------------------------------------");
+			*/
+		}
+		
+		
+		
+		
+		
+		
+		System.out.println(checkMessage.getMessage());
+		
+		
+		
+	}
+}
 
src/main/java/com/takensoft/taken_bi_manager/MemberSelectTest.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/MemberSelectTest.java
@@ -0,0 +1,60 @@
+package com.takensoft.taken_bi_manager;
+
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.takensoft.taken_bi_manager.common.connection.api.util.ApiUtil;
+import com.takensoft.taken_bi_manager.common.connection.api.vo.ApiParam;
+import com.takensoft.taken_bi_manager.common.connection.api.vo.ConnectionApi;
+import com.takensoft.taken_bi_manager.common.util.CommonUtil;
+import com.takensoft.taken_bi_manager.data.util.DataTableConvert;
+import com.takensoft.taken_bi_manager.data.vo.DataTable;
+
+
+public class MemberSelectTest {
+		
+	public static void main(String[] args) throws Exception {
+		
+			DataTable dt = new DataTable();
+			
+			ConnectionApi ca = new ConnectionApi();
+			ca.setUrl("http://61.82.138.90:10971/aiSafetyCrossing/requestLogInfo.json");
+			ca.setType(1);
+			ca.setRequestType(1);
+			ca.setDepth("resultData>");
+			ApiParam apiParam1 = new ApiParam();
+			apiParam1.setKey("st_dt");
+			apiParam1.setValue("yyyy-MM-dd 10:22:00");
+			apiParam1.setDateForm(true);
+			apiParam1.setDateType("month");
+			apiParam1.setAddDate(0);
+			ca.getParams().add(apiParam1);
+			ApiParam apiParam2 = new ApiParam();
+			apiParam2.setKey("ed_dt");
+			apiParam2.setValue("yyyy-MM-dd 10:24:00");
+			apiParam2.setDateForm(true);
+			apiParam2.setDateType("month");
+			apiParam2.setAddDate(0);
+			ca.getParams().add(apiParam2);
+			ApiParam apiParam3 = new ApiParam();
+			apiParam3.setKey("apiKey");
+			apiParam3.setValue("f66b623060d0f20fee9663b8c0e445dc882cbf4ec4543630abd16c7960be7012");
+			ca.getParams().add(apiParam3);
+			
+			List<Map<String,Object>> data = ApiUtil.getApiDataList(ApiUtil.apiRequest(ca));
+			
+			dt = DataTableConvert.listMaptoDataset(data);
+			
+			int co = 0;
+			for(List<Object> temp: dt.getRowData()) {				
+				System.out.println(dt.getColumnDatas().get(co).getOrginlColumnNm() + " : " +   temp.get(co++));						
+				if(co == 9 ) co = 0;
+			}
+			
+			System.out.print(dt);
+	}
+}
 
src/main/java/com/takensoft/taken_bi_manager/TakenBiManagerApplication.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/TakenBiManagerApplication.java
@@ -0,0 +1,13 @@
+package com.takensoft.taken_bi_manager;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+class TakenBiManagerApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(TakenBiManagerApplication.class, args);
+	}
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/code/vo/CmmnCode.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/code/vo/CmmnCode.java
@@ -0,0 +1,51 @@
+package com.takensoft.taken_bi_manager.common.code.vo;
+
+import java.sql.Timestamp;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2023-12-28
+ * 
+ * 공통코드 객체
+ */
+@Getter
+@Setter
+public class CmmnCode {
+	
+	// 콩통코드  
+	private String cmmnCode;
+	
+	// 그룹코드
+	private String groupCode;
+	
+	// 코드명 
+	private String codeNm;
+	
+	// 코드 설명
+	private String codeDc;
+	
+	// 상위코드 (없으면 생략)
+	private String upperCode;
+	
+	// 코드 정렬순서 
+	private String codeOrdr;
+	
+	// 코드 사용여부
+	private boolean useAt;
+	
+	// 생성일
+	private Timestamp creatDt;
+	
+	// 생성자ID
+	private String creatId;
+	
+	// 수정일 
+	private Timestamp updtDt;
+		
+	// 수정자 ID
+	private String updtId;
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/code/vo/CmmnGroup.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/code/vo/CmmnGroup.java
@@ -0,0 +1,42 @@
+package com.takensoft.taken_bi_manager.common.code.vo;
+
+import java.sql.Timestamp;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2023-12-28
+ * 
+ * 공통코드 그룹 객체
+ */
+@Getter
+@Setter
+public class CmmnGroup {
+
+	// 공통코드 그룹 코드
+	private String groupCode;
+	
+	// 공통코드 그룹 코드 명 
+	private String groupCodeNm;
+	
+	// 공통코드 그룹 설명 
+	private String groupCodeDc;
+	
+	// 공통코드 그룹 사용여부
+	private boolean useAt;
+	
+	// 생성일
+	private Timestamp creatDt;
+	
+	// 생성자ID
+	private String creatId;
+	
+	// 수정일 
+	private Timestamp updtDt;
+		
+	// 수정자 ID
+	private String updtId;
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/config/FilterConfig.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/config/FilterConfig.java
@@ -0,0 +1,21 @@
+package com.takensoft.taken_bi_manager.common.config;
+
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.takensoft.taken_bi_manager.common.config.filter.SessionCheck;
+
+@Configuration
+public class FilterConfig {
+
+	@Bean
+    public FilterRegistrationBean<SessionCheck> sessionCheck() {
+        FilterRegistrationBean<SessionCheck> registrationBean = new FilterRegistrationBean<>();
+        registrationBean.setFilter(new SessionCheck());
+        registrationBean.addUrlPatterns("/*");
+        registrationBean.setOrder(1);
+        registrationBean.setName("sessionCheck");
+        return registrationBean;
+    }
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/config/MybatisConfig.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/config/MybatisConfig.java
@@ -0,0 +1,7 @@
+package com.takensoft.taken_bi_manager.common.config;
+
+public class MybatisConfig {
+
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/config/filter/SessionCheck.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/config/filter/SessionCheck.java
@@ -0,0 +1,53 @@
+package com.takensoft.taken_bi_manager.common.config.filter;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import org.springframework.web.filter.GenericFilterBean;
+import org.springframework.web.util.ContentCachingResponseWrapper;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.takensoft.taken_bi_manager.common.util.AuthUtil;
+import com.takensoft.taken_bi_manager.common.vo.CustomeResultMap;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+public class SessionCheck extends GenericFilterBean {
+
+	@Override
+	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+		 throws IOException, ServletException {		
+	
+		 HttpServletRequest  httpServletRequest = (HttpServletRequest)request;
+		 String uri =httpServletRequest.getRequestURI().toString();		 
+		 
+		 // 로그인 세션 처리 (없으면 세션 없음 메세지 전달)
+		 if(!uri.trim().contains("/login")) {
+			 HashMap<String, Object> LoginUserInfo = (HashMap<String, Object>)httpServletRequest.getSession().getAttribute(AuthUtil.LOGIN_USER_SESSION);
+			 if(LoginUserInfo == null) {
+				 ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper((HttpServletResponse) response);
+				 chain.doFilter(request, responseWrapper);
+				 CustomeResultMap map = new CustomeResultMap();
+				 map.getCheckMessage().setError("로그인 정보가 없습니다.");
+				 map.getCheckMessage().setStatus(100);
+				 map.getCheckMessage().setSuccess(false);
+				 
+				 String newResponse = new ObjectMapper().writeValueAsString(map);
+			     response.setContentType("application/json");
+			     response.setContentLength(newResponse.length());
+			     response.getOutputStream().write(newResponse.getBytes());				
+			 }else {
+				 System.out.println("세션있음");
+				 System.out.println(LoginUserInfo.get("user_id"));
+				 chain.doFilter(request, response);
+			 }
+		 }		 
+        
+	}
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/api/util/ApiUtil.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/api/util/ApiUtil.java
@@ -0,0 +1,126 @@
+package com.takensoft.taken_bi_manager.common.connection.api.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.takensoft.taken_bi_manager.common.connection.api.vo.ConnectionApi;
+import com.takensoft.taken_bi_manager.common.util.CommonUtil;
+import com.takensoft.taken_bi_manager.common.util.HTTPUtil;
+
+/**
+ * @author 김성원
+ * @since 2024.01.12
+ * 
+ * API 연계 관련 기능 리스트 입니다. 
+ */
+public class ApiUtil {
+
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.12
+	 * 
+	 * OpenApi 데이터 수집 기능 
+	 */
+	public static ConnectionApi apiRequest(ConnectionApi connApi) throws Exception {
+		ObjectMapper mapper = new ObjectMapper();
+
+		HTTPUtil httpcon = new HTTPUtil();	
+		connApi.setResult(httpcon.HttpConnectionApi(connApi.getUrl(),connApi.getRequestType(), connApi.getParams()));
+	
+        return connApi;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.12
+	 * 
+	 * OpenApi 데이터 수집 기능 
+	 */
+	public static List<Map<String,Object>>  getApiDataList (ConnectionApi connApi) throws Exception{
+		ObjectMapper mapper = new ObjectMapper();
+
+		// depth 리스트
+		String [] depthList = connApi.getDepth().split(">");
+		CommonUtil commonUtil = new CommonUtil();
+
+		// Return Type :  1=JSON, 2=XML
+		if(connApi.getType() ==2) {
+			// XML String to JSON String
+			String jsonStr = commonUtil.xmlStrToJsonStr(connApi.getResult());
+			connApi.setResult(jsonStr);
+		}
+		
+		JSONParser parser = new JSONParser();		
+		
+		JSONObject jsonObject = null;
+		JSONArray jsonArray = null;
+		
+		if(connApi.getResult().substring(0,1).equals("[")) {
+			jsonArray = (JSONArray) parser.parse(connApi.getResult());
+		}else {
+			jsonObject = (JSONObject) parser.parse(connApi.getResult());
+		}
+		
+		List<Map<String, Object>> apiDataList = new ArrayList<Map<String, Object>>();
+		
+		if(jsonArray == null) {
+			// jsonObject to Map
+			Map<String, Object> resultMap = new HashMap<String, Object>();
+			resultMap = commonUtil.jsonObjectToMap(jsonObject);
+		
+			int deptCount = 0;			
+			for(String depth : depthList) {
+				deptCount++;
+				depth = depth.trim();			
+				Object temp = (Object)resultMap.get(depth);
+				
+				// 리스트 판별
+				if(temp instanceof List) {
+					if(deptCount < depthList.length) {
+						List<Map<String, Object>> tempList = (List<Map<String, Object>>) temp;
+						resultMap =  tempList.get(0);
+					}else {
+						apiDataList = (List<Map<String, Object>>) temp;
+					}		
+				}else {
+					resultMap = (Map<String, Object>) temp;	
+				}
+			}
+		}else {
+			apiDataList = (List<Map<String, Object>>)jsonArray;
+		}
+		
+		int max = 0;
+		int indx = 0;
+		
+		// 최대 길이의 키값을 가진 객체 구하기 		
+		for(int i = 0 ; i < apiDataList.size() ; i++){
+			if(apiDataList.get(i).keySet().size() > max) {
+				max = apiDataList.get(i).keySet().size();
+				indx = i;
+			}			
+		}
+		
+		// 빈정보 공백으로 채우기 
+		for(Map<String, Object> item : apiDataList ) {
+			if(max != item.size()) {
+				for (Map.Entry<String, Object> entry : apiDataList.get(indx).entrySet()) 
+				{
+					if(item.get(entry.getKey()) == null) {
+						item.put(entry.getKey(),"");
+					}
+				}
+			}
+		}		
+		
+		return apiDataList;
+	}
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/api/vo/ApiParam.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/api/vo/ApiParam.java
@@ -0,0 +1,71 @@
+package com.takensoft.taken_bi_manager.common.connection.api.vo;
+
+
+
+import java.io.Serializable;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2021.11.02
+ * 
+ * Api 커넥션의 파라미터 정보를 담습니다. 
+ */
+@Getter
+@Setter
+public class ApiParam implements Serializable {
+	
+	/**
+	 * 시리얼 버전
+	 */	
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 파라미터 DB저장 Key값
+	 */
+	private String paramId;	
+	
+	/**
+	 *  파라미터 순서
+	 */
+	private int index;
+	
+	/**
+	 * 파라미터 Key값
+	 */
+	private String key;
+	
+	/**
+	 * 파라미터 value값
+	 */
+	private Object value;
+	
+	/**
+	 * encode 제외 변수
+	 */
+	private boolean disableDecode;
+	
+	/**
+	 * 날짜계산 변수
+	 */
+	private boolean dateForm = false;	
+	
+	
+	/**
+	 * 날자 제어 타입(year, month, day) 
+	 */
+	private String dateType;
+	
+	/**
+	 * 날자 제어변수 
+	 */
+	private int addDate = 0;
+
+	
+	public static long getSerialversionuid() {
+		return serialVersionUID;
+	}
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/api/vo/ConnectionApi.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/api/vo/ConnectionApi.java
@@ -0,0 +1,92 @@
+package com.takensoft.taken_bi_manager.common.connection.api.vo;
+
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2021.11.02
+ * 
+ * Api 커넥션 정보를 담는 Class 
+ */
+@Getter
+@Setter
+public class ConnectionApi implements Serializable {
+
+	
+	/**
+	 * 연계 PAI 제목
+	 */	
+	private String title;
+	
+	/**
+	 * 연계 url
+	 */	
+	private String url;
+
+	/**
+	 * 연계 타입 1 = json, 2=xml
+	 */	
+	private int type;
+	
+	/**
+	 * 연계 타입 1 = post, 2 = get
+	 */	
+	private int requestType;
+	
+	/**
+	 * 연계 결과
+	 */	
+	private String result;
+	
+	/**
+	 * 뎁스설정  구분자 > 
+	 */	
+	private String depth;
+	
+	/**
+	 * 파라미터 리스트
+	 */	
+	private List<ApiParam> params = new  ArrayList<ApiParam>();
+	
+	/**
+	 * 데이터(행,열)의 컬럼인 Row의 Index
+	 */
+	private int rowDataColumnIndex;
+	
+	/**
+	 * 데이터(행,열)의 Row 시작 Index
+	 */
+	private int startRowIndex;
+	
+	/**
+	 * 데이터(행,열)의 Cell 시작 Index
+	 */
+	private int startCellIndex;
+	
+	public ConnectionApi() {
+		this.params = new ArrayList<ApiParam>();
+		this.type = 1;
+	}	
+
+	
+	public Map<String, Object> paramstoMap(){
+		Map<String, Object> result = new HashMap<String,Object>();
+		
+		// this.params -> map 
+		for(int i=0; i< this.params.size(); i++	) {
+			result.put(this.params.get(i).getKey(), this.params.get(i).getValue());
+		}
+		
+		return result;
+	}
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/dao/DatabaseDAO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/dao/DatabaseDAO.java
@@ -0,0 +1,239 @@
+package com.takensoft.taken_bi_manager.common.connection.db.dao;
+
+
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.takensoft.taken_bi_manager.common.connection.db.vo.ConnectionDB;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.TableBasicInfo;
+import com.takensoft.taken_bi_manager.data.vo.ColumnData;
+import com.takensoft.taken_bi_manager.data.vo.DataTable;
+import com.takensoft.taken_bi_manager.data.vo.Dataset;
+
+
+/**
+ * @author 김성원
+ * @since 2024.01.09
+ * 
+ * 데이터베이스 접속 모듈에 관련된 SQL문에 접근하는 DAO 추상 Class입니다.
+ */
+public abstract class DatabaseDAO {
+
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * SqlSessionTemplate 생성 메서드 입니다.
+	 */
+	public abstract void createConnector (ConnectionDB db) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 접속한 데이터베이스의 테이블 목록 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	public abstract List<Dataset> getDBConnectionTableList(ConnectionDB db) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커넥션된 데이터베이스의 테이블의 컬럼 정보 조회 (DB 기준 데이터 타입, 데이터 크기 등)
+	 */
+	public abstract List<ColumnData> getDBConnectionTableColumnList (Dataset dataset) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 특정 테이블의 데이터 목록 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	public abstract List<LinkedHashMap<String, Object>> getDBConnectionTableDataList (DataTable datatable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 특정 테이블의 데이터 총 개수 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	public abstract int getDBConnectionTableDataTotalRows (DataTable datatable) throws Exception;
+	
+		
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 특정 테이블의 데이터 목록 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	public abstract List<LinkedHashMap<String, Object>> getDBConnectionCustomQueryDataList (DataTable datatable) throws Exception;
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 조회 없는 실행형 쿼리 
+	 */
+	public abstract int executeCustomQuery (DataTable datatable) throws Exception;
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.097
+	 * 
+	 * 특정 테이블의 데이터 총 개수 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	public abstract int getDBConnectionCustomQueryDataTotalRows (DataTable datatable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * DB연계 데이터 목록 조회 (초기 DB화 때에 등록한 컬럼만 가지고 옴)
+	 */
+	public abstract List<LinkedHashMap<String, Object>> getDBCollectionQueryDataList (DataTable datatable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * DB연계 데이터 목록 총 갯수 조회
+	 */
+	public abstract int getDBCollectionQueryDataTotalRows (DataTable datatable) throws Exception;
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커트텀 쿼리 지정된 PK의 중복 데이터 수 (지정된 PK로 Table 생성이 가능한지 알아보기 위함) 
+	 */
+	public abstract int getCustomQueryPrimaryOverlapCount (DataTable datatable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * DataSource Close
+	 */
+	public abstract void dbConnectionClose() throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 쿼리 실행후, 실행한 쿼리문 조회
+	 */
+	public abstract String getQuery (String id, Object parameter) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커넥션된 데이터베이스의 실제 테이블 생성(pk 존재유)
+	 */
+	public abstract int datasetTableCreate(DataTable datatable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커넥션된 데이터베이스의 실제 테이블 생성(pk 존재무)
+	 */
+	public abstract int datasetDefaultTableCreate(DataTable datatable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 커넥션된 데이터 베이스 데이터 업데이트(pk 존재무)
+	 */
+	public abstract void datasetDataUpdate(DataTable datatable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 데이터 셋의 ROW 삭제
+	 */
+	public abstract void datasetDataDelete(DataTable datatable) throws Exception;
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 커넥션된 데이터 베이스 중복체크 (pk 존재무)
+	 */
+	public abstract int duplicateCheckTableName(Map info) throws Exception;
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 데이터 셋의 컬럼 정보 목록 조회 SQL에 접근하는 메소드 입니다.(페이징)
+	 */
+	public abstract List<LinkedHashMap<String, Object>> getRowData (DataTable dataTable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 데이터 셋의 컬럼 정보 목록 조회 SQL에 접근하는 메소드 입니다.(x)
+	 */
+	public abstract List<LinkedHashMap<String, Object>> getRowDataAll (DataTable dataTable) throws Exception;
+	
+	/**
+	 * @author 최정우
+	 * @since 2019.12.09
+	 * 
+	 * 데이터 셋의 컬럼 정보 목록 총 갯수 조회 메소드 입니다.
+	 */
+	public abstract int getRowDataTotalRows (DataTable dataTable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.1.12
+	 * 
+	 *  데이터 셋의 비우기 (데이터 셋 내용삭제)
+	 */
+	public abstract int emptyDataset (DataTable dataTable) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.1.20
+	 * 
+	 *  실제 생성된 컬럼 변경
+	 */
+	public abstract int  tableColumnChange (TableBasicInfo tableBasicInfo) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.1.20
+	 * 
+	 *  실제 생성된 테이블 PK처리
+	 */
+	public abstract int  changePrimaryKey (TableBasicInfo tableBasicInfo) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.1.20
+	 * 
+	 *  AI PK 생성 
+	 */
+	public abstract int  createAutoIncrement (TableBasicInfo tableBasicInfo) throws Exception;
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.09.30
+	 * 
+	 *  테이블 명 변경
+	 *   
+	 */
+	public abstract void updateTableMetaInfo(DataTable dataTable)  throws Exception;
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/dao/MariadbDAO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/dao/MariadbDAO.java
@@ -0,0 +1,294 @@
+package com.takensoft.taken_bi_manager.common.connection.db.dao;
+
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.springframework.stereotype.Repository;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.takensoft.taken_bi_manager.common.connection.db.util.DBConnectionConfig;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.ConnectionDB;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.TableBasicInfo;
+import com.takensoft.taken_bi_manager.common.util.StringUtil;
+import com.takensoft.taken_bi_manager.data.vo.ColumnData;
+import com.takensoft.taken_bi_manager.data.vo.DataTable;
+import com.takensoft.taken_bi_manager.data.vo.Dataset;
+
+
+/**
+	 * @author 김성원
+	 * @since 2024.01.09
+ * 
+ * Mariadb 접속 모듈에 관련된 SQL문에 접근하는 DAO Class입니다.
+ */
+@Repository
+public class MariadbDAO extends DatabaseDAO {
+	
+	public MariadbDAO () {}
+	
+	public MariadbDAO (ConnectionDB db) throws Exception {
+		this.createConnector(db);
+	}
+	
+	private DBConnectionConfig dbUtil = null;
+	
+	public DBConnectionConfig getDbUtil() {
+		return dbUtil;
+	}
+	public void setDbUtil(DBConnectionConfig dbUtil) {
+		this.dbUtil = dbUtil;
+	}
+
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * SqlSessionTemplate 생성 메서드 입니다.
+	 */
+	@Override
+	public void createConnector (ConnectionDB db) throws Exception {
+		dbUtil = new DBConnectionConfig();
+		dbUtil.mybatisSqlTemplateCreate(db);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 접속한 데이터베이스의 테이블 목록 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	@Override
+	public List<Dataset> getDBConnectionTableList(ConnectionDB db) throws Exception {
+		try {
+			return dbUtil.getTemplate().selectList("MariadbDAO.getDBConnectionTableList", db);
+		} catch (Exception e) {
+			return new ArrayList<Dataset>();
+		}
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커넥션된 데이터베이스의 테이블의 컬럼 정보 조회 (DB 기준 데이터 타입, 데이터 크기 등)
+	 */
+	@Override
+	public List<ColumnData> getDBConnectionTableColumnList(Dataset dataset) throws Exception {
+		return dbUtil.getTemplate().selectList("MariadbDAO.getDBConnectionTableColumnList", dataset);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 특정 테이블의 데이터 목록 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	@Override
+	public List<LinkedHashMap<String, Object>> getDBConnectionTableDataList (DataTable datatable) throws Exception {
+		return dbUtil.getTemplate().selectList("MariadbDAO.getDBConnectionTableDataList", datatable);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 특정 테이블의 데이터 총 개수 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	@Override
+	public int getDBConnectionTableDataTotalRows (DataTable datatable) throws Exception {
+		return dbUtil.getTemplate().selectOne("MariadbDAO.getDBConnectionTableDataTotalRows", datatable);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커스텀 테이블 데이터 조회 (페이징사용 유무에 따라 페이징 처리) SQL에 접근하는 메소드 입니다.
+	 */
+	@Override
+	public List<LinkedHashMap<String, Object>> getDBConnectionCustomQueryDataList (DataTable datatable) throws Exception {
+		return dbUtil.getTemplate().selectList("MariadbDAO.getDBConnectionCustomQueryDataList", datatable);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커스텀 테이블 데이터 목록 총 갯수 조회 SQL에 접근하는 메소드 입니다.
+	 */
+	@Override
+	public int getDBConnectionCustomQueryDataTotalRows (DataTable datatable) throws Exception {
+		return dbUtil.getTemplate().selectOne("MariadbDAO.getDBConnectionCustomQueryDataTotalRows", datatable);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * DB연계 데이터 목록 조회 (초기 DB화 때에 등록한 컬럼만 가지고 옴)
+	 */
+	@Override
+	public List<LinkedHashMap<String, Object>> getDBCollectionQueryDataList (DataTable datatable) throws Exception {
+		return dbUtil.getTemplate().selectList("MariadbDAO.getDBCollectionQueryDataList", datatable);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * DB연계 데이터 목록 총 갯수 조회
+	 */
+	@Override
+	public int getDBCollectionQueryDataTotalRows (DataTable datatable) throws Exception {
+		return dbUtil.getTemplate().selectOne("MariadbDAO.getDBCollectionQueryDataTotalRows", datatable);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커트텀 쿼리 지정된 PK의 중복 데이터 수 (지정된 PK로 Table 생성이 가능한지 알아보기 위함) 
+	 */
+	@Override
+	public int getCustomQueryPrimaryOverlapCount(DataTable datatable) throws Exception {
+		return dbUtil.getTemplate().selectOne("MariadbDAO.getCustomQueryPrimaryOverlapCount", datatable);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * SqlSessionTemplate Close
+	 */
+	@Override
+	public void dbConnectionClose() throws Exception {
+		dbUtil.close();
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 쿼리 실행후, 실행한 쿼리문 조회
+	 */
+	@Override
+	public String getQuery (String id, Object parameter) throws Exception {
+		SqlSessionTemplate template = dbUtil.getTemplate();
+		
+		id = "OracleDAO." + id;
+		
+	    String sql = template.getConfiguration().getMappedStatement(id).getBoundSql(parameter).getSql();
+	    List<ParameterMapping> paramMap = template.getConfiguration().getMappedStatement(id).getBoundSql(parameter).getParameterMappings();
+	    
+	    ObjectMapper mapper = new ObjectMapper();
+	    String json = mapper.writeValueAsString(parameter);
+	    HashMap<String, Object> params = mapper.readValue(json, new TypeReference<HashMap<String, Object>>(){});
+	    for (ParameterMapping par : paramMap) {
+	        String param = StringUtil.toString(params.get(par.getProperty()));
+	        if(parameter == null)
+	            sql = sql.replaceFirst("\\?", "NULL");
+	        else
+	            sql = sql.replaceFirst("\\?", "'" + param + "'");
+	    }
+	    System.out.println("");
+	    System.out.println("---------------------- OracleDAO sql --------------------");
+	    System.out.println(sql);
+	    System.out.println("");
+	    return sql;
+	}
+
+	@Override
+	public int datasetTableCreate(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("MariadbDAO.datasetTableCreate", datatable);
+	}
+
+	@Override
+	public int datasetDefaultTableCreate(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("MariadbDAO.datasetDefaultTableCreate", datatable);
+	}
+
+	@Override
+	public void datasetDataUpdate(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		dbUtil.getTemplate().update("MariadbDAO.datasetDataUpdate", datatable);
+	}
+
+	@Override
+	public int duplicateCheckTableName(Map info) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectOne("MariadbDAO.duplicateCheckTableName", info);
+	}
+
+	@Override
+	public List<LinkedHashMap<String, Object>> getRowData(DataTable dataTable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectList("MariadbDAO.getRowData", dataTable);
+	}
+
+	@Override
+	public List<LinkedHashMap<String, Object>> getRowDataAll(DataTable dataTable) throws Exception {
+		return dbUtil.getTemplate().selectList("MariadbDAO.getRowDataAll", dataTable);		
+	}
+
+	@Override
+	public int getRowDataTotalRows(DataTable dataTable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectOne("MariadbDAO.getRowDataTotalRows", dataTable);		
+	}
+
+	@Override
+	public int emptyDataset(DataTable dataTable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().delete("MariadbDAO.emptyDataset", dataTable);		
+	}
+
+	@Override
+	public int tableColumnChange(TableBasicInfo tableBasicInfo) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("MariadbDAO.tableColumnChange", tableBasicInfo);	
+	}
+
+
+	@Override
+	public int changePrimaryKey(TableBasicInfo tableBasicInfo) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("MariadbDAO.changePromaryKey", tableBasicInfo);	
+	}
+
+
+	@Override
+	public void datasetDataDelete(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		dbUtil.getTemplate().delete("MariadbDAO.datasetDataDelete", datatable);	
+	}
+
+	@Override
+	public int createAutoIncrement(TableBasicInfo tableBasicInfo) throws Exception {
+		
+		return dbUtil.getTemplate().update("MariadbDAO.createAutoIncrement", tableBasicInfo);	
+
+	}
+
+	@Override
+	public int executeCustomQuery(DataTable datatable) throws Exception {
+	
+		return dbUtil.getTemplate().update("MariadbDAO.executeCustomQuery", datatable);	
+	}
+
+
+	@Override
+	public void updateTableMetaInfo(DataTable dataTable) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/dao/PostgresqlDAO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/dao/PostgresqlDAO.java
@@ -0,0 +1,231 @@
+package com.takensoft.taken_bi_manager.common.connection.db.dao;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.mybatis.spring.SqlSessionTemplate;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.takensoft.taken_bi_manager.common.connection.db.util.DBConnectionConfig;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.ConnectionDB;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.TableBasicInfo;
+import com.takensoft.taken_bi_manager.common.util.StringUtil;
+import com.takensoft.taken_bi_manager.data.vo.ColumnData;
+import com.takensoft.taken_bi_manager.data.vo.DataTable;
+import com.takensoft.taken_bi_manager.data.vo.Dataset;
+
+
+
+public class PostgresqlDAO  extends DatabaseDAO {
+
+	public PostgresqlDAO () {}
+	
+	public PostgresqlDAO (ConnectionDB db) throws Exception {
+		this.createConnector(db);
+	}
+	
+	private DBConnectionConfig dbUtil = null;
+	
+	public DBConnectionConfig getDbUtil() {
+		return dbUtil;
+	}
+	public void setDbUtil(DBConnectionConfig dbUtil) {
+		this.dbUtil = dbUtil;
+	}
+	
+	
+	@Override
+	public void createConnector(ConnectionDB db) throws Exception {
+		// TODO Auto-generated method stub
+		dbUtil = new DBConnectionConfig();
+		dbUtil.mybatisSqlTemplateCreate(db);
+	}
+
+	@Override
+	public List<Dataset> getDBConnectionTableList(ConnectionDB db) throws Exception {
+		// TODO Auto-generated method stub
+		try {
+			return dbUtil.getTemplate().selectList("PostgresqlDAO.getDBConnectionTableList", db);
+		} catch (Exception e) {
+			return new ArrayList<Dataset>();
+		}
+	}
+
+	@Override
+	public List<ColumnData> getDBConnectionTableColumnList(Dataset dataset) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectList("PostgresqlDAO.getDBConnectionTableColumnList", dataset);
+	}
+
+	@Override
+	public List<LinkedHashMap<String, Object>> getDBConnectionTableDataList(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectList("PostgresqlDAO.getDBConnectionTableDataList", datatable);
+	}
+
+	@Override
+	public int getDBConnectionTableDataTotalRows(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectOne("PostgresqlDAO.getDBConnectionTableDataTotalRows", datatable);
+	}
+
+	@Override
+	public List<LinkedHashMap<String, Object>> getDBConnectionCustomQueryDataList(DataTable datatable)
+			throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectList("PostgresqlDAO.getDBConnectionCustomQueryDataList", datatable);
+	}
+
+	@Override
+	public int executeCustomQuery(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("PostgresqlDAO.executeCustomQueryDataList", datatable);
+	}
+
+	@Override
+	public int getDBConnectionCustomQueryDataTotalRows(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectOne("PostgresqlDAO.getDBConnectionCustomQueryDataTotalRows", datatable);
+	}
+
+	@Override
+	public List<LinkedHashMap<String, Object>> getDBCollectionQueryDataList(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectList("PostgresqlDAO.getDBCollectionQueryDataList", datatable);
+	}
+
+	@Override
+	public int getDBCollectionQueryDataTotalRows(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectOne("PostgresqlDAO.getDBCollectionQueryDataTotalRows", datatable);
+	}
+
+	@Override
+	public int getCustomQueryPrimaryOverlapCount(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectOne("getCustomQueryPrimaryOverlapCount.getCustomQueryPrimaryOverlapCount", datatable);
+	}
+
+	@Override
+	public void dbConnectionClose() throws Exception {
+		dbUtil.close();
+	}
+
+	@Override
+	public String getQuery(String id, Object parameter) throws Exception {
+		SqlSessionTemplate template = dbUtil.getTemplate();
+		
+		id = "PostgresqlDAO." + id;
+		
+	    String sql = template.getConfiguration().getMappedStatement(id).getBoundSql(parameter).getSql();
+	    List<ParameterMapping> paramMap = template.getConfiguration().getMappedStatement(id).getBoundSql(parameter).getParameterMappings();
+	    
+	    ObjectMapper mapper = new ObjectMapper();
+	    String json = mapper.writeValueAsString(parameter);
+	    HashMap<String, Object> params = mapper.readValue(json, new TypeReference<HashMap<String, Object>>(){});
+	    for (ParameterMapping par : paramMap) {
+	        String param = StringUtil.toString(params.get(par.getProperty()));
+	        if(parameter == null)
+	            sql = sql.replaceFirst("\\?", "NULL");
+	        else
+	            sql = sql.replaceFirst("\\?", "'" + param + "'");
+	    }
+	    System.out.println("");
+	    System.out.println("---------------------- PostGresqlDAO sql --------------------");
+	    System.out.println(sql);
+	    System.out.println("");
+	    return sql;
+	}
+
+	@Override
+	public int datasetTableCreate(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("PostgresqlDAO.datasetTableCreate", datatable);
+	}
+
+	@Override
+	public int datasetDefaultTableCreate(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("PostgresqlDAO.datasetDefaultTableCreate", datatable);
+	}
+
+	@Override
+	public void datasetDataUpdate(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		dbUtil.getTemplate().update("PostgresqlDAO.datasetDataUpdate", datatable);
+	}
+
+	@Override
+	public void datasetDataDelete(DataTable datatable) throws Exception {
+		// TODO Auto-generated method stub
+		dbUtil.getTemplate().update("PostgresqlDAO.datasetDataUpdate", datatable);
+	}
+
+	@Override
+	public int duplicateCheckTableName(Map info) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectOne("PostgresqlDAO.duplicateCheckTableName", info);
+	}
+
+	@Override
+	public List<LinkedHashMap<String, Object>> getRowData(DataTable dataTable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectList("PostgresqlDAO.getRowData", dataTable);
+	}
+
+	@Override
+	public List<LinkedHashMap<String, Object>> getRowDataAll(DataTable dataTable) throws Exception {
+		// TODO Auto-generated method stub
+		
+		ObjectMapper mapper = new ObjectMapper();
+		System.out.println("dataTable :::: " + mapper.writeValueAsString(dataTable));
+		
+		return dbUtil.getTemplate().selectList("PostgresqlDAO.getRowDataAll", dataTable);		
+	}
+
+	@Override
+	public int getRowDataTotalRows(DataTable dataTable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().selectOne("PostgresqlDAO.getRowDataTotalRows", dataTable);
+	}
+
+	@Override
+	public int emptyDataset(DataTable dataTable) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().delete("PostgresqlDAO.emptyDataset", dataTable);
+	}
+
+	@Override
+	public int tableColumnChange(TableBasicInfo tableBasicInfo) throws Exception {
+		// TODO Auto-generated method stub
+		ObjectMapper mapper = new ObjectMapper();
+		
+		System.out.println("tableColumnChange" + mapper.writeValueAsString(tableBasicInfo));
+		return dbUtil.getTemplate().update("PostgresqlDAO.tableColumnChange", tableBasicInfo);	
+	}
+
+	@Override
+	public int changePrimaryKey(TableBasicInfo tableBasicInfo) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("PostgresqlDAO.changePromaryKey", tableBasicInfo);	
+	}
+
+	@Override
+	public int createAutoIncrement(TableBasicInfo tableBasicInfo) throws Exception {
+		// TODO Auto-generated method stub
+		return dbUtil.getTemplate().update("PostgresqlDAO.createAutoIncrement", tableBasicInfo);	
+	}
+	
+
+	@Override
+	public void updateTableMetaInfo(DataTable dataTable) throws Exception {
+		dbUtil.getTemplate().update("PostgresqlDAO.updateTableMetaInfo", dataTable);
+		
+	}
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/mybatis/config/config.xml (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/mybatis/config/config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
+
+<configuration>
+	<settings>
+		<setting name="cacheEnabled" value="true"/> <!-- mapper 캐시 전역 사용여부 -->
+		<setting name="lazyLoadingEnabled" value="false"/> <!-- mybatis 지연 로딩 사용여부 -->
+		<setting name="multipleResultSetsEnabled" value="true"/> <!-- 한개의 구문에서 여러개의  ResultSet 허용 여부 -->
+		<setting name="useColumnLabel" value="true"/> <!-- 컬럼명 대신 컬럼라벨 사용 여부 -->
+		<setting name="useGeneratedKeys" value="false"/> <!-- 키자동생성 -->
+		<setting name="defaultExecutorType" value="SIMPLE"/>
+		<setting name="defaultStatementTimeout" value="25000"/>
+		<setting name="callSettersOnNulls" value="true"/><!-- 조회 조회시, null값 무조건 허용 -->
+	</settings>
+
+	<typeAliases>
+		
+		<typeAlias type="com.takensoft.taken_bi_manager.data.vo.Dataset" alias="Dataset"/>
+		<typeAlias type="com.takensoft.taken_bi_manager.data.vo.ColumnData" alias="ColumnData"/>
+		<typeAlias type="com.takensoft.taken_bi_manager.data.vo.DataTable" alias="DataTable"/>
+		<typeAlias type="com.takensoft.taken_bi_manager.common.connection.db.vo.TableBasicInfo" alias="TableBasicInfo"/>
+		<typeAlias type="com.takensoft.taken_bi_manager.common.connection.db.vo.ConnectionDB" alias="ConnectionDB"/>
+		
+		
+		<!-- etl -->
+		
+		<!--
+		<typeAlias type="kr.co.sppartners.etl.common.collection.util.db.vo.TableBasicInfo" alias="TableBasicInfo"/>
+		<typeAlias type="kr.co.sppartners.etl.common.data.vo.DataTable" alias="DataTable"/>
+		
+		<typeAlias type="kr.co.sppartners.etl.data.dataset.vo.DatasetPost" alias="DatasetPost"/>
+		
+		<typeAlias type="kr.co.sppartners.etl.data.dataset.vo.DBCollection" alias="DBCollection"/>
+		<typeAlias type="kr.co.sppartners.etl.data.dataset.vo.CollectionTable" alias="CollectionTable"/>		
+		
+		-->
+		
+		
+	</typeAliases>
+	
+	<!-- 사용안함 
+	<typeHandlers>
+		<typeHandler handler="kr.co.sppartners.etl.config.MybatisStringTypeHandler"/>
+	</typeHandlers>
+	-->
+</configuration>
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/mybatis/sql/mariadb-SQL.xml (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/mybatis/sql/mariadb-SQL.xml
@@ -0,0 +1,571 @@
+<?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">
+
+<!--
+	작성자 : 최정우
+	작성일 : 2019.11.17
+	내용 : Mariadb 접속 모듈에 관련된 SQL입니다.
+ -->
+<mapper namespace="MariadbDAO">
+
+	<!--
+		작성자 : 최정우
+		작성일 : 2020.01.27
+		내용 : 커넥션된 데이터베이스의 테이블 목록 조회 SQL입니다.
+	 -->
+	<select id="getDBConnectionTableList" parameterType="ConnectionDB" resultType="Dataset">
+		SELECT
+			TABLE_SCHEMA AS databaseNm
+		    , TABLE_NAME AS tableNm
+		FROM
+			INFORMATION_SCHEMA.TABLES
+		WHERE
+			TABLE_SCHEMA = #{databaseNm}
+		ORDER BY
+			tableNm ASC
+	</select>
+	
+	<!--
+	 	작성자 : 최정우
+		작성일 : 2020.01.27
+		내용 : 커넥션된 데이터베이스의 테이블의 컬럼 정보 조회 (DB 기준 데이터 타입, 데이터 크기 등)
+	 -->
+	<select id="getDBConnectionTableColumnList" parameterType="Dataset" resultType="ColumnData">
+		SELECT
+			TABLE_SCHEMA AS databaseNm
+		    , TABLE_NAME AS tableNm
+			, COLUMN_NAME AS columnNm
+			, COLUMN_NAME AS displyColumnNm
+			, COLUMN_NAME AS orginlColumnNm
+			, DATA_TYPE AS dbDataType
+		    , CHARACTER_MAXIMUM_LENGTH AS dataSize
+		    , ORDINAL_POSITION AS ordr
+		    , CASE WHEN COLUMN_KEY = 'PRI' then true else false end as "pkAt"
+		    , CASE WHEN COLUMN_KEY = 'UNI' then true else false end as "uniqeAt"
+		FROM
+			INFORMATION_SCHEMA.COLUMNS
+		WHERE
+			TABLE_SCHEMA = #{databaseNm}
+		AND
+			TABLE_NAME = #{tableNm}
+		
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: 커넥션된 데이터베이스의 테이블의 데이터 목록 조회 SQL입니다.(페이징)
+	 -->
+	<select id="getDBConnectionTableDataList" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			*
+		FROM
+			`${databaseNm}`.`${tableNm}`
+		WHERE 1 = 1
+		
+		<!-- 검색 -->
+		<choose>
+			<!-- 컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<when test="columnDatas != null and columnDatas.size() > 0 and (searchCondition == null or searchCondition == '') and searchKeyword != null and searchKeyword != ''">
+				AND
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator=" OR " close=")">
+					<foreach item="keyword" index="index2" collection="searchKeywordList" separator=" OR ">
+					`${item.columnName}` LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</foreach>
+			</when>
+			<!-- //컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<!-- 컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+			<otherwise>
+				<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+				AND
+					<foreach item="keyword" index="index2" collection="searchKeywordList" open="(" separator=" OR " close=")">
+					`${searchCondition}` LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</if>
+			</otherwise>
+			<!-- //컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+		</choose>
+		<!-- //검색 -->
+		
+		<!-- 정렬 -->
+		<if test="order != null and order != ''">
+			ORDER BY `${order}`
+			<choose>
+				<!-- 오름차순일 때 -->
+				<when test="isOrderASC == true">
+					ASC
+				</when>
+				<!-- //오름차순일 때 -->
+				<!-- 내림차순일 때 -->
+				<otherwise>
+					DESC
+				</otherwise>
+				<!-- 내림차순일 때 -->
+			</choose>
+			) AS NUM
+		</if>
+		<!-- //정렬 -->
+		
+		<if test="isUsePaging == true">
+		LIMIT #{perPage} OFFSET #{startIndex}
+		</if>
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: 커넥션된 데이터베이스의 테이블의 데이터 목록 총 갯수 조회 SQL입니다.
+	 -->
+	<select id="getDBConnectionTableDataTotalRows" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			COUNT(0)
+		FROM
+			`${databaseNm}`.`${tableNm}`
+		WHERE 1 = 1
+		
+		<!-- 검색 -->
+		<choose>
+			<!-- 컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<when test="columnDatas != null and columnDatas.size() > 0 and (searchCondition == null or searchCondition == '') and searchKeyword != null and searchKeyword != ''">
+				AND
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator=" OR " close=")">
+					<foreach item="keyword" index="index2" collection="searchKeywordList" separator=" OR ">
+					`${item.columnName}` LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</foreach>
+			</when>
+			<!-- //컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<!-- 컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+			<otherwise>
+				<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+				AND
+					<foreach item="keyword" index="index2" collection="searchKeywordList" open="(" separator=" OR " close=")">
+					`${searchCondition}` LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</if>
+			</otherwise>
+			<!-- //컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+		</choose>
+		<!-- //검색 -->
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용:  커스텀 테이블 데이터 조회 (페이징사용 유무에 따라 페이징 처리) SQL입니다.
+	 -->
+	<select id="getDBConnectionCustomQueryDataList" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			a.*
+		FROM (
+			${query}
+		) a
+		<if test="limit > 0">
+		LIMIT #{limit}		
+		</if>
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용:  커스텀 테이블 실행형
+	 -->
+	<update id="executeCustomQuery" parameterType="DataTable">		
+		/*+ RULE */
+		${query}		
+	</update>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: 커스텀 테이블 데이터 목록 총 갯수 조회 SQL입니다.
+	 -->
+	<select id="getDBConnectionCustomQueryDataTotalRows" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			COUNT(0)
+		FROM (
+			${query}
+		) a
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: DB연계 데이터 목록 조회 (초기 DB화 때에 등록한 컬럼만 가지고 옴)
+	 -->
+	<select id="getDBCollectionQueryDataList" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			<foreach item="item" index="index" collection="columnDatas" open="" separator="," close="">
+				a.`${item.originColumnName}` AS '${item.columnName}' 
+			</foreach>
+		FROM (
+			${query}
+		) a
+		
+		<!-- 검색 -->
+		<choose>
+			<!-- 컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<when test="columnDatas != null and columnDatas.size() > 0 and (searchCondition == null or searchCondition == '') and searchKeyword != null and searchKeyword != ''">
+				AND
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator=" OR " close=")">
+					<foreach item="keyword" index="index2" collection="searchKeywordList" separator=" OR ">
+					a.`${item.originColumnName}` LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</foreach>
+			</when>
+			<!-- //컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<!-- 컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+			<otherwise>
+				<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+				AND
+					<foreach item="keyword" index="index2" collection="searchKeywordList" open="(" separator=" OR " close=")">
+					a.`${searchCondition}` LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</if>
+			</otherwise>
+			<!-- //컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+		</choose>
+		<!-- //검색 -->
+		
+		<!-- 정렬 -->
+		<if test="order != null and order != ''">
+			ORDER BY `${order}`
+			<choose>
+				<!-- 오름차순일 때 -->
+				<when test="isOrderASC == true">
+					ASC
+				</when>
+				<!-- //오름차순일 때 -->
+				<!-- 내림차순일 때 -->
+				<otherwise>
+					DESC
+				</otherwise>
+				<!-- 내림차순일 때 -->
+			</choose>
+			) AS NUM
+		</if>
+		<!-- //정렬 -->
+		
+		<if test="isUsePaging == true">
+		LIMIT #{perPage} OFFSET #{startIndex}
+		</if>
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: DB연계 데이터 목록 총 갯수 조회
+	 -->
+	<select id="getDBCollectionQueryDataTotalRows" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			COUNT(0)
+		FROM (
+			${query}
+		) a
+		
+		<!-- 검색 -->
+		<choose>
+			<!-- 컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<when test="columnDatas != null and columnDatas.size() > 0 and (searchCondition == null or searchCondition == '') and searchKeyword != null and searchKeyword != ''">
+				AND
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator=" OR " close=")">
+					<foreach item="keyword" index="index2" collection="searchKeywordList" separator=" OR ">
+					a.`${item.originColumnName}` LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</foreach>
+			</when>
+			<!-- //컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<!-- 컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+			<otherwise>
+				<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+				AND
+					<foreach item="keyword" index="index2" collection="searchKeywordList" open="(" separator=" OR " close=")">
+					a.`${searchCondition}` LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</if>
+			</otherwise>
+			<!-- //컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+		</choose>
+		<!-- //검색 -->
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.11.29
+		내용: 커트텀 쿼리 지정된 PK의 중복 데이터 수 (지정된 PK로 Table 생성이 가능한지 알아보기 위함) 
+	 -->
+	<select id="getCustomQueryPrimaryOverlapCount" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			IFNULL(SUM(a.overlapCount), 0) AS totalOverlapCount
+		FROM (
+			SELECT
+				COUNT(0) AS overlapCount
+			FROM (
+				${query}
+			) t
+			GROUP BY
+				<foreach item="item" index="index" collection="columnData" open="" separator="," close="">
+					t.`${item.columnName}`
+				</foreach>
+			HAVING
+			  COUNT(0) > 1
+		) a
+	</select>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 데이터 셋의 DB화 (테이블 생성)
+	 -->
+	<update id="datasetTableCreate" parameterType="DataTable">
+		 CREATE TABLE `${tableNm}` (
+			<foreach item="item" index="index" collection="columnDatas" separator=",">
+				`${item.columnName}` ${item.dbDataType}
+				<if test="item.dbDataType == 'varchar'">(#{item.size})</if>
+				<choose>
+					<when test="item.isPrimary == true"> NOT NULL</when>
+					<otherwise> DEFAULT NULL</otherwise>
+				</choose>
+			</foreach>
+			, PRIMARY KEY (
+			<foreach item="item" index="index" collection="columnDatas" separator=",">
+				<if test="item.isPrimary == true">
+				`${item.columnName}`
+				</if>
+			</foreach>
+			)
+			<foreach item="item" index="index" collection="columnDatas">
+				<if test="item.isUniq == true">
+				, UNIQUE INDEX `${tableNm}_${item.columnName}_UNIQUE` (`${item.columnName}` ASC)
+				</if>
+			</foreach>
+		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
+		<if test="title != null and title != ''">
+			COMMENT = #{title}
+		</if>
+	</update>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 데이터 셋의 DB화 (테이블 생성)
+	 -->
+	<update id="datasetDefaultTableCreate" parameterType="DataTable">
+		 CREATE TABLE `${tableNm}` (
+			`spm_row` bigint NOT NULL AUTO_INCREMENT
+			<foreach item="item" index="index" collection="columnDatas">
+				,`${item.columnName}` ${item.dbDataType}
+				<if test="item.dbDataType == 'varchar'">
+					(#{item.size})
+				</if>
+				DEFAULT NULL 
+			</foreach>
+			, PRIMARY KEY (`spm_row`)
+			<foreach item="item" index="index" collection="columnDatas">
+				<if test="item.isUniq == true">
+				, UNIQUE INDEX `${tableNm}_${item.columnName}_UNIQUE` (`${item.columnName}` ASC)
+				</if>
+			</foreach>
+		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
+		<if test="title != null and title != ''">
+			COMMENT = #{title}
+		</if>
+	</update>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 데이터 셋의 DB화 (데이터 생성 및 업데이트)
+	 -->
+	<update id="datasetDataUpdate" parameterType="DataTable">
+		REPLACE INTO `${tableNm}`
+			<foreach item="item" index="index" collection="columnDatas" open="(" separator="," close=")">
+			`${item.columnName}`
+			</foreach>
+		VALUES 
+			<foreach item="row" collection="rowData" separator=",">
+			(
+				<foreach item="cell" index="index" collection="row" separator=",">
+					#{cell}
+					<!-- 
+					<choose>
+						<when test="columnDatas[index].dbDataType == 'varchar' or columnDatas[index].dbDataType == 'datetime'">#{cell}</when>
+						<otherwise>${cell}</otherwise>
+					</choose>
+					 -->
+				</foreach>
+			)
+			</foreach>
+	</update>
+	
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 데이터 셋의 ROW 삭제
+	 -->
+	<update id="datasetDataDelete" parameterType="DataTable">	
+		DELETE FROM ${tableNm} 
+		WHERE 
+			 1 = 1 	
+			<foreach item="item" index="index" collection="columnDatas" open=" AND " separator=" AND " close="">
+			 `${item.columnName}` in 
+		 			<foreach item="items" index="indexs" collection="item.values" open="(" separator=", " close=")">
+		 				#{items.value}
+		 			</foreach>
+			</foreach>	
+	</update>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 중복 테이블명 체크
+	 -->
+	<select id="duplicateChecktableNm" parameterType="Map" resultType="INTEGER">
+		SELECT count(*)  
+		FROM 
+			Information_schema.tables 
+		WHERE 
+			TABLE_SCHEMA = #{schema}
+		AND 
+			TABLE_NAME = #{tableNm};
+	</select>
+	
+	<!-- 
+		작성자 : 김성원
+		작성일 : 2021.01.17
+		내용: 데이터 셋의 컬럼 정보 목록 조회 SQL에 접근하는 메소드 입니다.(페이징)
+	 -->
+	<select id="getRowData" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			<foreach item="item" index="index" collection="columnDatas" open="" separator="," close="">
+				`${item.columnName}`<!--  AS `${item.displayColumnName}` -->
+			</foreach>
+		FROM
+			`${tableNm}`
+		WHERE 1
+		
+		<!-- 검색 -->
+		<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+		AND
+			`${searchCondition}` LIKE CONCAT('%', #{searchKeyword}, '%')
+		</if>
+		<!-- //검색 -->
+		
+		<!-- 정렬 -->
+		<if test="order != null and order != ''">
+			ORDER BY `${order}`
+			<choose>
+				<!-- 오름차순일 때 -->
+				<when test="isOrderASC == true">
+					ASC
+				</when>
+				<!-- //오름차순일 때 -->
+				<!-- 내림차순일 때 -->
+				<otherwise>
+					DESC
+				</otherwise>
+				<!-- 내림차순일 때 -->
+			</choose>
+			) AS NUM
+		</if>
+		<!-- //정렬 -->
+		
+		LIMIT #{perPage} OFFSET #{startIndex}
+	</select>
+	
+	<!-- 
+		작성자: 김성원
+		작성일: 2022.01.17
+		내용: 데이터 셋의 컬럼 정보 목록 조회 SQL에 접근하는 메소드 입니다.(노페이징)
+	 -->
+	<select id="getRowDataAll" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			<foreach item="item" index="index" collection="columnDatas" open="" separator="," close="">
+				`${item.columnName}`<!--  AS `${item.displayColumnName}` -->
+			</foreach>
+		FROM
+			`${tableNm}`	
+		<if test="query != null and query != ''">
+		WHERE 1
+		    ${query}
+		</if>	
+	</select>
+	
+	<!-- 
+		작성자: 김성원
+		작성일: 2022.01.17
+		내용: 데이터 셋의 컬럼 정보 목록 총 갯수 조회 SQL
+	 -->
+	<select id="getRowDataTotalRows" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			COUNT(0)
+		FROM
+			`${tableNm}`
+		WHERE 1
+		<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+		AND
+			`${searchCondition}` LIKE CONCAT('%', #{searchKeyword}, '%')
+		</if>
+	</select>
+	
+	<!--
+	 	작성자: 김성원
+		작성일: 2022.01.17
+		내용 : 데이터 셋의 비우기 (데이터 셋 내용삭제)
+	 -->
+	<delete id="emptyDataset" parameterType="DataTable">
+		DELETE FROM `${tableNm}`
+	</delete>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2022.01.20
+		내용 : 실제 생성된 컬럼 변경
+	 -->
+	<update id="tableColumnChange" parameterType="TableBasicInfo">
+		ALTER TABLE `${tableNm}` ${process} `${columnName}` 
+		<if test="process == 'CHANGE'">
+			 `${tobeColumnName}` ${dataType}
+		</if>
+		<if test="process == 'MODIFY' || process == 'ADD' ">${dataType}</if><if test="dataType == 'varchar' and process != 'DROP'">(${size})</if>
+	</update>
+	
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2022.01.20
+		내용 : 실제 생성된 테이블 PK처리
+	 -->
+	<update id="changePromaryKey" parameterType="TableBasicInfo">
+		ALTER TABLE `${tableNm}` ${process}  PRIMARY KEY
+		<if test="process != 'DROP'">
+			<foreach item="item" index="index" collection="primaryList" open=" (" separator=", " close=")">
+				${item}
+			</foreach>
+		</if>	
+	</update>	
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2022.01.20
+		내용 :  AI PK 생성 
+	 -->
+	<update id="createAutoIncrement" parameterType="TableBasicInfo">
+		ALTER TABLE `${tableNm}` ADD `${columnName}`
+		BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST 
+	</update>	
+	
+		<!--
+		작성자 : 김성원
+		작성일 : 2022.09.30
+		내용 : 테이블 메타정보 변경 (comments)
+	 -->
+	<update id="updateTableMetaInfo" parameterType="DataTable">
+		ALTER TABLE  ${tableNm}
+		COMMENT = #{title}
+	</update>
+	
+	
+</mapper>(No newline at end of file)
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/mybatis/sql/postgre-SQL.xml (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/mybatis/sql/postgre-SQL.xml
@@ -0,0 +1,601 @@
+<?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">
+
+<!--
+	작성자 : 최정우
+	작성일 : 2019.11.17
+	내용 : PostgreSQL 접속 모듈에 관련된 SQL입니다. 
+ -->
+<mapper namespace="PostgresqlDAO"> 
+
+	<!--
+		작성자 : 최정우
+		작성일 : 2020.01.27
+		내용 : 커넥션된 데이터베이스의 테이블 목록 조회 SQL입니다.
+	 -->
+	<select id="getDBConnectionTableList" parameterType="ConnectionDB" resultType="Dataset">		
+		SELECT
+			schemaname AS "databaseNm"
+		    , tableName AS "tableNm"	
+		FROM
+			PG_TABLES
+		WHERE
+			schemaname = #{schemaNm}
+		ORDER BY
+			tableName ASC	
+	</select>
+	
+	<!--
+	 	작성자 : 최정우
+		작성일 : 2020.01.27
+		내용 : 커넥션된 데이터베이스의 테이블의 컬럼 정보 조회 (DB 기준 데이터 타입, 데이터 크기 등)
+	 -->
+	<select id="getDBConnectionTableColumnList" parameterType="Dataset" resultType="ColumnData">
+		SELECT
+			A.TABLE_SCHEMA AS "databaseNm"
+		    , A.TABLE_NAME AS "tableNm"
+			, A.COLUMN_NAME AS "columnNm"
+			, A.COLUMN_NAME AS "displyColumnNm"
+			, A.COLUMN_NAME AS "orginlColumnNm"
+			, A.ORDINAL_POSITION as "ordr"
+			, A.DATA_TYPE AS "dbDataType"
+		    , A.CHARACTER_MAXIMUM_LENGTH AS "dataSize"			
+			, case when c.constraint_type = 'PRIMARY KEY' then true else false end as "pkAt"
+			, case when c.constraint_type = 'UNIQUE' then true else false end as "uniqeAt"
+		FROM
+			INFORMATION_SCHEMA.columns A
+			left join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE B on A.table_name  = B.table_name and  B.column_name  = A.column_name  
+			left join INFORMATION_SCHEMA.TABLE_CONSTRAINTS C on B.constraint_name  = C.constraint_name  
+		WHERE
+			A.table_catalog = #{databaseNm}
+		AND
+			A.TABLE_NAME = #{tableNm}
+		
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: 커넥션된 데이터베이스의 테이블의 데이터 목록 조회 SQL입니다.(페이징)
+	 -->
+	<select id="getDBConnectionTableDataList" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			*
+		FROM
+			${tableNm}
+		WHERE 1 = 1		
+		<!-- 검색 -->
+		<choose>
+			<!-- 컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<when test="columnDatas != null and columnDatas.size() > 0 and (searchCondition == null or searchCondition == '') and searchKeyword != null and searchKeyword != ''">
+				AND
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator=" OR " close=")">
+					<foreach item="keyword" index="index2" collection="searchKeywordList" separator=" OR ">
+					${item.columnName} LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</foreach>
+			</when>
+			<!-- //컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<!-- 컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+			<otherwise>
+				<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+				AND
+					<foreach item="keyword" index="index2" collection="searchKeywordList" open="(" separator=" OR " close=")">
+					${searchCondition} LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</if>
+			</otherwise>
+			<!-- //컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+		</choose>
+		<!-- //검색 -->
+		
+		<!-- 정렬 -->
+		<if test="order != null and order != ''">
+			ORDER BY ${order}
+			<choose>
+				<!-- 오름차순일 때 -->
+				<when test="isOrderASC == true">
+					ASC
+				</when>
+				<!-- //오름차순일 때 -->
+				<!-- 내림차순일 때 -->
+				<otherwise>
+					DESC
+				</otherwise>
+				<!-- 내림차순일 때 -->
+			</choose>
+			) AS NUM
+		</if>
+		<!-- //정렬 -->
+		
+		<if test="isUsePaging == true">
+		LIMIT #{perPage} OFFSET #{startIndex}
+		</if>
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: 커넥션된 데이터베이스의 테이블의 데이터 목록 총 갯수 조회 SQL입니다.
+	 -->
+	<select id="getDBConnectionTableDataTotalRows" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			COUNT(0)
+		FROM
+			${tableNm}
+		WHERE 1 = 1		
+		<!-- 검색 -->
+		<choose>
+			<!-- 컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<when test="columnDatas != null and columnDatas.size() > 0 and (searchCondition == null or searchCondition == '') and searchKeyword != null and searchKeyword != ''">
+				AND
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator=" OR " close=")">
+					<foreach item="keyword" index="index2" collection="searchKeywordList" separator=" OR ">
+					${item.columnName} LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</foreach>
+			</when>
+			<!-- //컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<!-- 컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+			<otherwise>
+				<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+				AND
+					<foreach item="keyword" index="index2" collection="searchKeywordList" open="(" separator=" OR " close=")">
+					${searchCondition} LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</if>
+			</otherwise>
+			<!-- //컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+		</choose>
+		<!-- //검색 -->
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용:  커스텀 테이블 데이터 조회 (페이징사용 유무에 따라 페이징 처리) SQL입니다.
+	 -->
+	<select id="getDBConnectionCustomQueryDataList" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			a.*
+		FROM (
+			${query}
+		) a
+		<if test="limit > 0">
+		LIMIT #{limit}		
+		</if>
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용:  커스텀 테이블 실행형
+	 -->
+	<update id="executeCustomQuery" parameterType="DataTable">		
+		/*+ RULE */
+		${query}		
+	</update>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: 커스텀 테이블 데이터 목록 총 갯수 조회 SQL입니다.
+	 -->
+	<select id="getDBConnectionCustomQueryDataTotalRows" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			COUNT(0)
+		FROM (
+			${query}
+		) a
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: DB연계 데이터 목록 조회 (초기 DB화 때에 등록한 컬럼만 가지고 옴)
+	 -->
+	<select id="getDBCollectionQueryDataList" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			<foreach item="item" index="index" collection="columnDatas" open="" separator="," close="">
+				a.${item.originColumnName} AS '${item.columnName}' 
+			</foreach>
+		FROM (
+			${query}
+		) a
+		
+		<!-- 검색 -->
+		<choose>
+			<!-- 컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<when test="columnDatas != null and columnDatas.size() > 0 and (searchCondition == null or searchCondition == '') and searchKeyword != null and searchKeyword != ''">
+				AND
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator=" OR " close=")">
+					<foreach item="keyword" index="index2" collection="searchKeywordList" separator=" OR ">
+					a.${item.originColumnName} LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</foreach>
+			</when>
+			<!-- //컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<!-- 컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+			<otherwise>
+				<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+				AND
+					<foreach item="keyword" index="index2" collection="searchKeywordList" open="(" separator=" OR " close=")">
+					a.${searchCondition} LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</if>
+			</otherwise>
+			<!-- //컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+		</choose>
+		<!-- //검색 -->
+		
+		<!-- 정렬 -->
+		<if test="order != null and order != ''">
+			ORDER BY ${order}
+			<choose>
+				<!-- 오름차순일 때 -->
+				<when test="isOrderASC == true">
+					ASC
+				</when>
+				<!-- //오름차순일 때 -->
+				<!-- 내림차순일 때 -->
+				<otherwise>
+					DESC
+				</otherwise>
+				<!-- 내림차순일 때 -->
+			</choose>
+			) AS NUM
+		</if>
+		<!-- //정렬 -->
+		
+		<if test="isUsePaging == true">
+		LIMIT #{perPage} OFFSET #{startIndex}
+		</if>
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.01.27
+		내용: DB연계 데이터 목록 총 갯수 조회
+	 -->
+	<select id="getDBCollectionQueryDataTotalRows" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			COUNT(0)
+		FROM (
+			${query}
+		) a
+		
+		<!-- 검색 -->
+		<choose>
+			<!-- 컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<when test="columnDatas != null and columnDatas.size() > 0 and (searchCondition == null or searchCondition == '') and searchKeyword != null and searchKeyword != ''">
+				AND
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator=" OR " close=")">
+					<foreach item="keyword" index="index2" collection="searchKeywordList" separator=" OR ">
+					a.${item.originColumnName} LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</foreach>
+			</when>
+			<!-- //컬럼 데이터 목록이 존재하고, 검색 조건이 없고, 검색 키워드가 있을 때 -->
+			<!-- 컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+			<otherwise>
+				<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+				AND
+					<foreach item="keyword" index="index2" collection="searchKeywordList" open="(" separator=" OR " close=")">
+					a.${searchCondition} LIKE CONCAT('%', #{keyword}, '%')
+					</foreach>
+				</if>
+			</otherwise>
+			<!-- //컬럼 데이터 목록이 존재하지 않거나, 검색 조건이 있거나, 검색 키워드가 있을 때 -->
+		</choose>
+		<!-- //검색 -->
+	</select>
+	
+	<!-- 
+		작성자: 최정우
+		작성일: 2020.11.29
+		내용: 커트텀 쿼리 지정된 PK의 중복 데이터 수 (지정된 PK로 Table 생성이 가능한지 알아보기 위함) 
+	 -->
+	<select id="getCustomQueryPrimaryOverlapCount" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			IFNULL(SUM(a.overlapCount), 0) AS totalOverlapCount
+		FROM (
+			SELECT
+				COUNT(0) AS overlapCount
+			FROM (
+				${query}
+			) t
+			GROUP BY
+				<foreach item="item" index="index" collection="columnData" open="" separator="," close="">
+					t.${item.columnName}
+				</foreach>
+			HAVING
+			  COUNT(0) > 1
+		) a
+	</select>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 데이터 셋의 DB화 (테이블 생성)
+	 -->
+	<update id="datasetTableCreate" parameterType="DataTable">
+		 CREATE TABLE ${tableNm} (
+			<foreach item="item" index="index" collection="columnDatas" separator=",">
+				${item.columnName} ${item.dbDataType}
+				<if test="item.dbDataType == 'varchar'">(#{item.size})</if>
+				<choose>
+					<when test="item.isPrimary == true"> NOT NULL</when>
+					<otherwise> DEFAULT NULL</otherwise>
+				</choose>
+			</foreach>
+			, PRIMARY KEY (
+			<foreach item="item" index="index" collection="columnDatas" separator=",">
+				<if test="item.isPrimary == true">
+				${item.columnName}
+				</if>
+			</foreach>
+			)
+			<foreach item="item" index="index" collection="columnDatas">
+				<if test="item.isUniq == true">
+				, UNIQUE INDEX ${tableNm}_${item.columnName}_UNIQUE (${item.columnName} ASC)
+				</if>
+			</foreach>
+		) ;
+		<if test="title != null and title != ''">
+			COMMENT ON TABLE ${tableNm} IS #{title};			
+		</if>
+	</update>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 데이터 셋의 DB화 (테이블 생성)
+	 -->
+	<update id="datasetDefaultTableCreate" parameterType="DataTable">
+		 CREATE TABLE ${tableNm} (
+			spm_row SERIAL PRIMARY KEY
+			<foreach item="item" index="index" collection="columnDatas">
+				<if test="item.dbDataType == 'double'">
+				, ${item.columnName} numeric
+				</if>
+				<if test="item.dbDataType != 'double'">
+				, ${item.columnName} ${item.dbDataType}
+				</if>
+				<if test="item.dbDataType == 'varchar'">
+					(${item.size})
+				</if>
+				DEFAULT NULL 
+			</foreach>			
+			<foreach item="item" index="index" collection="columnDatas">
+				<if test="item.isUniq == true">
+				, UNIQUE INDEX ${tableNm}_${item.columnName}_UNIQUE (${item.columnName} ASC)
+				</if>
+			</foreach>
+		);
+		<if test="title != null and title != ''">
+			COMMENT ON TABLE ${tableNm} IS '${title}';			
+		</if>
+	</update>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 데이터 셋의 DB화 (데이터 생성 및 업데이트)
+	 -->
+	<update id="datasetDataUpdate" parameterType="DataTable">
+		INSERT INTO ${tableNm}
+			<foreach item="item" index="index" collection="columnDatas" open="(" separator="," close=")">
+				<if test="columnDatas[index].AutoIncrement != null and columnDatas[index].AutoIncrement == false">
+					${item.columnName}
+				</if>
+				
+			</foreach>
+		VALUES 
+			<foreach item="row" collection="rowData" separator=",">
+			(
+			
+				<foreach item="cell" index="index" collection="row" separator=",">			
+					<if test="columnDatas[index].AutoIncrement == false">		
+						<choose>
+							<when test="columnDatas[index].dbDataType == 'varchar' or columnDatas[index].dbDataType == 'datetime'">#{cell}</when>
+							<otherwise>${cell}</otherwise>
+						</choose>
+					</if>
+				</foreach>
+			)
+			</foreach>
+			ON CONFLICT ON CONSTRAINT ${tableNm}_pkey
+			DO UPDATE
+			SET
+				<foreach item="item" index="index" collection="columnDatas" open="(" separator="," close=")">
+				<if test="columnDatas[index].AutoIncrement != null and columnDatas[index].AutoIncrement == false">
+					${item.columnName}
+				</if>
+				</foreach>
+			    =
+			    <foreach item="item" index="index" collection="columnDatas" open="(" separator="," close=")">
+				<if test="columnDatas[index].AutoIncrement != null and columnDatas[index].AutoIncrement == false">
+					ExCLUDED.${item.columnName}
+				</if>
+				</foreach>
+	</update>
+	
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 데이터 셋의 ROW 삭제
+	 -->
+	<update id="datasetDataDelete" parameterType="DataTable">	
+		DELETE FROM ${tableNm} 
+		WHERE 
+			 1 = 1 	
+			<foreach item="item" index="index" collection="columnDatas" open=" AND " separator=" AND " close="">
+			 ${item.columnName} in 
+		 			<foreach item="items" index="indexs" collection="item.values" open="(" separator=", " close=")">
+		 				#{items.value}
+		 			</foreach>
+			</foreach>	
+	</update>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2021.01.17
+		내용 : 중복 테이블명 체크
+	 -->
+	<select id="duplicateChecktableNm" parameterType="Map" resultType="INTEGER">
+		SELECT count(*)
+		FROM 
+			Information_schema.tables 
+		WHERE 
+			table_catalog = #{schema}
+		AND 
+			TABLE_NAME = #{tableNm};
+	</select>
+	
+	<!-- 
+		작성자 : 김성원
+		작성일 : 2021.01.17
+		내용: 데이터 셋의 컬럼 정보 목록 조회 SQL에 접근하는 메소드 입니다.(페이징)
+	 -->
+	<select id="getRowData" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			<foreach item="item" index="index" collection="columnDatas" open="" separator="," close="">
+				${item.columnName}<!--  AS `${item.displayColumnName}` -->
+			</foreach>
+		FROM
+			${tableNm}
+		WHERE true
+		
+		<!-- 검색 -->
+		<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+		AND
+			${searchCondition} LIKE CONCAT('%', #{searchKeyword}, '%')
+		</if>
+		<!-- //검색 -->
+		
+		<!-- 정렬 -->
+		<if test="order != null and order != ''">
+			ORDER BY ${order}
+			<choose>
+				<!-- 오름차순일 때 -->
+				<when test="isOrderASC == true">
+					ASC
+				</when>
+				<!-- //오름차순일 때 -->
+				<!-- 내림차순일 때 -->
+				<otherwise>
+					DESC
+				</otherwise>
+				<!-- 내림차순일 때 -->
+			</choose>
+			) AS NUM
+		</if>
+		<!-- //정렬 -->
+		
+		LIMIT #{perPage} OFFSET #{startIndex}
+	</select>
+	
+	<!-- 
+		작성자: 김성원
+		작성일: 2022.01.17
+		내용: 데이터 셋의 컬럼 정보 목록 조회 SQL에 접근하는 메소드 입니다.(노페이징)
+	 -->
+	<select id="getRowDataAll" parameterType="DataTable" resultType="java.util.LinkedHashMap">
+		SELECT
+			<foreach item="item" index="index" collection="columnDatas" open="" separator="," close="">
+				${item.columnName}<!--  AS `${item.displayColumnName}` -->
+			</foreach>
+		FROM
+			${tableNm}
+		<if test="query != null and query != ''">
+		WHERE 1 = 1
+<!-- 		AND -->
+		    ${query}
+		</if>	
+	</select>
+	
+	<!-- 
+		작성자: 김성원
+		작성일: 2022.01.17
+		내용: 데이터 셋의 컬럼 정보 목록 총 갯수 조회 SQL
+	 -->
+	<select id="getRowDataTotalRows" parameterType="DataTable" resultType="java.lang.Integer">
+		SELECT
+			COUNT(0)
+		FROM
+			${tableNm}
+		WHERE 1=1
+		<if test="searchCondition != null and searchCondition != '' and searchKeyword != null and searchKeyword != ''">
+		AND
+			${searchCondition} LIKE CONCAT('%', #{searchKeyword}, '%')
+		</if>
+	</select>
+	
+	<!--
+	 	작성자: 김성원
+		작성일: 2022.01.17
+		내용 : 데이터 셋의 비우기 (데이터 셋 내용삭제)
+	 -->
+	<delete id="emptyDataset" parameterType="DataTable">
+		DELETE FROM ${tableNm}
+	</delete>
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2022.01.20
+		내용 : 실제 생성된 컬럼 변경
+	 -->
+	<update id="tableColumnChange" parameterType="TableBasicInfo">
+		ALTER TABLE ${tableNm} 
+		
+		
+		${process} 
+		<if test="process == 'RENAME'">
+		COLUMN 
+		</if>
+		${columnName}
+		<if test="process == 'RENAME'">
+			 TO ${tobeColumnName}
+		</if>
+		<if test="process == 'MODIFY' || process == 'ADD' ">${dataType}<if test="dataType == 'varchar' and process != 'DROP'">(${size})</if></if>
+	</update>
+	
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2022.01.20
+		내용 : 실제 생성된 테이블 PK처리
+	 -->
+	<update id="changePromaryKey" parameterType="TableBasicInfo">
+		ALTER TABLE ${tableNm} ${process}  PRIMARY KEY
+		<if test="process != 'DROP'">
+			<foreach item="item" index="index" collection="primaryList" open=" (" separator=", " close=")">
+				${item}
+			</foreach>
+		</if>	
+	</update>	
+	
+	<!--
+	 	작성자 : 김성원
+		작성일 : 2022.01.20
+		내용 :  AI PK 생성 
+	 -->
+	<update id="createAutoIncrement" parameterType="TableBasicInfo">
+		ALTER TABLE ${tableNm} ADD ${columnName}
+		BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST 
+	</update>	
+	
+	
+		<!--
+		작성자 : 김혜민
+		작성일 : 2022.09.30
+		내용 : 테이블 메타정보 변경 (comments)
+	 -->
+	<update id="updateTableMetaInfo" parameterType="DataTable">
+			COMMENT ON TABLE ${tableNm} IS #{title}
+		
+<!-- 		ALTER TABLE  ${tableNm} -->
+<!-- 		COMMENT = #{title} -->
+	</update>
+</mapper>(No newline at end of file)
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/util/DBConnectionConfig.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/util/DBConnectionConfig.java
@@ -0,0 +1,180 @@
+package com.takensoft.taken_bi_manager.common.connection.db.util;
+
+import java.sql.SQLException;
+
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+
+import com.takensoft.taken_bi_manager.common.connection.db.vo.ConnectionDB;
+import com.takensoft.taken_bi_manager.common.vo.SystemCode.DatabaseType;
+import com.zaxxer.hikari.HikariDataSource;
+
+/**
+ * @author 김성원
+ * @since 2024.01.02
+ * 
+ * 동적 데이터 베이스 연계 관리 클래스 입니다.
+ */
+public class DBConnectionConfig {
+	
+	//프로젝트 내부 Class Path 정보
+	// 한개 logger.debug(pathMatchingResourcePatternResolver.getResource("절대경로 혹은 classpath:이하경로").getFile().getAbsolutePath()); 
+	// 여러개 Resource[] resource = pathMatchingResourcePatternResolver.getResources("절대경로 혹은 classpath:이하경로");
+	private final static PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
+	
+	//동적 Mybatis 연계 - mybatis 설정 정보 파일 경로
+	private final static String DYNAMIC_MYBATIS_CONFIG = "com/takensoft/taken_bi_manager/common/connection/db/mybatis/config/config.xml";
+	
+	//동적 Mybatis 연계 - mybatis Mapper 문서 파일 경로 
+	private final static String DYNAMIC_MYBATIS_MAPPERS = "com/takensoft/taken_bi_manager/common/connection/db/mybatis/sql/*-SQL.xml";
+	
+	private HikariDataSource dataSource = null;
+	
+	private SqlSessionFactoryBean sqlSession = null;
+	
+	private SqlSessionTemplate template = null;
+	
+	private DataSourceTransactionManager dataSourceTransaction = null;
+	
+	public HikariDataSource getDataSource() {
+		return dataSource;
+	}
+
+	public void setDataSource(HikariDataSource dataSource) {
+		this.dataSource = dataSource;
+	}
+
+	public SqlSessionFactoryBean getSqlSession() {
+		return sqlSession;
+	}
+
+	public void setSqlSession(SqlSessionFactoryBean sqlSession) {
+		this.sqlSession = sqlSession;
+	}
+
+	public SqlSessionTemplate getTemplate() {
+		return template;
+	}
+
+	public void setTemplate(SqlSessionTemplate template) {
+		this.template = template;
+	}
+
+
+	/**
+	 * @author 김성원
+	 * @since 2024.01.08
+	 * 
+	 * 동적 DB + Mybatis 객체 생성 -> Mapper에 접근하기위한 SQL 템플릿 반환
+	 */
+	public SqlSessionTemplate mybatisSqlTemplateCreate (ConnectionDB db) {
+		dataSource = dataSourceCreate(db);
+		sqlSession = sqlSessionCreate(dataSource);
+		template = sqlSessionTemplateCreate(sqlSession);		
+		dataSourceTransaction = getTransaction(dataSource);
+		
+		return template;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.08
+	 * 
+	 * 동적 DataSource 생성
+	 */
+	public HikariDataSource dataSourceCreate (ConnectionDB db) {
+		dataSource = null;
+		try {
+			dataSource = new HikariDataSource();
+			DatabaseType dataBaseType = db.getDatabaseType();
+			dataSource.setDriverClassName(dataBaseType.getDriverClassName());
+			dataSource.setJdbcUrl(dataBaseType.getUrl(db));
+			
+			dataSource.setUsername(db.getUserId());
+			dataSource.setPassword(db.getUserPassword());
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		
+		return dataSource;
+	}
+	
+	/**
+	  * @author 김성원
+	 * @since 2024.01.08
+	 * 
+	 * 동적으로 생성한 DataSource정보와 Mybatis 설정 정보 연계 생성
+	 */
+	private SqlSessionFactoryBean sqlSessionCreate (HikariDataSource dataSource) {
+		try {
+			sqlSession = new SqlSessionFactoryBean();
+			sqlSession.setDataSource(dataSource);
+			sqlSession.setConfigLocation(resourceResolver.getResource(DYNAMIC_MYBATIS_CONFIG));
+			sqlSession.setMapperLocations(resourceResolver.getResources(DYNAMIC_MYBATIS_MAPPERS));
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		
+		return sqlSession;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.08
+	 * 
+	 * 동적 Mybatis Mapper에 접근하기위한 SQL 템플릿 생성
+	 */
+	private SqlSessionTemplate sqlSessionTemplateCreate (SqlSessionFactoryBean sqlSession) {
+		try {
+			template = new SqlSessionTemplate(sqlSession.getObject());
+			template.clearCache();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		
+		return template;
+	}
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.08
+	 * 
+	 * 동적 Mybatis Mapper에 접근하기위한 SQL 템플릿 생성
+	 */
+	private DataSourceTransactionManager getTransaction (HikariDataSource dataSource) {
+		
+		this.dataSourceTransaction = new DataSourceTransactionManager(dataSource);
+	
+		return dataSourceTransaction;
+	}	
+	
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.08
+	 * 
+	 * 커넥션 닫기
+	 */
+	public void close() throws SQLException {
+		try {
+			if (dataSource != null) {
+				dataSource.evictConnection(dataSource.getConnection());
+				if (dataSource.getConnection() != null) {
+					dataSource.getConnection().close();
+				}
+				dataSource.close();
+			}
+		}catch(Exception e) {
+			if (dataSource != null) {
+				dataSource.close();
+			}
+		}
+		
+	}
+	
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/util/DBConnectionUtil.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/util/DBConnectionUtil.java
@@ -0,0 +1,745 @@
+package com.takensoft.taken_bi_manager.common.connection.db.util;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.takensoft.taken_bi_manager.common.connection.db.dao.DatabaseDAO;
+import com.takensoft.taken_bi_manager.common.connection.db.dao.MariadbDAO;
+import com.takensoft.taken_bi_manager.common.connection.db.dao.PostgresqlDAO;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.ConnectionDB;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.TableBasicInfo;
+import com.takensoft.taken_bi_manager.common.util.CommonUtil;
+import com.takensoft.taken_bi_manager.common.util.StringUtil;
+import com.takensoft.taken_bi_manager.common.vo.CheckMessage;
+import com.takensoft.taken_bi_manager.common.vo.SystemCode.DatabaseType;
+import com.takensoft.taken_bi_manager.data.vo.ColumnData;
+import com.takensoft.taken_bi_manager.data.vo.DataTable;
+import com.takensoft.taken_bi_manager.data.vo.Dataset;
+
+
+
+/**
+ * @author 최정우
+ * @since 2019.11.12
+ * 
+ * 데이터 수집 - DB 데이터 연계 관련 Util 입니다. 
+ */
+@Transactional
+public class DBConnectionUtil {
+	
+	private Logger logger = LoggerFactory.getLogger(DBConnectionUtil.class);
+
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * 데이터베이스 접속 모듈 DAO 객체 생성 메서드입니다.
+	 */
+	public DatabaseDAO createDatabaseDAO (ConnectionDB db) throws Exception {
+		
+		DatabaseDAO databaseDao= null;
+		
+		if (db.getDatabaseType() == DatabaseType.MYSQL) {
+	//		databaseDao =  new MysqlDAO(db);
+		} else if (db.getDatabaseType() == DatabaseType.MARIADB) {
+			databaseDao =  new MariadbDAO(db);
+		} else if (db.getDatabaseType() == DatabaseType.ORACLE) {
+		//	databaseDao =  new OracleDAO(db);
+		} else if (db.getDatabaseType() == DatabaseType.MSSQL) {
+		//	databaseDao =  new MssqlDAO(db);
+		} else if (db.getDatabaseType() == DatabaseType.TIBERO) {
+		// databaseDao =  new TeberoDAO(db);
+		}else if (db.getDatabaseType() == DatabaseType.POSTGRESQL) {
+		 	return new PostgresqlDAO(db);
+		} else {
+			throw new Exception();
+		}
+		return databaseDao;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * DB 접속 테스트 입니다.
+	 */
+	public CheckMessage dbConnectionCheck (ConnectionDB dbCollection) throws Exception {
+		if(StringUtil.isEmpty(dbCollection.getConectIp()) == true) {
+			return new CheckMessage(false, "접속 IP를 입력해주세요");
+		} else if(StringUtil.isEmpty(dbCollection.getConectPort()) == true) {
+			return new CheckMessage(false, "접속 Port를 입력해주세요");
+		} else if(CommonUtil.isInt(dbCollection.getConectPort()) == false) {
+			return new CheckMessage(false, "접속 Port는 숫자로만 입력해주세요");
+		} else if(StringUtil.isEmpty(dbCollection.getDatabaseNm()) == true) {
+			return new CheckMessage(false, "DB명을 입력해주세요");
+		} else if(StringUtil.isEmpty(dbCollection.getConectIp()) == true) {
+			return new CheckMessage(false, "접속 ID를 입력해주세요.");
+		} else if(StringUtil.isEmpty(dbCollection.getUserPassword()) == true) {
+			return new CheckMessage(false, "접속 PW를 입력해주세요.");
+		} else {
+			/*if (CommonUtil.pingCheck(dbCollection.getIp()) == false) {
+				return new CheckMessage(false, "접속 IP(" + dbCollection.getIp() + ")와 연결할 수 없습니다");
+			}*/
+			if (CommonUtil.linkCheck(dbCollection.getConectIp(), Integer.parseInt(dbCollection.getConectPort())) == false) {
+				return new CheckMessage(false, "접속 IP(" + dbCollection.getConectIp() + ")의 Port(" + dbCollection.getConectPort() + ")와 연결할 수 없습니다");
+			} 
+			Connection connection = null;
+			DBConnectionConfig dbUtil = new DBConnectionConfig();
+			try {
+				dbUtil.dataSourceCreate(dbCollection);
+				connection = dbUtil.getDataSource().getConnection();
+				return new CheckMessage(true, "[" + dbCollection.getDatabaseType().getValue() + "] " + dbCollection.getDatabaseNm() + " 접속 성공");
+			} catch (SQLException e) {
+				System.out.println(e.toString());
+				return new CheckMessage(false, "접속 에러 : " + e.toString());
+			} catch (Exception e) {
+				System.out.println(e.toString());
+				return new CheckMessage(false, "접속 에러 : " + e.toString());
+			} finally {
+				if (connection != null) {
+					try {
+						connection.close();
+					} catch (Exception e) {
+						System.out.println(e.toString());
+						return new CheckMessage(false, "접속 에러 : " + e.toString());
+					}
+				} if (dbUtil != null) {
+					dbUtil.close();
+				}
+			}
+		}
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * DB 접속 - 테이블 목록 조회 메소드 입니다.
+	 */
+	public List<Dataset> getDBConnectionTableList (ConnectionDB dbCollection) throws Exception {
+		CheckMessage message = dbConnectionCheck(dbCollection);
+		
+		if (message.isSuccess() == false) {
+			logger.info("getDbConnectionTableList DB연결실패 : " + message.getMessage());
+			return new ArrayList<Dataset>();
+		}
+		
+		List<Dataset> dbConnectionTableList = new ArrayList<Dataset>();
+		
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+			//테이블 목록 조회
+			 dbConnectionTableList = databaseDAO.getDBConnectionTableList(dbCollection);
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();	
+		}
+			
+		
+		
+		return dbConnectionTableList;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * 커넥션된 데이터베이스의 테이블의 컬럼 정보 조회 (DB 기준 데이터 타입, 데이터 크기 등)
+	 */
+	public List<ColumnData> getDBConnectionTableColumnList(ConnectionDB dbCollection, Dataset dataset) throws Exception {
+		CheckMessage message = dbConnectionCheck(dbCollection);
+		
+		if (message.isSuccess() == false) {
+			logger.info("getDBConnectionTableColumnList DB연결실패 : " + message.getMessage());
+			return new ArrayList<ColumnData>();
+		}
+		
+		List<ColumnData> tableColumnList = new ArrayList<ColumnData>();
+		
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+			//테이블 컬럼 목록 조회
+			tableColumnList = databaseDAO.getDBConnectionTableColumnList(dataset);
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();	
+		}
+		
+		return tableColumnList;
+	}
+	
+	/**
+	 * @author 최정우
+	 * @since 2020.01.28
+	 * 
+	 * 커넥션된 데이터베이스의 테이블의 데이터에 대한 데이터 테이블 조회 메서드입니다.
+	 */
+	public void setDataTableByDBConnectionTable (ConnectionDB dbCollection, DataTable dataTable) throws Exception {
+		CheckMessage message = dbConnectionCheck(dbCollection);
+		
+		if (message.isSuccess() == false) {
+			dataTable.setCheckMessage(message);
+			logger.info("setDataTableByDBConnectionTable DB연결실패 : " + message.getMessage());
+			return;
+		}
+		
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		int tableDataTotalRows = 0;
+		
+		List<LinkedHashMap<String, Object>> tableDataMapList  = new ArrayList<LinkedHashMap<String, Object>>();
+		
+		try {
+			
+			//테이블 기본 Select 정보(데이터베이스명, 테이블명) 입력
+			Dataset dataset = new Dataset();
+			dataset.setDatabaseNm(dbCollection.getDatabaseNm());
+			dataset.setTableNm(dataTable.getTableNm());		
+			
+			//테이블 컬럼 목록 조회
+			dataTable.setColumnDatas(databaseDAO.getDBConnectionTableColumnList(dataset));//테이블 컬럼 정보 set
+			dataTable.setColumnDatas( DataTypeUtil.convertDataTypeDbtoJavaList(dataTable.getColumnDatas(),dbCollection.getDatabaseType()));
+			
+			//테이블 데이터 조회
+			if (dbCollection.getDatabaseType() == DatabaseType.ORACLE) {
+				dataTable.setDatabaseNm(dbCollection.getUserId());
+			}
+			
+			tableDataMapList = databaseDAO.getDBConnectionTableDataList(dataTable);
+			dataTable.setRowData(CommonUtil.rowDataMapToList(tableDataMapList));//테이블 데이터 set
+			
+			//테이블 데이터 총 개수 조회
+			tableDataTotalRows = databaseDAO.getDBConnectionTableDataTotalRows(dataTable);
+			dataTable.setTotalRows(tableDataTotalRows);//테이블 데이터 총 개수 set
+			
+			//SELECT 쿼리 생성
+			dataTable.setQuery();
+			
+		}catch(Exception e) {
+			
+			logger.error(e.toString());
+			
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();
+		}
+				
+		//성공 메세지 입력
+		dataTable.getCheckMessage().setSuccess(true);
+		dataTable.getCheckMessage().setMessage("(총 조회된 행수 " + tableDataTotalRows + "개 / 현재 조회된 데이터 수 " + tableDataMapList.size() + "개)");
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * 커스텀 쿼리를 통한 dataTable setting (페이징사용 유무에 따라 페이징 처리 - {rowDatas, columnDatas, query(이미 존재함)})
+	 */
+	public void setDataTableByDBConnectionCustomQuery (ConnectionDB dbCollection, DataTable dataTable) throws Exception {
+		CheckMessage message = dbConnectionCheck(dbCollection);
+		
+		if (message.isSuccess() == false) {
+			dataTable.setCheckMessage(message);
+			logger.info("setDataTableByDBConnectionCustomQuery DB연결실패 : " + message.getMessage());
+			return;
+		}
+		
+		int tableDataTotalRows = 0;
+		
+		List<LinkedHashMap<String, Object>> tableDataMapList  = new ArrayList<LinkedHashMap<String, Object>>();
+		
+		
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+			//테이블 데이터 조회
+			tableDataMapList = databaseDAO.getDBConnectionCustomQueryDataList(dataTable);
+			
+			//DataTable에 조회된 데이터에서 첫번째 행 값의 컬럼 분리 후, columnDatas에 세팅
+			//DataTable에 rowData 세팅
+			if (tableDataMapList != null && tableDataMapList.size() > 0) {				
+				
+				//테이블 데이터 set
+				dataTable.setRowData(CommonUtil.rowDataMapToList(tableDataMapList));				
+				
+				//컬럼명 set
+				List<ColumnData> columnDatas = new ArrayList<ColumnData>();
+				LinkedHashMap<String, Object> map = tableDataMapList.get(0);
+				
+				for(String key : map.keySet()){					
+					ColumnData column = new ColumnData();
+					column.setColumnNm(key);
+					column.setDisplyColumnNm(key);
+					column.setOrginlColumnNm(key);				
+					// 데이터 타입 정의 기능 
+					column.dataTyDefine(map.get(key));					
+					columnDatas.add(column);	
+				}
+				
+				dataTable.setColumnDatas(columnDatas);				
+			}
+			
+			//테이블 데이터 총 개수 조회
+			tableDataTotalRows = databaseDAO.getDBConnectionCustomQueryDataTotalRows(dataTable);
+			dataTable.setTotalRows(tableDataTotalRows);//테이블 데이터 총 개수 set
+		}catch(Exception e) {
+			logger.error(e.toString());			
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();
+		}
+		//DB연결 종료
+		databaseDAO.dbConnectionClose();
+		
+		//성공 메세지 입력
+		dataTable.getCheckMessage().setSuccess(true);
+		dataTable.getCheckMessage().setMessage("(총 조회된 행수 " + tableDataTotalRows + "개 / 현재 조회된 데이터 수 " + tableDataMapList.size() + "개)");
+	}
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * 조회내용이 없는 실행형 커스텀 쿼리(update, delete 등)
+	 */
+	public int executeCustomQuery(ConnectionDB dbCollection, DataTable dataTable) throws Exception {
+		
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		int result = 0;
+		try {
+			result = databaseDAO.executeCustomQuery(dataTable);
+		}catch(Exception e) {
+			
+		}finally{
+			databaseDAO.dbConnectionClose();	
+		}
+		
+		return result;
+	}
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * 커스텀 쿼리 지정된 PK로 테이블 생성이 가능한지 확인
+	 */
+	public void setCustomQueryPrimaryCreatePossibleCheck (ConnectionDB dbCollection, DataTable dataTable) throws Exception {
+		
+		if (dataTable.getColumnDatas() == null || dataTable.getColumnDatas().size() == 0) {
+			dataTable.getCheckMessage().setSuccess(false);
+			dataTable.getCheckMessage().setMessage("PK생성 가능 유무 검사 - 테이블을 생성할 컬럼이 없습니다.");
+			return;
+		}
+		
+		String primaryColumns = "";
+		List<ColumnData> primaryColumnDatas = new ArrayList<ColumnData>();
+		
+		for (int i = 0; i < dataTable.getColumnDatas().size(); i++) {
+			if (dataTable.getColumnDatas().get(i).isPkAt() == true) {
+				primaryColumns += ("[" + dataTable.getColumnDatas().get(i).getColumnNm() + "]");
+				primaryColumnDatas.add(dataTable.getColumnDatas().get(i));
+			}
+		}
+		
+		if (primaryColumnDatas.size() == 0) {
+			dataTable.getCheckMessage().setSuccess(true);
+			dataTable.getCheckMessage().setMessage("PK생성 가능 유무 검사 - PK로 지정한 컬럼이 없습니다.(검사통과)");
+			return;
+		}
+		
+		//DB Connecting
+		CheckMessage message = dbConnectionCheck(dbCollection);
+		if (message.isSuccess() == false) {
+			dataTable.setCheckMessage(message);
+			logger.info("setDataTableByDBConnectionCustomQuery DB연결실패 : " + message.getMessage());
+			return;
+		}
+		
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		DataTable param = new DataTable();
+		param.setColumnDatas(primaryColumnDatas);
+		param.setQuery(dataTable.getQuery());
+		
+		//커스텀 쿼리 지정된 PK로 테이블 생성이 가능한지 확인
+		int totalOverlapCount = databaseDAO.getCustomQueryPrimaryOverlapCount(param);
+		
+		//DB연결 종료
+		databaseDAO.dbConnectionClose();
+		
+		//결과 메세지 입력
+		if (totalOverlapCount == 0) {
+			dataTable.getCheckMessage().setSuccess(true);
+			dataTable.getCheckMessage().setMessage("PK생성 가능 유무 검사 - 지정한 컬럼(" + primaryColumns + ")으로 PrimaryKey 생성이 가능합니다.");
+		} else {
+			dataTable.getCheckMessage().setSuccess(false);
+			dataTable.getCheckMessage().setMessage("PK생성 가능 유무 검사 - 지정한 컬럼(" + primaryColumns + ")으로 PrimaryKey 생성이 불가능합니다.(중복되는 데이터 수 :" + totalOverlapCount + ")");
+		}		
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * 커넥션된 데이터베이스의 테이블의 데이터에 대한 데이터 테이블 조회 메서드입니다.
+	 */
+	public void setDataTableByDBCollectionQuery (ConnectionDB dbCollection, DataTable dataTable) throws Exception {
+		if (dataTable.getColumnDatas() == null || dataTable.getColumnDatas().size() == 0) {
+			dataTable.getCheckMessage().setMessage("조회할 컬럼정보가 없습니다.");
+			dataTable.getCheckMessage().setSuccess(false);
+			logger.info("setDataTableByDBConnectionTable : " + dataTable.getCheckMessage().getMessage());
+			return;
+		}
+		
+		//DB연결 확인
+		CheckMessage message = dbConnectionCheck(dbCollection);
+		if (message.isSuccess() == false) {
+			dataTable.setCheckMessage(message);
+			logger.info("setDataTableByDBConnectionTable DB연결실패 : " + message.getMessage());
+			return;
+		}
+		
+		int tableDataTotalRows = 0;
+		
+		List<LinkedHashMap<String, Object>> tableDataMapList  = new ArrayList<LinkedHashMap<String, Object>>();
+		
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+			tableDataMapList = databaseDAO.getDBCollectionQueryDataList(dataTable);
+			dataTable.setRowData(CommonUtil.rowDataMapToList(tableDataMapList));//테이블 데이터 set
+			
+			//테이블 데이터 총 개수 조회
+			tableDataTotalRows = databaseDAO.getDBCollectionQueryDataTotalRows(dataTable);
+			dataTable.setTotalRows(tableDataTotalRows);//테이블 데이터 총 개수 set
+		}catch(Exception e) {
+			
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();
+		}
+		
+		
+		//성공 메세지 입력
+		dataTable.getCheckMessage().setSuccess(true);
+		dataTable.getCheckMessage().setMessage("(총 조회된 행수 " + tableDataTotalRows + "개 / 현재 조회된 데이터 수 " + tableDataMapList.size() + "개)");
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.04
+	 * 
+	 * 데이터 셋 목록 Convert List<TableBasicInfo> to List<ColumnData>
+	 */
+	/*
+	public List<ColumnData> tableColumnToColumnData (List<TableBasicInfo> tableBasicList) throws Exception {
+		List<ColumnData> columnDataList = new ArrayList<ColumnData>();
+		for (int i = 0; i < tableBasicList.size(); i++) {
+			TableBasicInfo tableBasicInfo = tableBasicList.get(i);
+			ColumnData columnData = new ColumnData();
+		    columnData.setTableName(tableBasicInfo.getTableName());
+		    columnData.setColumnNm(tableBasicInfo.getColumnName());
+		    columnData.setOrginlColumnNm(tableBasicInfo.getColumnName());
+		    columnData.setDisplyColumnNm(tableBasicInfo.getColumnName());
+		    columnData.setDbDataType(tableBasicInfo.getDataType());
+		    columnData.setDataSize(tableBasicInfo.getSize());
+		    columnData.setPkAt(tableBasicInfo.isPrimary());
+		    
+			columnDataList.add(columnData);
+		}
+		return columnDataList;
+	}
+	*/
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 커넥션된 데이터베이스의 실제 테이블 생성
+	 */
+	public int datasetTableCreate(ConnectionDB dbCollection, DataTable datatable) throws Exception {
+			
+		int result = 0;
+				
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+			//테이블 컬럼 목록 조회
+			result = databaseDAO.datasetTableCreate(datatable);
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();		
+		}
+		
+		return result;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 커넥션된 데이터베이스의 실제 테이블 생성
+	 */
+	public int datasetDefaultTableCreate(ConnectionDB dbCollection, DataTable datatable) throws Exception {
+			
+		int result = 0;
+				
+		//DAO 인스턴스 생성		
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+		//테이블 컬럼 목록 조회
+			result = databaseDAO.datasetDefaultTableCreate(datatable);
+		}catch(Exception e) {
+			
+			e.printStackTrace();
+			
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();		
+		}
+		
+		return result;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 커넥션된 데이터베이스의 실제 테이블 업데이트
+	 */
+	public void datasetDataUpdate(ConnectionDB dbCollection, DataTable datatable) throws Exception {
+						
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		//datatable.getColumnDatas().get(0).isAutoIncrement();
+		try {
+			//테이블 컬럼 목록 조회
+			databaseDAO.datasetDataUpdate(datatable);
+		}catch(Exception e) {
+			e.printStackTrace();
+		}
+		finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();		
+		}		
+	
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 커넥션된 데이터베이스의 실제 테이블 이름 중복검사
+	 */
+	public int duplicateCheckTableName(ConnectionDB dbCollection, Map info) throws Exception {
+	
+	
+		int result = 0;
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		try {
+			//테이블 컬럼 목록 조회
+			result = databaseDAO.duplicateCheckTableName(info);
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();
+		}	
+	
+		return result;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 데이터 셋의 컬럼 정보 목록 조회 SQL에 접근하는 메소드 입니다.(페이징)
+	 */
+	public List<LinkedHashMap<String, Object>> getRowData (ConnectionDB dbCollection, DataTable dataTable) throws Exception {
+				
+		List<LinkedHashMap<String, Object>> rowMapData = new ArrayList<LinkedHashMap<String, Object>>();
+		
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		try {
+			//테이블 컬럼 목록 조회
+			rowMapData = databaseDAO.getRowData(dataTable);
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();		
+		}	
+	
+		return rowMapData;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 데이터 셋의 컬럼 정보 목록 조회 메소드 입니다.(페이징X)
+	 */	
+	public List<LinkedHashMap<String, Object>> getRowDataAll (ConnectionDB dbCollection, DataTable dataTable) throws Exception {
+	
+		List<LinkedHashMap<String, Object>> rowMapData = new ArrayList<LinkedHashMap<String, Object>>();
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+			//테이블 컬럼 목록 조회
+			rowMapData = databaseDAO.getRowDataAll(dataTable);
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();		
+		}	
+		
+		return rowMapData;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 데이터 셋의 컬럼 정보 목록 총 갯수 조회 메소드 입니다.
+	 */
+	public int getRowDataTotalRows (ConnectionDB dbCollection, DataTable dataTable) throws Exception {
+		
+		int result = 0;
+		
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+		//테이블 컬럼 목록 조회
+			result = databaseDAO.getRowDataTotalRows(dataTable);		
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();		
+		}		
+	
+		return result;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 데이터 셋의 비우기 (데이터 셋 내용삭제)
+	 */
+	public int emptyDataset (ConnectionDB dbCollection, DataTable dataTable) throws Exception {		
+	
+		int result = 0;
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		try {
+		//테이블 컬럼 목록 조회
+			result = databaseDAO.emptyDataset(dataTable);
+		}finally {
+			//DB연결 종료
+			databaseDAO.dbConnectionClose();		
+		}
+		
+		return result;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 *  실제 생성된 컬럼 변경
+	 */
+	public int tableColumnChange (DatabaseDAO databaseDAO, TableBasicInfo tableBasicInfo) throws Exception {
+		
+		int result = 0;	
+		
+		//테이블 컬럼 목록 조회
+		result = databaseDAO.tableColumnChange(tableBasicInfo);		
+		
+		return result;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 *  실제 생성된 테이블 키변경
+	 */
+	public int changePromaryKey (DatabaseDAO databaseDAO, TableBasicInfo tableBasicInfo) throws Exception {
+		
+		int result = 0;				
+		
+		//테이블 컬럼 목록 조회
+		result = databaseDAO.changePrimaryKey(tableBasicInfo);		
+	
+		return result;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 * 데이터 셋의 ROW 삭제
+	 */
+	public void datasetDataDelete (ConnectionDB dbCollection, DataTable dataTable) throws Exception {		
+	
+		//DAO 인스턴스 생성
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		//테이블 컬럼 목록 조회
+	    databaseDAO.datasetDataDelete(dataTable);
+		
+		//DB연결 종료
+		databaseDAO.dbConnectionClose();				
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 *   AI PK 생성 
+	 */
+	public int createAutoIncrement (DatabaseDAO databaseDAO, TableBasicInfo tableBasicInfo) throws Exception {
+		
+		int result = 0;				
+		
+		//테이블 컬럼 목록 조회
+		result = databaseDAO.createAutoIncrement(tableBasicInfo);		
+	
+		return result;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2022.01.17
+	 * 
+	 *   테이블 메타정보 변경 (comments)
+	 */
+	public void updateTableMetaInfo(ConnectionDB dbCollection,DataTable dataTable) throws Exception {
+		
+		DatabaseDAO databaseDAO = createDatabaseDAO(dbCollection);
+		
+		databaseDAO.updateTableMetaInfo(dataTable);
+		
+	}
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/util/DataTypeUtil.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/util/DataTypeUtil.java
@@ -0,0 +1,159 @@
+package com.takensoft.taken_bi_manager.common.connection.db.util;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.takensoft.taken_bi_manager.common.connection.db.vo.DataType;
+import com.takensoft.taken_bi_manager.common.vo.SystemCode.DatabaseType;
+import com.takensoft.taken_bi_manager.data.vo.ColumnData;
+
+/**
+ * @author 김성원
+ * @since 2024.01.02
+ * 
+ * 데이터 타입별로 DB -> JAVA ,  JAVA -> DB 변경을 위한 인터페이스 입니다.
+ */
+public class DataTypeUtil {
+
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 데이터베이스 자료타입을 자바형태로 변환
+	 */
+	public static DataType convertDataTypeDbtoJava (ColumnData column, DatabaseType databaseType ) {
+    	
+		 DataType dataType = null;
+		 
+		if(databaseType.equals(DatabaseType.MARIADB) || databaseType.equals(DatabaseType.MYSQL)){
+			dataType = mariadbDataConvertDBtoJava(column);
+		}else {
+			dataType = postgresqlDbDataConvertDBtoJava(column);
+		}
+    	
+    	return dataType;	    	
+    }
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 자바 자료형태를 DB 타입으로 변환 
+	 */
+	public static DataType convertDataTypeJavatoDB (ColumnData column, DatabaseType databaseType ) {
+    	
+    	
+    	return null;	    	
+    }
+	
+	public static List<ColumnData> convertDataTypeDbtoJavaList(List<ColumnData> ColumnDatas , DatabaseType databaseType){
+		
+		for(ColumnData item : ColumnDatas) {
+			item.setDataTy(convertDataTypeDbtoJava(item,databaseType));
+		}
+		
+		
+		return ColumnDatas;		
+	}
+	
+	 
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 마리아 및 myslq 데이터베이스 자료타입을 자바형태로 변환
+	 */
+	 private static DataType mariadbDataConvertDBtoJava(ColumnData column) {
+		 
+		 DataType dataType = null;
+		 
+		 // 스트링 타입 변환 
+		 if(Arrays.asList("TEXT", "VARCHAR", "TINYTEXT", "LONGTEXT","ENUM","SET","CHAR","LONGBLOB","BLOB","TINYBLOB","VARBINARY","BINARY","CHAR").contains(column.getDbDataType().toUpperCase().trim())) {
+			 dataType = DataType.STRING;
+		 }
+		 // boolean 타이 변환 
+		 else  if(Arrays.asList("BIT").contains(column.getDbDataType().toLowerCase().trim())) {
+			 dataType = DataType.INT;
+		 }
+		 // Integer 타이 변환 
+		 else  if(Arrays.asList("TINYINT", "SMALLINT").contains(column.getDbDataType().toUpperCase().trim())) {
+			 dataType = DataType.INT;
+		 }
+		// Long 타이 변환 
+		 else  if(Arrays.asList("MEDIUMINT", "INT","BIGINT").contains(column.getDbDataType().toUpperCase().trim())) {
+			 dataType = DataType.INT;
+		 }
+		 // float 타이 변환 
+		 else  if(Arrays.asList("FLOAT").contains(column.getDbDataType().toUpperCase().trim())) {
+			 dataType = DataType.FLOAT;
+		 }
+		 // double 타이 변환 
+		 else  if(Arrays.asList("DOUBLE").contains(column.getDbDataType().toUpperCase().trim())) {
+			 dataType = DataType.DOUBLE;
+		 }
+		 // DECIMAL  타이 변환 
+		 else  if(Arrays.asList("DECIMAL").contains(column.getDbDataType().toUpperCase().trim())) {
+			 dataType = DataType.DECIMAL;
+		 }
+		 // DATE  타이 변환 
+		 else  if(Arrays.asList("DATE").contains(column.getDbDataType().toUpperCase().trim())) {
+			 dataType = DataType.DATE;
+		 } 
+		 // TIMESTAMP  타이 변환 
+		 else  if(Arrays.asList("DATETIME,TIMESTAMP,TIME").contains(column.getDbDataType().toUpperCase().trim())) {
+			 dataType = DataType.TIMESTAMP;
+		 } 		
+		 
+		 return dataType;
+	 }
+	 
+	 /**
+		 * @author 김성원
+		 * @since 2024.01.09
+		 * 
+		 * 마리아 및 myslq 데이터베이스 자료타입을 자바형태로 변환
+		 */
+		 private static DataType postgresqlDbDataConvertDBtoJava(ColumnData column) {
+			 
+			 DataType dataType = null;
+			 
+			 // 스트링 타입 변환 
+			 if(Arrays.asList("character varying", "character","text").contains(column.getDbDataType().toLowerCase().trim())) {
+				 dataType = DataType.STRING;
+			 }
+			 // boolean 타이 변환 
+			 else  if(Arrays.asList("bit").contains(column.getDbDataType().toLowerCase().trim())) {
+				 dataType = DataType.BOOL;
+			 }
+			 // Integer 타이 변환 
+			 else  if(Arrays.asList("integer","smallint","serial").contains(column.getDbDataType().toLowerCase().trim())) {
+				 dataType = DataType.INT;
+			 }
+			 // Long 타이 변환 
+			 else  if(Arrays.asList("bigint", "bigserial").contains(column.getDbDataType().toLowerCase().trim())) {
+				 dataType = DataType.LONG;
+			 }			
+			 // float 타이 변환 
+			 else  if(Arrays.asList("real").contains(column.getDbDataType().toLowerCase().trim())) {
+				 dataType = DataType.FLOAT;
+			 }
+			 // double 타이 변환 
+			 else  if(Arrays.asList("double precision","numeric").contains(column.getDbDataType().toLowerCase().trim())) {
+				 dataType = DataType.DOUBLE;
+			 }			
+			 // DATE  타이 변환 
+			 else  if(Arrays.asList("date","time without time zone").contains(column.getDbDataType().toLowerCase().trim())) {
+				 dataType = DataType.DATE;
+			 } 
+			 // TIMESTAMP  타이 변환 
+			 else  if(Arrays.asList("time","timestamp","timestamp with time zone","timestamp without time zone", "time with time zone").contains(column.getDbDataType().toLowerCase().trim())) {
+				 dataType = DataType.TIMESTAMP;
+			 }else {
+				 dataType = DataType.STRING;
+			 }
+			 
+			 return dataType;
+		 }
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/vo/ConnectionDB.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/vo/ConnectionDB.java
@@ -0,0 +1,70 @@
+package com.takensoft.taken_bi_manager.common.connection.db.vo;
+
+import java.sql.Timestamp;
+
+import com.takensoft.taken_bi_manager.common.vo.SystemCode.DatabaseType;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ConnectionDB {
+
+	// 커넥션 설명
+	private String conectNm;
+	
+	// 커넥션 이름
+	private String conect_dc;
+	
+	// 데이터베이스명(데이터 베이스 > 스키마) 
+	private String databaseNm;
+	
+	// 스키마명
+	private String schemaNm;
+	
+	// 데이터 베이스 타입	
+	private DatabaseType databaseType;
+	
+	// IP or URL
+	private String conectIp;
+	
+	// 접속 포트 
+	private String conectPort;
+	
+	// 접속 아이디
+	private String userId;
+	
+	// 접속 비밀번호
+	private String userPassword;
+	
+	// 접속 옵션 
+	private String option;
+	
+	// 사용여부
+	private String useAt;
+	
+	
+	
+	/**
+	 * 오라클
+	 * 	SERVICE: true 
+	 *  SID: false
+	 *  인지 아닌지
+	 */
+	private boolean isGroupDatabase;	
+	
+	// 생성일
+	private Timestamp creatDt;
+	
+	// 생성자ID
+	private String creatId;
+	
+	// 수정일 
+	private Timestamp updtDt;
+		
+	// 수정자 ID
+	private String updtId;
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/vo/DataType.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/vo/DataType.java
@@ -0,0 +1,269 @@
+package com.takensoft.taken_bi_manager.common.connection.db.vo;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import com.takensoft.taken_bi_manager.common.util.CommonUtil;
+import com.takensoft.taken_bi_manager.common.util.StringUtil;
+
+/**
+ * @author 김성원
+ * @since 2024.01.02
+ * 
+ * 데이터 타입을 정의한 상수 Class 입니다.
+ * 상수명(java데이터타입, 초기값, mysql데이터타입, display데이터타입
+ */
+
+public enum DataType {
+	NULL(null, null)
+	, BYTE(Byte.class, 0)
+	, BOOL(Boolean.class, false)
+	, CHAR(Character.class, '\u0000')
+	, STRING(String.class, "")
+	, SHORT(Short.class, 0)
+	, INT(Integer.class, 0)
+	, DECIMAL(BigDecimal.class,0)
+	, LONG(Long.class, 0)
+	, FLOAT(Float.class, 0.0)
+	, DOUBLE(Double.class, 0.0)
+	, DATE(Date.class, "")
+	, DATETIME(Date.class, "")
+	, TIMESTAMP(Timestamp.class, "")
+	, ENTER(Character.class,'\n');
+
+	/**
+	 * enum(열거형데이터)의 생성자 
+	 * 1. 상수에 나열된 parameter와 형태가 똑같이 만들어줘야함.
+	 * 2. 접근제한자는 private로만 다른 접근제한자는 허용하지 않음
+	 */
+	private DataType (Class<?> javaType, Object iniValue) {
+        this.javaType = javaType;
+        this.initValue = iniValue;
+    }
+	
+	/**
+	 * java데이터타입
+	 */
+	final private Class<?> javaType;
+	
+	/**
+	 * 초기값
+	 */
+	final private Object initValue;
+	
+    public Class<?> getJavaType() {
+        return javaType;
+    }
+    public Object getInitValue() {
+        return initValue;
+    }
+    	 
+    
+    /**
+	 * 데이터 타입 검사, DataType 조회
+	 */
+    public static Map<DataType, String> getDataTypeList () {
+    	Map<DataType, String> info = new LinkedHashMap<DataType, String>();
+    	info.put(STRING, "문자열");
+    	info.put(LONG, "정수");
+    	info.put(DOUBLE, "실수");
+    	info.put(DATE, "날짜");
+    	info.put(DATETIME,"날짜,시간");
+    	return info;
+	}
+    
+    
+    /**
+	 * 데이터 타입 검사, DataType 조회
+	 */
+    public static List<DataType> getDataTypeArray () {
+    	List<DataType> info = new ArrayList<DataType>();
+    	info.add(STRING);
+    	info.add(LONG);
+    	info.add(DOUBLE);
+    	info.add(DATE);
+    	info.add(DATETIME);
+    	info.add(BOOL);
+    	return info;
+	}
+    
+    /**
+	 * 데이터 타입 검사, DataType 조회
+	 */
+    public static DataType getDataType (String text) {
+    	/*
+    	 * 2021-11-02 김혜민 dataType 전화번호, 날짜 정규식 수정
+    	 * 
+    	 * 
+    	 * 전화번호 정규식*/
+    	String regExp = "^\\d{2,3}-\\d{3,4}-\\d{4}$";
+    	String regDateTime = "\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]) (0[1-9]|1[0-9]|2[0-4]):(0[1-9]|[1-5][0-9]):(0[1-9]|[1-5][0-9])";
+    	String regDate = "\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])";
+    			
+		if(StringUtil.isEmpty(text)) {
+			return NULL;
+		} else if(CommonUtil.isLong(text)) {
+			/*
+			 * 숫자로 변환 가능 하지만 앞에 '0'이 붙어 있으면 문자열로 봄
+			 * ex) 0102 -> String, 1102 -> Long
+			 */
+			if (text.length() > 1 && text.indexOf("0") == 0) {
+				return STRING;
+			} else {
+				return LONG;
+			}
+		}else if(CommonUtil.isDouble(text)) {
+			
+			return DOUBLE;
+			
+		} else if (CommonUtil.isDate(text)) {
+			/*
+	    	 * 2021-11-02 김혜민 dataType 전화번호, 날짜 정규식 수정
+	    	 * 
+	    	 * 
+	    	 * 전화번호 정규식*/
+	    	boolean expResult = Pattern.matches(regExp, text);
+	    	boolean dateTimeResult = Pattern.matches(regDateTime, text);
+	    	boolean dateResult = Pattern.matches(regDate, text);
+	    	
+			if(expResult) {
+				return STRING;
+			}else if(dateResult) {				
+				return DATE;
+			}else {
+				return DATETIME;
+			}
+			
+		} else {
+			return STRING;
+		}
+	}
+    
+    /**
+	 * 데이터 타입 검사, dbDataType 조회
+	 */
+    public static String convertDbDataType (DataType datatype, Integer size) {
+    	final int MAX_VARCHAR_SIZE = 765;
+    	
+    	if (datatype == STRING) {
+    		if (size == null || size <= MAX_VARCHAR_SIZE) {
+    			return "varchar";
+    		} else {
+    			return "text";
+    		}
+    	} else if (datatype == DATE) {
+    		return "date";
+    	} else if (datatype == DATETIME){
+    		return "datetime";
+    	} else if (datatype == LONG) {
+    		return "bigint";
+    	} else if (datatype == DOUBLE) {
+    		return "double";
+    	} else {
+    		return "varchar";
+    	}
+    }
+    
+    /**
+	 * 데이터 타입 검사, dbDataType -> javaType 조회
+	 */
+    public static DataType convertDataTypeDbtoJava (DataType datatype, Integer size) {
+    	
+    	
+    	return null;	    	
+    }
+    
+    
+    /**
+	 * 데이터 타입 형태로 값 변경
+	 */
+	public static Object parse(DataType dataType, Object value) {
+		if (CommonUtil.isNull(value) == true) {
+			return null;
+		}
+		
+		Class<?> javaType = dataType.getJavaType();
+		try {
+			if (javaType.getSimpleName().equals("Byte")) {
+				return Byte.parseByte(value.toString());
+			} else if (javaType.getSimpleName().equals("Boolean")) {
+				return Boolean.parseBoolean(value.toString());
+			} else if (javaType.getSimpleName().equals("Character")) {
+				return value.toString().toCharArray();
+			} else if (javaType.getSimpleName().equals("String")) {
+				return value.toString();
+			} else if (javaType.getSimpleName().equals("Short")) {
+				//Short.parseShort(value.toString().replaceAll("[^0-9]",""));
+				return Short.parseShort(value.toString());
+			} else if (javaType.getSimpleName().equals("Integer")) {
+				//Integer.parseInt(value.toString().replaceAll("[^0-9]",""));
+				return Integer.parseInt(value.toString());
+			} else if (javaType.getSimpleName().equals("Long")) {
+				//Long.parseLong(value.toString().replaceAll("[^0-9]",""));
+				return Long.parseLong(value.toString());
+			} else if (javaType.getSimpleName().equals("Float")) {
+				//Float.parseFloat(value.toString().replaceAll("[^0-9]",""));
+				return Float.parseFloat(value.toString());
+			} else if (javaType.getSimpleName().equals("Double")) {
+				//Double.parseDouble(value.toString().replaceAll("[^0-9]",""));
+				return Double.parseDouble(value.toString());
+			} else {
+				return value;
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			return dataType.getInitValue();
+		}
+	}
+	
+	/**
+	 * 데이터 타입 형태로 값 변경
+	 */
+	public static boolean parseCheck (DataType dataType, Object value) {
+		if (CommonUtil.isNull(value) == true) {
+			return false;
+		}
+		
+		Class<?> javaType = dataType.getJavaType();
+		try {
+			if (javaType.getSimpleName().equals("Byte")) {
+				Byte.parseByte(value.toString());
+			} else if (javaType.getSimpleName().equals("Boolean")) {
+				Boolean.parseBoolean(value.toString());
+			} else if (javaType.getSimpleName().equals("Character")) {
+				value.toString().toCharArray();
+			} else if (javaType.getSimpleName().equals("String")) {
+				value.toString();
+			} else if (javaType.getSimpleName().equals("Short")) {
+				//Short.parseShort(value.toString().replaceAll("[^0-9]",""));
+				Short.parseShort(value.toString());
+			} else if (javaType.getSimpleName().equals("Integer")) {
+				//Integer.parseInt(value.toString().replaceAll("[^0-9]",""));
+				Integer.parseInt(value.toString());
+			} else if (javaType.getSimpleName().equals("Long")) {
+				//Long.parseLong(value.toString().replaceAll("[^0-9]",""));
+				Long.parseLong(value.toString());
+			} else if (javaType.getSimpleName().equals("Float")) {
+				//Float.parseFloat(value.toString().replaceAll("[^0-9]",""));
+				Float.parseFloat(value.toString());
+			} else if (javaType.getSimpleName().equals("Double")) {
+				//Double.parseDouble(value.toString().replaceAll("[^0-9]",""));
+				Double.parseDouble(value.toString());
+			}
+			
+			return true;
+		} catch (Exception e) {
+			//e.printStackTrace();
+			return false;
+		}
+	}
+	
+	
+}
+
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/vo/TableBasicColumn.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/vo/TableBasicColumn.java
@@ -0,0 +1,56 @@
+package com.takensoft.taken_bi_manager.common.connection.db.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2024.01.04
+ * 
+ * 데이터 베이스 기본 정보를 담는 Class 입니다.
+ */
+@Getter
+@Setter
+public class TableBasicColumn implements Cloneable{
+	
+	public TableBasicColumn () {}
+	
+	public TableBasicColumn (TableBasicInfo tableBasicInfo) {
+		this.columnName = tableBasicInfo.getColumnName();
+		this.tobeColumnName = tableBasicInfo.getTobeColumnName();
+		this.dataType = tableBasicInfo.getDataType();
+		this.size = tableBasicInfo.getSize();
+	}
+	
+	/**
+	 * 컬럼명
+	 */
+	private String columnName;
+	
+	/**
+	 * 바뀔 컬럼명
+	 */
+	private String tobeColumnName;
+	
+	/**
+	 * 컬럼의 데이터 타입(DB기준)
+	 */
+	private String dataType;
+	
+	/**
+	 * 컬럼의 데이터 size
+	 */
+	private long size;
+	
+	/**
+	 * 해당 열의 PK인지 아닌지에 대한 여부
+	 */
+	private boolean isPrimary;
+
+
+	
+	public TableBasicColumn clone() throws CloneNotSupportedException {
+        return (TableBasicColumn)super.clone();
+    }
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/connection/db/vo/TableBasicInfo.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/connection/db/vo/TableBasicInfo.java
@@ -0,0 +1,85 @@
+package com.takensoft.taken_bi_manager.common.connection.db.vo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2024.01.04
+ * 
+ * 데이터 베이스 기본 설정 변경시 사용할 class 입니다.
+ */
+@Getter
+@Setter
+public class TableBasicInfo {
+	
+	public TableBasicInfo () {}
+	
+	public TableBasicInfo (String databaseName, String tableName, String columnName) {
+		this.databaseName = databaseName;
+		this.tableName = tableName;
+		this.columnName = columnName;
+	}
+
+	/**
+	 * 데이터 베이스 명 (스키마명)
+	 */
+	private String databaseName;
+	
+	/**
+	 * 데이터 베이스 접속 아이디
+	 */
+	private String id;
+	
+	/**
+	 * 테이블명
+	 */
+	private String tableName;
+	
+	/**
+	 * 컬럼명
+	 */
+	private String columnName;
+	
+	/**
+	 * 바뀔 컬럼명
+	 */
+	private String tobeColumnName;
+	
+	/**
+	 * 컬럼의 데이터 타입(DB기준)
+	 */
+	private String dataType;
+	
+	/**
+	 * 컬럼의 데이터 size
+	 */
+	private long size;
+	
+	/**
+	 * 해당 열의 PK인지 아닌지에 대한 여부
+	 */
+	private boolean isPrimary;
+		
+	/**
+	 * PK 리스트 
+	 */
+	private List<String> primaryList;		
+	
+	/**
+	 * PK 리스트 
+	 */
+	private String process;
+		
+
+	/**
+	 * 컬럼의 데이터 목록
+	 */
+	List<TableBasicColumn> tableBasicColumns = new ArrayList<TableBasicColumn>(); 
+
+	
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/file/vo/CmmnFile.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/file/vo/CmmnFile.java
@@ -0,0 +1,48 @@
+package com.takensoft.taken_bi_manager.common.file.vo;
+
+import java.sql.Timestamp;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2023-12-28
+ * 
+ * 공통파일 관리 객체
+ */
+@Getter
+@Setter
+public class CmmnFile {
+
+	// 파일ID 
+	private String fileId;
+	
+	// 파일명
+	private String name;
+	
+	// 파일 마스크 먕
+	private String maskName;
+	
+	// 파일사이즈
+	private long size;
+	
+	// 콘텐츠 타입? 
+	private String contentType;
+	
+	// 파일 경로 
+	private String fullPath;
+	
+	// 파일 서브 경로 
+	private String subPath;
+	
+	// 파일 확장자
+	private String extention;
+	
+	// 생성일 
+	private Timestamp creatDt;
+	
+	// 파일매니저 ID
+	private String fileManagerId;
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/file/vo/FileInfo.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/file/vo/FileInfo.java
@@ -0,0 +1,119 @@
+package com.takensoft.taken_bi_manager.common.file.vo;
+
+import java.io.File;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2024.01.12
+ * 
+ * 파일변환 관련 Object입니다. 
+ */
+@Getter
+@Setter
+public class FileInfo {
+	
+	
+	/**
+	 * 생성자(파일)
+	 */
+	public FileInfo(File file) {
+		this.file = file;
+	}
+	
+	/**
+	 * 생성자(파일, 확장자)
+	 */
+	public FileInfo(File file, String fileFome) {
+		this.file = file;
+		this.fileFom = fileFome;
+	}
+	
+	
+	/**
+	 * 생성자(파일및, 확장자, 구분자)
+	 */
+	public FileInfo(File file, String fileFome, String suffix) {
+		this.file = file;
+		this.fileFom = fileFome;
+		this.suffix = suffix;
+		
+	}
+	
+
+	/** 
+	 * 관리 파일
+	 */
+	private File file;	
+	
+	/**
+	 *  파일 명
+	 */
+	private String fileName;
+
+	
+	/**
+	 *  파일 수집 타입 : 전체, 포함, 특정
+	 */
+	private String type;	
+	
+	/**
+	 *  마지막  파일 옵션
+	 */
+	private boolean lastData;
+	
+	/**
+	 *  데이터셋 업데이트 보다 최신 파일만 선택 옵션
+	 */
+	private boolean datasetAfter;	
+	
+	/**
+	 *  데이터셋 아이디
+	 */
+	private String datasetId;
+	
+	/**
+	 * 데이터(행,열)의 컬럼인 Row의 Index
+	 */
+	private int rowDataColumnIndex;
+	
+	/**
+	 * 데이터(행,열)의 Row 시작 Index
+	 */
+	private int startRowIndex;
+	
+	/**
+	 * 데이터(행,열)의 Cell 시작 Index
+	 */
+	private int startCellIndex;
+	
+	/**
+	 *  파일 쓰기 옵션
+	 */
+	private boolean streOptn = true;
+	
+	/**
+	 *   파일 타입 : xlsx, xls, csv, text, json, xml ... 
+	 */
+	private String fileFom = "xlsx";
+	
+	/**
+	 *  날짜시간 형식
+	 */
+	private String suffix = "_YYYYMMDDHHmmss";
+	
+	/**
+	 * 일계산
+	 */
+	private int addDay = 0;	
+	
+	/**
+	 * file 구분자
+	 */
+	private String delimiter = ",";	
+	
+
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/file/vo/FileManage.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/file/vo/FileManage.java
@@ -0,0 +1,132 @@
+package com.takensoft.taken_bi_manager.common.file.vo;
+
+
+import java.sql.Timestamp;
+import java.util.Date;
+
+import com.takensoft.taken_bi_manager.common.vo.SystemCode.FileType;
+
+import lombok.Getter;
+import lombok.Setter;
+
+
+
+/**
+ * @author 김성원
+ * @since 2023.12.29
+ * 
+ * File 관리 Domain 입니다.
+ */
+@Getter
+@Setter
+public class FileManage {
+	
+	public FileManage() {};
+	
+	public FileManage(String fileManagerId) {
+		this.fileManagerId = fileManagerId;
+	};
+	
+	public FileManage(long fileSeq) {
+		this.fileId = fileSeq;
+	};
+	
+	public FileManage(String fileManagerId, long fileSeq) {
+		this.fileManagerId = fileManagerId;
+		this.fileId = fileSeq;
+	};
+	
+	public FileManage(FileType fileType) {
+		this.fileType = fileType;
+	};
+	
+	public FileManage(FileType fileType, String contentType) {
+		this.fileType = fileType;
+		this.contentType = contentType;
+	};
+	
+	public FileManage(String fileManagerId, FileType fileType) {
+		this.fileManagerId = fileManagerId;
+		this.fileType = fileType;
+	};
+	
+	public FileManage(String fileManagerId, FileType fileType, String contentType) {
+		this.fileManagerId = fileManagerId;
+		this.fileType = fileType;
+		this.contentType = contentType;
+	};
+
+	/**
+	 * 파일 관리 아이디
+	 */
+	private String fileManagerId;
+	
+	/**
+	 * 파일 타입
+	 */
+	private FileType fileType;
+	
+	/**
+	 * 등록한 컨텐츠 타입
+	 */
+	private String contentType;
+	
+	/**
+	 * 파일 SEQ
+	 */
+	private long fileId;
+
+	/**
+	 * 파일명
+	 */
+	private String name;
+
+	/**
+	 * 마스크 파일명
+	 */
+	private String maskName;
+
+	/**
+	 * 파일 사이즈.
+	 */
+	private long size;
+
+	/**
+	 * 서브 디렉토리.
+	 */
+	private String subDir;
+	
+	/**
+	 * 데이터 셋 파일 절대 경로
+	 */
+	private String fullDir;
+
+	/**
+	 * 파일 확장자.
+	 */
+	private String extension;
+
+	/**
+	 * 파일 생성일.
+	 */
+	private Date createDate;
+	
+	
+	
+	
+	
+	/**
+	 * file 관련 메세지
+	 */
+	//private CheckMessage checkMessage = new CheckMessage();	
+
+//	public CheckMessage getCheckMessage() {
+//		return checkMessage;
+//	}
+//
+//	public void setCheckMessage(CheckMessage checkMessage) {
+//		this.checkMessage = checkMessage;
+//	}
+
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/util/AuthUtil.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/util/AuthUtil.java
@@ -0,0 +1,100 @@
+package com.takensoft.taken_bi_manager.common.util;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpSession;
+
+import java.util.HashMap;
+
+public class AuthUtil {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AuthUtil.class);
+
+    //Session에 등록된 Login User ID Key
+    public static final String LOGIN_USER_SESSION = "loginUser";
+
+    //중복 로그인가능 여부
+    public static final boolean IS_POSSIBLE_DUPLICATION_LOGIN = false;
+
+    //Session Max 시간(초)
+    public static final int SESSION_MAX_TIME = 60*60*6;//6시간
+
+    public static HashMap<String, Object> getLoginUser () {
+        try {
+            //현재 client의 HttpSession 조회
+            HttpSession session = CommonUtil.getHttpSession(false);
+            if(session == null || session.getAttribute(LOGIN_USER_SESSION) == null || ((HashMap<String, Object>) session.getAttribute(LOGIN_USER_SESSION)).get("user_id") == null) {
+                return null;
+            }else {
+                return (HashMap<String, Object>) session.getAttribute(LOGIN_USER_SESSION);
+            }
+        } catch(NullPointerException e) {
+            LOGGER.error(e.toString());
+         //   System.out.println("AuthUtil getLoginUser Error : ");
+         //   e.printStackTrace();
+            return null;
+        }
+    }
+
+    public static String getLoginUserId () {
+        HashMap<String, Object> user = getLoginUser();
+        if (user != null) {
+            return (String) user.get("user_id");
+        } else {
+            return null;
+        }
+    }
+    public static HashMap<String, Object> getKey () {
+        try {
+            //현재 client의 HttpSession 조회
+            HttpSession session = CommonUtil.getHttpSession(true);
+            if(session == null || session.getAttribute("key") == null || ((HashMap<String, Object>) session.getAttribute("key")).get("salt") == null) {
+                return null;
+            }else {
+                return ((HashMap<String, Object>) session.getAttribute("key"));
+            }
+        } catch(NullPointerException e) {
+            LOGGER.error(e.toString());
+            return null;
+        }
+    }
+
+    public static String getKeySaltKey () {
+        HashMap<String, Object> key = getKey();
+        if (key != null ) {
+            if(key.get("salt") != null) {
+                return key.get("salt").toString();
+            }else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+    public static String getKeyIvtKey () {
+        HashMap<String, Object> key = getKey();
+        if (key != null ) {
+            if(key != null) {
+                return key.get("iv").toString();
+            }else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+    public static String getKeyENC_KEY () {
+        HashMap<String, Object> key = getKey();
+        if (key != null ) {
+            if(key.get("ENC_KEY") != null) {
+                return key.get("ENC_KEY").toString();
+            }else{
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/util/CommonUtil.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/util/CommonUtil.java
@@ -0,0 +1,718 @@
+package com.takensoft.taken_bi_manager.common.util;
+
+
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpSession;
+
+import org.json.XML;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+public class CommonUtil {
+
+	/**
+     * @author 최정우
+     * @since 2019.12.11
+     * 
+     * 데이터의 표준화 사용 유무 
+     */
+	private static boolean IS_USE_STANDARD = true;
+	
+	public static void setIsUseStandard (boolean isUseStandard) {
+		IS_USE_STANDARD = isUseStandard;
+	}
+	
+	public static boolean getIsUseStandard () {
+		return IS_USE_STANDARD;
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 빈 문자열 검사
+     */
+    public static boolean isNull(Object obj) {
+        return obj == null;
+    }
+    
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * string to int check
+     */
+    public static boolean isInt (String text) {
+		try {
+			Integer.parseInt(text);
+			return true;
+		} catch(NumberFormatException e) {
+			return false;
+		}
+	}
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * string to int check
+     */
+    public static boolean isLong (String text) {
+		try {
+			Long.parseLong(text);
+			return true;
+		} catch(NumberFormatException e) {
+			return false;
+		}
+	}
+	
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * string to double check
+     */
+	public static boolean isDouble (String text) {
+		try {
+			Double.parseDouble(text);
+			return true;
+		} catch (NumberFormatException e) {
+			return false;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2020.01.08
+     * 
+     * object to int
+     */
+	public static int parseInt (Object obj) {
+		try {
+			return Integer.parseInt(obj.toString());
+		} catch(Exception e) {
+			return 0;
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2020.01.08
+     * 
+     * string to int
+     */
+	public static int parseInt (String text) {
+		try {
+			return Integer.parseInt(text);
+		} catch(NumberFormatException e) {
+			return 0;
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2020.01.08
+     * 
+     * int to double 
+     */
+	public static long parseLong (int number) {
+		try {
+			return (long) number;
+		} catch(Exception e) {
+			return 0;
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2020.01.08
+     * 
+     * object to double 
+     */
+	public static long parseLong (String text) {
+		try {
+			return Long.parseLong(text);
+		} catch(Exception e) {
+			return 0;
+		}
+	}
+
+	/**
+     * @author 최정우
+     * @since 2020.01.08
+     * 
+     * object to double 
+     */
+	public static long parseLong (Object obj) {
+		try {
+			if (obj instanceof Integer) {
+				return (long) obj;
+			} else {
+				return Long.parseLong(obj.toString());
+			}
+		} catch(Exception e) {
+			return 0;
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2020.01.08
+     * 
+     * int to double 
+     */
+	public static double parseDouble (int number) {
+		try {
+			return (double) number;
+		} catch(Exception e) {
+			return 0.0;
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2020.01.08
+     * 
+     * object to double 
+     */
+	public static double parseDouble (String text) {
+		try {
+			return Double.parseDouble(text);
+		} catch(Exception e) {
+			return 0.0;
+		}
+	}
+
+	/**
+     * @author 최정우
+     * @since 2020.01.08
+     * 
+     * object to double 
+     */
+	public static double parseDouble (Object obj) {
+		try {
+			if (obj instanceof Integer) {
+				return (double) obj;
+			} else {
+				return Double.parseDouble(obj.toString());
+			}
+		} catch(Exception e) {
+			return 0.0;
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열의 모든 공백 제거
+     */
+	public static String allTrim(String text) {
+		return text.replaceAll("\\p{Z}", "");
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열 앞뒤 공백 제거후, 문자열 사이에 존재하는 공백을 한개의 공백으로 치환
+     * ex) " abcd     efg    hijk   " => "abcd efg hijk" 
+     */
+	public static String normalizeSpace(String text) {
+		return text.trim().replaceAll("\\s+", " ");
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 숫자 빼고 모든 문자 제거
+     */
+	public static String getOnlyNumber (String text) {
+		return text.replaceAll("[^0-9]", "");
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자 빼고 모든 숫자 제거
+     */
+	public static String getOnlyText (String text) {
+		return text.replaceAll("[0-9]", "");
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 특정 문자열 개수 check
+     */
+	public static int getWordCount (String text, String word) {
+		int size = 0;
+		int fromIndex = -1;
+		while ((fromIndex = text.indexOf(word, fromIndex + 1)) >= 0) {
+			size++;
+		}
+		return size;
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열 to Date문자열
+     */
+	public static boolean isDate (String text) {
+		if (StringUtil.isEmpty(text) == true || StringUtil.isEmpty(getOnlyNumber(text)) == true || getOnlyNumber(text).length() < 6) {
+			return false;
+		}
+		
+		//공백을 제외한 문자얻기, 대문자로 치환
+		String newText = allTrim(text).toUpperCase();
+		
+		try {
+			//문자열의 날짜 패턴 생성
+			String pattern = createDatePattern(newText);
+			if (pattern == null) {
+				return false;
+			}
+		
+			SimpleDateFormat newPattern = new SimpleDateFormat(pattern);
+			//문자열 날짜 형태로 변환
+			newPattern.parse(newText);
+			return true;
+		} catch (Exception e) {
+			//e.printStackTrace();
+			return false;
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열 to Date문자열
+     */
+	public static String parseDateText (String text) {
+		if (StringUtil.isEmpty(text) == true || StringUtil.isEmpty(getOnlyNumber(text)) == true || getOnlyNumber(text).length() < 6) {
+			return null;
+		}
+		
+		//공백을 제외한 문자얻기, 대문자로 치환
+		String newText = allTrim(text).toUpperCase();
+		
+		//문자열의 날짜 패턴 생성 
+		String pattern = createDatePattern(newText);
+		if (pattern == null) {
+			return null;
+		}
+
+		Date date = null;
+		String dateText = null;
+		try {
+			SimpleDateFormat newPattern = new SimpleDateFormat(pattern);
+			
+			//문자열 날짜 형태로 변환
+			date = newPattern.parse(newText);
+			
+			//DB에 저장할 날짜 패턴
+			SimpleDateFormat defalutPattern = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+			dateText = defalutPattern.format(date);
+		} catch (Exception e) {
+			//e.printStackTrace();
+		}
+		return dateText;
+	}
+	
+	public static <T> List<T> mapToList (Map<?, T> map) {
+		List<T> items = new ArrayList<T>();
+		
+		if (map != null) {
+			for(Map.Entry<?, T> item : map.entrySet()) {
+				items.add(item.getValue());
+	        }
+		}
+		
+		return items;
+	}
+	
+	public static Map objectToMap(Object obj) {
+		if (obj != null) {
+			try {
+				return (Map) obj;
+			} catch (Exception e) {
+				return new HashMap();
+			}
+		} else {
+			return new HashMap();
+		}
+	}
+	
+	
+	/*
+	 * 시간 타입
+	 * PM, AM
+	 */
+	public final static List<String> TIME_TYPES = Arrays.asList(new String[] {"AM", "PM", "오전", "오후"});
+	
+	/*
+	 * 날짜 포맷 패턴's
+	 */
+	public final static List<Character> DATE_PATTERNS = Arrays.asList(new Character[] {'y', 'M', 'd', 'H', 'm', 's'});
+	
+	/*
+	 * 날짜 포맷 패턴's의 최대 문자열 수
+	 */
+	public final static List<Integer> DATE_PATTERNS_MAX_LENGTH = Arrays.asList(new Integer[] {4, 2, 2, 2, 2, 2});
+	
+	/**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열의 날짜 패턴 생성
+     */
+	public static String createDatePattern (String date) {
+		
+		List<Character> DATE_PATTERNS = Arrays.asList(new Character[] {'y', 'M', 'd', 'H', 'm', 's'});
+		
+		//시간 표기가 (0~12 -> AM, PM사용)인지 (0~23)인지 확인 후, 날짜 포맷 패턴's에 있는 시간 패턴 변경
+		int timeTypeFindIndex = -1;
+		for (int i = 0; i < TIME_TYPES.size(); i++) {
+			//("AM", "PM", "오전", "오후" 중 1개)가 포함된 단어가 있는지 확인, Index 위치를 담기(없으면 -1)
+			if ((timeTypeFindIndex = date.indexOf(TIME_TYPES.get(i))) > -1) {
+				//문자열에 포함된 ("AM", "PM", "오전", "오후" 중 1개) 삭제
+				date = date.replaceAll(TIME_TYPES.get(i), "");
+				//시간 패턴 변경 [H -> h]
+				DATE_PATTERNS.set(3, 'h');
+				break;
+			}
+		}
+		
+		//숫자를 뺀 나머지 문자열 가지고오기 ex) "2020.08.03" -> ".."
+		//숫자를 뺀 나머지 문자열 가지고오기 ex) "2020.08.03 19:20:21" -> "..::"
+		final char[] separators = getOnlyText(date).toCharArray();
+		
+	
+		
+		//사용할 최대 패턴 수
+		int maxPatterSize = 0;
+		if (DATE_PATTERNS.size() <= separators.length) {
+			maxPatterSize = DATE_PATTERNS.size();
+		} else {
+			maxPatterSize = separators.length;
+		}
+		
+		//구분자별 Index 위치's (사용할 최대 패턴 수 + 시작점:-1, 종료점:date문자열의 최종 길이)
+		List<Integer> sizeByPatterns = new ArrayList<Integer>();
+		
+		
+		//구분자 별 Index 위치 파악 후, 앞에 있는 문자열의 수 찾은 후, 추가 (마지막 패턴 뒤에 있는 문자열을 따로 처리해줘야함)
+		int fromIndex = -1;
+		for (int i = 0; i < maxPatterSize; i++) {
+			//구분자
+			char separator = separators[i];
+			
+			//'현재 찾은 위치' : 이전에 찾은 위치(찾기 시작할 위치 => fromIndex) + 1 부터 찾기 시작함
+			int currentFromIndex = date.indexOf(separator, fromIndex + 1);
+			
+			//현재 패턴의 문자열 수 = '현재 찾은 위치' - '이전에 찾은 위치' - 1 [추가]
+			sizeByPatterns.add(currentFromIndex - fromIndex - 1);			
+			
+			//'현재 찾은 위치'는 '이전에 찾은 위치'가 됨
+			fromIndex = currentFromIndex;
+		}
+		//마지막 패턴 뒤에 있는 문자열 = '문자열의 길이' - '마지막에 찾은 위치(이전에 찾은 위치)' - 1 [추가]
+		sizeByPatterns.add(date.length() - fromIndex - 1);
+		
+		
+		//패턴을 담을 변수
+		StringBuilder pattern = new StringBuilder();
+		
+		//DATE_PATTERS 순서 대로, 각 구분자 별 Index 위치 크기만큼 문자열에 패턴 삽입 + 구분자 삽입
+		//마지막 전까지만 for문 돌림
+		for (int i = 0, patternIndex = 0; i < sizeByPatterns.size() && patternIndex < DATE_PATTERNS.size(); i++, patternIndex++) {
+			
+			//패턴 추가
+			int usingSize = 0;
+			for (int j = 0; j < sizeByPatterns.get(i); j++) {
+				if (j >= usingSize + DATE_PATTERNS_MAX_LENGTH.get(patternIndex)) {
+					usingSize += DATE_PATTERNS_MAX_LENGTH.get(patternIndex++);
+					
+					/*단 한개의 패턴이라도 '최대 문자열 수'를 넘어서면 -> '날짜 아님'*/
+					if (i >= sizeByPatterns.size() || patternIndex >= DATE_PATTERNS.size()) {
+						return null;
+					}
+				}
+				
+				pattern.append(DATE_PATTERNS.get(patternIndex));
+			}
+			
+			//날짜 구분자 추가 (마지막 구분자까지만) 
+			if (i < separators.length) {
+				pattern.append(separators[i]);
+			}
+			
+			
+		}
+		
+		if (timeTypeFindIndex > -1) {
+			pattern.insert(timeTypeFindIndex, 'a');
+		}
+		
+		if(!(pattern.toString().equals("-") || pattern.toString().equals("/") || pattern.toString().equals("."))){
+			pattern = null;
+		}
+		
+		return pattern.toString();
+	}
+	
+	
+	/**
+     * @author 최정우
+     * @since 2020.01.26
+     * 
+     * ping 체크
+     */
+	public static boolean pingCheck (String ip) {
+		InetAddress inetAddress;
+		try {
+			inetAddress = InetAddress.getByName(ip);
+			return inetAddress.isReachable(1000);
+		} catch (UnknownHostException e) {
+			return false;
+		} catch (IOException e) {
+			return false;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+	
+	/**
+     * @author 김성원
+     * @since 2024.01.04
+     * 
+     * 접속 체크 (ip + port)
+     */
+	public static boolean linkCheck(String ip, int port) {
+		Socket socket = new Socket();
+		try {
+			socket.connect(new InetSocketAddress(ip, port), 1000);
+			boolean isConnect = socket.isConnected();
+			socket.close();
+			return isConnect;
+		} catch (UnknownHostException e) {
+			return false;
+		} catch (IOException e) {
+			return false;
+		} catch (Exception e) {
+			return false;
+		}
+	}	
+	
+	
+	/**
+	 * @author 최정우
+	 * @since 2019.12.09
+	 * 
+	 * 데이터 셋 목록 Convert LinkedHashMap<String, Object> to List<String>
+	 */
+	public static List<List<Object>> rowDataMapToList (List<LinkedHashMap<String, Object>> rowMapData) throws Exception {
+		List<List<Object>> rowData = new ArrayList<List<Object>>();
+		for (int i = 0; i < rowMapData.size(); i++) {
+			List<Object> row = new ArrayList<Object>();
+			LinkedHashMap<String, Object> mapdata = rowMapData.get(i);
+	        for( String key : mapdata.keySet() ){
+	        	if (mapdata.get(key) == null) {
+	        		row.add(null);//null값 대체  
+	        	} else {
+	        		row.add(mapdata.get(key).toString());
+	        	}
+	        }
+	        rowData.add(row);
+		}
+		return rowData;
+	}
+	
+	/**
+	 * @author 최정우
+	 * @since 2020.01.26
+	 *
+	 * 현재 client의 HttpServletRequest 조회
+	 */
+	public static HttpServletRequest getHttpServletRequest () {
+		try {
+			ServletRequestAttributes servletRequestAttribute = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
+			return servletRequestAttribute.getRequest();
+		} catch (NullPointerException e) {
+			return null;
+		}
+	}
+	
+	
+	/**
+	 * @author 최정우
+	 * @since 2020.01.26
+	 *
+	 * 현재 client의 HttpSession 조회
+	 */
+	public static HttpSession getHttpSession (boolean create) {
+		try {
+			HttpServletRequest request = getHttpServletRequest();
+			if (request != null) {
+				return request.getSession(create);
+			} else {
+				return null;
+			}
+		} catch (NullPointerException e) {
+			return null;
+		}
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.10
+	 *
+	 * 사용자 세션 정보 조회
+	 */
+	public static HashMap<String, Object> getHttpSessionMember () {
+		try {
+			HttpServletRequest request = getHttpServletRequest();
+			if(request.getSession().getAttribute(AuthUtil.LOGIN_USER_SESSION) != null) {				
+				return (HashMap<String, Object>)request.getSession().getAttribute(AuthUtil.LOGIN_USER_SESSION);	
+			}else {
+				return null;
+			}	
+		} catch (NullPointerException e) {
+			return null;
+		}
+	}
+	
+	/**
+	 * @author 최정우
+	 * @since 2020.01.26
+	 *
+	 * HttpServletRequest를 활용한 Client IP 가지고오기
+	 * Header의 X-FORWARDED-FOR 값을 통해 IP 조회, 만약 Header에 X-FORWARDED-FOR가 없으면 getRemoteAddr() 이걸로 조회
+	 */
+	public static String getClientIp () {
+		try {
+			HttpServletRequest request = getHttpServletRequest();
+			if (null != request.getHeader("X-FORWARDED-FOR")) {
+				return request.getHeader("X-FORWARDED-FOR");
+			} else {
+				return request.getRemoteAddr();
+			}
+		} catch (NullPointerException e) {
+			return null;
+		}
+	}
+	
+
+	
+	/**
+	 * @author 최정우
+	 * @since 2019.12.09
+	 * 
+	 * JSONObject to Map<String, Object>
+	 */
+	public static Map<String, Object> jsonObjectToMap( JSONObject jsonObj ) {
+        Map<String, Object> map = null;
+        try {
+            map = new ObjectMapper().readValue(jsonObj.toJSONString(), Map.class) ;
+            	
+        } catch (JsonParseException e) {
+            e.printStackTrace();
+        } catch (JsonMappingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return map;
+    }
+	
+	/**
+	 * @author 최정우
+	 * @since 2019.12.09
+	 * 
+	 * JSONObject to List<Map<String, Object>>
+	 */
+	public static List<Map<String, Object>> jsonArrayToMap( JSONArray jsonObj ) {
+		List<Map<String, Object>> map = null;
+        try {
+            map = new ObjectMapper().readValue(jsonObj.toJSONString(), new TypeReference<List<Map<String, Object>>>(){}) ;
+            	
+        } catch (JsonParseException e) {
+            e.printStackTrace();
+        } catch (JsonMappingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return map;
+    }
+	
+	/**
+	 * @author 최정우
+	 * @since 2019.12.09
+	 * 
+	 * xmlStr to JsonStr
+	 */
+	public static String xmlStrToJsonStr(String xmlStr) throws Exception {
+ 	    org.json.JSONObject jObject = XML.toJSONObject(xmlStr);
+ 	    ObjectMapper mapper = new ObjectMapper();
+ 	    mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ 	    Object json = mapper.readValue(jObject.toString(), Object.class);
+ 	    String output = mapper.writeValueAsString(json);
+ 	    return output;
+	}
+	
+	
+	
+	/**
+     * @author 김성원 
+	 * @since 2024.01.10
+     * 
+     * 데이터베이스 난수생성
+     */
+	public static String getRandKey(String prifix) {
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+		long timeInMillis =System.currentTimeMillis();
+		Date timeInDate = new Date(timeInMillis);		
+		return prifix+"_"+sdf.format(timeInDate)+UUID.randomUUID().toString().substring(0,5);
+	}
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/util/CryptoUtil.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/util/CryptoUtil.java
@@ -0,0 +1,221 @@
+package com.takensoft.taken_bi_manager.common.util;
+
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Base64.Decoder;
+import java.util.Base64.Encoder;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.encrypt.AesBytesEncryptor;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+/**
+ * @author 김성원
+ * @since 2024.01.02
+ * 
+ * 암호화 관련 클래스 
+ */
+public class CryptoUtil {
+	
+
+	private final static String encoderKey = "bcrypt";
+	private final static String secret = "takenbmsc!@#";
+	private final static String salt = "70726574657374";
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 기본 단방향 엔코드 생성
+	 */
+	public static PasswordEncoder createDelegatingPasswordEncoder() {	
+		Map<String, PasswordEncoder> encoders = new HashMap<>();
+		encoders.put(encoderKey, new BCryptPasswordEncoder());	
+		return new DelegatingPasswordEncoder(encoderKey, encoders);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커스텀 key기반의  단방향 엔코드 생성
+	 */
+	public static PasswordEncoder createDelegatingPasswordEncoder(String key) {	
+		Map<String, PasswordEncoder> encoders = new HashMap<>();
+		encoders.put(key, new BCryptPasswordEncoder());	
+		return new DelegatingPasswordEncoder(key, encoders);
+	}
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 기본 단방향 암호화 
+	 */
+	public static String PasswordEncoder(String data) {	
+		
+		PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
+		Encoder encoder = Base64.getEncoder();       
+		return  encoder.encodeToString(passwordEncoder.encode(data).getBytes(StandardCharsets.UTF_8)) ;
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커스텀 key기반의  단방향 암호화 
+	 */
+	public static String PasswordEncoder(String key , String data) {	
+		
+		if(StringUtil.isEmpty(data)) {
+			return data;
+		}
+		
+		PasswordEncoder passwordEncoder = createDelegatingPasswordEncoder(key);
+		
+		return passwordEncoder.encode(data);
+	}
+		
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 단방향 암호화 비교구문 
+	 */
+	public static boolean passwordMatch(String data, String checkData) {
+		
+		PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
+		Decoder decoder = Base64.getDecoder();		
+		return passwordEncoder.matches(data,new String(decoder.decode(checkData), StandardCharsets.UTF_8) );
+		
+	}
+	
+
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 기본 key, salt 기반의 양방향 암호화 객체 생성  
+	 */
+	public static AesBytesEncryptor aesBytesEncryptor() {
+	    return new AesBytesEncryptor("232323", salt);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커스텀 key, salt 기반의 양방향 암호화 객체 생성  
+	 */
+	public static AesBytesEncryptor aesBytesEncryptor(String key, String salt) {
+	    return new AesBytesEncryptor(key, salt);
+	    
+	}	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 기본 key, salt 기반의 양방향 암호화 
+	 */
+	public static String encryptData(String data) {
+		if(StringUtil.isEmpty(data)) {
+			return data;
+		}
+		AesBytesEncryptor  bytesEncryptor =  aesBytesEncryptor();
+        byte[] encrypt = bytesEncryptor.encrypt(data.getBytes(StandardCharsets.UTF_8));
+        Encoder encoder = Base64.getEncoder();       
+        return encoder.encodeToString(encrypt); 
+    }
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커스텀  key, salt 기반의 양방향 암호화 
+	 */
+	public static String encryptData(String key, String salt, String data) {
+		if(StringUtil.isEmpty(data)) {
+			return data;
+		}
+		AesBytesEncryptor  bytesEncryptor =  aesBytesEncryptor(key, salt);
+        byte[] encrypt = bytesEncryptor.encrypt(data.getBytes(StandardCharsets.UTF_8));
+        Encoder encoder = Base64.getEncoder();       
+        return encoder.encodeToString(encrypt); 
+    }
+	
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 기본 key, salt 기반의 양방향 복호화
+	 */
+	public static String decryptData(String data) {
+		if(StringUtil.isEmpty(data)) {
+			return data;
+		}
+		AesBytesEncryptor  bytesEncryptor =  aesBytesEncryptor();
+		Decoder decoder = Base64.getDecoder();		
+        byte[] decrypt = bytesEncryptor.decrypt(decoder.decode(data));
+        return new String(decrypt, StandardCharsets.UTF_8);
+    }	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 커스텀 key, salt 기반의 양방향 복호화
+	 */
+	public static String decryptData(String key, String salt, String data) {
+		if(StringUtil.isEmpty(data)) {
+			return data;
+		}
+		AesBytesEncryptor  bytesEncryptor =  aesBytesEncryptor(key, salt);
+		Decoder decoder = Base64.getDecoder();		
+        byte[] decrypt = bytesEncryptor.decrypt(decoder.decode(data));
+        return new String(decrypt, StandardCharsets.UTF_8);
+    }	
+	
+	 
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 	* 바이트 스트링 변환
+	*/
+	public static String byteArrayToString(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (byte abyte :bytes){
+            sb.append(abyte);
+            sb.append(" ");
+        }
+        return sb.toString();
+    }
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 스트링 바이트 변환
+	*/
+	public static byte[] stringToByteArray(String byteString) {
+        String[] split = byteString.split("\\s");
+        ByteBuffer buffer = ByteBuffer.allocate(split.length);
+        for (String s : split) {
+            buffer.put((byte) Integer.parseInt(s));
+        }
+        return buffer.array();
+    }
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/util/HTTPUtil.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/util/HTTPUtil.java
@@ -0,0 +1,145 @@
+package com.takensoft.taken_bi_manager.common.util;
+
+
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.List;
+import java.util.Map;
+
+import com.takensoft.taken_bi_manager.common.connection.api.vo.ApiParam;
+
+
+/**
+ * @author 김성원
+ * @since 2024.01.12
+ * 
+ * 데이터 수집 - HTTP통신 관련 Util 입니다. 
+ */
+public class HTTPUtil {
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.12
+	 * 
+	 * [GET] HTTP 통신
+	 */
+	public synchronized String HttpConnectionApi (String urlText, int type,  List<ApiParam>  parameter) {
+		StringBuffer response = new StringBuffer();
+		
+		URL url = null;
+		try {
+			if (parameter.isEmpty() == false) {
+				urlText += "?" + createUrlQueryApi(parameter, "UTF-8"); 
+			}	
+			url = new URL(urlText);
+		} catch (MalformedURLException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		
+		HttpURLConnection httpCon = null;
+		try {
+			
+			/* Connection */
+			httpCon = (HttpURLConnection) url.openConnection();
+			if(type == 1) {
+				httpCon.setRequestMethod("POST");
+			}else {
+				httpCon.setRequestMethod("GET");
+			}
+			
+			httpCon.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36");
+			httpCon.setConnectTimeout(1000 * 60);//http통신 최대 커넥션 시간(1분)
+			httpCon.setReadTimeout(1000 * 60);//http통신 커넥션 이후, 데이터를 받아오는데 걸리는 최대 시간(1분)
+			httpCon.setDoInput(true);//받아올 데이터가 있을 때, 사용
+			
+			//HTTP Request 결과 코드
+			int responseCode = httpCon.getResponseCode();
+			if (responseCode == 200) {
+				//Response 결과 데이터 받기
+				BufferedReader input = new BufferedReader(new InputStreamReader(httpCon.getInputStream(), "UTF-8"));
+				
+				//Response 결과 데이터를 문자열로 만들기
+				String result = null;
+				while ((result = input.readLine()) != null) {
+					response.append(result);
+				}
+				
+				//InputStream, BufferedReader 종료
+				input.close();
+				
+				//HTTP Connection 종료
+				httpCon.disconnect();
+				
+			} else {
+				System.out.println("[HTTP]" + url + "(" + responseCode + " 에러)");
+			}
+			
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		
+		//문자열로된 Response 결과 return
+		return response.toString();
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.12
+	 * 
+	 * 파라메터 데이터를 HTTP통신을 위한 문자열로 변환시켜주는 메서드
+	 * Map -> String
+	 */
+	public String createUrlQueryApi (List<ApiParam> parameter, String incoding) {
+		if (parameter.isEmpty() == true) {
+			return "";
+		} else {
+			
+		
+			StringBuilder query = new StringBuilder();
+		    for(ApiParam param : parameter) {		   
+		        try {
+		        	
+		        	// 날짜 변경 처리 
+		        	if(param.isDateForm() == true) {		        		
+		        			param.setValue(StringUtil.getTodayaddDate(param.getValue().toString(),param.getDateType(), param.getAddDate()));
+		        		        		
+		        	}		        
+		        	
+		        	if(query.length() > 0) {
+		        		query.append('&');
+		        	}
+		        	
+		        	if (StringUtil.isEmpty(incoding) == true) {
+		        		query.append(param.getKey());
+			        	query.append('=');
+			        	query.append(param.getValue());
+		        	} else {
+		        		query.append(URLEncoder.encode(param.getKey(), incoding));
+			        	query.append('=');
+			        	if(param.isDisableDecode()) {
+			        		query.append(param.getValue());
+			        	}else {
+			        		query.append(URLEncoder.encode(String.valueOf(param.getValue()), incoding));
+			        	}			        
+		        	}		        	
+		        
+				} catch (UnsupportedEncodingException e) {
+					e.printStackTrace();
+				}
+		    }
+		    
+		    return query.toString();
+		}
+	}
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/util/SesssionEventListener.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/util/SesssionEventListener.java
@@ -0,0 +1,293 @@
+package com.takensoft.taken_bi_manager.common.util;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.annotation.WebListener;
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.HttpSessionEvent;
+import jakarta.servlet.http.HttpSessionListener;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author 서영석
+ * @since 2023.05.31
+ *
+ * Custom session 저장소를 만들어 놓고
+ * Tomcat이 관리하는 session 생성 또는 소멸시, 발생하는 이벤트를 활용하여 (HttpSessionListener를 통해 이벤트를 받을 수 있음)
+ * Custom session 저장소에 추가, 삭제를 통해
+ * session을 적절히 controll 하기위한 목적을 가진 Class 입니다.
+ */
+@WebListener
+public class SesssionEventListener implements HttpSessionListener {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SesssionEventListener.class);
+
+    //싱글턴패턴 사용을 위한 클래스변수
+    public static SesssionEventListener sesssionEventListener = null;
+
+    //싱글턴패턴으로 객체 생성 후 리턴.
+    public static synchronized SesssionEventListener getInstance() {
+        if(sesssionEventListener == null) {
+            sesssionEventListener = new SesssionEventListener();
+        }
+        return sesssionEventListener;
+    }
+
+    /**
+     * Custom session 저장소 (tomcat이 관리하고있는 실제 session저장소는 아님) 목록
+     * ConcurrentHashMap을 사용하는 이유 :
+     * HashMap은 Thread Safe 하지 않기 때문에 싱글턴 패턴에서 해당 session 저장소를 사용하기 위해서는 Thread Safe 한 ConcurrentHashMap를 사용
+     * HashTable도 Thread Safe 하지만, 읽기 쓰기 둘다 한개의 Thread만 접근 가능함
+     * ConcurrentHashMap은 쓰기에서한 한개의 Tread만 접근 가능하도록 해놓음 (읽기는 여러개의 쓰레드에서 동시 접근 가능)
+     */
+    private static final Map<String, HttpSession> sessions = new ConcurrentHashMap<>();
+
+    /**
+     * @author 서영석
+     * @since 2023.05.31
+     *
+     * @param userId : 사용자(회원) ID
+     *
+     * userId와 동일한 로그인 session을 가진 session ID 목록 조회
+     */
+    public synchronized static List<String> duplicationLoginSessionIdSelectListByUserId (String userId) {
+        List<String> result = new ArrayList<>();
+        try {
+            //Custom session 저장소에서 session ID는 다르지만 userId가 같은게 존재하는지 확인
+            for (String key : sessions.keySet()) {
+                HttpSession session = sessions.get(key);
+                if (session == null || session.getAttribute(AuthUtil.LOGIN_USER_SESSION) == null) {
+                    //세션이 존재하고, 로그인 정보가 없으면 continue;
+                    continue;
+                } else {
+                    //로그인 정보가 있으면 -> 중복 확인
+                    HashMap<String, Object> loginUser = (HashMap<String, Object>) session.getAttribute(AuthUtil.LOGIN_USER_SESSION);
+                    String loginUserId = (String) loginUser.get("user_id");
+
+                    /** 사용자(회원) ID와 동일한 로그인 정보 일 시 -> add **/
+                    if (userId.equals(loginUserId) == true) {
+                        result.add(session.getId());
+                    } else {
+                        //동일한 로그인 정보가 아니면 -> continue;
+                        continue;
+                    }
+                }
+            }
+        } catch (NullPointerException e) {
+            LOGGER.error(e.toString());
+        }
+
+        return result;
+    }
+
+
+    /**
+     * @author 서영석
+     * @since 2023.05.31
+     *
+     * 현재 client의 정보와 중복된 로그인 session ID 목록 조회
+     *
+     * 현재 User의 세션과 Custom session 저장소에 저장된 session 중
+     * session ID는 다르지만 userId가 같은 session List return
+     */
+    public synchronized static List<String> duplicationLoginSessionIdSelectList () {
+        List<String> result = new ArrayList<>();
+
+        try {
+            //현재 사용자의 session
+            HttpSession currentUserSession = CommonUtil.getHttpSession(false);
+            //현재 사용자의 session이 존재하고, 로그인 정보가 있을 때
+            if (currentUserSession != null && currentUserSession.getAttribute(AuthUtil.LOGIN_USER_SESSION) == null) {
+                //현재 사용자의 로그인 정보
+                HashMap<String, Object> currentLoginUser = (HashMap<String, Object>) currentUserSession.getAttribute(AuthUtil.LOGIN_USER_SESSION);
+                String currentLoginUserId = (String) currentLoginUser.get("user_id");
+
+                //Custom session 저장소에서 session ID는 다르지만 userId가 같은게 존재하는지 확인
+                for (String key : sessions.keySet()) {
+                    HttpSession session = sessions.get(key);
+                    if (session == null || session.getAttribute(AuthUtil.LOGIN_USER_SESSION) == null) {
+                        //세션이 존재하고, 로그인 정보가 없으면 continue;
+                        continue;
+                    } else if (currentUserSession.getId().equals(session.getId()) == true) {
+                        //동일한 세션 ID이면 continue;
+                        continue;
+                    } else {
+                        //로그인 정보가 있으면 -> 중복 확인
+                        HashMap<String, Object> duplicationLoginUser = (HashMap<String, Object>) session.getAttribute(AuthUtil.LOGIN_USER_SESSION);
+                        String duplicationLoginUserId = (String) duplicationLoginUser.get("user_id");
+
+                        /** 동일한 로그인 정보 일 시 -> add **/
+                        if (currentLoginUserId.equals(duplicationLoginUserId) == true) {
+                            result.add(session.getId());
+                        } else {
+                            //동일한 로그인 정보가 아니면 -> continue;
+                            continue;
+                        }
+                    }
+                }
+            }
+        } catch (NullPointerException e) {
+            LOGGER.error(e.toString());
+        }
+
+        return result;
+    }
+
+    /**
+     * @author 서영석
+     * @since 2023.05.31
+     *
+     * @param userId : 사용자(회원) ID
+     *
+     * userId와 동일한 로그인 session을 가진 session ID 목록 삭제
+     */
+    public static int duplicationLoginSessionDeleteByUserId (String userId) {
+        int result = 0;
+        try {
+            List<String> sessionIds = duplicationLoginSessionIdSelectListByUserId(userId);
+            for (int i = 0; i < sessionIds.size(); i++) {
+                //Custom session 저장소에서 session 무효화 시키기
+                sessions.get(sessionIds.get(i)).invalidate();
+                //Custom session 저장소에서 session 삭제
+                sessions.remove(sessionIds.get(i));
+            }
+        } catch (NullPointerException e) {
+            LOGGER.error(e.toString());
+        }
+        return result;
+    }
+
+    /**
+     * @author 서영석
+     * @since 2023.05.31
+     *
+     * 현재 client의 정보와 중복된 로그인 session 전부 무효화 시키기 (완전 삭제는 못시킴)
+     */
+    public static int duplicationLoginSessionDeleteAll () {
+        int result = 0;
+        try {
+            List<String> sessionIds = duplicationLoginSessionIdSelectList();
+            for (int i = 0; i < sessionIds.size(); i++) {
+                //Custom session 저장소에서 session 무효화 시키기
+                sessions.get(sessionIds.get(i)).invalidate();
+                //Custom session 저장소에서 session 삭제
+                sessions.remove(sessionIds.get(i));
+            }
+        } catch (NullPointerException e) {
+            LOGGER.error(e.toString());
+        }
+        return result;
+    }
+
+    //난수생성
+    public static String generateRandomHex(int length) {
+        SecureRandom random = new SecureRandom();
+        byte[] randomBytes = new byte[length / 2]; // 16진수 문자열의 길이에 맞게 바이트 배열 크기를 조절
+
+        random.nextBytes(randomBytes);
+
+        // 바이트 배열을 16진수 문자열로 변환
+        StringBuilder hexStringBuilder = new StringBuilder();
+        for (byte b : randomBytes) {
+            hexStringBuilder.append(String.format("%02x", b));
+        }
+
+        return hexStringBuilder.toString();
+    }
+
+    /**
+     * HttpSessionListener Interface로 부터 상속 받은 메소드
+     *
+     * tomcat에서 session이 생성되었을 때(session timeout), 발생하는 이벤트
+     * @param target : session 이벤트(생성) 객체
+     *
+     * session 생성 이벤트가 발생하면 Custom session 저장소(sessions)에 해당 session ID 값을 Key로 잡고 저장
+     * (※ Default로 session에 현재 Client의 IP를 넣어줌)
+     */
+    @Override
+    public void sessionCreated(HttpSessionEvent target) {
+        //System.out.println("sessionCreated - 현재 세션 개수 : " + sessions.size() + "개");
+        int i = 1;
+        for (String key : sessions.keySet()) {
+            HttpSession hs = sessions.get(key);
+            //System.out.println("sessionCreated - 세션 목록 " + (i++) + ". " + hs.getId());
+        }
+//        System.out.println("sessionCreated - 이제 추가될 session id : " +  target.getSession().getId());
+        //System.out.println("");
+        //System.out.println("");
+
+        // session에 key(salt) 값 넣기 시작
+        HashMap<String, Object> key = new HashMap<String, Object>();
+
+        // "SHA1PRNG"은 알고리즘 이름
+//        SecureRandom random = null;
+//        try {
+//            random = SecureRandom.getInstance("SHA1PRNG");
+//        } catch (NoSuchAlgorithmException e) {
+//            e.printStackTrace();
+//        }
+//        SecureRandom random = new SecureRandom();
+//
+//        byte[] saltBytes  = new byte[24];
+//        byte[] encKeyBytes = new byte[24];
+//        byte[] ivBytes = new byte[24];
+//        random.nextBytes(saltBytes);
+//        random.nextBytes(encKeyBytes);
+//        random.nextBytes(ivBytes);
+        //SALT 생성
+//        String salt = Base64.getEncoder().encodeToString(saltBytes);
+//        String ENC_KEY = Base64.getEncoder().encodeToString(encKeyBytes);
+//        String iv = Base64.getEncoder().encodeToString(ivBytes);
+        String salt = generateRandomHex(32);
+        String ENC_KEY = generateRandomHex(32);
+        String iv = generateRandomHex(32);
+        key.put("salt",salt);
+        key.put("ENC_KEY",ENC_KEY);
+        key.put("iv",iv);
+
+        target.getSession().setAttribute("key", key);
+
+//        System.out.println("key : "+key);
+        //종료
+
+
+        //현재 Client의 IP set
+        target.getSession().setAttribute("ip", CommonUtil.getClientIp());
+//        target.getSession().setAttribute("key",);
+//        System.out.println("target test1: "+target);
+//        System.out.println("target.getSession() test1: "+target.getSession());
+//        System.out.println("sessions test1: "+sessions);
+//        System.out.println("sessions test2: "+sessions.get(target.getSession().getId()));
+//        System.out.println("CommonUtil.getClientIp() test: "+CommonUtil.getClientIp());
+//        System.out.println("target.getSession() test: "+target.getSession());
+
+        //세션 저장소에 set
+        sessions.put(target.getSession().getId(), target.getSession());
+    }
+
+    /**
+     * HttpSessionListener Interface로 부터 상속 받은 메소드
+     *
+     * tomcat에서 session이 소멸되었을 때, 발생하는 이벤트
+     * @param target : session 이벤트(소멸) 객체
+     *
+     * session 제거 이벤트가 발생하면 Custom session 저장소(sessions)에 해당 session ID 값을 가지고 있는 session 무효화 및 제거
+     */
+    @Override
+    public void sessionDestroyed(HttpSessionEvent target) {
+        //소멸된 세션 Custom session 저장소에서 가지고 오기
+        if (sessions.get(target.getSession().getId()) != null) {
+            //소멸된 세션 무효화 시키기 (가능한지 모르겠지만, 일단 작성해봄)
+            sessions.get(target.getSession().getId()).invalidate();
+            //Custom session 저장소에서 해당 session 삭제
+            sessions.remove(target.getSession().getId());
+        } else {
+            return;
+        }
+    }
+}(No newline at end of file)
 
src/main/java/com/takensoft/taken_bi_manager/common/util/StringUtil.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/util/StringUtil.java
@@ -0,0 +1,713 @@
+package com.takensoft.taken_bi_manager.common.util;
+
+
+
+import java.io.UnsupportedEncodingException;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.Random;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.servlet.server.Encoding.Type;
+
+
+/**
+ * @author 최정우
+ * @since 2019.11.13
+ * 
+ * 문자열과 관련된 기능을 정의 해놓은 Util입니다.
+ */
+public class StringUtil {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(StringUtil.class);
+	
+	public static final String NULL_TEXT = "NULL";
+	
+	public static String toString(Object obj) {
+		if (obj == null) {
+			return null;
+		} else {
+			try {
+				return obj.toString();
+			} catch (Exception e) {
+				return null;
+			}
+		}
+	}
+	
+	public static String toStringNotNull(Object obj) {
+		if (obj == null) {
+			return "";
+		} else {
+			try {
+				return obj.toString();
+			} catch (Exception e) {
+				return "";
+			}
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2020.11.26
+     * 
+     * 객체를 문자열로 바꾼 후, 문자열 길이 반환
+     */
+	public static int stringLength(Object obj) {
+		if (obj == null) {
+			return 0;
+		} else {
+			try {
+				return obj.toString().length();
+			} catch (Exception e) {
+				return 0;
+			}
+		}
+	}
+	
+	/**
+     * @author 최정우
+     * @since 2020.11.26
+     * 
+     * 문자열이 Null or null or NULL인 경우 실제 null값 세팅 
+     */
+	public static boolean isNullText(String text) {
+		if (isEmpty(text) == false && text.toUpperCase().equals(NULL_TEXT)) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+	
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 빈 문자열 검사
+     */
+    public static boolean isEmpty(String text) {
+        return text == null || text.trim().length() == 0;
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * indexOf - 문자 검색 후, 해당 문자의 위치(index)반환
+     */
+    public static int indexOf(String text, String searchText) {
+        if (text == null || searchText == null) {
+            return -1;
+        }
+        return text.indexOf(searchText);
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * lastIndexOf - 문자 검색 후, 해당 문자의 위치(index)반환
+     */
+    public static int lastIndexOf(String text, String searchText) {
+    	if (text == null || searchText == null) {
+            return -1;
+        }
+        return text.lastIndexOf(searchText);
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * substringBetween - 특정 문자열 사이에 값을 뽑아내는 메서드
+     */
+    public static String substringBetween(String text, String startText, String endText) {
+		if (isEmpty(text) == true || isEmpty(startText) == true || isEmpty(endText) == true) {
+			return null;
+		}
+		text = text.toLowerCase();
+		startText = startText.toLowerCase();
+		endText = endText.toLowerCase();
+		
+		int start = text.indexOf(startText);
+		if (start != -1) {
+			int end = text.indexOf(endText, start + startText.length());
+			if (end != -1) {
+				return text.substring(start + startText.length(), end);
+			}
+		}
+		return null;
+	}
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 모든 공백 제거
+     */
+    public static String removeSpace(String text) {
+        if (isEmpty(text)) {
+            return text;
+        }
+        int length = text.length();
+        char[] newCharList = new char[length];
+        int count = 0;
+        for (int i = 0; i < length; i++) {
+            if (Character.isWhitespace(text.charAt(i)) == false) {
+            	newCharList[count++] = text.charAt(i);
+            }
+        }
+        if (count == length) {
+            return text;
+        }
+
+        return new String(newCharList, 0, count);
+    }
+    
+	 
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 소문자 변환
+     */
+    public static String lowerCase(String text) {
+        if (isEmpty(text) == true) {
+            return text;
+        } else {
+        	return text.toLowerCase();
+        }
+    }
+
+    /**
+     * 대문자 변환
+     */
+    public static String upperCase(String text) {
+    	if (isEmpty(text) == true) {
+            return text;
+        } else {
+        	return text.toUpperCase();
+        }
+    }
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 현재날짜(년,월,일)를 구하는 기능
+     */
+    public static String getToday() {
+		String pattern = "yyyy-MM-dd";
+		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
+		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
+		return dateFormat.format(timestamp.getTime());
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 현재날짜(년,월,일)를 구하는 기능
+     */
+    public static String getToday(String pattern) {
+    	String defaultPattern = "yyyy-MM-dd";
+    	if (isEmpty(pattern) == true) {
+    		pattern = defaultPattern;
+    	}
+    	
+    	SimpleDateFormat dateFormat = null;
+		try {
+			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
+		} catch (Exception e) {
+			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
+		}
+		Timestamp timestamp = new Timestamp(System.currentTimeMillis());		
+		return dateFormat.format(timestamp.getTime());
+    }
+    
+    
+    /**
+     * @author 김성원
+     * @since 2019.11.13
+     * 
+     * 현재날짜(년,월,일)에 특정 날짜 + -
+     */
+    public static String getTodayaddDate(String pattern, String type,  int date) {
+    	String defaultPattern = "yyyy-MM-dd";
+    	if (isEmpty(pattern) == true) {
+    		pattern = defaultPattern;
+    	}
+    	
+    	SimpleDateFormat dateFormat = null;
+		try {
+			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
+		} catch (Exception e) {
+			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
+		}
+		
+		Timestamp timestamp = new Timestamp(System.currentTimeMillis());		
+		Calendar cal = Calendar.getInstance();
+		if(type.equals("year")) {
+			cal.add(Calendar.YEAR, date);
+		}else if(type.equals("month")) {
+			cal.add(Calendar.MONTH, date);
+		}else if(type.equals("day")) {
+			cal.add(Calendar.DATE, date);
+		}		
+		
+		return dateFormat.format(cal.getTime());
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 현재날짜(년,월,일)를 구하는 기능
+     */
+    public static String getToday(String yearSuffix, String monthSuffix, String daySuffix) {
+    	String defaultPattern = "yyyy년MM월dd일";
+    	if (isEmpty(yearSuffix) == true) {
+    		yearSuffix = "";
+    	}
+    	if (isEmpty(monthSuffix) == true) {
+    		monthSuffix = "";
+    	}
+    	if (isEmpty(daySuffix) == true) {
+    		daySuffix = "";
+    	}
+    	
+    	String pattern = "yyyy" + yearSuffix + "MM" + monthSuffix + "dd" + daySuffix;
+    	
+    	SimpleDateFormat dateFormat = null;
+		try {
+			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
+		} catch (Exception e) {
+			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
+		}
+		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
+		return dateFormat.format(timestamp.getTime());
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 17자리의 현재일시를 구하는 기능
+     */
+    public static String getDateTime() {
+		// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
+		String pattern = "yyyyMMddHHmmssSSS";
+		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
+		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
+		return dateFormat.format(timestamp.getTime());
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 원하는 패턴의 현재일시 구하는 기능
+     */
+    public static String getDateTime(String pattern) {
+    	// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
+    	String defaultPattern = "yyyyMMddHHmmssSSS";
+    	if (isEmpty(pattern)) {
+    		pattern = defaultPattern;
+    	}
+		SimpleDateFormat dateFormat = null;
+		try {
+			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
+		} catch (Exception e) {
+			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
+		}
+		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
+		return dateFormat.format(timestamp.getTime());
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 현재 일시 - addDay => 원하는 패턴의 일시를 구하는 기능 
+     */
+    public static String getDateTime(String pattern, int addDay) {
+    	// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
+    	String defaultPattern = "yyyyMMddHHmmssSSS";	
+    	if (pattern == null) {
+    		pattern = defaultPattern;
+    	}
+		SimpleDateFormat dateFormat = null;
+		try {
+			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
+		} catch (Exception e) {
+			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
+		}
+		Calendar cal = new GregorianCalendar();
+		cal.add(Calendar.DATE, addDay);
+		Date date = cal.getTime();
+		return dateFormat.format(date.getTime());
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 현재 일시 - addDay => 원하는 패턴의 일시를 구하는 기능 
+     */
+    public static String getDateTime(String pattern, int addDay, int addHour, int addMin, int addSec) {
+    	// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
+    	String defaultPattern = "yyyyMMddHHmmssSSS";	
+    	if (pattern == null) {
+    		pattern = defaultPattern;
+    	}
+		SimpleDateFormat dateFormat = null;
+		try {
+			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
+		} catch (Exception e) {
+			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
+		}
+		Calendar cal = new GregorianCalendar();
+		cal.add(Calendar.DATE, addDay);
+		cal.add(Calendar.HOUR, addHour);
+		cal.add(Calendar.MINUTE, addMin);
+		cal.add(Calendar.SECOND, addSec);
+		Date date = cal.getTime();
+		return dateFormat.format(date.getTime());
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 현재 일시(17자리)와, 랜덤숫자(4자리)를 이용하여 키값 생성
+     */
+    public static String getCreateKey (String prefix) {
+		int random = new Random().nextInt(9999);
+		String result = prefix + "_" + getDateTime() + "_" + numberToText(random, 4);
+		return result;
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열이 Date문자열(yyyy-MM-dd)로 포맷 가능한지
+     * text: 문자열
+     * pattern: 문자열의 날짜 패턴
+     */
+    public static boolean isDate(String text, String pattern) {
+    	try {
+    		Date date = new SimpleDateFormat(pattern).parse(text);
+    		text = new SimpleDateFormat("yyyy-MM-dd").format(date);
+        	return true;
+    	} catch (java.text.ParseException e) {
+			// TODO Auto-generated catch block
+			return false;
+		}
+    }
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열을 날짜형태로 Convert
+     * text: 문자열
+     * pattern: 문자열의 날짜 패턴
+     * newPattern: 해당 문자열을 Converting할 날짜 패턴 
+     */
+    public static String textToDateText (String text, String pattern, String newPattern) {
+		String defaultPattern = "yyyy-MM-dd";
+		if (isEmpty(newPattern) == true) {
+			newPattern = defaultPattern;
+    	}
+		
+		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
+		Date date = new Date();
+		try {
+			date = dateFormat.parse(text);
+			dateFormat.applyPattern(newPattern);
+			return dateFormat.format(date);
+        } catch (Exception e) {
+            //e.printStackTrace();
+            return text;
+        }
+	}
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 숫자 -> 문자열 -> 문자열 길이가 length보다 작을 때, length길이 만큼될 수 있도록 앞에 '0'을 붙여줌
+     */
+    public static String numberToText (int number, int length) {
+    	String text = Integer.toString(number);
+    	if (text.length() < length) {
+            int emptyLength = length - text.length();
+            for (int i = 0; i < emptyLength; i++) {
+            	text = "0" + text;
+            }
+        }
+        return text;
+    }
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열이 지정한 길이를 초과했을때 해당 문자열을 삭제하는 메서드
+     * @param text 원본 문자열 배열
+     * @param maxLength 지정길이
+     * @return 지정길이로 자른 문자열
+     */
+    public static String cutString(String text, int maxLength) {
+        String result = null;
+        if (text != null) {
+            if (text.length() > maxLength) {
+                result = text.substring(0, maxLength);
+            } else
+                result = text;
+        }
+        return result;
+    }
+	
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열이 지정한 길이를 초과했을때 지정한길이에다가 해당 문자열을 붙여주는 메서드.
+     * @param text 원본 문자열 배열
+     * @param addText 더할문자열
+     * @param maxLength 지정길이
+     * @return 지정길이로 잘라서 더할분자열 합친 문자열
+     */
+    public static String cutString(String text, String addText, int maxLength) {
+        String result = null;
+        if (text != null) {
+            if (text.length() > maxLength) {
+            	result = text.substring(0, maxLength) + addText;
+            } else
+            	result = text;
+        }
+        return result;
+    }
+
+    
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * <p>기준 문자열에 포함된 모든 대상 문자(char)를 제거한다.</p>
+     *
+     * <pre>
+     * StringUtil.remove(null, *)       = null
+     * StringUtil.remove("", *)         = ""
+     * StringUtil.remove("queued", 'u') = "qeed"
+     * StringUtil.remove("queued", 'z') = "queued"
+     * </pre>
+     *
+     * @param str  입력받는 기준 문자열
+     * @param remove  입력받는 문자열에서 제거할 대상 문자열
+     * @return 제거대상 문자열이 제거된 입력문자열. 입력문자열이 null인 경우 출력문자열은 null
+     */
+    public static String remove(String text, char remove) {
+        if (isEmpty(text) || text.indexOf(remove) == -1) {
+            return text;
+        }
+        char[] chars = text.toCharArray();
+        int pos = 0;
+        for (int i = 0; i < chars.length; i++) {
+            if (chars[i] != remove) {
+                chars[pos++] = chars[i];
+            }
+        }
+        
+        return new String(chars, 0, pos);
+    }
+
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 원본 문자열의 포함된 특정 문자열을 새로운 문자열로 변환하는 메서드
+     * @param source 원본 문자열
+     * @param subject 원본 문자열에 포함된 특정 문자열
+     * @param object 변환할 문자열
+     * @return sb.toString() 새로운 문자열로 변환된 문자열
+     */
+    public static String replace(String text, String subject, String object) {
+        StringBuffer rtnStr = new StringBuffer();
+        String preStr = "";
+        String nextStr = text;
+        String srcStr  = text;
+
+        while (srcStr.indexOf(subject) >= 0) {
+            preStr = srcStr.substring(0, srcStr.indexOf(subject));
+            nextStr = srcStr.substring(srcStr.indexOf(subject) + subject.length(), srcStr.length());
+            srcStr = nextStr;
+            rtnStr.append(preStr).append(object);
+        }
+        rtnStr.append(nextStr);
+        return rtnStr.toString();
+    }
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 원본 문자열의 포함된 특정 문자열 첫번째 한개만 새로운 문자열로 변환하는 메서드
+     * @param source 원본 문자열
+     * @param subject 원본 문자열에 포함된 특정 문자열
+     * @param object 변환할 문자열
+     * @return sb.toString() 새로운 문자열로 변환된 문자열 / source 특정문자열이 없는 경우 원본 문자열
+     */
+    public static String replaceOnce(String source, String subject, String object) {
+        StringBuffer rtnStr = new StringBuffer();
+        String preStr = "";
+        String nextStr = source;
+        if (source.indexOf(subject) >= 0) {
+            preStr = source.substring(0, source.indexOf(subject));
+            nextStr = source.substring(source.indexOf(subject) + subject.length(), source.length());
+            rtnStr.append(preStr).append(object).append(nextStr);
+            return rtnStr.toString();
+        } else {
+            return source;
+        }
+    }
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * <code>subject</code>에 포함된 각각의 문자를 object로 변환한다.
+     *
+     * @param source 원본 문자열
+     * @param subject 원본 문자열에 포함된 특정 문자열
+     * @param object 변환할 문자열
+     * @return sb.toString() 새로운 문자열로 변환된 문자열
+     */
+    public static String replaceChar(String source, String subject, String object) {
+        StringBuffer rtnStr = new StringBuffer();
+        String preStr = "";
+        String nextStr = source;
+        String srcStr  = source;
+
+        char chA;
+
+        for (int i = 0; i < subject.length(); i++) {
+            chA = subject.charAt(i);
+
+            if (srcStr.indexOf(chA) >= 0) {
+                preStr = srcStr.substring(0, srcStr.indexOf(chA));
+                nextStr = srcStr.substring(srcStr.indexOf(chA) + 1, srcStr.length());
+                srcStr = rtnStr.append(preStr).append(object).append(nextStr).toString();
+            }
+        }
+
+        return srcStr;
+    }
+
+    /**
+     * @author 최정우
+     * @since 2019.11.13
+     * 
+     * 문자열을 다양한 문자셋(EUC-KR[KSC5601],UTF-8..)을 사용하여 인코딩하는 기능 역으로 디코딩하여 원래의 문자열을
+     * 복원하는 기능을 제공함 String temp = new String(문자열.getBytes("바꾸기전 인코딩"),"바꿀 인코딩");
+     * String temp = new String(문자열.getBytes("8859_1"),"KSC5601"); => UTF-8 에서
+     * EUC-KR
+     *
+     * @param text - 문자열
+     * @param encoding - 원래의 인코딩된 값
+     * @param decoding - 디코딩할 문자값
+     * @return 인(디)코딩 문자열
+     * @exception MyException
+     * @see
+     */
+    public static String textDecoding(String text, String encoding, String decoding) {
+		if (text == null) {
+			return null;
+		}
+	
+		try {
+			text = new String(text.getBytes(encoding), decoding);
+		} catch (UnsupportedEncodingException e) {
+			text = null;
+		}
+	
+		return text;
+    }
+    
+    
+    /**
+     * @author 최정우
+     * @since 2020.11.26
+     * 
+     * 문자열 특정 포맷팅으로 변환 ##-####
+     */
+    public static String formatConvert(String data, String format) {
+		
+    	StringBuilder bf = new StringBuilder();
+		
+    	if(StringUtil.isEmpty(format) || StringUtil.isEmpty(data)) {
+    		bf.append(data);
+    	}else {
+    		int num =  data.length()-1;    		
+    		for(int i = format.length()-1 ; i >= 0 ; i--) {
+    			if(format.charAt(i) == '#') {
+    				bf.insert(0, data.charAt(num--));
+    			}else {
+    				bf.insert(0,format.charAt(i));
+    			}
+    		}
+    	}
+		
+		return bf.toString();
+	}
+    
+    /**
+     * @author 김성원
+     * @since 2022.07.06
+     * 
+     * 날짜형식 문자열  특정 포맷팅으로 변환 ##-####
+     */
+    public static String dateConvert(String date) {
+    	
+    	StringBuilder bf = new StringBuilder();
+    	
+    	boolean dateForm = true;
+    	
+    	if(!date.contains("-") && date.length() > 4) {
+    		dateForm = false;
+    	}
+    	
+    	if(!StringUtil.isEmpty(date)) {
+    	
+    		String dateStr =  date.replaceAll("[^0-9]", "");
+    		// 년도 처리 
+    		if(dateStr.length() < 5) {
+    			bf.append(date.substring(0,4));
+    		}else {
+    			if(dateForm == true) {
+    				bf.append(StringUtil.formatConvert(dateStr.substring(0,6),"####-##"));
+    			}else {
+    				bf.append(StringUtil.formatConvert(dateStr.substring(0,6),"####-##"));
+    				//bf.append(dateStr.substring(0,4));
+    				//bf.append("년 ");
+    			}
+    		}
+    	}    
+		
+		return bf.toString();
+	}
+    
+    
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/vo/CheckMessage.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/vo/CheckMessage.java
@@ -0,0 +1,73 @@
+package com.takensoft.taken_bi_manager.common.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2024.01.04
+ * 
+ * 데이터 체크, 유효성 검사 등과 같이 검사와 관련된 변수를 정의한 Class 입니다.
+ */
+@Getter
+@Setter
+public class CheckMessage {
+	
+	public CheckMessage() {}
+	
+	public CheckMessage(boolean isSuccess) {
+		this.isSuccess = isSuccess;
+	}
+	
+	public CheckMessage(String message) {
+		this.message = message;
+	}
+	
+	public CheckMessage(boolean isSuccess, String message) {
+		this.isSuccess = isSuccess;
+		this.message = message;
+	}
+	
+	public CheckMessage(boolean isSuccess, String message, int status) {
+		this.isSuccess = isSuccess;
+		this.message = message;
+		this.status = status;
+	}
+	
+	public CheckMessage(boolean isSuccess, String message, String error) {
+		this.isSuccess = isSuccess;
+		this.message = message;
+		this.error = error;
+	}
+	
+	/**
+	 * 체크 완료(사용가능 or 성공) 여부
+	 */
+	private boolean isSuccess;
+	
+	/**
+	 * 체크한 상태의 메세지값
+	 */
+	private String message;
+	
+	/**
+	 * 에러 메세지
+	 */
+	private String error;
+	
+	/**
+	 * 체크한 상태의 상태값 -> 상황마다 다름
+	 */
+	private int status;	
+	
+	
+	// 오류처리
+	public void setError(String message) {	
+		this.message = message;
+		this.error = message;
+		this.isSuccess = false;
+		this.status = 0;
+	}
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/vo/CommonVO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/vo/CommonVO.java
@@ -0,0 +1,139 @@
+package com.takensoft.taken_bi_manager.common.vo;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.takensoft.taken_bi_manager.common.util.StringUtil;
+
+import lombok.Getter;
+import lombok.Setter;
+
+
+
+/**
+ * @author 김성원
+ * @since 2024.01.09
+ * 
+ * 공통 검색 VO 입니다.(상속받으세요)
+ */
+@Getter
+@Setter
+public class CommonVO {
+
+	/**************************** 공통 ****************************/
+	/**
+	 * 검색조건
+	 */
+	private String searchCondition = "";
+
+	/**
+	 * 검색Keyword
+	 */
+	private String searchKeyword = "";
+	
+	/**
+	 * 검색Keyword
+	 */
+	private List<String> searchKeywordList = new ArrayList<String>();
+
+	/** 
+	 * 검색사용여부
+	 */
+	private String searchUseYn = "";
+  
+	/** 
+	 * 검색 시작일
+	 */
+	private String startDate = "";
+  
+	/** 
+	 * 검색 종료일
+	 */
+	private String endDate = "";
+	
+	/** 
+	 * 정렬 기준 (컬럼명)
+	 */
+	private String order = "";
+	
+	/** 
+	 * 정렬 타입
+	 * true - ASC
+	 * false - DESC
+	 */
+	private boolean isOrderASC = true;
+
+	/** 
+	 * 현재페이지
+	 */
+	private int currentPage = 1;
+
+	/** 
+	 * 페이지갯수
+	 */
+	private int perPage = 10;
+	
+	/** 
+	 * 총 개시물 수
+	 */
+	private int totalRows;
+	
+	/** 
+	 * 페이징 사용 유무
+	 */
+	private boolean isUsePaging = true;
+	
+	/** firstIndex */
+	private int firstIndex = 1;
+
+	/** lastIndex */
+	private int lastIndex = 1;
+	
+	/** 페이지사이즈 */
+	private int pageSize = 10;
+	
+	/** recordCountPerPage */
+	private int recordCountPerPage = 10;	  
+	
+	
+	public boolean getIsUsePaging() {
+		return isUsePaging;
+	}
+
+	public void setIsUsePaging(boolean isUsePaging) {
+		this.isUsePaging = isUsePaging;
+	}
+	/**************************** 공통 ****************************/
+	
+	/**************************** 검색어 분할 ****************************/
+	
+
+	public void setSearchKeywordList(List<String> searchKeywordList) {
+		this.searchKeywordList = searchKeywordList;
+	}
+	/**************************** 검색어 분할 ****************************/
+	
+	/**************************** 데이터베이스 별 페이징 ****************************/
+
+	
+	private int startIndex;
+	
+	/** 
+	 * 마지막 게시물의 인덱스 번호 (변환과정없음, 0부터 시작)
+	 */
+	private long limit = 0;
+	
+
+	public void searchClear() {
+		searchCondition = "";
+		searchKeyword = "";
+		searchUseYn = "";
+		startDate = "";
+		endDate = "";
+		order = "";
+	}
+	
+	/**************************** 데이터베이스 별 페이징 ****************************/
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/vo/CustomeResultMap.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/vo/CustomeResultMap.java
@@ -0,0 +1,27 @@
+package com.takensoft.taken_bi_manager.common.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.HashMap;
+
+/**
+ * 컨트롤러의 데이터를 반환할 기본 Map클래스
+ *
+ * @author 김성원
+ * @since 2023.12.28
+ */
+@Getter
+@Setter
+public class CustomeResultMap {
+
+    // 결과메세지
+    private CheckMessage checkMessage;
+    
+    // 결과 데이터 
+    private HashMap<String,Object> resultData;
+
+    public CustomeResultMap(){    
+        checkMessage = new CheckMessage(true, "성공" , 200);
+    }
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/vo/SearchObject.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/vo/SearchObject.java
@@ -0,0 +1,35 @@
+package com.takensoft.taken_bi_manager.common.vo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2024.01.09
+ * 
+ * 공통 검색용 VO 입니다
+ */
+@Getter
+@Setter
+public class SearchObject {
+	
+	/**
+	 * 검색 key
+	 */
+	private String key;
+
+	/**
+	 * 검색 값
+	 */
+	private Object value;
+	
+	/**
+	 * 데이터 타입(날짜, 숫자, 문자)
+	 */
+	private String type;
+
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/vo/SearchVO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/vo/SearchVO.java
@@ -0,0 +1,51 @@
+package com.takensoft.taken_bi_manager.common.vo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2024.01.09
+ * 
+ * 공통 검색 VO 입니다
+ */
+@Getter
+@Setter
+public class SearchVO {
+	
+	/**
+	 * 검색Keyword
+	 */
+	private List<SearchObject> searchObjectList = new ArrayList<SearchObject>();
+	
+	/** 
+	 * 정렬 기준 (컬럼명)
+	 */
+	private String order = "";
+
+	/** 
+	 * 정렬 타입
+	 * true - ASC
+	 * false - DESC
+	 */
+	private boolean isOrderASC = true;
+	
+	/** 
+	 * 현재페이지
+	 */
+	private int currentPage = 1;
+
+	/** 
+	 * 페이지갯수
+	 */
+	private int perPage = 10;
+	
+	/** 
+	 * 총 개시물 수
+	 */
+	private int totalRows;
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/common/vo/SystemCode.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/common/vo/SystemCode.java
@@ -0,0 +1,495 @@
+package com.takensoft.taken_bi_manager.common.vo;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import com.sun.jna.platform.win32.Sspi.TimeStamp;
+import com.takensoft.taken_bi_manager.common.connection.db.vo.ConnectionDB;
+import com.takensoft.taken_bi_manager.common.util.CommonUtil;
+import com.takensoft.taken_bi_manager.common.util.StringUtil;
+
+
+
+
+public class SystemCode {
+
+	//191자 => mariaDB에서 indexing가능한 최대 크기 765Byte/한글 4Byte(utf8mb4) 
+	public final static int DEFAULT_VARCHAR_SIZE = 191;
+		
+	//mariaDB에서 indexing가능한 varchar 최대 크기 765Byte
+	public final static int MAX_VARCHAR_SIZE = 765;
+	
+	
+	/**
+	 * @author 최정우
+	 * @since 2019.11.13
+	 * 
+	 * 데이터 타입을 정의한 상수 Class 입니다.
+	 * 상수명(java데이터타입, 초기값, mysql데이터타입, display데이터타입
+	 */
+	public enum DataType {
+		NULL(null, null)
+		, BYTE(Byte.class, 0)
+		, BOOL(Boolean.class, false)
+		, CHAR(Character.class, '\u0000')
+		, STRING(String.class, "")
+		, SHORT(Short.class, 0)
+		, INT(Integer.class, 0)
+		, DECIMAL(BigDecimal.class,0)
+		, LONG(Long.class, 0)
+		, FLOAT(Float.class, 0.0)
+		, DOUBLE(Double.class, 0.0)
+		, DATE(Date.class, "")
+		, DATETIME(Date.class, "")
+		, TIMESTAMP(Timestamp.class, "")
+		, ENTER(Character.class,'\n');
+
+		/**
+		 * enum(열거형데이터)의 생성자 
+		 * 1. 상수에 나열된 parameter와 형태가 똑같이 만들어줘야함.
+		 * 2. 접근제한자는 private로만 다른 접근제한자는 허용하지 않음
+		 */
+		private DataType (Class<?> javaType, Object iniValue) {
+	        this.javaType = javaType;
+	        this.initValue = iniValue;
+	    }
+		
+		/**
+		 * java데이터타입
+		 */
+		final private Class<?> javaType;
+		
+		/**
+		 * 초기값
+		 */
+		final private Object initValue;
+		
+	    public Class<?> getJavaType() {
+	        return javaType;
+	    }
+	    public Object getInitValue() {
+	        return initValue;
+	    }
+	    	 
+	    
+	    /**
+		 * 데이터 타입 검사, DataType 조회
+		 */
+	    public static Map<DataType, String> getDataTypeList () {
+	    	Map<DataType, String> info = new LinkedHashMap<DataType, String>();
+	    	info.put(STRING, "문자열");
+	    	info.put(LONG, "정수");
+	    	info.put(DOUBLE, "실수");
+	    	info.put(DATE, "날짜");
+	    	info.put(DATETIME,"날짜,시간");
+	    	return info;
+		}
+	    
+	    
+	    /**
+		 * 데이터 타입 검사, DataType 조회
+		 */
+	    public static List<DataType> getDataTypeArray () {
+	    	List<DataType> info = new ArrayList<DataType>();
+	    	info.add(STRING);
+	    	info.add(LONG);
+	    	info.add(DOUBLE);
+	    	info.add(DATE);
+	    	info.add(DATETIME);
+	    	info.add(BOOL);
+	    	return info;
+		}
+	    
+	    /**
+		 * 데이터 타입 검사, DataType 조회
+		 */
+	    public static DataType getDataType (String text) {
+	    	/*
+	    	 * 2021-11-02 김혜민 dataType 전화번호, 날짜 정규식 수정
+	    	 * 
+	    	 * 
+	    	 * 전화번호 정규식*/
+	    	String regExp = "^\\d{2,3}-\\d{3,4}-\\d{4}$";
+	    	String regDateTime = "\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]) (0[1-9]|1[0-9]|2[0-4]):(0[1-9]|[1-5][0-9]):(0[1-9]|[1-5][0-9])";
+	    	String regDate = "\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])";
+	    			
+			if(StringUtil.isEmpty(text)) {
+				return NULL;
+			} else if(CommonUtil.isLong(text)) {
+				/*
+				 * 숫자로 변환 가능 하지만 앞에 '0'이 붙어 있으면 문자열로 봄
+				 * ex) 0102 -> String, 1102 -> Long
+				 */
+				if (text.length() > 1 && text.indexOf("0") == 0) {
+					return STRING;
+				} else {
+					return LONG;
+				}
+			}else if(CommonUtil.isDouble(text)) {
+				
+				return DOUBLE;
+				
+			} else if (CommonUtil.isDate(text)) {
+				/*
+		    	 * 2021-11-02 김혜민 dataType 전화번호, 날짜 정규식 수정
+		    	 * 
+		    	 * 
+		    	 * 전화번호 정규식*/
+		    	boolean expResult = Pattern.matches(regExp, text);
+		    	boolean dateTimeResult = Pattern.matches(regDateTime, text);
+		    	boolean dateResult = Pattern.matches(regDate, text);
+		    	
+				if(expResult) {
+					return STRING;
+				}else if(dateResult) {				
+					return DATE;
+				}else {
+					return DATETIME;
+				}
+				
+			} else {
+				return STRING;
+			}
+		}
+	    
+	    /**
+		 * 데이터 타입 검사, dbDataType 조회
+		 */
+	    public static String convertDbDataType (DataType datatype, Integer size) {
+	    	if (datatype == STRING) {
+	    		if (size == null || size <= MAX_VARCHAR_SIZE) {
+	    			return "varchar";
+	    		} else {
+	    			return "text";
+	    		}
+	    	} else if (datatype == DATE) {
+	    		return "date";
+	    	} else if (datatype == DATETIME){
+	    		return "datetime";
+	    	} else if (datatype == LONG) {
+	    		return "bigint";
+	    	} else if (datatype == DOUBLE) {
+	    		return "double";
+	    	} else {
+	    		return "varchar";
+	    	}
+	    }
+	    
+	    /**
+		 * 데이터 타입 검사, dbDataType -> javaType 조회
+		 */
+	    public static DataType convertDataTypeDbtoJava (DataType datatype, Integer size) {
+	    	
+	    	
+	    	return null;	    	
+	    }
+	    
+	    
+	    /**
+		 * 데이터 타입 형태로 값 변경
+		 */
+		public static Object parse(DataType dataType, Object value) {
+			if (CommonUtil.isNull(value) == true) {
+				return null;
+			}
+			
+			Class<?> javaType = dataType.getJavaType();
+			try {
+				if (javaType.getSimpleName().equals("Byte")) {
+					return Byte.parseByte(value.toString());
+				} else if (javaType.getSimpleName().equals("Boolean")) {
+					return Boolean.parseBoolean(value.toString());
+				} else if (javaType.getSimpleName().equals("Character")) {
+					return value.toString().toCharArray();
+				} else if (javaType.getSimpleName().equals("String")) {
+					return value.toString();
+				} else if (javaType.getSimpleName().equals("Short")) {
+					//Short.parseShort(value.toString().replaceAll("[^0-9]",""));
+					return Short.parseShort(value.toString());
+				} else if (javaType.getSimpleName().equals("Integer")) {
+					//Integer.parseInt(value.toString().replaceAll("[^0-9]",""));
+					return Integer.parseInt(value.toString());
+				} else if (javaType.getSimpleName().equals("Long")) {
+					//Long.parseLong(value.toString().replaceAll("[^0-9]",""));
+					return Long.parseLong(value.toString());
+				} else if (javaType.getSimpleName().equals("Float")) {
+					//Float.parseFloat(value.toString().replaceAll("[^0-9]",""));
+					return Float.parseFloat(value.toString());
+				} else if (javaType.getSimpleName().equals("Double")) {
+					//Double.parseDouble(value.toString().replaceAll("[^0-9]",""));
+					return Double.parseDouble(value.toString());
+				} else {
+					return value;
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+				return dataType.getInitValue();
+			}
+		}
+		
+		/**
+		 * 데이터 타입 형태로 값 변경
+		 */
+		public static boolean parseCheck (DataType dataType, Object value) {
+			if (CommonUtil.isNull(value) == true) {
+				return false;
+			}
+			
+			Class<?> javaType = dataType.getJavaType();
+			try {
+				if (javaType.getSimpleName().equals("Byte")) {
+					Byte.parseByte(value.toString());
+				} else if (javaType.getSimpleName().equals("Boolean")) {
+					Boolean.parseBoolean(value.toString());
+				} else if (javaType.getSimpleName().equals("Character")) {
+					value.toString().toCharArray();
+				} else if (javaType.getSimpleName().equals("String")) {
+					value.toString();
+				} else if (javaType.getSimpleName().equals("Short")) {
+					//Short.parseShort(value.toString().replaceAll("[^0-9]",""));
+					Short.parseShort(value.toString());
+				} else if (javaType.getSimpleName().equals("Integer")) {
+					//Integer.parseInt(value.toString().replaceAll("[^0-9]",""));
+					Integer.parseInt(value.toString());
+				} else if (javaType.getSimpleName().equals("Long")) {
+					//Long.parseLong(value.toString().replaceAll("[^0-9]",""));
+					Long.parseLong(value.toString());
+				} else if (javaType.getSimpleName().equals("Float")) {
+					//Float.parseFloat(value.toString().replaceAll("[^0-9]",""));
+					Float.parseFloat(value.toString());
+				} else if (javaType.getSimpleName().equals("Double")) {
+					//Double.parseDouble(value.toString().replaceAll("[^0-9]",""));
+					Double.parseDouble(value.toString());
+				}
+				
+				return true;
+			} catch (Exception e) {
+				//e.printStackTrace();
+				return false;
+			}
+		}
+	    
+	}
+	
+	/**
+	 * @author 최정우
+	 * @since 2019.11.20
+	 * 
+	 * 데이터 베이스 타입별 상수를 정의
+	 */
+	public enum DatabaseType {
+		MYSQL("MySql", "com.mysql.jdbc.Driver", "jdbc:mysql://", "3306", "allowMultiQueries=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC")
+		, MARIADB("MariaDB", "org.mariadb.jdbc.Driver", "jdbc:mariadb://", "3306", "")
+		, ORACLE("Oracle", "oracle.jdbc.OracleDriver", "jdbc:oracle:thin:@", "1521", "")
+		, MSSQL("MS-SQL", "com.microsoft.sqlserver.jdbc.SQLServerDriver", "jdbc:sqlserver://", "1433", "")
+		, TIBERO("Tibero", "com.tmax.tibero.jdbc.TbDriver", "jdbc:tibero:thin:@", "8629", "")
+		, POSTGRESQL("PostgreSql", "org.postgresql.Driver", "jdbc:postgresql://", "5432", "");
+		
+		private DatabaseType(String value, String driverClassName, String baseUrl, String defalutPort, String option) {
+			this.value = value;
+			this.driverClassName = driverClassName;
+			this.baseUrl = baseUrl;
+			this.defalutPort = defalutPort;
+			this.option = option;
+		}
+		
+		/**
+		 * 한글값
+		 */
+		final private String value;
+		
+		/**
+		 * 드라이버 클래스
+		 */
+		final private String driverClassName;
+		
+		/**
+		 * 접속 URL
+		 */
+		final private String baseUrl;
+		
+		/**
+		 * 기본 포트
+		 */
+		final private String defalutPort;
+		
+		/**
+		 * 접속 옵션
+		 */
+		final private String option;
+		
+		
+		/**
+		 * 한글값 조회
+		 */
+		public String getValue () {
+			return value;
+		}
+		
+		/**
+		 * 드라이버 클래스 조회
+		 */
+		public String getDriverClassName () {
+			return driverClassName;
+		}
+		
+		/**
+		 * 접속 URL 조회
+		 */
+		public String getBaseUrl () {
+			return baseUrl;
+		}
+		
+		/**
+		 * 기본 포트 조회
+		 */
+		public String getDefaultPort () {
+			return defalutPort;
+		}
+		
+		/**
+		 * 접속 옵션 조회
+		 */
+		public String getOption () {
+			return option;
+		}
+		
+		/**
+		 * 접속 URL 조회
+		 */
+		public String getUrl (ConnectionDB connectionDB) {
+			StringBuilder builder = new StringBuilder();		
+			if ((this == ORACLE || this == TIBERO ) && connectionDB.isGroupDatabase() == false) {
+				builder.append(this.baseUrl);
+				builder.append(connectionDB.getConectIp());
+				builder.append(":");
+				builder.append(connectionDB.getConectPort());
+				builder.append(":");
+				builder.append(connectionDB.getDatabaseNm());				
+			} else {
+				builder.append(this.baseUrl);
+				builder.append(connectionDB.getConectIp());
+				builder.append(":");
+				builder.append(connectionDB.getConectPort());
+				if(this == MSSQL) {
+					builder.append(";databaseName=");
+					
+				}else {
+					builder.append("/");
+				}				
+				builder.append(connectionDB.getDatabaseNm());				
+				if (this == MYSQL) {
+					builder.append("?");
+					builder.append(this.option.replaceAll("&amp;", "&"));
+				}else if(this == POSTGRESQL) {
+					builder.append("?");
+					builder.append("currentSchema="+connectionDB.getSchemaNm());					
+				}
+			}
+			
+			return builder.toString();
+		}
+		
+		/**
+		 * 접속 URL 조회
+		 */
+		public String getUrl (String ip, String port, String databaseName, boolean isGroupDatabase, String option) {
+			StringBuilder builder = new StringBuilder();		
+			if ((this == ORACLE || this == TIBERO ) && isGroupDatabase == false) {
+				builder.append(this.baseUrl);
+				builder.append(ip);
+				builder.append(":");
+				builder.append(port);
+				builder.append(":");
+				builder.append(databaseName);
+			} else {
+				builder.append(this.baseUrl);
+				builder.append(ip);
+				builder.append(":");
+				builder.append(port);
+				builder.append("/");
+				builder.append(databaseName);
+			}
+			
+			if (StringUtil.isEmpty(option) == false) {
+				builder.append("?");
+				option.replaceAll("&amp;", "&");
+				builder.append(option);
+			}	
+		
+			
+			return builder.toString();
+		}
+		
+		/**
+		 * 데이터 베이스 타입별 상수 목록 조회
+		 */
+		public static Map<DatabaseType, String> getDatabaseTypeList () {
+	    	Map<DatabaseType, String> info = new LinkedHashMap<DatabaseType, String>();
+	    	DatabaseType[] array = DatabaseType.values();
+	    	for (int i = 0; i < array.length; i++) {
+	    		info.put(array[i], array[i].getValue());
+	    	}
+	    	return info;
+		}
+		
+		/**
+		 * 데이터 베이스 타입별 상수 목록 조회
+		 */
+		public static Map<DatabaseType, Map<String, String>> getDatabaseTypeInfoList () {
+			Map<DatabaseType, Map<String, String>> info = new LinkedHashMap<DatabaseType, Map<String, String>>();
+	    	DatabaseType[] array = DatabaseType.values();
+	    	for (int i = 0; i < array.length; i++) {
+	    		Map<String, String> detailInfo = new HashMap<String, String>();
+	    		detailInfo.put("key", array[i].toString());
+	    		detailInfo.put("value", array[i].getValue());
+	    		detailInfo.put("driverClassName", array[i].getDriverClassName());
+	    		detailInfo.put("baseUrl", array[i].getBaseUrl());
+	    		detailInfo.put("defalutPort", array[i].getDefaultPort());
+	    		detailInfo.put("option", array[i].getOption());
+	    		info.put(array[i], detailInfo);
+	    	}
+	    	return info;
+		}
+		
+	}
+	
+	
+	/**
+	 * @author 최정우
+	 * @since 2019.11.13
+	 * 
+	 * SPMiner에서 등록되는 파일 타입과, 해당 파일 타입의 등록가능한 확장자를 정의한 상수 Class 입니다.
+	 * 첨부파일, 이미지파일, 데이터 셋 파일 순서입니다.
+	 */
+	public enum FileType {
+		ALL_FILE(Arrays.asList("bmp","jpg","gif","png","jpeg","bmp","wma","avi","wav","mp3","mp4","mpeg","wmv","asf","pdf","ppt","pptx","docx","xls","xlsx","csv","hwp","txt","doc","zip", "json", "xml"))
+		, IMG_FILE(Arrays.asList("bmp","jpg","gif","png","jpeg"))
+		, DATASET_FILE(Arrays.asList("xls","xlsx","csv"));
+		
+		private FileType(List<String> extensions) {
+			this.extensions = extensions;
+		}
+		
+		/**
+		 * 확장자 목록
+		 */
+		final private List<String> extensions;
+		
+		/**
+		 * 확장자 목록 조회
+		 */
+		public List<String> getExtensions () {
+			return extensions;
+		}
+	}
+		
+}
 
src/main/java/com/takensoft/taken_bi_manager/controller/ScedulerService.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/controller/ScedulerService.java
@@ -0,0 +1,28 @@
+package com.takensoft.taken_bi_manager.controller;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.takensoft.taken_bi_manager.common.vo.CustomeResultMap;
+import com.takensoft.taken_bi_manager.user.member.servie.MemberService;
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+@Component
+public class ScedulerService implements InitializingBean {
+
+	@Autowired
+    private MemberService memberService;	
+	
+	@Override
+	public void afterPropertiesSet() throws Exception {
+		// TODO Auto-generated method stub
+	/*	Member member = new Member();
+		member.setUserId("admin");
+		member.setUserPassword("qwer1234!");
+		CustomeResultMap map = memberService.userLogin(member);
+		System.out.print(map.getCheckMessage().getMessage());
+		*/
+	}
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/data/util/DataTableConvert.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/data/util/DataTableConvert.java
@@ -0,0 +1,99 @@
+package com.takensoft.taken_bi_manager.data.util;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.takensoft.taken_bi_manager.common.file.vo.FileInfo;
+import com.takensoft.taken_bi_manager.data.vo.ColumnData;
+import com.takensoft.taken_bi_manager.data.vo.DataTable;
+import com.takensoft.taken_bi_manager.data.vo.Dataset;
+
+/**
+ * @author 김성원
+ * @since 2024.01.09
+ * 
+ * 파일, DB, API, Dataset 간의 변환을 위한 클래스 
+ */
+public class DataTableConvert {
+
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.12
+	 * 
+	 * 파일  -> 데이터셋 변환(엑셀, CSV, TEXT, JSON, XML)
+	 */
+	public static Dataset filetoDataset(FileInfo fileInfo) {
+		
+		// 데이터 확장자 
+		String dataType = fileInfo.getFileFom();
+		
+		
+		
+		
+		return null;
+	}	
+		
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.12
+	 * 
+	 * List<Map<Object, String>> -> Dataset
+	 */	
+	public static DataTable listMaptoDataset(List<Map<String, Object>> mapData) {
+
+		// 데이터 테이블 생성
+		DataTable dataTable = new DataTable();
+		
+		// 헤더정보 리스트
+		List<String> header = new ArrayList<>();
+		
+		// 컬럼 데이터 리스트
+		List<ColumnData> columnDatas = new ArrayList<ColumnData>();
+		
+		int manxSize = 0;		
+		
+		// 제일큰 ROW의 헤더값 가져오기
+		for(Map<String, Object> mapItm : mapData) {
+			if(manxSize < mapItm.entrySet().size()) { 				
+				manxSize = mapItm.entrySet().size();				
+				header.clear();				
+				for (Map.Entry<String, Object> elem : mapItm.entrySet()) {					
+					header.add(elem.getKey());
+				}							
+			}	
+		}		
+		
+		// row 데이터 생성
+		for (Map<String, Object> temp : mapData) {
+			List<Object> listTemp = new ArrayList();
+			for(String head : header) {			
+				if(temp.get(head) == null) {
+					listTemp.add(null);
+				}else {
+					listTemp.add(temp.get(head));
+				}			
+			}
+			dataTable.getRowData().add(listTemp);
+		}		
+		
+		// 컬럼명 세팅
+		for(String head : header) {			
+			ColumnData columnData = new ColumnData();
+			// 헤더명 (컬럼명)
+			columnData.setColumnNm(head);
+			columnData.setOrginlColumnNm(head);
+			columnData.setDisplyColumnNm(head);
+			columnDatas.add(columnData);
+		}	
+		
+		// DataTable의 컬럼정보 세팅
+		dataTable.setColumnDatas(columnDatas);
+
+		return dataTable;
+	}
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/data/vo/Column.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/data/vo/Column.java
@@ -0,0 +1,84 @@
+package com.takensoft.taken_bi_manager.data.vo;
+
+import java.io.Serializable;
+
+import com.takensoft.taken_bi_manager.common.connection.db.vo.DataType;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2024.01.02
+ * 
+ * Columns Domain 입니다.
+ */
+@Getter
+@Setter
+public class Column implements Serializable {
+	
+	/**
+	 * 시리얼 버전
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	
+	// 컬럼 ID
+	private String columnId;
+	
+	// 컬럼명
+	private String columnNm;
+	
+	// 표츌 컬럼명 
+	private String displyColumnNm;
+	
+	// 원본데이터 컬럼명 
+	private String orginlColumnNm;
+	
+	// dataset id(fk)
+	private String datasetId;
+	
+	// 데이터 타입
+	private DataType dataTy;
+	
+	// 데이터 길이
+	private long dataSize;
+	
+	// 컬럼순서
+	private int ordr;
+	
+	// pk여부
+	private boolean pkAt;
+	
+	// 고유값 여부 
+	private boolean uniqeAt;
+	
+	// 자동증가 여부 
+	private boolean autoIncrementAt;
+	
+	// 컬럼명 표준화 여부
+	private boolean columnStdizAt;
+	
+	// 도메인 표준화 여부
+	private boolean domnStdizAt;
+	
+	// 도메인 코드 
+	private String domnCode;
+	
+	// 사용여부 
+	private boolean useAt;
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/data/vo/ColumnData.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/data/vo/ColumnData.java
@@ -0,0 +1,154 @@
+package com.takensoft.taken_bi_manager.data.vo;
+
+
+
+import java.io.Serializable;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.takensoft.taken_bi_manager.common.connection.db.vo.DataType;
+import com.takensoft.taken_bi_manager.meta.term.vo.StandardTermSearch;
+
+import lombok.Getter;
+import lombok.Setter;
+
+
+/**
+ * @author 김성원
+ * @since 2024.01.04
+ * 
+ * 열(Column) 데이터의 정보를 담는 Class 입니다.
+ */
+@Getter
+@Setter
+public class ColumnData extends Column implements Serializable {
+	
+	public ColumnData () {}
+	
+	public ColumnData (String originColumnName) {
+		super.setOrginlColumnNm(originColumnName);
+	}
+	
+	public ColumnData (String originColumnName, String displayColumnName, DataType dataType) {
+		super.setOrginlColumnNm(originColumnName);
+		super.setDisplyColumnNm(originColumnName);
+		super.setDataTy(dataType);
+	}
+	
+	public ColumnData (String originColumnName, String displayColumnName, DataType dataType, boolean isPrimary) {
+		super.setOrginlColumnNm(originColumnName);
+		super.setDisplyColumnNm(originColumnName);
+		super.setDataTy(dataType);
+		super.setPkAt(isPrimary);
+	}
+	
+	public ColumnData (String originColumnName, String displayColumnName, String columnName, DataType dataType) {
+		super.setOrginlColumnNm(originColumnName);
+		super.setDisplyColumnNm(displayColumnName);
+		super.setColumnNm(columnName);
+		super.setDataTy(dataType);
+	}
+	
+	/**
+	 * 시리얼 버전
+	 */
+	private static final long serialVersionUID = 1L;	
+	
+	
+	/**
+	 * 테이블 명
+	 */
+	private String databaseNm;
+	
+	
+	/**
+	 * 테이블 명
+	 */
+	private String tableNm;
+	
+	/**
+	 * 데이터 베이스에 생성될 데이터 타입
+	 */
+	private String dbDataType;
+	
+	/**
+	 * 표준 용어 검색 Box Display 여부  (client단에서만 사용)
+	 */
+	private boolean isSearching;
+	
+	/**
+	 * 표준 용어 검색된 목록 Display 여부 (client단에서만 사용)
+	 */
+	private boolean isSearchListView;
+	
+	/**
+	 * 컬럼 유니크 옵션
+	 */
+	private boolean isUniq;
+
+	/**
+	 * 해당 컬럼의 표준용어 검색 목록 중 사용하기 위해 선택 중인 표중용어 정보 (client단에서만 사용)
+	 */
+	private StandardTermSearch selectingStandardTerm;
+	
+	/**
+	 * 해당 컬럼의 표준용어 검색 목록 (client단에서만 사용)
+	 */
+	private List<StandardTermSearch> standardTermSearchList = new ArrayList<StandardTermSearch>();
+	
+	/**
+	 * 컬럼 유니크 옵션
+	 */
+	private boolean isView;
+	
+	
+	public void cellValuesClear() {
+	//	this.columnValues.clear();
+	}
+	
+	public void dataTyDefine(Object data) {
+		if(data == null ) {
+			this.setDataTy(DataType.NULL);
+		}else if(data instanceof Boolean) {
+			this.setDataTy(DataType.BOOL);
+		}else if(data instanceof Character) {
+			this.setDataTy(DataType.CHAR);
+		}else if(data instanceof Short) {
+			this.setDataTy(DataType.SHORT);
+		}else if(data instanceof Integer) {
+			this.setDataTy(DataType.INT);
+		}else if(data instanceof Long) {
+			this.setDataTy(DataType.LONG);
+		}else if(data instanceof Float) {
+			this.setDataTy(DataType.FLOAT);
+		}else if(data instanceof Double) {
+			this.setDataTy(DataType.DOUBLE);
+		}else if(data instanceof Timestamp) {
+			this.setDataTy(DataType.TIMESTAMP);
+		}else if(data instanceof Date) {
+			this.setDataTy(DataType.DATETIME);
+		}else if(data instanceof Character) {
+			this.setDataTy(DataType.ENTER);
+		}		
+	}
+	
+	/******************************************************************* 추가 *******************************************************************/
+	
+	/**
+	 * 열의 합계
+	 */
+	private Object sum;
+	
+	public Object getSum() {
+		return sum;
+	}
+
+	public void setSum(Object sum) {
+		this.sum = sum;
+	}
+	
+	/******************************************************************* 추가 *******************************************************************/
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/data/vo/ColumnValue.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/data/vo/ColumnValue.java
@@ -0,0 +1,107 @@
+package com.takensoft.taken_bi_manager.data.vo;
+
+
+
+import java.io.Serializable;
+
+import com.takensoft.taken_bi_manager.common.connection.db.vo.DataType;
+import com.takensoft.taken_bi_manager.common.util.CommonUtil;
+import com.takensoft.taken_bi_manager.common.util.StringUtil;
+
+
+/**
+ * @author 최정우
+ * @since 2019.11.13
+ * 
+ * 열(Column) 데이터(데이터목록)를 담는 Class 입니다.
+ */
+public class ColumnValue implements Serializable , Comparable<ColumnValue> {
+	
+	/**
+	 * 시리얼 버전
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	/**
+	 * 컬럼의 값
+	 */
+	private Object value;
+	
+	/**
+	 * 해당 열 데이터의 데이터 타입
+	 */
+	private DataType dataType;
+	
+	/**
+	 * 중복제거 시, 중복되는 갯수
+	 */
+	private int count;
+	
+	public ColumnValue() {
+		
+	}
+	
+	/**
+	 * 초기화
+	 */
+	public ColumnValue(Object value,DataType dataType) {
+		this.value = value;
+		this.dataType = dataType;	
+	}
+	
+	
+	public ColumnValue(Object value,DataType dataType, int count ) {
+		this.value = value;
+		this.dataType = dataType;
+		this.count = count;
+	}
+	
+	public Object getValue() {
+		return value;
+	}
+
+	public void setValue(Object value) {
+		this.value = value;
+	}
+
+	public DataType getDataType() {
+		return dataType;
+	}
+
+	public void setDataType(DataType dataType) {
+		this.dataType = dataType;
+	}
+
+	public int getCount() {
+		return count;
+	}
+
+	public void setCount(int count) {
+		this.count = count;
+	}
+
+	@Override
+	public int compareTo(ColumnValue columnValue) {
+		
+		int result = 0;
+		if (this.value == null && columnValue.getValue() != null) {
+			result = -1;
+		} else if (this.value != null && columnValue.getValue() == null) {
+			result = 1;
+		} else if (this.value != null && columnValue.getValue() != null) {
+			if(this.dataType.equals(DataType.STRING)) {
+				result = StringUtil.toString(this.value).compareTo(StringUtil.toString(columnValue.getValue()));
+			} else if(this.dataType.equals(DataType.DOUBLE)) {
+				result = Double.compare(CommonUtil.parseDouble(this.value), CommonUtil.parseDouble(columnValue.getValue()));
+			}else if(this.dataType.equals(DataType.LONG)) {
+				result = Double.compare(CommonUtil.parseDouble(this.value), CommonUtil.parseDouble(columnValue.getValue()));
+				//result = Long.compare(Long.parseLong(this.value.toString()), Long.parseLong(columnValue.getValue().toString()));
+			}
+		} else {//둘다 null
+			result = 0;
+		}
+	
+		return result;
+	}
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/data/vo/DataTable.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/data/vo/DataTable.java
@@ -0,0 +1,170 @@
+package com.takensoft.taken_bi_manager.data.vo;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.takensoft.taken_bi_manager.common.vo.CheckMessage;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class DataTable extends Dataset{
+
+	/**
+	 * 시리얼 버전
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	public DataTable () {};
+	
+	public DataTable (Dataset parents) {
+		super.setDatasetId(parents.getDatasetId());
+		super.setDatasetSj(parents.getDatasetSj());
+		super.setDbConectId(parents.getDbConectId());
+		super.setTableNm(parents.getTableNm());
+		super.setTableNmKr(parents.getTableNmKr());
+		super.setCreatTableAt(parents.isCreatTableAt());
+		super.setCreatDt(parents.getCreatDt());
+		super.setUpdtDt(parents.getUpdtDt());		
+		super.setDatasetPostId(parents.getDatasetPostId());
+		super.setStdizColumnAt(parents.isStdizColumnAt());
+		super.setStdizDomnAt(parents.isStdizDomnAt());
+		super.setStdizTableNm(parents.isStdizTableNm());
+		super.setQuery(parents.getQuery());			
+	};
+	
+
+	/**
+	 * 열 기준 데이터 정보 (헤더 정보 + 열별 데이터 목록)
+	 */
+	private List<ColumnData> columnDatas = new ArrayList<ColumnData>();
+	
+	/**
+	 * 데이터(행,열)
+	 */	
+	private List<List<Object>> rowData = new ArrayList<List<Object>>();
+	
+	/**
+	 * 열 기준 데이터 정보 (헤더 정보 + 열별 데이터 목록)
+	 */
+	private List<ColumnData> changeColumnDatas = null;
+	
+	/**
+	 * primary key 존재 여부
+	 */	
+	private boolean isExistPrimary = false;
+	
+	/**
+	 * 헤더(컬럼)데이터를 현재 생성된 rowData 인스턴스에 0번째Index에 추가했는지에 대한 여부
+	 */	
+	private boolean isRowDataHeaderAdd = false;
+	
+	/**
+	 * 헤더(컬럼)데이터의 columnName이 메모리상에서 변경된는 지에 대한 여부
+	 */	
+	private boolean isColumnNameChange = false;
+	
+	/**
+	 * 데이터(행,열)의 컬럼인 Row의 Index
+	 */
+	private int rowDataColumnIndex;
+	
+	/**
+	 * 데이터(행,열)의 Row 시작 Index
+	 */
+	private int startRowIndex;
+	
+	/**
+	 * 데이터(행,열)의 Cell 시작 Index
+	 */
+	private int startCellIndex;
+	
+	/** 
+	 * 총 개시물 수
+	 */
+	private int totalRows;
+	
+	/**
+	 * 데이터 편집 결과 메세지(화면에서만 쓰임)
+	 */
+	private List<Map<String, String>> editResultList = new ArrayList<Map<String, String>>();
+	
+	/**
+	 * DataTable 생성 관련 메세지
+	 */
+	private CheckMessage checkMessage = new CheckMessage();
+	
+	
+	public void cellValuesClear() {
+		for (int i = 0; i < columnDatas.size(); i++) {
+			columnDatas.get(i).cellValuesClear();
+		}
+	}
+	
+	/**
+	 * 컬럼 데이터 값 저장 
+	 */
+	/*
+	public void setColumnValues(List<LinkedHashMap<String,Object>> datas) {
+		this.setTotalRows(datas.size());
+		for(LinkedHashMap<String,Object> temp : datas) {
+			for(ColumnData columnData : this.columnDatas) {
+				columnData.getColumnValues().add(new ColumnValue(temp.get(columnData.getColumnNm()),columnData.getDataTy()));
+			}
+		}
+	}
+	*/
+	
+	/**
+	 * 쿼리 생성(DB포함) 
+	 */
+	public void setQuery() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("SELECT \n");
+		for (int i = 0; i < this.getColumnDatas().size(); i++) {
+			builder.append("\t");
+			if (i > 0) {
+				builder.append(", ");
+			}
+			builder.append(this.getColumnDatas().get(i).getColumnNm());
+			builder.append("\n");
+		}
+		builder.append("FROM \n\t");
+		builder.append(this.getDatabaseNm());
+		builder.append(".");
+		builder.append(this.getTableNm());
+		builder.append("\n");
+		
+		this.setQuery(builder.toString());		
+	}
+	
+	/**
+	 * 쿼리생성
+	 */
+	public String makeQuery() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("SELECT \n");
+		for (int i = 0; i < this.getColumnDatas().size(); i++) {
+			builder.append("\t");
+			if (i > 0) {
+				builder.append(", ");
+			}
+			builder.append(this.getColumnDatas().get(i).getColumnNm());
+			builder.append("\n");
+		}
+		builder.append("FROM \n\t");	
+		builder.append(this.getTableNm());
+		builder.append("\n");
+		
+		this.setQuery(builder.toString());
+		
+		return builder.toString();
+	
+	}
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/data/vo/Dataset.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/data/vo/Dataset.java
@@ -0,0 +1,79 @@
+package com.takensoft.taken_bi_manager.data.vo;
+
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+import com.takensoft.taken_bi_manager.common.vo.CommonVO;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+/**
+ * @author 김성원
+ * @since 2024.01.03
+ * 
+ * Dataset Domain 입니다.
+ */
+public class Dataset extends CommonVO implements Serializable {	
+
+	/**
+	 * 시리얼 버전
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	
+	// 데이터셋 아이디
+	private String datasetId;
+	
+	// 데이터셋 명 
+	private String datasetSj;
+	
+	// 테이블 명 
+	private String tableNm;
+	
+	// 한글 테이블 명
+	private String tableNmKr;
+	
+	// 테이블 생성여부
+	private boolean creatTableAt;
+	
+	// 테이블명 표준화 여부
+	private boolean stdizTableNm;	
+	
+	// 컬럼명 표준화 여부
+	private boolean stdizColumnAt;
+	
+	// 도메인 표준화 여부 
+	private boolean stdizDomnAt;	
+	
+	// 데이터 게시물 ID(FK)
+	private String datasetPostId;
+	
+	// 생성일
+	private Timestamp creatDt;
+	
+	// 생성자ID
+	private String creatId;
+	
+	// 수정일 
+	private Timestamp updtDt;
+		
+	// 수정자 ID
+	private String updtId;
+	
+	// 커넥션 ID
+	private String dbConectId;	
+	
+	// 사용쿼리
+	private String query;	
+
+	//  데이터베이스명	
+	private String databaseNm;
+	
+		
+	
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/meta/term/vo/StandardTerm.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/meta/term/vo/StandardTerm.java
@@ -0,0 +1,264 @@
+package com.takensoft.taken_bi_manager.meta.term.vo;
+
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.takensoft.taken_bi_manager.data.vo.Column;
+
+
+
+/**
+ * @author 최정우
+ * @since 2019.11.13
+ * 
+ * StandardTerm(표준용어) Domain 입니다.
+ */
+public class StandardTerm implements Serializable {
+
+	
+	/**
+	 * 시리얼 버전
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	/**************************** Domain 원본 ****************************/
+	
+	/**
+	 * 표준용어 SEQ
+	 */
+	private long termSeq;
+	
+	/**
+	 * 표준용어 ID (SEQ여러개 포함)
+	 */
+	private String termId;
+	
+	/**
+	 * 표준용어 한글
+	 */
+	private String korean;
+
+	/**
+	 * 표준용어 영어
+	 */
+	private String english;
+	
+	/**
+	 * 표준용어 영어 약어
+	 */
+	private String englishAbbr;
+	
+	/**
+	 * 용어 설명
+	 */
+	private String termDc;
+	
+	/**
+	 * 표준용어 사용 시스템
+	 */
+	private String usingSystem;
+	
+	/**
+	 * 생성일
+	 */
+	private String createDate;
+	
+	/**
+	 * 생성자
+	 */
+	private String createId;
+	
+	/**
+	 * 수정일
+	 */
+	private String updateDate;
+	
+	/**
+	 * 수정자
+	 */
+	private String updateId;
+	
+	/**
+	 * 사용여부
+	 */
+	private boolean isUse;
+	
+	/**
+	 * 표준 여부
+	 */
+	private boolean isStandard;
+	
+	/**
+	 * 행안부 표준 여부
+	 */
+	private boolean isMinistryStandard;
+	
+	/**
+	 * 한 용어에 대한 순서 (히스토리 Index)
+	 */
+	private int orders;
+	
+	/**
+	 * 한 용어에 대한 검색 횟수
+	 */
+	private long searchCount = 0;
+
+	public long getTermSeq() {
+		return termSeq;
+	}
+
+	public void setTermSeq(long termSeq) {
+		this.termSeq = termSeq;
+	}
+
+	public String getTermId() {
+		return termId;
+	}
+
+	public void setTermId(String termId) {
+		this.termId = termId;
+	}
+
+	public String getKorean() {
+		return korean;
+	}
+
+	public void setKorean(String korean) {
+		this.korean = korean;
+	}
+
+	public String getEnglish() {
+		return english;
+	}
+
+	public void setEnglish(String english) {
+		this.english = english;
+	}
+
+	public String getEnglishAbbr() {
+		return englishAbbr;
+	}
+
+	public void setEnglishAbbr(String englishAbbr) {
+		this.englishAbbr = englishAbbr;
+	}
+
+	public String getTermDc() {
+		return termDc;
+	}
+
+	public void setTermDc(String termDc) {
+		this.termDc = termDc;
+	}
+
+	public String getUsingSystem() {
+		return usingSystem;
+	}
+
+	public void setUsingSystem(String usingSystem) {
+		this.usingSystem = usingSystem;
+	}
+
+	public String getCreateDate() {
+		return createDate;
+	}
+
+	public void setCreateDate(String createDate) {
+		this.createDate = createDate;
+	}
+
+	public String getCreateId() {
+		return createId;
+	}
+
+	public void setCreateId(String createId) {
+		this.createId = createId;
+	}
+
+	public String getUpdateDate() {
+		return updateDate;
+	}
+
+	public void setUpdateDate(String updateDate) {
+		this.updateDate = updateDate;
+	}
+
+	public String getUpdateId() {
+		return updateId;
+	}
+
+	public void setUpdateId(String updateId) {
+		this.updateId = updateId;
+	}
+
+	public boolean getIsUse() {
+		return isUse;
+	}
+
+	public void setIsUse(boolean isUse) {
+		this.isUse = isUse;
+	}
+
+	public boolean getIsStandard() {
+		return isStandard;
+	}
+
+	public void setIsStandard(boolean isStandard) {
+		this.isStandard = isStandard;
+	}
+
+	public boolean getIsMinistryStandard() {
+		return isMinistryStandard;
+	}
+
+	public void setIsMinistryStandard(boolean isMinistryStandard) {
+		this.isMinistryStandard = isMinistryStandard;
+	}
+
+	public int getOrders() {
+		return orders;
+	}
+
+	public void setOrders(int orders) {
+		this.orders = orders;
+	}
+	
+	public long getSearchCount() {
+		return searchCount;
+	}
+
+	public void setSearchCount(long searchCount) {
+		this.searchCount = searchCount;
+	}
+	
+	/**************************** Domain 원본 ****************************/
+
+	/**
+	 * 컬럼 ID
+	 */
+	private String columnId;
+	
+	/**
+	 * 해당 용어와 연결된 컬럼 목록입니다.
+	 */
+	private List<Column> columns = new ArrayList<Column>();
+
+	public List<Column> getColumns() {
+		return columns;
+	}
+
+	public void setColumns(List<Column> columns) {
+		this.columns = columns;
+	}
+
+	public String getColumnId() {
+		return columnId;
+	}
+
+	public void setColumnId(String columnId) {
+		this.columnId = columnId;
+	}
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/meta/term/vo/StandardTermSearch.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/meta/term/vo/StandardTermSearch.java
@@ -0,0 +1,102 @@
+package com.takensoft.taken_bi_manager.meta.term.vo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author 최정우
+ * @since 2019.11.13
+ * 
+ * 표준용어 검색 결과 VO 입니다.
+ */
+public class StandardTermSearch implements Serializable {
+
+	public StandardTermSearch() {}
+	
+	public StandardTermSearch(StandardTerm term) {
+		this.termSeqs = Long.toString(term.getTermSeq());
+		this.korean = term.getKorean();
+		this.english = term.getEnglish();
+		this.englishAbbr = term.getEnglishAbbr();
+		this.standardTermList.add(term);
+	}
+	
+	public StandardTermSearch(String termSeqs, String korean, String english, String englishAbbr, List<StandardTerm> standardTermList) {
+		this.termSeqs = termSeqs;
+		this.korean = korean;
+		this.english = english;
+		this.englishAbbr = englishAbbr;
+		this.standardTermList = standardTermList;
+	}
+	
+	/**
+	 * 시리얼 버전
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	private String termSeqs;
+	
+	/**
+	 * 표준용어 한글
+	 */
+	private String korean;
+
+	/**
+	 * 표준용어 영어
+	 */
+	private String english;
+	
+	/**
+	 * 표준용어 영어 약어
+	 */
+	private String englishAbbr;
+	
+	/**
+	 * 표준용어 목록
+	 */
+	private List<StandardTerm> standardTermList = new ArrayList<StandardTerm>();
+
+	
+	public String getTermSeqs() {
+		return termSeqs;
+	}
+
+	public void setTermSeqs(String termSeqs) {
+		this.termSeqs = termSeqs;
+	}
+
+	public String getKorean() {
+		return korean;
+	}
+
+	public void setKorean(String korean) {
+		this.korean = korean;
+	}
+
+	public String getEnglish() {
+		return english;
+	}
+
+	public void setEnglish(String english) {
+		this.english = english;
+	}
+
+	public String getEnglishAbbr() {
+		return englishAbbr;
+	}
+
+	public void setEnglishAbbr(String englishAbbr) {
+		this.englishAbbr = englishAbbr;
+	}
+
+	public List<StandardTerm> getStandardTermList() {
+		return standardTermList;
+	}
+
+	public void setStandardTermList(List<StandardTerm> standardTermList) {
+		this.standardTermList = standardTermList;
+	}
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/test/dao/TestDAO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/test/dao/TestDAO.java
@@ -0,0 +1,12 @@
+package com.takensoft.taken_bi_manager.test.dao;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.takensoft.taken_bi_manager.test.vo.TestVO;
+
+
+@Mapper
+public interface TestDAO {
+
+    public TestVO testSelectOne() throws Exception;
+}
 
src/main/java/com/takensoft/taken_bi_manager/test/service/TestService.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/test/service/TestService.java
@@ -0,0 +1,16 @@
+package com.takensoft.taken_bi_manager.test.service;
+
+import com.takensoft.taken_bi_manager.test.vo.TestVO;
+
+/**
+ *  테스트 중인 서비스
+ *
+ * @author 김성원
+ * @since 2023.12.28
+ */
+public interface TestService {
+
+
+    public TestVO testSelectOne() throws Exception;
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/test/service/impl/TestServiceImpl.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/test/service/impl/TestServiceImpl.java
@@ -0,0 +1,21 @@
+package com.takensoft.taken_bi_manager.test.service.impl;
+
+import com.takensoft.taken_bi_manager.test.dao.TestDAO;
+import com.takensoft.taken_bi_manager.test.service.TestService;
+import com.takensoft.taken_bi_manager.test.vo.TestVO;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TestServiceImpl implements TestService {
+
+  //  @Autowired
+  //  private TestDAO testDAO;
+
+    @Override
+    public TestVO testSelectOne() throws Exception {    	
+        return null;
+    }
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/test/vo/TestVO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/test/vo/TestVO.java
@@ -0,0 +1,11 @@
+package com.takensoft.taken_bi_manager.test.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class TestVO {
+
+    private String testId;
+}
 
src/main/java/com/takensoft/taken_bi_manager/test/web/TestController.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/test/web/TestController.java
@@ -0,0 +1,39 @@
+package com.takensoft.taken_bi_manager.test.web;
+
+import com.takensoft.taken_bi_manager.common.vo.CustomeResultMap;
+import com.takensoft.taken_bi_manager.test.service.TestService;
+import com.takensoft.taken_bi_manager.user.member.servie.LoginService;
+import com.takensoft.taken_bi_manager.user.member.servie.MemberService;
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+
+@RestController
+@RequestMapping("/test")
+public class TestController {
+
+	@Autowired
+    private MemberService memberService;	
+	
+	@Autowired
+    private LoginService loginService;	
+	
+    @Autowired
+    TestService testService;
+
+    @GetMapping(path = "/test1")
+    public CustomeResultMap TestRestApi(@ModelAttribute("member") Member member) throws Exception {
+
+    	//Member member = new Member();
+		//member.setUserId("admin");
+		//member.setUserPassword("qwer1234");
+		CustomeResultMap map = loginService.userLogin(member);
+		System.out.print(map.getCheckMessage().getMessage());   
+		
+        return map;
+    }
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/member/dao/LoginDAO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/member/dao/LoginDAO.java
@@ -0,0 +1,32 @@
+package com.takensoft.taken_bi_manager.user.member.dao;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+/**
+ * @author 김성원
+ * @since 2021.01.10
+ * 
+ * 로그인 처리 관련 DAO 클래스
+ */
+@Mapper
+public interface LoginDAO {
+	
+	/**
+	 * @author 김성원
+	 * @since 2021.01.10
+	 * 
+	 * 로그인 성공시 로직(비밀번호 카운트, 잠김 해재)
+	 */
+	 public int loginSuccess(Member member) throws Exception;
+	 
+	 /**
+	 * @author 김성원
+	 * @since 2021.01.10
+	 * 
+	 * 회원가입(패스워드 카운트 업 및 잠김 처리)
+	 */
+	 public int passowrdFail(Member member) throws Exception;
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/member/dao/MemberDAO.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/member/dao/MemberDAO.java
@@ -0,0 +1,24 @@
+package com.takensoft.taken_bi_manager.user.member.dao;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+/**
+ * @author 김성원
+ * @since 2023-12-28
+ * 
+ * 회원(개인) 관련된 SQL문에 접근하는 DAO Class
+ */
+@Mapper
+public interface MemberDAO {
+	
+	/**
+	 * @author 김성원
+	 * @since 2021.12.29
+	 * 
+	 * 회원정보 가져오기
+	 */
+	 public Member getMemnberById(String userId) throws Exception;
+
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/member/servie/LoginService.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/member/servie/LoginService.java
@@ -0,0 +1,24 @@
+package com.takensoft.taken_bi_manager.user.member.servie;
+
+import com.takensoft.taken_bi_manager.common.vo.CustomeResultMap;
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+public interface LoginService {
+
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 유저로그인 처리(userId, userPassword)
+	 */
+	public CustomeResultMap userLogin(Member member) throws Exception;	
+	
+	/**
+     * @author 김성원
+	 * @since 2024.01.10
+     *
+     * 세션 무효화 (로그아웃 처리)
+     */
+    public boolean userLogout() throws Exception;
+    
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/member/servie/MemberService.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/member/servie/MemberService.java
@@ -0,0 +1,80 @@
+package com.takensoft.taken_bi_manager.user.member.servie;
+
+import java.util.HashMap;
+import java.util.List;
+
+import com.takensoft.taken_bi_manager.common.vo.CheckMessage;
+import com.takensoft.taken_bi_manager.common.vo.CommonVO;
+import com.takensoft.taken_bi_manager.common.vo.CustomeResultMap;
+import com.takensoft.taken_bi_manager.common.vo.SearchVO;
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+public interface MemberService {
+	    
+    /**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 아이디로 멤버조회(userId)
+	 */
+	public Member getMemnberById(String userId) throws Exception;	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 회원가입(userId)
+	 */
+	public Member insertMember(Member member) throws Exception;	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.10
+	 * 
+	 * 회원정보 업데이트(Member)
+	 */
+	public Member updateMember(Member member) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.10
+	 * 
+	 * 회원삭제(Member)
+	 */
+	public Member deleteMember(Member member) throws Exception;
+
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 회원가입(userId)
+	 */
+	public List<Member> selectMemberList(SearchVO searchVO) throws Exception;	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 회원가입(userId)
+	 */
+	public long selectMemberListCount(SearchVO searchVO) throws Exception;		
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.10
+	 * 
+	 * 회원권한 부여(Member)
+	 */
+	public Member insertMemberAuth(Member member) throws Exception;
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.10
+	 * 
+	 * 회원권한 삭제(Member)
+	 */
+	public Member deleteMemberAuth(Member member) throws Exception;	
+	
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/member/servie/impl/LoginServiceImpl.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/member/servie/impl/LoginServiceImpl.java
@@ -0,0 +1,154 @@
+package com.takensoft.taken_bi_manager.user.member.servie.impl;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.takensoft.taken_bi_manager.common.util.AuthUtil;
+import com.takensoft.taken_bi_manager.common.util.CommonUtil;
+import com.takensoft.taken_bi_manager.common.util.CryptoUtil;
+import com.takensoft.taken_bi_manager.common.util.SesssionEventListener;
+import com.takensoft.taken_bi_manager.common.util.StringUtil;
+import com.takensoft.taken_bi_manager.common.vo.CustomeResultMap;
+import com.takensoft.taken_bi_manager.user.member.dao.LoginDAO;
+import com.takensoft.taken_bi_manager.user.member.dao.MemberDAO;
+import com.takensoft.taken_bi_manager.user.member.servie.LoginService;
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpSession;
+
+
+/**
+ * @author 김성원
+ * @since 2024.01.10
+ * 
+ * 로그인 관련 처리 서비스 클래스
+ */
+@Service
+public class LoginServiceImpl implements LoginService {
+
+	@Autowired
+    private MemberDAO memberDAO;
+	
+	@Autowired
+    private LoginDAO loginDAO;
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 유저로그인 처리(userId, userPassword)
+	 */
+	@Override
+	public CustomeResultMap userLogin(Member member) throws Exception {			
+		
+		// 결과맵 생성
+		CustomeResultMap resultMap = new CustomeResultMap();
+		
+		//사용자 정보 조회 
+		Member memebrInfo = memberDAO.getMemnberById(member.getUserId());
+		
+		// 사용자 정보 있음
+		if(memebrInfo != null && !StringUtil.isEmpty(memebrInfo.getUserId())){
+					
+			
+			// 사용자 정보 복호화
+			memebrInfo.dataDecoder();
+			
+			if(memebrInfo.isLockAt()) {
+				resultMap.getCheckMessage().setError("계정이 잠겨있습니다. 관리자에게 문의하세요");	
+				return resultMap;
+			}
+			
+			//비밀번호 비교 성공
+			if(CryptoUtil.passwordMatch(member.getUserPassword(), memebrInfo.getUserPassword())){
+				
+				/** 로그인 처리이후, 세션처리 (시작) **/
+	            //세션 무효화 처리
+				userLogout();
+				
+				//현재 로그인할 userId와 동일한 로그인 session을 가진 session ID 목록 조회
+	            List<String> sessionIds = SesssionEventListener.duplicationLoginSessionIdSelectListByUserId(member.getUserId());
+	           
+	            /**
+	             * 현재 로그인 요청한 userId와 동일한 접속 session이 1명 이상 있고,
+	             * 중복 로그인 가능 유무가 true이면 -> 중복 로그인 처리 진행
+	             * 중복 로그인 가능 유무가 false이면 -> 기존 로그인 유저를 session에서 제거
+	             */
+	            if (sessionIds.size() > 0 && AuthUtil.IS_POSSIBLE_DUPLICATION_LOGIN == false)  {
+	                //기존 로그인 유저 session에서 제거
+	                SesssionEventListener.duplicationLoginSessionDeleteByUserId(member.getUserId());
+	            }
+				
+				//현재 Http Request 객체 가지고 오기
+		        HttpServletRequest request = CommonUtil.getHttpServletRequest();
+				
+		        //기존 session이 존재하더라도 제거하고 새로운 세션 생성
+	            HttpSession session = request.getSession(true);
+	            
+	            //세션 timeout(30분)
+	            session.setMaxInactiveInterval(60 * 30); 
+	            
+	            // session 저장 정보 생성
+	            HashMap<String, Object> LoginUserInfo = new HashMap<>();	            
+	            LoginUserInfo.put("user_id", memebrInfo.getUserId());							//유저아이디
+	            LoginUserInfo.put("user_name", memebrInfo.getUserNm());							//유저이름
+	            LoginUserInfo.put("user_auth", memebrInfo.getAuthList());     					//권한리스트 
+	            LoginUserInfo.put("dept_name", memebrInfo.getDeptNm());      					//부서명
+	            
+	            // session 생성
+	            session.setAttribute(AuthUtil.LOGIN_USER_SESSION, LoginUserInfo);    
+	            resultMap.getCheckMessage().setMessage( memebrInfo.getUserId() + "님 환영합니다.");	            
+	            
+	            // 성공로직 아래에 만들기 
+	            loginDAO.loginSuccess(member);  
+	            
+			}
+			// 실패
+			else {	
+				// 로그인 비밀번호 실패카운트
+				memebrInfo.setLoginFailrCnt(memebrInfo.getLoginFailrCnt() + 1);
+				
+				if(memebrInfo.getLoginFailrCnt() ==5) {
+					memebrInfo.setLockAt(true);
+				}
+				
+				resultMap.getCheckMessage().setError("비밀번호 불일치 "+memebrInfo.getLoginFailrCnt()+"회, 5회 실패시 계정이 잠깁니다." );						
+				// 비밀번호 실패 업데이트 로직 	
+				 loginDAO.passowrdFail(memebrInfo);  
+			}
+			
+							
+		}else {
+			resultMap.getCheckMessage().setError("일치하는 정보가 없습니다. \\r\\n사용자 정보를 확인해 주세요");		
+		}				
+		
+		return resultMap;
+	}
+
+	/**
+     * @author 김성원
+	 * @since 2024.01.10
+     *
+     * 세션 무효화 (로그아웃 처리)
+     */
+	@Override
+	public boolean userLogout() throws Exception {
+
+		//현재 Http Request 객체 가지고 오기
+        HttpServletRequest request = CommonUtil.getHttpServletRequest();
+        //기존 session이 존재하면 session값을 받아오고, 존재하지 않으면 null
+        HttpSession session = request.getSession(false);
+        //기존 session이 존재하면 -> session 삭제
+        if (session != null) {
+            //session 삭제
+            session.invalidate();
+        }
+
+		return false;
+	}
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/member/servie/impl/MemberServiceImpl.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/member/servie/impl/MemberServiceImpl.java
@@ -0,0 +1,82 @@
+package com.takensoft.taken_bi_manager.user.member.servie.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.takensoft.taken_bi_manager.common.vo.CommonVO;
+import com.takensoft.taken_bi_manager.common.vo.SearchVO;
+import com.takensoft.taken_bi_manager.user.member.dao.MemberDAO;
+import com.takensoft.taken_bi_manager.user.member.servie.MemberService;
+import com.takensoft.taken_bi_manager.user.member.vo.Member;
+
+
+/**
+ * @author 김성원
+ * @since 2024.01.10
+ * 
+ * member 관련 처리 서비스 로직 
+ */
+@Service
+public class MemberServiceImpl implements MemberService {
+
+	@Autowired
+    private MemberDAO memberDAO;	
+
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 아이디로 멤버조회(userId)
+	 */
+	@Override
+	public Member getMemnberById(String userId) throws Exception {		
+		Member member =  memberDAO.getMemnberById(userId);
+		member.dataDecoder();
+		return member;
+	}	
+
+	@Override
+	public Member insertMember(Member member) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Member updateMember(Member member) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Member deleteMember(Member member) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public List<Member> selectMemberList(SearchVO searchVO) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public long selectMemberListCount(SearchVO searchVO) throws Exception {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public Member insertMemberAuth(Member member) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Member deleteMemberAuth(Member member) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/member/vo/Member.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/member/vo/Member.java
@@ -0,0 +1,122 @@
+package com.takensoft.taken_bi_manager.user.member.vo;
+
+import java.sql.Date;
+import java.sql.Timestamp;
+import java.util.List;
+
+import com.takensoft.taken_bi_manager.common.util.CryptoUtil;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2023-12-28
+ * 
+ * 회원정보 객체 
+ */
+@Getter
+@Setter
+public class Member {
+
+	// 사용자 ID
+	private String userId;
+	
+	// 사용자 비밀번호
+	private String userPassword;
+	
+	// 사용자 이름
+	private String userNm;
+	
+	// 사용자 이메일
+	private String userEmail;
+	
+	// 사용자 전화번호
+	private String userTel;
+	
+	// 사용자 휴대폰 번호
+	private String userPhone;
+	
+	// 사용자 우편번호
+	private String zipCode;
+	
+	// 사용자 주소 
+	private String adres;
+	
+	// 사용자 상세주소 
+	private String adresDetail;
+	
+	// 사용자 성별 
+	private String gender;
+	
+	// 사용자 생년월일
+	private Date BirthDt;
+	
+	// 생성일
+	private Timestamp creatDt;
+	
+	// 생성자ID
+	private String creatId;
+	
+	// 수정일 
+	private Timestamp updtDt;
+		
+	// 수정자 ID
+	private String updtId;
+	
+	// 사용자 로그인 잠김 여부 
+	private boolean lockAt;
+	
+	// 사용자 로그인 잠김 일시
+	private Timestamp lockDt;
+	
+	// 사용자 로그인 실패 카운트 
+	private int loginFailrCnt;	
+	
+	// 현재 부서명  
+	private String deptNm;
+	
+	// 권한 리스트 
+	private List<String> authList;
+	
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 사용자 비번 암호화 
+	 */
+	public void PasswordEncoder() {
+		this.userPassword = CryptoUtil.PasswordEncoder(this.userPassword);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 사용자 정보 암호화 
+	 */
+	public void dataEncoder() {		
+		this.userPhone = CryptoUtil.encryptData(this.userPhone);
+		this.userTel = CryptoUtil.encryptData(this.userTel);
+		this.userEmail = CryptoUtil.encryptData(this.userEmail);
+		this.adres = CryptoUtil.encryptData(this.adres);
+		this.adresDetail = CryptoUtil.encryptData(this.adresDetail);
+	}
+	
+	/**
+	 * @author 김성원
+	 * @since 2024.01.09
+	 * 
+	 * 사용자 정보 복호화 
+	 */
+	public void dataDecoder() {		
+		this.userPhone = CryptoUtil.decryptData(this.userPhone);
+		this.userTel = CryptoUtil.decryptData(this.userTel);
+		this.userEmail = CryptoUtil.decryptData(this.userEmail);
+		this.adres = CryptoUtil.decryptData(this.adres);
+		this.adresDetail = CryptoUtil.decryptData(this.adresDetail);
+	}
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/member/vo/MemberHistory.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/member/vo/MemberHistory.java
@@ -0,0 +1,40 @@
+package com.takensoft.taken_bi_manager.user.member.vo;
+
+import java.sql.Date;
+import java.sql.Timestamp;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2023-12-28
+ * 
+ * 회원정보 객체 
+ */
+@Getter
+@Setter
+public class MemberHistory {
+
+	// 사용자 ID
+	private String userId;	
+	
+	// 사용자 이름
+	private String userNm;
+	
+	// 사용자 이메일
+	private String userEmail;
+	
+	// 사용자 전화번호
+	private String userTel;
+	
+	// 사용자 휴대폰 번호
+	private String userPhone;	
+	
+	// 생성일
+	private Timestamp creatDt;
+	
+	// 부서명
+	private String deptCode;
+		
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/org/vo/Organization.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/org/vo/Organization.java
@@ -0,0 +1,56 @@
+package com.takensoft.taken_bi_manager.user.org.vo;
+
+import java.sql.Date;
+import java.sql.Timestamp;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2023-12-28
+ * 
+ * 부서정보 객체 
+ */
+@Getter
+@Setter
+public class Organization {
+
+	// 부서코드(pk)
+	private String deptCode;
+	
+	// 상위부서 코드
+	private String upperDept;
+	
+	// 조직 코드(최상위 부서?)
+	private String orgCode;
+	
+	// 부서명 
+	private String deptNm;
+	
+	// 부서명 설명
+	private String deptDc;
+	
+	// 부서 깊이 
+	private int deptDp;
+	
+	// 부서 정렬 순서
+	private int dept_ordr;
+	
+	// 사용여부
+	private boolean useAt;
+	
+	// 생성일
+	private Timestamp creatDt;
+	
+	// 생성자ID
+	private String creatId;
+	
+	// 수정일 
+	private Timestamp updtDt;
+		
+	// 수정자 ID
+	private String updtId;
+	
+	
+}
 
src/main/java/com/takensoft/taken_bi_manager/user/org/vo/OrganizationHistory.java (added)
+++ src/main/java/com/takensoft/taken_bi_manager/user/org/vo/OrganizationHistory.java
@@ -0,0 +1,43 @@
+package com.takensoft.taken_bi_manager.user.org.vo;
+
+import java.sql.Date;
+import java.sql.Timestamp;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author 김성원
+ * @since 2023-12-28
+ * 
+ * 부서변경정보 객체 
+ */
+@Getter
+@Setter
+public class OrganizationHistory {
+
+	// 부서코드(pk)
+	private String deptCode;
+	
+	// 상위부서 코드
+	private String upperDept;
+	
+	// 조직 코드(최상위 부서?)
+	private String orgCode;
+	
+	// 이전 부서명 
+	private String beforDeptNm;
+	
+	// 현재 부서설명
+	private String deptNm;	
+	
+	// 부서 깊이 
+	private int deptDp;
+	
+	// 부서 정렬 순서
+	private int dept_ordr;
+	
+	// 수정일 
+	private Timestamp updtDt;		
+	
+}
 
src/main/resources/application.properties (added)
+++ src/main/resources/application.properties
@@ -0,0 +1,14 @@
+#server default
+server.port = 9090
+
+#Datasource Configuration
+spring.datasource.hikari.maximum-pool-size=4
+spring.datasource.url=jdbc:postgresql://210.180.118.83:5432/bi_manager?currentSchema=bi_manager
+spring.datasource.username=takensoft
+spring.datasource.password=tts64103165!@
+spring.sql.init.platform=postgres
+
+
+# Mapper Xml Location
+mybatis.mapper-locations=classpath:/spring/mapper/**/*-SQL.xml
+mybatis.config-location=classpath:/spring/mapper/mybatis-config.xml(No newline at end of file)
 
src/main/resources/spring/mapper/mybatis-config.xml (added)
+++ src/main/resources/spring/mapper/mybatis-config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
+        "http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+    <settings>
+        <setting name="cacheEnabled" value="true"/> <!-- mapper 캐시 전역 사용여부 -->
+        <setting name="lazyLoadingEnabled" value="false"/> <!-- mybatis 지연 로딩 사용여부 -->
+        <setting name="multipleResultSetsEnabled" value="true"/> <!-- 한개의 구문에서 여러개의  ResultSet 허용 여부 -->
+        <setting name="useColumnLabel" value="true"/> <!-- 컬럼명 대신 컬럼라벨 사용 여부 -->
+        <setting name="useGeneratedKeys" value="false"/> <!-- 키자동생성 -->
+        <setting name="defaultExecutorType" value="SIMPLE"/>
+        <setting name="defaultStatementTimeout" value="25000"/>
+        <setting name="callSettersOnNulls" value="true"/>
+    </settings>
+
+
+    <typeAliases>      
+        <typeAlias type="com.takensoft.taken_bi_manager.test.vo.TestVO" alias="TestVO"/>
+        <!-- 검색 객체 -->
+        <typeAlias type="com.takensoft.taken_bi_manager.common.vo.SearchVO" alias="SearchVO"/>
+        <!-- 회원정보 객체 -->
+        <typeAlias type="com.takensoft.taken_bi_manager.user.member.vo.Member" alias="Member"/>        
+    </typeAliases>
+
+</configuration>(No newline at end of file)
 
src/main/resources/spring/mapper/postgres/test-SQL.xml (added)
+++ src/main/resources/spring/mapper/postgres/test-SQL.xml
@@ -0,0 +1,11 @@
+<?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.takensoft.taken_bi_manager.test.dao.TestDAO">
+	
+    <select id="testSelectOne" resultType="testVO">
+        SELECT 'testId' as "testId"
+    </select>
+    
+</mapper>(No newline at end of file)
 
src/main/resources/spring/mapper/user/login-SQL.xml (added)
+++ src/main/resources/spring/mapper/user/login-SQL.xml
@@ -0,0 +1,30 @@
+<?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.takensoft.taken_bi_manager.user.member.dao.LoginDAO">
+	
+	<!-- 로그인 성공처리 -->
+    <update id="loginSuccess" parameterType="Member">
+		UPDATE user_info
+		SET 
+		  login_failr_cnt = 0
+		 ,lock_at = '0'		
+		WHERE 	 
+        user_id = #{userId}   			
+	</update>
+	
+	<!-- 로그인 실패처리 -->
+	<update id="passowrdFail" parameterType="Member">
+		UPDATE user_info
+		SET 
+		  login_failr_cnt = #{loginFailrCnt}
+		 ,lock_at = #{lockAt}	
+		 <if test="loginFailrCnt != null and loginFailrCnt > 4">
+			 ,lock_dt = current_timestamp
+		 </if>
+		WHERE 	 
+        user_id = #{userId}   			
+	</update>
+    
+</mapper>(No newline at end of file)
 
src/main/resources/spring/mapper/user/member-SQL.xml (added)
+++ src/main/resources/spring/mapper/user/member-SQL.xml
@@ -0,0 +1,79 @@
+<?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.takensoft.taken_bi_manager.user.member.dao.MemberDAO">
+	
+	<resultMap id="memberResult" type="Member">
+		<result property="userId" column="user_id"/>
+		<result property="userPassword" column="user_password"/>
+		<result property="userNm" column="user_nm"/>
+		<result property="userEmail" column="user_email"/>
+		<result property="userTel" column="user_tel"/>
+		<result property="userPhone" column="user_phone"/>
+		<result property="zipCode" column="zip_code"/>
+		<result property="adres" column="adres"/>
+		<result property="adresDetail" column="adres_dtail"/>
+		<result property="gender" column="gender"/>
+		<result property="BirthDt" column="birth_dt"/>
+		<result property="dept_nm" column="deptNm"/>		
+		<result property="creatDt" column="creat_dt"/>		
+		<result property="updtDt" column="updt_dt"/>		
+		<result property="creatId" column="creat_id"/>
+		<result property="updtId" column="updt_id"/>	
+		<result property="loginFailrCnt" column="login_failr_cnt"/>
+		<result property="lockAt" column="lock_at"/>
+		<result property="lockDt" column="lock_dt"/>	
+		<collection property="authList" column="user_id" javaType="java.util.ArrayList" ofType="String" select="getAuthList" />
+	</resultMap>
+		
+		
+	<!-- 로그인 아이디로 회원 조회. -->
+    <select id="getMemnberById" parameterType="String" resultMap="memberResult">
+      	SELECT 
+      	   ui.user_id
+      	 , user_password
+      	 , user_nm
+      	 , user_email
+      	 , user_tel
+      	 , user_phone
+      	 , zip_code
+      	 , adres
+      	 , adres_dtail
+      	 , oi.dept_nm 
+      	 , ui.creat_dt
+      	 , ui.updt_dt      	
+      	 , ui.creat_id
+      	 , ui.updt_id
+      	 , gender
+      	 , birth_dt
+      	 , login_failr_cnt
+      	 , lock_at
+      	 , lock_dt      	 
+  	   FROM 
+  	   	 user_info ui 
+  	   	 left join orgnzt_member om on ui.user_id  = om.user_id 
+  	   	 left join orgnzt_info oi on om.dept_code = oi.dept_code 
+       WHERE 	 
+         ui.user_id =  #{userId}       
+    </select>
+    
+    
+    <!-- 사용자 부서 및 본인 권한 리스트 가져오기 -->
+    <select id="getAuthList" parameterType="String" resultType="String">
+		SELECT 
+			author
+		FROM 
+		user_author ua 
+		WHERE 
+			ua.user_id = #{user_id}
+		UNION 
+		SELECT 
+			author 
+		FROM 
+		orgnzt_member om 
+		LEFT JOIN orgnzt_author oa on om.dept_code = oa.dept_code 
+		WHERE om.user_id = #{user_id}
+	</select>
+    
+</mapper>(No newline at end of file)
 
src/main/resources/static/index.html (added)
+++ src/main/resources/static/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+    good
+</body>
+</html>(No newline at end of file)
 
src/main/webapp/META-INF/MANIFEST.MF (added)
+++ src/main/webapp/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+
 
src/test/java/com/takensoft/taken_bi_manager/TakenBiManagerApplicationTests.java (added)
+++ src/test/java/com/takensoft/taken_bi_manager/TakenBiManagerApplicationTests.java
@@ -0,0 +1,13 @@
+package com.takensoft.taken_bi_manager;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TakenBiManagerApplicationTests {
+
+	@Test
+	void contextLoads() {
+	}
+
+}
Add a comment
List