박정하 박정하 01-08
250108 박정하 최초 커밋
@5348208f7d5b018e92b1bd79bc95cded20474f83
 
.gitignore (added)
+++ .gitignore
@@ -0,0 +1,32 @@
+HELP.md
+target/
+### 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/(파일 끝에 줄바꿈 문자 없음)
 
pom.xml (added)
+++ pom.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>com.takensoft</groupId>
+	<artifactId>cms</artifactId>
+	<packaging>jar</packaging>
+	<version>1.0.0</version>
+	<name>cms</name>
+	<url>http://www.egovframe.go.kr</url>
+
+	<licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+        </license>
+    </licenses>
+
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>2.7.12</version>
+	</parent>
+
+	<properties>
+	    <spring.maven.artifact.version>5.3.27</spring.maven.artifact.version>
+		<org.egovframe.rte.version>4.2.0</org.egovframe.rte.version>
+	</properties>
+
+	<repositories>
+        <repository>
+            <id>mvn2s</id>
+            <url>https://repo1.maven.org/maven2/</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+			<id>egovframe</id>
+			<url>https://maven.egovframe.go.kr/maven/</url>
+			<releases>
+				<enabled>true</enabled>
+			</releases>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+    </repositories>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+			<exclusions>
+				<exclusion>
+					<groupId>org.springframework.boot</groupId>
+					<artifactId>spring-boot-starter-logging</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-thymeleaf</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-validation</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-devtools</artifactId>
+			<optional>true</optional>
+		</dependency>
+
+		<!-- 표준프레임워크 실행환경 -->
+        <dependency>
+		    <groupId>org.egovframe.rte</groupId>
+		    <artifactId>org.egovframe.rte.ptl.mvc</artifactId>
+		    <version>${org.egovframe.rte.version}</version>
+        </dependency>
+        <dependency>
+		    <groupId>org.egovframe.rte</groupId>
+		    <artifactId>org.egovframe.rte.psl.dataaccess</artifactId>
+		    <version>${org.egovframe.rte.version}</version>
+        </dependency>
+        <dependency>
+			<groupId>org.egovframe.rte</groupId>
+			<artifactId>org.egovframe.rte.fdl.idgnr</artifactId>
+			<version>${org.egovframe.rte.version}</version>
+		</dependency>
+       	<dependency>
+			<groupId>org.egovframe.rte</groupId>
+			<artifactId>org.egovframe.rte.fdl.property</artifactId>
+			<version>${org.egovframe.rte.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.hsqldb</groupId>
+			<artifactId>hsqldb</artifactId>
+			<version>2.7.2</version>
+			<classifier>jdk8</classifier>
+		</dependency>
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<version>1.18.28</version>
+			<optional>true</optional>
+		</dependency>
+		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-entitymanager</artifactId>
+			<version>5.6.15.Final</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+		<!--                                           추가                                           -->
+		<dependency>
+			<groupId>org.mybatis.spring.boot</groupId>
+			<artifactId>mybatis-spring-boot-starter</artifactId>
+			<version>2.2.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-security</artifactId>
+			<version>3.2.4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-cache</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.github.ben-manes.caffeine</groupId>
+			<artifactId>caffeine</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<version>8.0.23</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mariadb.jdbc</groupId>
+			<artifactId>mariadb-java-client</artifactId>
+			<version>2.6.2</version>
+		</dependency>
+
+		<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
+		<dependency>
+			<groupId>org.postgresql</groupId>
+			<artifactId>postgresql</artifactId>
+			<version>42.6.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.bgee.log4jdbc-log4j2</groupId>
+			<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
+			<version>1.16</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml</artifactId>
+			<version>4.1.2</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt-api</artifactId>
+			<version>0.12.5</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt-impl</artifactId>
+			<version>0.12.5</version>
+			<scope>runtime</scope>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson -->
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt-jackson</artifactId>
+			<version>0.12.5</version>
+			<scope>runtime</scope>
+		</dependency>
+
+		<!--                                           추가                                           -->
+		<!-- HTML 엔티티를 처리 관련 https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-lang3</artifactId>
+			<version>3.14.0</version>
+		</dependency>
+
+		<!-- oracle  추가 -->
+		<dependency>
+			<groupId>com.oracle.database.jdbc</groupId>
+			<artifactId>ojdbc10</artifactId>
+			<version>19.16.0.0</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<excludes>
+						<exclude>
+							<groupId>org.projectlombok</groupId>
+							<artifactId>lombok</artifactId>
+						</exclude>
+					</excludes>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
 
src/main/java/com/takensoft/CmsApplication.java (added)
+++ src/main/java/com/takensoft/CmsApplication.java
@@ -0,0 +1,16 @@
+package com.takensoft;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+//@MapperScan(basePackages="com.takensoft.*.*.dao, com.takensoft.*.*.*.dao")
+@EnableScheduling
+public class CmsApplication {
+
+	public static void main(String[] args) {
+      SpringApplication.run(CmsApplication.class, args);
+	}
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/accesCtrl/dao/AccesCtrlDAO.java (added)
+++ src/main/java/com/takensoft/cms/accesCtrl/dao/AccesCtrlDAO.java
@@ -0,0 +1,60 @@
+package com.takensoft.cms.accesCtrl.dao;
+
+import com.takensoft.cms.accesCtrl.vo.AccesCtrlVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 접근 제어 관련 Mapper
+ */
+@Mapper("accesCtrlDAO")
+public interface AccesCtrlDAO {
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 등록
+     */
+    int save(AccesCtrlVO accesCtrlVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 접근 제어 수정
+     */
+    int update(AccesCtrlVO accesCtrlVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.12
+     * 접근 제어 조회(관리자 페이지용)
+     */
+    List<AccesCtrlVO> findAll(Pagination pagination);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.12
+     * 접근제어 목록 갯수(관리자 페이지용)
+     */
+    int findAllCnt(Pagination pagination);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.12
+     * 접근 제어 조회(관시스템용 - 시큐리티 접근 제어)
+     */
+    List<AccesCtrlVO> findAllAccesCtrlSecurity(String ip);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.12
+     * 접근 제어 상세 조회
+     */
+    AccesCtrlVO findByAccesCtrl(int acsCntrlId);
+
+}
 
src/main/java/com/takensoft/cms/accesCtrl/service/AccesCtrlService.java (added)
+++ src/main/java/com/takensoft/cms/accesCtrl/service/AccesCtrlService.java
@@ -0,0 +1,52 @@
+package com.takensoft.cms.accesCtrl.service;
+
+import com.takensoft.cms.accesCtrl.vo.AccesCtrlVO;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 접근 제어 정보 관련 인터페이스
+ */
+public interface AccesCtrlService {
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 등록
+     */
+    public Map<String, Object> accesCtrlSave(AccesCtrlVO accesCtrlVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 접근 제어 수정
+     */
+    public int accesCtrlUpdate(AccesCtrlVO accesCtrlVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.12
+     * 접근 제어 조회(관리자 페이지용)
+     */
+    public Map<String, Object> findAll(Map<String, String> params) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 조회(관시스템용 - 시큐리티 접근 제어)
+     */
+    public List<AccesCtrlVO> findAllAccesCtrlSecurity(String ip) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 상세 조회
+     */
+    public Map<String, Object> findByAccesCtrl(int acsCntrlId) throws Exception;
+}
 
src/main/java/com/takensoft/cms/accesCtrl/service/Impl/AccesCtrlServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/accesCtrl/service/Impl/AccesCtrlServiceImpl.java
@@ -0,0 +1,122 @@
+package com.takensoft.cms.accesCtrl.service.Impl;
+
+import com.takensoft.cms.accesCtrl.dao.AccesCtrlDAO;
+import com.takensoft.cms.accesCtrl.service.AccesCtrlService;
+import com.takensoft.cms.accesCtrl.vo.AccesCtrlVO;
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 접근 제어 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * AccesCtrlService : 접근 제어 관련 인터페이스 상속
+ */
+@Service("accesCtrlService")
+@RequiredArgsConstructor
+public class AccesCtrlServiceImpl extends EgovAbstractServiceImpl implements AccesCtrlService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AccesCtrlServiceImpl.class);
+    private final JWTUtil jwtUtil;
+    private final AccesCtrlDAO accesCtrlDAO;
+    private final CodeManageService codeManageService;
+
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 등록
+     */
+    @Override
+    @CacheEvict(value = "routerAccesCheck", allEntries = true)
+    public Map<String, Object> accesCtrlSave(AccesCtrlVO accesCtrlVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        accesCtrlVO.setRgtr(jwtUtil.getWriter());
+        int saveResult = accesCtrlDAO.save(accesCtrlVO);
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("result", saveResult);
+        result.put("acsCntrlId", accesCtrlVO.getAcsCntrlId());
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 접근 제어 수정
+     */
+    @Override
+    @CacheEvict(value = "routerAccesCheck", allEntries = true)
+    public int accesCtrlUpdate(AccesCtrlVO accesCtrlVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        accesCtrlVO.setMdfr(jwtUtil.getWriter());
+        return accesCtrlDAO.update(accesCtrlVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.12
+     * 접근 제어 조회(관리자 페이지용)
+     */
+    @Override
+    public Map<String, Object> findAll(Map<String, String> params) throws Exception {
+        Map<String, Object> result = new HashMap<String, Object>(); // 반환 객체 생성
+        Pagination search = new Pagination(0, params); // 검색조건 객체 생성
+        int cnt = accesCtrlDAO.findAllCnt(search); // 게시물 갯수
+        Pagination pagination = new Pagination(cnt, params); // 게시물 갯수 조회 후 검색조건 객쳄 초기화
+        List<AccesCtrlVO> list = accesCtrlDAO.findAll(pagination); // 목록 조회
+        List<CodeManageVO> codeList = codeManageService.findByChildCdCache("acsCntrlGroup"); // 검색 조건
+
+        result.put("list", list);
+        result.put("pagination", pagination);
+        result.put("codeList", codeList);
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 조회(관시스템용 - 시큐리티 접근 제어)
+     */
+    @Override
+    @Cacheable(value = "routerAccesCheck", key = "#ip")
+    public List<AccesCtrlVO> findAllAccesCtrlSecurity(String ip) throws Exception {
+        return accesCtrlDAO.findAllAccesCtrlSecurity(ip);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 상세 조회
+     */
+    @Override
+    public Map<String, Object> findByAccesCtrl(int acsCntrlId) throws Exception {
+        Map<String, Object> result = new HashMap<String, Object>(); // 반환 객체 생성
+        AccesCtrlVO accesCtrl = new AccesCtrlVO();
+        if(acsCntrlId != 0) {
+            accesCtrl = accesCtrlDAO.findByAccesCtrl(acsCntrlId);
+        }
+        List<CodeManageVO> codeList = codeManageService.findByChildCdCache("accesGroup"); // 수정 및 등록에 필요한 접근제어 종류 조회
+
+        result.put("accesCtrl", accesCtrl);
+        result.put("codeList", codeList);
+
+        return result;
+    }
+
+
+}
 
src/main/java/com/takensoft/cms/accesCtrl/service/Impl/SystemAccesCtrlServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/accesCtrl/service/Impl/SystemAccesCtrlServiceImpl.java
@@ -0,0 +1,88 @@
+package com.takensoft.cms.accesCtrl.service.Impl;
+
+import com.takensoft.cms.accesCtrl.service.AccesCtrlService;
+import com.takensoft.cms.accesCtrl.service.SystemAccesCtrlService;
+import com.takensoft.cms.accesCtrl.vo.AccesCtrlVO;
+import com.takensoft.common.util.CommonUtils;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+import org.springframework.util.AntPathMatcher;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.20
+ *
+ * 시스템 접근 제어 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * AuthorService : 시스템 접근 제어 관련 인터페이스 상속
+ */
+@Service("systemAccesCtrlService")
+@RequiredArgsConstructor
+public class SystemAccesCtrlServiceImpl extends EgovAbstractServiceImpl implements SystemAccesCtrlService {
+
+    private final CommonUtils commonUtils;
+    private final AccesCtrlService accesCtrlService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 조회(시스템용 - 라우터)
+     */
+    @Override
+    public boolean routerAccesCheck(Map params, HttpServletRequest req) throws Exception {
+        String ipAdrs = commonUtils.getIp(req); // 아이피 정보
+        String path = params.get("path").toString(); // 접근 경로
+        // 공통 접근 경로인 경우
+        if(isPath(path, "/cmmn/**")) {
+            return true;
+        }
+
+        List<AccesCtrlVO> list = accesCtrlService.findAllAccesCtrlSecurity(ipAdrs); // 접근 제어 정보 조회
+
+        // 관리자 경로 접근 검증
+        if(isPath(path, "/adm/**")) {
+            // 관리자 페이지로 접속하였으나 접근 제어 정보가 없을 경우
+            if(list.isEmpty()) {
+                return false;
+            }
+        }
+        return matches(list, path);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.05.29
+     * @param accesCtrlList : 해당 아이피의 접근 제어 정보
+     * @param path : 현재 접근 경로
+     * 접근 여부 확인
+     */
+    private boolean matches(List<AccesCtrlVO> accesCtrlList, String path) throws Exception {
+        AntPathMatcher matcher = new AntPathMatcher();
+        for(AccesCtrlVO vo : accesCtrlList) {
+            if(matcher.match(vo.getCntrlCrs(), path)) {
+                return "permit".equals(vo.getCntrlType()); // 접근 허용일 경우 true, 그 외 false
+            }
+        }
+        if(matcher.match("/adm/**", path)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.05.29
+     * @param path : 현재 접근 경로
+     * @param url : 확인 경로
+     * 경로 확인
+     */
+    private boolean isPath(String path, String url) {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(url, path);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/accesCtrl/service/SystemAccesCtrlService.java (added)
+++ src/main/java/com/takensoft/cms/accesCtrl/service/SystemAccesCtrlService.java
@@ -0,0 +1,20 @@
+package com.takensoft.cms.accesCtrl.service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 시스템 접근 제어 정보 관련 인터페이스
+ */
+public interface SystemAccesCtrlService {
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 접근 제어 조회(시스템용 - 라우터)
+     */
+    public boolean routerAccesCheck(Map params, HttpServletRequest req) throws Exception;
+}
 
src/main/java/com/takensoft/cms/accesCtrl/vo/AccesCtrlVO.java (added)
+++ src/main/java/com/takensoft/cms/accesCtrl/vo/AccesCtrlVO.java
@@ -0,0 +1,65 @@
+package com.takensoft.cms.accesCtrl.vo;
+
+import com.takensoft.common.Pagination;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.HashMap;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 접근 제어 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class AccesCtrlVO {
+    /**
+     * 접근 제어 아이디
+     */
+    private int acsCntrlId;
+    /**
+     * 제어 유형
+     * 공통코드 값 등록 - permit: 허용, limit: 제한
+     */
+    private String cntrlType;
+
+    /**
+     * 제어 유형명
+     */
+    private String cntrlTypeNm;
+
+    /**
+     * 제어 아이피
+     */
+    private String cntrlIp;
+    /**
+     * 제어 경로
+     */
+    private String cntrlCrs;
+    /**
+     * 사용여부
+     */
+    private String useYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+}
 
src/main/java/com/takensoft/cms/accesCtrl/web/AccesCtrlController.java (added)
+++ src/main/java/com/takensoft/cms/accesCtrl/web/AccesCtrlController.java
@@ -0,0 +1,170 @@
+package com.takensoft.cms.accesCtrl.web;
+
+import com.takensoft.cms.accesCtrl.service.AccesCtrlService;
+import com.takensoft.cms.accesCtrl.vo.AccesCtrlVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 접근 제어 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value = "/admin/accesCtrl")
+public class AccesCtrlController {
+
+    private final AccesCtrlService accesCtrlService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * @param accesCtrlVO
+     * @return
+     * @throws Exception
+     *
+     * 접근제어 등록
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> saveProc(@RequestBody AccesCtrlVO accesCtrlVO) throws Exception {
+
+        Map<String, Object> result = accesCtrlService.accesCtrlSave(accesCtrlVO);
+        int saveResult = (int) result.get("result");
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(saveResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param params
+     * @return
+     * @throws Exception
+     *
+     * 접근제어 목록 조회
+     */
+    @PostMapping("/findAll.json")
+    public ResponseEntity<?> findAll(@RequestBody Map<String, String> params) throws Exception {
+
+        // 접근제어 목록 관련 정보 조회
+        Map<String, Object> result = accesCtrlService.findAll(params);
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param accesCtrlVO
+     * @return
+     * @throws Exception
+     *
+     * 접근제어 상세 조회
+     */
+    @PostMapping("/findByAcces.json")
+    public ResponseEntity<?> findByAcces(@RequestBody AccesCtrlVO accesCtrlVO) throws Exception {
+        // 상세 조회
+        Map<String, Object> result = accesCtrlService.findByAccesCtrl(accesCtrlVO.getAcsCntrlId());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param accesCtrlVO
+     * @return
+     * @throws Exception
+     *
+     * 접근제어 수정
+     */
+    @PostMapping("/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody AccesCtrlVO accesCtrlVO) throws Exception {
+        // 접근제어 수정 처리
+        int result = accesCtrlService.accesCtrlUpdate(accesCtrlVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param accesCtrlVO
+     * @return
+     * @throws Exception
+     *
+     * 접근제어 삭제
+     */
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody AccesCtrlVO accesCtrlVO) throws Exception {
+        // 접근제어 삭제 처리
+        int result = accesCtrlService.accesCtrlUpdate(accesCtrlVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/accesCtrl/web/SystemAccesCtrlController.java (added)
+++ src/main/java/com/takensoft/cms/accesCtrl/web/SystemAccesCtrlController.java
@@ -0,0 +1,58 @@
+package com.takensoft.cms.accesCtrl.web;
+
+import com.takensoft.cms.accesCtrl.service.AccesCtrlService;
+import com.takensoft.cms.accesCtrl.service.SystemAccesCtrlService;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.Charset;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.20
+ *
+ * 접근 제어 확인 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value = "/sys/accesCtrl")
+public class SystemAccesCtrlController {
+
+    private final SystemAccesCtrlService systemAccesCtrlService;
+
+    /**
+     * @author takensoft
+     * @since 2024.05.20
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 접근 제어 관련 사용자 확인
+     */
+    @PostMapping(value = "/accessCheck.json")
+    public ResponseEntity<?> accessCheck(@RequestBody Map params, HttpServletRequest req) throws Exception {
+        boolean result = systemAccesCtrlService.routerAccesCheck(params, req);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("검증");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+}
 
src/main/java/com/takensoft/cms/author/dao/AuthorDAO.java (added)
+++ src/main/java/com/takensoft/cms/author/dao/AuthorDAO.java
@@ -0,0 +1,66 @@
+package com.takensoft.cms.author.dao;
+
+import com.takensoft.cms.author.dto.AuthorDTO;
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 권한 정보 관련 Mapper
+ */
+@Mapper("authorDAO")
+public interface AuthorDAO {
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한코드 중복 검사
+     */
+    boolean findByCheckAuthorCode(AuthorVO authorVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 전체 권한 목록 조회(신규 메뉴 등록 시 권한을 주기 위해 사용)
+     */
+    List<AuthorVO> findAllSystem();
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 목록 조회
+     */
+    List<AuthorVO> findAll(Pagination pagination);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 권한 목록 갯수
+     */
+    int findAllCnt(Pagination pagination);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 상세 조회
+     */
+    AuthorVO findByAuthorCode(String authrtCd);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 등록
+     */
+    int save(AuthorVO authorVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 수정
+     */
+    int update(AuthorVO authorVO);
+}
 
src/main/java/com/takensoft/cms/author/dto/AuthorDTO.java (added)
+++ src/main/java/com/takensoft/cms/author/dto/AuthorDTO.java
@@ -0,0 +1,50 @@
+package com.takensoft.cms.author.dto;
+
+import lombok.*;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 권한 등록/수정 관련 DTO
+ */
+@Setter
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ToString
+public class AuthorDTO {
+
+    /**
+     * 권한 코드
+     */
+    @NotBlank(message = "권한코드는 필수 입력 값입니다.")
+    @Size(min = 5, max = 50)
+    private String authrtCd;
+    /**
+     * 권한명
+     */
+    @NotBlank(message = "권한명은 필수 입력 값입니다.")
+    @Size(min = 4, max = 50)
+    private String authrtNm;
+    /**
+     * 권한 설명
+     */
+    private String authrtExpln;
+    /**
+     * 사용여부
+     */
+    private boolean useYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+}
 
src/main/java/com/takensoft/cms/author/service/AuthorService.java (added)
+++ src/main/java/com/takensoft/cms/author/service/AuthorService.java
@@ -0,0 +1,58 @@
+package com.takensoft.cms.author.service;
+
+import com.takensoft.cms.author.dto.AuthorDTO;
+import com.takensoft.cms.author.vo.AuthorVO;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 권한 정보 관련 인터페이스
+ */
+public interface AuthorService {
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 중복 검사
+     */
+    public boolean findByCheckAuthorCode(AuthorVO authorVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 목록 조회
+     */
+    public Map<String, Object> findAllAuthor(Map<String, String> params) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 상세 조회
+     */
+    AuthorVO findByAuthorCode(String authrtCd) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 등록
+     */
+    public int authorSave(AuthorVO authorVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 수정
+     */
+    public int authorUpdate(AuthorVO authorVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 전체 권한 목록 조회(신규 메뉴 등록 시 권한을 주기 위해 사용)
+     */
+    public List<AuthorVO> findAllSystem() throws Exception;
+}
 
src/main/java/com/takensoft/cms/author/service/Impl/AuthorServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/author/service/Impl/AuthorServiceImpl.java
@@ -0,0 +1,116 @@
+package com.takensoft.cms.author.service.Impl;
+
+import com.takensoft.cms.author.dao.AuthorDAO;
+import com.takensoft.cms.author.service.AuthorService;
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.menu.service.MenuAuthorService;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 권한 정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * AuthorService : 권한 정보 인터페이스 상속
+ */
+@Service("authorService")
+@RequiredArgsConstructor
+public class AuthorServiceImpl extends EgovAbstractServiceImpl implements AuthorService {
+    private final AuthorDAO authorDAO;
+    private final MenuAuthorService menuAuthorService;
+    private final JWTUtil jwtUtil;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 중복 검사
+     */
+    @Override
+    public boolean findByCheckAuthorCode(AuthorVO authorVO) throws Exception {
+        return authorDAO.findByCheckAuthorCode(authorVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 목록 조회
+     */
+    @Override
+    public Map<String, Object> findAllAuthor(Map<String, String> params) throws Exception {
+        Map<String, Object> result = new HashMap<String, Object>(); // 반환 객체 생성
+        Pagination search = new Pagination(0, params); // 검색조건 객체 생성
+        int cnt = authorDAO.findAllCnt(search); // 게시물 갯수
+        Pagination pagination = new Pagination(cnt, params); // 게시물 갯수 조회 후 검색조건 객체 초기화
+        List<AuthorVO> list = authorDAO.findAll(pagination); // 목록 조회
+
+        result.put("list", list);
+        result.put("pagination", pagination);
+
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 상세 조회
+     */
+    @Override
+    public AuthorVO findByAuthorCode(String authrtCd) throws Exception {
+        AuthorVO result = new AuthorVO();
+        if(authrtCd != null && !authrtCd.equals("")) {
+            result = authorDAO.findByAuthorCode(authrtCd);
+        } else {
+            result.setUseYn("Y");
+        }
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 등록
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int authorSave(AuthorVO authorVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        authorVO.setRgtr(jwtUtil.getWriter());
+        int result = authorDAO.save(authorVO);
+        
+        // 메뉴별 권한 등록
+        if(result > 0) {
+            result += menuAuthorService.menuAuthrtSave(authorVO.getAuthrtCd(), "author");
+        }
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 권한 수정
+     */
+    @Override
+    public int authorUpdate(AuthorVO authorVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        authorVO.setMdfr(jwtUtil.getWriter());
+        return authorDAO.update(authorVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * 전체 권한 목록 조회(신규 메뉴 등록 시 권한을 주기 위해 사용)
+     */
+    @Override
+    public List<AuthorVO> findAllSystem() throws Exception {
+        return authorDAO.findAllSystem();
+    }
+}
 
src/main/java/com/takensoft/cms/author/vo/AuthorVO.java (added)
+++ src/main/java/com/takensoft/cms/author/vo/AuthorVO.java
@@ -0,0 +1,72 @@
+package com.takensoft.cms.author.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 권한 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class AuthorVO {
+    /**
+     * 권한코드
+     */
+    private String authrtCd;
+    /**
+     * 변경전 권한코드
+     */
+    private String originAuthrtCd;
+    /**
+     * 권한명
+     */
+    private String authrtNm;
+    /**
+     * 권한 사용자
+     */
+    private String mbrId;
+    /**
+     * 권한설명
+     */
+    private String authrtExpln;
+    /**
+     * 사용여부
+     */
+    private String useYn;
+    /**
+     * 시스템 제공 여부 -> 시스템에서 제공되는 데이터는 사용자가 제거하지 못하도록 하기 위한 설정값
+     * 0: 시스템, 1: 사용자
+     */
+    private String sysPvsnYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록자명
+     */
+    private String rgtrNm;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정자명
+     */
+    private String mdfrNm;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+
+}
 
src/main/java/com/takensoft/cms/author/web/AuthorController.java (added)
+++ src/main/java/com/takensoft/cms/author/web/AuthorController.java
@@ -0,0 +1,220 @@
+package com.takensoft.cms.author.web;
+
+import com.takensoft.cms.author.dto.AuthorDTO;
+import com.takensoft.cms.author.service.AuthorService;
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.common.exception.IdDuplicationException;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 권한 정보 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping("/admin/auth")
+public class AuthorController {
+
+    private final AuthorService authorService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     * @param authorVO
+     * @return
+     * @throws Exception
+     *
+     * 권한 등록
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> saveProc(@RequestBody AuthorVO authorVO) throws Exception {
+        // 권한 코드 중복 검사
+        boolean isExistence = authorService.findByCheckAuthorCode(authorVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        if(isExistence) {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("이미 존재하는 권한코드입니다.");
+            log.error("이미 존재하는 권한코드입니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+        // 권한 등록
+        int result = authorService.authorSave(authorVO);
+
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param params
+     * @return
+     * @throws Exception
+     *
+     * 권한 목록 조회
+     */
+    @PostMapping("/findAll.json")
+    public ResponseEntity<?> findAll(@RequestBody Map<String, String> params) throws Exception {
+        // 권한 목록 조회
+        Map<String, Object> result = authorService.findAllAuthor(params);
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param authorVO
+     * @return
+     * @throws Exception
+     *
+     * 권한 상세 조회
+     */
+    @PostMapping("/findByAuthrt.json")
+    public ResponseEntity<?> findByAuthrt(@RequestBody AuthorVO authorVO) throws Exception {
+        // 권한 상세 조회
+        AuthorVO authrt = authorService.findByAuthorCode(authorVO.getAuthrtCd());
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("authrt", authrt);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param authorVO
+     * @return
+     * @throws Exception
+     *
+     * 권한 수정
+     */
+    @PostMapping("/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody AuthorVO authorVO) throws Exception {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        
+        // 권한 코드의 변경 사항이 있을 때만 코드 중복 검사 진행
+        if(authorVO.getOriginAuthrtCd() != null && !authorVO.getOriginAuthrtCd().equals("") && !authorVO.getOriginAuthrtCd().equals(authorVO.getAuthrtCd())) {
+            // 권한 코드 중복 검사
+            boolean isExistence = authorService.findByCheckAuthorCode(authorVO);
+            if(isExistence) {
+                responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+                responseData.setMessage("이미 존재하는 권한코드입니다.");
+                log.error("이미 존재하는 권한코드입니다.");
+                return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+            }
+        }
+        
+        // 권한 수정
+        int result = authorService.authorUpdate(authorVO);
+
+        // 응답 처리
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param authorVO
+     * @return
+     * @throws Exception
+     *
+     * 권한 삭제
+     */
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody AuthorVO authorVO) throws Exception {
+        // 권한 삭제
+        int result = authorService.authorUpdate(authorVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.04.26
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 전체 권한 목록 조회(신규 메뉴 등록 시 권한을 주기 위해 사용)
+     */
+    @PostMapping("/findAllSystem.json")
+    public ResponseEntity<?> findAllSystem() throws Exception {
+        List<AuthorVO> result = authorService.findAllSystem();
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}
 
src/main/java/com/takensoft/cms/bbs/dao/BbsCnDAO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/dao/BbsCnDAO.java
@@ -0,0 +1,118 @@
+package com.takensoft.cms.bbs.dao;
+
+import com.takensoft.cms.bbs.vo.BbsCnVO;
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.05.09
+ *
+ * 게시판 내용 관련 Mapper
+ */
+@Mapper("bbsCnDAO")
+public interface BbsCnDAO {
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 아이디 중복 검사
+     */
+    public boolean bbsCnIdCheck(BbsCnVO bbsCnVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 내용 등록
+     */
+    public int save(BbsCnVO bbsCn) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 내용 목록 조회 개수
+     */
+    public int findAllCnt(Pagination pagination) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 내용 목록 조회
+     */
+    public List<BbsCnVO> findAll(Pagination pagination) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 내용 상세 조회
+     */
+    public BbsCnVO findByBbsId(String bbsCnId);
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 내용 수정
+     */
+    public int update(HashMap<String, Object> params);
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 내용 삭제
+     */
+    public int delete(BbsCnVO bbsCnVO);
+
+    /**
+     * @author 방선주
+     * @since  2024.05.22
+     *
+     * 조회수 증가 처리
+     */
+    public int updateVwCnt(String bbsId) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.05.23
+     *
+     * 이전글
+     */
+    public BbsCnVO findPrevBbsCn(BbsCnVO bbsCnVO);
+
+    /**
+     * @author 방선주
+     * @since  2024.05.23
+     *
+     * 다음글
+     */
+    public BbsCnVO findNextBbsCn(BbsCnVO bbsCnVO);
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.28
+     *
+     * 게시글 최신 목록 조회 (최신글 5건 출력)
+     */
+    public List<HashMap> selectBbsCnListByNew() throws Exception;
+
+    /**
+     * @author  : 방선주
+     * @since   : 2024.06.04
+     *
+     * 질의형 게시판 답변 등록
+     */
+    public int saveAnswer(BbsCnVO bbsCnVO) throws Exception;
+
+    /**
+     * @author  : 방선주
+     * @since   : 2024.06.13
+     *
+     * 최근 공지 5개 조회
+     */
+    public List<BbsCnVO> findFiveNotice(BbsCnVO bbsCn);
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/dao/BbsMngDAO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/dao/BbsMngDAO.java
@@ -0,0 +1,128 @@
+package com.takensoft.cms.bbs.dao;
+
+import com.takensoft.cms.bbs.vo.BbsMngVO;
+import com.takensoft.cms.bbs.vo.BbsRouterVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 관리 관련 Mapper
+ */
+@Mapper("bbsMngDAO")
+public interface BbsMngDAO {
+    /**
+     * @author  박정하
+     * @since   2024.05.08
+     * 게시판 아이디 중복 검사
+     */
+    public boolean bbsMngIdCheck(BbsMngVO bbsMngVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * 게시판 관리 등록
+     */
+    public int save(BbsMngVO bbsMngVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * 게시판 관리 목록 조회 개수
+     */
+    public int findAllCnt(Pagination pagination) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * 게시판 관리 목록 조회
+     */
+    public List<BbsMngVO> findAll(Pagination pagination) throws Exception;
+
+    /**
+     * @author  박정하
+     * @since   2024.05.16
+     * 게시판 관리 목록 조회 (메뉴 관리용)
+     */
+    public List<BbsMngVO> findAllByMenuMng() throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.08
+     *
+     * 게시판 관리 상세 조회
+     */
+    public BbsMngVO findByBbsMngId(String bbsMngId) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 수정
+     */
+    public int update(BbsMngVO bbsMngVO) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 삭제
+     */
+    public int delete(BbsMngVO bbsMngVO) throws Exception;
+
+
+
+    /** ********************************* 게시판 라우터 (시작) ********************************* */
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 등록
+     */
+    public int saveBbsRouter(BbsRouterVO bbsRouterVO) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 수정
+     */
+    public int updateBbsRouter(BbsRouterVO bbsRouterVO) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 삭제
+     */
+    public int deleteBbsRouter(String bbsMngId) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.06.04
+     *
+     * 게시판 라우터 목록 조회
+     */
+    public List<BbsRouterVO> findAllBbsRouter(String bbsMngId);
+
+    /**
+     * @author 방선주
+     * @since  2024.06.05
+     *
+     * 게시판 라우터 pshrcrs 수정
+     */
+    public void updateCrs(BbsRouterVO route);
+
+    /** ********************************* 게시판 라우터 (종료) ********************************* */
+
+    /**
+     * @author  박정하
+     * @since   2024.07.18
+     * 게시판 관리 목록 조회 개수 (접속 통계용)
+     */
+    public int findAllCntNotPagination() throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/dao/BbsRouterDAO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/dao/BbsRouterDAO.java
@@ -0,0 +1,25 @@
+package com.takensoft.cms.bbs.dao;
+
+import com.takensoft.cms.bbs.vo.BbsCnVO;
+import com.takensoft.cms.contsType.vo.ContsAuthrtVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.05.09
+ *
+ * 게시판 내용 관련 Mapper
+ */
+@Mapper("bbsRouterDAO")
+public interface BbsRouterDAO {
+    /**
+     * @author  takensoft
+     * @since   2024.05.16
+     * 게시판 라우터 정보 호출
+     */
+    List<ContsAuthrtVO> findByBbsRouterAuthrt();
+
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/dao/BbsTypeMngDAO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/dao/BbsTypeMngDAO.java
@@ -0,0 +1,37 @@
+package com.takensoft.cms.bbs.dao;
+
+import com.takensoft.cms.bbs.vo.BbsTypeMngVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 유형 관리 관련 Mapper
+ */
+@Mapper("bbsTypeMngDAO")
+public interface BbsTypeMngDAO {
+    /**
+     * @author  박정하
+     * @since   2024.05.08
+     * 게시판 유형 관리 등록
+     */
+    public int insertBbsTypeMng(BbsTypeMngVO bbsTypeMngVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 유형 관리 목록 조회
+     */
+    public List<BbsTypeMngVO> findAll(BbsTypeMngVO bbsTypeMngVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 유형 관리 상세 조회
+     */
+    public BbsTypeMngVO findByBbsTypeId(String bbsTypeId) throws Exception;
+}
 
src/main/java/com/takensoft/cms/bbs/dao/CmntDAO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/dao/CmntDAO.java
@@ -0,0 +1,53 @@
+package com.takensoft.cms.bbs.dao;
+
+import com.takensoft.cms.bbs.vo.CmntVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+
+/**
+ * @author  : 방선주
+ * @since   : 2024.05.27
+ *
+ * 게시판 댓글 관련 DAO
+ */
+
+@Mapper("cmntDAO")
+public interface CmntDAO {
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * 게시판 댓글 등록
+     */
+    public int saveCmnt(CmntVO cmntVO) throws Exception;
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * 게시판 댓글 카운트 조회
+     */
+    public int getCmntCount(CmntVO cmntVO) throws Exception;
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * 부모 댓글 조회
+     */
+    public CmntVO findParentCmnt(int upCmntId) throws Exception;
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * 게시판 댓글 목록 조회
+     */
+    public List<CmntVO> findCmntList(String bbsId) throws Exception;
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * 게시판 댓글 업데이트
+     */
+    public int updateCmnt(CmntVO cmntVO) throws Exception;
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * 게시판 삭제
+     */
+    public int deleteCmnt(CmntVO cmntVO) throws Exception;
+}
 
src/main/java/com/takensoft/cms/bbs/dao/WordMngDAO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/dao/WordMngDAO.java
@@ -0,0 +1,26 @@
+package com.takensoft.cms.bbs.dao;
+
+import com.takensoft.cms.bbs.vo.WordMngVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.05.31
+ *
+ * 금지어 관련 Mapper
+ */
+@Mapper("wordMngDAO")
+public interface WordMngDAO {
+    public int saveWords(WordMngVO wordMngVO) throws Exception;
+
+    public List<WordMngVO> findAllWord(Pagination search) throws Exception;
+
+    public int findAllCnt(Pagination search) throws Exception;
+
+    public int deleteWords(int word) throws Exception;
+
+    public List<String> findWordList() throws Exception;
+}
 
src/main/java/com/takensoft/cms/bbs/service/BbsCnService.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/BbsCnService.java
@@ -0,0 +1,133 @@
+package com.takensoft.cms.bbs.service;
+
+import com.takensoft.cms.bbs.vo.BbsCnVO;
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.common.Pagination;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.05.09
+ *
+ * 게시판 관리 관련 인터페이스
+ */
+public interface BbsCnService {
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 아이디 중복 검사
+     */
+    public boolean bbsCnIdCheck(BbsCnVO bbsCnVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 내용 등록
+     */
+    public HashMap<String, Object> saveBbsCn(BbsCnVO bbsCn, List<MultipartFile> multipartFileList, List<MultipartFile> multipartImgList) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 내용 목록 조회 개수
+     */
+    public int findAllCnt(Pagination pagination) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 내용 목록 조회
+     */
+    public Map<String, Object> findAllBbsCn(HashMap<String, String> params) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 상세 조회
+     */
+    public BbsCnVO findByBbsId(String bbsId) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 수정
+     */
+    public HashMap<String, Object> updateBbsCn(HashMap<String, Object> params, List<HashMap<String, Object>> deleteFileList, List<MultipartFile> multipartFileList, List<HashMap<String, Object>> deleteImgFileList, List<MultipartFile> multipartImgList) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 삭제
+     */
+    public int deleteBbsCn(BbsCnVO bbsCnVO) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.05.22
+     *
+     * 조회수 증가
+     */
+    public int updateVwCnt(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.05.23
+     *
+     * 이전글 조회
+     */
+     public BbsCnVO findPrevBbsCn(BbsCnVO bbsCnVO) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.05.23
+     *
+     * 다음글 조회
+     */
+    public BbsCnVO findNextBbsCn(BbsCnVO bbsCnVO) throws Exception;
+    /**
+     * @author 방선주
+     * @since  2024.05.30
+     *
+     * 첨부파일 이미지 경로 변경
+     */
+    public List<HashMap<String, Object>> fileListPathChange(String fileMngId) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.05.31
+     *
+     * 질의형 답변 등록
+     */
+    public HashMap<String, Object> saveAnswer(BbsCnVO bbsCnVO) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.05.31
+     *
+     * 질의형 답변 수정
+     */
+    public HashMap<String, Object> updateAnswer(BbsCnVO bbsCnVO) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.06.07
+     *
+     * 질의형 답변 삭제
+     */
+    public int deleteAns(BbsCnVO bbsCnVO) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since  2024.06.13
+     *
+     * 최신 공지 5개
+     */
+    public List<BbsCnVO> findFiveNotice(BbsCnVO bbsCn) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/service/BbsMngService.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/BbsMngService.java
@@ -0,0 +1,96 @@
+package com.takensoft.cms.bbs.service;
+
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.bbs.vo.BbsMngVO;
+import com.takensoft.cms.bbs.vo.BbsRouterVO;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 관리 관련 인터페이스
+ */
+public interface BbsMngService {
+    /**
+     * @author  박정하
+     * @since   2024.05.08
+     * 게시판 아이디 중복 검사
+     */
+    public boolean bbsMngIdCheck(BbsMngVO bbsMngVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * 게시판 관리 등록
+     */
+    public HashMap<String, Object> saveBbsMng(BbsMngVO bbsMngVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * 게시판 관리 목록 조회
+     */
+    public Map<String, Object> findAllBbsMng(HashMap<String, String> params) throws Exception;
+
+    /**
+     * @author  박정하
+     * @since   2024.05.16
+     * 게시판 관리 목록 조회 (메뉴 관리용)
+     */
+    public List<BbsMngVO> findAllByMenuMng() throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.08
+     *
+     * 게시판 관리 상세 조회
+     */
+    public BbsMngVO findByBbsMngId(String bbsMngId) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 수정
+     */
+    public int updateBbsMng(BbsMngVO bbsMngVO) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 삭제
+     */
+    public int deleteBbsMng(BbsMngVO bbsMngVO) throws Exception;
+
+
+
+    /** ********************************* 게시판 라우터 (시작) ********************************* */
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 등록
+     */
+    public int saveBbsRouter(BbsRouterVO bbsRouterVO) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 수정
+     */
+    public int updateBbsRouter(BbsRouterVO bbsRouterVO) throws Exception;
+
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 삭제
+     */
+    public int deleteBbsRouter(String bbsMngId) throws Exception;
+
+    /** ********************************* 게시판 라우터 (종료) ********************************* */
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/service/BbsTypeMngService.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/BbsTypeMngService.java
@@ -0,0 +1,36 @@
+package com.takensoft.cms.bbs.service;
+
+import com.takensoft.cms.bbs.vo.BbsTypeMngVO;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 유형 관리 관련 인터페이스
+ */
+public interface BbsTypeMngService {
+    /**
+     * @author  박정하
+     * @since   2024.05.08
+     * 게시판 유형 관리 등록
+     */
+    public HashMap<String, Object> insertBbsTypeMng(BbsTypeMngVO bbsTypeMngVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 유형 관리 목록 조회
+     */
+    public Map<String, Object> findAllBbsTypeMng(BbsTypeMngVO bbsTypeMngVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 유형 관리 상세 조회
+     */
+    public BbsTypeMngVO findByBbsTypeId(String bbsTypeId) throws Exception;
+}
 
src/main/java/com/takensoft/cms/bbs/service/CmntService.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/CmntService.java
@@ -0,0 +1,23 @@
+package com.takensoft.cms.bbs.service;
+
+import com.takensoft.cms.bbs.vo.CmntVO;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 방선주
+ * @since   : 2024.05.27
+ *
+ * 게시판 댓글 관련 Service
+ */
+public interface CmntService {
+    // 댓글 등록
+    public HashMap<String, Object> saveCmnt(CmntVO cmntVO) throws Exception;
+    // 댓글 목록 조회
+    public List<CmntVO> findCmntList(String bbsId) throws Exception;
+    // 댓글 업데이트
+    public HashMap<String, Object> updateCmnt(CmntVO cmntVO) throws Exception;
+
+    public int deleteCmnt(CmntVO cmntVO) throws Exception;
+}
 
src/main/java/com/takensoft/cms/bbs/service/Impl/BbsCnServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/Impl/BbsCnServiceImpl.java
@@ -0,0 +1,557 @@
+package com.takensoft.cms.bbs.service.Impl;
+
+import com.takensoft.cms.bbs.dao.BbsCnDAO;
+import com.takensoft.cms.bbs.dao.BbsMngDAO;
+import com.takensoft.cms.bbs.dao.WordMngDAO;
+import com.takensoft.cms.bbs.service.BbsCnService;
+import com.takensoft.cms.bbs.vo.BbsCnVO;
+import com.takensoft.cms.bbs.vo.BbsMngVO;
+import com.takensoft.cms.bbs.vo.WordMngVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.file.dao.FileDAO;
+import com.takensoft.common.file.service.FileMngService;
+import com.takensoft.common.file.vo.FileMngVO;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.05.09
+ *
+ * 게시판 내용 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * BbsCnService : 게시판 내용 인터페이스 상속
+ */
+@Service("bbsCnService")
+@RequiredArgsConstructor
+public class BbsCnServiceImpl extends EgovAbstractServiceImpl implements BbsCnService {
+    private final BbsCnDAO bbsCnDAO;
+    private final BbsMngDAO bbsMngDAO;
+    private final FileDAO fileDAO;
+    private final WordMngDAO wordMngDAO;
+
+    private final IdgenService bbsIdgn;
+    private final JWTUtil jwtUtil;
+
+    private final FileMngService fileMngService;
+
+    @Value("${front.url}")
+    private String frontUrl;
+
+    @Value("${server.port}")
+    private String serverPort;
+
+    @Value("${spring.web.resources.static-locations}")
+    private String locationPath;
+
+    @Value("${file.file-upload-path}")
+    private String fileUploadPath;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 아이디 중복 검사
+     */
+    @Override
+    public boolean bbsCnIdCheck(BbsCnVO bbsCnVO) throws Exception {
+        return bbsCnDAO.bbsCnIdCheck(bbsCnVO);
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 내용 등록
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public HashMap<String, Object> saveBbsCn(BbsCnVO bbsCn, List<MultipartFile> multipartFileList, List<MultipartFile> multipartImgList) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+        List<String> wordList = wordMngDAO.findWordList();
+
+        // 금지어 포함 여부 체크
+        // 제목에 금지어가 포함되어있는가?
+        if(bbsCn.getBbsNm() != null && !bbsCn.getBbsNm().isEmpty()) {
+        String bbsNm = bbsCn.getBbsNm();
+        for (String word : wordList) {
+            if (bbsNm.contains(word)) {
+                result.put("result", -1);
+                result.put("word", word);
+                return result;
+            }
+        }
+        }
+
+        // 내용에 금지어가 포함되어있는가?
+        String content = bbsCn.getBbsCn();
+        for (String word : wordList) {
+            if (content.contains(word)) {
+                result.put("result", -1);
+                result.put("word", word);
+                return result;
+            }
+        }
+
+
+        // 게시판 내용 아이디 생성
+        String bbsId = bbsIdgn.getNextStringId();
+        bbsCn.setBbsId(bbsId);
+
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsCn.setRgtr(writer);
+
+        // youtube 링크 여부에 따라 처리
+        if(bbsCn.getVdoUrl() != null){
+            bbsCn.setVdoUrl(vdoUrlCheck(bbsCn.getVdoUrl()));
+        }
+
+
+        // 첨부파일 유무
+        if (multipartFileList != null && !multipartFileList.isEmpty()) {
+            try {
+                FileMngVO fileMngVO = new FileMngVO();
+
+                // 파일매니저 등록
+                HashMap<String, Object> fileMng = fileMngService.fileMngInsert(fileMngVO, multipartFileList);
+                result.put("multipartFileMngResult", fileMng);
+
+                // 파일매니저 아이디 삽입
+                bbsCn.setAtchFileMngId(fileMng.get("fileMngId").toString());
+            } catch (IOException e) {
+                e.printStackTrace();
+                return result;
+            }
+        }
+        // 이미지파일 유무
+        if (multipartImgList != null && !multipartImgList.isEmpty()) {
+            try {
+                FileMngVO fileMngVO = new FileMngVO();
+
+                // 파일매니저 등록
+                HashMap<String, Object> imgFileMng = fileMngService.fileMngInsert(fileMngVO, multipartImgList);
+                result.put("multipartFileMngResult", imgFileMng);
+
+                // 이미지 파일매니저 아이디 삽입
+                bbsCn.setImgFileMngId(imgFileMng.get("fileMngId").toString());
+            } catch (IOException e) {
+                e.printStackTrace();
+                return result;
+            }
+        }
+
+        // 질의형인 경우 \n을 <br>로 변경
+        if(bbsCn.getBbsNm() == null){
+            String text = bbsCn.getBbsCn().replaceAll("\n", "<br/>");
+            bbsCn.setBbsCn(text);
+        }
+
+        // 기본정보 DB 등록
+        int saveBbsCnResult = bbsCnDAO.save(bbsCn);
+        result.put("bbsId", bbsId);
+        result.put("result", saveBbsCnResult);
+
+        return result;
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 내용 목록 조회 개수
+     */
+    public int findAllCnt(Pagination pagination) throws Exception{
+        return bbsCnDAO.findAllCnt(pagination);
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * 게시판 내용 목록 조회
+     */
+    @Override
+    public Map<String, Object> findAllBbsCn(HashMap<String, String> params) throws Exception {
+        Map<String, Object> result = new HashMap<>();
+
+        // 게시판 관리 정보
+        BbsMngVO bbsMng = bbsMngDAO.findByBbsMngId(params.get("id"));
+        params.put("recordSize", String.valueOf(bbsMng.getArtclCnt()));
+
+        // 게시판 보여줄 갯수 설정
+        Pagination search = new Pagination(0, params);
+        int cnt = bbsCnDAO.findAllCnt(search);
+        Pagination pagination = new Pagination(cnt, params);
+        List<BbsCnVO> list = bbsCnDAO.findAll(pagination);
+
+        list.forEach(entity -> {
+            String imagePath = entity.getAbsltPath();
+            entity.setAbsltPath(convertPathToUrl(imagePath));
+        });
+
+        result.put("list", list);
+        result.put("pagination", pagination);
+        result.put("codeList", null); // 검색 조건
+        result.put("bbsMng", bbsMng); // 게시판 관리 정보
+        return result;
+    }
+
+    private String convertPathToUrl(String filePath) {
+
+        String previewPath = null;
+        String[] pathArray = locationPath.split("/, ");
+        for (String path : pathArray) {
+            if (path.startsWith("file:///")) {
+                // "file:///" 부분을 제거하고 경로를 반환
+                previewPath = path.replace("file:///", "") + fileUploadPath;
+            } else {
+                previewPath = locationPath + fileUploadPath;
+            }
+        }
+        if (filePath == null) return null;
+        // 서버경로를 절대경로에서 상대경로로 변환
+        String basePath = previewPath; // 이 부분은 환경설정 파일에서 가져오는 것이 좋습니다.
+        String relativePath = filePath.substring(basePath.length());
+        return frontUrl + ":" + serverPort + fileUploadPath + relativePath;
+    }
+
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 내용 상세 조회
+     */
+    @Override
+    public BbsCnVO findByBbsId(String bbsId) throws Exception {
+        BbsCnVO result = new BbsCnVO();
+        if(bbsId != null && !bbsId.isEmpty()) {
+            result = bbsCnDAO.findByBbsId(bbsId);
+
+            if(result.getBbsNm() == null){
+                String text = result.getBbsCn().replaceAll("<br/>", "\n");
+                result.setBbsCn(text);
+                if(result.getAnsCn() != null){
+                    String ansText = result.getAnsCn().replaceAll("<br/>", "\n");
+                    result.setAnsCn(ansText);
+                }
+            }
+
+        } else {
+            result.setUseYn("Y");
+        }
+        return result;
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 내용 수정
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public HashMap<String, Object> updateBbsCn(HashMap<String, Object> params, List<HashMap<String, Object>> deleteFileList, List<MultipartFile> multipartFileList, List<HashMap<String, Object>> deleteImgFileList, List<MultipartFile> multipartImgList) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+        int intResult= 0;
+
+        List<String> wordList = wordMngDAO.findWordList();
+
+        // 금지어 포함 여부 체크
+        // 제목에 금지어가 포함되어있는가?
+        String bbsNm = (params.get("bbsNm") != null) ? params.get("bbsNm").toString() : null;
+        if(bbsNm != null && !bbsNm.isEmpty()) {
+            for (String word : wordList) {
+                if (bbsNm.contains(word)) {
+                    result.put("result", -1);
+                    result.put("word", word);
+                    return result;
+                }
+            }
+        }
+
+        // 내용에 금지어가 포함되어있는가?
+        String content = params.get("bbsCn").toString();
+        for (String word : wordList) {
+            if (content.contains(word)) {
+                result.put("result", -1);
+                result.put("word", word);
+                return result;
+            }
+        }
+
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        params.put("mdfr", writer);
+
+        // youtube 링크 여부에 따라 처리
+        if(params.get("vdoUrl") != null){
+            params.put("vdoUrl", vdoUrlCheck(params.get("vdoUrl").toString()));
+        }
+
+        // 파일 업로드
+        FileMngVO fileMngVO = new FileMngVO();
+        if (params.get("atchFileMngId") != null) {
+            // 파일매니저 수정
+            try {
+                String fileMngId = params.get("atchFileMngId").toString();
+                fileMngVO.setFileMngId(fileMngId);
+                intResult += fileMngService.fileMngUpadate(fileMngVO, deleteFileList, multipartFileList);
+            } catch (IOException e) {
+                e.printStackTrace();
+                result.put("result", 0);
+                return result;
+            }
+        } else if (multipartFileList != null && !multipartFileList.isEmpty()){
+            // 파일매니저 등록
+            try {
+                HashMap<String, Object> fileMng = fileMngService.fileMngInsert(fileMngVO, multipartFileList);
+                intResult += (int)fileMng.get("fileMngResult");
+                params.put("atchFileMngId", fileMng.get("fileMngId").toString());
+            } catch (IOException e) {
+                e.printStackTrace();
+                result.put("result", 0);
+                return result;
+            }
+        }
+
+        // 이미지 파일 업로드
+        FileMngVO fileImgMngVO = new FileMngVO();
+        if (params.get("imgFileMngId") != null) {
+            // 파일매니저 수정
+            try {
+                String imgFileMng = params.get("imgFileMngId").toString();
+                fileImgMngVO.setFileMngId(imgFileMng);
+                intResult += fileMngService.fileMngUpadate(fileImgMngVO, deleteImgFileList, multipartImgList);
+            } catch (IOException e) {
+                e.printStackTrace();
+                result.put("result", 0);
+                return result;
+            }
+        } else if (multipartImgList != null && !multipartImgList.isEmpty()){
+            // 파일매니저 등록
+            try {
+                HashMap<String, Object> imgFileMng = fileMngService.fileMngInsert(fileImgMngVO, multipartImgList);
+                intResult += (int)imgFileMng.get("fileMngResult");
+                params.put("imgFileMngId", imgFileMng.get("fileMngId").toString());
+            } catch (IOException e) {
+                e.printStackTrace();
+                result.put("result", 0);
+                return result;
+            }
+        }
+
+        // 질의형인 경우 \n을 <br>로 변경
+        if(params.get("bbsNm") == null){
+            String text = params.get("bbsCn").toString().replaceAll("\n", "<br/>");
+            params.put("bbsCn", text);
+        }
+
+        // 게시판 내용 수정
+        intResult += bbsCnDAO.update(params);
+
+        result.put("result", intResult);
+        return result;
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 내용 삭제
+     */
+    @Override
+    public int deleteBbsCn(BbsCnVO bbsCnVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsCnVO.setMdfr(writer);
+
+        return bbsCnDAO.delete(bbsCnVO);
+    }
+    /**
+     * @author 방선주
+     * @since  2024.05.21
+     *
+     * vdoUrl 조건 처리
+     */
+     private String vdoUrlCheck(String vdoUrl) {
+         // youtube 링크가 있을 경우
+         if (vdoUrl.contains("youtube.com") || vdoUrl.contains("youtu.be")) {
+             String[] url = vdoUrl.split("/");
+             String videoId = url[url.length - 1];
+             String videoUrl = "https://www.youtube.com/embed/" + videoId;
+             return videoUrl;
+         } else {
+             return vdoUrl;
+         }
+     }
+
+    /**
+     * @author 방선주
+     * @since  2024.05.22
+     *
+     * 조회수 증가 처리
+     */
+    @Override
+    public int updateVwCnt(HashMap<String, Object> params) throws Exception {
+        return bbsCnDAO.updateVwCnt(params.get("bbsId").toString());
+    }
+
+    /**
+     * @author 방선주
+     * @since  2024.05.23
+     *
+     * 이전글 다음글 조회
+     *
+     */
+    @Override
+    public BbsCnVO findPrevBbsCn(BbsCnVO bbsCnVO) throws Exception {
+        Map<String, Object> result = new HashMap<>();
+
+        BbsCnVO prevBbsCn = bbsCnDAO.findPrevBbsCn(bbsCnVO);
+        return prevBbsCn;
+    }
+    /**
+     * @author 방선주
+     * @since  2024.05.23
+     *
+     * 이전글 다음글 조회
+     *
+     */
+    @Override
+    public BbsCnVO findNextBbsCn(BbsCnVO bbsCnVO) throws Exception {
+        Map<String, Object> result = new HashMap<>();
+
+        BbsCnVO NextBbsCn = bbsCnDAO.findNextBbsCn(bbsCnVO);
+        return NextBbsCn;
+    }
+
+    /**
+     * 첨부파일 이미지 경로 변경
+     * @param fileMngId
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public List<HashMap<String, Object>> fileListPathChange(String fileMngId) throws Exception {
+
+        List<HashMap<String, Object>> fileList = fileDAO.fileSelectList(fileMngId);
+
+        for (HashMap<String, Object> file : fileList) {
+            String absltPath = file.get("absltPath").toString();
+            file.put("absltPath", convertPathToUrl(absltPath));
+        }
+        return fileList;
+    }
+
+    /**
+     * 질의형 게시판 답변 등록
+     * @param bbsCnVO
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public HashMap<String, Object> saveAnswer(BbsCnVO bbsCnVO) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsCnVO.setAnswer(writer);
+
+        // 답변 금지어 포함 여부 체크
+        List<String> wordList = wordMngDAO.findWordList();
+        String ansCn = bbsCnVO.getAnsCn();
+        for (String word : wordList) {
+            if (ansCn.contains(word)) {
+                result.put("result", -1);
+                result.put("word", word);
+                return result;
+            }
+        }
+
+        // 질의형인 경우 \n을 <br>로 변경
+        if(bbsCnVO.getBbsNm() == null){
+            String text = bbsCnVO.getAnsCn().replaceAll("\n", "<br/>");
+            bbsCnVO.setAnsCn(text);
+        }
+
+        int saveAns = bbsCnDAO.saveAnswer(bbsCnVO);
+
+        result.put("result", saveAns);
+        return result;
+    }
+
+    /**
+     * 질의형 게시판 답변 수정
+     * @param bbsCnVO
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public HashMap<String, Object> updateAnswer(BbsCnVO bbsCnVO) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsCnVO.setAnswer(writer);
+
+        // 답변 금지어 포함 여부 체크
+        List<String> wordList = wordMngDAO.findWordList();
+        String ansCn = bbsCnVO.getAnsCn();
+        for (String word : wordList) {
+            if (ansCn.contains(word)) {
+                result.put("result", -1);
+                result.put("word", word);
+                return result;
+            }
+        }
+
+        String text = bbsCnVO.getAnsCn().replaceAll("\n", "<br/>");
+        bbsCnVO.setAnsCn(text);
+
+        int saveAns = bbsCnDAO.saveAnswer(bbsCnVO);
+
+        result.put("result", saveAns);
+        return result;
+    }
+
+    /**
+     * 질의형 게시판 답변 삭제
+     * @param bbsCnVO
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public int deleteAns(BbsCnVO bbsCnVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsCnVO.setAnswer(writer);
+
+        bbsCnVO.setAnsCn(null);
+        bbsCnVO.setAnsStts("N");
+
+        return bbsCnDAO.saveAnswer(bbsCnVO);
+    }
+
+    /**
+     * 최근 공지사항 5개 가져오기
+     * @param
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public List<BbsCnVO> findFiveNotice(BbsCnVO bbsCn) throws Exception{
+        return bbsCnDAO.findFiveNotice(bbsCn);
+    }
+
+
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/service/Impl/BbsMngServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/Impl/BbsMngServiceImpl.java
@@ -0,0 +1,350 @@
+package com.takensoft.cms.bbs.service.Impl;
+
+import com.takensoft.cms.bbs.dao.BbsMngDAO;
+import com.takensoft.cms.bbs.service.BbsCnService;
+import com.takensoft.cms.bbs.service.BbsMngService;
+import com.takensoft.cms.bbs.service.BbsTypeMngService;
+import com.takensoft.cms.bbs.vo.BbsMngVO;
+import com.takensoft.cms.bbs.vo.BbsRouterVO;
+import com.takensoft.cms.bbs.vo.BbsTypeMngVO;
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.menu.service.MenuService;
+import com.takensoft.cms.menu.vo.MenuVO;
+import com.takensoft.common.HierachyVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 관리 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * BbsMngService : 게시판 관리 인터페이스 상속
+ */
+@Service("bbsMngService")
+@RequiredArgsConstructor
+public class BbsMngServiceImpl extends EgovAbstractServiceImpl implements BbsMngService {
+    private final BbsMngDAO bbsMngDAO;
+    private final BbsTypeMngService bbsTypeMngService;
+    private final BbsCnService bbsCnService;
+    private final IdgenService bbsMngIdgn;
+    private final IdgenService bbsRouterIdgn;
+    private final MenuService menuService;
+
+    private final JWTUtil jwtUtil;
+
+    /**
+     * @author  박정하
+     * @since   2024.05.08
+     * 게시판 아이디 중복 검사
+     */
+    @Override
+    public boolean bbsMngIdCheck(BbsMngVO bbsMngVO) throws Exception {
+        return bbsMngDAO.bbsMngIdCheck(bbsMngVO);
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * 게시판 관리 등록
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public HashMap<String, Object> saveBbsMng(BbsMngVO bbsMngVO) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+
+        // 게시판 관리 아이디 생성
+        String bbsMngId = bbsMngIdgn.getNextStringId();
+        bbsMngVO.setBbsMngId(bbsMngId);
+
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsMngVO.setRgtr(writer);
+
+        // 확장자 리스트 문자열로 변경
+        bbsMngVO.setFileExtnNm(String.join(",", bbsMngVO.getFileExtnNmList()));
+
+        // 첨부파일 용량 변경 (Mb -> Byte)
+        bbsMngVO.setFileSzLmt(bbsMngVO.getFileSzLmt() * 1024 * 1024);
+
+        // 게시판 관리 등록
+        int insertResult = bbsMngDAO.save(bbsMngVO);
+
+        // 게시판 라우터 등록 프로세스
+        saveBbsRouterProc(bbsMngVO);
+
+        // 메뉴 등록 MENU_000000000000032 : 게시판 관리 메뉴 아이디
+
+        MenuVO menuVO = new MenuVO();
+        menuVO.setUpMenuId("MENU_000000000000032"); // 상위메뉴아이디(콘텐츠 관리 메뉴 아이디)
+        menuVO.setMenuNm(bbsMngVO.getBbsNm()); // 메뉴명
+        menuVO.setMenuType("bbs"); // 메뉴타입
+        menuVO.setMenuTypeCtgry(bbsMngVO.getBbsMngId()); // 메뉴타입항목(콘텐츠 유형 아이디)
+        menuVO.setLinkType("0"); // 링크유형(현재창)
+        menuVO.setDgstfnExmnUseYn("Y"); // 만족도조사사용여부(노출)
+        menuVO.setMenuExpsrYn("Y"); // 메뉴노출여부(노출)
+        menuVO.setMenuUser("A"); // 메뉴사용자(관리자)
+        menuVO.setSysPvsnYn("1"); // 시스템제공여부(시스템등록)
+        menuService.menuSave(menuVO);
+
+        result.put("bbsMngId", bbsMngId);
+        result.put("result", insertResult);
+        return result;
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * 게시판 관리 목록 조회
+     */
+    @Override
+    public Map<String, Object> findAllBbsMng(HashMap<String, String> params) throws Exception {
+        Map<String, Object> result = new HashMap<>();
+        Pagination search = new Pagination(0, params);
+        int cnt = bbsMngDAO.findAllCnt(search);
+        Pagination pagination = new Pagination(cnt, params);
+        List<BbsMngVO> bbsMngList = bbsMngDAO.findAll(pagination);
+
+        List<HashMap<String, Object>> list = new ArrayList<>();
+
+        //게시판 관리 목록 별 게시물 수
+        for(BbsMngVO vo : bbsMngList) {
+            HashMap<String, Object> map = new HashMap<>();
+
+            // 게시판 유형 그룹
+            BbsTypeMngVO bbsTypeMng = bbsTypeMngService.findByBbsTypeId(vo.getBbsTypeId());
+            String bbsTypeNm = bbsTypeMng.getBbsTypeKornNm();
+            int spaceIndex = bbsTypeNm.indexOf(" "); // 첫 번째 공백의 인덱스를 찾음
+            if (spaceIndex != -1) { // 공백이 있는 경우
+                bbsTypeNm = bbsTypeNm.substring(0, spaceIndex); // 첫 공백 전까지의 문자열을 추출
+            }
+
+            map.put("bbsMngId", vo.getBbsMngId());
+            map.put("bbsNm", vo.getBbsNm());
+            map.put("bbsTypeId", vo.getBbsTypeId());
+            map.put("bbsTypeNm", bbsTypeNm);
+            map.put("atchFileUseYn", vo.getAtchFileUseYn());
+            map.put("ntcUseYn", vo.getNtcUseYn());
+            map.put("prvtPstUseYn", vo.getPrvtPstUseYn());
+            map.put("bfrAftrPstUseYn", vo.getBfrAftrPstUseYn());
+            map.put("cmntUseYn", vo.getCmntUseYn());
+            map.put("bbsCnCnt", vo.getBbsCnCnt()); // 게시판 관리 목록 별 게시물 수 (수정 필요)
+            list.add(map);
+        }
+
+        result.put("list", list);
+        result.put("pagination", pagination);
+        return result;
+    }
+
+    /**
+     * @author  박정하
+     * @since   2024.05.16
+     * 게시판 관리 목록 조회 (메뉴 관리용)
+     */
+    @Override
+    public List<BbsMngVO> findAllByMenuMng() throws Exception {
+        return bbsMngDAO.findAllByMenuMng();
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.08
+     *
+     * 게시판 관리 상세 조회
+     */
+    @Override
+    public BbsMngVO findByBbsMngId(String bbsMngId) throws Exception {
+        BbsMngVO result = new BbsMngVO();
+
+        if(bbsMngId != null && !bbsMngId.isEmpty()) {
+            result = bbsMngDAO.findByBbsMngId(bbsMngId);
+            // 첨부파일 확장자 리스트 분리
+            if(result.getFileExtnNm() != null && !result.getFileExtnNm().isEmpty()){
+                result.setFileExtnNmList(Arrays.asList(result.getFileExtnNm().split(",")));
+            }
+            // 첨부파일 용량 변경 (Byte -> Mb)
+            result.setFileSzLmt(result.getFileSzLmt() / 1024 / 1024);
+
+        } else {
+            result.setUseYn("Y");
+        }
+        return result;
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 수정
+     */
+    @Override
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public int updateBbsMng(BbsMngVO bbsMngVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsMngVO.setMdfr(writer);
+
+        // 확장자 리스트 문자열로 변경
+        bbsMngVO.setFileExtnNm(String.join(",", bbsMngVO.getFileExtnNmList()));
+
+        bbsMngVO.setFileSzLmt(bbsMngVO.getFileSzLmt() * 1024 * 1024);
+
+        /** 게시판 라우터 수정 프로세스 */
+        BbsMngVO bbsMng = bbsMngDAO.findByBbsMngId(bbsMngVO.getBbsMngId());
+
+        // 게시판 유형이 변경된 경우
+        if(!bbsMng.getBbsTypeId().equals(bbsMngVO.getBbsTypeId())) {
+            // 기존 게시판 라우터 삭제
+            deleteBbsRouter(bbsMngVO.getBbsMngId());
+            
+            // 변경된 유형으로 게시판 라우터 등록
+            saveBbsRouterProc(bbsMngVO);
+        }
+        // 게시판 페이지 유형이 변경된 경우
+        if(!bbsMng.getCd().equals(bbsMngVO.getCd())) {
+            // 게시판 라우터 페이지 경로 변경
+            List<BbsRouterVO> bbsRouterList = bbsMngDAO.findAllBbsRouter(bbsMngVO.getBbsMngId());
+            for(BbsRouterVO route : bbsRouterList) {
+                String pageCrs = route.getPageCrs().replace(bbsMng.getCd(), bbsMngVO.getCd());
+                route.setPageCrs(pageCrs);
+                bbsMngDAO.updateCrs(route);
+
+            }
+
+        }
+
+        return bbsMngDAO.update(bbsMngVO);
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     *
+     * 게시판 관리 삭제
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public int deleteBbsMng(BbsMngVO bbsMngVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsMngVO.setMdfr(writer);
+        
+        // 게시판 라우터 비활성화
+        BbsRouterVO bbsRouterVO = new BbsRouterVO();
+        bbsRouterVO.setBbsMngId(bbsMngVO.getBbsMngId());
+        bbsRouterVO.setUseYn("N");
+        updateBbsRouter(bbsRouterVO);
+
+        // 메뉴에서도 삭제 처리
+        MenuVO menuVO = new MenuVO();
+        menuVO.setMenuTypeCtgry(bbsMngVO.getBbsMngId());
+        menuVO.setUseYn("N");
+        menuVO.setMdfr(writer);
+        int bbsMngMenuResult = menuService.bbsMngMenuDelete(menuVO);
+
+
+
+        return bbsMngDAO.delete(bbsMngVO);
+    }
+
+
+    /** ********************************* 게시판 라우터 (시작) ********************************* */
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 등록
+     */
+    @Override
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public int saveBbsRouter(BbsRouterVO bbsRouterVO) throws Exception {
+        return bbsMngDAO.saveBbsRouter(bbsRouterVO);
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 수정
+     */
+    @Override
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public int updateBbsRouter(BbsRouterVO bbsRouterVO) throws Exception {
+        return bbsMngDAO.updateBbsRouter(bbsRouterVO);
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.13
+     *
+     * 게시판 라우터 삭제
+     */
+    @Override
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public int deleteBbsRouter(String bbsMngId) throws Exception {
+        return bbsMngDAO.deleteBbsRouter(bbsMngId);
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 라우터 등록 프로세스
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public void saveBbsRouterProc(BbsMngVO bbsMngVO) throws Exception {
+        int result = 0;
+        try {
+            // 게시판 유형 조회 (bbs_type 조회)
+            BbsTypeMngVO bbsTypeMng = bbsTypeMngService.findByBbsTypeId(bbsMngVO.getBbsTypeId());
+            // 동일한 유형의 게시판 유형 목록 조회
+            List<BbsTypeMngVO> bbsTypeList = (List<BbsTypeMngVO>) bbsTypeMngService.findAllBbsTypeMng(bbsTypeMng).get("list");
+            // 게시판 유형 목록만큼 게시판 라우터 등록
+            for (BbsTypeMngVO vo : bbsTypeList) {
+                // 빈 게시판 라우터 VO 생성
+                BbsRouterVO bbsRouterVO = new BbsRouterVO();
+
+                // 게시판 라우터 아이디 생성
+                String bbsRouterId = bbsRouterIdgn.getNextStringId();
+
+                // 페이지 경로에 게시판 관리 아이디 추가
+                String pageCrs = vo.getPageCrs().replace("change", bbsMngVO.getBbsMngId());
+                String userPageCrs = pageCrs.replace("cmmn", bbsMngVO.getCd());
+                String adminPageCrs = pageCrs.replace("cmmn", "adm");
+                String compnCrs = vo.getCompnCrs();
+
+                bbsRouterVO.setBbsRouterId(bbsRouterId);
+                bbsRouterVO.setBbsMngId(bbsMngVO.getBbsMngId());
+                bbsRouterVO.setBbsKornNm(vo.getBbsTypeKornNm());
+                bbsRouterVO.setBbsEngNm(vo.getBbsTypeEngNm() + "_" + bbsMngVO.getBbsMngId());
+                bbsRouterVO.setPageCrs(userPageCrs);
+                bbsRouterVO.setMngrPageCrs(adminPageCrs);
+                bbsRouterVO.setCompnCrs(compnCrs);
+                bbsRouterVO.setExpsrYn(vo.getExpsrYn());
+
+                // 게시판 라우터 등록
+                result += saveBbsRouter(bbsRouterVO);
+            }
+
+            if(result != bbsTypeList.size()) {
+                throw new Exception("게시판 라우터 등록에 실패했습니다.");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new Exception("게시판 라우터 등록 중 오류가 발생했습니다.");
+        }
+    }
+    /** ********************************* 게시판 라우터 (종료) ********************************* */
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/service/Impl/BbsTypeMngServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/Impl/BbsTypeMngServiceImpl.java
@@ -0,0 +1,76 @@
+package com.takensoft.cms.bbs.service.Impl;
+
+import com.takensoft.cms.bbs.dao.BbsTypeMngDAO;
+import com.takensoft.cms.bbs.service.BbsTypeMngService;
+import com.takensoft.cms.bbs.vo.BbsTypeMngVO;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 유형 관리 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * BbsTypeMngService : 게시판 유형 관리 인터페이스 상속
+ */
+@Service("bbsTypeMngService")
+@RequiredArgsConstructor
+public class BbsTypeMngServiceImpl extends EgovAbstractServiceImpl implements BbsTypeMngService {
+    private final BbsTypeMngDAO bbsTypeMngDAO;
+    private final IdgenService bbsTypeIdgn;
+    private final JWTUtil jwtUtil;
+
+    /**
+     * @author  박정하
+     * @since   2024.05.08
+     * 게시판 유형 관리 등록
+     */
+    public HashMap<String, Object> insertBbsTypeMng(BbsTypeMngVO bbsTypeMngVO) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+
+        // 게시판 유형 아이디 생성
+        String bbsTypeMngId = bbsTypeIdgn.getNextStringId();
+        bbsTypeMngVO.setBbsTypeId(bbsTypeMngId);
+
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        bbsTypeMngVO.setRgtr(writer);
+
+        // 게시판 관리 등록
+        int insertResult = bbsTypeMngDAO.insertBbsTypeMng(bbsTypeMngVO);
+
+        result.put("bbsTypeMngId", bbsTypeMngId);
+        result.put("result", insertResult);
+        return result;
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 유형 관리 목록 조회
+     */
+    public Map<String, Object> findAllBbsTypeMng(BbsTypeMngVO bbsTypeMngVO) throws Exception {
+        Map<String, Object> result = new HashMap<>();
+
+        List<BbsTypeMngVO> list = bbsTypeMngDAO.findAll(bbsTypeMngVO);
+        result.put("list", list);
+        return result;
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * 게시판 유형 관리 상세 조회
+     */
+    public BbsTypeMngVO findByBbsTypeId(String bbsTypeId) throws Exception {
+        return bbsTypeMngDAO.findByBbsTypeId(bbsTypeId);
+    }
+}
 
src/main/java/com/takensoft/cms/bbs/service/Impl/CmntServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/Impl/CmntServiceImpl.java
@@ -0,0 +1,159 @@
+package com.takensoft.cms.bbs.service.Impl;
+
+import com.takensoft.cms.bbs.dao.CmntDAO;
+import com.takensoft.cms.bbs.dao.WordMngDAO;
+import com.takensoft.cms.bbs.service.CmntService;
+import com.takensoft.cms.bbs.vo.CmntVO;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 방선주
+ * @since   : 2024.05.27
+ *
+ * 게시판 댓글 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * CmntService : 게시판 댓글 인터페이스 상속
+ */
+@Service("cmntService")
+@RequiredArgsConstructor
+public class CmntServiceImpl extends EgovAbstractServiceImpl implements CmntService {
+
+    private final CmntDAO cmntDAO;
+    private final JWTUtil jwtUtil;
+    private final WordMngDAO wordMngDAO;
+
+    /**
+     * @author 방선주
+     * @since  2024.05.27
+     *
+     * 게시판 댓글 등록
+     */
+    public HashMap<String, Object> saveCmnt(CmntVO cmntVO) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+        List<String> wordList = wordMngDAO.findWordList();
+
+        // 내용에 금지어가 포함되어있는가?
+        String content = cmntVO.getCmntCn();
+        for (String word : wordList) {
+            if (content.contains(word)) {
+                result.put("result", -1);
+                result.put("word", word);
+                return result;
+            }
+        }
+
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        if(writer == null) {
+            result.put("result", -2);
+            return result;
+        }
+
+        cmntVO.setRgtr(writer);
+
+        // 댓글 깊이
+        // 부모의 깊이 가져와 +1
+
+        if (cmntVO.getUpCmntId() != 0) {
+            CmntVO parentCmnt = cmntDAO.findParentCmnt(cmntVO.getUpCmntId());
+            cmntVO.setCmntGrd(parentCmnt.getCmntGrd() + 1);
+        }
+
+        // 댓글 순서
+        int count = cmntDAO.getCmntCount(cmntVO);
+        cmntVO.setCmntSn(count + 1);
+
+
+        result.put("result", cmntDAO.saveCmnt(cmntVO));
+
+        return result;
+    }
+
+    /**
+     * @author 방선주
+     * @since  2024.05.27
+     *
+     * 게시판 댓글 목록 조회
+     */
+    public List<CmntVO> findCmntList(String bbsId) throws Exception {
+
+        List<CmntVO> flatCommentList = cmntDAO.findCmntList(bbsId);
+        return buildCommentTree(flatCommentList);
+    }
+
+    private List<CmntVO> buildCommentTree(List<CmntVO> comments) {
+        Map<Integer, CmntVO> commentMap = new HashMap<>();
+        List<CmntVO> rootComments = new ArrayList<>();
+
+        // 댓글 ID를 키로 하여 맵 생성
+        for (CmntVO comment : comments) {
+            commentMap.put(comment.getCmntId(), comment);
+        }
+
+        // 자식 댓글을 부모의 children 리스트에 추가
+        for (CmntVO comment : comments) {
+            Integer parentId = comment.getUpCmntId();
+            if (parentId != null && commentMap.containsKey(parentId)) { // 상위 댓글이 있는 경우
+                CmntVO parent = commentMap.get(parentId);
+                parent.getChildren().add(comment);
+            } else { // 최상위 댓글인 경우 또는 부모가 맵에 없는 경우(데이터 무결성 문제)
+                rootComments.add(comment);
+            }
+        }
+
+        return rootComments; // 최상위 댓글 리스트 반환
+    }
+    /**
+     * @author 방선주
+     * @since  2024.05.27
+     *
+     * 게시판 댓글 업데이트
+     */
+    public HashMap<String, Object> updateCmnt(CmntVO cmntVO) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+        List<String> wordList = wordMngDAO.findWordList();
+
+        // 내용에 금지어가 포함되어있는가?
+        String content = cmntVO.getCmntCn();
+        for (String word : wordList) {
+            if (content.contains(word)) {
+                result.put("result", -1);
+                result.put("word", word);
+                return result;
+            }
+        }
+
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        cmntVO.setMdfr(writer);
+
+        result.put("result", cmntDAO.updateCmnt(cmntVO));
+
+        return result;
+    }
+
+    /**
+     * @author 방선주
+     * @since  2024.05.27
+     *
+     * 게시판 댓글 삭제
+     */
+    public int deleteCmnt(CmntVO cmntVO) throws Exception {
+
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+        cmntVO.setMdfr(writer);
+
+        cmntVO.setUseYn("N");
+
+        return cmntDAO.deleteCmnt(cmntVO);
+    }
+}
 
src/main/java/com/takensoft/cms/bbs/service/Impl/WordMngServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/Impl/WordMngServiceImpl.java
@@ -0,0 +1,83 @@
+package com.takensoft.cms.bbs.service.Impl;
+
+import com.takensoft.cms.bbs.dao.WordMngDAO;
+import com.takensoft.cms.bbs.service.WordMngService;
+import com.takensoft.cms.bbs.vo.WordMngVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+
+@Service("WordMngService")
+@RequiredArgsConstructor
+public class WordMngServiceImpl extends EgovAbstractServiceImpl implements WordMngService {
+
+    private final WordMngDAO wordMngDAO;
+    private final JWTUtil jwtUtil;
+
+    /**
+     * @author 방선주
+     * @since  2024.05.31
+     *
+     * 금지어 추가
+     */
+    @Override
+    public int saveWords(HashMap<String, Object> wordList) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        String writer = jwtUtil.getWriter();
+
+        List<String> wordsArr = (List<String>) wordList.get("wordsArr");
+        // 금지어 등록
+        for (String word : wordsArr){
+            WordMngVO wordMngVO = new WordMngVO();
+            wordMngVO.setCntrlNm(word);
+            wordMngVO.setRgtr(writer);
+            wordMngDAO.saveWords(wordMngVO);
+        }
+
+        return wordList.size();
+    }
+
+    /**
+     * @author 방선주
+     * @since  2024.05.31
+     *
+     * 금지어 목록 조회
+     */
+    @Override
+    public HashMap<String, Object> findAllWord(HashMap<String, String> params) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+
+        Pagination search = new Pagination(0, params);
+        int cnt = wordMngDAO.findAllCnt(search);
+        Pagination pagination = new Pagination(cnt, params);
+        List<WordMngVO> wordList = wordMngDAO.findAllWord(pagination);
+
+        result.put("wordList", wordList);
+        result.put("pagination", pagination);
+        result.put("wordsCnt", cnt);
+
+        return result;
+    }
+    /**
+     * @author 방선주
+     * @since  2024.05.31
+     *
+     * 금지어 삭제
+     */
+    @Override
+    public int deleteWords(HashMap<String, Object> params) throws Exception {
+        List<Integer> wordsArr = (List<Integer>) params.get("wordsArr");
+
+        // 금지어 id로 삭제
+        for (int cntrlNmId : wordsArr){
+            wordMngDAO.deleteWords(cntrlNmId);
+        }
+
+        return wordsArr.size();
+    }
+}
 
src/main/java/com/takensoft/cms/bbs/service/WordMngService.java (added)
+++ src/main/java/com/takensoft/cms/bbs/service/WordMngService.java
@@ -0,0 +1,18 @@
+package com.takensoft.cms.bbs.service;
+
+import com.takensoft.cms.bbs.vo.WordMngVO;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public interface WordMngService {
+    // 금지어 관리 등록
+    public int saveWords(HashMap<String, Object> wordList) throws Exception;
+
+    // 금지어 관리 목록 조회
+    public HashMap<String, Object> findAllWord(HashMap<String, String> params) throws Exception;
+
+    // 금지어 관리 삭제
+    public int deleteWords(HashMap<String, Object> params) throws Exception;
+}
 
src/main/java/com/takensoft/cms/bbs/vo/BbsCnVO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/vo/BbsCnVO.java
@@ -0,0 +1,144 @@
+package com.takensoft.cms.bbs.vo;
+
+import lombok.*;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.05.09
+ *
+ * 게시판 관리 관련 VO
+ */
+@Setter
+@Getter
+@AllArgsConstructor
+public class BbsCnVO {
+    /**
+     * 게시판 아이디
+     */
+    private String bbsId;
+    /**
+     * 게시판 관리 아이디
+     */
+    private String bbsMngId;
+    /**
+     * 게시판 제목
+     */
+    private String bbsNm;
+    /**
+     * 게시판 내용
+     */
+    private String bbsCn;
+    /**
+     * 조회수
+     */
+    private int inqCnt;
+    /**
+     * 첨부파일 관리 아이디
+     */
+    private String atchFileMngId;
+    /**
+     * 이미지파일 관리 아이디 [ 갤러리형 / 영상형 전용 ]
+     */
+    private String imgFileMngId;
+    /**
+     * 썸네일 이미지 경로
+     */
+    private String absltPath;
+    /**
+     * 공지글 여부
+     * Y : 사용, N : 미사용
+     */
+    private String ntcPstYn;
+    /**
+     * 공지글 시작일
+     */
+    private String ntcBgngDt;
+    /**
+     * 공지글 종료일
+     */
+    private String ntcEndDt;
+    /**
+     * 비밀글 여부
+     * Y : 사용, N : 미사용
+     */
+    private String prvtPstYn;
+    /**
+     * 답변 게시판 아이디
+     */
+    private String ansBbsId;
+    /**
+     * 답변 내용
+     */
+    private String ansCn;
+    /**
+     * 답변 깊이(레벨)
+     */
+    private int ansGrd;
+    /**
+     * 답변 순서
+     */
+    private int ansSn;
+    /**
+     * 답변 상태
+     * Y : 사용, N : 미사용
+     */
+    private String ansStts;
+    /**
+     * 영상 주소
+     */
+    private String vdoUrl;
+    /**
+     * 사용여부
+     * Y : 사용, N : 미사용
+     */
+    private String useYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 등록자 명
+     */
+    private String rgtrNm; // 화면 표출 용도
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+    /**
+     * 수정자 명
+     */
+    private String mdfrNm; // 화면 표출 용도
+    /**
+     * 현재 공지 여부
+     */
+    private String nowNtcYn;
+    /**
+     * 답변자
+     */
+    private String answer;
+    /**
+     * 답변자명
+     */
+    private String answerNm;
+    /**
+     * 답변일자
+     */
+    private String ansDt;
+    
+    public BbsCnVO() {
+        this.bbsCn = "";
+        this.ntcPstYn = "N";
+        this.prvtPstYn = "N";
+        this.ntcBgngDt = null;
+        this.ntcEndDt = null;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/vo/BbsMngVO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/vo/BbsMngVO.java
@@ -0,0 +1,114 @@
+package com.takensoft.cms.bbs.vo;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 관리 관련 VO
+ */
+@Data
+public class BbsMngVO {
+    /**
+     * 게시판관리아이디
+     */
+    private String bbsMngId;
+    /**
+     * 게시판유형아이디
+     */
+    private String bbsTypeId;
+    /**
+     * 게시판유형
+     */
+    private BbsTypeMngVO bbsType; // 사용 안함
+    /**
+     * 게시판명
+     */
+    private String bbsNm;
+    /**
+     * 게시판상단정보
+     */
+    private String bbsUpInfo;
+    /**
+     * 게시판설명
+     */
+    private String bbsExpln;
+    /**
+     * 목록수
+     */
+    private int artclCnt;
+    /**
+     * 첨부파일 사용여부
+     * Y : 사용, N : 미사용
+     */
+    private String atchFileUseYn;
+    /**
+     * 공지글 사용여부
+     * Y : 사용, N : 미사용
+     */
+    private String ntcUseYn;
+    /**
+     * 파일확장자
+     */
+    private List<String> fileExtnNmList;
+    /**
+     * 파일확장자
+     */
+    private String fileExtnNm;
+    /**
+     * 파일크기제한
+     */
+    private int fileSzLmt;
+    /**
+     * 비밀글 사용여부
+     * Y : 사용, N : 미사용
+     */
+    private String prvtPstUseYn;
+    /**
+     * 이전글/다음글 사용여부
+     * Y : 사용, N : 미사용
+     */
+    private String bfrAftrPstUseYn;
+    /**
+     * 댓글 사용여부
+     * Y : 사용, N : 미사용
+     */
+    private String cmntUseYn;
+    /**
+     * 사용여부
+     * Y : 사용, N : 미사용
+     */
+    private String useYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+    /**
+     * 페이지 유형
+     */
+    private String cd;
+    /**
+     * 게시물 수
+     */
+    private int bbsCnCnt;
+
+    public BbsMngVO() {
+        this.fileExtnNmList = new ArrayList<>();
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/vo/BbsRouterVO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/vo/BbsRouterVO.java
@@ -0,0 +1,55 @@
+package com.takensoft.cms.bbs.vo;
+
+import lombok.Data;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 관리 관련 VO
+ */
+@Data
+public class BbsRouterVO {
+    /**
+     * 게시판 라우터 아이디
+     */
+    private String bbsRouterId;
+    /**
+     * 게시판 관리 아이디
+     */
+    private String bbsMngId;
+    /**
+     * 게시판 한글명
+     */
+    private String bbsKornNm;
+    /**
+     * 게시판 영문명
+     */
+    private String bbsEngNm;
+    /**
+     * 사용자 페이지 경로
+     */
+    private String pageCrs;
+    /**
+     * 관리자 페이지 경로
+     */
+    private String mngrPageCrs;
+    /**
+     * 컴포넌트 경로
+     */
+    private String compnCrs;
+    /**
+     * 노출여부
+     * Y : 노출, N : 미노출
+     */
+    private String expsrYn;
+    /**
+     * 사용여부
+     * Y : 사용, N : 미사용
+     */
+    private String useYn;
+    /**
+     * 등록일
+     */
+    private String regDt;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/vo/BbsTypeMngVO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/vo/BbsTypeMngVO.java
@@ -0,0 +1,63 @@
+package com.takensoft.cms.bbs.vo;
+
+import lombok.Data;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 유형 관리 관련 VO
+ */
+@Data
+public class BbsTypeMngVO {
+    /**
+     * 게시판유형아이디
+     */
+    private String bbsTypeId;
+    /**
+     * 게시판유형한글명
+     */
+    private String bbsTypeKornNm;
+    /**
+     * 게시판유형영문명
+     */
+    private String bbsTypeEngNm;
+    /**
+     * 게시판유형
+     */
+    private String bbsType;
+    /**
+     * 페이지경로
+     */
+    private String pageCrs;
+    /**
+     * 컴포넌트경로
+     */
+    private String compnCrs;
+    /**
+     * 노출여부
+     * Y: 예, N: 아니오
+     */
+    private String expsrYn;
+    /**
+     * 사용여부
+     * Y: 사용, N: 미사용
+     */
+    private String useYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/vo/CmntVO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/vo/CmntVO.java
@@ -0,0 +1,79 @@
+package com.takensoft.cms.bbs.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : 방선주
+ * @since   : 2024.05.27
+ *
+ * 게시판 댓글 관련 VO
+ */
+@Setter
+@Getter
+public class CmntVO {
+    /**
+     * 게시판 댓글 아이디
+     */
+    private int cmntId;
+    /**
+     * 게시판 아이디
+     */
+    private String bbsId;
+    /**
+     * 상위 댓글 아이디
+     */
+    private int upCmntId;
+    /**
+     * 댓글 내용
+     */
+    private String cmntCn;
+    /**
+     * 댓글 깊이 (레벨)
+     */
+    private int cmntGrd;
+    /**
+     * 댓글 순서
+     */
+    private int cmntSn;
+    /**
+     * 사용여부
+     */
+    private String useYn;
+    /**
+     * 작성자
+     */
+    private String rgtr;
+    /**
+     * 작성일자
+     */
+    private String regDt;
+    /**
+     * 등록자 명
+     */
+    private String rgtrNm;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일자
+     */
+    private String mdfcnDt;
+    /**
+     * 수정자 명
+     */
+    private String mdfrNm; // 화면 표출 용도
+
+    private List<CmntVO> children; // 자식 댓글 목록
+
+    public CmntVO() {
+        this.upCmntId = 0;
+        this.cmntGrd = 0;
+        this.cmntSn = 0;
+        this.children = new ArrayList<>();
+    }
+}
 
src/main/java/com/takensoft/cms/bbs/vo/WordMngVO.java (added)
+++ src/main/java/com/takensoft/cms/bbs/vo/WordMngVO.java
@@ -0,0 +1,25 @@
+package com.takensoft.cms.bbs.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author  : 방선주
+ * @since   : 2024.05.31
+ *
+ * 금지단어 관련 VO
+ */
+@Setter
+@Getter
+public class WordMngVO {
+    // 금지어 관리 번호
+    private int cntrlNmId;
+    // 금지어
+    private String cntrlNm;
+    // 등록자명
+    private String rgtrNm;
+    // 등록자 아이디
+    private String rgtr;
+    // 등록일
+    private String regDt;
+}
 
src/main/java/com/takensoft/cms/bbs/web/BbsCnController.java (added)
+++ src/main/java/com/takensoft/cms/bbs/web/BbsCnController.java
@@ -0,0 +1,472 @@
+package com.takensoft.cms.bbs.web;
+
+import com.takensoft.cms.bbs.service.BbsCnService;
+import com.takensoft.cms.bbs.service.BbsMngService;
+import com.takensoft.cms.bbs.service.CmntService;
+import com.takensoft.cms.bbs.vo.BbsCnVO;
+import com.takensoft.cms.bbs.vo.BbsMngVO;
+import com.takensoft.cms.bbs.vo.CmntVO;
+import com.takensoft.common.file.service.FileService;
+import com.takensoft.common.file.vo.FileVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.05.09
+ *
+ * 게시판 내용 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value="/sys/bbsCn")
+public class BbsCnController {
+
+    private final BbsCnService bbsCnService;
+    private final BbsMngService bbsMngService;
+    private final FileService fileService;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * @param   bbsCnVO
+     * @return
+     * @throws  Exception
+     *
+     * 게시판 내용 등록
+     */
+//    @PostMapping("/saveProc.json")
+//    public ResponseEntity<?> saveProc(@RequestBody BbsCnVO bbsCnVO) throws Exception {
+//        // 응답 처리
+//        HttpHeaders headers = new HttpHeaders();
+//        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+//        ResponseData responseData = new ResponseData();
+//
+//        // 게시판 내용 등록
+//        int result = bbsCnService.saveBbsCn(bbsCnVO);
+//        if(result > 0) {
+//            responseData.setStatus(HttpStatus.OK);
+//            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+//            responseData.setData(result);
+//            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+//        } else {
+//            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+//            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+//            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+//        }
+//    }
+    /**
+     * @author 방선주
+     * @since 2024.05.21
+     * @param bbsCn, multipartFileList
+     * @return
+     * @throws Exception
+     *
+     * 게시판 내용 등록
+     */
+    @PostMapping(path = "/saveBbsCn.file")
+    public ResponseEntity<?> saveBbsCn(@RequestPart BbsCnVO bbsCn, List<MultipartFile> multipartFileList, List<MultipartFile> multipartImgList) throws Exception {
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 게시판 내용 등록
+        HashMap<String, Object> result = bbsCnService.saveBbsCn(bbsCn, multipartFileList, multipartImgList);
+        int insertResult = (int) result.get("result");
+
+        if (insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else if (insertResult == -1){
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("아래의 금지어가 포함되어 있습니다.\n* " + result.get("word"));
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.09
+     * @param   params
+     * @return
+     * @throws  Exception
+     *
+     * 게시판 내용 목록 조회
+     */
+    @PostMapping("/findAll.json")
+    public ResponseEntity<?> findAll(@RequestBody HashMap<String, String> params) throws Exception {
+        // 게시판 내용 목록 조회
+        Map<String, Object> result = bbsCnService.findAllBbsCn(params);
+
+        // 응답처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     * @param  bbsCnVO
+     * @return
+     * @throws Exception
+     *
+     * 게시판 내용 상세 조회
+     */
+    @PostMapping("/findByBbsCn.json")
+    public ResponseEntity<?> findByBbsCn(@RequestBody BbsCnVO bbsCnVO) throws Exception {
+
+        // 게시판 관리 정보 조회
+        BbsMngVO bbsMng = bbsMngService.findByBbsMngId(bbsCnVO.getBbsMngId());
+        // 게시판 내용 상세 조회
+        BbsCnVO bbsCn = bbsCnService.findByBbsId(bbsCnVO.getBbsId());
+        // 첨부파일 목록 조회
+        String fileMngId = bbsCn.getAtchFileMngId();
+        List<HashMap<String,Object>> fileList = bbsCnService.fileListPathChange(fileMngId);
+        //이미지 파일 목록 조회
+        String imgFileMngId = bbsCn.getImgFileMngId();
+        List<HashMap<String,Object>> imgFileList = bbsCnService.fileListPathChange(imgFileMngId);
+
+
+        // 이전글 다음글 조회
+        BbsCnVO prevBbsCn = bbsCnService.findPrevBbsCn(bbsCnVO);
+        BbsCnVO nextBbsCn = bbsCnService.findNextBbsCn(bbsCnVO);
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("bbsMng", bbsMng);
+        result.put("bbsCn", bbsCn);
+        result.put("fileList", fileList);
+        result.put("imgFileList", imgFileList);
+        result.put("prevBbsCn", prevBbsCn);
+        result.put("nextBbsCn", nextBbsCn);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+//    /**
+//     * @author 하석형
+//     * @since  2024.05.09
+//     * @param  bbsCnVO
+//     * @return
+//     * @throws Exception
+//     *
+//     * 게시판 내용 수정
+//     */
+//    @PostMapping("/updateProc.json")
+//    public ResponseEntity<?> updateProc(@RequestBody BbsCnVO bbsCnVO) throws Exception {
+//        HttpHeaders headers = new HttpHeaders();
+//        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+//        ResponseData responseData = new ResponseData();
+//
+//        // 게시판 내용 수정
+//        int result = bbsCnService.updateBbsCn(bbsCnVO);
+//
+//        // 응답 처리
+//        if(result > 0) {
+//            responseData.setStatus(HttpStatus.OK);
+//            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+//            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+//        } else {
+//            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+//            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+//            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+//        }
+//    }
+    /**
+     * @author 방선주
+     * @since 2024.05.21
+     * @param params, multipartFileList
+     * @return
+     * @throws Exception
+     *
+     * 게시판 내용 수정
+     */
+    @PostMapping(path = "/updateBbsCn.file")
+    public ResponseEntity<?> updateBbsCn(@RequestPart HashMap<String, Object> params, @RequestPart List<HashMap<String, Object>> deleteFileList, List<MultipartFile> multipartFileList, @RequestPart List<HashMap<String, Object>> deleteImgFileList, List<MultipartFile> multipartImgList) throws Exception {
+
+        // 게시판 내용 수정
+        HashMap<String, Object> result = bbsCnService.updateBbsCn(params, deleteFileList, multipartFileList, deleteImgFileList, multipartImgList);
+
+        int updateResult = (int) result.get("result");
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if (updateResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 게시글이 수정 되었습니다.");
+            responseData.setData(params.get("bbsId"));
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else if (updateResult == -1){
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("아래의 금지어가 포함되어 있습니다.\n* " + result.get("word"));
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+
+        } else {
+            responseData.setStatus(HttpStatus.BAD_REQUEST);
+            responseData.setMessage("게시글 수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.BAD_REQUEST);
+        }
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     * @param  bbsCnVO
+     * @return
+     * @throws Exception
+     *
+     * 게시판 내용 삭제
+     */
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody BbsCnVO bbsCnVO) throws Exception {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 게시판 내용 수정
+        int result = bbsCnService.deleteBbsCn(bbsCnVO);
+
+        // 응답 처리
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+    /**
+     * @author 방선주
+     * @since  2024.05.22
+     * @param  params
+     * @return
+     * @throws Exception
+     *
+     * 조회수 증가
+     */
+    @PostMapping("/updateVwCnt.json")
+    public ResponseEntity<?> updateVwCnt(@RequestBody HashMap<String, Object> params) throws Exception {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        
+        // 조회수 증가
+        int result = bbsCnService.updateVwCnt(params);
+
+        // 응답 처리
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 조회수가 증가되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("조회수 증가에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 방선주
+     * @since  2024.05.21
+     * @param  fileId
+     * @return
+     * @throws Exception
+     *
+     * 게시판 첨부 파일 다운로드
+     */
+    @PostMapping("/fileDownload.json")
+    public void fileDownload(@RequestBody int fileId, HttpServletResponse response) throws Exception {
+
+        // 파일 정보 조회
+        FileVO file = fileService.fileSelectOne(fileId);
+        File downloadFile = null;
+        // 받은 파일 정보로 파일 다운로드 생성
+        if(file != null){
+            String filePath = file.getAbsltPath();
+            downloadFile = new File(filePath);
+
+            response.setContentType("application/octet-stream");
+            response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(file.getFileNm(), "UTF-8") + "\"");
+            response.setHeader("Content-Transfer-Encoding", "binary");
+
+            try (OutputStream out = response.getOutputStream(); FileInputStream fis = new FileInputStream(downloadFile)) {
+                byte[] buffer = new byte[1024];
+                int bytesRead;
+                while ((bytesRead = fis.read(buffer)) != -1) {
+                    out.write(buffer, 0, bytesRead);
+                }
+            }
+        }
+    }
+
+
+    /********* 질의형 게시판 **********/
+
+    /**
+     * @author  방선주
+     * @since   2024.05.31
+     * @param   bbsCnVO
+     * @return
+     * @throws  Exception
+     *
+     * 질의형 게시판 답변 등록
+     */
+    @PostMapping("/ansSaveProc.json")
+    public ResponseEntity<?> ansSaveProc(@RequestBody BbsCnVO bbsCnVO) throws Exception {
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+//        int result = 1;
+        HashMap<String, Object> result = bbsCnService.saveAnswer(bbsCnVO);
+        int insertResult = (int) result.get("result");
+
+
+        if(insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else if (insertResult == -1){
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("아래의 금지어가 포함되어 있습니다.\n* " + result.get("word"));
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+    /**
+     * @author  방선주
+     * @since   2024.05.31
+     * @param   bbsCnVO
+     * @return
+     * @throws  Exception
+     *
+     * 질의형 게시판 답변 수정
+     */
+    @PostMapping("/ansUpdateProc.json")
+    public ResponseEntity<?> ansUpdateProc(@RequestBody BbsCnVO bbsCnVO) throws Exception {
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+//        int result = 1;
+        HashMap<String, Object> result = bbsCnService.updateAnswer(bbsCnVO);
+        int updateResult = (int) result.get("result");
+
+        if(updateResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else if (updateResult == -1){
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("아래의 금지어가 포함되어 있습니다.\n* " + result.get("word"));
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+    /**
+     * @author  방선주
+     * @since   2024.06.07
+     * @param   bbsCnVO
+     * @return
+     * @throws  Exception
+     *
+     * 질의형 게시판 답변 삭제
+     */
+    @PostMapping("/ansDeleteProc.json")
+    public ResponseEntity<?> ansDeleteProc(@RequestBody BbsCnVO bbsCnVO) throws Exception {
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+//        int result = 1;
+        int result = bbsCnService.deleteAns(bbsCnVO);
+
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+    /**
+     * @author  방선주
+     * @since   2024.06.13
+     * @param
+     * @return
+     * @throws  Exception
+     *
+     * 공지사항 최신 5개 조회
+     */
+    @PostMapping("/findFiveNotice.json")
+    public ResponseEntity<?> findFiveNotice(@RequestBody BbsCnVO bbsCn) throws Exception {
+        // 공지사항 최신 5개 조회
+        List<BbsCnVO> result = bbsCnService.findFiveNotice(bbsCn);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/web/BbsMngController.java (added)
+++ src/main/java/com/takensoft/cms/bbs/web/BbsMngController.java
@@ -0,0 +1,224 @@
+package com.takensoft.cms.bbs.web;
+
+import com.takensoft.cms.bbs.service.BbsCnService;
+import com.takensoft.cms.bbs.service.BbsMngService;
+import com.takensoft.cms.bbs.service.BbsTypeMngService;
+import com.takensoft.cms.bbs.vo.BbsMngVO;
+import com.takensoft.cms.bbs.vo.BbsTypeMngVO;
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.common.HierachyVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 관리 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value="/admin/bbsMng")
+public class BbsMngController {
+
+    private final BbsMngService bbsMngService;
+    private final BbsTypeMngService bbsTypeMngService;
+    private final CodeManageService codeManageService;
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * @param   bbsMngVO
+     * @return
+     * @throws  Exception
+     *
+     * 게시판 관리 등록
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> saveProc(@RequestBody BbsMngVO bbsMngVO) throws Exception {
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 게시판 관리 아이디 중복 검사 (아이디 입력 삭제로 미사용)
+        /*boolean isExistence = bbsMngService.bbsMngIdCheck(bbsMngVO);
+        if(isExistence) {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("이미 존재하는 게시판 아이디입니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }*/
+
+        // 게시판 관리 등록
+        HashMap<String, Object> result = bbsMngService.saveBbsMng(bbsMngVO);
+        int insertResult = (int) result.get("result");
+        if(insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.10
+     * @param   params
+     * @return
+     * @throws  Exception
+     *
+     * 게시판 관리 목록 조회
+     */
+    @PostMapping("/findAll.json")
+    public ResponseEntity<?> findAll(@RequestBody HashMap<String, String> params) throws Exception {
+        // 게시판 관리 목록 조회
+        Map<String, Object> result = bbsMngService.findAllBbsMng(params);
+
+        // 응답처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author  박정하
+     * @since   2024.05.16
+     * @param
+     * @return
+     * @throws  Exception
+     *
+     * 게시판 관리 목록 조회 (메뉴 관리용)
+     */
+    @PostMapping("/findAllByMenuMng.json")
+    public ResponseEntity<?> findAllByMenuMng() throws Exception {
+        // 게시판 관리 목록 조회
+        List<BbsMngVO> result = bbsMngService.findAllByMenuMng();
+
+        // 응답처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.08
+     * @param  bbsMngVO
+     * @return
+     * @throws Exception
+     *
+     * 게시판 관리 상세 조회
+     */
+    @PostMapping("/findByBbsMng.json")
+    public ResponseEntity<?> findByBbsMng(@RequestBody BbsMngVO bbsMngVO) throws Exception {
+        // 게시판 관리 상세 조회
+        BbsMngVO bbsMng = bbsMngService.findByBbsMngId(bbsMngVO.getBbsMngId());
+
+        // 게시판 유형 목록 조회
+        BbsTypeMngVO bbsTypeMap = new BbsTypeMngVO();
+        bbsTypeMap.setExpsrYn("Y");
+        List<BbsTypeMngVO> bbsType = (List<BbsTypeMngVO>) bbsTypeMngService.findAllBbsTypeMng(bbsTypeMap).get("list");
+        // 페이지 유형 목록 조회
+        List<CodeManageVO> pageType = codeManageService.findByChildCdCache("pageType");
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("bbsMng", bbsMng);
+        result.put("bbsTypeList", bbsType);
+        result.put("pageTypeList", pageType);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     * @param  bbsMngVO
+     * @return
+     * @throws Exception
+     *
+     * 게시판 관리 수정
+     */
+    @PostMapping("/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody BbsMngVO bbsMngVO) throws Exception {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 게시판 관리 수정
+        int result = bbsMngService.updateBbsMng(bbsMngVO);
+
+        // 응답 처리
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 하석형
+     * @since  2024.05.09
+     * @param  bbsMngVO
+     * @return
+     * @throws Exception
+     *
+     * 게시판 관리 삭제
+     */
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody BbsMngVO bbsMngVO) throws Exception {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 게시판 관리 수정
+        int result = bbsMngService.deleteBbsMng(bbsMngVO);
+
+        // 응답 처리
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/bbs/web/BbsTypeMngController.java (added)
+++ src/main/java/com/takensoft/cms/bbs/web/BbsTypeMngController.java
@@ -0,0 +1,85 @@
+package com.takensoft.cms.bbs.web;
+
+import com.takensoft.cms.bbs.service.BbsTypeMngService;
+import com.takensoft.cms.bbs.vo.BbsTypeMngVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.08
+ *
+ * 게시판 유형 관리 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value="/admin/bbsTypeMng")
+public class BbsTypeMngController {
+    private final BbsTypeMngService bbsTypeMngService;
+
+    /**
+     * @author  박정하
+     * @since   2024.05.08
+     * @param   bbsTypeMngVO
+     * @return
+     * @throws  Exception
+     *
+     * 게시판 유형 관리 등록
+     */
+    @PostMapping("/insertBbsTypeMng.json")
+    public ResponseEntity<?> insertBbsTypeMng(@RequestBody BbsTypeMngVO bbsTypeMngVO) throws Exception {
+        // 게시판 관리 등록
+        HashMap<String, Object> result = bbsTypeMngService.insertBbsTypeMng(bbsTypeMngVO);
+        int insertResult = (int) result.get("result");
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.05.13
+     * @param   bbsTypeMngVO
+     * @return
+     * @throws  Exception
+     *
+     * 게시판 유형 관리 목록 조회
+     */
+    @PostMapping("/findAll.json")
+    public ResponseEntity<?> findAll(@RequestBody BbsTypeMngVO bbsTypeMngVO) throws Exception{
+        // 게시판 유형 관리 목록 조회
+        Map<String, Object> result = bbsTypeMngService.findAllBbsTypeMng(bbsTypeMngVO);
+
+        // 응답처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}
 
src/main/java/com/takensoft/cms/bbs/web/CmntController.java (added)
+++ src/main/java/com/takensoft/cms/bbs/web/CmntController.java
@@ -0,0 +1,174 @@
+package com.takensoft.cms.bbs.web;
+
+import com.takensoft.cms.bbs.service.CmntService;
+import com.takensoft.cms.bbs.vo.CmntVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 방선주
+ * @since   : 2024.05.27
+ *
+ * 게시판 댓글 관련 Controller
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value="/sys/cmnt")
+public class CmntController {
+
+    private final CmntService cmntService;
+
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * @param   cmntVO
+     * @return
+     * @throws  Exception
+     *
+     * 댓글 등록
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> saveProc(@RequestBody CmntVO cmntVO) throws Exception {
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 댓글 등록
+
+        HashMap<String,Object> result = cmntService.saveCmnt(cmntVO);
+
+        int insertResult = (int) result.get("result");
+
+        if(insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else if (insertResult == -1) {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("아래의 금지어가 포함되어 있습니다.\n* " + result.get("word"));
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        } else if (insertResult == -2){
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("로그인 후 이용 가능합니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+
+    }
+
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * @param   cmntVO
+     * @return
+     * @throws  Exception
+     *
+     * 댓글 목록 조회
+     */
+    @PostMapping("/findCmntList.json")
+    public ResponseEntity<?> findCmntList(@RequestBody CmntVO cmntVO) throws Exception {
+        // 댓글 목록 조회
+        List<CmntVO> cmntList = cmntService.findCmntList(cmntVO.getBbsId());
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("cmntList", cmntList);
+
+        // 응답처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+
+    }
+
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * @param   cmntVO
+     * @return
+     * @throws  Exception
+     *
+     * 댓글 수정
+     */
+    @PostMapping("/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody CmntVO cmntVO) throws Exception {
+// 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 댓글 수정
+        HashMap<String, Object> result = cmntService.updateCmnt(cmntVO);
+        int updateResult = (int) result.get("result");
+
+        // 응답처리
+        if(updateResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else if (updateResult == -1){
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("아래의 금지어가 포함되어 있습니다.\n* " + result.get("word"));
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+
+    }
+    /**
+     * @author  방선주
+     * @since   2024.05.27
+     * @param   cmntVO
+     * @return
+     * @throws  Exception
+     *
+     * 댓글 삭제
+     */
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody CmntVO cmntVO) throws Exception {
+
+        // 댓글 삭제 처리 (댓글 삭제는 업데이트로 처리 useYn = 'N')
+        int result = cmntService.deleteCmnt(cmntVO);
+
+        // 응답처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 삭제가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+
+    }
+
+
+
+
+}
 
src/main/java/com/takensoft/cms/bbs/web/WordMngController.java (added)
+++ src/main/java/com/takensoft/cms/bbs/web/WordMngController.java
@@ -0,0 +1,106 @@
+package com.takensoft.cms.bbs.web;
+
+import com.takensoft.cms.bbs.service.WordMngService;
+import com.takensoft.cms.bbs.vo.WordMngVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 방선주
+ * @since   : 2024.05.31
+ *
+ * 금지 단어 관리 Controller
+ */
+
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value="/wordMng")
+public class WordMngController {
+
+    private final WordMngService wordMngService;
+
+    /**
+     * @author  방선주
+     * @since   2024.05.09
+     * @param   wordList
+     * @return
+     * @throws  Exception
+     *
+     * 금지어 추가
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> saveProc(@RequestBody HashMap<String, Object> wordList) throws Exception {
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 금지어 등록
+        int result = wordMngService.saveWords(wordList);
+
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+    @PostMapping("/findAll.json")
+    public ResponseEntity<?> findAll(@RequestBody HashMap<String, String> params) throws Exception {
+        // 금지어 목록 조회
+        Map<String, Object> result = new HashMap<>();
+        HashMap<String, Object> wordsList = wordMngService.findAllWord(params);
+
+
+        result.put("words", wordsList);
+
+        // 응답처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody HashMap<String, Object> params) throws Exception {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 금지어 삭제
+        int result = wordMngService.deleteWords(params);
+
+        // 응답 처리
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}
 
src/main/java/com/takensoft/cms/cntnStats/dao/CntnStatsDAO.java (added)
+++ src/main/java/com/takensoft/cms/cntnStats/dao/CntnStatsDAO.java
@@ -0,0 +1,146 @@
+package com.takensoft.cms.cntnStats.dao;
+
+import com.takensoft.cms.cntnStats.vo.CntnStatsVO;
+import com.takensoft.cms.popup.vo.PopupVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.23
+ *
+ * 접속통계 관련 Mapper
+ */
+@Mapper("cntnStatsDAO")
+public interface CntnStatsDAO {
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 사용자 접속 통계 등록 검증
+     */
+    boolean userCntnStatsSaveChck(CntnStatsVO cntnStatsVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 사용자 접속 통계 등록
+     */
+    int userCntnStatsSave(CntnStatsVO cntnStatsVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 사용자 접속 통계 수정
+     */
+    int userCntnStatsUpdate(CntnStatsVO cntnStatsVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 컨텐츠 접속 통계 등록 검증
+     */
+    boolean contsCntnStatsSaveChck(CntnStatsVO cntnStatsVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 컨텐츠 접속 통계 등록
+     */
+    int contsCntnStatsSave(CntnStatsVO cntnStatsVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 컨텐츠 접속 통계 수정
+     */
+    int contsCntnStatsUpdate(CntnStatsVO cntnStatsVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 게시판 접속 통계 등록 검증
+     */
+    boolean bbsCntnStatsSaveChck(CntnStatsVO cntnStatsVO);
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 게시판 접속 통계 등록
+     */
+    int bbsCntnStatsSave(CntnStatsVO cntnStatsVO);
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 컨텐츠 접속 통계 수정
+     */
+    int bbsCntnStatsUpdate(CntnStatsVO cntnStatsVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 메뉴 접속 통계 등록 검증
+     */
+    boolean menuCntnStatsSaveChck(CntnStatsVO cntnStatsVO);
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 메뉴 접속 통계 등록
+     */
+    int menuCntnStatsSave(CntnStatsVO cntnStatsVO);
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 메뉴 접속 통계 수정
+     */
+    int menuCntnStatsUpdate(CntnStatsVO cntnStatsVO);
+
+    /**
+     * @author 박정하
+     * @since 2024.05.29
+     *
+     * 사용자 접속 통계
+     */
+    public List<HashMap<String, Object>> selectUserCntnStats(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.29
+     *
+     * 사용자 접속 통계 총 개수
+     */
+    public int selectUserCntnStatsCnt(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     *
+     * 메뉴별 접속 통계
+     */
+    public List<HashMap<String, Object>> selectMenuCntnStats(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     *
+     * 메뉴별 접속 통계 총 개수
+     */
+    public int selectMenuCntnStatsCnt(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     *
+     * 게시판 접속 통계
+     */
+    public List<HashMap<String, Object>> selectBbsCntnStats(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     *
+     * 게시판 접속 통계 총 개수
+     */
+    public int selectBbsCntnStatsCnt(HashMap<String, Object> params) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/cntnStats/dto/CntnStatsDTO.java (added)
+++ src/main/java/com/takensoft/cms/cntnStats/dto/CntnStatsDTO.java
@@ -0,0 +1,29 @@
+package com.takensoft.cms.cntnStats.dto;
+
+import lombok.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.23
+ *
+ * 접속 통계 관련 DTO
+ */
+@Setter
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ToString
+public class CntnStatsDTO {
+    /**
+     * 타입 아이디
+     */
+    private String typeId;
+    /**
+     * 권한 목록
+     */
+    private List<String> mbrAuthList = new ArrayList<String>();
+}
 
src/main/java/com/takensoft/cms/cntnStats/dto/CntnStatsExcelDTO.java (added)
+++ src/main/java/com/takensoft/cms/cntnStats/dto/CntnStatsExcelDTO.java
@@ -0,0 +1,42 @@
+package com.takensoft.cms.cntnStats.dto;
+
+import com.takensoft.common.excel.annotation.ExcelColumnName;
+import com.takensoft.common.excel.annotation.ExcelFileName;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import javax.persistence.*;
+
+@Entity
+@Getter
+@Setter
+@NoArgsConstructor
+@ExcelFileName(fileName="게시판 접속 통계")
+public class CntnStatsExcelDTO {
+    @Id
+    @Column
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @ExcelColumnName(headerName = "구분")
+    private String date;
+
+    @Column
+    @ExcelColumnName(headerName = "관리자")
+    private int admin;
+
+    @Column
+    @ExcelColumnName(headerName = "사용자")
+    private int user;
+
+    @Column
+    @ExcelColumnName(headerName = "비로그인 사용자")
+    private int none;
+
+    @Builder
+    public CntnStatsExcelDTO(String date, int admin, int user, int none) {
+        this.date = date;
+        this.admin = admin;
+        this.user = user;
+        this.none = none;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/cntnStats/service/CntnStatsService.java (added)
+++ src/main/java/com/takensoft/cms/cntnStats/service/CntnStatsService.java
@@ -0,0 +1,49 @@
+package com.takensoft.cms.cntnStats.service;
+
+import com.takensoft.cms.cntnStats.dto.CntnStatsDTO;
+import com.takensoft.cms.popup.vo.PopupVO;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.23
+ *
+ * 접속통계 관련 인터페이스
+ */
+public interface CntnStatsService {
+
+    /**
+     * @author  : takensoft
+     * @since   : 2024.05.23
+     *
+     * 접속 통계 등록
+     */
+    public int cntnStatsSave(CntnStatsDTO cntnStatsDTO) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.29
+     *
+     * 사용자 접속 통계
+     */
+    public HashMap<String, Object> userCntnStatsSelect(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     *
+     * 메뉴별 접속 통계
+     */
+    public HashMap<String, Object> menuCntnStatsSelect(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     *
+     * 게시판 접속 통계
+     */
+    public HashMap<String, Object> bbsCntnStatsSelect(HashMap<String, Object> params) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/cntnStats/service/Impl/CntnStatsServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/cntnStats/service/Impl/CntnStatsServiceImpl.java
@@ -0,0 +1,207 @@
+package com.takensoft.cms.cntnStats.service.Impl;
+
+import com.takensoft.cms.bbs.dao.BbsMngDAO;
+import com.takensoft.cms.cntnStats.dao.CntnStatsDAO;
+import com.takensoft.cms.cntnStats.dto.CntnStatsDTO;
+import com.takensoft.cms.cntnStats.service.CntnStatsService;
+import com.takensoft.cms.cntnStats.vo.CntnStatsVO;
+import com.takensoft.cms.menu.dao.MenuDAO;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.util.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.23
+ *
+ * 접속통계 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * CntnStatsService : 접속 통계 관련 인터페이스 상속
+ */
+@Service("cntnStatsService")
+@RequiredArgsConstructor
+public class CntnStatsServiceImpl extends EgovAbstractServiceImpl implements CntnStatsService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CntnStatsServiceImpl.class);
+    private final CntnStatsDAO cntnStatsDAO;
+    private final BbsMngDAO bbsMngDAO;
+    private final MenuDAO menuDAO;
+
+    /**
+     * @author  : takensoft
+     * @since   : 2024.05.23
+     *
+     * 접속 통계 등록
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int cntnStatsSave(CntnStatsDTO cntnStatsDTO) throws Exception {
+        LocalDate date = LocalDate.now(); // 오늘 금일 날짜 출력
+        CntnStatsVO vo = new CntnStatsVO(); // 접속 통계 객체 생성
+
+        vo.setCntnYr(String.valueOf(date.getYear())); // 년도 추출
+        vo.setCntnMm(String.format("%02d", date.getMonthValue())); // 월 추출
+        vo.setCntnDay(String.format("%02d", date.getDayOfMonth())); // 일 추출
+
+        int result = 0;
+
+        // 사용자 접속 통계 생성
+        if(cntnStatsDTO.getTypeId() == null || cntnStatsDTO.getTypeId().equals("")) {
+            result += userCntnStatsSave(vo, cntnStatsDTO);
+        // 메뉴 접속 통계 생성
+        } else if(cntnStatsDTO.getTypeId().contains("MENU")) {
+            result += menuCntnStatsSave(vo, cntnStatsDTO);
+        // 게시판 접속 통계 생성
+        } else if(cntnStatsDTO.getTypeId().contains("BBS")) {
+            result += bbsCntnStatsSave(vo, cntnStatsDTO);
+        // 콘텐츠 접속 통게 생성
+        } else if(cntnStatsDTO.getTypeId().contains("CONTS")) {
+            result += contsCntnStatsSave(vo, cntnStatsDTO);
+        }
+
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 사용자 접속 통계 등록
+     */
+    private int userCntnStatsSave(CntnStatsVO cntnStatsVO, CntnStatsDTO cntnStatsDTO) throws Exception {
+        int result = 0;
+        for(String auth : cntnStatsDTO.getMbrAuthList()) {
+            cntnStatsVO.setAuthrtCd(auth);
+            boolean chck = cntnStatsDAO.userCntnStatsSaveChck(cntnStatsVO);
+            // 카운트 증가
+            if(chck) {
+                result += cntnStatsDAO.userCntnStatsUpdate(cntnStatsVO);
+            // 신규 등록
+            } else {
+                result += cntnStatsDAO.userCntnStatsSave(cntnStatsVO);
+            }
+        }
+        return result;
+    };
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 컨텐츠 접속 통계 등록
+     */
+    private int contsCntnStatsSave(CntnStatsVO cntnStatsVO, CntnStatsDTO cntnStatsDTO)throws Exception {
+        int result = 0;
+        for(String auth : cntnStatsDTO.getMbrAuthList()) {
+            cntnStatsVO.setAuthrtCd(auth);
+            cntnStatsVO.setTypeId(cntnStatsDTO.getTypeId());
+            boolean chck = cntnStatsDAO.contsCntnStatsSaveChck(cntnStatsVO);
+            // 카운트 증가
+            if(chck) {
+                result += cntnStatsDAO.contsCntnStatsUpdate(cntnStatsVO);
+                // 신규 등록
+            } else {
+                result += cntnStatsDAO.contsCntnStatsSave(cntnStatsVO);
+            }
+        }
+        return result;
+    };
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 게시판 접속 통계 등록
+     */
+    private int bbsCntnStatsSave(CntnStatsVO cntnStatsVO, CntnStatsDTO cntnStatsDTO)throws Exception {
+        int result = 0;
+        for(String auth : cntnStatsDTO.getMbrAuthList()) {
+            cntnStatsVO.setAuthrtCd(auth);
+            cntnStatsVO.setTypeId(cntnStatsDTO.getTypeId());
+            boolean chck = cntnStatsDAO.bbsCntnStatsSaveChck(cntnStatsVO);
+            // 카운트 증가
+            if(chck) {
+                result += cntnStatsDAO.bbsCntnStatsUpdate(cntnStatsVO);
+                // 신규 등록
+            } else {
+                result += cntnStatsDAO.bbsCntnStatsSave(cntnStatsVO);
+            }
+        }
+        return result;
+    };
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * 메뉴 접속 통계 등록
+     */
+    private int menuCntnStatsSave(CntnStatsVO cntnStatsVO, CntnStatsDTO cntnStatsDTO)throws Exception {
+        int result = 0;
+        for(String auth : cntnStatsDTO.getMbrAuthList()) {
+            cntnStatsVO.setAuthrtCd(auth);
+            cntnStatsVO.setTypeId(cntnStatsDTO.getTypeId());
+            boolean chck = cntnStatsDAO.menuCntnStatsSaveChck(cntnStatsVO);
+            // 카운트 증가
+            if(chck) {
+                result += cntnStatsDAO.menuCntnStatsUpdate(cntnStatsVO);
+                // 신규 등록
+            } else {
+                result += cntnStatsDAO.menuCntnStatsSave(cntnStatsVO);
+            }
+        }
+        return result;
+    };
+
+    /**
+     * @author 박정하
+     * @since 2024.05.29
+     *
+     * 사용자 접속 통계
+     */
+    @Override
+    public HashMap<String, Object> userCntnStatsSelect(HashMap<String, Object> params) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("list", cntnStatsDAO.selectUserCntnStats(params));
+        result.put("totalCnt", cntnStatsDAO.selectUserCntnStatsCnt(params));
+        return result;
+    };
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     *
+     * 메뉴별 접속 통계
+     */
+    @Override
+    public HashMap<String, Object> menuCntnStatsSelect(HashMap<String, Object> params) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+        int menuCnt = menuDAO.findAllCnt(params);
+        result.put("menuCnt", menuCnt);
+        if (menuCnt > 0) {
+            result.put("list", cntnStatsDAO.selectMenuCntnStats(params));
+            result.put("totalCnt", cntnStatsDAO.selectMenuCntnStatsCnt(params));
+        }
+        return result;
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     *
+     * 게시판 접속 통계
+     */
+    @Override
+    public HashMap<String, Object> bbsCntnStatsSelect(HashMap<String, Object> params) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+        int bbsCnt = bbsMngDAO.findAllCntNotPagination();
+        result.put("bbsCnt", bbsCnt);
+        if (bbsCnt > 0) {
+            result.put("list", cntnStatsDAO.selectBbsCntnStats(params));
+            result.put("totalCnt", cntnStatsDAO.selectBbsCntnStatsCnt(params));
+        }
+        return result;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/cntnStats/vo/CntnStatsVO.java (added)
+++ src/main/java/com/takensoft/cms/cntnStats/vo/CntnStatsVO.java
@@ -0,0 +1,39 @@
+package com.takensoft.cms.cntnStats.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.23
+ *
+ * 접속 통계 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class CntnStatsVO {
+    /**
+     * 타입 아이디 (게시판/콘텐츠/메뉴)
+     */
+    private String typeId;
+    /**
+     * 권한 코드
+     */
+    private String authrtCd;
+    /**
+     * 접속 년도
+     */
+    private String cntnYr;
+    /**
+     * 접속 월
+     */
+    private String cntnMm;
+    /**
+     * 접속 일
+     */
+    private String cntnDay;
+}
 
src/main/java/com/takensoft/cms/cntnStats/web/CntnStatsController.java (added)
+++ src/main/java/com/takensoft/cms/cntnStats/web/CntnStatsController.java
@@ -0,0 +1,148 @@
+package com.takensoft.cms.cntnStats.web;
+
+import com.takensoft.cms.cntnStats.dto.CntnStatsDTO;
+import com.takensoft.cms.cntnStats.dto.CntnStatsExcelDTO;
+import com.takensoft.cms.cntnStats.service.CntnStatsService;
+import com.takensoft.common.excel.service.ExcelService;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.23
+ *
+ * 접속 통계 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value = "/sys/cntnStats")
+public class CntnStatsController {
+    private final CntnStatsService cntnStatsService;
+    private final ExcelService excelService;
+
+    /**
+     * @author takensoft
+     * @since 2024.05.23
+     * @param cntnStatsDTO
+     * @return
+     * @throws Exception
+     *
+     * 접속 통게 등록
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> saveProc(@RequestBody CntnStatsDTO cntnStatsDTO) throws Exception {
+        int result = cntnStatsService.cntnStatsSave(cntnStatsDTO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.29
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 사용자 접속 통계
+     */
+    @PostMapping("/selectUserCntnStatsProc.json")
+    public ResponseEntity<?> selectUserCntnStatsProc(@RequestBody HashMap<String, Object> params) throws Exception {
+        // 사용자 접속 통계 조회
+        HashMap<String, Object> result = cntnStatsService.userCntnStatsSelect(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 메뉴별 접속 통계
+     */
+    @PostMapping("/selectMenuCntnStatsProc.json")
+    public ResponseEntity<?> selectMenuCntnStatsProc(@RequestBody HashMap<String, Object> params) throws Exception {
+        // 메뉴별 접속 통계 조회
+        HashMap<String, Object> result = cntnStatsService.menuCntnStatsSelect(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 게시판 접속 통계
+     */
+    @PostMapping("/selectBbsCntnStatsProc.json")
+    public ResponseEntity<?> selectBbsCntnStatsProc(@RequestBody HashMap<String, Object> params) throws Exception {
+        // 게시판 접속 통계 조회
+        HashMap<String, Object> result = cntnStatsService.bbsCntnStatsSelect(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.30
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 접속 통계 엑셀 다운로드
+     */
+    @PostMapping("/excelDownload.file")
+    public void excelDownload(HttpServletResponse response, @RequestPart List<CntnStatsExcelDTO> cntnStats, @RequestPart String chart) throws Exception {
+        excelService.cntnStatsExcelDownload(response, cntnStats, chart);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/codeManage/dao/CodeManageDAO.java (added)
+++ src/main/java/com/takensoft/cms/codeManage/dao/CodeManageDAO.java
@@ -0,0 +1,116 @@
+package com.takensoft.cms.codeManage.dao;
+
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.common.HierachyVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 공통코드 정보 관련 Mapper
+ */
+@Mapper("codeManageDAO")
+public interface CodeManageDAO {
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 공통 코드 중복 검사
+     */
+    boolean findByCheckCd(CodeManageVO codeManageVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 등록
+     */
+    int save(CodeManageVO codeManageVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 코드 수정
+     */
+    int update(CodeManageVO codeManageVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 상위코드가 수정됨에 따라 하위코드의 상위코드값 변경
+     */
+    int updateUpCd(CodeManageVO codeManageVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 깊이 조회
+     */
+    int findByCdGrd(String upCd);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 순서 조회
+     */
+    int findByCdSn(String upCd);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 최상위 코드 조회
+     */
+    List<CodeManageVO> findTopCd();
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 하위 코드 조회[관리자용]
+     */
+    List<CodeManageVO> findChildCd(String cd);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 하위 코드 조회[사용자용]
+     */
+    List<CodeManageVO> findChildCdUser(String cd);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 상세 조회
+     */
+    CodeManageVO findByCd(String cd);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.23
+     * 코드 삭제
+     */
+    int deleteCd(String cd);
+
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 최상위 코드 조회
+     */
+    List<HierachyVO> findByTopNode();
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 하위 코드 조회
+     */
+    List<HierachyVO> findChildNode(String id);
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 공통 코드 목록 정보 수정 (hierachyVO 사용)
+     */
+    public int codeUpdateByHierachy(CodeManageVO codeManageVO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/codeManage/service/CodeManageService.java (added)
+++ src/main/java/com/takensoft/cms/codeManage/service/CodeManageService.java
@@ -0,0 +1,106 @@
+package com.takensoft.cms.codeManage.service;
+
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.common.HierachyVO;
+
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 공통코드 정보 관련 인터페이스
+ */
+public interface CodeManageService {
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 중복 검사
+     */
+    public boolean findByCheckCd(CodeManageVO codeManageVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 등록
+     */
+    public int cdSave(CodeManageVO codeManageVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 코드 수정
+     */
+    public int cdUpdate(CodeManageVO codeManageVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 전체 코드 조회 [관리자용 ]
+     */
+    public List<CodeManageVO> findTopCd() throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 하위 코드 조회
+     */
+    public List<CodeManageVO> findByChildCd(String cd) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 상세 조회
+     */
+    public CodeManageVO findByCd(String cd) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 특정 공통 목록 코드 조회(시스템 처리용)
+     */
+    public CodeManageVO findByCdSystem(String cd) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.19
+     * 하위 코드 조회(cache)
+     */
+    public List<CodeManageVO> findByChildCdCache(String cd) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.23
+     * 코드 삭제
+     */
+    public int cdDelete(String cd) throws Exception;
+
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 최상위 코드 조회
+     */
+    public List<HierachyVO> findByTopNode();
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 하위 코드 조회
+     */
+    public List<HierachyVO> findChildNode(String id);
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 공통 코드 목록 수정
+     */
+    public int updateList(List<HierachyVO> deptList) throws Exception;
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 하위 코드 수정
+     */
+    public int updateChildNode(List<HierachyVO> childList, CodeManageVO upCodeManageVO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/codeManage/service/Impl/CodeManageServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/codeManage/service/Impl/CodeManageServiceImpl.java
@@ -0,0 +1,256 @@
+package com.takensoft.cms.codeManage.service.Impl;
+
+import com.takensoft.cms.codeManage.dao.CodeManageDAO;
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.common.util.JWTUtil;
+import com.takensoft.common.HierachyVO;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 공통코드 정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * AuthorService : 공통코드 정보 인터페이스 상속
+ */
+@Service("codeManageService")
+@RequiredArgsConstructor
+public class CodeManageServiceImpl extends EgovAbstractServiceImpl implements CodeManageService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CodeManageServiceImpl.class);
+    private final JWTUtil jwtUtil;
+    private final CodeManageDAO codeManageDAO;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 중복 검사
+     */
+    @Override
+    public boolean findByCheckCd(CodeManageVO codeManageVO) throws Exception {
+        return codeManageDAO.findByCheckCd(codeManageVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 등록
+     */
+    @Override
+    public int cdSave(CodeManageVO codeManageVO) throws Exception {
+        // 상위 코드가 존재 하는 경우
+        if(codeManageVO.getUpCd() != null && !codeManageVO.getUpCd().equals("")) {
+            // 상위 메뉴 아이디 보다 깊이(레벨) 1 추가
+            codeManageVO.setCdGrd(codeManageDAO.findByCdGrd(codeManageVO.getUpCd()) + 1);
+            // 동일한 깊이의 코드 순서 보다 1 추가
+            codeManageVO.setCdSn(codeManageDAO.findByCdSn(codeManageVO.getUpCd()) + 1);
+        // 상위 코드가 존재 하지 않는 경우
+        } else {
+            codeManageVO.setCdGrd(0);
+            codeManageVO.setCdSn(codeManageDAO.findByCdSn(null) + 1);
+        }
+        // 등록된 토큰에서 사용자 정보 조회
+        codeManageVO.setRgtr(jwtUtil.getWriter());
+        return codeManageDAO.save(codeManageVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 코드 수정
+     */
+    @Override
+    public int cdUpdate(CodeManageVO codeManageVO) throws Exception {
+        // 등록된 토큰에서 사용자 정보 조회
+        codeManageVO.setMdfr(jwtUtil.getWriter());
+        // 코드 수정
+        int result = codeManageDAO.update(codeManageVO);
+        // 해당 코드가 변경됨에 따라 하위 코드의 상위코드값 변경
+        result += codeManageDAO.updateUpCd(codeManageVO);
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 전체 코드 조회 [관리자용 ]
+     */
+    @Override
+    public List<CodeManageVO> findTopCd() throws Exception {
+        // 상위 코드 조회
+        List<CodeManageVO> topCdList = codeManageDAO.findTopCd();
+        // 상위 코드에 따른 하위 코드 조회
+        for(CodeManageVO codeManage : topCdList) {
+            List<CodeManageVO> childCd = findByChildCd(codeManage.getCd());
+            codeManage.setChildCdList(childCd);
+        }
+        return topCdList;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 하위 코드 조회
+     */
+    @Override
+    public List<CodeManageVO> findByChildCd(String cd) throws Exception {
+        List<CodeManageVO> childCdList = codeManageDAO.findChildCd(cd);
+        for(CodeManageVO codeManage : childCdList) {
+            List<CodeManageVO> childCd = findByChildCd(codeManage.getCd());
+            codeManage.setChildCdList(childCd);
+        }
+        return childCdList;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 코드 상세 조회
+     */
+    @Override
+    public CodeManageVO findByCd(String cd) throws Exception {
+        return codeManageDAO.findByCd(cd);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 특정 공통 목록 코드 조회(시스템 처리용)
+     */
+    @Override
+    public CodeManageVO findByCdSystem(String cd) throws Exception {
+        CodeManageVO codeManage = codeManageDAO.findByCd(cd);
+        codeManage.setChildCdList(findByChildCd(cd));
+        return codeManage;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.19
+     * 하위 코드 조회(cache)
+     */
+    @Override
+    @Cacheable(value = "findByChildCdCache", key = "#cd")
+    public List<CodeManageVO> findByChildCdCache(String cd) throws Exception {
+        LOGGER.info("Loading search conditions from the database for boardType: {}", cd);
+        return codeManageDAO.findChildCdUser(cd);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.23
+     * 코드 삭제
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int cdDelete(String cd) throws Exception {
+        return codeManageDAO.deleteCd(cd);
+    }
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 최상위 코드 조회
+     */
+    @Override
+    public List<HierachyVO> findByTopNode() {
+        // 상위 코드 조회
+        List<HierachyVO> topCdList = codeManageDAO.findByTopNode();
+        // 상위 코드에 따른 하위 코드 조회
+        for(HierachyVO hierachy : topCdList) {
+            List<HierachyVO> child = findChildNode(hierachy.getId());
+            hierachy.setChildList(child);
+        }
+        return topCdList;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 하위 코드 조회
+     */
+    @Override
+    public List<HierachyVO> findChildNode(String id) {
+        List<HierachyVO> childList = codeManageDAO.findChildNode(id);
+        for(HierachyVO hierachyVO : childList) {
+            List<HierachyVO> child = findChildNode(hierachyVO.getId());
+            hierachyVO.setChildList(child);
+        }
+        return childList;
+    }
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 부서 코드 수정 (hierachyVO 사용)
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateList(List<HierachyVO> deptList) throws Exception {
+        int result = 0;
+        String writer = jwtUtil.getWriter();
+
+        if(deptList != null && deptList.size() > 0) {
+            int sn = 1;
+            for(HierachyVO hierachyVO : deptList) {
+                // 최상위 노드 수정
+                CodeManageVO vo = new CodeManageVO();
+                vo.setCd(hierachyVO.getId());
+                vo.setUpCd(null);
+                vo.setCdGrd(0);
+                vo.setCdSn(sn);
+                vo.setMdfr(writer);
+                result += codeManageDAO.codeUpdateByHierachy(vo);
+
+                // 하위 노드 수정
+                if (hierachyVO.getChildList() != null && hierachyVO.getChildList().size() > 0) {
+                    result += updateChildNode(hierachyVO.getChildList(), vo);
+                }
+                sn++;
+            }
+        }
+        return result;
+    }
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 하위 코드 수정
+     */
+    @Override
+    public int updateChildNode(List<HierachyVO> childList, CodeManageVO upCodeManageVO) throws Exception {
+        int result = 0;
+        String upDeptId = upCodeManageVO.getCd();
+        int grd = upCodeManageVO.getCdGrd() + 1;
+        int sn = 1;
+        String mdfr = upCodeManageVO.getMdfr();
+        for(HierachyVO hierachyVO : childList) {
+            // 현재 노드 수정
+            CodeManageVO vo = new CodeManageVO();
+            vo.setCd(hierachyVO.getId());
+            vo.setUpCd(upDeptId);
+            vo.setCdGrd(grd);
+            vo.setCdSn(sn);
+            vo.setMdfr(mdfr);
+            result += codeManageDAO.codeUpdateByHierachy(vo);
+
+            // 하위 노드 수정
+            if (hierachyVO.getChildList() != null && hierachyVO.getChildList().size() > 0) {
+                result += updateChildNode(hierachyVO.getChildList(), vo);
+            }
+            sn++;
+        }
+        return result;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/codeManage/vo/CodeManageVO.java (added)
+++ src/main/java/com/takensoft/cms/codeManage/vo/CodeManageVO.java
@@ -0,0 +1,86 @@
+package com.takensoft.cms.codeManage.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 공통코드 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class CodeManageVO {
+    /**
+     * 코드
+     */
+    private String cd;
+    /**
+     * 변경전 코드
+     */
+    private String originCd;
+    /**
+     * 상위코드
+     */
+    private String upCd;
+    /**
+     * 상위코드명
+     */
+    private String upCdNm;
+    /**
+     * 코드명
+     */
+    private String cdNm;
+    /**
+     * 코드값
+     */
+    private String cdVl;
+    /**
+     * 코드설명
+     */
+    private String cdExpln;
+    /**
+     * 코드깊이(레벨)
+     */
+    private int cdGrd;
+    /**
+     * 코드순서
+     */
+    private int cdSn;
+    /**
+     * 사용여부
+     */
+    private String useYn;
+    /**
+     * 시스템 제공 여부
+     */
+    private String sysPvsnYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+    /**
+     * 하위 코드 목록
+     */
+    private List<CodeManageVO> childCdList = new ArrayList<CodeManageVO>();
+}
 
src/main/java/com/takensoft/cms/codeManage/web/CodeManageController.java (added)
+++ src/main/java/com/takensoft/cms/codeManage/web/CodeManageController.java
@@ -0,0 +1,254 @@
+package com.takensoft.cms.codeManage.web;
+
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.common.util.ResponseData;
+import com.takensoft.common.HierachyVO;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 공통코드 정보 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping("/admin/code")
+public class CodeManageController {
+
+    private final CodeManageService codeManageService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * @param codeManageVO
+     * @return
+     * @throws Exception
+     *
+     * 공통코드 등록
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> saveProc(@RequestBody CodeManageVO codeManageVO) throws Exception {
+        // 코드 중복 검사
+        boolean isExistence = codeManageService.findByCheckCd(codeManageVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        if(isExistence) {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("이미 존재하는 코드입니다.");
+            log.error("이미 존재하는 코드입니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        // 코드 등록
+        int result = codeManageService.cdSave(codeManageVO);
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 공통코드 목록 조회 (관리자용)
+     */
+    @GetMapping(value = "/findAll.json")
+    public ResponseEntity<?> findAll() throws Exception {
+        // Tree용
+        List<HierachyVO> hierachyList = codeManageService.findByTopNode();
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("hierachyList", hierachyList);
+        result.put("newCode", new CodeManageVO());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * @param codeManageVO
+     * @return
+     * @throws Exception
+     *
+     * 공통코드 상세 조회 (관리자용)
+     */
+    @PostMapping("/findByCd.json")
+    public ResponseEntity<?> findByCd(@RequestBody CodeManageVO codeManageVO) throws Exception {
+        // 공통코드 조회
+        CodeManageVO code = codeManageService.findByCd(codeManageVO.getCd());
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("code", code);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param codeManageVO
+     * @return
+     * @throws Exception
+     *
+     * 공통코드 수정
+     */
+    @PostMapping("/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody CodeManageVO codeManageVO) throws Exception {
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 코드의 변경 사항이 있을 때만 코드 중복 검사 진행
+        if(codeManageVO.getOriginCd() != null && !codeManageVO.getOriginCd().equals("") && !codeManageVO.getOriginCd().equals(codeManageVO.getCd())) {
+            // 코드 중복 검사
+            boolean isExistence = codeManageService.findByCheckCd(codeManageVO);
+            if(isExistence) {
+                responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+                responseData.setMessage("이미 존재하는 코드입니다.");
+                log.error("이미 존재하는 코드입니다.");
+                return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+            }
+        }
+        // 코드 수정
+        int result = codeManageService.cdUpdate(codeManageVO);
+
+        // 응답 처리
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param codeManageVO
+     * @return
+     * @throws Exception
+     *
+     * 공통코드 삭제
+     */
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody CodeManageVO codeManageVO) throws Exception {
+        // 공통 코드 삭제(하위 항목 모두)
+        int result = codeManageService.cdDelete(codeManageVO.getCd());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * @param codeManageVO
+     * @return
+     * @throws Exception
+     *
+     * 특정 공통 목록 코드 조회(시스템 처리용)
+     */
+    @PostMapping("/findByCdSystem.json")
+    public ResponseEntity<?> findByCdSystem(@RequestBody CodeManageVO codeManageVO) throws Exception {
+        // 메뉴 조회
+        CodeManageVO code = codeManageService.findByCdSystem(codeManageVO.getCd());
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("code", code);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * @param codeList
+     * @return
+     * @throws Exception
+     *
+     * 공통 코드 목록 수정
+     */
+    @PostMapping(value = "/updateListProc.json")
+    public ResponseEntity<?> updateListProc(@RequestBody List<HierachyVO> codeList) throws Exception {
+        // 공통 코드 목록 수정
+        int result = codeManageService.updateList(codeList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/contsType/dao/ContsTypeDAO.java (added)
+++ src/main/java/com/takensoft/cms/contsType/dao/ContsTypeDAO.java
@@ -0,0 +1,75 @@
+package com.takensoft.cms.contsType.dao;
+
+import com.takensoft.cms.contsType.vo.ContsAuthrtVO;
+import com.takensoft.cms.contsType.vo.ContsTypeVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.17
+ *
+ * 콘텐츠 유형 관리 관련 Mapper
+ */
+@Mapper("contsTypeDAO")
+public interface ContsTypeDAO {
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 등록
+     */
+    int save(ContsTypeVO contsTypeVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 수정
+     */
+    int update(ContsTypeVO contsTypeVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 목록 조회
+     */
+    List<ContsTypeVO> findAll(Pagination pagination);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 목록 조회(노출인 목록만)
+     */
+    List<ContsTypeVO> findByContsTypeSys(ContsTypeVO contsTypeVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 상세 조회
+     */
+    ContsTypeVO findByContsType(String contsId);
+
+    /**
+     * @author 박정하
+     * @since 2024.04.23
+     * 콘텐츠 유형 목록 갯수(관리자 페이지용)
+     */
+    int findAllCnt(Pagination pagination);
+
+    /**
+     * @author 박정하
+     * @since 2024.04.29
+     * 콘텐츠 유형 목록 조회 (메뉴 노출 건만)
+     */
+    List<ContsTypeVO> findAllByExpsr(ContsTypeVO contsTypeVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.02
+     * 콘텐츠 조회(권한 포함)
+     */
+    List<ContsAuthrtVO> findByContsAuthrt();
+}
 
src/main/java/com/takensoft/cms/contsType/service/ContsTypeService.java (added)
+++ src/main/java/com/takensoft/cms/contsType/service/ContsTypeService.java
@@ -0,0 +1,66 @@
+package com.takensoft.cms.contsType.service;
+
+import com.takensoft.cms.contsType.vo.ContsAuthrtVO;
+import com.takensoft.cms.contsType.vo.ContsTypeVO;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.17
+ *
+ * 콘텐츠 유형 관리 관련 인터페이스
+ */
+public interface ContsTypeService {
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 등록
+     */
+    public HashMap<String, Object> contsSave(ContsTypeVO contsTypeVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 수정
+     */
+    public int contsUpdate(ContsTypeVO contsTypeVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 목록 조회
+     */
+    public Map<String, Object> findAll(Map<String, String> params) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 목록 조회(노출인 목록만)
+     */
+    public List<ContsTypeVO> findByContsTypeSys(ContsTypeVO contsTypeVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 상세 조회
+     */
+    public ContsTypeVO findByContsType(String contsId) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.04.29
+     * 콘텐츠 유형 목록 조회 (메뉴 노출 건만)
+     */
+    public List<ContsTypeVO> findAllByExpsr(ContsTypeVO contsTypeVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.05.02
+     * 콘텐츠 조회(권한 포함)
+     */
+    public List<ContsAuthrtVO> findByContsAuthrt() throws Exception;
+}
 
src/main/java/com/takensoft/cms/contsType/service/Impl/ContsTypeServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/contsType/service/Impl/ContsTypeServiceImpl.java
@@ -0,0 +1,232 @@
+package com.takensoft.cms.contsType.service.Impl;
+
+import com.takensoft.cms.bbs.dao.BbsRouterDAO;
+import com.takensoft.cms.contsType.dao.ContsTypeDAO;
+import com.takensoft.cms.contsType.service.ContsTypeService;
+import com.takensoft.cms.contsType.vo.ContsAuthrtVO;
+import com.takensoft.cms.contsType.vo.ContsTypeVO;
+import com.takensoft.cms.menu.dao.MenuDAO;
+import com.takensoft.cms.menu.service.MenuService;
+import com.takensoft.cms.menu.vo.MenuAuthorVO;
+import com.takensoft.cms.menu.vo.MenuVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.17
+ *
+ * 콘텐츠 유형 관리 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * ContsTypeService : 콘텐츠 유형 관리 관련 인터페이스 상속
+ */
+@Service("contsTypeService")
+@RequiredArgsConstructor
+public class ContsTypeServiceImpl extends EgovAbstractServiceImpl implements ContsTypeService {
+    private final ContsTypeDAO contsTypeDAO;
+    private final BbsRouterDAO bbsRouterDAO;
+    private final IdgenService contsTypeIdgn;
+    private final JWTUtil jwtUtil;
+    private final MenuService menuService; // 메뉴 인터페이스
+    private final MenuDAO menuDAO;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 등록
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public HashMap<String, Object> contsSave(ContsTypeVO contsTypeVO) throws Exception {
+        HashMap<String, Object> result = new HashMap<>();
+
+        // 콘텐츠 유형 아이디 생성
+        String contsId = contsTypeIdgn.getNextStringId();
+        contsTypeVO.setContsId(contsId);
+
+        // 등록된 토큰에서 사용자 정보 조회
+        contsTypeVO.setRgtr(jwtUtil.getWriter());
+
+        // 콘텐츠 유형 등록
+        int insertResult = contsTypeDAO.save(contsTypeVO);
+
+        // 메뉴 등록
+        if (contsTypeVO.getExpsrYn().equals("Y")) {
+            MenuVO menuVO = new MenuVO();
+            menuVO.setUpMenuId("MENU_000000000000018"); // 상위메뉴아이디(콘텐츠 관리 메뉴 아이디)
+            menuVO.setMenuNm(contsTypeVO.getContsKornNm()); // 메뉴명
+            menuVO.setMenuType("conts"); // 메뉴타입
+            menuVO.setMenuTypeCtgry(contsId); // 메뉴타입항목(콘텐츠 유형 아이디)
+            menuVO.setLinkType("0"); // 링크유형(현재창)
+            menuVO.setDgstfnExmnUseYn("N"); // 만족도조사사용여부(미노출)
+            menuVO.setMenuExpsrYn("Y"); // 메뉴노출여부(노출)
+            menuVO.setMenuUser("A"); // 메뉴사용자(관리자)
+            menuVO.setSysPvsnYn("0"); // 시스템제공여부(시스템등록)
+            menuService.menuSave(menuVO);
+        }
+        
+        result.put("contsId", contsId);
+        result.put("result", insertResult);
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 수정
+     */
+    @Override
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public int contsUpdate(ContsTypeVO contsTypeVO) throws Exception {
+        int result = 0;
+        // 등록된 토큰에서 사용자 정보 조회
+        contsTypeVO.setMdfr(jwtUtil.getWriter());
+        result += contsTypeDAO.update(contsTypeVO);
+
+        // 메뉴 수정
+        menuDAO.updateByContsId(contsTypeVO);
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 목록 조회
+     */
+    @Override
+    public Map<String, Object> findAll(Map<String, String> params) throws Exception {
+        Map<String, Object> result = new HashMap<>();
+        Pagination search = new Pagination(0, params);
+        int cnt = contsTypeDAO.findAllCnt(search);
+        Pagination pagination = new Pagination(cnt, params);
+        List<ContsTypeVO> list = contsTypeDAO.findAll(pagination);
+
+        result.put("list", list);
+        result.put("pagination", pagination);
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 목록 조회(노출인 목록만)
+     */
+    @Override
+    public List<ContsTypeVO> findByContsTypeSys(ContsTypeVO contsTypeVO) throws Exception {
+        return contsTypeDAO.findByContsTypeSys(contsTypeVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * 콘텐츠 유형 상세 조회
+     */
+    @Override
+    public ContsTypeVO findByContsType(String contsId) throws Exception {
+        ContsTypeVO contsTypeVO = new ContsTypeVO();
+
+        if (contsId != null) {
+            contsTypeVO = contsTypeDAO.findByContsType(contsId);
+        }
+
+        // 메뉴노출 기본값
+        if (contsTypeVO.getExpsrYn() == null) {
+            contsTypeVO.setExpsrYn("N");
+        }
+        // 사용여부 기본값
+        if (contsTypeVO.getUseYn() == null) {
+            contsTypeVO.setUseYn("Y");
+        }
+
+        return contsTypeVO;
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.04.29
+     * 콘텐츠 유형 목록 조회 (메뉴 노출 건만)
+     */
+    @Override
+    public List<ContsTypeVO> findAllByExpsr(ContsTypeVO contsTypeVO) throws Exception {
+        return contsTypeDAO.findAllByExpsr(contsTypeVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.05.02
+     * 콘텐츠 조회(권한 포함)
+     */
+    @Override
+    @Cacheable(value = "routerAuthInfo", key = "'routerAuth'")
+    public List<ContsAuthrtVO> findByContsAuthrt() throws Exception {
+        // 콘텐츠(라우터)정보 조회
+        List<ContsAuthrtVO> list = contsTypeDAO.findByContsAuthrt();
+        // 권한 공유
+        List<ContsAuthrtVO> result = groupAndShareAuth(list);
+
+        // 게시판 라우터 정보 조회
+        List<ContsAuthrtVO> bbsList = bbsRouterDAO.findByBbsRouterAuthrt();
+        result.addAll(bbsList);
+
+        return result;
+    }
+
+    /**
+     * @author toakensoft
+     * @since 2024.05.08
+     * 라우터의 특정경로로 그룹화하여 각 그룹 내에서 권한을 공유
+     */
+    private List<ContsAuthrtVO> groupAndShareAuth(List<ContsAuthrtVO> routes) {
+        // 경로의 특정 기준점으로 라우터를 그룹화
+        Map<String, List<ContsAuthrtVO>> groupedRoutes = routes.stream()
+                .collect(Collectors.groupingBy(route -> route.getPageCrs().substring(0, route.getPageCrs().lastIndexOf('/')))); // 마지막 슬래시까지 포함된 경로 추출
+
+        /* key */
+//        Iterator<String> keys = groupedRoutes.keySet().iterator();
+//        while(keys.hasNext()) {
+//            String key = keys.next();
+//            System.out.println("key : " + key);
+//        }
+        /* key */
+
+        // 그룹화된 각 경로에 대해 권한 정보 공유
+        groupedRoutes.forEach((basePath, routeGroup) -> {
+            List<MenuAuthorVO> sharedAuth = findMostComprehensiveAuth(routeGroup); // 그룹 내에서 가장 완전한 권한 정보 조회
+            // 그룹의 모든 라우트에 권한 정보가 없으면 공유된 권한 정보로 설정
+            routeGroup.forEach(route -> {
+                if(route.getAuthrtList().isEmpty()) {
+                    route.setAuthrtList(sharedAuth);
+                }
+            });
+        });
+        // 각 그룹의 라우터들을 리스트로 반환
+        return groupedRoutes.values().stream()
+                .flatMap(List::stream)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * @author toakensoft
+     * @since 2024.05.08
+     * 그룹 내에서 가장 완전한 권한 정보를 가진 라우터를 찾아 해당 권한 리트스 반환
+     */
+    private List<MenuAuthorVO> findMostComprehensiveAuth(List<ContsAuthrtVO> routeGroup) {
+        // 권한정보가 있는 첫 번째 라우터를 찾아 권한 정보 반환
+        return routeGroup.stream()
+                .filter(route -> !route.getAuthrtList().isEmpty())
+                .findFirst()
+                .map(ContsAuthrtVO::getAuthrtList)
+                .orElse(Collections.emptyList()); // 권한 정보가 없으면 빈 리스트 반환
+    }
+}
 
src/main/java/com/takensoft/cms/contsType/vo/ContsAuthrtVO.java (added)
+++ src/main/java/com/takensoft/cms/contsType/vo/ContsAuthrtVO.java
@@ -0,0 +1,52 @@
+package com.takensoft.cms.contsType.vo;
+
+import com.takensoft.cms.menu.vo.MenuAuthorVO;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.checkerframework.checker.units.qual.A;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.17
+ *
+ * 콘텐츠 유형과 권한 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class ContsAuthrtVO {
+    /**
+     * 콘텐츠 아이디
+     */
+    private String contsId;
+    /**
+     * 메뉴 아이디
+     */
+    private String menuId;
+    /**
+     * 콘텐츠 한글명
+     */
+    private String contsKornNm;
+    /**
+     * 콘텐츠 영문명
+     */
+    private String contsEngNm;
+    /**
+     * 페이지 경로
+     */
+    private String pageCrs;
+    /**
+     * 컴포넌트 경로
+     */
+    private String compnCrs;
+    /**
+     * 권한 목록
+     */
+    private List<MenuAuthorVO> authrtList = new ArrayList<MenuAuthorVO>();
+}
 
src/main/java/com/takensoft/cms/contsType/vo/ContsTypeVO.java (added)
+++ src/main/java/com/takensoft/cms/contsType/vo/ContsTypeVO.java
@@ -0,0 +1,71 @@
+package com.takensoft.cms.contsType.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.17
+ *
+ * 콘텐츠 유형 관리 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class ContsTypeVO {
+    /**
+     * 콘텐츠 아이디
+     */
+    private String contsId;
+    /**
+     * 콘텐츠 한글명
+     */
+    private String contsKornNm;
+    /**
+     * 콘텐츠 영문명
+     */
+    private String contsEngNm;
+    /**
+     * 사용자 페이지 경로
+     */
+    private String pageCrs;
+    /**
+     * 관리자 페이지 경로
+     */
+    private String mngrPageCrs;
+    /**
+     * 컴포넌트 경로
+     */
+    private String compnCrs;
+    /**
+     * 노출여부
+     */
+    private String expsrYn;
+    /**
+     * 사용여부
+     */
+    private String useYn;
+    /**
+     * 시스템 제공 여부
+     */
+    private String sysPvsnYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+}
 
src/main/java/com/takensoft/cms/contsType/web/ContsTypeController.java (added)
+++ src/main/java/com/takensoft/cms/contsType/web/ContsTypeController.java
@@ -0,0 +1,190 @@
+package com.takensoft.cms.contsType.web;
+
+import com.takensoft.cms.contsType.service.ContsTypeService;
+import com.takensoft.cms.contsType.vo.ContsTypeVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.17
+ *
+ * 콘텐츠 유형 관리 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/admin/contsType")
+public class ContsTypeController {
+    private final ContsTypeService contsTypeService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * @param contsTypeVO
+     * @return
+     * @throws Exception
+     *
+     * 콘텐츠 유형 등록
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> savePorc(@RequestBody ContsTypeVO contsTypeVO) throws Exception {
+        // 콘텐츠 유형 등록
+        HashMap<String, Object> result = contsTypeService.contsSave(contsTypeVO);
+        int insertResult = (int) result.get("result");
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * @param contsTypeVO
+     * @return
+     * @throws Exception
+     *
+     * 콘텐츠 유형 수정
+     */
+    @PostMapping("/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody ContsTypeVO contsTypeVO) throws Exception {
+        // 콘텐츠 유형 수정 처리
+        int result = contsTypeService.contsUpdate(contsTypeVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * @param params
+     * @return
+     * @throws Exception
+     *
+     * 콘텐츠 유형 목록 조회
+     */
+    @PostMapping("/findAll.json")
+    public ResponseEntity<?> findAll(@RequestBody Map<String, String> params) throws Exception {
+        // 콘텐츠 유형 목록 조회
+        Map<String, Object> result = contsTypeService.findAll(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * @param contsTypeVO
+     * @return
+     * @throws Exception
+     *
+     * 콘텐츠 유형 상세 조회
+     */
+    @PostMapping("/findByContsType.json")
+    public ResponseEntity<?> findByContsType(@RequestBody ContsTypeVO contsTypeVO) throws Exception {
+        ContsTypeVO result = contsTypeService.findByContsType(contsTypeVO.getContsId());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * @param contsTypeVO
+     * @return
+     * @throws Exception
+     *
+     * 콘텐츠 유형 삭제
+     */
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody ContsTypeVO contsTypeVO) throws Exception {
+        contsTypeVO.setUseYn("N");
+        int result = contsTypeService.contsUpdate(contsTypeVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.04.29
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 콘텐츠 유형 목록 조회 (메뉴 노출 건만)
+     */
+    @PostMapping("/findAllByExpsr.json")
+    public ResponseEntity<?> findAllByExpsr(@RequestBody ContsTypeVO contsTypeVO) throws Exception {
+        // 콘텐츠 유형 목록 조회 (메뉴 노출 건만)
+        List<ContsTypeVO> result = contsTypeService.findAllByExpsr(contsTypeVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}
 
src/main/java/com/takensoft/cms/contsType/web/SystemContsTypeController.java (added)
+++ src/main/java/com/takensoft/cms/contsType/web/SystemContsTypeController.java
@@ -0,0 +1,75 @@
+package com.takensoft.cms.contsType.web;
+
+import com.takensoft.cms.contsType.service.ContsTypeService;
+import com.takensoft.cms.contsType.vo.ContsAuthrtVO;
+import com.takensoft.cms.contsType.vo.ContsTypeVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.17
+ *
+ * 콘텐츠 유형 관리 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value = "/sys/contsType")
+public class SystemContsTypeController {
+
+    private final ContsTypeService contsTypeService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * @param
+     * @return
+     * @throws Exception
+     */
+    @PostMapping(value = "/findByContsTypeSys.json")
+    public ResponseEntity<?> findByContsTypeSys(ContsTypeVO contsTypeVO) throws Exception {
+        // 콘텐츠 유형 목록 조회 (메뉴 노출 건만)
+        List<ContsTypeVO> result = contsTypeService.findByContsTypeSys(contsTypeVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * @param
+     * @return
+     * @throws Exception
+     */
+    @PostMapping(value = "/findByContsAuthrtSys.json")
+    public ResponseEntity<?> findByContsTypeSys() throws Exception {
+        // 콘텐츠 유형 목록 조회 (메뉴 노출 건만)
+        List<ContsAuthrtVO> result = contsTypeService.findByContsAuthrt();
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}
 
src/main/java/com/takensoft/cms/dept/dao/DeptDAO.java (added)
+++ src/main/java/com/takensoft/cms/dept/dao/DeptDAO.java
@@ -0,0 +1,132 @@
+package com.takensoft.cms.dept.dao;
+
+import com.takensoft.cms.dept.vo.DeptAuthrtVO;
+import com.takensoft.cms.dept.vo.DeptMbrVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.common.HierachyVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.24
+ *
+ * 부서 정보 관련 Mapper
+ */
+@Mapper("deptDAO")
+public interface DeptDAO {
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 부서 등록
+     */
+    int save(DeptVO deptVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 부서 권한 등록
+     */
+    int authrtSave(DeptAuthrtVO deptAuthrtVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * 부서 사용자 등록
+     */
+    int deptMbrSave(DeptMbrVO deptMbrVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 부서 깊이(레벨) 조회
+     */
+    int findByDeptGrd(String upDeptId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 부서 순서 조회
+     */
+    int findByDeptSn(String upDeptId);
+
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 최상위 부서 조회
+     */
+    List<HierachyVO> findByTopNode();
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 하위 부서 조회
+     */
+    List<HierachyVO> findChildNode(String id);
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 정보 조회
+     */
+    DeptVO findByDept(String deptId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 정보 수정
+     */
+    int update(DeptVO deptVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 권한 삭제
+     */
+    int deleteAuth(String deptId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 사용자 등록을 위한 사용자 정보 목록 조회 (부서에 등록되지 않은 사용자 목록)
+     */
+    List<DeptMbrVO> findByMber(Map<String, String> params);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서에 등록된 사용자 목록 조회
+     */
+    List<DeptMbrVO> findByDeptMber(String deptId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 상위,하위 부서 삭제
+     */
+    int deleteDept(String deptId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 상위, 하위 부서 삭제에 따른 부서의 사용자 삭제
+     */
+    int deleteDeptInDeptMbr(String deptId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서에 등록된 사용자 제거
+     */
+    int deleteDeptMbr(Map<String, Object> params);
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 부서 정보 수정 (hierachyVO 사용)
+     */
+    public int deptUpdateByHierachy(DeptVO deptVO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/dept/service/DeptService.java (added)
+++ src/main/java/com/takensoft/cms/dept/service/DeptService.java
@@ -0,0 +1,94 @@
+package com.takensoft.cms.dept.service;
+
+import com.takensoft.cms.dept.vo.DeptMbrVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.common.HierachyVO;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 부서 정보 관련 인터페이스
+ */
+public interface DeptService {
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 부서 등록
+     */
+    public HashMap<String, Object> deptSave(DeptVO deptVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * 부서 사용자 등록
+     */
+    public int deptMbrSave(DeptMbrVO deptMbrVO) throws Exception;
+
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 최상위 코드 조회
+     */
+    public List<HierachyVO> findByTopNode() throws Exception;
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 하위 코드 조회
+     */
+    public List<HierachyVO> findChildNode(String id) throws Exception;
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 정보 조회
+     */
+    public Map<String, Object> findByDept(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 정보 수정
+     */
+    public int deptUpdate(DeptVO deptVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 정보 삭제
+     */
+    public int deptDelete(DeptVO deptVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 사용자 삭제
+     */
+    public int deptMbrDelete(List<DeptMbrVO> deptMbrList) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * 부서에 등록되지 않는 사용자 조회
+     */
+    public Map<String, Object> findByMbr(Map<String, String> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.09
+     * 부서 목록 수정
+     */
+    public int updateList(List<HierachyVO> deptList) throws Exception;
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 하위 부서 수정
+     */
+    public int updateChildNode(List<HierachyVO> childList, DeptVO upDeptVO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/dept/service/Impl/DeptServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/dept/service/Impl/DeptServiceImpl.java
@@ -0,0 +1,289 @@
+package com.takensoft.cms.dept.service.Impl;
+
+import com.takensoft.cms.dept.dao.DeptDAO;
+import com.takensoft.cms.dept.service.DeptService;
+import com.takensoft.cms.dept.vo.DeptAuthrtVO;
+import com.takensoft.cms.dept.vo.DeptMbrVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.common.HierachyVO;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.JWTUtil;
+import com.takensoft.common.util.Secret;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.24
+ *
+ * 부서 정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * DeptService : 부서 정보 인터페이스 상속
+ */
+@Service("deptService")
+@RequiredArgsConstructor
+public class DeptServiceImpl extends EgovAbstractServiceImpl implements DeptService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(DeptServiceImpl.class);
+    private final JWTUtil jwtUtil;
+    private final DeptDAO deptDAO;
+    private final IdgenService deptIdgn;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 부서 등록
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HashMap<String, Object> deptSave(DeptVO deptVO) throws Exception {
+        String deptId = deptIdgn.getNextStringId(); // 부서 아이디 생성
+        deptVO.setDeptId(deptId);
+
+        // 상위 부서가 존재하는 경우
+        if(deptVO.getUpDeptId() != null && !deptVO.getUpDeptId().equals("")) {
+            // 상위 부서보다 깊이(레벨) + 1
+            deptVO.setDeptGrd(deptDAO.findByDeptGrd(deptVO.getUpDeptId()) + 1);
+            // 동일한 깊이의 부서 순서보다 + 1
+            deptVO.setDeptSn(deptDAO.findByDeptSn(deptVO.getUpDeptId()) + 1);
+        // 상위 부서가 존재 하지 않는 경우
+        } else {
+            deptVO.setDeptGrd(0);
+            deptVO.setDeptSn(deptDAO.findByDeptSn(null) + 1);
+        }
+        deptVO.setRgtr(jwtUtil.getWriter()); // 작성자 정보 등록
+        int insertResult = deptDAO.save(deptVO);
+        // 부서 권한 등록
+        if(deptVO.getAuthrtList().size() > 0) {
+            for(DeptAuthrtVO vo : deptVO.getAuthrtList()) {
+                vo.setDeptId(deptId);
+                vo.setRgtr(jwtUtil.getWriter());
+                insertResult += deptDAO.authrtSave(vo);
+            }
+        }
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("deptId", deptId);
+        result.put("insertResult", insertResult); // 부서 등록
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * 부서 사용자 등록
+     */
+    @Override
+    public int deptMbrSave(DeptMbrVO deptMbrVO) throws Exception {
+        deptMbrVO.setRgtr(jwtUtil.getWriter()); // 작성자 정보 등록
+        return deptDAO.deptMbrSave(deptMbrVO);
+    }
+
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 최상위 부서 조회
+     */
+    @Override
+    public List<HierachyVO> findByTopNode() throws Exception {
+        List<HierachyVO> topDeptList = deptDAO.findByTopNode();
+        for(HierachyVO vo : topDeptList) {
+            List<HierachyVO> child = findChildNode(vo.getId());
+            vo.setChildList(child);
+        }
+        return topDeptList;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 하위 부서 조회
+     */
+    @Override
+    public List<HierachyVO> findChildNode(String id) throws Exception {
+        List<HierachyVO> childList = deptDAO.findChildNode(id);
+        for(HierachyVO vo : childList) {
+            List<HierachyVO> child = findChildNode(vo.getId());
+            vo.setChildList(child);
+        }
+        return childList;
+    }
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 정보 조회
+     */
+    @Override
+    public Map<String, Object> findByDept(HashMap<String, Object> params) throws Exception {
+        String deptId = params.get("deptId").toString(); // 아이디 추출
+        DeptVO dept = deptDAO.findByDept(deptId); // 부서 정보 조회
+        List<DeptMbrVO> deptMbr = deptDAO.findByDeptMber(deptId); // 부서에 등록된 사용자 정보 조회
+        // 사용자 정보 복호화
+        if(deptMbr.size() > 0) {
+            for(DeptMbrVO vo : deptMbr) {
+                // 연락처 복호화
+                vo.setMblTelno(Secret.decrypt(vo.getMblTelno().toString()));
+            }
+        }
+        Map<String, Object> result = new HashMap<String, Object>(); // 반환 객체 생성
+        result.put("dept", dept); // 부서 상세 정보
+        result.put("deptMbr", deptMbr); // 부서 사용자 목록 정보
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 정보 수정
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deptUpdate(DeptVO deptVO) throws Exception {
+        deptVO.setMdfr(jwtUtil.getWriter()); // 토큰에서 사용자 정보 추출
+        int result = deptDAO.update(deptVO); // 부서정보 수정
+        result += deptDAO.deleteAuth(deptVO.getDeptId()); // 부서 권한 삭제
+        // 부서 권한 등록
+        if(deptVO.getAuthrtList().size() > 0) {
+            for(DeptAuthrtVO vo : deptVO.getAuthrtList()) {
+                vo.setDeptId(deptVO.getDeptId());
+                vo.setRgtr(jwtUtil.getWriter());
+                result += deptDAO.authrtSave(vo);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 정보 삭제
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deptDelete(DeptVO deptVO) throws Exception {
+        int result = deptDAO.deleteDept(deptVO.getDeptId());
+        result += deptDAO.deleteDeptInDeptMbr(deptVO.getDeptId());
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * 부서 사용자 삭제
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deptMbrDelete(List<DeptMbrVO> deptMbrList) throws Exception {
+        int result = 0;
+        if(deptMbrList.size() == 0) return 0;
+        for(DeptMbrVO vo : deptMbrList) {
+            Map<String, Object> param = new HashMap<String, Object>();
+            param.put("mbrId", vo.getMbrId());
+            result += deptDAO.deleteDeptMbr(param);
+        }
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * 부서에 등록되지 않는 사용자 조회
+     */
+    @Override
+    public Map<String, Object> findByMbr(Map<String, String> params) throws Exception {
+        List<DeptMbrVO> mbrList = deptDAO.findByMber(params); // 부서에 등록되지 않는 사용자 조회
+        // 사용자 정보 복호화
+        if(mbrList.size() > 0) {
+            for(DeptMbrVO vo : mbrList) {
+                // 연락처 복호화
+                vo.setMblTelno(Secret.decrypt(vo.getMblTelno().toString()));
+            }
+        }
+        List<DeptMbrVO> deptMbr = deptDAO.findByDeptMber(params.get("deptId").toString()); // 부서에 등록된 사용자 정보 조회
+        // 사용자 정보 복호화
+        if(deptMbr.size() > 0) {
+            for(DeptMbrVO vo : deptMbr) {
+                // 연락처 복호화
+                vo.setMblTelno(Secret.decrypt(vo.getMblTelno().toString()));
+            }
+        }
+
+        Map<String, Object> result = new HashMap<String, Object>(); // 반환 객체 생성
+        result.put("mbrList", mbrList); // 부서에 등록되지 않는 사용자 정보
+        result.put("deptMbr", deptMbr); // 부서 사용자 목록 정보
+        return result;
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 부서 정보 수정 (hierachyVO 사용)
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateList(List<HierachyVO> deptList) throws Exception {
+        int result = 0;
+        String writer = jwtUtil.getWriter();
+
+        if(deptList != null && deptList.size() > 0) {
+            int sn = 1;
+            for(HierachyVO hierachyVO : deptList) {
+                // 최상위 노드 수정
+                DeptVO vo = new DeptVO();
+                vo.setDeptId(hierachyVO.getId());
+                vo.setUpDeptId(null);
+                vo.setDeptGrd(0);
+                vo.setDeptSn(sn);
+                vo.setMdfr(writer);
+                result += deptDAO.deptUpdateByHierachy(vo);
+
+                // 하위 노드 수정
+                if (hierachyVO.getChildList() != null && hierachyVO.getChildList().size() > 0) {
+                    result += updateChildNode(hierachyVO.getChildList(), vo);
+                }
+                sn++;
+            }
+        }
+        return result;
+    }
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 하위 부서 수정
+     */
+    @Override
+    public int updateChildNode(List<HierachyVO> childList, DeptVO upDeptVO) throws Exception {
+        int result = 0;
+        String upDeptId = upDeptVO.getDeptId();
+        int grd = upDeptVO.getDeptGrd() + 1;
+        int sn = 1;
+        String mdfr = upDeptVO.getMdfr();
+        for(HierachyVO hierachyVO : childList) {
+            // 현재 노드 수정
+            DeptVO vo = new DeptVO();
+            vo.setDeptId(hierachyVO.getId());
+            vo.setUpDeptId(upDeptId);
+            vo.setDeptGrd(grd);
+            vo.setDeptSn(sn);
+            vo.setMdfr(mdfr);
+            result += deptDAO.deptUpdateByHierachy(vo);
+
+            // 하위 노드 수정
+            if (hierachyVO.getChildList() != null && hierachyVO.getChildList().size() > 0) {
+                result += updateChildNode(hierachyVO.getChildList(), vo);
+            }
+            sn++;
+        }
+        return result;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/dept/vo/DeptAuthrtVO.java (added)
+++ src/main/java/com/takensoft/cms/dept/vo/DeptAuthrtVO.java
@@ -0,0 +1,34 @@
+package com.takensoft.cms.dept.vo;
+
+import lombok.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.25
+ *
+ * 부서 권한 정보 관련 VO
+ */
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class DeptAuthrtVO {
+    /**
+     * 부서 아이디
+     */
+    private String deptId;
+    /**
+     * 권한 코드
+     */
+    private String authrtCd;
+    /**
+     * 작성자
+     */
+    private String rgtr;
+    /**
+     * 작성일
+     */
+    private String regDt;
+}
 
src/main/java/com/takensoft/cms/dept/vo/DeptMbrVO.java (added)
+++ src/main/java/com/takensoft/cms/dept/vo/DeptMbrVO.java
@@ -0,0 +1,55 @@
+package com.takensoft.cms.dept.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.26
+ *
+ * 부서 사용자 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class DeptMbrVO {
+    /**
+     * 부서 아이디
+     */
+    private String deptId;
+    /**
+     * 회원 아이디
+     */
+    private String mbrId;
+    /**
+     * 로그인 아이디
+     */
+    private String lgnId;
+    /**
+     * 회원 이름
+     */
+    private String mbrNm;
+    /**
+     * 닉네임
+     */
+    private String ncnm;
+    /**
+     * 이메일
+     */
+    private String eml;
+    /**
+     * 연락처
+     */
+    private String mblTelno;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+}
 
src/main/java/com/takensoft/cms/dept/vo/DeptVO.java (added)
+++ src/main/java/com/takensoft/cms/dept/vo/DeptVO.java
@@ -0,0 +1,76 @@
+package com.takensoft.cms.dept.vo;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.24
+ *
+ * 부서 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class DeptVO {
+    /**
+     * 부서 아이디
+     */
+    private String deptId;
+    /**
+     * 상위 부서 아이디
+     */
+    private String upDeptId;
+    /**
+     * 부서명
+     */
+    private String deptNm;
+    /**
+     * 상위부서명
+     */
+    private String upDeptNm;
+    /**
+     * 부서설명
+     */
+    private String deptExpln;
+    /**
+     * 부서 깊이(레벨)
+     */
+    private int deptGrd;
+    /**
+     * 부서 순서
+     */
+    private int deptSn;
+    /**
+     * 사용여부
+     */
+    private String useYn;
+    /**
+     * 작성자
+     */
+    private String rgtr;
+    /**
+     * 작성일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+    /**
+     * 권한정보
+     */
+    private List<DeptAuthrtVO> authrtList = new ArrayList<DeptAuthrtVO>();
+
+}
 
src/main/java/com/takensoft/cms/dept/web/DeptController.java (added)
+++ src/main/java/com/takensoft/cms/dept/web/DeptController.java
@@ -0,0 +1,297 @@
+package com.takensoft.cms.dept.web;
+
+import com.takensoft.cms.author.service.AuthorService;
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.dept.service.DeptService;
+import com.takensoft.cms.dept.vo.DeptMbrVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.common.HierachyVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.24
+ *
+ * 부서 정보 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping("/admin/dept")
+public class DeptController {
+
+    private final DeptService deptService;
+    private final AuthorService authorService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * @param deptVO
+     * @return
+     * @throws Exception
+     * 
+     * 부서 등록
+     */
+    @PostMapping("/saveProc.json")
+    public ResponseEntity<?> saveProc(@RequestBody DeptVO deptVO) throws Exception {
+        // 부서 등록
+        HashMap<String, Object> result = deptService.deptSave(deptVO);
+        int insertResult = (int) result.get("insertResult");
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        if(insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * @param deptMbrVO
+     * @return
+     * @throws Exception
+     *
+     * 부서 사용자 등록
+     */
+    @PostMapping("/deptMbrSaveProc.json")
+    public ResponseEntity<?> deptMbrSaveProc(@RequestBody DeptMbrVO deptMbrVO) throws Exception {
+        // 부서 사용자 등록
+        int result = deptService.deptMbrSave(deptMbrVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 부서 목록 조회
+     */
+    @GetMapping(value = "/findAll.json")
+    public ResponseEntity<?> findAll() throws Exception {
+        // Tree용
+        List<HierachyVO> hierachyList = deptService.findByTopNode();
+        // 권한 목록 조회
+        List<AuthorVO> authList = authorService.findAllSystem();
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("hierachyList", hierachyList);
+        result.put("authList", authList);
+        result.put("newDept", new DeptVO());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 부서정보 상세 조회
+     */
+    @PostMapping(value = "/findByDept.json")
+    public ResponseEntity<?> findByDept(@RequestBody HashMap<String, Object> params) throws Exception {
+        // 부서정보 조회
+        Map<String, Object> result = deptService.findByDept(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * @param deptVO
+     * @return
+     * @throws Exception
+     *
+     * 부서 수정
+     */
+    @PostMapping(value = "/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody DeptVO deptVO) throws Exception {
+        // 부서 수정
+        int result = deptService.deptUpdate(deptVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * @param deptVO
+     * @return
+     * @throws Exception
+     *
+     * 부서 삭제
+     */
+    @PostMapping(value = "/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody DeptVO deptVO) throws Exception {
+        // 부서 수정
+        int result = deptService.deptDelete(deptVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.26
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 부서 사용자 삭제
+     */
+    @PostMapping(value = "/deptMbrDelProc.json")
+    public ResponseEntity<?> deptMbrDelProc(@RequestBody List<DeptMbrVO> deptMbrList) throws Exception {
+        // 부서 사용자 삭제
+        int result = deptService.deptMbrDelete(deptMbrList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.29
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 부서에 등록되지 않는 사용자 조회
+     */
+    @PostMapping("/findByMbr.json")
+    public ResponseEntity<?> findByMbr(@RequestBody Map<String, String> params) throws Exception {
+        // 사용자 목록 조회
+        Map<String, Object> result = deptService.findByMbr(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.09
+     * @param deptList
+     * @return
+     * @throws Exception
+     *
+     * 부서 목록 수정
+     */
+    @PostMapping(value = "/updateListProc.json")
+    public ResponseEntity<?> updateListProc(@RequestBody List<HierachyVO> deptList) throws Exception {
+        // 부서 목록 수정
+        int result = deptService.updateList(deptList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}
 
src/main/java/com/takensoft/cms/main/dao/MainDAO.java (added)
+++ src/main/java/com/takensoft/cms/main/dao/MainDAO.java
@@ -0,0 +1,62 @@
+package com.takensoft.cms.main.dao;
+
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.29
+ *
+ * 메인 관련 Mapper
+ */
+@Mapper("mainDAO")
+public interface MainDAO {
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.28
+     *
+     * 관리자 메인페이지 : 신규회원 가입자 수
+     */
+    public int selectCntnNewCnt() throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.28
+     *
+     * 관리자 메인페이지 : 오늘 방문자 수
+     */
+    public int selectCntnDayCnt() throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.28
+     *
+     * 관리자 메인페이지 : 이번달 방문자 수
+     */
+    public int selectCntnMmCnt() throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.28
+     *
+     * 관리자 메인페이지 : 총 방문자 수
+     */
+    public int selectCntnTotalCnt() throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.28
+     *
+     * 관리자 메인페이지 : 방문자 접속 통계
+     */
+    public List<HashMap<String, Object>> findByMonthCntnStats() throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.28
+     *
+     * 관리자 메인페이지 : 기업상담신청 알림
+     */
+    public List<HashMap<String, Object>> findAplyToasts() throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/main/service/Impl/MainServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/main/service/Impl/MainServiceImpl.java
@@ -0,0 +1,71 @@
+package com.takensoft.cms.main.service.Impl;
+
+import com.takensoft.cms.bbs.dao.BbsCnDAO;
+import com.takensoft.cms.main.dao.MainDAO;
+import com.takensoft.cms.main.service.MainService;
+import com.takensoft.cms.popup.dao.PopupDAO;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.29
+ *
+ * 메인 관련 인터페이스
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * GovernmentMainService : 메인 관련 인터페이스 상속
+ */
+@Service("mainService")
+@RequiredArgsConstructor
+public class MainServiceImpl extends EgovAbstractServiceImpl implements MainService {
+    private final MainDAO mainDAO;
+    private final PopupDAO popupDAO;
+    private final BbsCnDAO bbsCnDAO;
+
+    /**
+     * @author takensoft
+     * @since 2024.05.27
+     *
+     * 관리자 메인페이지 통계정보 조회 [ 신규회원 가입자 수, 오늘 방문자 수, 이번달 방문자 수, 총 방문자 수 ]
+     */
+    @Override
+    public Map<String, Object> selectAdminMain() throws Exception {
+        Map<String, Object> result = new HashMap<>();
+
+        // 팝업 관리
+        result.put("popupMng", popupDAO.selectPopupListByNew());
+        
+        // 최신 등록 글
+        result.put("bbsCnNew", bbsCnDAO.selectBbsCnListByNew());
+
+        // 신규회원 가입자 수
+        // result.put("cntnNewCnt", mainDAO.selectCntnNewCnt());
+
+        // 오늘 방문자 수
+        result.put("cntnDayCnt", mainDAO.selectCntnDayCnt());
+
+        // 이번달 방문자 수
+        result.put("cntnMmCnt", mainDAO.selectCntnMmCnt());
+
+        // 총 방문자 수
+        result.put("cntnTotalCnt", mainDAO.selectCntnTotalCnt());
+
+        // 방문자 접속 통계
+        result.put("monthCntnStats", mainDAO.findByMonthCntnStats());
+
+        return result;
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.06.14
+     *
+     * 관리자 메인페이지 기업상담신청 알람
+     */
+    public List<HashMap<String, Object>> findAplyToasts() throws Exception {
+        return mainDAO.findAplyToasts();
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/main/service/MainService.java (added)
+++ src/main/java/com/takensoft/cms/main/service/MainService.java
@@ -0,0 +1,27 @@
+package com.takensoft.cms.main.service;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.29
+ *
+ * 메인 관련 인터페이스
+ */
+public interface MainService {
+    /**
+     * @author takensoft
+     * @since 2024.05.27
+     *
+     * 관리자 메인페이지 통계정보 조회 [ 신규회원 가입자 수, 오늘 방문자 수, 이번달 방문자 수, 총 방문자 수 ]
+     */
+    public Map<String, Object> selectAdminMain() throws Exception;
+    
+    /**
+     * @author 박정하
+     * @since 2024.06.14
+     *
+     * 관리자 메인페이지 기업상담신청 알람
+     */
+    public List<HashMap<String, Object>> findAplyToasts() throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/main/web/MainController.java (added)
+++ src/main/java/com/takensoft/cms/main/web/MainController.java
@@ -0,0 +1,107 @@
+package com.takensoft.cms.main.web;
+
+import com.takensoft.cms.main.service.MainService;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.29
+ *
+ * 메인 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/admin/main")
+public class MainController {
+    private final MainService mainService;
+    private final CacheManager cacheManager; // 캐시를 관리하기 위한 CacheManager 인스턴스
+
+    /**
+     * @author takensoft
+     * @since 2024.05.27
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 관리자 메인페이지 통계정보 조회 [ 신규회원 가입자 수, 오늘 방문자 수, 이번달 방문자 수, 총 방문자 수, 방문자 접속 통계 ]
+     */
+    @PostMapping("/adminMainProc.json")
+    public ResponseEntity<?> adminMainProc() throws Exception {
+        // 관리자 메인페이지 통계정보 조회
+        Map<String, Object> result = mainService.selectAdminMain();
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.05.29
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 캐시 초기화
+     */
+    @PostMapping("/cacheReSet.json")
+    public ResponseEntity<?> serverRestart() throws Exception {
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        try {
+            for(String nm : cacheManager.getCacheNames()) {
+                cacheManager.getCache(nm).clear();
+            }
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } catch (Exception e) {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("적용에 실패했습니다.\n관리자에게 문의해주시기 바랍니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.06.14
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 관리자 메인페이지 기업상담신청 알람
+     */
+    @PostMapping("/findAplyToastsProc.json")
+    public ResponseEntity<?> findAplyToastsProc() throws Exception {
+        List<HashMap<String, Object>> result = mainService.findAplyToasts();
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/Schedule/RefreshScheduler.java (added)
+++ src/main/java/com/takensoft/cms/mber/Schedule/RefreshScheduler.java
@@ -0,0 +1,34 @@
+package com.takensoft.cms.mber.Schedule;
+
+import com.takensoft.cms.mber.dao.RefreshTokenDAO;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * RefreshToken 만료 기한이 된 token 제거를 위한 스케쥴러
+ */
+@Component
+public class RefreshScheduler {
+
+    private final RefreshTokenDAO refreshTokenDAO;
+
+    public RefreshScheduler(RefreshTokenDAO refreshTokenDAO) {
+        this.refreshTokenDAO = refreshTokenDAO;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.05
+     * refresh token 삭제 스케쥴러
+     * 매일 자정에 만료 기한이 지난 refresh token 삭제
+     */
+    @Scheduled(cron = "0 0 0 * * *")
+    @Transactional(rollbackFor = Exception.class)
+    public void cleanExpiredRefreshTokens() {
+        refreshTokenDAO.cleanExpiredRefreshTokens();
+    }
+}
 
src/main/java/com/takensoft/cms/mber/dao/AdmMbrDAO.java (added)
+++ src/main/java/com/takensoft/cms/mber/dao/AdmMbrDAO.java
@@ -0,0 +1,92 @@
+package com.takensoft.cms.mber.dao;
+
+import com.takensoft.cms.mber.dto.AdmMbrDTO;
+import com.takensoft.cms.mber.dto.JoinDTO;
+import com.takensoft.cms.mber.vo.MberAuthorVO;
+import com.takensoft.cms.mber.vo.MberVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.06.21
+ *
+ * 회원정보 관련 Mapper
+ */
+@Mapper("admMbrDAO")
+public interface AdmMbrDAO {
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 목록 갯수
+     */
+    public int mbrListCnt(Pagination pagination) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 목록 조회
+     */
+    public List<AdmMbrDTO> mbrList(Pagination pagination) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 상세 조회
+     */
+    public AdmMbrDTO mbrDetail(String mbrId) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 수정
+     */
+    public int updateMbr(AdmMbrDTO admMbrDTO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 권한 목록 삭제 (mbrId 사용)
+     */
+    public int deleteAuthorListByMbrId(String mbrId) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원 권한 목록 삭제 (mbrId 사용)
+     */
+    public int insertAuthor(MberAuthorVO mberAuthorVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 등록
+     */
+    public int mbrInsert(JoinDTO joinDTO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.07.03
+     *
+     * 아이디 찾기 (로그인 아이디)
+     */
+    public String lgnIdSearch(MberVO mbrVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.07.03
+     *
+     * 아이디 찾기 (멤버 아이디)
+     */
+    public String mbrIdSearch(AdmMbrDTO admMbrDTO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/dao/LgnHstryDAO.java (added)
+++ src/main/java/com/takensoft/cms/mber/dao/LgnHstryDAO.java
@@ -0,0 +1,40 @@
+package com.takensoft.cms.mber.dao;
+
+import com.takensoft.cms.mber.vo.LgnHstryVO;
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 로그인 이력 관련 Mapper
+ */
+@Mapper("lgnHstryDAO")
+public interface LgnHstryDAO {
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 로그인 이력 등록
+     */
+    int save(LgnHstryVO lgnHstryVO);
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 로그인 이력 목록 갯수
+     */
+    public int selectLgnHstryListCnt(Pagination pagination) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 로그인 이력 목록 조회
+     */
+    public List<LgnHstryVO> selectLgnHstryList(Pagination pagination) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/dao/MberDAO.java (added)
+++ src/main/java/com/takensoft/cms/mber/dao/MberDAO.java
@@ -0,0 +1,61 @@
+package com.takensoft.cms.mber.dao;
+
+import com.takensoft.cms.mber.dto.JoinDTO;
+import com.takensoft.cms.mber.dto.PasswordDTO;
+import com.takensoft.cms.mber.vo.MberAuthorVO;
+import com.takensoft.cms.mber.vo.MberVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 회원 정보 관련 Mapper
+ */
+@Mapper("mberDAO")
+public interface MberDAO {
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     * 사용자 정보 조회 [security 용]
+     */
+    MberVO findByMberSecurity(String lgnId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     * 아이디 중복 검사
+     */
+    boolean findByCheckLoginId(String lgnId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     * 회원가입
+     */
+    int save(JoinDTO joinDTO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     * 사용자 권한 등록
+     */
+    int authorSave(MberAuthorVO mberAuthorVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 비밀 번호 변경
+     */
+    int updatePassword(PasswordDTO passwordDTO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 사용자 정보 조회
+     */
+    MberVO findByMber(String mbrId);
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/dao/RefreshTokenDAO.java (added)
+++ src/main/java/com/takensoft/cms/mber/dao/RefreshTokenDAO.java
@@ -0,0 +1,42 @@
+package com.takensoft.cms.mber.dao;
+
+import com.takensoft.cms.mber.vo.RefreshVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * RefreshToken 관련 Mapper
+ */
+@Mapper("refreshTokenDAO")
+public interface RefreshTokenDAO {
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * refresh token 등록
+     */
+    int save(RefreshVO refreshVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * refresh token 삭제
+     */
+    int deleteByRefresh(RefreshVO refreshVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * 기한 만료된 refresh token 삭제 [ Schedule 용 ]
+     */
+    int cleanExpiredRefreshTokens();
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * refresh token 등록 유무 확인
+     */
+    boolean findByCheckRefresh(RefreshVO refreshVO);
+}
 
src/main/java/com/takensoft/cms/mber/dto/AdmMbrDTO.java (added)
+++ src/main/java/com/takensoft/cms/mber/dto/AdmMbrDTO.java
@@ -0,0 +1,136 @@
+package com.takensoft.cms.mber.dto;
+
+import com.takensoft.cms.mber.vo.MberAuthorVO;
+import lombok.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.06.21
+ *
+ * 회원정보 관련 DTO
+ */
+@Setter
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ToString
+public class AdmMbrDTO {
+    /**
+     * 회원 아이디
+     */
+    private String mbrId;
+    /**
+     * 로그인 아이디
+     */
+    private String lgnId;
+    /**
+     * 회원 이름
+     */
+    private String mbrNm;
+    /**
+     * 닉네임
+     */
+    private String ncnm;
+    /**
+     * 비밀번호
+     */
+    private String pswd;
+    /**
+     * 휴대폰번호
+     */
+    private String mblTelno;
+    /**
+     * 전화번호
+     */
+    private String telno;
+    /**
+     * 이메일
+     */
+    private String eml;
+    /**
+     * 우편번호
+     */
+    private String zip;
+    /**
+     * 주소
+     */
+    private String addr;
+    /**
+     * 상세주소
+     */
+    private String daddr;
+    /**
+     * 회원상태
+     * 0: 탈퇴, 1: 승인, 2: 승인대기, 3: 차단
+     */
+    private String mbrStts;
+    /**
+     * 사용여부
+     */
+    private String useYn;
+    /**
+     * 차단일
+     */
+    private String cntrlDt;
+    /**
+     * 차단사유
+     */
+    private String cntrlRsn;
+    /**
+     * 문자수신여부
+     * 0: 거부, 1: 허용
+     */
+    private String smsRcptnAgreYn;
+    /**
+     * 이메일수신여부
+     * 0: 거부, 1: 허용
+     */
+    private String emlRcptnAgreYn;
+    /**
+     * 개인정보공개여부
+     * 0: 거부, 1: 허용
+     */
+    private String prvcRlsYn;
+    /**
+     * 회원형태
+     * S: 시스템, K: 카카오, N: 네이버, G: 구글, F: 페이스북
+     */
+    private String mbrType;
+    /**
+     * 비밀번호 변경일
+     */
+    private String pswdChgDt;
+    /**
+     * 최초등록 아이디
+     */
+    private String frstRegIp;
+    /**
+     * 시스템 제공 여부 -> 시스템에서 제공되는 데이터는 사용자가 제거하지 못하도록 하기 위한 설정값
+     * 0: 시스템, 1: 사용자
+     */
+    private String sysPvsnYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+    /**
+     * 권한 정보
+     */
+    private List<MberAuthorVO> authorList = new ArrayList<MberAuthorVO>();
+}
 
src/main/java/com/takensoft/cms/mber/dto/JoinDTO.java (added)
+++ src/main/java/com/takensoft/cms/mber/dto/JoinDTO.java
@@ -0,0 +1,145 @@
+package com.takensoft.cms.mber.dto;
+
+import com.takensoft.cms.mber.vo.MberAuthorVO;
+import lombok.*;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 회원 가입 관련 DTO
+ */
+@Setter
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ToString
+public class JoinDTO {
+    /**
+     * 회원 아이디
+     */
+    private String mbrId;
+    /**
+     * 로그인 아이디
+     */
+    @NotBlank(message = "로그인 아이디는 필수 입력 값입니다.")
+    @Size(min = 5, max = 50)
+    private String lgnId;
+    /**
+     * 회원 이름
+     */
+    @NotBlank(message = "이름은 필수 입력 값입니다.")
+    @Size(min = 2, max = 50)
+    private String mbrNm;
+    /**
+     * 닉네임
+     */
+    private String ncnm;
+    /**
+     * 비밀번호
+     */
+    @NotBlank(message = "비밀번호는 필수 입력 값입니다.")
+    private String pswd;
+    /**
+     * 휴대폰번호
+     */
+    private String mblTelno;
+    /**
+     * 전화번호
+     */
+    private String telno;
+    /**
+     * 이메일
+     */
+    @Email(message = "이메일 형식에 맞지 않습니다.")
+    private String eml;
+    /**
+     * 우편번호
+     */
+    private String zip;
+    /**
+     * 주소
+     */
+    private String addr;
+    /**
+     * 상세주소
+     */
+    private String daddr;
+    /**
+     * 회원상태
+     * 0: 탈퇴, 1: 승인, 2: 승인대기, 3: 차단
+     */
+    private String mbrStts;
+    /**
+     * 사용여부
+     */
+    private String useYn;
+    /**
+     * 차단일
+     */
+    private String cntrlDt;
+    /**
+     * 차단사유
+     */
+    private String cntrlRsn;
+    /**
+     * 문자수신여부
+     * 0: 거부, 1: 허용
+     */
+    private String smsRcptnAgreYn;
+    /**
+     * 이메일수신여부
+     * 0: 거부, 1: 허용
+     */
+    private String emlRcptnAgreYn;
+    /**
+     * 개인정보공개여부
+     * 0: 거부, 1: 허용
+     */
+    private String prvcRlsYn;
+    /**
+     * 회원형태
+     * S: 시스템, K: 카카오, N: 네이버, G: 구글, F: 페이스북
+     */
+    private String mbrType;
+    /**
+     * 비밀번호 변경일
+     */
+    private String pswdChgDt;
+    /**
+     * 최초등록 아이디
+     */
+    private String frstRegIp;
+    /**
+     * 시스템 제공 여부 -> 시스템에서 제공되는 데이터는 사용자가 제거하지 못하도록 하기 위한 설정값
+     * 0: 시스템, 1: 사용자
+     */
+    private String sysPvsnYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+    /**
+     * 권한 정보
+     */
+    private List<MberAuthorVO> authorList = new ArrayList<MberAuthorVO>();
+}
 
src/main/java/com/takensoft/cms/mber/dto/LoginDTO.java (added)
+++ src/main/java/com/takensoft/cms/mber/dto/LoginDTO.java
@@ -0,0 +1,35 @@
+package com.takensoft.cms.mber.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 로그인 관련 DTO
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class LoginDTO {
+    /**
+     * 로그인 아이디
+     */
+    @NotNull
+    private String lgnId;
+    /**
+     * 비밀번호
+     */
+    @NotNull
+    private String pswd;
+    /**
+     * refreshToken 정보
+     */
+    private String refreshToken;
+}
 
src/main/java/com/takensoft/cms/mber/dto/PasswordDTO.java (added)
+++ src/main/java/com/takensoft/cms/mber/dto/PasswordDTO.java
@@ -0,0 +1,37 @@
+package com.takensoft.cms.mber.dto;
+
+
+import lombok.*;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 비밀 번호 변경
+ */
+@Setter
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ToString
+public class PasswordDTO {
+    /**
+     * 회원 아이디
+     */
+    private String mbrId;
+
+    /**
+     * 비밀번호[현재 비밀번호]
+     */
+    @NotBlank(message = "비밀번호는 필수 입력 값입니다.")
+    private String pswd;
+
+    /**
+     * 비밀번호[변경될 비밀번호]
+     */
+    @NotBlank(message = "변경할 비밀번호는 필수 입력 값입니다.")
+    private String newPswd;
+}
 
src/main/java/com/takensoft/cms/mber/service/AdmMbrService.java (added)
+++ src/main/java/com/takensoft/cms/mber/service/AdmMbrService.java
@@ -0,0 +1,64 @@
+package com.takensoft.cms.mber.service;
+
+import com.takensoft.cms.mber.dto.AdmMbrDTO;
+import com.takensoft.cms.mber.dto.JoinDTO;
+import com.takensoft.cms.mber.vo.MberVO;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.06.21
+ *
+ * 회원정보 관련 인터페이스
+ */
+public interface AdmMbrService {
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 목록 조회
+     */
+    public HashMap<String, Object> mbrList(HashMap<String, String> params) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 상세 조회
+     */
+    public AdmMbrDTO mbrDetail(String mbrId) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 수정
+     */
+    public int updateMbr(AdmMbrDTO admMbrDTO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 등록
+     */
+    public HashMap<String, Object> mbrInsert(HttpServletRequest req, JoinDTO joinDTO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.07.03
+     *
+     * 아이디 찾기 (로그인 아이디)
+     */
+    public String lgnIdSearch(MberVO mbrVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.07.03
+     *
+     * 아이디 찾기 (멤버 아이디)
+     */
+    public int mbrIdSearch(String resetPswd, AdmMbrDTO admMbrDTO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/service/Impl/AdmMbrServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/mber/service/Impl/AdmMbrServiceImpl.java
@@ -0,0 +1,235 @@
+package com.takensoft.cms.mber.service.Impl;
+
+import com.takensoft.cms.mber.dao.AdmMbrDAO;
+import com.takensoft.cms.mber.dto.AdmMbrDTO;
+import com.takensoft.cms.mber.dto.JoinDTO;
+import com.takensoft.cms.mber.dto.PasswordDTO;
+import com.takensoft.cms.mber.service.AdmMbrService;
+import com.takensoft.cms.mber.service.MberService;
+import com.takensoft.cms.mber.vo.MberAuthorVO;
+import com.takensoft.cms.mber.vo.MberVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.CommonUtils;
+import com.takensoft.common.util.JWTUtil;
+import com.takensoft.common.util.Secret;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.06.21
+ *
+ * 회원정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * AdmMbrService : 회원정보 인터페이스 상속
+ */
+@Service("admMbrService")
+@RequiredArgsConstructor
+public class AdmMbrServiceImpl extends EgovAbstractServiceImpl implements AdmMbrService {
+    private final JWTUtil jwtUtil;
+    private final IdgenService mberIdgn;
+    private final CommonUtils commonUtils;
+    private final BCryptPasswordEncoder bCryptPasswordEncoder;
+    private final AdmMbrDAO admMbrDAO;
+    private final MberService mbrService;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 목록 조회
+     */
+    @Override
+    public HashMap<String, Object> mbrList(HashMap<String, String> params) throws Exception {
+        Pagination search = new Pagination(0, params);
+        int cnt = admMbrDAO.mbrListCnt(search);
+
+        Pagination pagination = new Pagination(cnt, params);
+        List<AdmMbrDTO> list = admMbrDAO.mbrList(pagination);
+
+        // 휴대폰번호 복호화
+        for (AdmMbrDTO admMbrDTO : list) {
+            if (admMbrDTO.getMblTelno() != null && !admMbrDTO.getMblTelno().equals("")) {
+                admMbrDTO.setMblTelno(Secret.decrypt(admMbrDTO.getMblTelno().toString()));
+            }
+        }
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("list", list);
+        result.put("pagination", pagination);
+        return result;
+
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 상세 조회
+     */
+    @Override
+    public AdmMbrDTO mbrDetail(String mbrId) throws Exception {
+        AdmMbrDTO admMbrDTO = new AdmMbrDTO();
+
+        // mbrId가 있는 경우
+        if (mbrId != null) {
+            admMbrDTO = admMbrDAO.mbrDetail(mbrId);
+
+            // 휴대폰번호 복호화
+            if (admMbrDTO.getMblTelno() != null && !admMbrDTO.getMblTelno().equals("")) {
+                admMbrDTO.setMblTelno(Secret.decrypt(admMbrDTO.getMblTelno()));
+            }
+
+            // 전화번호 복호화
+            if (admMbrDTO.getTelno() != null && !admMbrDTO.getTelno().equals("")) {
+                admMbrDTO.setTelno(Secret.decrypt(admMbrDTO.getTelno()));
+            }
+        }
+        // mbrId가 없는 경우
+        else {
+            admMbrDTO.setUseYn("Y");
+            admMbrDTO.setMbrStts("1");
+            admMbrDTO.setSmsRcptnAgreYn("Y");
+            admMbrDTO.setEmlRcptnAgreYn("Y");
+        }
+
+        return admMbrDTO;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 수정
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateMbr(AdmMbrDTO admMbrDTO) throws Exception {
+        // 비밀번호 변경
+        if (admMbrDTO.getPswd() != null && !admMbrDTO.getPswd().equals("")) {
+            PasswordDTO passwordDTO = new PasswordDTO();
+            passwordDTO.setMbrId(admMbrDTO.getMbrId());
+            passwordDTO.setNewPswd(admMbrDTO.getPswd());
+            mbrService.updatePassword(passwordDTO);
+        }
+
+        // 연락처 암호화
+        if(admMbrDTO.getMblTelno() != null && !admMbrDTO.getMblTelno().equals("")){
+            admMbrDTO.setMblTelno(Secret.encrypt(admMbrDTO.getMblTelno()));
+        }
+        if(admMbrDTO.getTelno() != null && !admMbrDTO.getTelno().equals("")) {
+            admMbrDTO.setTelno(Secret.encrypt(admMbrDTO.getTelno()));
+        }
+
+        // 수정자 조회 및 등록
+        String writer = jwtUtil.getWriter();
+        admMbrDTO.setMdfr(writer);
+
+        // 회원정보 수정
+        int result = admMbrDAO.updateMbr(admMbrDTO);
+
+        // 권한 수정
+        result += admMbrDAO.deleteAuthorListByMbrId(admMbrDTO.getMbrId()); // 회원 권한 전체 삭제
+        if (admMbrDTO.getUseYn().equals("Y")) {
+            if(admMbrDTO.getAuthorList() != null && admMbrDTO.getAuthorList().size() > 0) {
+                for(MberAuthorVO mberAuthorVO : admMbrDTO.getAuthorList()) {
+                    mberAuthorVO.setMbrId(admMbrDTO.getMbrId());
+                    mberAuthorVO.setRgtr(writer);
+                    result += admMbrDAO.insertAuthor(mberAuthorVO);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.06.21
+     *
+     * 회원정보 등록
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HashMap<String, Object> mbrInsert(HttpServletRequest req, JoinDTO joinDTO) throws Exception {
+        // 회원 아이디 생성
+        String mbrId = mberIdgn.getNextStringId();
+        joinDTO.setMbrId(mbrId);
+
+        // 비밀번호 암호화
+        joinDTO.setPswd(bCryptPasswordEncoder.encode(joinDTO.getPswd()));
+
+        // 연락처 암호화
+        if(joinDTO.getMblTelno() != null && !joinDTO.getMblTelno().equals("")) {
+            joinDTO.setMblTelno(Secret.encrypt(joinDTO.getMblTelno()));
+        }
+        if(joinDTO.getTelno() != null && !joinDTO.getTelno().equals("")) {
+            joinDTO.setTelno(Secret.encrypt(joinDTO.getTelno()));
+        }
+
+        // 아이피 등록
+        String ip = commonUtils.getIp(req);
+        joinDTO.setFrstRegIp(ip);
+
+        // 작성자 등록
+        String writer = jwtUtil.getWriter();
+        if(writer != null && !writer.equals("")) {
+            joinDTO.setRgtr(writer);
+        }
+
+        // 회원정보 등록
+        int insertResult = admMbrDAO.mbrInsert(joinDTO);
+
+        // 권한 등록
+        if(joinDTO.getAuthorList().size() > 0) {
+            for(MberAuthorVO mberAuthorVO : joinDTO.getAuthorList()) {
+                mberAuthorVO.setMbrId(joinDTO.getMbrId());
+                mberAuthorVO.setRgtr(writer);
+                insertResult += admMbrDAO.insertAuthor(mberAuthorVO);
+            }
+        }
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("mbrId", mbrId);
+        result.put("insertResult", insertResult);
+        return result;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.07.03
+     *
+     * 아이디 찾기 (로그인 아이디)
+     */
+    public String lgnIdSearch(MberVO mbrVO) throws Exception {
+        return admMbrDAO.lgnIdSearch(mbrVO);
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.07.03
+     *
+     * 아이디 찾기 (멤버 아이디)
+     */
+    public int mbrIdSearch(String resetPswd, AdmMbrDTO admMbrDTO) throws Exception {
+        String mbrId = admMbrDAO.mbrIdSearch(admMbrDTO);
+
+        PasswordDTO passwordDTO = new PasswordDTO();
+        passwordDTO.setMbrId(mbrId);
+        passwordDTO.setPswd(admMbrDTO.getPswd());
+        passwordDTO.setNewPswd(resetPswd);
+
+        // 비밀번호 변경
+        int result = mbrService.updatePassword(passwordDTO);
+
+        return result;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/service/Impl/LgnHstryServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/mber/service/Impl/LgnHstryServiceImpl.java
@@ -0,0 +1,66 @@
+package com.takensoft.cms.mber.service.Impl;
+
+
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.cms.mber.dao.LgnHstryDAO;
+import com.takensoft.cms.mber.service.LgnHstryService;
+import com.takensoft.cms.mber.vo.LgnHstryVO;
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 로그인 이력 정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * LgnHstryService : 로그인 이력 정보 인터페이스 상속
+ */
+@Service("lgnHstryService")
+@RequiredArgsConstructor
+public class LgnHstryServiceImpl extends EgovAbstractServiceImpl implements LgnHstryService {
+    private final LgnHstryDAO lgnHstryDAO;
+    private final CodeManageService codeManageService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 로그인 이력 등록
+     */
+    @Override
+    public int LgnHstrySave(LgnHstryVO lgnHstryVO) throws Exception {
+        return lgnHstryDAO.save(lgnHstryVO);
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 로그인 이력 목록 조회
+     */
+    @Override
+    public HashMap<String, Object> lgnHstryList(HashMap<String, String> params) throws Exception {
+        Pagination search = new Pagination(0, params);
+        int cnt = lgnHstryDAO.selectLgnHstryListCnt(search);
+
+        Pagination pagination = new Pagination(cnt, params);
+        List<LgnHstryVO> list = lgnHstryDAO.selectLgnHstryList(pagination);
+        List<CodeManageVO> codeList = codeManageService.findByChildCdCache("lgnHstry"); // 검색 조건
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("list", list);
+        result.put("pagination", pagination);
+        result.put("codeList", codeList);
+        return result;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/service/Impl/MberServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/mber/service/Impl/MberServiceImpl.java
@@ -0,0 +1,170 @@
+package com.takensoft.cms.mber.service.Impl;
+
+import com.takensoft.cms.mber.dao.MberDAO;
+import com.takensoft.cms.mber.dto.JoinDTO;
+import com.takensoft.cms.mber.dto.PasswordDTO;
+import com.takensoft.cms.mber.service.MberService;
+import com.takensoft.cms.mber.vo.MberAuthorVO;
+import com.takensoft.cms.mber.vo.MberVO;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.CommonUtils;
+import com.takensoft.common.util.JWTUtil;
+import com.takensoft.common.util.Secret;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 회원 정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * UserDetailsService : security 사용을 위해 상속
+ * MberService : 회원정보 인터페이스 상속
+ */
+@Service("mberService")
+@RequiredArgsConstructor
+public class MberServiceImpl extends EgovAbstractServiceImpl implements UserDetailsService, MberService {
+    private final MberDAO mberDAO;
+    private final IdgenService mberIdgn;
+    private final BCryptPasswordEncoder bCryptPasswordEncoder;
+    private final JWTUtil jwtUtil;
+    private final CommonUtils commonUtils;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     *
+     * security 상속 시 Override 하는 메소드
+     */
+    @Override
+    @Transactional(readOnly = true)
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        return mberDAO.findByMberSecurity(username);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     *
+     * 아이디 중복 검사
+     */
+    @Override
+    public boolean findByCheckLoginId(String lgnId) throws Exception {
+        return mberDAO.findByCheckLoginId(lgnId);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     * 회원가입
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HashMap<String, Object> userJoin(HttpServletRequest req,  JoinDTO joinDTO) throws Exception {
+        // 회원 아이디 생성
+        String mbrId = mberIdgn.getNextStringId();
+        joinDTO.setMbrId(mbrId);
+
+        // 비밀번호 암호화
+        joinDTO.setPswd(bCryptPasswordEncoder.encode(joinDTO.getPswd()));
+
+        // 연락처 암호화
+        if(joinDTO.getMblTelno() != null && !joinDTO.getMblTelno().equals("")) {
+            joinDTO.setMblTelno(Secret.encrypt(joinDTO.getMblTelno()));
+        }
+        if(joinDTO.getTelno() != null && !joinDTO.getTelno().equals("")) {
+            joinDTO.setTelno(Secret.encrypt(joinDTO.getTelno()));
+        }
+
+        // 아이피 조회 및 등록
+        joinDTO.setFrstRegIp(commonUtils.getIp(req));
+        
+        // 작성자 조회 및 등록
+        if(jwtUtil.getWriter() != null && !jwtUtil.getWriter().equals("")) {
+            joinDTO.setRgtr(jwtUtil.getWriter());
+        }
+
+        // 회원정보 등록
+        HashMap<String, Object> result = new HashMap<>();
+        int saveResult = mberDAO.save(joinDTO);
+        result.put("mbrId", mbrId);
+
+        // 권한 등록
+        int authorResult = 0;
+        if(joinDTO.getAuthorList().size() > 0) {
+            for(MberAuthorVO vo : joinDTO.getAuthorList()) {
+                vo.setMbrId(joinDTO.getMbrId());
+                // 작성자 조회 및 등록
+                if(jwtUtil.getWriter() != null && !jwtUtil.getWriter().equals("")) {
+                    vo.setRgtr(jwtUtil.getWriter());
+                }
+                authorResult += mberDAO.authorSave(vo);
+            }
+        }
+        result.put("result", saveResult + authorResult);
+
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 비밀번호 비교
+     */
+    @Override
+    public boolean passwordCheck(PasswordDTO passwordDTO) throws Exception {
+        // 회원 정보 호출
+        MberVO mbr = mberDAO.findByMber(jwtUtil.getWriter());
+        // 비밀번호 비교 후 성공 시 비밀번호 수정 후 true 반환
+        if(bCryptPasswordEncoder.matches(passwordDTO.getPswd(), mbr.getPassword())) {
+            passwordDTO.setNewPswd(bCryptPasswordEncoder.encode(passwordDTO.getNewPswd()));
+            passwordDTO.setMbrId(mbr.getMbrId());
+            mberDAO.updatePassword(passwordDTO);
+            return true;
+            // 기존 비밀번호와 입력한 비밀번호가 서로 다를 경우 false 반환
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.04.23
+     * 회원정보 상세 조회
+     */
+    @Override
+    public MberVO findByMbr(HashMap<String, Object> params) throws Exception {
+        String mbrId = params.get("mbrId").toString();
+        MberVO mberVO = mberDAO.findByMber(mbrId);
+        // 휴대폰번호 복호화
+        if (mberVO.getMblTelno() != null && !mberVO.getMblTelno().equals("")) {
+            mberVO.setMblTelno(Secret.decrypt(mberVO.getMblTelno().toString()));
+        }
+        // 전화번호 복호화
+        if (mberVO.getTelno() != null && !mberVO.getTelno().equals("")) {
+            mberVO.setTelno(Secret.decrypt(mberVO.getTelno().toString()));
+        }
+        return mberVO;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 비밀번호 수정
+     */
+    @Override
+    public int updatePassword(PasswordDTO passwordDTO) throws Exception {
+        passwordDTO.setNewPswd(bCryptPasswordEncoder.encode(passwordDTO.getNewPswd()));
+        return mberDAO.updatePassword(passwordDTO);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/service/Impl/RefreshTokenServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/mber/service/Impl/RefreshTokenServiceImpl.java
@@ -0,0 +1,197 @@
+package com.takensoft.cms.mber.service.Impl;
+
+import com.fasterxml.jackson.datatype.jsr310.ser.YearSerializer;
+import com.takensoft.cms.mber.dao.RefreshTokenDAO;
+import com.takensoft.cms.mber.service.RefreshTokenService;
+import com.takensoft.cms.mber.vo.MberAuthorVO;
+import com.takensoft.cms.mber.vo.MberVO;
+import com.takensoft.cms.mber.vo.RefreshVO;
+import com.takensoft.common.util.CommonUtils;
+import com.takensoft.common.util.JWTUtil;
+import io.jsonwebtoken.ExpiredJwtException;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * RefreshToken 정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * RefreshTokenService : RefreshToken 인터페이스 상속
+ */
+@Service("refreshTokenService")
+@RequiredArgsConstructor
+public class RefreshTokenServiceImpl extends EgovAbstractServiceImpl implements RefreshTokenService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(RefreshTokenServiceImpl.class);
+    private final RefreshTokenDAO refreshTokenDAO;
+    private final JWTUtil jwtUtil;
+    private final CommonUtils commonUtils;
+
+    @Value("${jwt.accessTime}")
+    private long JWT_ACCESSTIME; // access 토큰 유지 시간
+    @Value("${jwt.refreshTime}")
+    private long JWT_REFRESHTIME; // refresh 토큰 유지 시간
+    @Value("${cookie.time}")
+    private int COOKIE_TIME; // 쿠키 유지 시간
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * refresh token 검증
+     */
+    private Map<String, Object> refreshTokenCheck(HttpServletRequest req) {
+        Map<String, Object> result = new HashMap <String, Object>();
+        // header 방식
+//        String refreshToken = req.getHeader("refresh");
+        // 쿠키 방식
+        String refreshToken = null;
+        Cookie[] cookies = req.getCookies();
+        for (Cookie cookie : cookies) {
+            if (cookie.getName().equals("refresh")) refreshToken = cookie.getValue();
+        }
+        if(refreshToken == null) {
+            result.put("result", 0);
+            return result;
+        }
+        try {
+            jwtUtil.isExpired(refreshToken);
+        } catch (ExpiredJwtException e) {
+            result.put("result", 0);
+            return result;
+        }
+        String category = jwtUtil.getCategory(refreshToken);
+        if(!category.equals("refresh")) {
+            result.put("result", 0);
+            return result;
+        }
+        result.put("result", 1);
+        result.put("refreshToken", refreshToken);
+
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * refresh token 등록
+     */
+    @Override
+    public int saveRefreshToken(HttpServletRequest req, HttpServletResponse res, RefreshVO refresh, long expiredMs) throws Exception {
+        // 만료 시간
+        refresh.setExpryDt(new Date(System.currentTimeMillis() + expiredMs));
+        // 사용중인 아이피
+        refresh.setUseIp(commonUtils.getIp(req));
+        return refreshTokenDAO.save(refresh);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * refresh token 삭제 프로세스 (로그아웃)
+     */
+    @Override
+    public int deleteByRefresh(HttpServletRequest req, HttpServletResponse res) throws Exception {
+        // refresh token 검증
+        int result = (int) refreshTokenCheck(req).get("result");
+        if(result == 0) return result;
+
+        //Refresh 토큰 Cookie 값 0
+//        res.addCookie(jwtUtil.createCookie("refresh",null, 0));
+
+        RefreshVO refreshVO = new RefreshVO();
+        refreshVO.setMbrId(jwtUtil.getMbrId(refreshTokenCheck(req).get("refreshToken").toString()));
+
+        return delete(req, refreshVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * 토큰 재발급
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int tokenReissueProc(HttpServletRequest req, HttpServletResponse res) throws Exception {
+        // refresh token 검증
+        int result = (int) refreshTokenCheck(req).get("result");
+        if(result == 0) return result;
+
+        String refreshToken = refreshTokenCheck(req).get("refreshToken").toString();
+
+        Date expired = jwtUtil.getExpired(refreshToken);
+
+        // 만료시간과 현재 시간의 차이 계산
+        long timeDffrnc = (expired.getTime() - new Date().getTime()) / (1000 * 60 * 60);
+
+        MberVO mber = new MberVO();
+        List<MberAuthorVO> roles = jwtUtil.getRoles(refreshToken);
+        mber.setLgnId(jwtUtil.getLgnId(refreshToken));
+        mber.setMbrId(jwtUtil.getMbrId(refreshToken));
+        mber.setMbrNm(jwtUtil.getMbrNm(refreshToken));
+        mber.setAuthorList(roles);
+        // 신규 AccessToken 발행
+        String newAccessToken = jwtUtil.createJwt("Authorization", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_ACCESSTIME);
+
+        // 남은 시간이 3시간 미만으로 남았을 경우 RefreshToken 재발급
+        if(timeDffrnc < 3) {
+            RefreshVO refresh = new RefreshVO();
+            refresh.setMbrId(mber.getMbrId());
+
+            // 기존 RefreshToken 삭제
+            result += delete(req, refresh);
+
+            // 신규 RefreshToken 발행
+            String newRefreshToken = jwtUtil.createJwt("refresh", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_REFRESHTIME);
+            refresh.setToken(newRefreshToken);
+            result += saveRefreshToken(req, res,refresh, JWT_REFRESHTIME);
+
+            // 응답설정 RefreshToken
+//            res.setHeader("refresh", newRefreshToken);
+            // 쿠키 방식
+            res.addCookie(jwtUtil.createCookie("refresh",newRefreshToken, COOKIE_TIME));
+        }
+        // 응답설정 AccessToken
+        res.setHeader("Authorization", newAccessToken);
+
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * 토큰 삭제
+     */
+    @Override
+    public int delete(HttpServletRequest req, RefreshVO refreshVO) throws Exception {
+        refreshVO.setUseIp(commonUtils.getIp(req));
+        return refreshTokenDAO.deleteByRefresh(refreshVO);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * refresh token 등록 유무 확인
+     */
+    @Override
+    public boolean findByCheckRefresh(HttpServletRequest req, RefreshVO refreshVO) throws Exception {
+        // 사용중인 아이피
+        refreshVO.setUseIp(commonUtils.getIp(req));
+        return refreshTokenDAO.findByCheckRefresh(refreshVO);
+    }
+
+}
 
src/main/java/com/takensoft/cms/mber/service/LgnHstryService.java (added)
+++ src/main/java/com/takensoft/cms/mber/service/LgnHstryService.java
@@ -0,0 +1,28 @@
+package com.takensoft.cms.mber.service;
+
+import com.takensoft.cms.mber.vo.LgnHstryVO;
+
+import java.util.HashMap;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 로그인 이력 정보 관련 인터페이스
+ */
+public interface LgnHstryService {
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 로그인 이력 등록
+     */
+    public int LgnHstrySave(LgnHstryVO lgnHstryVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 로그인 이력 목록 조회
+     */
+    public HashMap<String, Object> lgnHstryList(HashMap<String, String> params) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/service/MberService.java (added)
+++ src/main/java/com/takensoft/cms/mber/service/MberService.java
@@ -0,0 +1,52 @@
+package com.takensoft.cms.mber.service;
+
+import com.takensoft.cms.mber.dto.JoinDTO;
+import com.takensoft.cms.mber.dto.PasswordDTO;
+import com.takensoft.cms.mber.vo.MberVO;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 회원 정보 관련 인터페이스
+ */
+public interface MberService {
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     *
+     * 아이디 중복 검사
+     */
+    public boolean findByCheckLoginId(String lgnId) throws  Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.03
+     * 회원가입
+     */
+    public HashMap<String, Object> userJoin(HttpServletRequest req, JoinDTO joinDTO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 비밀번호 비교
+     */
+    public boolean passwordCheck(PasswordDTO passwordDTO) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.04.23
+     * 회원정보 상세 조회
+     */
+    public MberVO findByMbr(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 비밀번호 수정
+     */
+    public int updatePassword(PasswordDTO passwordDTO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/service/RefreshTokenService.java (added)
+++ src/main/java/com/takensoft/cms/mber/service/RefreshTokenService.java
@@ -0,0 +1,50 @@
+package com.takensoft.cms.mber.service;
+
+import com.takensoft.cms.mber.vo.RefreshVO;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * RefreshToken 정보 관련 인터페이스
+ */
+public interface RefreshTokenService {
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * refresh token 등록
+     */
+    public int saveRefreshToken(HttpServletRequest req, HttpServletResponse res, RefreshVO refresh, long expiredMs) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * refresh token 삭제 프로세스
+     */
+    public int deleteByRefresh(HttpServletRequest req, HttpServletResponse res) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * 토큰 재발급
+     */
+    public int tokenReissueProc(HttpServletRequest req, HttpServletResponse res) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * 토큰 삭제
+     */
+    public int delete(HttpServletRequest req, RefreshVO refreshVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.17
+     * refresh token 등록 유무 확인
+     */
+    public boolean findByCheckRefresh(HttpServletRequest req, RefreshVO refreshVO) throws Exception;
+}
 
src/main/java/com/takensoft/cms/mber/vo/LgnHstryVO.java (added)
+++ src/main/java/com/takensoft/cms/mber/vo/LgnHstryVO.java
@@ -0,0 +1,47 @@
+package com.takensoft.cms.mber.vo;
+
+import lombok.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 로그인 이력 정보 관련 VO
+ */
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class LgnHstryVO {
+
+    /**
+     * 로그인 아이디
+     */
+    private String lgnId;
+    /**
+     * 로그인 유형
+     */
+    private String lgnType;
+    /**
+     * 접속일
+     */
+    private String cntnDt;
+    /**
+     * 접속 아이피
+     */
+    private String cntnIp;
+    /**
+     * 접속 운영체제
+     */
+    private String cntnOperSys;
+    /**
+     * 디바이스명
+     */
+    private String deviceNm;
+    /**
+     * 브라우저명
+     */
+    private String brwsrNm;
+}
 
src/main/java/com/takensoft/cms/mber/vo/MberAuthorVO.java (added)
+++ src/main/java/com/takensoft/cms/mber/vo/MberAuthorVO.java
@@ -0,0 +1,38 @@
+package com.takensoft.cms.mber.vo;
+
+import lombok.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 회원 권한 정보 관련 VO
+ */
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class MberAuthorVO {
+    /**
+     * 회원 아이디
+     */
+    private String mbrId;
+    /**
+     * 권한명
+     */
+    private String authrtNm;
+    /**
+     * 권한 코드
+     */
+    private String authrtCd;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/vo/MberVO.java (added)
+++ src/main/java/com/takensoft/cms/mber/vo/MberVO.java
@@ -0,0 +1,190 @@
+package com.takensoft.cms.mber.vo;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 회원 정보 관련 VO
+ * UserDetails : security 사용을 위해 상속
+ * Serializable : 직렬화를 위해 상속
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class MberVO implements UserDetails, Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 회원 아이디
+     */
+    private String mbrId;
+    /**
+     * 로그인 아이디
+     */
+    private String lgnId;
+    /**
+     * 회원 이름
+     */
+    private String mbrNm;
+    /**
+     * 닉네임
+     */
+    private String ncnm;
+    /**
+     * 비밀번호
+     */
+    private String pswd;
+    /**
+     * 휴대폰번호
+     */
+    private String mblTelno;
+    /**
+     * 전화번호
+     */
+    private String telno;
+    /**
+     * 이메일
+     */
+    private String eml;
+    /**
+     * 우편번호
+     */
+    private String zip;
+    /**
+     * 주소
+     */
+    private String addr;
+    /**
+     * 상세주소
+     */
+    private String daddr;
+    /**
+     * 회원상태
+     * 0: 탈퇴, 1: 승인, 2: 승인대기, 3: 차단
+     */
+    private String mbrStts;
+    /**
+     * 사용여부
+     */
+    private boolean useYn;
+    /**
+     * 차단일
+     */
+    private String cntrlDt;
+    /**
+     * 차단사유
+     */
+    private String cntrlRsn;
+    /**
+     * 문자수신여부
+     * 0: 거부, 1: 허용
+     */
+    private String smsRcptnAgreYn;
+    /**
+     * 이메일수신여부
+     * 0: 거부, 1: 허용
+     */
+    private String emlRcptnAgreYn;
+    /**
+     * 개인정보공개여부
+     * 0: 거부, 1: 허용
+     */
+    private String prvcRlsYn;
+    /**
+     * 회원형태
+     * S: 시스템, K: 카카오, N: 네이버, G: 구글, F: 페이스북
+     */
+    private String mbrType;
+    /**
+     * 비밀번호 변경일
+     */
+    private String pswdChgDt;
+    /**
+     * 최초등록 아이디
+     */
+    private String frstRegIp;
+    /**
+     * 시스템 제공 여부 -> 시스템에서 제공되는 데이터는 사용자가 제거하지 못하도록 하기 위한 설정값
+     * 0: 시스템, 1: 사용자
+     */
+    private String sysPvsnYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+    /**
+     * 권한 정보
+     */
+    @JsonIgnore
+    private List<MberAuthorVO> authorList = new ArrayList<MberAuthorVO>();
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        if(this.authorList.size() > 0) {
+            return this.authorList.stream().map(auth -> new SimpleGrantedAuthority(
+                    auth.getAuthrtCd()
+            )).collect(Collectors.toList());
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public String getPassword() {
+        return this.pswd;
+    }
+
+    @Override
+    public String getUsername() {
+        return this.lgnId;
+    }
+
+    @Override
+    public boolean isAccountNonExpired() {
+        return this.useYn;
+    }
+
+    @Override
+    public boolean isAccountNonLocked() {
+        return this.useYn;
+    }
+
+    @Override
+    public boolean isCredentialsNonExpired() {
+        return this.useYn;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return this.useYn;
+    }
+}
 
src/main/java/com/takensoft/cms/mber/vo/RefreshVO.java (added)
+++ src/main/java/com/takensoft/cms/mber/vo/RefreshVO.java
@@ -0,0 +1,37 @@
+package com.takensoft.cms.mber.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * RefreshToken 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class RefreshVO {
+    /**
+     * 회원 아이디
+     */
+    private String mbrId;
+    /**
+     * 토큰
+     */
+    private String token;
+    /**
+     * 만료기간 expry_dt expryYmd
+     */
+    private Date expryDt;
+    /**
+     * 사용중인 아이피
+     */
+    private String useIp;
+}
 
src/main/java/com/takensoft/cms/mber/web/AdmMbrController.java (added)
+++ src/main/java/com/takensoft/cms/mber/web/AdmMbrController.java
@@ -0,0 +1,277 @@
+package com.takensoft.cms.mber.web;
+
+import com.takensoft.cms.mber.dto.AdmMbrDTO;
+import com.takensoft.cms.mber.dto.JoinDTO;
+import com.takensoft.cms.mber.dto.PasswordDTO;
+import com.takensoft.cms.mber.service.AdmMbrService;
+import com.takensoft.cms.mber.service.MberService;
+import com.takensoft.cms.mber.vo.MberVO;
+import com.takensoft.common.exception.IdDuplicationException;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.beans.factory.annotation.Value;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.06.21
+ *
+ * 회원정보 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/mbr")
+public class AdmMbrController {
+    private final AdmMbrService admMbrService;
+    private final MberService mbrService;
+
+    /**
+     * @author 박정하
+     * @since 2024.06.21
+     * @param params
+     * @return
+     * @throws Exception
+     *
+     * 회원정보 목록 조회
+     */
+    @PostMapping(value = "/listProc.json")
+    public ResponseEntity<?> listProc(@RequestBody HashMap<String, String> params) throws Exception {
+        HashMap<String, Object> result = admMbrService.mbrList(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.06.21
+     * @param resetPswd, admMbrDTO
+     * @return
+     * @throws Exception
+     *
+     * 회원정보 비밀번호 초기화
+    */
+    @PostMapping(value = "/pswdResetProc.json")
+    public ResponseEntity<?> pswdResetProc(@Value("${password.reset}") String resetPswd, @RequestBody AdmMbrDTO admMbrDTO) throws  Exception {
+        PasswordDTO passwordDTO = new PasswordDTO();
+        passwordDTO.setMbrId(admMbrDTO.getMbrId());
+        passwordDTO.setPswd(admMbrDTO.getPswd());
+        passwordDTO.setNewPswd(resetPswd);
+
+        // 비밀번호 변경
+        int result = mbrService.updatePassword(passwordDTO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 초기화 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("초기화에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.06.21
+     * @param admMbrDTO
+     * @return
+     * @throws Exception
+     *
+     * 회원정보 상세 조회
+     */
+    @PostMapping(value = "/detailProc.json")
+    public ResponseEntity<?> detailProc(@RequestBody AdmMbrDTO admMbrDTO) throws Exception {
+        // 상세 조회
+        AdmMbrDTO result = admMbrService.mbrDetail(admMbrDTO.getMbrId());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 회원정보 상세 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.06.21
+     * @param admMbrDTO
+     * @return
+     * @throws Exception
+     *
+     * 회원정보 수정
+     */
+    @PostMapping(value = "/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody AdmMbrDTO admMbrDTO) throws Exception {
+        int result = admMbrService.updateMbr(admMbrDTO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.06.21
+     * @param admMbrDTO
+     * @return
+     * @throws Exception
+     *
+     * 회원정보 삭제
+     */
+    @PostMapping(value = "/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody AdmMbrDTO admMbrDTO) throws Exception {
+        admMbrDTO.setUseYn("N"); // 회원정보 삭제
+        int result = admMbrService.updateMbr(admMbrDTO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+    
+    /**
+     * @author 박정하
+     * @since 2024.06.21
+     * @param req, joinDTO
+     * @return
+     * @throws Exception
+     *
+     * 회원정보 등록
+     */
+    @PostMapping(value = "/joinProc.json")
+    public ResponseEntity<?> joinProc(HttpServletRequest req, @RequestBody @Valid JoinDTO joinDTO) throws Exception {
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        // 아이디 중복 검사
+        boolean isExistence = mbrService.findByCheckLoginId(joinDTO.getLgnId());
+        if(isExistence) {
+//            throw new IdDuplicationException("이미 존재하는 아이디입니다.");
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("이미 존재하는 아이디입니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        // 회원 가입 진행
+        HashMap<String, Object> result = admMbrService.mbrInsert(req, joinDTO);
+        int insertResult = (int) result.get("insertResult");
+
+        if(insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 회원가입 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("회원가입에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.07.03
+     * @param mbrVO
+     * @return
+     * @throws Exception
+     *
+     * 아이디 찾기
+     */
+    @PostMapping(value = "/searchIdProc.json")
+    public ResponseEntity<?> searchIdProc(@RequestBody MberVO mbrVO) throws Exception {
+        String result = admMbrService.lgnIdSearch(mbrVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result != null) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 조회 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("입력하신 정보와 일치하는 회원이 존재하지 않습니다.\n다시 시도하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+
+    /**
+     * @author 박정하
+     * @since 2024.07.03
+     * @param admMbrDTO
+     * @return
+     * @throws Exception
+     *
+     * 비밀번호 초기화
+     */
+    @PostMapping(value = "/resetPswdProc.json")
+    public ResponseEntity<?> resetPswdProc(@Value("${password.reset}") String resetPswd, @RequestBody AdmMbrDTO admMbrDTO) throws Exception {
+        int result = admMbrService.mbrIdSearch(resetPswd, admMbrDTO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 조회 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("입력하신 정보와 일치하는 회원이 존재하지 않습니다.\n다시 시도하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/web/LgnHstryController.java (added)
+++ src/main/java/com/takensoft/cms/mber/web/LgnHstryController.java
@@ -0,0 +1,52 @@
+package com.takensoft.cms.mber.web;
+
+import com.takensoft.cms.mber.service.LgnHstryService;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.24
+ *
+ * 로그인 이력 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/admin/lgnHstry")
+public class LgnHstryController {
+    private final LgnHstryService lgnHstryService;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.13
+     * @param params
+     * @return
+     * @throws Exception
+     *
+     * 로그인 이력 목록 조회
+     */
+    @PostMapping("/listProc.json")
+    public ResponseEntity<?> listProc(@RequestBody HashMap<String, String> params) throws Exception {
+        HashMap<String, Object> result = lgnHstryService.lgnHstryList(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/web/MberController.java (added)
+++ src/main/java/com/takensoft/cms/mber/web/MberController.java
@@ -0,0 +1,87 @@
+package com.takensoft.cms.mber.web;
+
+import com.takensoft.cms.mber.dto.JoinDTO;
+import com.takensoft.cms.mber.dto.PasswordDTO;
+import com.takensoft.cms.mber.service.MberService;
+import com.takensoft.cms.mber.vo.MberVO;
+import com.takensoft.common.exception.IdDuplicationException;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 회원 정보 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value = "/mbr")
+public class MberController {
+    private final MberService mberService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.16
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 회원정보 상세 조회
+     */
+    @PostMapping(value = "/findByMbr.json")
+    public ResponseEntity<?> findByMbr(@RequestBody HashMap<String, Object> params) throws Exception {
+        // 상세 조회
+        MberVO result = mberService.findByMbr(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 회원정보 상세 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * @param passwordDTO
+     * @return
+     * @throws Exception
+     *
+     * 비밀번호 변경
+     */
+    @PostMapping(value = "/updatePassword.json")
+    public ResponseEntity<?> joinProc(@RequestBody @Valid PasswordDTO passwordDTO) throws  Exception {
+        // 비밀 번호 비교
+        boolean isExistence = mberService.passwordCheck(passwordDTO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(isExistence) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("비밀번호를 확인하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/mber/web/RefreshTokenController.java (added)
+++ src/main/java/com/takensoft/cms/mber/web/RefreshTokenController.java
@@ -0,0 +1,89 @@
+package com.takensoft.cms.mber.web;
+
+
+import com.takensoft.cms.mber.service.RefreshTokenService;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.nio.charset.Charset;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * RefreshToken 정보 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+public class RefreshTokenController {
+
+    private final RefreshTokenService refreshTokenService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * @return
+     * @throws Exception
+     * 로그아웃
+     */
+    @PostMapping(value = "/mbr/logout.json")
+    public ResponseEntity<?> logout(HttpServletRequest req, HttpServletResponse res) throws Exception {
+        int result = refreshTokenService.deleteByRefresh(req, res);
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            Cookie cookie = new Cookie("refresh", null);
+            cookie.setMaxAge(0); // 생명주기
+            //cookie.setSecure(true); // https 통신을 할 경우 true로 사용
+            cookie.setPath("/"); // 쿠키 적용 범위
+            cookie.setHttpOnly(true);
+            res.addCookie(cookie);
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 로그아웃 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("로그아웃에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.04
+     * @return
+     * @throws Exception
+     * 토큰 재발급
+     */
+    @PostMapping("/refresh/tokenReissue.json")
+    public ResponseEntity<?> tokenReissue(HttpServletRequest req, HttpServletResponse res) throws Exception {
+        int result = refreshTokenService.tokenReissueProc(req, res);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 발급 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("로그인을 다시해주시기 바랍니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}
 
src/main/java/com/takensoft/cms/menu/dao/MenuAuthorDAO.java (added)
+++ src/main/java/com/takensoft/cms/menu/dao/MenuAuthorDAO.java
@@ -0,0 +1,37 @@
+package com.takensoft.cms.menu.dao;
+
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.menu.vo.MenuAuthorVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.07
+ *
+ * 메뉴 권한 정보 관련 Mapper
+ */
+@Mapper("menuAuthorDAO")
+public interface MenuAuthorDAO {
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 메뉴별 권한 등록
+     */
+    public int menuAuthrtSave(MenuAuthorVO menuAuthorVO);
+
+    /**
+     * @author 박정하
+     * @since 2024.05.02
+     * 메뉴 권한 수정
+     */
+    public int updateMenuAuthrt(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.08
+     * 메뉴 권한 조회
+     */
+    public List<HashMap<String, Object>> findAll(AuthorVO authorVO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/menu/dao/MenuDAO.java (added)
+++ src/main/java/com/takensoft/cms/menu/dao/MenuDAO.java
@@ -0,0 +1,147 @@
+package com.takensoft.cms.menu.dao;
+
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.contsType.vo.ContsTypeVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.cms.menu.vo.*;
+import com.takensoft.common.HierachyVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 메뉴 정보 관련 Mapper
+ */
+@Mapper("menuDAO")
+public interface MenuDAO {
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 최상위 메뉴 조회
+     */
+    List<MenuVO> findTopMenu();
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 하위 메뉴 조회
+     */
+    List<MenuVO> findChildMenus(String menuId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 메뉴 전체 조회(최상위 메뉴 제외-> grd:0)
+     */
+    List<MenuVO> findExceptTopMenu();
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴 등록
+     */
+    int save(MenuVO menuVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 메뉴 수정
+     */
+    int update(MenuVO menuVO);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴 상세 조회
+     */
+    MenuVO findByMenu(String menuId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴 깊이 조회
+     */
+    int findByMenuGrd(String upMenuId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴 순서 조회
+     */
+    int findByMenuSn(String upMenuId);
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴별 만족도 등록
+     */
+    int saveMenuStsfdg(MenuStsfdgVO menuStsfdgVO);
+
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 최상위 부서 조회
+     */
+    List<HierachyVO> findByTopNode();
+    /**
+     * @author takensoft
+     * @since 2024.04.24
+     * 하위 부서 조회
+     */
+    List<HierachyVO> findChildNode(String id);
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author 박정하
+     * @since 2024.04.29
+     * 상위,하위 메뉴 삭제
+     */
+    int deleteMenu(MenuVO menuVO);
+
+    /**
+     * @author 박정하
+     * @since 2024.05.02
+     * 상위 메뉴 조회
+     */
+    String findUpMenuId(String MenuId);
+
+    /**
+     * @author takensoft
+     * @since 2024.05.09
+     * 메뉴 조회(시스템용)
+     */
+    List<SysMenuVO> findByMenuWithRouter(MenuRequest menuRequest);
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 메뉴 정보 수정 (hierachyVO 사용)
+     */
+    public int menuUpdateByHierachy(MenuVO menuVO) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 메뉴 수정 (콘텐츠 유형)
+     */
+    public int updateByContsId(ContsTypeVO contsTypeVO) throws Exception;
+
+    /**
+     * @author 방선주
+     * @since 2024.06.07
+     * 게시판 관리에서 게시판 삭제 시 게시판 메뉴 미노출로 변경
+     */
+    public int bbsMngMenuDelete(MenuVO menuVO) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.07.18
+     * 메뉴 개수 조회 (접속 통계용)
+     */
+    public int findAllCnt(HashMap<String, Object> params) throws Exception;
+}
 
src/main/java/com/takensoft/cms/menu/service/Impl/MenuAuthorServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/menu/service/Impl/MenuAuthorServiceImpl.java
@@ -0,0 +1,126 @@
+package com.takensoft.cms.menu.service.Impl;
+
+import com.takensoft.cms.author.dao.AuthorDAO;
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.menu.dao.MenuAuthorDAO;
+import com.takensoft.cms.menu.dao.MenuDAO;
+import com.takensoft.cms.menu.service.MenuAuthorService;
+import com.takensoft.cms.menu.vo.MenuAuthorVO;
+import com.takensoft.cms.menu.vo.MenuVO;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.07
+ *
+ * 메뉴 권한 정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * MenuAuthorService : 메뉴 정보 인터페이스 상속
+ */
+@Service("menuAuthorServiceImpl")
+@RequiredArgsConstructor
+public class MenuAuthorServiceImpl extends EgovAbstractServiceImpl implements MenuAuthorService {
+    private final MenuDAO menuDAO;
+    private final MenuAuthorDAO menuAuthorDAO;
+    private final AuthorDAO authorDAO;
+    private final JWTUtil jwtUtil;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 메뉴별 권한 등록을 위한 전처리
+     */
+    private MenuAuthorVO saveMenuAuthor(String menuId, String AuthrtCd) {
+        MenuAuthorVO menuAuthorVO = new MenuAuthorVO();
+        menuAuthorVO.setMenuId(menuId);
+        menuAuthorVO.setAuthrtCd(AuthrtCd);
+        return menuAuthorVO;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 메뉴별 권한 등록
+     * 파라미터로 들어오는 id는 type에 따라 권한 코드 or 메뉴 아이디로 들어옴
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public int menuAuthrtSave(String id, String type) throws Exception {
+        int result = 0;
+        // 타입이 null or empty 경우 에러 발생
+        if(type == null || type.equals("")) {
+            throw new IllegalArgumentException("type is null or empty");
+        }
+        // 신규 메뉴 등록 시
+        if("menu".equals(type)) {
+            // 등록된 권한 목록 조회
+            List<AuthorVO> authList = authorDAO.findAllSystem();
+            for(AuthorVO author : authList) {
+                MenuAuthorVO menuAuthor = saveMenuAuthor(id, author.getAuthrtCd());
+                result += menuAuthorDAO.menuAuthrtSave(menuAuthor);
+            }
+            // 신규 권한 등록 시
+        } else if("author".equals(type)) {
+            // 등록된 메뉴 목록 조회
+            List<MenuVO> menuList = menuDAO.findExceptTopMenu();
+            for(MenuVO menu : menuList) {
+                MenuAuthorVO menuAuthor = saveMenuAuthor(menu.getMenuId(), id);
+                result += menuAuthorDAO.menuAuthrtSave(menuAuthor);
+            }
+            // 타입이 맞지 않다면 에러
+        } else {
+            throw new IllegalArgumentException("Invalid value : " + type);
+        }
+        return result;
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.02
+     * 메뉴 권한 수정
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    @CacheEvict(value = "routerAuthInfo", allEntries = true)
+    public int updateMenuAuthrtProc(HashMap<String, Object> params) throws Exception {
+        int result = 0;
+        List<HashMap<String, Object>> menuList = (List<HashMap<String, Object>>)params.get("menuList");
+        String authrtCd = params.get("authrtCd").toString();
+        for(HashMap<String, Object> menu : menuList) {
+            menu.put("mdfr", jwtUtil.getWriter());
+            menu.put("authrtCd", authrtCd);
+            result += menuAuthorDAO.updateMenuAuthrt(menu);
+        }
+        return result;
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.08
+     * 메뉴 권한 조회
+     */
+    @Override
+    public List<HashMap<String, Object>> findAll(AuthorVO authorVO) throws Exception {
+        List<HashMap<String, Object>> result = menuAuthorDAO.findAll(authorVO);
+        for(HashMap<String, Object> menuAuthor : result) {
+            if (menuAuthor.get("upMenuId") != null) {
+                if (menuAuthor.get("inqAuthrt") != null && menuAuthor.get("regAuthrt") != null && menuAuthor.get("mdfcnAuthrt") != null && menuAuthor.get("delAuthrt") != null && menuAuthor.get("fileDwnldAuthrt") != null) {
+                    if(menuAuthor.get("inqAuthrt").equals("Y") && menuAuthor.get("regAuthrt").equals("Y") && menuAuthor.get("mdfcnAuthrt").equals("Y") && menuAuthor.get("delAuthrt").equals("Y") && menuAuthor.get("fileDwnldAuthrt").equals("Y")) {
+                        menuAuthor.put("checkedAll", "Y");
+                    } else {
+                        menuAuthor.put("checkedAll", "N");
+                    }
+                }
+            }
+        }
+        return result;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/menu/service/Impl/MenuServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/menu/service/Impl/MenuServiceImpl.java
@@ -0,0 +1,310 @@
+package com.takensoft.cms.menu.service.Impl;
+
+import com.takensoft.cms.menu.dao.MenuAuthorDAO;
+import com.takensoft.cms.menu.dao.MenuDAO;
+import com.takensoft.cms.menu.service.MenuAuthorService;
+import com.takensoft.cms.menu.service.MenuService;
+import com.takensoft.cms.menu.vo.MenuAuthorVO;
+import com.takensoft.cms.menu.vo.MenuRequest;
+import com.takensoft.cms.menu.vo.MenuVO;
+import com.takensoft.cms.menu.vo.SysMenuVO;
+import com.takensoft.common.HierachyVO;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 메뉴 정보 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * AuthorService : 메뉴 정보 인터페이스 상속
+ */
+@Service("menuServiceImpl")
+@RequiredArgsConstructor
+public class MenuServiceImpl extends EgovAbstractServiceImpl implements MenuService {
+    private final MenuDAO menuDAO;
+    private final MenuAuthorService menuAuthorService;
+    private final MenuAuthorDAO menuAuthorDAO;
+    private final IdgenService menuIdgn;
+    private final JWTUtil jwtUtil;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 메뉴별 권한 등록을 위한 전처리
+     */
+    private MenuAuthorVO saveMenuAuthor(String menuId, String AuthrtCd) {
+        MenuAuthorVO menuAuthorVO = new MenuAuthorVO();
+        menuAuthorVO.setMenuId(menuId);
+        menuAuthorVO.setAuthrtCd(AuthrtCd);
+        return menuAuthorVO;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴 등록
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    @CacheEvict(value = "findByMenuWithRouter", allEntries = true)
+    public int menuSave(MenuVO menuVO) throws Exception {
+        // 메뉴 아이디 생성
+        String menuId = menuIdgn.getNextStringId();
+        menuVO.setMenuId(menuId);
+        // 상위 메뉴가 존재하는 경우
+        if(menuVO.getUpMenuId() != null && !menuVO.getUpMenuId().equals("")) {
+            // 상위 메뉴 아이디 보다 깊이(레벨) 1추가
+            menuVO.setMenuGrd(menuDAO.findByMenuGrd(menuVO.getUpMenuId()) + 1);
+            // 동일한 깊이의 메뉴 순서 보다 1추가
+            menuVO.setMenuSn(menuDAO.findByMenuSn(menuVO.getUpMenuId()) + 1);
+        // 상위메뉴가 존재 하지 않는 경우
+        } else {
+            menuVO.setMenuGrd(0);
+            menuVO.setMenuSn(menuDAO.findByMenuSn(null) + 1);
+        }
+        // 작성자 정보
+        String writer = jwtUtil.getWriter();
+        menuVO.setRgtr(writer);
+        // 시스템 제공 여부
+        menuVO.setSysPvsnYn("1");
+        if(menuVO.getMenuGrd() != 0) {
+            String upMenuId = menuVO.getUpMenuId();
+            for (int i = 0; i < menuVO.getMenuGrd() - 1; i++) {
+                upMenuId = menuDAO.findUpMenuId(upMenuId);
+            }
+            if (upMenuId.equals("MENU_000000000000001")) {
+                menuVO.setSysPvsnYn("0");
+            }
+        }
+        // 메뉴 등록
+        int result = menuDAO.save(menuVO);
+
+        // 메뉴별 권한 등록
+        if(result > 0 && menuVO.getMenuGrd() != 0) {
+            String oriMenuId = menuVO.getMenuId();
+            for (int i = 0; i < menuVO.getMenuGrd(); i++) {
+                oriMenuId = menuDAO.findUpMenuId(oriMenuId);
+            }
+            if (oriMenuId.equals("MENU_000000000000001")) {
+                MenuAuthorVO menuAuthor = saveMenuAuthor(menuId, "ROLE_ADMIN");
+                result += menuAuthorDAO.menuAuthrtSave(menuAuthor);
+            } else {
+                result += menuAuthorService.menuAuthrtSave(menuId, "menu");
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 전체 메뉴 조회
+     * !!현재 java버전과 mybatis버전이 낮은관계로 재귀적 쿼리 작성 불가!!
+     */
+    @Override
+    public List<MenuVO> findAll() throws Exception {
+        // 상위 메뉴 조회
+        List<MenuVO> topMenus = menuDAO.findTopMenu();
+        // 상위 메뉴에 따른 하위 메뉴 조회
+        for(MenuVO menu : topMenus) {
+            List<MenuVO> childMenus = findByChildMenu(menu.getMenuId());
+            menu.setChildMenuList(childMenus);
+        }
+
+        return topMenus;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 하위 메뉴 조회
+     */
+    @Override
+    public List<MenuVO> findByChildMenu(String menuId) throws Exception {
+        List<MenuVO> childMenus = menuDAO.findChildMenus(menuId);
+        for(MenuVO menu : childMenus) {
+            List<MenuVO> grandChildMenus = findByChildMenu(menu.getMenuId());
+            menu.setChildMenuList(grandChildMenus);
+        }
+        return childMenus;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴 상세 조회
+     */
+    @Override
+    public MenuVO findByMenu(String menuId) throws Exception {
+        return menuDAO.findByMenu(menuId);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 메뉴 수정
+     */
+    @Override
+    @CacheEvict(value = "findByMenuWithRouter", allEntries = true)
+    public int MenuUpdate(MenuVO menuVO) throws Exception {
+        // 토큰정보에서 사용자 아이디 조회 후 등록
+        menuVO.setMdfr(jwtUtil.getWriter());
+        return menuDAO.update(menuVO);
+    }
+
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 최상위 메뉴 조회
+     */
+    @Override
+    public List<HierachyVO> findByTopNode() throws Exception {
+        List<HierachyVO> topDeptList = menuDAO.findByTopNode();
+        for(HierachyVO vo : topDeptList) {
+            List<HierachyVO> child = findChildNode(vo.getId());
+            vo.setChildList(child);
+        }
+        return topDeptList;
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 하위 메뉴 조회
+     */
+    @Override
+    public List<HierachyVO> findChildNode(String id) throws Exception {
+        List<HierachyVO> childList = menuDAO.findChildNode(id);
+        for(HierachyVO vo : childList) {
+            List<HierachyVO> child = findChildNode(vo.getId());
+            vo.setChildList(child);
+        }
+        return childList;
+    }
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author 박정하
+     * @since 2024.04.29
+     * 메뉴 정보 삭제
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int menuDelete(MenuVO menuVO) throws Exception {
+        menuVO.setMdfr(jwtUtil.getWriter());
+        return menuDAO.deleteMenu(menuVO);
+    }
+
+    /************************************** 홈페이지 메뉴 호출 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.05.09
+     * 메뉴 조회(시스템용)
+     */
+    @Override
+    @Cacheable(value = "findByMenuWithRouter", key = "#mReq.menuType")
+    public List<SysMenuVO> findByMenuWithRouter(MenuRequest mReq) throws Exception {
+        if(mReq.isChck() && mReq.getMenuType().equals("adm")) {
+            mReq.setMenuId("MENU_000000000000001");
+        } else if(mReq.isChck() && mReq.getMenuType().equals("company")) {
+            mReq.setMenuId("MENU_000000000000002");
+        } else if(mReq.isChck() && mReq.getMenuType().equals("government")) {
+            mReq.setMenuId("MENU_000000000000003");
+        }
+        mReq.setChck(false);
+        List<SysMenuVO> result = menuDAO.findByMenuWithRouter(mReq);
+        for(SysMenuVO vo : result) {
+            mReq.setMenuId(vo.getMenuId());
+            List<SysMenuVO> child = findByMenuWithRouter(mReq);
+            vo.setChildList(child);
+        }
+        return result;
+    }
+    /************************************** 홈페이지 메뉴 호출 전용 **************************************/
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 메뉴 정보 수정 (hierachyVO 사용)
+     */
+    @Override
+    @CacheEvict(value = "findByMenuWithRouter", allEntries = true)
+    @Transactional(rollbackFor = Exception.class)
+    public int updateList(List<HierachyVO> deptList) throws Exception {
+        int result = 0;
+        String writer = jwtUtil.getWriter();
+
+        if(deptList != null && deptList.size() > 0) {
+            int sn = 1;
+            for(HierachyVO hierachyVO : deptList) {
+                // 최상위 노드 수정
+                MenuVO vo = new MenuVO();
+                vo.setMenuId(hierachyVO.getId());
+                vo.setUpMenuId(null);
+                vo.setMenuGrd(0);
+                vo.setMenuSn(sn);
+                vo.setMdfr(writer);
+                result += menuDAO.menuUpdateByHierachy(vo);
+
+                // 하위 노드 수정
+                if (hierachyVO.getChildList() != null && hierachyVO.getChildList().size() > 0) {
+                    result += updateChildNode(hierachyVO.getChildList(), vo);
+                }
+                sn++;
+            }
+        }
+        return result;
+    }
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 하위 메뉴 수정
+     */
+    @Override
+    @CacheEvict(value = "findByMenuWithRouter", allEntries = true)
+    public int updateChildNode(List<HierachyVO> childList, MenuVO upMenuVO) throws Exception {
+        int result = 0;
+        String upDeptId = upMenuVO.getMenuId();
+        int grd = upMenuVO.getMenuGrd() + 1;
+        int sn = 1;
+        String mdfr = upMenuVO.getMdfr();
+        for(HierachyVO hierachyVO : childList) {
+            // 현재 노드 수정
+            MenuVO vo = new MenuVO();
+            vo.setMenuId(hierachyVO.getId());
+            vo.setUpMenuId(upDeptId);
+            vo.setMenuGrd(grd);
+            vo.setMenuSn(sn);
+            vo.setMdfr(mdfr);
+            result += menuDAO.menuUpdateByHierachy(vo);
+
+            // 하위 노드 수정
+            if (hierachyVO.getChildList() != null && hierachyVO.getChildList().size() > 0) {
+                result += updateChildNode(hierachyVO.getChildList(), vo);
+            }
+            sn++;
+        }
+        return result;
+    }
+    /**
+     * @author 방선주
+     * @since 2024.06.07
+     * 게시판 관리에서 게시판 삭제 시 게시판 메뉴 미노출로 변경
+     */
+    @Override
+    @CacheEvict(value = "findByMenuWithRouter", allEntries = true)
+    public int bbsMngMenuDelete(MenuVO menuVO) throws Exception {
+        return menuDAO.bbsMngMenuDelete(menuVO);
+    }
+}
 
src/main/java/com/takensoft/cms/menu/service/MenuAuthorService.java (added)
+++ src/main/java/com/takensoft/cms/menu/service/MenuAuthorService.java
@@ -0,0 +1,34 @@
+package com.takensoft.cms.menu.service;
+
+import com.takensoft.cms.author.vo.AuthorVO;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.07
+ *
+ * 메뉴 권한 정보 관련 인터페이스
+ */
+public interface MenuAuthorService {
+    /**
+     * @author takensoft
+     * @since 2024.04.15
+     * 메뉴별 권한 등록
+     */
+    public int menuAuthrtSave(String menuId, String type) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.02
+     * 메뉴 권한 수정
+     */
+    public int updateMenuAuthrtProc(HashMap<String, Object> params) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.08
+     * 메뉴 권한 조회
+     */
+    public List<HashMap<String, Object>> findAll(AuthorVO authorVO) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/menu/service/MenuService.java (added)
+++ src/main/java/com/takensoft/cms/menu/service/MenuService.java
@@ -0,0 +1,102 @@
+package com.takensoft.cms.menu.service;
+
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.contsType.vo.ContsTypeVO;
+import com.takensoft.cms.menu.vo.MenuRequest;
+import com.takensoft.cms.menu.vo.MenuStsfdgVO;
+import com.takensoft.cms.menu.vo.MenuVO;
+import com.takensoft.cms.menu.vo.SysMenuVO;
+import com.takensoft.common.HierachyVO;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 메뉴 정보 관련 인터페이스
+ */
+public interface MenuService {
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴 등록
+     */
+    public int menuSave(MenuVO menuVO) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 전체 메뉴 조회
+     */
+    public List<MenuVO> findAll() throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 하위 메뉴 조회
+     */
+    public List<MenuVO> findByChildMenu(String menuId) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * 메뉴 조회
+     */
+    public MenuVO findByMenu(String menuId) throws Exception;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.09
+     * 메뉴 수정
+     */
+    public int MenuUpdate(MenuVO menuVO) throws Exception;
+
+    /************************************** Hierachy 전용 **************************************/
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 최상위 코드 조회
+     */
+    public List<HierachyVO> findByTopNode() throws Exception;
+    /**
+     * @author takensoft
+     * @since 2024.04.25
+     * 하위 코드 조회
+     */
+    public List<HierachyVO> findChildNode(String id) throws Exception;
+    /************************************** Hierachy 전용 **************************************/
+
+    /**
+     * @author 박정하
+     * @since 2024.04.29
+     * 메뉴 정보 삭제
+     */
+    public int menuDelete(MenuVO menuVO) throws Exception;
+    /**
+     * @author takensoft
+     * @since 2024.05.09
+     * 메뉴 조회(시스템용)
+     */
+    public List<SysMenuVO> findByMenuWithRouter(MenuRequest menuRequest) throws Exception;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.09
+     * 메뉴 목록 수정
+     */
+    public int updateList(List<HierachyVO> deptList) throws Exception;
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * 하위 메뉴 수정
+     */
+    public int updateChildNode(List<HierachyVO> childList, MenuVO menuVO) throws Exception;
+    /**
+     * @author 방선주
+     * @since 2024.06.07
+     * 게시판 관리에서 게시판 삭제 시 게시판 메뉴 미노출로 변경
+     */
+    public int bbsMngMenuDelete(MenuVO menuVO) throws Exception;
+}
 
src/main/java/com/takensoft/cms/menu/vo/MenuAuthorVO.java (added)
+++ src/main/java/com/takensoft/cms/menu/vo/MenuAuthorVO.java
@@ -0,0 +1,68 @@
+package com.takensoft.cms.menu.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.09
+ *
+ * 메뉴별 권한 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class MenuAuthorVO {
+    /**
+     * 권한코드
+     */
+    private String authrtCd;
+    /**
+     * 메뉴 아이디
+     */
+    private String menuId;
+    /**
+     * 읽기 권한
+     * Y: 여, N: 부
+     */
+    private String inqAuthrt;
+    /**
+     * 쓰기 권한
+     * Y: 여, N: 부
+     */
+    private String regAuthrt;
+    /**
+     * 수정 권한
+     * Y: 여, N: 부
+     */
+    private String mdfcnAuthrt;
+    /**
+     * 삭제 권한
+     * Y: 여, N: 부
+     */
+    private String delAuthrt;
+    /**
+     * 파일다운로드 권한
+     * Y: 여, N: 부
+     */
+    private String fileDwnldAuthrt;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+}
 
src/main/java/com/takensoft/cms/menu/vo/MenuRequest.java (added)
+++ src/main/java/com/takensoft/cms/menu/vo/MenuRequest.java
@@ -0,0 +1,38 @@
+package com.takensoft.cms.menu.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.09
+ *
+ * 메뉴 조회 파라미터
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class MenuRequest {
+    /**
+     * 메뉴 아이디
+     */
+    private String menuId;
+    /**
+     * 권한정보
+     */
+    private List<String> roles;
+    /**
+     * 메뉴 종류
+     */
+    private String menuType;
+
+    /**
+     * 반복 방지
+     */
+    private boolean chck = true;
+}
 
src/main/java/com/takensoft/cms/menu/vo/MenuStsfdgVO.java (added)
+++ src/main/java/com/takensoft/cms/menu/vo/MenuStsfdgVO.java
@@ -0,0 +1,68 @@
+package com.takensoft.cms.menu.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.08
+ *
+ * 메뉴 만족도 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class MenuStsfdgVO {
+    /**
+     * 메뉴별 만족도 아이디
+     */
+    private String menuDgstfnId;
+    /**
+     * 메뉴 아이디
+     */
+    private String menuId;
+    /**
+     * 응답 5
+     * N: 미체크, Y: 체크
+     */
+    private String rspnsFive;
+    /**
+     * 응답 4
+     * N: 미체크, Y: 체크
+     */
+    private String rspnsFour;
+    /**
+     * 응답 3
+     * N: 미체크, Y: 체크
+     */
+    private String rspnsThree;
+    /**
+     * 응답 2
+     * N: 미체크, Y: 체크
+     */
+    private String rspnsTwo;
+    /**
+     * 응답 1
+     * N: 미체크, Y: 체크
+     */
+    private String rspnsOne;
+    /**
+     * 의견
+     */
+    private String opnn;
+    /**
+     * 등록 아이피
+     */
+    private String regIp;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록일
+     */
+    private String regDt;
+}
 
src/main/java/com/takensoft/cms/menu/vo/MenuVO.java (added)
+++ src/main/java/com/takensoft/cms/menu/vo/MenuVO.java
@@ -0,0 +1,122 @@
+package com.takensoft.cms.menu.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.08
+ *
+ * 메뉴 정보 관련 VO
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class MenuVO {
+    /**
+     * 메뉴 아이디
+     */
+    private String menuId;
+    /**
+     * 상위 메뉴 아이디
+     */
+    private String upMenuId;
+    /**
+     * 상위 메뉴명
+     */
+    private String upMenuNm;
+    /**
+     * 메뉴명
+     */
+    private String menuNm;
+    /**
+     * 메뉴 설명
+     */
+    private String menuExpln;
+    /**
+     * 메뉴 깊이(레벨)
+     */
+    private int menuGrd;
+    /**
+     * 메뉴 순서
+     */
+    private int menuSn;
+    /**
+     * 메뉴 타입
+     * 공통코드 : 게시판, 콘텐츠, 링크
+     */
+    private String menuType;
+    /**
+     * 메뉴 타입 항목
+     * 게시판 유형 아이디 / 콘텐츠 유형 아이디
+     */
+    private String menuTypeCtgry;
+    /**
+     * 링크 주소
+     */
+    private String linkUrl;
+    /**
+     * 링크 유형
+     * 0: 현재창, 1: 새창
+     */
+    private String linkType;
+    /**
+     * 만족도조사 사용여부
+     * N: 미사용, Y: 사용
+     */
+    private String dgstfnExmnUseYn;
+    /**
+     * 메뉴 노출여부
+     * N: 미노출, Y: 노출
+     */
+    private String menuExpsrYn;
+    /**
+     * 메뉴 사용자
+     * A: 관리자, U: 사용자
+     */
+    private String menuUser;
+    /**
+     * 사용여부
+     * N: 미사용, Y: 사용
+     */
+    private String useYn;
+    /**
+     * 등록자
+     */
+    private String rgtr;
+    /**
+     * 등록자명
+     */
+    private String rgtrNm;
+    /**
+     * 등록일
+     */
+    private String regDt;
+    /**
+     * 수정자
+     */
+    private String mdfr;
+    /**
+     * 수정자명
+     */
+    private String mdfrNm;
+    /**
+     * 수정일
+     */
+    private String mdfcnDt;
+    /**
+     * 시스템제공여부
+     * 0 : 시스템 등록, 1 : 사용자 등록
+     */
+    private String sysPvsnYn;
+    /**
+     * 하위 메뉴 목록
+     */
+    private List<MenuVO> childMenuList = new ArrayList<MenuVO>();
+}
 
src/main/java/com/takensoft/cms/menu/vo/SysMenuVO.java (added)
+++ src/main/java/com/takensoft/cms/menu/vo/SysMenuVO.java
@@ -0,0 +1,56 @@
+package com.takensoft.cms.menu.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.05.09
+ *
+ * 메뉴 호출(권한, 라우터 정보 포함)
+ */
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class SysMenuVO {
+
+    /**
+     * 메뉴 아이디
+     */
+    String menuId;
+    /**
+     * 상위 메뉴 아이디
+     */
+    String upMenuId;
+    /**
+     * 메뉴명
+     */
+    String menuNm;
+    /**
+     * 라우터 경로
+     */
+    private String routerUrl;
+    /**
+     * 링크 타입
+     */
+    private String linkType;
+    /**
+     * 메뉴 타입
+     */
+    private String menuType;
+    /**
+     * 메뉴 타입 카테고리
+     */
+    private String menuTypeCtgry;
+    /**
+     * 자식 메뉴
+     */
+    List<SysMenuVO> childList = new ArrayList<SysMenuVO>();
+
+}
 
src/main/java/com/takensoft/cms/menu/web/MenuAuthorController.java (added)
+++ src/main/java/com/takensoft/cms/menu/web/MenuAuthorController.java
@@ -0,0 +1,83 @@
+package com.takensoft.cms.menu.web;
+
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.menu.service.MenuAuthorService;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.07
+ *
+ * 메뉴 권한 정보 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/admin/menuAuthor")
+public class MenuAuthorController {
+    private final MenuAuthorService menuAuthorService;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.02
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 권한 목록 조회
+     */
+    @PostMapping(value = "/findAllByAuthor.json")
+    public ResponseEntity<?> findAllByAuthor(@RequestBody AuthorVO authorVO) throws Exception {
+        List<HashMap<String, Object>> result = menuAuthorService.findAll(authorVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 메뉴 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.02
+     * @param params
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 권한 수정
+     */
+    @PostMapping(value = "/updateMenuAuthrtProc.json")
+    public ResponseEntity<?> updateMenuAuthrtProc(@RequestBody HashMap<String, Object> params) throws Exception {
+        // 메뉴 권한 수정
+        int result = menuAuthorService.updateMenuAuthrtProc(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 메뉴 권한 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("메뉴 권한 수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}
 
src/main/java/com/takensoft/cms/menu/web/MenuController.java (added)
+++ src/main/java/com/takensoft/cms/menu/web/MenuController.java
@@ -0,0 +1,209 @@
+package com.takensoft.cms.menu.web;
+
+import com.takensoft.cms.author.vo.AuthorVO;
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.cms.dept.vo.DeptVO;
+import com.takensoft.cms.menu.service.MenuService;
+import com.takensoft.cms.menu.vo.MenuVO;
+import com.takensoft.common.HierachyVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.01
+ *
+ * 메뉴 정보 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value = "/admin/menu")
+public class MenuController {
+
+    private final MenuService menuService;
+    private final CodeManageService codeManageService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * @param menuVO
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 등록
+     */
+    @PostMapping(value = "/saveProc.json")
+    public ResponseEntity<?> SaveProc(@RequestBody MenuVO menuVO) throws Exception {
+        // 메뉴 등록
+        int result = menuService.menuSave(menuVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 메뉴 등록이 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("메뉴 등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 목록 조회 (관리자 페이지용)
+     */
+    @GetMapping(value = "/findAll.json")
+    public ResponseEntity<?> findAll() throws Exception {
+        // Tree용
+        List<HierachyVO> hierachyList = menuService.findByTopNode();
+
+        // 메뉴타입
+        List<CodeManageVO> codeList = codeManageService.findByChildCdCache("menuGroup");
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("hierachyList", hierachyList);
+        result.put("newMenu", new MenuVO());
+        result.put("codeList", codeList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 메뉴 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * @param menuVO
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 상세 조회 (관리자 페이지용)
+     */
+    @PostMapping("/findByMenu.json")
+    public ResponseEntity<?> findByMenu(@RequestBody MenuVO menuVO) throws Exception {
+        // 메뉴 조회
+        MenuVO result = menuService.findByMenu(menuVO.getMenuId());
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 메뉴 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author takensoft
+     * @since 2024.04.08
+     * @param menuVO
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 정보 수정
+     */
+    @PostMapping(value = "/updateProc.json")
+    public ResponseEntity<?> updateProc(@RequestBody MenuVO menuVO) throws Exception {
+        // 메뉴 등록
+        int result = menuService.MenuUpdate(menuVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 메뉴 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("메뉴 수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.04.29
+     * @param menuVO
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 정보 삭제
+     */
+    @PostMapping(value = "/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody MenuVO menuVO) throws Exception {
+        // 메뉴 삭제
+        int result = menuService.menuDelete(menuVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.10
+     * @param menuList
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 목록 수정
+     */
+    @PostMapping(value = "/updateListProc.json")
+    public ResponseEntity<?> updateListProc(@RequestBody List<HierachyVO> menuList) throws Exception {
+        // 메뉴 목록 수정
+        int result = menuService.updateList(menuList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+}
 
src/main/java/com/takensoft/cms/menu/web/SystemMenuController.java (added)
+++ src/main/java/com/takensoft/cms/menu/web/SystemMenuController.java
@@ -0,0 +1,63 @@
+package com.takensoft.cms.menu.web;
+
+import com.takensoft.cms.menu.service.MenuService;
+import com.takensoft.cms.menu.vo.MenuRequest;
+import com.takensoft.cms.menu.vo.MenuVO;
+import com.takensoft.cms.menu.vo.SysMenuVO;
+import com.takensoft.common.HierachyVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : takensoft
+ * @since   : 2024.04.30
+ *
+ * 메뉴 정보 관련 컨트롤러(사용자단용)
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping(value = "/sys/menu")
+public class SystemMenuController {
+
+    private final MenuService menuService;
+
+    /**
+     * @author takensoft
+     * @since 2024.04.30
+     * @param
+     * @return
+     * @throws Exception
+     *
+     * 메뉴 조회(홈페이지 메뉴 조회용)
+     */
+    @PostMapping(value = "/findByMenu.json")
+    public ResponseEntity<?> findByMenu(@RequestBody MenuRequest menuRequest) throws Exception {
+        List<SysMenuVO> menuList = menuService.findByMenuWithRouter(menuRequest);
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("menuList", menuList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 메뉴 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+}
 
src/main/java/com/takensoft/cms/popup/Schedule/PopupScheduler.java (added)
+++ src/main/java/com/takensoft/cms/popup/Schedule/PopupScheduler.java
@@ -0,0 +1,33 @@
+package com.takensoft.cms.popup.Schedule;
+
+import com.takensoft.cms.popup.dao.PopupDAO;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.23
+ *
+ * 팝업 종료일이 된 팝업 제거를 위한 스케쥴러
+ */
+@Component
+public class PopupScheduler {
+    private final PopupDAO popupDAO;
+
+    public PopupScheduler(PopupDAO popupDAO) {
+        this.popupDAO = popupDAO;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.23
+     *
+     * 매일 자정에 종료일이 지난 팝업 삭제
+     */
+    @Scheduled(cron = "0 0 0 * * *")
+    @Transactional(rollbackFor = Exception.class)
+    public void cleanExpiredPopups() throws Exception {
+        popupDAO.cleanExpiredPopups();
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/popup/dao/PopupDAO.java (added)
+++ src/main/java/com/takensoft/cms/popup/dao/PopupDAO.java
@@ -0,0 +1,80 @@
+package com.takensoft.cms.popup.dao;
+
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.13
+ *
+ * 팝업 관련 Mapper
+ */
+@Mapper("popupDAO")
+public interface PopupDAO {
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 등록
+     */
+    public int insertPopup(PopupVO popupVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 목록 갯수
+     */
+    public int selectPopupListCnt(Pagination pagination) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 목록 조회
+     */
+    public List<PopupVO> selectPopupList(Pagination pagination) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 목록 상세
+     */
+    public PopupVO selectPopupDetail(PopupVO popupVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 수정
+     */
+    public int updatePopup(PopupVO popupVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.22
+     *
+     * 팝업 목록 조회 (팝업창 띄우는 용도)
+     */
+    public List<PopupVO> selectPopupListByPage(String pageType) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.23
+     *
+     * 매일 자정에 종료일이 지난 팝업 삭제
+     */
+    public int cleanExpiredPopups() throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.28
+     *
+     * 팝업 최신 목록 조회 (최신글 5건 출력)
+     */
+    public List<PopupVO> selectPopupListByNew() throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/popup/service/Impl/PopupServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/popup/service/Impl/PopupServiceImpl.java
@@ -0,0 +1,242 @@
+package com.takensoft.cms.popup.service.Impl;
+
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.cms.popup.dao.PopupDAO;
+import com.takensoft.cms.popup.service.PopupService;
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.file.service.FileMngService;
+import com.takensoft.common.file.vo.FileMngVO;
+import com.takensoft.common.idgen.service.IdgenService;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.13
+ *
+ * 팝업 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * PopupService : 팝업 관련 인터페이스 상속
+ */
+@Service("popupService")
+@RequiredArgsConstructor
+public class PopupServiceImpl extends EgovAbstractServiceImpl implements PopupService {
+    private final JWTUtil jwtUtil;
+    private final PopupDAO popupDAO;
+    private final IdgenService popupIdgn;
+    private final FileMngService fileMngService;
+    private final CodeManageService codeManageService;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 등록
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HashMap<String, Object> popupInsert(PopupVO popupVO, List<MultipartFile> multipartFileList) throws Exception {
+        // 투자상담 아이디 생성
+        String popupId = popupIdgn.getNextStringId();
+        popupVO.setPopupId(popupId);
+
+        // 등록자 삽입
+        String writer = jwtUtil.getWriter();
+        popupVO.setRgtr(writer);
+
+        HashMap<String, Object> result = new HashMap<>();
+
+        // 첨부파일 유무
+        if (multipartFileList != null && !multipartFileList.isEmpty()) {
+            FileMngVO fileMngVO = new FileMngVO();
+
+            // 파일매니저 등록
+            HashMap<String, Object> fileMng = fileMngService.fileMngInsert(fileMngVO, multipartFileList);
+            result.put("multipartFileMngResult", fileMng);
+
+            // 파일매니저 아이디 삽입
+            popupVO.setFileMngId(fileMng.get("fileMngId").toString());
+        }
+
+        // 팝업 등록
+        int insertResult = popupDAO.insertPopup(popupVO);
+
+        result.put("insertResult", insertResult);
+        result.put("popupId", popupVO.getPopupId());
+
+        return result;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 목록 조회
+     */
+    @Override
+    public HashMap<String, Object> popupList(HashMap<String, String> params) throws Exception {
+        Pagination search = new Pagination(0, params);
+        int cnt = popupDAO.selectPopupListCnt(search);
+
+        Pagination pagination = new Pagination(cnt, params);
+        List<PopupVO> list = popupDAO.selectPopupList(pagination);
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("list", list);
+        result.put("pagination", pagination);
+        return result;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 상세 조회
+     */
+    @Override
+    public HashMap<String, Object> popupDetail(PopupVO popupVO) throws Exception {
+        PopupVO newPopupVO = new PopupVO();
+        if (popupVO.getPopupId() != null) {
+            newPopupVO = popupDAO.selectPopupDetail(popupVO);
+        }
+
+        // 팝업크기 설정
+        if (newPopupVO.getWdthLen() != 0 && newPopupVO.getVrtcLen() != 0) {
+            if (newPopupVO.getWdthLen() == 300 && newPopupVO.getVrtcLen() == 300) {
+                newPopupVO.setPopupSizeType("fixed");
+                newPopupVO.setPopupSize("PS1");
+            } else if (newPopupVO.getWdthLen() == 500 && newPopupVO.getVrtcLen() == 700) {
+                newPopupVO.setPopupSizeType("fixed");
+                newPopupVO.setPopupSize("PS2");
+            } else if (newPopupVO.getWdthLen() == 700 && newPopupVO.getVrtcLen() == 1000) {
+                newPopupVO.setPopupSizeType("fixed");
+                newPopupVO.setPopupSize("PS3");
+            } else if (newPopupVO.getWdthLen() == 1200 && newPopupVO.getVrtcLen() == 850) {
+                newPopupVO.setPopupSizeType("fixed");
+                newPopupVO.setPopupSize("PS4");
+            } else {
+                newPopupVO.setPopupSizeType("custom");
+            }
+        } else {
+            newPopupVO.setPopupSizeType("fixed");
+            newPopupVO.setPopupSize("PS1");
+        }
+
+        // 업로드 형식 설정
+        if (newPopupVO.getPopupType() == null) {
+            newPopupVO.setPopupType("image");
+        }
+
+        // 팝업 노출 페이지
+        if (newPopupVO.getPageType() == null) {
+            newPopupVO.setPageType("");
+        }
+
+        // 팝업 사용 유무
+        if (newPopupVO.getPopupUseYn() == null) {
+            newPopupVO.setPopupUseYn("Y");
+        }
+
+        // 사용 유무
+        if (newPopupVO.getUseYn() == null) {
+            newPopupVO.setUseYn("Y");
+        }
+
+        List<CodeManageVO> codeList = codeManageService.findByChildCdCache("pageType"); // 검색 조건
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("popupVO", newPopupVO);
+        result.put("codeList", codeList);
+
+        return result;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.14
+     *
+     * 팝업 수정
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int popupUpdate(PopupVO popupVO, List<MultipartFile> multipartFileList) throws Exception {
+        // 수정자 삽입
+        String writer = jwtUtil.getWriter();
+        popupVO.setMdfr(writer);
+
+        // 파일 수정
+        int fileUpdateResult = 0;
+        FileMngVO fileMngVO = new FileMngVO();
+        if (popupVO.getFileMngId() != null) {
+            List<HashMap<String, Object>> deleteFileList = new ArrayList<>();
+            if (popupVO.getDeleteFileList() != null && popupVO.getDeleteFileList().size() > 0) {
+                deleteFileList = popupVO.getDeleteFileList();
+            }
+
+            // 파일매니저 수정
+            fileMngVO.setFileMngId(popupVO.getFileMngId());
+            fileUpdateResult += fileMngService.fileMngUpadate(fileMngVO, deleteFileList, multipartFileList);
+        } else {
+            // 파일매니저 등록
+            if(multipartFileList != null && multipartFileList.size() > 0) {
+                HashMap<String, Object> fileMng = fileMngService.fileMngInsert(fileMngVO, multipartFileList);
+                fileUpdateResult += (int) fileMng.get("fileMngResult");
+                popupVO.setFileMngId(fileMng.get("fileMngId").toString());
+            }
+        }
+
+        // 팝업 수정
+        int updateResult = popupDAO.updatePopup(popupVO);
+
+        return updateResult + fileUpdateResult;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.14
+     *
+     * 팝업 삭제
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int popupDelete(PopupVO popupVO) throws Exception {
+        // 수정자 삽입
+        String writer = jwtUtil.getWriter();
+        popupVO.setMdfr(writer);
+
+        // 파일매니저 삭제
+        int fileDeleteResult = 0;
+        if (popupVO.getFileMngId() != null && popupVO.getFileMngId().equals("")) {
+            HashMap<String, Object> hashMap = new HashMap<>();
+            hashMap.put("fileMngId", popupVO.getFileMngId());
+            fileDeleteResult = fileMngService.fileMngDelete(hashMap);
+        }
+
+        // 팝업 삭제
+        popupVO.setUseYn("N");
+        popupVO.setFileMngId(null);
+        int deleteResult = popupDAO.updatePopup(popupVO);
+
+        return deleteResult + fileDeleteResult;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.22
+     *
+     * 팝업 목록 조회 (팝업창 띄우는 용도)
+     */
+    @Override
+    public List<PopupVO> popupListByPage(String pageType) throws Exception {
+        return popupDAO.selectPopupListByPage(pageType);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/popup/service/PopupService.java (added)
+++ src/main/java/com/takensoft/cms/popup/service/PopupService.java
@@ -0,0 +1,62 @@
+package com.takensoft.cms.popup.service;
+
+import com.takensoft.cms.popup.vo.PopupVO;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.13
+ *
+ * 팝업 관련 인터페이스
+ */
+public interface PopupService {
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 등록
+     */
+    public HashMap<String, Object> popupInsert(PopupVO popupVO, List<MultipartFile> multipartFileList) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 목록 조회
+     */
+    public HashMap<String, Object> popupList(HashMap<String, String> params) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 상세 조회
+     */
+    public HashMap<String, Object> popupDetail(PopupVO popupVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.14
+     *
+     * 팝업 수정
+     */
+    public int popupUpdate(PopupVO popupVO, List<MultipartFile> multipartFileList) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.14
+     *
+     * 팝업 삭제
+     */
+    public int popupDelete(PopupVO popupVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.13
+     *
+     * 팝업 목록 조회 (팝업창 띄우는 용도)
+     */
+    public List<PopupVO> popupListByPage(String pageType) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/popup/vo/PopupVO.java (added)
+++ src/main/java/com/takensoft/cms/popup/vo/PopupVO.java
@@ -0,0 +1,61 @@
+package com.takensoft.cms.popup.vo;
+
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.13
+ *
+ * 팝업 관련 VO
+ */
+@Data
+public class PopupVO {
+    // 팝업아이디
+    private String popupId;
+    // 팝업제목
+    private String popupTtl;
+    // 시작일
+    private String bgngDt;
+    // 종료일
+    private String endDt;
+    // 가로길이    
+    private int wdthLen;
+    // 세로길이
+    private int vrtcLen;
+    // 팝업유형
+    private String popupType;
+    // 팝업사용여부
+    private String popupUseYn;
+    // 동영상URL
+    private String vdoUrl;
+    // 링크 URL
+    private String linkUrl;
+    // 파일 관리 아이디
+    private String fileMngId;
+    // 순서
+    private int sn;
+    // 페이지 타입(팝업노출페이지)
+    private String pageType;
+    // 사용여부
+    private String useYn;
+    // 등록자
+    private String rgtr;
+    // 등록일
+    private String regDt;
+    // 수정자
+    private String mdfr;
+    // 수정일
+    private String mdfcnDt;
+
+    // 팝업사이즈타입
+    private String popupSizeType;
+    // 팝업사이즈
+    private String popupSize;
+    // 등록자명
+    private String mbrNm;
+    // 삭제 파일 목록
+    private List<HashMap<String, Object>> deleteFileList;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/popup/web/PopupController.java (added)
+++ src/main/java/com/takensoft/cms/popup/web/PopupController.java
@@ -0,0 +1,192 @@
+package com.takensoft.cms.popup.web;
+
+import com.takensoft.cms.popup.service.PopupService;
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.common.file.service.FileService;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.13
+ *
+ * 팝업 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/admin/popup")
+public class PopupController {
+    private final PopupService popupService;
+    private final FileService fileService;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.13
+     * @param popupVO
+     * @return
+     * @throws Exception
+     *
+     * 팝업 등록
+     */
+    @PostMapping("/insertProc.file")
+    public ResponseEntity<?> insertProc(@RequestPart PopupVO popupVO, List<MultipartFile> multipartFileList) throws Exception {
+        HashMap<String, Object> result = popupService.popupInsert(popupVO, multipartFileList);
+        int insertResult = (int) result.get("insertResult");
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(insertResult > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            responseData.setData(result);
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.13
+     * @param params
+     * @return
+     * @throws Exception
+     *
+     * 팝업 목록 조회
+     */
+    @PostMapping("/listProc.json")
+    public ResponseEntity<?> listProc(@RequestBody HashMap<String, String> params) throws Exception {
+        HashMap<String, Object> result = popupService.popupList(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.13
+     * @param popupVO
+     * @return
+     * @throws Exception
+     *
+     * 팝업 상세 조회
+     */
+    @PostMapping("/detailProc.json")
+    public ResponseEntity<?> detailProc(@RequestBody PopupVO popupVO) throws Exception {
+        HashMap<String, Object> result = popupService.popupDetail(popupVO);
+        PopupVO popup = (PopupVO) result.get("popupVO");
+
+        List<HashMap<String, Object>> fileList = new ArrayList<>();
+        if (popup.getFileMngId() != null) {
+            fileList = fileService.fileSelectList(popup.getFileMngId());
+        }
+        result.put("fileList", fileList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.14
+     * @param popupVO
+     * @return
+     * @throws Exception
+     *
+     * 팝업 수정
+     */
+    @PostMapping("/updateProc.file")
+    public ResponseEntity<?> updateProc(@RequestPart PopupVO popupVO, @RequestParam(required = false) List<MultipartFile> multipartFileList) throws Exception {
+        int result = popupService.popupUpdate(popupVO, multipartFileList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 수정 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("수정에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.14
+     * @param popupVO
+     * @return
+     * @throws Exception
+     *
+     * 팝업 삭제
+     */
+    @PostMapping("/deleteProc.json")
+    public ResponseEntity<?> deleteProc(@RequestBody PopupVO popupVO) throws Exception {
+        int result = popupService.popupDelete(popupVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 삭제 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("삭제에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.22
+     * @param popupVO
+     * @return
+     * @throws Exception
+     *
+     * 팝업 목록 조회 (팝업창 띄우는 용도)
+     */
+    @PostMapping("/listByPageProc.json")
+    public ResponseEntity<?> listByPageProc(@RequestBody PopupVO popupVO) throws Exception {
+        List<PopupVO> result = popupService.popupListByPage(popupVO.getPageType());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/popup/web/SysPopupController.java (added)
+++ src/main/java/com/takensoft/cms/popup/web/SysPopupController.java
@@ -0,0 +1,87 @@
+package com.takensoft.cms.popup.web;
+
+import com.takensoft.cms.popup.service.PopupService;
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.common.file.service.FileService;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.27
+ *
+ * 팝업 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/sys/popup")
+public class SysPopupController {
+    private final PopupService popupService;
+    private final FileService fileService;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.22
+     * @param popupVO
+     * @return
+     * @throws Exception
+     *
+     * 팝업 목록 조회 (팝업창 띄우는 용도)
+     */
+    @PostMapping("/listByPageProc.json")
+    public ResponseEntity<?> listByPageProc(@RequestBody PopupVO popupVO) throws Exception {
+        List<PopupVO> result = popupService.popupListByPage(popupVO.getPageType());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.13
+     * @param popupVO
+     * @return
+     * @throws Exception
+     *
+     * 팝업 상세 조회
+     */
+    @PostMapping("/detailProc.json")
+    public ResponseEntity<?> detailProc(@RequestBody PopupVO popupVO) throws Exception {
+        HashMap<String, Object> result = popupService.popupDetail(popupVO);
+        PopupVO popup = (PopupVO) result.get("popupVO");
+
+        List<HashMap<String, Object>> fileList = new ArrayList<>();
+        if (popup.getFileMngId() != null) {
+            fileList = fileService.fileSelectList(popup.getFileMngId());
+        }
+        result.put("fileList", fileList);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}
 
src/main/java/com/takensoft/cms/prvcInqHstry/dao/PrvcInqHstryDAO.java (added)
+++ src/main/java/com/takensoft/cms/prvcInqHstry/dao/PrvcInqHstryDAO.java
@@ -0,0 +1,49 @@
+package com.takensoft.cms.prvcInqHstry.dao;
+
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.cms.prvcInqHstry.vo.PrvcInqHstryVO;
+import com.takensoft.common.Pagination;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.22
+ *
+ * 개인정보 조회 이력 관련 Mapper
+ */
+@Mapper("prvcInqHstryDAO")
+public interface PrvcInqHstryDAO {
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.22
+     *
+     * 개인정보 조회 이력 등록
+     */
+    public int insertPrvcInqHstry(PrvcInqHstryVO prvcInqHstryVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.27
+     *
+     * 개인정보 조회 이력 목록 갯수
+     */
+    public int selectPrvcInqHstryListCnt(Pagination pagination) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.27
+     *
+     * 개인정보 조회 이력 목록 조회
+     */
+    public List<PrvcInqHstryVO> selectPrvcInqHstryList(Pagination pagination) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.27
+     *
+     * 개인정보 조회 이력 상세 조회
+     */
+    public PrvcInqHstryVO selectPrvcInqHstryDetail(int inqHstryId) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/prvcInqHstry/service/Impl/PrvcInqHstryServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/prvcInqHstry/service/Impl/PrvcInqHstryServiceImpl.java
@@ -0,0 +1,86 @@
+package com.takensoft.cms.prvcInqHstry.service.Impl;
+
+import com.takensoft.cms.codeManage.service.CodeManageService;
+import com.takensoft.cms.codeManage.vo.CodeManageVO;
+import com.takensoft.cms.popup.vo.PopupVO;
+import com.takensoft.cms.prvcInqHstry.dao.PrvcInqHstryDAO;
+import com.takensoft.cms.prvcInqHstry.service.PrvcInqHstryService;
+import com.takensoft.cms.prvcInqHstry.vo.PrvcInqHstryVO;
+import com.takensoft.common.Pagination;
+import com.takensoft.common.util.CommonUtils;
+import com.takensoft.common.util.JWTUtil;
+import lombok.RequiredArgsConstructor;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.22
+ *
+ * 개인정보 조회 이력 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * PrvcInqHstryService : 팝업 관련 인터페이스 상속
+ */
+@Service("prvcInqHstryService")
+@RequiredArgsConstructor
+public class PrvcInqHstryServiceImpl extends EgovAbstractServiceImpl implements PrvcInqHstryService {
+    private final JWTUtil jwtUtil;
+    private final CommonUtils commonUtils;
+    private final PrvcInqHstryDAO prvcInqHstryDAO;
+    private final CodeManageService codeManageService;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.22
+     *
+     * 개인정보 조회 이력 등록
+     */
+    public int prvcInqHstryInsert(HttpServletRequest request, PrvcInqHstryVO prvcInqHstryVO) throws Exception {
+        // 조회 아이피 삽입
+        String ipAdd = commonUtils.getIp(request);
+        prvcInqHstryVO.setInqIp(ipAdd);
+
+        // 조회자 삽입
+        String writer = jwtUtil.getWriter();
+        prvcInqHstryVO.setRdr(writer);
+
+        return prvcInqHstryDAO.insertPrvcInqHstry(prvcInqHstryVO);
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.27
+     *
+     * 개인정보 조회 이력 목록 조회
+     */
+    @Override
+    public HashMap<String, Object> prvcInqHstryList(HashMap<String, String> params) throws Exception {
+        Pagination search = new Pagination(0, params);
+        int cnt = prvcInqHstryDAO.selectPrvcInqHstryListCnt(search);
+
+        Pagination pagination = new Pagination(cnt, params);
+        List<PrvcInqHstryVO> list = prvcInqHstryDAO.selectPrvcInqHstryList(pagination);
+        List<CodeManageVO> codeList = codeManageService.findByChildCdCache("prvcInqHstry"); // 검색 조건
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("list", list);
+        result.put("pagination", pagination);
+        result.put("codeList", codeList);
+        return result;
+    }
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.27
+     *
+     * 개인정보 조회 이력 상세 조회
+     */
+    @Override
+    public PrvcInqHstryVO prvcInqHstryDetail(int inqHstryId) throws Exception {
+        return prvcInqHstryDAO.selectPrvcInqHstryDetail(inqHstryId);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/prvcInqHstry/service/PrvcInqHstryService.java (added)
+++ src/main/java/com/takensoft/cms/prvcInqHstry/service/PrvcInqHstryService.java
@@ -0,0 +1,38 @@
+package com.takensoft.cms.prvcInqHstry.service;
+
+import com.takensoft.cms.prvcInqHstry.vo.PrvcInqHstryVO;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.22
+ *
+ * 개인정보 조회 이력 관련 인터페이스
+ */
+public interface PrvcInqHstryService {
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.22
+     *
+     * 개인정보 조회 이력 등록
+     */
+    public int prvcInqHstryInsert(HttpServletRequest request, PrvcInqHstryVO prvcInqHstryVO) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.27
+     *
+     * 개인정보 조회 이력 목록 조회
+     */
+    public HashMap<String, Object> prvcInqHstryList(HashMap<String, String> params) throws Exception;
+
+    /**
+     * @author  : 박정하
+     * @since   : 2024.05.27
+     *
+     * 개인정보 조회 이력 상세 조회
+     */
+    public PrvcInqHstryVO prvcInqHstryDetail(int inqHstryId) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/prvcInqHstry/vo/PrvcInqHstryVO.java (added)
+++ src/main/java/com/takensoft/cms/prvcInqHstry/vo/PrvcInqHstryVO.java
@@ -0,0 +1,29 @@
+package com.takensoft.cms.prvcInqHstry.vo;
+
+import lombok.Data;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.22
+ *
+ * 개인정보 조회 이력 관련 VO
+ */
+@Data
+public class PrvcInqHstryVO {
+    // 조회 이력 아이디
+    private int inqHstryId;
+    // 조회 대상자 아이디
+    private String inqTrprId;
+    // 조회 사유
+    private String inqRsn;
+    // 조회 아이피
+    private String inqIp;
+    // 조회자
+    private String rdr;
+    // 조회일
+    private String inqDt;
+    // 조회자 이름
+    private String mbrNm;
+    // 조회 대상자 로그인 아이디
+    private String lgnId;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/prvcInqHstry/web/PrvcInqHstryController.java (added)
+++ src/main/java/com/takensoft/cms/prvcInqHstry/web/PrvcInqHstryController.java
@@ -0,0 +1,102 @@
+package com.takensoft.cms.prvcInqHstry.web;
+
+import com.takensoft.cms.prvcInqHstry.service.PrvcInqHstryService;
+import com.takensoft.cms.prvcInqHstry.vo.PrvcInqHstryVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.Charset;
+import java.util.*;
+
+/**
+ * @author  : 박정하
+ * @since   : 2024.05.22
+ *
+ * 개인정보 조회 이력 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/admin/prvcInqHstry")
+public class PrvcInqHstryController {
+    private final PrvcInqHstryService prvcInqHstryService;
+
+    /**
+     * @author 박정하
+     * @since 2024.05.22
+     * @param prvcInqHstryVO
+     * @return
+     * @throws Exception
+     *
+     * 개인정보 조회 이력 등록
+     */
+    @PostMapping("/insertProc.json")
+    public ResponseEntity<?> insertProc(HttpServletRequest request, @RequestBody PrvcInqHstryVO prvcInqHstryVO) throws Exception {
+        int result = prvcInqHstryService.prvcInqHstryInsert(request, prvcInqHstryVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        if(result > 0) {
+            responseData.setStatus(HttpStatus.OK);
+            responseData.setMessage("정상적으로 등록 처리되었습니다.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+        } else {
+            responseData.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
+            responseData.setMessage("등록에 실패하였습니다.\n담당자에게 문의하세요.");
+            return new ResponseEntity<>(responseData, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.27
+     * @param params
+     * @return
+     * @throws Exception
+     *
+     * 개인정보 조회 이력 목록 조회
+     */
+    @PostMapping("/listProc.json")
+    public ResponseEntity<?> listProc(@RequestBody HashMap<String, String> params) throws Exception {
+        HashMap<String, Object> result = prvcInqHstryService.prvcInqHstryList(params);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.05.27
+     * @param prvcInqHstryVO
+     * @return
+     * @throws Exception
+     *
+     * 개인정보 조회 이력 상세 조회
+     */
+    @PostMapping("/detailProc.json")
+    public ResponseEntity<?> listProc(@RequestBody PrvcInqHstryVO prvcInqHstryVO) throws Exception {
+        PrvcInqHstryVO result = prvcInqHstryService.prvcInqHstryDetail(prvcInqHstryVO.getInqHstryId());
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/search/dao/SearchDAO.java (added)
+++ src/main/java/com/takensoft/cms/search/dao/SearchDAO.java
@@ -0,0 +1,92 @@
+package com.takensoft.cms.search.dao;
+
+import com.takensoft.cms.search.vo.SearchContentVO;
+import com.takensoft.cms.search.vo.SearchVO;
+import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.06.12
+ *
+ * 통합 검색 관련 Mapper
+ */
+@Mapper("searchDAO")
+public interface SearchDAO {
+    /**
+     * @author  하석형
+     * @since   2024.06.12
+     * 게시판 검색 목록 조회 개수
+     */
+    public int findAllCountByBbs(SearchVO searchVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.06.12
+     * 게시판 검색 목록 조회
+     */
+    public List<SearchContentVO> findAllByBbs(SearchVO searchVO) throws Exception;
+
+
+
+
+    /** ********************************* 컨텐츠 검색 - 기업 정보 (시작) ********************************* */
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 기업 정보 검색 목록 조회 개수
+     */
+    public int findAllCountByEntInfo(SearchVO searchVO) throws Exception;
+    
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 기업 정보 검색 목록 조회
+     */
+    public List<HashMap<String, Object>> findAllByEntInfo(SearchVO searchVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 기업 상담 신청 검색 목록 조회 개수
+     */
+    public int findAllCountByEntDscsnAply(SearchVO searchVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 기업 상담 신청 검색 목록 조회
+     */
+    public List<HashMap<String, Object>> findAllByEntDscsnAply(SearchVO searchVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 투자 상담 검색 목록 조회 개수
+     */
+    public int findAllCountByIvstDscsn(SearchVO searchVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 투자 상담 검색 목록 조회
+     */
+    public List<HashMap<String, Object>> findAllByIvstDscsn(SearchVO searchVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 검토 사항 검색 목록 조회 개수
+     */
+    public int findAllCountByRvwMttr(SearchVO searchVO) throws Exception;
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 검토 사항 검색 목록 조회
+     */
+    public List<HashMap<String, Object>> findAllByRvwMttr(SearchVO searchVO) throws Exception;
+    /** ********************************* 컨텐츠 검색 - 기업 정보 (종료) ********************************* */
+}
 
src/main/java/com/takensoft/cms/search/service/Impl/SearchServiceImpl.java (added)
+++ src/main/java/com/takensoft/cms/search/service/Impl/SearchServiceImpl.java
@@ -0,0 +1,316 @@
+package com.takensoft.cms.search.service.Impl;
+
+import com.takensoft.cms.menu.service.MenuService;
+import com.takensoft.cms.menu.vo.MenuRequest;
+import com.takensoft.cms.menu.vo.SysMenuVO;
+import com.takensoft.cms.search.dao.SearchDAO;
+import com.takensoft.cms.search.service.SearchService;
+import com.takensoft.cms.search.vo.SearchContentVO;
+import com.takensoft.cms.search.vo.SearchMenuVO;
+import com.takensoft.cms.search.vo.SearchResultVO;
+import com.takensoft.cms.search.vo.SearchVO;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.06.12
+ *
+ * 통합 검색 관련 구현체
+ * EgovAbstractServiceImpl : 전자정부 상속
+ * SearchService : 통합 검색 인터페이스 상속
+ */
+@Service("searchService")
+@RequiredArgsConstructor
+public class SearchServiceImpl extends EgovAbstractServiceImpl implements SearchService {
+
+    private final MenuService menuService;
+    private final SearchDAO searchDAO;
+
+    /**
+     * @author  하석형
+     * @since   2024.06.12
+     * 통합 검색
+     */
+    public SearchResultVO searchAll (SearchVO searchVO) throws Exception {
+        SearchResultVO searchResultVO = new SearchResultVO();
+
+        /* 메뉴 목록 */
+        MenuRequest mReq = new MenuRequest();
+        mReq.setMenuType(searchVO.getMenuType()); // 메뉴타입: "government"
+        mReq.setRoles(searchVO.getRoles()); // 로그인 사용자 권한: "ROLE_ADMIN" / "ROLE_USER"
+        SysMenuVO topMenu = new SysMenuVO();
+        List<SysMenuVO> menuList = menuService.findByMenuWithRouter(mReq);
+        topMenu.setChildList(menuList);
+
+        //TODO: 메뉴명 검색
+
+        /* 검색 */
+        this.searchMenu(topMenu, searchVO, searchResultVO);
+
+        return searchResultVO;
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.06.12
+     * 검색 함수
+     */
+    public void searchMenu (SysMenuVO sysMenu, SearchVO searchVO, SearchResultVO searchResultVO) throws Exception {
+        List<SysMenuVO> menuList = sysMenu.getChildList();
+        for(SysMenuVO menu : menuList) {
+            SearchMenuVO searchMenu = new SearchMenuVO(); // 검색 메뉴 정보
+            searchMenu.setMenuId(menu.getMenuId());
+            searchMenu.setRouterUrl(menu.getRouterUrl());
+
+            // 전체 메뉴명 생성
+            String fullMenuNm = "";
+            if(sysMenu.getMenuNm() != null && !sysMenu.getMenuNm().isEmpty()) {
+                fullMenuNm =  sysMenu.getMenuNm() + " > ";
+            }
+            fullMenuNm = fullMenuNm + menu.getMenuNm();
+            searchMenu.setFullMenuNm(fullMenuNm);
+
+            // 자식 메뉴 존재 시 재귀 처리
+            if (!menu.getChildList().isEmpty()) {
+                menu.setMenuNm(fullMenuNm); // 자식 메뉴에 사용할 이전 전체 메뉴명
+                this.searchMenu(menu, searchVO, searchResultVO);
+            } else {
+                // 메뉴 타입이 있을 시
+                if (menu.getMenuType() != null && !menu.getMenuType().isEmpty()) {
+                    String menuType = menu.getMenuType(); // bbs: 게시판, conts: 컨텐츠
+                    // 메뉴 URL이 있을 시
+//                    if(menu.getRouterUrl() != null && !menu.getRouterUrl().isEmpty()) {
+//                        String routerUrl = menu.getRouterUrl(); // 메뉴 URL
+//                        if (routerUrl.contains(".page")) {
+//                            int lastSlashIndex = routerUrl.lastIndexOf('/'); // 마지막 '/' 인덱스
+//                            String path = routerUrl.substring(0, lastSlashIndex); // 마지막 '/' 이전 경로
+//                        }
+//                    }
+
+                    /* 게시판 검색 */
+                    if (menuType.equals("bbs")) {
+                        // 타입이 게시판일 시 게시판 내용 테이블에서 조회
+                        String bbsMngId = menu.getMenuTypeCtgry(); // 게시판 관리 ID
+                        searchVO.setBbsMngId(bbsMngId);
+
+                        //TODO: (사용중)방법1.전체 개수 구하는 SQL, 미리보기 개수만큼 목록을 조회하는 SQL
+                        //TODO: 방법2.전체 목록을 검색해서 개수를 구한 뒤, 미리보기 개수만큼 for문 사용해 목록 상단에서부터 따로 담기
+
+                        // 전체 검색 목록 개수
+                        int totalListCount = searchDAO.findAllCountByBbs(searchVO);
+                        searchResultVO.setPageCount(searchResultVO.getPageCount() + totalListCount); // 페이지 개수
+                        searchResultVO.setBoardCount(searchResultVO.getBoardCount() + totalListCount); // 게시판 개수
+                        searchMenu.setTotalListCount(totalListCount);
+
+                        // 미리보기 검색 게시판 목록
+                        List<SearchContentVO> bbsList = searchDAO.findAllByBbs(searchVO);
+                        for(SearchContentVO bbs : bbsList) {
+                            bbs.setContent(this.stripHtmlTags(bbs.getContent())); // HTML 태그 제거
+                        }
+                        if (!bbsList.isEmpty()) {
+                            searchMenu.setPreviewList(bbsList); // 미리보기 목록 추가
+                            searchResultVO.getPageList().add(searchMenu); // 페이지 목록에 추가
+                            searchResultVO.getBoardList().add(searchMenu); // 게시판 목록에 추가
+                        }
+                    }
+                    /* 컨텐츠 검색 */
+                    else if (menuType.equals("conts")) {
+                        // 타입이 콘텐츠일 시 하드코딩으로 검색 조회
+                        String contsId = menu.getMenuTypeCtgry(); // 컨텐츠 ID
+                        List<SearchContentVO> contentList = new ArrayList<>();
+
+                        // 기업 정보 검색
+                        if(contsId.equals("CONTS_000000000000030")) {
+                            this.searchEntInfo(searchVO, contentList, searchMenu, searchResultVO);
+                        }
+                        // 기업 상담 신청 검색
+                        else if(contsId.equals("CONTS_000000000000035")){
+                            this.searchEntDscsnAply(searchVO, contentList, searchMenu, searchResultVO);
+                        }
+                        // 투자 상담 검색
+                        else if(contsId.equals("CONTS_000000000000040")){
+                            this.searchIvstDscsn(searchVO, contentList, searchMenu, searchResultVO);
+                        }
+                        // 검토 사항 검색
+                        else if(contsId.equals("CONTS_000000000000037")){
+                            this.searchRvwMttr(searchVO, contentList, searchMenu, searchResultVO);
+                        }
+
+                        if (!contentList.isEmpty()) {
+                            searchMenu.setPreviewList(contentList); // 미리보기 목록 추가
+                            searchResultVO.getPageList().add(searchMenu); // 페이지 목록에 추가
+                            searchResultVO.getContentList().add(searchMenu); // 컨텐츠 목록에 추가
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.06.13
+     * HTML 태그 제거
+     */
+    public String stripHtmlTags(String html) {
+        if (html == null || html.isEmpty()) {
+            return html;
+        }
+        // HTML 태그 제거
+        String noTags = html.replaceAll("<[^>]*>", "");
+        // HTML 엔티티 디코딩
+        return StringEscapeUtils.unescapeHtml4(noTags);
+    }
+
+
+
+    /** ********************************* 컨텐츠 검색 - 기업 정보 (시작) ********************************* */
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 기업 정보 검색
+     */
+    public void searchEntInfo (SearchVO searchVO, List<SearchContentVO> contentList, SearchMenuVO searchMenu, SearchResultVO searchResultVO) throws Exception {
+        // 전체 검색 목록 개수
+        int totalListCount = searchDAO.findAllCountByEntInfo(searchVO);
+        this.searchListCount(totalListCount, searchMenu, searchResultVO);
+
+        // 미리보기 검색 컨텐츠 목록
+        List<HashMap<String, Object>> contsLists = searchDAO.findAllByEntInfo(searchVO);
+        for(HashMap<String, Object> conts : contsLists) {
+            String entNm = conts.get("ent_nm").toString(); // 기업명
+            String rprsvNm = conts.get("rprsv_nm").toString(); // 대표자명
+//                                String clsbizYn = ""; // 기업상태
+//                                if(conts.get("clsbiz_yn").equals("Y")) {
+//                                    clsbizYn = "폐업";
+//                                } else if(conts.get("clsbiz_yn").equals("N")) {
+//                                    clsbizYn = "정상";
+//                                } else {
+//                                    clsbizYn = "-";
+//                                }
+//                                conts.get("ivst_dscsn_inten"); // (보류)입주의향
+            String rmrk = Optional.ofNullable(conts.get("rmrk")).map(Object::toString).orElse(""); // 비고
+            String regDt = conts.get("reg_dt").toString(); // 등록일
+            String pageId = conts.get("page_id").toString(); // 페이지 ID
+
+            String makeTitle = String.format("[기업명: %s] [대표자: %s]", entNm, rprsvNm); // 제목
+            String makeContent =  rmrk; // 내용
+
+            // 검색 결과 형태로 변환
+            this.convertToSearchContent(contentList, makeTitle, makeContent, regDt, pageId);
+        }
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 기업 상담 신청 검색
+     */
+    public void searchEntDscsnAply (SearchVO searchVO, List<SearchContentVO> contentList, SearchMenuVO searchMenu, SearchResultVO searchResultVO) throws Exception {
+        // 전체 검색 목록 개수
+        int totalListCount = searchDAO.findAllCountByEntDscsnAply(searchVO);
+        this.searchListCount(totalListCount, searchMenu, searchResultVO);
+
+        // 미리보기 검색 컨텐츠 목록
+        List<HashMap<String, Object>> contsLists = searchDAO.findAllByEntDscsnAply(searchVO);
+        for(HashMap<String, Object> conts : contsLists) {
+            String entNm = conts.get("ent_nm").toString(); // 기업명
+            String prcsStts = conts.get("prcs_stts").toString(); // 진행상태
+            String rmrk = Optional.ofNullable(conts.get("rmrk")).map(Object::toString).orElse(""); // 비고
+            String regDt = conts.get("reg_dt").toString(); // 등록일
+            String pageId = conts.get("page_id").toString(); // 페이지 ID
+
+            String makeTitle = String.format("(%s)[기업명: %s]", prcsStts, entNm); // 제목
+            String makeContent =  rmrk; // 내용
+
+            // 검색 결과 형태로 변환
+            this.convertToSearchContent(contentList, makeTitle, makeContent, regDt, pageId);
+        }
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 투자 상담 검색
+     */
+    public void searchIvstDscsn (SearchVO searchVO, List<SearchContentVO> contentList, SearchMenuVO searchMenu, SearchResultVO searchResultVO) throws Exception {
+        // 전체 검색 목록 개수
+        int totalListCount = searchDAO.findAllCountByIvstDscsn(searchVO);
+        this.searchListCount(totalListCount, searchMenu, searchResultVO);
+
+        // 미리보기 검색 컨텐츠 목록
+        List<HashMap<String, Object>> contsLists = searchDAO.findAllByIvstDscsn(searchVO);
+        for(HashMap<String, Object> conts : contsLists) {
+            String entNm = conts.get("ent_nm").toString(); // 기업명
+            String ttl = conts.get("ttl").toString(); // 제목
+            String mainCn = Optional.ofNullable(conts.get("main_cn")).map(Object::toString).orElse(""); // 주요내용
+            String regDt = conts.get("reg_dt").toString(); // 등록일
+            String pageId = conts.get("page_id").toString(); // 페이지 ID
+
+            String makeTitle = String.format("[기업명: %s] - %s", entNm, ttl); // 제목
+            String makeContent =  mainCn; // 내용
+
+            // 검색 결과 형태로 변환
+            this.convertToSearchContent(contentList, makeTitle, makeContent, regDt, pageId);
+        }
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 검토 사항 검색
+     */
+    public void searchRvwMttr (SearchVO searchVO, List<SearchContentVO> contentList, SearchMenuVO searchMenu, SearchResultVO searchResultVO) throws Exception {
+        // 전체 검색 목록 개수
+        int totalListCount = searchDAO.findAllCountByRvwMttr(searchVO);
+        this.searchListCount(totalListCount, searchMenu, searchResultVO);
+
+        // 미리보기 검색 컨텐츠 목록
+        List<HashMap<String, Object>> contsLists = searchDAO.findAllByRvwMttr(searchVO);
+        for(HashMap<String, Object> conts : contsLists) {
+            String entNm = conts.get("ent_nm").toString(); // 기업명
+            String ttl = conts.get("ttl").toString(); // 투자상담명
+            String type = conts.get("type").toString(); // 유형
+            String mainCn = Optional.ofNullable(conts.get("rcpt_cn")).map(Object::toString).orElse(""); // 접수내용
+            String regDt = conts.get("reg_dt").toString(); // 등록일
+            String pageId = conts.get("page_id").toString(); // 페이지 ID
+
+            String makeTitle = String.format("(%s)[기업명: %s] - %s", type, entNm, ttl); // 제목
+            String makeContent =  mainCn; // 내용
+
+            // 검색 결과 형태로 변환
+            this.convertToSearchContent(contentList, makeTitle, makeContent, regDt, pageId);
+        }
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 전체 검색 목록 조회 개수
+     */
+    public void searchListCount (int totalListCount, SearchMenuVO searchMenu, SearchResultVO searchResultVO) throws Exception {
+        searchResultVO.setPageCount(searchResultVO.getPageCount() + totalListCount); // 페이지 개수
+        searchResultVO.setContentCount(searchResultVO.getContentCount() + totalListCount); // 게시판 개수
+        searchMenu.setTotalListCount(totalListCount);
+    }
+
+    /**
+     * @author  하석형
+     * @since   2024.06.14
+     * 컨텐츠를 검색 결과 형태로 변환
+     */
+    public void convertToSearchContent (List<SearchContentVO> contentList, String title, String content, String regDt, String pageId) throws Exception {
+        SearchContentVO searchContentVO = new SearchContentVO();
+        searchContentVO.setTitle(title);
+        searchContentVO.setContent(content);
+        searchContentVO.setRegDt(regDt);
+        searchContentVO.setPageId(pageId);
+        contentList.add(searchContentVO);
+    }
+    /** ********************************* 컨텐츠 검색 - 기업 정보 (종료) ********************************* */
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/search/service/SearchService.java (added)
+++ src/main/java/com/takensoft/cms/search/service/SearchService.java
@@ -0,0 +1,24 @@
+package com.takensoft.cms.search.service;
+
+import com.takensoft.cms.search.vo.SearchResultVO;
+import com.takensoft.cms.search.vo.SearchVO;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.06.12
+ *
+ * 통합 검색 관련 인터페이스
+ */
+public interface SearchService {
+    /**
+     * @author  하석형
+     * @since   2024.06.12
+     * 통합 검색
+     */
+    public SearchResultVO searchAll (SearchVO searchVO) throws Exception;
+
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/cms/search/vo/SearchContentVO.java (added)
+++ src/main/java/com/takensoft/cms/search/vo/SearchContentVO.java
@@ -0,0 +1,39 @@
+package com.takensoft.cms.search.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.06.12
+ *
+ * 통합 검색 내용 관련 VO
+ */
+@Getter
+@Setter
+public class SearchContentVO {
+    /**
+     * 제목
+     */
+    private String title;
+    /**
+     * 내용
+     */
+    private String content;
+    /**
+     * 작성일
+     */
+    private String regDt;
+    /**
+     * 페이지 아이디
+     */
+    private String pageId;
+    /**
+     * (미사용)url
+     */
+    private String url;
+    /**
+     * (미사용)첨부파일 ID
+     */
+    private String fileMngId;
+}
 
src/main/java/com/takensoft/cms/search/vo/SearchMenuVO.java (added)
+++ src/main/java/com/takensoft/cms/search/vo/SearchMenuVO.java
@@ -0,0 +1,42 @@
+package com.takensoft.cms.search.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.06.12
+ *
+ * 통합 검색 메뉴 관련 VO
+ */
+@Getter
+@Setter
+public class SearchMenuVO {
+    /**
+     * 상위 메뉴 아이디
+     */
+    private String upMenuId;
+    /**
+     * 메뉴 아이디
+     */
+    private String menuId;
+    /**
+     * 전체 메뉴 명 (상위메뉴명 + 메뉴명)
+     */
+    private String fullMenuNm;
+    /**
+     * 라우터 경로
+     */
+    private String routerUrl;
+    /**
+     * 전체 목록 개수
+     */
+    private int totalListCount;
+    /**
+     * 미리보기 목록
+     */
+    private List<SearchContentVO> previewList = new ArrayList<>();
+}
 
src/main/java/com/takensoft/cms/search/vo/SearchResultVO.java (added)
+++ src/main/java/com/takensoft/cms/search/vo/SearchResultVO.java
@@ -0,0 +1,66 @@
+package com.takensoft.cms.search.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.06.12
+ *
+ * 통합 검색 결과 관련 VO
+ */
+@Getter
+@Setter
+public class SearchResultVO {
+    /**
+     * (미사용)메뉴 개수
+     */
+    private int menuCount;
+    /**
+     * (미사용)미리보기 메뉴 목록
+     */
+    private List<SearchContentVO> menuList = new ArrayList<>();
+    /**
+     * 페이지 개수 (컨텐츠 + 게시판)
+     */
+    private int pageCount;
+    /**
+     * 페이지 목록
+     */
+    private List<SearchMenuVO> pageList = new ArrayList<>();
+    /**
+     * 컨텐츠 개수
+     */
+    private int contentCount;
+    /**
+     * 컨텐츠 목록
+     */
+    private List<SearchMenuVO> contentList = new ArrayList<>();
+    /**
+     * 게시판 개수
+     */
+    private int boardCount;
+    /**
+     * 게시판 목록
+     */
+    private List<SearchMenuVO> boardList = new ArrayList<>();
+    /**
+     * (미사용)첨부파일 개수
+     */
+    private int fileCount;
+    /**
+     * (미사용)첨부파일 목록
+     */
+    private List<SearchMenuVO> fileList = new ArrayList<>();
+
+    public SearchResultVO () {
+        this.menuCount = 0;
+        this.pageCount = 0;
+        this.contentCount = 0;
+        this.boardCount = 0;
+        this.fileCount = 0;
+    }
+}
 
src/main/java/com/takensoft/cms/search/vo/SearchVO.java (added)
+++ src/main/java/com/takensoft/cms/search/vo/SearchVO.java
@@ -0,0 +1,64 @@
+package com.takensoft.cms.search.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.06.12
+ *
+ * 통합 검색 관련 VO
+ */
+@Getter
+@Setter
+public class SearchVO {
+    /**
+     * 검색어
+     */
+    private String searchText;
+    /**
+     * (미사용)검색 조건
+     * title : 제목, content : 내용
+     */
+    private String searchType;
+    /**
+     * (미사용)검색 정렬
+     * L : 최신순, A : 정확도
+     */
+    private String sort;
+    /**
+     * (미사용)검색 시작일
+     */
+    private String startDt;
+    /**
+     * (미사용)검색 종료일
+     */
+    private String endDt;
+    /**
+     * 카테고리별 미리보기 개수
+     */
+    private int typePreCnt;
+    /**
+     * 사용자 Id
+     */
+    private String mbrId;
+    /**
+     * 사용자 권한정보
+     */
+    private List<String> roles;
+    /**
+     * 메뉴 종류
+     */
+    private String menuType;
+    /**
+     * 게시판 관리 ID (게시판 검색 전용)
+     */
+    private String bbsMngId;
+
+//    public SearchVO() {
+//        this.typePreCnt = 5;
+//    }
+}
 
src/main/java/com/takensoft/cms/search/web/SearchController.java (added)
+++ src/main/java/com/takensoft/cms/search/web/SearchController.java
@@ -0,0 +1,53 @@
+package com.takensoft.cms.search.web;
+
+import com.takensoft.cms.search.service.SearchService;
+import com.takensoft.cms.search.vo.SearchResultVO;
+import com.takensoft.cms.search.vo.SearchVO;
+import com.takensoft.common.util.ResponseData;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.nio.charset.Charset;
+
+/**
+ * @author  : 하석형
+ * @since   : 2024.06.12
+ *
+ * 통합 검색 관련 컨트롤러
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping("/sys/search")
+public class SearchController {
+
+    private final SearchService searchService;
+
+    /**
+     * @author 하석형
+     * @since  2024.06.11
+     * @param  searchVO
+     * @return
+     * @throws Exception
+     *
+     * 통합 검색
+     */
+    @PostMapping("/totalSearch.json")
+    public ResponseEntity<?> totalSearch(@RequestBody SearchVO searchVO) throws Exception {
+        SearchResultVO result = searchService.searchAll(searchVO);
+
+        // 응답 처리
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));
+        ResponseData responseData = new ResponseData();
+        responseData.setStatus(HttpStatus.OK);
+        responseData.setMessage("정상적으로 조회가 처리되었습니다.");
+        responseData.setData(result);
+        return new ResponseEntity<>(responseData, headers, HttpStatus.OK);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/HierachyVO.java (added)
+++ src/main/java/com/takensoft/common/HierachyVO.java
@@ -0,0 +1,43 @@
+package com.takensoft.common;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class HierachyVO {
+
+    /**
+     * 공통으로 사용될 아이디
+     */
+    private String id;
+    /**
+     * 공통으로 사용될 상위 아이디
+     */
+    private String upId;
+    /**
+     * 공통으로 사용될 이름
+     */
+    private String nm;
+    /**
+     * 공통으로 사용될 깊이(레벨)
+     */
+    private int grd;
+    /**
+     * 공통으로 사용될 순서
+     */
+    private int sn;
+
+    /**
+     * 공통으로 사용될 자식 객체
+     */
+    List<HierachyVO> childList = new ArrayList<HierachyVO>();
+
+}
 
src/main/java/com/takensoft/common/Pagination.java (added)
+++ src/main/java/com/takensoft/common/Pagination.java
@@ -0,0 +1,91 @@
+package com.takensoft.common;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Getter
+@Setter
+public class Pagination {
+    private int currentPage = 1;    // 현재 페이지
+    private int recordSize = 10;    // 한 페이지에 표시할 데이터 개수
+    private int pageSize = 10;      // 하단에 표시할 페이지 번호 개수
+
+    private int totalRecordCount;   // 전체 데이터 개수
+    private int totalPageCount;     // 전체 페이지 개수
+    private int startPage;          // 첫 페이지 번호
+    private int endPage;            // 끝 페이지 번호
+    private int limitStart;         // LIMIT 시작 위치
+    private boolean existPrevPage;  // 이전 페이지 존재 여부
+    private boolean existNextPage;  // 다음 페이지 존재 여부
+    
+    private String searchType;      // 검색조건
+    private String searchText;      // 검색어
+
+    private String startDt;         // 시작일
+    private String endDt;           // 종료일
+
+    private String id;              // 게시판 아이디 (게시판 내용 목록 조회 조건시 사용)
+
+    private String cateId;          // 상세 분류 아이디
+    private String cateValue;       // 상세 분류 내용
+
+    private String mvnInten;        // 입주의향 (기업정보 전용)
+    private String mouInten;        // MOU의향 (기업정보 전용)
+
+    private String type;            // 형태 (검토사항 전용)
+    private String prgrsCrs;        // 진행단계 (검토사항 전용)
+    
+    private String mbrId;           // 멤버 Id (권한 확인 용도)
+    private String isAdmin;        // 멤버 권한 관리자 여부 (권한 확인 용도)
+
+    public Pagination(int totalRecordCount, Map<String, String> params) {
+        this.currentPage = Integer.parseInt(params.getOrDefault("currentPage", "1"));
+        this.recordSize = Integer.parseInt(params.getOrDefault("recordSize", "1"));
+        this.pageSize = Integer.parseInt(params.getOrDefault("pageSize", "10"));
+        this.searchType = (String)params.get("searchType");
+        this.searchText = (String)params.get("searchText");
+        this.startDt = (String)params.get("startDt");
+        this.endDt = (String)params.get("endDt");
+        this.id = (String)params.get("id");
+        this.cateId = (String)params.get("cateId");
+        this.cateValue = (String)params.get("cateValue");
+        this.mvnInten = (String)params.get("mvnInten");
+        this.mouInten = (String)params.get("mouInten");
+        this.type = (String)params.get("type");
+        this.prgrsCrs = (String)params.get("prgrsCrs");
+        this.mbrId = (String)params.get("mbrId");
+        this.isAdmin = (String)params.get("isAdmin");
+
+        if (totalRecordCount > 0) {
+            // 전체 데이터 개수
+            this.totalRecordCount = totalRecordCount;
+
+            // 전체 페이지 개수
+            this.totalPageCount = ((this.totalRecordCount - 1) / this.recordSize) + 1;
+            if (this.currentPage > this.totalPageCount) {
+                this.currentPage = this.totalPageCount;
+            }
+
+            // 첫 페이지 번호
+            this.startPage = ((this.currentPage - 1) / this.pageSize) * this.pageSize + 1;
+
+            // 끝 페이지 번호
+            this.endPage = this.startPage + this.pageSize - 1;
+            if (this.endPage > this.totalPageCount) {
+                this.endPage = this.totalPageCount;
+            }
+
+            // LIMIT 시작 위치
+            this.limitStart = (this.currentPage - 1) * this.recordSize;
+
+            // 이전 페이지 존재 여부
+            this.existPrevPage = this.startPage != 1;
+
+            // 다음 페이지 존재 여부
+            this.existNextPage = (this.endPage * this.recordSize) < this.totalRecordCount;
+        }
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/config/CacheConfig.java (added)
+++ src/main/java/com/takensoft/common/config/CacheConfig.java
@@ -0,0 +1,10 @@
+package com.takensoft.common.config;
+
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableCaching
+public class CacheConfig {
+
+}
 
src/main/java/com/takensoft/common/config/CmsDataSourceConfig.java (added)
+++ src/main/java/com/takensoft/common/config/CmsDataSourceConfig.java
@@ -0,0 +1,63 @@
+package com.takensoft.common.config;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages="com.takensoft.*.*.dao, com.takensoft.*.*.*.dao", sqlSessionFactoryRef = "cmsSqlSessionFactory")
+public class CmsDataSourceConfig {
+
+    @Primary
+    @Bean(name = "cmsDataSource")
+    @ConfigurationProperties(prefix = "spring.cms.datasource")
+    public DataSource cmsDataSource() {
+        return DataSourceBuilder.create().build();
+    }
+
+    @Primary
+    @Bean(name = "cmsSqlSessionFactory")
+    public SqlSessionFactory cmsSqlSessionFactory(@Qualifier("cmsDataSource") DataSource cmsDataSource,
+                                                  ApplicationContext applicationContext) throws Exception {
+        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
+        sqlSessionFactoryBean.setDataSource(cmsDataSource);
+        sqlSessionFactoryBean.setTypeAliasesPackage("com.takensoft.**.**.vo, com.takensoft.**.**.dto, com.takensoft.common");
+        sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mybatis/mapper/**/*-SQL.xml"));
+
+        // MyBatis Configuration 설정 추가
+        org.apache.ibatis.session.Configuration myBatisConfig = new org.apache.ibatis.session.Configuration();
+        myBatisConfig.setCacheEnabled(true);
+        myBatisConfig.setLazyLoadingEnabled(false);
+        myBatisConfig.setMultipleResultSetsEnabled(true);
+        myBatisConfig.setUseColumnLabel(true);
+        myBatisConfig.setUseGeneratedKeys(false);
+        myBatisConfig.setDefaultExecutorType(org.apache.ibatis.session.ExecutorType.SIMPLE);
+        myBatisConfig.setDefaultStatementTimeout(25000);
+        myBatisConfig.setCallSettersOnNulls(true);
+        myBatisConfig.setMapUnderscoreToCamelCase(true);
+
+        sqlSessionFactoryBean.setConfiguration(myBatisConfig);
+
+        return sqlSessionFactoryBean.getObject();
+    }
+
+    @Primary
+    @Bean(name = "firstSessionTemplate")
+    public SqlSessionTemplate firstSqlSessionTemplate(@Qualifier("cmsSqlSessionFactory") SqlSessionFactory cmsSqlSessionFactory) {
+        return new SqlSessionTemplate(cmsSqlSessionFactory);
+    }
+}
+
+
+
+
 
src/main/java/com/takensoft/common/config/CommonConfig.java (added)
+++ src/main/java/com/takensoft/common/config/CommonConfig.java
@@ -0,0 +1,69 @@
+package com.takensoft.common.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.egovframe.rte.fdl.cmmn.trace.LeaveaTrace;
+import org.egovframe.rte.fdl.cmmn.trace.handler.DefaultTraceHandler;
+import org.egovframe.rte.fdl.cmmn.trace.handler.TraceHandler;
+import org.egovframe.rte.fdl.cmmn.trace.manager.DefaultTraceHandleManager;
+import org.egovframe.rte.fdl.cmmn.trace.manager.TraceHandlerService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
+
+@Configuration
+public class CommonConfig {
+
+    @Bean(name="jsonView")
+    public MappingJackson2JsonView getJsonView () {
+        ObjectMapper objectMapper = getObjectMapper();
+        MappingJackson2JsonView jsonView = new MappingJackson2JsonView(objectMapper);
+        jsonView.setExtractValueFromSingleKeyModel(true);
+        return jsonView;
+    }
+
+    @Bean(name = "objectMapper")
+    public ObjectMapper getObjectMapper() {
+        ObjectMapper mapper = new ObjectMapper();
+
+        mapper.registerModule(new JavaTimeModule());
+        //기본 날짜 포맷 비활성화
+        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+
+        //새로운 날짜 포맷 세팅
+		/*SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		mapper.setDateFormat(dateFormat);
+		mapper.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));*/
+
+        return mapper;
+    }
+
+    @Bean
+    public AntPathMatcher antPathMatcher() {
+        return new AntPathMatcher();
+    }
+
+    @Bean
+    public DefaultTraceHandler defaultTraceHandler() {
+        return new DefaultTraceHandler();
+    }
+
+    @Bean
+    public DefaultTraceHandleManager traceHandlerService() {
+        DefaultTraceHandleManager defaultTraceHandleManager = new DefaultTraceHandleManager();
+        defaultTraceHandleManager.setReqExpMatcher(antPathMatcher());
+        defaultTraceHandleManager.setPatterns(new String[]{"*"});
+        defaultTraceHandleManager.setHandlers(new TraceHandler[]{defaultTraceHandler()});
+        return defaultTraceHandleManager;
+    }
+
+    @Bean
+    public LeaveaTrace leaveaTrace() {
+        LeaveaTrace leaveaTrace = new LeaveaTrace();
+        leaveaTrace.setTraceHandlerServices(new TraceHandlerService[]{traceHandlerService()});
+        return leaveaTrace;
+    }
+
+}
 
src/main/java/com/takensoft/common/config/CorsMvcConfig.java (added)
+++ src/main/java/com/takensoft/common/config/CorsMvcConfig.java
@@ -0,0 +1,22 @@
+package com.takensoft.common.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class CorsMvcConfig implements WebMvcConfigurer {
+
+    private static String FRONT_URL; // 프론트 경로
+    @Value("${front.url}")
+    public void setFrontUrl(String value) {
+        FRONT_URL = value;
+    }
+
+    @Override
+    public void addCorsMappings(CorsRegistry corsRegistry) {
+        corsRegistry.addMapping("/**")
+                .allowedOrigins(FRONT_URL);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/config/SecurityConfig.java (added)
+++ src/main/java/com/takensoft/common/config/SecurityConfig.java
@@ -0,0 +1,135 @@
+package com.takensoft.common.config;
+
+import com.takensoft.cms.accesCtrl.service.AccesCtrlService;
+import com.takensoft.cms.mber.service.LgnHstryService;
+import com.takensoft.cms.mber.service.RefreshTokenService;
+import com.takensoft.common.filter.AccesFilter;
+import com.takensoft.common.filter.JWTFilter;
+import com.takensoft.common.filter.LoginFilter;
+import com.takensoft.common.util.CommonUtils;
+import com.takensoft.common.util.CustomAccessDenieHandler;
+import com.takensoft.common.util.CustomAuthenticationEntryPoint;
+import com.takensoft.common.util.JWTUtil;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Collections;
+
+/**
+ * @author takensoft
+ * @since 2024.04.01
+ * 
+ * 스프링 시큐리티 설정
+ */
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig {
+
+    // AuthenticationManager가 인자로 받을 AuthenticationConfiguration 객체 생성자 주입
+    private final AuthenticationConfiguration authenticationConfiguration;
+    private final JWTUtil jwtUtil;
+    private final RefreshTokenService refreshTokenService;
+    private final LgnHstryService lgnHstryService;
+    private final AccesCtrlService accesCtrlService;
+    private final CustomAuthenticationEntryPoint authenticationEntryPoint;
+    private final CustomAccessDenieHandler accessDenieHandler;
+    private final CommonUtils commonUtils;
+    private final CommonConfig commonConfig;
+
+    private static String FRONT_URL;    // 프론트 접근 허용 URL
+    private static long JWT_ACCESSTIME; // access 토큰 유지 시간
+    private static long JWT_REFRESHTIME; // refresh 토큰 유지 시간
+    private static int COOKIE_TIME; // 쿠키 유지 시간
+
+    public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil, RefreshTokenService refreshTokenService, AccesCtrlService accesCtrlService, CommonConfig commonConfig,
+                          LgnHstryService lgnHstryService, CustomAuthenticationEntryPoint authenticationEntryPoint, CustomAccessDenieHandler accessDenieHandler, CommonUtils commonUtils,
+                          @Value("${front.url}")String fUrl,@Value("${jwt.accessTime}")long aTime, @Value("${jwt.refreshTime}")long rTime, @Value("${cookie.time}")int ctime) {
+
+        this.authenticationConfiguration = authenticationConfiguration;
+        this.refreshTokenService = refreshTokenService;
+        this.lgnHstryService = lgnHstryService;
+        this.accesCtrlService = accesCtrlService;
+        this.authenticationEntryPoint = authenticationEntryPoint;
+        this.accessDenieHandler = accessDenieHandler;
+        this.jwtUtil = jwtUtil;
+        this.commonUtils = commonUtils;
+        this.commonConfig = commonConfig;
+
+        this.FRONT_URL = fUrl;
+        this.JWT_ACCESSTIME = aTime;
+        this.JWT_REFRESHTIME = rTime;
+        this.COOKIE_TIME = ctime;
+    }
+
+    // AuthenticationManager Bean 등록
+    @Bean
+    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
+        return configuration.getAuthenticationManager();
+    }
+
+    // 해시 암호화
+    @Bean
+    public BCryptPasswordEncoder bCryptPasswordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+        http.cors((cors) -> cors
+                .configurationSource(new CorsConfigurationSource() {
+                    @Override
+                    public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
+                        CorsConfiguration configuration = new CorsConfiguration();
+                        configuration.setAllowedOrigins(Collections.singletonList(FRONT_URL)); // 허용할 프론트 포트 포함 경로 입력
+                        configuration.setAllowedMethods(Collections.singletonList("*")); // 허용할 메소드(GET, POST, PUT 등)
+                        configuration.setAllowedHeaders(Collections.singletonList("*")); // 허용할 헤드
+                        configuration.setAllowCredentials(true); // 프론트에서 credentials 설정하면 true
+                        configuration.setMaxAge(3600L); // 허용을 물고 있을 시간
+                        configuration.setExposedHeaders(Collections.singletonList("Authorization")); // 서버에서 JWT를 Authorization에 담아 보내기 위해 허용을 함
+                        return configuration;
+                    }
+                })
+        );
+        // csrf disable
+        http.csrf((auth) -> auth.disable());
+        // formLogin disable
+        http.formLogin((auth) -> auth.disable());
+        // http basic 인증 방식 disable
+        http.httpBasic((auth) -> auth.disable());
+        // 세션 설정
+        http.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
+
+        http.exceptionHandling((exception) -> exception
+                .authenticationEntryPoint(authenticationEntryPoint) // 접근 권한이 없는 경우에 호출
+                .accessDeniedHandler(accessDenieHandler) // 인증되지 않은 상태로 접근 했을 때 호출
+        );
+
+        http.authorizeHttpRequests((auth) -> auth
+                .antMatchers("/", "/mbr/**", "/company/**", "/refresh/**", "/sys/**").permitAll() // 회원관련, 시스템 제공 관련, 기업용페이지는 누구나 접근 가능
+                .antMatchers("/admin/**").hasRole("ADMIN") // 관리자 페이지는 ADMIN 권한을 가진 사용자만 접근 가능
+                .antMatchers("/editFileUpload/**", "/fileUpload/**").permitAll() // 에디터 파일 업로드
+                .anyRequest().authenticated() // 그 외에는 로그인한 사용자만 접근 가능
+//                .anyRequest().permitAll() // 모든 사용자 접근 가능
+        );
+
+
+        http.addFilterBefore(new JWTFilter(jwtUtil, commonConfig), LoginFilter.class); // 토큰 검증 필터
+        http.addFilterBefore(new AccesFilter(accesCtrlService, commonUtils, commonConfig), JWTFilter.class); // 아이피 검증
+        http.addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil, refreshTokenService, lgnHstryService, commonUtils,
+                        commonConfig, JWT_ACCESSTIME, JWT_REFRESHTIME, COOKIE_TIME), UsernamePasswordAuthenticationFilter.class); // 로그인 필터
+
+        return http.build();
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/config/UmsDataSourceConfig.java (added)
+++ src/main/java/com/takensoft/common/config/UmsDataSourceConfig.java
@@ -0,0 +1,56 @@
+package com.takensoft.common.config;
+
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.context.WebApplicationContext;
+
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages="com.takensoft.ums.dao", sqlSessionFactoryRef = "umsSqlSessionFactory")
+public class UmsDataSourceConfig {
+    @Bean(name = "umsDataSource")
+    @ConfigurationProperties(prefix="spring.ums.datasource")
+    public DataSource umsDataSource() {
+        return DataSourceBuilder.create().build();
+    }
+
+    @Bean(name = "umsSqlSessionFactory")
+    public SqlSessionFactory umsSqlSessionFactory(@Qualifier("umsDataSource") DataSource umsDataSource,
+                                                  ApplicationContext applicationContext) throws Exception {
+        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
+        sqlSessionFactoryBean.setDataSource(umsDataSource);
+        sqlSessionFactoryBean.setTypeAliasesPackage("com.takensoft.ums.vo");
+        sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mybatis/mapper-ora/**/*-SQL.xml"));
+
+        // MyBatis Configuration 설정 추가
+        org.apache.ibatis.session.Configuration myBatisConfig = new org.apache.ibatis.session.Configuration();
+        myBatisConfig.setCacheEnabled(true);
+        myBatisConfig.setLazyLoadingEnabled(false);
+        myBatisConfig.setMultipleResultSetsEnabled(true);
+        myBatisConfig.setUseColumnLabel(true);
+        myBatisConfig.setUseGeneratedKeys(false);
+        myBatisConfig.setDefaultExecutorType(org.apache.ibatis.session.ExecutorType.SIMPLE);
+        myBatisConfig.setDefaultStatementTimeout(25000);
+        myBatisConfig.setCallSettersOnNulls(true);
+        myBatisConfig.setMapUnderscoreToCamelCase(true);
+
+        sqlSessionFactoryBean.setConfiguration(myBatisConfig);
+
+        return sqlSessionFactoryBean.getObject();
+    }
+
+    @Bean(name = "umsSessionTemplate")
+    public SqlSessionTemplate umsSqlSessionTemplate(@Qualifier("umsSqlSessionFactory") SqlSessionFactory umsSqlSessionFactory) {
+        return new SqlSessionTemplate(umsSqlSessionFactory);
+    }
+}
 
src/main/java/com/takensoft/common/config/WebConfig.java (added)
+++ src/main/java/com/takensoft/common/config/WebConfig.java
@@ -0,0 +1,26 @@
+package com.takensoft.common.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.filter.CommonsRequestLoggingFilter;
+import org.springframework.web.filter.ForwardedHeaderFilter;
+
+import javax.servlet.Filter;
+
+@Configuration
+public class WebConfig {
+    @Bean
+    public Filter forwardedHeaderFilter() {
+        return new ForwardedHeaderFilter();
+    }
+
+    @Bean
+    public CommonsRequestLoggingFilter requestLoggingFilter() {
+        CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
+        loggingFilter.setIncludeClientInfo(true);
+        loggingFilter.setIncludeQueryString(true);
+        loggingFilter.setIncludePayload(true);
+        loggingFilter.setIncludeHeaders(true);
+        return loggingFilter;
+    }
+}
 
src/main/java/com/takensoft/common/excel/annotation/ExcelColumnName.java (added)
+++ src/main/java/com/takensoft/common/excel/annotation/ExcelColumnName.java
@@ -0,0 +1,12 @@
+package com.takensoft.common.excel.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ExcelColumnName {
+    String headerName() default "";
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/excel/annotation/ExcelFileName.java (added)
+++ src/main/java/com/takensoft/common/excel/annotation/ExcelFileName.java
@@ -0,0 +1,12 @@
+package com.takensoft.common.excel.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ExcelFileName {
+    String fileName() default "";
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/excel/resource/ExcelRenderResource.java (added)
+++ src/main/java/com/takensoft/common/excel/resource/ExcelRenderResource.java
@@ -0,0 +1,17 @@
+package com.takensoft.common.excel.resource;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import java.util.*;
+
+@Getter
+@RequiredArgsConstructor
+public class ExcelRenderResource {
+    private final String excelFileName;
+    private final Map<String, String> excelHeaderNames;
+    private final List<String> dataFieldNames;
+
+    public String getExcelHeaderName(String dataFieldName) {
+        return excelHeaderNames.get(dataFieldName);
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/excel/resource/ExcelRenderResourceFactory.java (added)
+++ src/main/java/com/takensoft/common/excel/resource/ExcelRenderResourceFactory.java
@@ -0,0 +1,35 @@
+package com.takensoft.common.excel.resource;
+
+import com.takensoft.common.excel.annotation.ExcelColumnName;
+import com.takensoft.common.excel.annotation.ExcelFileName;
+import com.takensoft.common.excel.util.SuperClassReflectionUtil;
+import org.springframework.util.StringUtils;
+import java.util.*;
+import java.lang.reflect.Field;
+
+public class ExcelRenderResourceFactory {
+    public static ExcelRenderResource prepareRenderResource(Class<?> type) {
+        String fileName = getFileName(type);
+        Map<String, String> headerNamesMap = new LinkedHashMap<>();
+        List<String> fieldNames = new ArrayList<>();
+        for (Field field : SuperClassReflectionUtil.getAllFields(type)) {
+            if (field.isAnnotationPresent(ExcelColumnName.class)) {
+                ExcelColumnName annotation = field.getAnnotation(ExcelColumnName.class);
+                fieldNames.add(field.getName());
+                String headerName = annotation.headerName();
+                headerName = StringUtils.hasText(headerName) ? headerName : field.getName();
+                headerNamesMap.put(field.getName(), headerName);
+            }
+        }
+        return new ExcelRenderResource(fileName, headerNamesMap, fieldNames);
+    }
+
+    private static String getFileName(Class<?> type) {
+        String fileName = type.getSimpleName();
+        if (type.isAnnotationPresent(ExcelColumnName.class)) {
+            fileName = type.getAnnotation(ExcelFileName.class).fileName();
+            if(!StringUtils.hasText(fileName)) fileName = type.getSimpleName();
+        }
+        return fileName;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/excel/service/ExcelCreateService.java (added)
+++ src/main/java/com/takensoft/common/excel/service/ExcelCreateService.java
@@ -0,0 +1,309 @@
+package com.takensoft.common.excel.service;
+
+import com.takensoft.common.excel.resource.ExcelRenderResource;
+import com.takensoft.common.excel.resource.ExcelRenderResourceFactory;
+import com.takensoft.common.excel.util.SuperClassReflectionUtil;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.springframework.util.ObjectUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.nio.file.Paths;
+import java.util.Base64;
+import java.util.List;
+
+public class ExcelCreateService<T> {
+    private Workbook workbook;
+    private Sheet sheet;
+    private ExcelRenderResource resource;
+    private List<T> dataList;
+    private static final String BASE64_PNG_PRE_FIX = "data:image/png;base64,";
+
+    public ExcelCreateService(Workbook workbook, Sheet sheet, List<T> dataList, Class<T> type) {
+        this.workbook = workbook;
+        this.sheet = sheet;
+        this.resource = ExcelRenderResourceFactory.prepareRenderResource(type);
+        this.dataList = dataList;
+    }
+
+    // 헤더 스타일
+    private CellStyle theadStyle() {
+        CellStyle headerCellStyle = tbodyStyle();
+        headerCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+        headerCellStyle.setFillPattern(FillPatternType.BRICKS);
+        return headerCellStyle;
+    }
+    // 내용 스타일
+    private CellStyle tbodyStyle() {
+        CellStyle bodyCellStyle = workbook.createCellStyle();
+        bodyCellStyle.setBorderLeft(BorderStyle.THIN);
+        bodyCellStyle.setBorderRight(BorderStyle.THIN);
+        bodyCellStyle.setBorderTop(BorderStyle.THIN);
+        bodyCellStyle.setBorderBottom(BorderStyle.THIN);
+        bodyCellStyle.setWrapText(true);
+        return bodyCellStyle;
+    }
+    // 빈칸 스타일
+    private CellStyle emptyStyle() {
+        CellStyle emptyStyle = workbook.createCellStyle();
+        emptyStyle.setBorderLeft(BorderStyle.NONE);
+        emptyStyle.setBorderRight(BorderStyle.NONE);
+        emptyStyle.setBorderTop(BorderStyle.NONE);
+        emptyStyle.setBorderBottom(BorderStyle.NONE);
+        return emptyStyle;
+    }
+
+    // 세로 적재 테이블 그리기
+    public int createVertical(ExcelRenderResource resource, List<T> dataList, int rowIndex) throws NoSuchFieldException, IllegalAccessException {
+        for (String dataFieldName : resource.getDataFieldNames()) {
+            // tr
+            Row row = sheet.createRow(rowIndex++);
+            // th
+            Cell cell = row.createCell(0);
+            String value = resource.getExcelHeaderName(dataFieldName);
+            cell.setCellValue(value);
+            cell.setCellStyle(theadStyle());
+            int columnIndex = 1;
+            // td
+            for (T data : dataList) {
+                cell = row.createCell(columnIndex++);
+                Field field = SuperClassReflectionUtil.getField(data.getClass(), (dataFieldName));
+                field.setAccessible(true);
+                Object cellValue = field.get(data);
+                field.setAccessible(false);
+                setCellValue(cell, cellValue);
+            }
+        }
+
+        return rowIndex;
+    }
+
+    // 가로 적재 테이블 그리기
+    public int createHorizontal(ExcelRenderResource resource, List<T> dataList, int rowIndex) throws NoSuchFieldException, IllegalAccessException {
+        // tr
+        Row row = sheet.createRow(rowIndex++);
+        // th
+        int columnIndex = 0;
+        for (String dataFieldName : resource.getDataFieldNames()) {
+            Cell cell = row.createCell(columnIndex++);
+            String value = resource.getExcelHeaderName(dataFieldName);
+            cell.setCellValue(value);
+            cell.setCellStyle(theadStyle());
+        }
+        // td
+        for (T data : dataList) {
+            row = sheet.createRow(rowIndex++);
+            columnIndex = 0;
+            for (String dataFieldName : resource.getDataFieldNames()) {
+                Cell cell = row.createCell(columnIndex++);
+                Field field = SuperClassReflectionUtil.getField(data.getClass(), (dataFieldName));
+                field.setAccessible(true);
+                Object cellValue = field.get(data);
+                field.setAccessible(false);
+                setCellValue(cell, cellValue);
+            }
+        }
+
+        return rowIndex;
+    }
+    
+    // 세로형 가로 적재 테이블 그리기
+    public int createVH(ExcelRenderResource resource, List<T> dataList, int rowIndex) throws NoSuchFieldException, IllegalAccessException {
+        for (T data : dataList) {
+            for (String dataFieldName : resource.getDataFieldNames()) {
+                // tr
+                Row row = sheet.createRow(rowIndex++);
+
+                int columnIndex = 0;
+
+                // th
+                Cell cell = row.createCell(columnIndex++);
+                String value = resource.getExcelHeaderName(dataFieldName);
+                cell.setCellValue(value);
+                cell.setCellStyle(theadStyle());
+
+                // td
+                cell = row.createCell(columnIndex++);
+                Field field = SuperClassReflectionUtil.getField(data.getClass(), (dataFieldName));
+                field.setAccessible(true);
+                Object cellValue = field.get(data);
+                field.setAccessible(false);
+                setCellValue(cell, cellValue);
+            }
+        }
+
+        return rowIndex;
+    }
+
+    // 구분선
+    public int createHr(int rowIndex) {
+        // tr
+        Row row = sheet.createRow(rowIndex++);
+        Cell cell = row.createCell(0);
+        setCellValue(cell, " ");
+        cell.setCellStyle(emptyStyle());
+        return rowIndex;
+    }
+
+    // 제목
+    public int createCaption(int rowIndex, String caption) {
+        // tr
+        Row row = sheet.createRow(rowIndex++);
+        Cell cell = row.createCell(0);
+        setCellValue(cell, caption);
+        cell.setCellStyle(emptyStyle());
+        return rowIndex;
+    }
+
+    // 셀 내 데이터 입력
+    private void setCellValue(Cell cell, Object cellValue) {
+        if (cellValue instanceof Number) {
+            Number numberValue = (Number) cellValue;
+            cell.setCellValue(numberValue.doubleValue());
+            cell.setCellStyle(tbodyStyle());
+            return;
+        }
+        cell.setCellValue(ObjectUtils.isEmpty(cellValue) ? "" : String.valueOf(cellValue));
+        cell.setCellStyle(tbodyStyle());
+    }
+
+    /**
+     * @author 박정하
+     * @since 2024.03.28
+     *
+     * 차트 이미지 넣기
+     */
+    public void chartDraw(Sheet sheet, String chart, int rowNum, int cellNum) {
+        if (chart != null && chart.equals("")) {
+            InputStream in = null;
+            FileOutputStream fos = null;
+            File imageFile = null;
+
+            try {
+                String encodingStr = chart.replace(BASE64_PNG_PRE_FIX, "");
+
+                Base64.Decoder decoder = Base64.getDecoder();
+                byte[] decodeImg = decoder.decode(encodingStr);
+
+                String uploadPath = Paths.get("C:", "upload-files").toString();
+                File dir = new File(uploadPath);
+                if (dir.exists() == false) {
+                    dir.mkdirs();
+                }
+                uploadPath = dir.getPath();
+
+                imageFile = new File(uploadPath + "/chartImg.png");
+                fos = new FileOutputStream(imageFile);
+                fos.write(decodeImg);
+
+                in = new FileInputStream(imageFile);
+                byte[] bytes = IOUtils.toByteArray(in);
+                int pictureIdx = workbook.addPicture(bytes, SXSSFWorkbook.PICTURE_TYPE_PNG);
+
+                final CreationHelper helper = workbook.getCreationHelper();
+                final Drawing drawing = sheet.createDrawingPatriarch();
+                final ClientAnchor anchor = helper.createClientAnchor();
+
+                // 이미지를 출력할 CELL 위치 선정
+                anchor.setCol1(cellNum++);
+                anchor.setRow1(rowNum++);
+
+                // 이미지 그리기
+                final Picture pict = drawing.createPicture(anchor, pictureIdx);
+                pict.resize(); // 이미지 사이즈 비율 설정
+                rowNum = rowNum + 20;
+            } catch(Exception e) {
+                e.printStackTrace();
+            } finally {
+                IOUtils.closeQuietly(in);
+                IOUtils.closeQuietly(fos);
+                imageFile.delete();
+            }
+        }
+    }
+
+    // 세로 적재 테이블 그리기 (기업정보용)
+    public int createVerticalByEntInfo(ExcelRenderResource resource, List<T> dataList, int rowIndex) throws NoSuchFieldException, IllegalAccessException {
+        String isIvstDscsn = null;
+        for (String dataFieldName : resource.getDataFieldNames()) {
+            if (dataFieldName!= "isIvstDscsn" && dataFieldName != "mvnInten" &&  dataFieldName != "mouInten" &&  dataFieldName != "rmrk") {
+                rowIndex = createTableByEntInfo(resource, rowIndex, dataFieldName);
+            }
+        }
+
+        rowIndex = createHr(rowIndex); // 구분선
+        rowIndex = createCaption(rowIndex, "세부정보");
+
+        Field field = SuperClassReflectionUtil.getField(dataList.get(0).getClass(), ("isIvstDscsn"));
+        field.setAccessible(true);
+        isIvstDscsn = field.get(dataList.get(0)).toString();
+        field.setAccessible(false);
+
+        rowIndex = createTableByEntInfo(resource, rowIndex, "isIvstDscsn");
+        if (isIvstDscsn == "Y") {
+            for (String dataFieldName : resource.getDataFieldNames()) {
+                if (dataFieldName == "mvnInten" || dataFieldName == "mouInten") {
+                    rowIndex = createTableByEntInfo(resource, rowIndex, dataFieldName);
+                }
+            }
+        }
+        rowIndex = createTableByEntInfo(resource, rowIndex, "rmrk");
+
+        return rowIndex;
+    }
+    // 테이블 그리기
+    private int createTableByEntInfo(ExcelRenderResource resource, int rowIndex, String dataFieldName) throws NoSuchFieldException, IllegalAccessException  {
+        // tr
+        Row row = sheet.createRow(rowIndex++);
+        // th
+        Cell cell = row.createCell(0);
+        String value = resource.getExcelHeaderName(dataFieldName);
+        cell.setCellValue(value);
+        cell.setCellStyle(theadStyle());
+        // td
+        cell = row.createCell(1);
+        Field field = SuperClassReflectionUtil.getField(dataList.get(0).getClass(), (dataFieldName));
+        field.setAccessible(true);
+        Object cellValue = field.get(dataList.get(0));
+        field.setAccessible(false);
+        setCellValue(cell, cellValue);
+        return rowIndex;
+    }
+
+    // 기업정보 전체 테이블 그리기 (기업정보용)
+    public int createByEntInfoAll(ExcelRenderResource resource, List<T> dataList, int rowIndex) throws NoSuchFieldException, IllegalAccessException {
+        // tr
+        Row row = sheet.createRow(rowIndex++);
+
+        // th
+        int columnIndex = 0;
+        for (String dataFieldName : resource.getDataFieldNames()) {
+            Cell cell = row.createCell(columnIndex++);
+            String value = resource.getExcelHeaderName(dataFieldName);
+            cell.setCellValue(value);
+            cell.setCellStyle(theadStyle());
+        }
+
+        // td
+        for (T data : dataList) {
+            row = sheet.createRow(rowIndex++);
+            columnIndex = 0;
+
+            for (String dataFieldName : resource.getDataFieldNames()) {
+                Cell cell = row.createCell(columnIndex++);
+                Field field = SuperClassReflectionUtil.getField(data.getClass(), (dataFieldName));
+                field.setAccessible(true);
+                Object cellValue = field.get(data);
+                field.setAccessible(false);
+                setCellValue(cell, cellValue);
+            }
+        }
+
+        return rowIndex;
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/excel/service/ExcelService.java (added)
+++ src/main/java/com/takensoft/common/excel/service/ExcelService.java
@@ -0,0 +1,19 @@
+package com.takensoft.common.excel.service;
+
+import com.takensoft.cms.cntnStats.dto.CntnStatsExcelDTO;
+import com.takensoft.portal.entInfo.dto.BplcExcelDTO;
+import com.takensoft.portal.entInfo.dto.EntInfoExcelDTO;
+import com.takensoft.portal.ivstDscsn.dto.IvstDscsnExcelDTO;
+import com.takensoft.portal.rvwMttr.dto.RvwMttrExcelDTO;
+import com.takensoft.portal.rvwMttr.dto.RvwMttrPrgrsExcelDTO;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+public interface ExcelService {
+    public void ivstDscsnExcelDownload(HttpServletResponse response, IvstDscsnExcelDTO ivstDscsn) throws Exception;
+    public void rvwMttrExcelDownload(HttpServletResponse response, RvwMttrExcelDTO rvwMttr, List<RvwMttrPrgrsExcelDTO> prgrsList) throws Exception;
+    public void entInfoExcelDownload(HttpServletResponse response, EntInfoExcelDTO entInfo, List<BplcExcelDTO> bplcList) throws Exception;
+    public void cntnStatsExcelDownload(HttpServletResponse response, List<CntnStatsExcelDTO> cntnStats, String chart) throws Exception;
+    public void entInfoExcelDownloadAll(HttpServletResponse response, List<EntInfoExcelDTO> entInfoList) throws Exception;
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/excel/service/Impl/ExcelServiceImpl.java (added)
+++ src/main/java/com/takensoft/common/excel/service/Impl/ExcelServiceImpl.java
@@ -0,0 +1,180 @@
+package com.takensoft.common.excel.service.Impl;
+
+import com.takensoft.cms.cntnStats.dto.CntnStatsExcelDTO;
+import com.takensoft.common.excel.resource.ExcelRenderResource;
+import com.takensoft.common.excel.resource.ExcelRenderResourceFactory;
+import com.takensoft.common.excel.service.ExcelCreateService;
+import com.takensoft.common.excel.service.ExcelService;
+import com.takensoft.portal.entInfo.dto.BplcExcelDTO;
+import com.takensoft.portal.entInfo.dto.EntInfoExcelDTO;
+import com.takensoft.portal.ivstDscsn.dto.IvstDscsnExcelDTO;
+import com.takensoft.portal.rvwMttr.dto.RvwMttrExcelDTO;
+import com.takensoft.portal.rvwMttr.dto.RvwMttrPrgrsExcelDTO;
+import lombok.RequiredArgsConstructor;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+@Service("excelService")
+@RequiredArgsConstructor
+public class ExcelServiceImpl extends EgovAbstractServiceImpl implements ExcelService {
+    // 엑셀 파일 출력
+    public static void writeExcel(HttpServletResponse response, Workbook workbook, ExcelRenderResource resource) throws IOException {
+        String fileName = new String(resource.getExcelFileName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
+        response.setContentType("ms-vnd/excel");
+        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=" + fileName + ".xlsx"));
+        workbook.write(response.getOutputStream());
+        workbook.close();
+    }
+
+    // 투자상담
+    @Override
+    public void ivstDscsnExcelDownload(HttpServletResponse response, IvstDscsnExcelDTO ivstDscsn) throws Exception {
+        // 기본 세팅
+        Workbook workbook = new SXSSFWorkbook();
+        Sheet sheet = workbook.createSheet();
+        int rowIndex = 0;
+
+        // 개별 설정
+        ExcelRenderResource mainResource = ExcelRenderResourceFactory.prepareRenderResource(IvstDscsnExcelDTO.class);
+        List<IvstDscsnExcelDTO> mainDataList = new ArrayList<>();
+        mainDataList.add(ivstDscsn);
+
+        // 엑셀 그리기
+        ExcelCreateService<IvstDscsnExcelDTO> mainExcel = new ExcelCreateService(workbook, sheet, mainDataList, mainDataList.getClass());
+        mainExcel.createVertical(mainResource, mainDataList, rowIndex);
+
+        // 엑셀 사이즈 지정
+        sheetSize(sheet, 2);
+
+        // 엑셀 파일 출력
+        writeExcel(response, workbook, mainResource);
+    }
+
+    // 검토사항
+    @Override
+    public void rvwMttrExcelDownload(HttpServletResponse response, RvwMttrExcelDTO rvwMttr, List<RvwMttrPrgrsExcelDTO> prgrsList) throws Exception {
+        // 기본 세팅
+        Workbook workbook = new SXSSFWorkbook();
+        Sheet sheet = workbook.createSheet();
+        int rowIndex = 0;
+
+        // 개별 설정
+        ExcelRenderResource mainResource = ExcelRenderResourceFactory.prepareRenderResource(RvwMttrExcelDTO.class);
+        List<RvwMttrExcelDTO> mainDataList = new ArrayList<>();
+        mainDataList.add(rvwMttr);
+
+        ExcelRenderResource prgrsResource = ExcelRenderResourceFactory.prepareRenderResource(RvwMttrPrgrsExcelDTO.class);
+
+        // 엑셀 그리기
+        ExcelCreateService<RvwMttrExcelDTO> mainExcel = new ExcelCreateService(workbook, sheet, mainDataList, mainDataList.getClass());
+        rowIndex = mainExcel.createCaption(rowIndex, "기본정보");
+        rowIndex = mainExcel.createVertical(mainResource, mainDataList, rowIndex);
+
+        rowIndex = mainExcel.createHr(rowIndex); // 구분선
+        rowIndex = mainExcel.createCaption(rowIndex, "진행단계 및 지원방안");
+        ExcelCreateService<RvwMttrPrgrsExcelDTO> prgrsExcel = new ExcelCreateService(workbook, sheet, prgrsList, prgrsList.getClass());
+        rowIndex = prgrsExcel.createVH(prgrsResource, prgrsList, rowIndex);
+
+        // 엑셀 사이즈 지정
+        sheetSize(sheet, 2);
+
+        // 엑셀 파일 출력
+        writeExcel(response, workbook, mainResource);
+    }
+
+    // 기업정보
+    @Override
+    public void entInfoExcelDownload(HttpServletResponse response, EntInfoExcelDTO entInfo, List<BplcExcelDTO> bplcList) throws Exception {
+        // 기본 세팅
+        Workbook workbook = new SXSSFWorkbook();
+        Sheet sheet = workbook.createSheet();
+        int rowIndex = 0;
+
+        // 개별 설정
+        ExcelRenderResource mainResource = ExcelRenderResourceFactory.prepareRenderResource(EntInfoExcelDTO.class);
+        List<EntInfoExcelDTO> mainDataList = new ArrayList<>();
+        mainDataList.add(entInfo);
+
+        ExcelRenderResource bplcResource = ExcelRenderResourceFactory.prepareRenderResource(BplcExcelDTO.class);
+
+        // 엑셀 그리기
+        ExcelCreateService<EntInfoExcelDTO> mainExcel = new ExcelCreateService(workbook, sheet, mainDataList, mainDataList.getClass());
+        rowIndex = mainExcel.createCaption(rowIndex, "기본정보");
+        rowIndex = mainExcel.createVerticalByEntInfo(mainResource, mainDataList, rowIndex);
+
+        rowIndex = mainExcel.createHr(rowIndex); // 구분선
+        rowIndex = mainExcel.createCaption(rowIndex, "주요사업장");
+        ExcelCreateService<BplcExcelDTO> bplcExcel = new ExcelCreateService(workbook, sheet, bplcList, bplcList.getClass());
+        bplcExcel.createVertical(bplcResource, bplcList, rowIndex);
+
+        // 엑셀 사이즈 지정
+        sheetSize(sheet, 2);
+
+        // 엑셀 파일 출력
+        writeExcel(response, workbook, mainResource);
+    }
+
+    // 통계관리
+    @Override
+    public void cntnStatsExcelDownload(HttpServletResponse response, List<CntnStatsExcelDTO> mainDataList, String chart) throws Exception {
+        // 기본 세팅
+        Workbook workbook = new SXSSFWorkbook();
+        Sheet sheet = workbook.createSheet();
+        int rowIndex = 0;
+
+        // 개별 설정
+        ExcelRenderResource mainResource = ExcelRenderResourceFactory.prepareRenderResource(CntnStatsExcelDTO.class);
+
+        // 엑셀 그리기
+        ExcelCreateService<CntnStatsExcelDTO> mainExcel = new ExcelCreateService(workbook, sheet, mainDataList, mainDataList.getClass());
+        mainExcel.chartDraw(sheet, chart, rowIndex, mainResource.getDataFieldNames().size() + 1);
+        rowIndex = mainExcel.createHorizontal(mainResource, mainDataList, rowIndex);
+
+        // 엑셀 사이즈 지정
+        int cellNumber = mainResource.getDataFieldNames().size();
+        sheetSize(sheet, cellNumber);
+
+        // 엑셀 파일 출력
+        writeExcel(response, workbook, mainResource);
+    }
+
+    // 기업정보 전체 다운로드
+    public void entInfoExcelDownloadAll(HttpServletResponse response, List<EntInfoExcelDTO> mainDataList) throws Exception {
+        // 기본 세팅
+        Workbook workbook = new SXSSFWorkbook();
+        Sheet sheet = workbook.createSheet();
+        int rowIndex = 0;
+
+        // 개별 설정
+        ExcelRenderResource mainResource = ExcelRenderResourceFactory.prepareRenderResource(EntInfoExcelDTO.class);
+
+        // 엑셀 그리기
+        ExcelCreateService<EntInfoExcelDTO> mainExcel = new ExcelCreateService(workbook, sheet, mainDataList, mainDataList.getClass());
+        mainExcel.createByEntInfoAll(mainResource, mainDataList, rowIndex);
+
+        // 엑셀 사이즈 지정
+        int cellNumber = mainResource.getDataFieldNames().size();
+        sheetSize(sheet, cellNumber);
+
+        // 엑셀 파일 출력
+        writeExcel(response, workbook, mainResource);
+    }
+
+    public void sheetSize(Sheet sheet, int cellNumber){
+        ((SXSSFSheet)sheet).trackAllColumnsForAutoSizing();
+        for(int k = 0 ; k < cellNumber + 1; k++){
+            sheet.autoSizeColumn(k);
+            sheet.setColumnWidth(k, Math.min(150*150, sheet.getColumnWidth(k) + 1024));
+        }
+    }
+}(파일 끝에 줄바꿈 문자 없음)
 
src/main/java/com/takensoft/common/excel/util/SuperClassReflectionUtil.java (added)
+++ src/main/java/com/takensoft/common/excel/util/SuperClassReflectionUtil.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/exception/IdDuplicationException.java (added)
+++ src/main/java/com/takensoft/common/exception/IdDuplicationException.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/dao/FileDAO.java (added)
+++ src/main/java/com/takensoft/common/file/dao/FileDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/dao/FileMngDAO.java (added)
+++ src/main/java/com/takensoft/common/file/dao/FileMngDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/service/FileMngService.java (added)
+++ src/main/java/com/takensoft/common/file/service/FileMngService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/service/FileService.java (added)
+++ src/main/java/com/takensoft/common/file/service/FileService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/service/Impl/FileMngServiceImpl.java (added)
+++ src/main/java/com/takensoft/common/file/service/Impl/FileMngServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/service/Impl/FileServiceImpl.java (added)
+++ src/main/java/com/takensoft/common/file/service/Impl/FileServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/vo/FileMngVO.java (added)
+++ src/main/java/com/takensoft/common/file/vo/FileMngVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/vo/FileVO.java (added)
+++ src/main/java/com/takensoft/common/file/vo/FileVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/file/web/FileController.java (added)
+++ src/main/java/com/takensoft/common/file/web/FileController.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/filter/AccesFilter.java (added)
+++ src/main/java/com/takensoft/common/filter/AccesFilter.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/filter/JWTFilter.java (added)
+++ src/main/java/com/takensoft/common/filter/JWTFilter.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/filter/LoginFilter.java (added)
+++ src/main/java/com/takensoft/common/filter/LoginFilter.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/idgen/context/ContextIdgen.java (added)
+++ src/main/java/com/takensoft/common/idgen/context/ContextIdgen.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/idgen/dao/IdgenMapper.java (added)
+++ src/main/java/com/takensoft/common/idgen/dao/IdgenMapper.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/idgen/service/IdgenService.java (added)
+++ src/main/java/com/takensoft/common/idgen/service/IdgenService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/idgen/vo/IdgenVO.java (added)
+++ src/main/java/com/takensoft/common/idgen/vo/IdgenVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/util/CommonUtils.java (added)
+++ src/main/java/com/takensoft/common/util/CommonUtils.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/util/CustomAccessDenieHandler.java (added)
+++ src/main/java/com/takensoft/common/util/CustomAccessDenieHandler.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/util/CustomAuthenticationEntryPoint.java (added)
+++ src/main/java/com/takensoft/common/util/CustomAuthenticationEntryPoint.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/util/ErrorResponse.java (added)
+++ src/main/java/com/takensoft/common/util/ErrorResponse.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/util/JWTUtil.java (added)
+++ src/main/java/com/takensoft/common/util/JWTUtil.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/util/KISA_SEED_CBC.java (added)
+++ src/main/java/com/takensoft/common/util/KISA_SEED_CBC.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/util/ResponseData.java (added)
+++ src/main/java/com/takensoft/common/util/ResponseData.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/common/util/Secret.java (added)
+++ src/main/java/com/takensoft/common/util/Secret.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entDscsnAply/dao/EntDscsnAplyDAO.java (added)
+++ src/main/java/com/takensoft/portal/entDscsnAply/dao/EntDscsnAplyDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entDscsnAply/service/EntDscsnAplyService.java (added)
+++ src/main/java/com/takensoft/portal/entDscsnAply/service/EntDscsnAplyService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entDscsnAply/service/Impl/EntDscsnAplyServiceImpl.java (added)
+++ src/main/java/com/takensoft/portal/entDscsnAply/service/Impl/EntDscsnAplyServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entDscsnAply/vo/EntDscsnAplyVO.java (added)
+++ src/main/java/com/takensoft/portal/entDscsnAply/vo/EntDscsnAplyVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entDscsnAply/web/EntDscsnAplyController.java (added)
+++ src/main/java/com/takensoft/portal/entDscsnAply/web/EntDscsnAplyController.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/dao/BplcDAO.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/dao/BplcDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/dao/EntInfoDAO.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/dao/EntInfoDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/dto/BplcExcelDTO.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/dto/BplcExcelDTO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/dto/EntInfoExcelDTO.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/dto/EntInfoExcelDTO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/service/BplcService.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/service/BplcService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/service/EntInfoService.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/service/EntInfoService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/service/Impl/BplcServiceImpl.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/service/Impl/BplcServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/service/Impl/EntInfoServiceImpl.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/service/Impl/EntInfoServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/vo/BplcVO.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/vo/BplcVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/vo/EntInfoVO.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/vo/EntInfoVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/entInfo/web/EntInfoController.java (added)
+++ src/main/java/com/takensoft/portal/entInfo/web/EntInfoController.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/ivstDscsn/dao/IvstDscsnDAO.java (added)
+++ src/main/java/com/takensoft/portal/ivstDscsn/dao/IvstDscsnDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/ivstDscsn/dto/IvstDscsnExcelDTO.java (added)
+++ src/main/java/com/takensoft/portal/ivstDscsn/dto/IvstDscsnExcelDTO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/ivstDscsn/service/Impl/IvstDscsnServiceImpl.java (added)
+++ src/main/java/com/takensoft/portal/ivstDscsn/service/Impl/IvstDscsnServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/ivstDscsn/service/IvstDscsnService.java (added)
+++ src/main/java/com/takensoft/portal/ivstDscsn/service/IvstDscsnService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/ivstDscsn/vo/IvstDscsnVO.java (added)
+++ src/main/java/com/takensoft/portal/ivstDscsn/vo/IvstDscsnVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/ivstDscsn/web/IvstDscsnController.java (added)
+++ src/main/java/com/takensoft/portal/ivstDscsn/web/IvstDscsnController.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/main/dao/GovernmentMainDAO.java (added)
+++ src/main/java/com/takensoft/portal/main/dao/GovernmentMainDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/main/service/GovernmentMainService.java (added)
+++ src/main/java/com/takensoft/portal/main/service/GovernmentMainService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/main/service/impl/GovernmentMainServiceImpl.java (added)
+++ src/main/java/com/takensoft/portal/main/service/impl/GovernmentMainServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/main/web/GovernmentMainController.java (added)
+++ src/main/java/com/takensoft/portal/main/web/GovernmentMainController.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/dao/RvwMttrDAO.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/dao/RvwMttrDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/dao/RvwMttrPrgrsDAO.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/dao/RvwMttrPrgrsDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/dto/RvwMttrExcelDTO.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/dto/RvwMttrExcelDTO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/dto/RvwMttrPrgrsExcelDTO.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/dto/RvwMttrPrgrsExcelDTO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/service/Impl/RvwMttrPrgrsServiceImpl.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/service/Impl/RvwMttrPrgrsServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/service/Impl/RvwMttrServiceImpl.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/service/Impl/RvwMttrServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/service/RvwMttrPrgrsService.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/service/RvwMttrPrgrsService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/service/RvwMttrService.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/service/RvwMttrService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/vo/RvwMttrPrgrsVO.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/vo/RvwMttrPrgrsVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/vo/RvwMttrVO.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/vo/RvwMttrVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/rvwMttr/web/RvwMttrController.java (added)
+++ src/main/java/com/takensoft/portal/rvwMttr/web/RvwMttrController.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/statistics/dao/StatisticsDAO.java (added)
+++ src/main/java/com/takensoft/portal/statistics/dao/StatisticsDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/statistics/service/Impl/StatisticsServiceImpl.java (added)
+++ src/main/java/com/takensoft/portal/statistics/service/Impl/StatisticsServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/statistics/service/StatisticsService.java (added)
+++ src/main/java/com/takensoft/portal/statistics/service/StatisticsService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/portal/statistics/web/StatisticsController.java (added)
+++ src/main/java/com/takensoft/portal/statistics/web/StatisticsController.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/ums/dao/UmsDAO.java (added)
+++ src/main/java/com/takensoft/ums/dao/UmsDAO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/ums/service/Impl/UmsServiceImpl.java (added)
+++ src/main/java/com/takensoft/ums/service/Impl/UmsServiceImpl.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/ums/service/UmsService.java (added)
+++ src/main/java/com/takensoft/ums/service/UmsService.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/ums/vo/UmsVO.java (added)
+++ src/main/java/com/takensoft/ums/vo/UmsVO.java
This diff is skipped because there are too many other diffs.
 
src/main/java/com/takensoft/ums/web/UmsController.java (added)
+++ src/main/java/com/takensoft/ums/web/UmsController.java
This diff is skipped because there are too many other diffs.
 
src/main/resources/application.yml (added)
+++ src/main/resources/application.yml
This diff is skipped because there are too many other diffs.
 
src/main/resources/log4jdbc.log4j2.properties (added)
+++ src/main/resources/log4jdbc.log4j2.properties
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper-ora/ums/ums-SQL.xml (added)
+++ src/main/resources/mybatis/mapper-ora/ums/ums-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/accesCtrl/accesCtrl-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/accesCtrl/accesCtrl-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/author/author-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/author/author-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/bbs/bbsCn-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/bbs/bbsCn-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/bbs/bbsMng-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/bbs/bbsMng-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/bbs/bbsRouter-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/bbs/bbsRouter-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/bbs/bbsTypeMng-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/bbs/bbsTypeMng-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/bbs/cmnt-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/bbs/cmnt-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/bbs/search-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/bbs/search-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/bbs/wordMng-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/bbs/wordMng-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/cntnStats/cntnStats-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/cntnStats/cntnStats-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/codeManage/codeManage-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/codeManage/codeManage-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/common/Idgen-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/common/Idgen-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/common/file-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/common/file-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/common/fileManage-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/common/fileManage-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/contsType/contsType-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/contsType/contsType-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/dept/dept-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/dept/dept-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/entDscsnAply/entDscsnAply-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/entDscsnAply/entDscsnAply-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/entInfo/bplc-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/entInfo/bplc-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/entInfo/entInfo-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/entInfo/entInfo-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/invtDscsn/invtDscsn-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/invtDscsn/invtDscsn-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/main/adminMain-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/main/adminMain-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/main/governmentMain-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/main/governmentMain-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/mber/admMbr-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/mber/admMbr-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/mber/lgnHstry-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/mber/lgnHstry-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/mber/mber-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/mber/mber-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/mber/refresh-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/mber/refresh-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/menu/menu-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/menu/menu-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/menu/menuAuthor-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/menu/menuAuthor-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/popup/popup-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/popup/popup-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/prvcInqHstry/prvcInqHstry-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/prvcInqHstry/prvcInqHstry-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/rvwMttr/rvwMttr-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/rvwMttr/rvwMttr-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/rvwMttr/rvwMttrPrgrs-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/rvwMttr/rvwMttrPrgrs-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/resources/mybatis/mapper/statistics/statistics-SQL.xml (added)
+++ src/main/resources/mybatis/mapper/statistics/statistics-SQL.xml
This diff is skipped because there are too many other diffs.
 
src/main/webapp/META-INF/MANIFEST.MF (added)
+++ src/main/webapp/META-INF/MANIFEST.MF
This diff is skipped because there are too many other diffs.
Add a comment
List