guntaek 08-07
Merge branch 'master' of http://210.180.118.83/sjbang/lms_back
@e052c2a887bdf451e87feed9dacfe6aa8b4d5254
 
src/main/java/com/takensoft/ai_lms/common/confing/RedisConfig.java (added)
+++ src/main/java/com/takensoft/ai_lms/common/confing/RedisConfig.java
@@ -0,0 +1,26 @@
+package com.takensoft.ai_lms.common.confing;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+public class RedisConfig {
+
+    @Bean
+    public RedisConnectionFactory redisConnectionFactory() {
+        return new LettuceConnectionFactory();
+    }
+
+    @Bean
+    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(connectionFactory);
+        redisTemplate.setKeySerializer(new StringRedisSerializer());
+        redisTemplate.setValueSerializer(new StringRedisSerializer());
+        return redisTemplate;
+    }
+}
src/main/java/com/takensoft/ai_lms/common/confing/SecurityConfig.java
--- src/main/java/com/takensoft/ai_lms/common/confing/SecurityConfig.java
+++ src/main/java/com/takensoft/ai_lms/common/confing/SecurityConfig.java
@@ -6,6 +6,7 @@
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -29,16 +30,20 @@
     private final JwtUtil jwtUtil;
     private final CommonConfig commonConfig;
 
+    private final RedisTemplate<String, String> redisTemplate;
+
     private static String FRONT_URL; // 프론트 경로
     private static long JWT_ACCESSTIME; // access 토큰 유지 시간
     private static int COOKIE_TIME; // 쿠키 유지 시간
 
+
     public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JwtUtil jwtUtil, CommonConfig commonConfig,
-                          @Value("${frontUrl}") String fUrl, @Value("${spring.jwt.accessTime}") long aTime, @Value("${spring.jwt.refreshTime}") long rTime, @Value("${cookie.time}") int ctime
+                          RedisTemplate<String, String> redisTemplate, @Value("${frontUrl}") String fUrl, @Value("${spring.jwt.accessTime}") long aTime, @Value("${spring.jwt.refreshTime}") long rTime, @Value("${cookie.time}") int ctime
     ) {
         this.authenticationConfiguration = authenticationConfiguration;
         this.jwtUtil = jwtUtil;
         this.commonConfig = commonConfig;
+        this.redisTemplate = redisTemplate;
 
         this.FRONT_URL = fUrl;
         this.JWT_ACCESSTIME = aTime;
@@ -90,7 +95,7 @@
                 .anyRequest().authenticated()); // 나머지 경로는 인증 필요
 
         // jwt 필터 처리 적용
-        http.addFilterBefore(new JwtFilter(jwtUtil, commonConfig), LoginFilter.class); // 토큰 검증 필터
+        http.addFilterBefore(new JwtFilter(jwtUtil, commonConfig, redisTemplate), LoginFilter.class); // 토큰 검증 필터
         http.addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil, commonConfig, JWT_ACCESSTIME), UsernamePasswordAuthenticationFilter.class);
 
         return http.build();
src/main/java/com/takensoft/ai_lms/common/filter/JwtFilter.java
--- src/main/java/com/takensoft/ai_lms/common/filter/JwtFilter.java
+++ src/main/java/com/takensoft/ai_lms/common/filter/JwtFilter.java
@@ -11,6 +11,7 @@
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.RequiredArgsConstructor;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.security.authentication.InsufficientAuthenticationException;
@@ -30,6 +31,7 @@
 
     private final JwtUtil jwtUtil;
     private final CommonConfig commonConfig;
+    private final RedisTemplate<String, String> redisTemplate;
 
     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws jakarta.servlet.ServletException, IOException {
@@ -45,6 +47,12 @@
             if (jwtUtil.isExpired(accessToken)) {
                 throw new JwtException("Token expired");
             }
+
+            // Redis에서 토큰이 존재하는지 확인 (로그아웃된 토큰인지 확인)
+            if (redisTemplate.hasKey(accessToken)) {
+                throw new JwtException("Invalid token");
+            }
+
             // 토큰에서 페이로드 확인[ 발급시 명시 ]
             String category = jwtUtil.getCategory(accessToken);
             if (!category.equals("Authorization")) {
src/main/java/com/takensoft/ai_lms/lms/auth/service/AuthService.java
--- src/main/java/com/takensoft/ai_lms/lms/auth/service/AuthService.java
+++ src/main/java/com/takensoft/ai_lms/lms/auth/service/AuthService.java
@@ -1,5 +1,6 @@
 package com.takensoft.ai_lms.lms.auth.service;
 
+import com.takensoft.ai_lms.lms.auth.dto.LoginDTO;
 import com.takensoft.ai_lms.lms.auth.vo.UserVO;
 
 /**
@@ -10,4 +11,8 @@
  */
 public interface AuthService {
     int insertUser(UserVO userVO) throws Exception;
+
+    String login(LoginDTO loginDTO) throws Exception;
+
+    void logout(String token) throws Exception;
 }
src/main/java/com/takensoft/ai_lms/lms/auth/service/Impl/AuthServiceImpl.java
--- src/main/java/com/takensoft/ai_lms/lms/auth/service/Impl/AuthServiceImpl.java
+++ src/main/java/com/takensoft/ai_lms/lms/auth/service/Impl/AuthServiceImpl.java
@@ -3,10 +3,14 @@
 import com.takensoft.ai_lms.common.idgen.service.IdgenService;
 import com.takensoft.ai_lms.common.util.JwtUtil;
 import com.takensoft.ai_lms.lms.auth.dao.AuthDAO;
+import com.takensoft.ai_lms.lms.auth.dto.LoginDTO;
 import com.takensoft.ai_lms.lms.auth.service.AuthService;
 import com.takensoft.ai_lms.lms.auth.vo.UserVO;
 import lombok.RequiredArgsConstructor;
 import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -16,6 +20,8 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * @author  : 방선주
@@ -31,6 +37,10 @@
     private final AuthDAO authDAO;
     private final BCryptPasswordEncoder bCryptPasswordEncoder;
     private final JwtUtil jwtUtil;
+    @Value("${spring.jwt.accessTime}")
+    private long jwtAccessTime;
+
+    private final RedisTemplate<String, String> redisTemplate;
 
     private final IdgenService userIdgn;
 
@@ -72,6 +82,46 @@
         return result;
     }
 
+    /**
+     * @author  : 박민혁
+     * @since   : 2024.08.02
+     * 로그인 기능
+     */
+    @Override
+    public String login(LoginDTO loginDTO) throws Exception{
+        try {
+            UserDetails userDetails = loadUserByUsername(loginDTO.getLoginId());
+            if (userDetails != null && bCryptPasswordEncoder.matches(loginDTO.getPassword(), userDetails.getPassword())) {
+                UserVO userVO = (UserVO) userDetails;
+                return jwtUtil.createJwt(
+                        "access",
+                        userVO.getUsid(),
+                        userVO.getLoginId(),
+                        userVO.getUserNm(),
+                        userVO.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()),
+                        jwtAccessTime // 액세스 토큰 유효 시간
+                );
+            } else {
+                throw new UsernameNotFoundException("유효하지 않은 사용자 이름 또는 비밀번호");
+            }
+        } catch (UsernameNotFoundException e) {
+            throw new Exception("유효하지 않은 사용자 이름 또는 비밀번호", e);
+        }
+    }
+
+    @Override
+    public void logout(String token) throws Exception {
+        try {
+            // 토큰에서 사용자 ID 추출
+            String userId = jwtUtil.getUsid(token);
+
+            // Redis에 토큰을 저장하여 무효화 시킴
+            redisTemplate.opsForValue().set(token, userId, jwtAccessTime, TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            System.err.println("로그아웃 오류: " + e.getMessage());
+            throw new Exception("로그아웃 중 오류가 발생했습니다.", e);
+        }
+    }
 
 }
 
src/main/java/com/takensoft/ai_lms/lms/auth/web/AuthController.java
--- src/main/java/com/takensoft/ai_lms/lms/auth/web/AuthController.java
+++ src/main/java/com/takensoft/ai_lms/lms/auth/web/AuthController.java
@@ -2,15 +2,13 @@
 
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
+import com.takensoft.ai_lms.lms.auth.dto.LoginDTO;
 import com.takensoft.ai_lms.lms.auth.service.AuthService;
 import com.takensoft.ai_lms.lms.auth.vo.UserVO;
 import io.swagger.v3.oas.annotations.Operation;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-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.web.bind.annotation.*;
 
 /**
  * @author  : 방선주
@@ -62,5 +60,46 @@
 
     }
 
+    /**
+     * @author  : 박민혁
+     * @since   : 2024.08.02
+     * 로그인 기능
+     */
+    @PostMapping("/login.json")
+    @Operation(summary = "사용자 로그인")
+    public String login(@RequestBody LoginDTO loginDTO) {
+        Gson gson = new Gson();
+        JsonObject response = new JsonObject();
+
+        try {
+            String token = authService.login(loginDTO);
+            response.addProperty("status", "success");
+            response.addProperty("token", token);
+            return gson.toJson(response);
+        } catch (Exception e) {
+            response.addProperty("status", "error");
+            response.addProperty("message", e.getMessage());
+            return gson.toJson(response);
+        }
+    }
+
+    @PostMapping("/logout.json")
+    @Operation(summary = "사용자 로그아웃")
+    public String logout(@RequestHeader("Authorization") String token) {
+        Gson gson = new Gson();
+        JsonObject response = new JsonObject();
+
+        try {
+            authService.logout(token);
+
+            response.addProperty("status", "success");
+            response.addProperty("message", "성공적으로 로그아웃되었습니다.");
+            return gson.toJson(response);
+        } catch (Exception e) {
+            response.addProperty("status", "error");
+            response.addProperty("message", e.getMessage());
+            return gson.toJson(response);
+        }
+    }
 
 }
src/main/java/com/takensoft/ai_lms/lms/board/dao/BoardDAO.java
--- src/main/java/com/takensoft/ai_lms/lms/board/dao/BoardDAO.java
+++ src/main/java/com/takensoft/ai_lms/lms/board/dao/BoardDAO.java
@@ -1,6 +1,7 @@
 package com.takensoft.ai_lms.lms.board.dao;
 
 
+import com.takensoft.ai_lms.lms.board.vo.BoardStudentVO;
 import com.takensoft.ai_lms.lms.board.vo.BoardVO;
 import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
 
@@ -38,6 +39,29 @@
     // 게시글 검색
     List<HashMap<String, Object>> searchBoard(HashMap<String, Object> params) throws Exception;
 
+    // 학생 게시판 등록
+    int insertBoardStudent(BoardStudentVO boardStudentVO) throws Exception;
+
+    // 학생 게시판 삭세
+    int deleteBoardStudent(String bbsId) throws Exception;
+
+    // 학생 게시판 조회
+    List<BoardStudentVO> boardStudentList(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 수 조회
+    int boardStudentCount(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 조회 여부 체크
+    int updateBoardCheck(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 조회 여부 일괄 갱신
+    int updateAllBoardCheck(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 조회 안한 게시물 수 조회
+    int checkCount(HashMap<String, Object> params) throws Exception;
+
+
+
 
 
 }
src/main/java/com/takensoft/ai_lms/lms/board/service/BoardService.java
--- src/main/java/com/takensoft/ai_lms/lms/board/service/BoardService.java
+++ src/main/java/com/takensoft/ai_lms/lms/board/service/BoardService.java
@@ -1,5 +1,6 @@
 package com.takensoft.ai_lms.lms.board.service;
 
+import com.takensoft.ai_lms.lms.board.vo.BoardStudentVO;
 import com.takensoft.ai_lms.lms.board.vo.BoardVO;
 
 import java.util.HashMap;
@@ -34,4 +35,25 @@
 
     // 게시글 검색
     List<HashMap<String, Object>> searchBoard(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 등록
+    int insertBoardStudent(BoardStudentVO boardStudentVO) throws Exception;
+
+    // 학생 게시판 삭세
+    int deleteBoardStudent(String bbsId) throws Exception;
+
+    // 학생 게시판 전체 조회
+    List<BoardStudentVO> boardStudentList(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 수 조회
+    int boardStudentCount(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 조회 여부 체크
+    int updateBoardCheck(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 조회 여부 일괄 갱신
+    int updateAllBoardCheck(HashMap<String, Object> params) throws Exception;
+
+    // 학생 게시판 조회 안한 게시물 수 조회
+    int checkCount(HashMap<String, Object> params) throws Exception;
 }
src/main/java/com/takensoft/ai_lms/lms/board/service/impl/BoardServiceImpl.java
--- src/main/java/com/takensoft/ai_lms/lms/board/service/impl/BoardServiceImpl.java
+++ src/main/java/com/takensoft/ai_lms/lms/board/service/impl/BoardServiceImpl.java
@@ -3,6 +3,7 @@
 import com.takensoft.ai_lms.common.idgen.service.IdgenService;
 import com.takensoft.ai_lms.lms.board.dao.BoardDAO;
 import com.takensoft.ai_lms.lms.board.service.BoardService;
+import com.takensoft.ai_lms.lms.board.vo.BoardStudentVO;
 import com.takensoft.ai_lms.lms.board.vo.BoardVO;
 import lombok.RequiredArgsConstructor;
 import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
@@ -24,7 +25,15 @@
     public int insertBoard(BoardVO boardVO) throws Exception {
         String boardId = boardIdgn.getNextStringId();
         boardVO.setBbsId(boardId);
-        return boardDAO.insertBoard(boardVO);
+        int result = boardDAO.insertBoard(boardVO);
+
+        if(result > 0) {
+            BoardStudentVO boardStudentVO = new BoardStudentVO();
+            boardStudentVO.setBbsId(boardId);
+            boardDAO.insertBoardStudent(boardStudentVO);
+        }
+
+        return result;
     }
     // 게시글 전체 조회
     @Override
@@ -62,7 +71,13 @@
     // 게시글 삭제
     @Override
     public int deleteBoard(String bbsId) throws Exception{
-        return boardDAO.deleteBoard(bbsId);
+        int result = boardDAO.deleteBoard(bbsId);
+
+        if(result > 0) {
+            boardDAO.deleteBoardStudent(bbsId);
+        }
+
+        return result;
     }
 
     // 게시글 검색
@@ -72,6 +87,57 @@
     }
 
 
+    // 학생 게시판 등록
+    @Override
+    public int insertBoardStudent(BoardStudentVO boardStudentVO) throws Exception {
+        return boardDAO.insertBoardStudent(boardStudentVO);
+    }
+
+    // 학생 게시판 삭세
+    @Override
+    public int deleteBoardStudent(String bbsId) throws Exception {
+        return boardDAO.deleteBoardStudent(bbsId);
+    }
+
+
+    // 학생 게시판 조회
+    @Override
+    public List<BoardStudentVO> boardStudentList(HashMap<String, Object> params) throws Exception{
+        int page = Integer.parseInt(params.get("page").toString());
+        int pageSize = Integer.parseInt(params.get("pageSize").toString());
+
+        // 조회를 위한 startIndex 계산
+        int startIndex = (page - 1) * pageSize;
+        params.put("startIndex", startIndex);
+        params.put("pageSize", pageSize);
+        System.out.println(startIndex);
+        return boardDAO.boardStudentList(params);
+    }
+
+    // 학생 게시판 수 조회
+    @Override
+    public int boardStudentCount(HashMap<String, Object> params) throws Exception {
+        return boardDAO.boardStudentCount(params);
+    }
+
+    // 학생 게시판 조회 여부 체크
+    @Override
+    public int updateBoardCheck(HashMap<String, Object> params) throws Exception{
+        return boardDAO.updateBoardCheck(params);
+    }
+
+    // 학생 게시판 조회 여부 일괄 갱신
+    @Override
+    public int updateAllBoardCheck(HashMap<String, Object> params) throws Exception{
+        return boardDAO.updateAllBoardCheck(params);
+    }
+
+    // 학생 게시판 조회 안한 게시물 수 조회
+    @Override
+    public int checkCount(HashMap<String, Object> params) throws Exception{
+        return boardDAO.checkCount(params);
+    }
+
 
 
 }
 
src/main/java/com/takensoft/ai_lms/lms/board/vo/BoardStudentVO.java (added)
+++ src/main/java/com/takensoft/ai_lms/lms/board/vo/BoardStudentVO.java
@@ -0,0 +1,30 @@
+package com.takensoft.ai_lms.lms.board.vo;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author  : 박세훈
+ * since   : 2024.08.06
+ *
+ * 학생 게시판 정보 관련 VO
+ */
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class BoardStudentVO {
+
+    // 학생 아이디
+    private String stdId;
+
+    // 게시판 아이디
+    private String bbsId;
+
+    // 공지 조회 여부
+    private String checkYn;
+}
src/main/java/com/takensoft/ai_lms/lms/board/web/BoardController.java
--- src/main/java/com/takensoft/ai_lms/lms/board/web/BoardController.java
+++ src/main/java/com/takensoft/ai_lms/lms/board/web/BoardController.java
@@ -2,6 +2,7 @@
 
 
 import com.takensoft.ai_lms.lms.board.service.BoardService;
+import com.takensoft.ai_lms.lms.board.vo.BoardStudentVO;
 import com.takensoft.ai_lms.lms.board.vo.BoardVO;
 import com.takensoft.ai_lms.lms.file.service.FileService;
 import lombok.RequiredArgsConstructor;
@@ -141,5 +142,52 @@
     }
 
 
+    /**
+     * @author 박세훈
+     * @since 2024.08.06
+     *
+     * 학생 게시판 조회
+     */
+    @PostMapping("/boardStudentList.json")
+    public ResponseEntity<?> boardStudentList(@RequestBody HashMap<String, Object> params) throws Exception{
+        HashMap<String, Object> result = new HashMap<>();
+
+        // 전체 게시물 수 조회 및 추가
+        result.put("totalBoard", boardService.boardStudentCount(params));
+        result.put("result", boardService.boardStudentList(params));
+        result.put("unCheck", boardService.checkCount(params));
+
+        return new ResponseEntity<>(result, HttpStatus.OK);
+    }
+
+
+    /**
+     * @author 박세훈
+     * @since 2024.08.06
+     *
+     * 학생 게시판 조회 여부 체크
+     */
+    @PostMapping("/boardStudentCheck.json")
+    public int updateBoardCheck(@RequestBody HashMap<String, Object> params) throws Exception {
+        return boardService.updateBoardCheck(params);
+    }
+
+
+    /**
+     * @author 박세훈
+     * @since 2024.08.06
+     *
+     * 학생 게시판 조회 여부 일괄 갱신
+     */
+    @PostMapping("/allBoardStudentCheck.json")
+    public int updateAllBoardCheck(@RequestBody HashMap<String, Object> params) throws Exception {
+        return boardService.updateAllBoardCheck(params);
+    }
+
+
+
+
+
+
 
 }
src/main/java/com/takensoft/ai_lms/lms/problem/vo/ProblemVO.java
--- src/main/java/com/takensoft/ai_lms/lms/problem/vo/ProblemVO.java
+++ src/main/java/com/takensoft/ai_lms/lms/problem/vo/ProblemVO.java
@@ -32,4 +32,16 @@
     private String bookId;
     // 단원 아이디
     private String unitId;
+    // 문제 지표 1
+    private String prblmMtr1;
+    // 문제 지표 2
+    private String prblmMtr2;
+    // 문제 지표 3
+    private String prblmMtr3;
+    // 문제 지표 4
+    private String prblmMtr4;
+    // 문제 지표 5
+    private String prblmMtr5;
+    // 문제 지표 6
+    private String prblmMtr6;
 }
src/main/java/com/takensoft/ai_lms/lms/text/web/TextController.java
--- src/main/java/com/takensoft/ai_lms/lms/text/web/TextController.java
+++ src/main/java/com/takensoft/ai_lms/lms/text/web/TextController.java
@@ -90,6 +90,7 @@
      */
     @PostMapping(value = "/textUpdate.json")
     @Operation(summary = "지문 수정")
+
     public String textUpdate(@RequestBody TextVO textVO) throws Exception {
         Gson gson = new Gson();
         JsonObject response = new JsonObject();
src/main/java/com/takensoft/ai_lms/lms/word_book/dao/WordBookDAO.java
--- src/main/java/com/takensoft/ai_lms/lms/word_book/dao/WordBookDAO.java
+++ src/main/java/com/takensoft/ai_lms/lms/word_book/dao/WordBookDAO.java
@@ -3,6 +3,7 @@
 import com.takensoft.ai_lms.lms.word_book.vo.WordBookVO;
 import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
 
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -16,10 +17,12 @@
 public interface WordBookDAO {
 
     // 임시: 단어장 전체 목록 조회
-    List<WordBookVO> getAllWordBooks();
+    List<WordBookVO> getAllWordBooks(HashMap<String, Object> params) throws Exception;
+    int getWordBooksCount() throws Exception;
 
     // 책에 소속된 단어장 목록 조회
-    List<WordBookVO> getWordBooksByBookId(String bookId);
+    List<WordBookVO> getWordBooksByBookId(HashMap<String, Object> params) throws Exception;
+    int getWordBooksByBookIdCount(String bookId) throws Exception;
 
     // 아이디에 해당하는 단어장 조회
     WordBookVO getWordBookById(String wdBookId);
@@ -34,9 +37,11 @@
     int deleteWordBook(String wdBookId);
 
     // 단어장 검색(지문 이름으로 검색)
-    List<WordBookVO> getWordBooksByTextTitle(String textTitle);
+    List<WordBookVO> getWordBooksByTextTitle(HashMap<String, Object> params) throws Exception;
+    int getWordBooksByTextTitleCount(String textTitle) throws Exception;
 
     // 단어장 검색(단어로 검색)
-    List<WordBookVO> getWordBooksByWord(String word);
+    List<WordBookVO> getWordBooksByWord(HashMap<String, Object> params) throws Exception;
+    int getWordBooksByWordCount(String word) throws Exception;
 
 }
src/main/java/com/takensoft/ai_lms/lms/word_book/service/Impl/WordBookServiceImpl.java
--- src/main/java/com/takensoft/ai_lms/lms/word_book/service/Impl/WordBookServiceImpl.java
+++ src/main/java/com/takensoft/ai_lms/lms/word_book/service/Impl/WordBookServiceImpl.java
@@ -7,6 +7,7 @@
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -25,13 +26,32 @@
     private final IdgenService wordBookIdgn;
 
     @Override
-    public List<WordBookVO> getAllWordBooks() {
-        return wordBookDAO.getAllWordBooks();
+    public List<WordBookVO> getAllWordBooks(int page, int pageSize) throws Exception {
+        int startIndex = (page - 1) * pageSize;
+        HashMap<String, Object> params = new HashMap<>();
+        params.put("startIndex", startIndex);
+        params.put("pageSize", pageSize);
+        return wordBookDAO.getAllWordBooks(params);
     }
 
     @Override
-    public List<WordBookVO> getWordBooksByBookId(String bookId) {
-        return wordBookDAO.getWordBooksByBookId(bookId);
+    public int getWordBooksCount() throws Exception {
+        return wordBookDAO.getWordBooksCount();
+    }
+
+    @Override
+    public List<WordBookVO> getWordBooksByBookId(String bookId, int page, int pageSize) throws Exception {
+        int startIndex = (page - 1) * pageSize;
+        HashMap<String, Object> params = new HashMap<>();
+        params.put("bookId", bookId);
+        params.put("startIndex", startIndex);
+        params.put("pageSize", pageSize);
+        return wordBookDAO.getWordBooksByBookId(params);
+    }
+
+    @Override
+    public int getWordBooksByBookIdCount(String bookId) throws Exception {
+        return wordBookDAO.getWordBooksByBookIdCount(bookId);
     }
 
     @Override
@@ -57,13 +77,33 @@
     }
 
     @Override
-    public List<WordBookVO> getWordBooksByTextTitle(String textTitle) {
-        return wordBookDAO.getWordBooksByTextTitle(textTitle);
+    public List<WordBookVO> getWordBooksByTextTitle(String textTitle, int page, int pageSize) throws Exception {
+        int startIndex = (page - 1) * pageSize;
+        HashMap<String, Object> params = new HashMap<>();
+        params.put("textTitle", "%" + textTitle + "%");
+        params.put("startIndex", startIndex);
+        params.put("pageSize", pageSize);
+        return wordBookDAO.getWordBooksByTextTitle(params);
     }
 
     @Override
-    public List<WordBookVO> getWordBooksByWord(String word) {
-        return wordBookDAO.getWordBooksByWord(word);
+    public int getWordBooksByTextTitleCount(String textTitle) throws Exception {
+        return wordBookDAO.getWordBooksByTextTitleCount(textTitle);
+    }
+
+    @Override
+    public List<WordBookVO> getWordBooksByWord(String word, int page, int pageSize) throws Exception {
+        int startIndex = (page - 1) * pageSize;
+        HashMap<String, Object> params = new HashMap<>();
+        params.put("word", word);
+        params.put("startIndex", startIndex);
+        params.put("pageSize", pageSize);
+        return wordBookDAO.getWordBooksByWord(params);
+    }
+
+    @Override
+    public int getWordBooksByWordCount(String word) throws Exception {
+        return wordBookDAO.getWordBooksByWordCount(word);
     }
 
 }
src/main/java/com/takensoft/ai_lms/lms/word_book/service/WordBookService.java
--- src/main/java/com/takensoft/ai_lms/lms/word_book/service/WordBookService.java
+++ src/main/java/com/takensoft/ai_lms/lms/word_book/service/WordBookService.java
@@ -14,10 +14,12 @@
 public interface WordBookService {
 
     // 임시: 단어장 전체 목록 조회
-    List<WordBookVO> getAllWordBooks();
+    List<WordBookVO> getAllWordBooks(int page, int pageSize) throws Exception;
+    int getWordBooksCount() throws Exception;
 
     // 책에 소속된 단어장 목록 조회
-    List<WordBookVO> getWordBooksByBookId(String bookId);
+    List<WordBookVO> getWordBooksByBookId(String bookId, int page, int pageSize) throws Exception;
+    int getWordBooksByBookIdCount(String bookId) throws Exception;
 
     // 아이디에 해당하는 단어장 조회
     WordBookVO getWordBookById(String wdBookId);
@@ -32,10 +34,12 @@
     void deleteWordBook(String wdBookId);
 
     // 단어장 검색(지문 이름으로 검색)
-    List<WordBookVO> getWordBooksByTextTitle(String textTitle);
+    List<WordBookVO> getWordBooksByTextTitle(String textTitle, int page, int pageSize) throws Exception;
+    int getWordBooksByTextTitleCount(String textTitle) throws Exception;
 
     // 단어장 검색(단어로 검색)
-    List<WordBookVO> getWordBooksByWord(String word);
+    List<WordBookVO> getWordBooksByWord(String word, int page, int pageSize) throws Exception;
+    int getWordBooksByWordCount(String word) throws Exception;
 
 
 }
src/main/java/com/takensoft/ai_lms/lms/word_book/web/WordBookController.java
--- src/main/java/com/takensoft/ai_lms/lms/word_book/web/WordBookController.java
+++ src/main/java/com/takensoft/ai_lms/lms/word_book/web/WordBookController.java
@@ -6,6 +6,7 @@
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -26,15 +27,35 @@
 
     // 단어장 전체 목록 조회
     @PostMapping("/findAll.json")
-    public List<WordBookVO> getAllWordBooks() {
-        return wordBookService.getAllWordBooks();
+    public HashMap<String, Object> getAllWordBooks(@RequestBody HashMap<String, Object> params) throws Exception {
+        int page = (int) params.get("page");
+        int pageSize = (int) params.get("pageSize");
+
+        List<WordBookVO> wordBooks = wordBookService.getAllWordBooks(page, pageSize);
+        int totalWordBooks = wordBookService.getWordBooksCount();
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("wordBooks", wordBooks);
+        result.put("totalWordBooks", totalWordBooks);
+
+        return result;
     }
 
     // 책에 소속된 단어장 목록 조회
     @PostMapping("/findByBookId.json")
-    public List<WordBookVO> getWordBooksByBookId(@RequestBody Map<String, String> request) {
-        String bookId = request.get("bookId");
-        return wordBookService.getWordBooksByBookId(bookId);
+    public HashMap<String, Object> getWordBooksByBookId(@RequestBody HashMap<String, Object> params) throws Exception {
+        String bookId = (String) params.get("bookId");
+        int page = (int) params.get("page");
+        int pageSize = (int) params.get("pageSize");
+
+        List<WordBookVO> wordBooks = wordBookService.getWordBooksByBookId(bookId, page, pageSize);
+        int totalWordBooks = wordBookService.getWordBooksByBookIdCount(bookId);
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("wordBooks", wordBooks);
+        result.put("totalWordBooks", totalWordBooks);
+
+        return result;
     }
 
     // 아이디에 해당하는 단어장 조회
@@ -68,15 +89,36 @@
 
     // 단어장 검색(지문 이름으로 검색)
     @PostMapping("/findByTextTitle.json")
-    public List<WordBookVO> getWordBooksByTextTitle(@RequestBody Map<String, String> request) {
-        String textTitle = "%" + request.get("textTitle") + "%"; // 부분 검색 허용
-        return wordBookService.getWordBooksByTextTitle(textTitle);
+    public HashMap<String, Object> getWordBooksByTextTitle(@RequestBody HashMap<String, Object> params) throws Exception {
+        String textTitle = (String) params.get("textTitle");
+        int page = (int) params.get("page");
+        int pageSize = (int) params.get("pageSize");
+
+        List<WordBookVO> wordBooks = wordBookService.getWordBooksByTextTitle(textTitle, page, pageSize);
+        int totalWordBooks = wordBookService.getWordBooksByTextTitleCount(textTitle);
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("wordBooks", wordBooks);
+        result.put("totalWordBooks", totalWordBooks);
+
+        return result;
     }
 
     // 단어장 검색(단어로 검색)
     @PostMapping("/findByWord.json")
-    public List<WordBookVO> getWordBooksByWord(@RequestBody Map<String, String> request) {
-        return wordBookService.getWordBooksByWord(request.get("word"));
+    public HashMap<String, Object> getWordBooksByWord(@RequestBody HashMap<String, Object> params) throws Exception {
+        String word = (String) params.get("word");
+        int page = (int) params.get("page");
+        int pageSize = (int) params.get("pageSize");
+
+        List<WordBookVO> wordBooks = wordBookService.getWordBooksByWord(word, page, pageSize);
+        int totalWordBooks = wordBookService.getWordBooksByWordCount(word);
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("wordBooks", wordBooks);
+        result.put("totalWordBooks", totalWordBooks);
+
+        return result;
     }
 
 }
src/main/resources/application.yml
--- src/main/resources/application.yml
+++ src/main/resources/application.yml
@@ -47,6 +47,11 @@
     secret: 42b08045ac84dbcdf50e946bf8ad34d35af707979b3230cfb84fb8fe34236d2f
     accessTime: 600000      # 10분 600000
     refreshTime: 86400000   # 24시간 86400000
+  data:
+    redis:
+      host: localhost
+      port: 6379
+      timeout: 60000
 cookie:
   time: 86400
 
src/main/resources/mybatis/mapper/lms/board-SQL.xml
--- src/main/resources/mybatis/mapper/lms/board-SQL.xml
+++ src/main/resources/mybatis/mapper/lms/board-SQL.xml
@@ -63,6 +63,12 @@
         </collection>
     </resultMap>
 
+    <resultMap id="boardStudentResultMap" type="BoardStudentVO">
+        <result property="stdId" column="std_id" />
+        <result property="bbsId" column="bbs_id" />
+        <result property="checkYn" column="check_yn" />
+    </resultMap>
+
     <!--
         작성자 : 박세훈
         작성일 : 2024.07.25
@@ -102,16 +108,7 @@
         내 용 : 게시글 전체 조회
     -->
     <select id="findAllBoard"  resultMap="boardResultMap">
-        SELECT  b.bbs_id,
-                b.bbs_ttl,
-                b.bbs_cls,
-                b.bbs_cnt,
-                b.bbs_tm,
-                b.file_mng_id,
-                c.scls_id,
-                c.scls_nm,
-                u.user_id,
-                u.user_nm
+        SELECT  *
         FROM board b
         LEFT JOIN class c ON b.scls_id = c.scls_id
         LEFT JOIN users u ON c.user_id = u.user_id
@@ -141,16 +138,7 @@
         내 용 : 게시글 검색
     -->
     <select id="searchBoard" resultMap="boardResultMap">
-        SELECT  b.bbs_id,
-                b.bbs_ttl,
-                b.bbs_cls,
-                b.bbs_cnt,
-                b.bbs_tm,
-                b.file_mng_id,
-                c.scls_id,
-                c.scls_nm,
-                u.user_id,
-                u.user_nm
+        SELECT  *
         FROM board b
         LEFT JOIN class c ON b.scls_id = c.scls_id
         LEFT JOIN users u ON c.user_id = u.user_id
@@ -196,5 +184,97 @@
         DELETE FROM board WHERE bbs_id = #{bbsId}
     </delete>
 
+
+    <!--
+        작성자 : 박세훈
+        작성일 : 2024.08.06
+        내 용 : 학생 게시판 등록
+    -->
+    <insert id="insertBoardStudent" parameterType="BoardStudentVO">
+        INSERT INTO user_board (std_id,
+                                bbs_id,
+                                check_yn)
+        SELECT u.std_id, b.bbs_id, 'F'
+        FROM user_class u
+        JOIN board b ON u.scls_id = b.scls_id
+        ON CONFLICT (std_id, bbs_id)
+        DO NOTHING;
+    </insert>
+
+    <!--
+        작성자 : 박세훈
+        작성일 : 2024.08.06
+        내 용 : 학생 게시판 삭제
+    -->
+    <delete id="deleteBoardStudent" parameterType="String">
+        DELETE FROM user_board
+        WHERE bbs_id = #{bbsId}
+    </delete>
+
+    <!--
+        작성자 : 박세훈
+        작성일 : 2024.08.06
+        내 용 : 학생 게시판 조회
+    -->
+    <select id="boardStudentList" resultMap="boardResultMap" >
+        SELECT  *
+        FROM user_class uc
+        JOIN board b ON uc.scls_id = b.scls_id
+        LEFT JOIN class c ON b.scls_id = c.scls_id
+        LEFT JOIN users u ON c.user_id = u.user_id
+        WHERE uc.std_id = #{stdId}
+        ORDER BY b.bbs_id DESC
+        LIMIT #{pageSize} OFFSET #{startIndex}
+    </select>
+
+    <!--
+        작성자 : 박세훈
+        작성일 : 2024.08.06
+        내 용 : 학생 게시판 조회 여부 갱신
+    -->
+    <update id="updateBoardCheck" parameterType="BoardStudentVO">
+        UPDATE user_board
+        set check_yn = 'T'
+        WHERE bbs_id = #{bbsId}
+         AND std_id = #{stdId}
+         AND check_yn = 'F'
+    </update>
+
+    <!--
+        작성자 : 박세훈
+        작성일 : 2024.08.06
+        내 용 : 학생 게시판 조회 여부 일괄 갱신
+    -->
+    <update id="updateAllBoardCheck" parameterType="BoardStudentVO">
+        UPDATE user_board
+        set check_yn = 'T'
+        WHERE std_id = #{stdId}
+         AND check_yn = 'F'
+    </update>
+
+    <!--
+        작성자 : 박세훈
+        작성일 : 2024.08.06
+        내 용 : 학생 게시판 게시물 수 확인
+    -->
+    <select id="boardStudentCount" resultType="Integer">
+        SELECT COUNT(*)
+        FROM user_board
+        WHERE std_id = #{stdId}
+    </select>
+
+
+    <!--
+        작성자 : 박세훈
+        작성일 : 2024.08.06
+        내 용 : 학생 게시판 미조회 게시물 수 확인
+    -->
+    <select id="checkCount" resultType="Integer">
+        SELECT COUNT(*)
+        FROM user_board
+        WHERE check_yn = 'F' AND std_id = #{stdId}
+    </select>
+
+
 </mapper>
 
src/main/resources/mybatis/mapper/lms/problem-SQL.xml
--- src/main/resources/mybatis/mapper/lms/problem-SQL.xml
+++ src/main/resources/mybatis/mapper/lms/problem-SQL.xml
@@ -19,7 +19,13 @@
             prblm_ctgry_id,
             user_id,
             book_id,
-            unit_id
+            unit_id,
+            prblm_mtr1,
+            prblm_mtr2,
+            prblm_mtr3,
+            prblm_mtr4,
+            prblm_mtr5,
+            prblm_mtr6
         FROM problem
         WHERE prblm_id = #{prblmId}
     </select>
@@ -57,7 +63,13 @@
             prblm_ctgry_id,
             user_id,
             book_id,
-            unit_id
+            unit_id,
+            prblm_mtr1,
+            prblm_mtr2,
+            prblm_mtr3,
+            prblm_mtr4,
+            prblm_mtr5,
+            prblm_mtr6
         ) VALUES (
             #{prblmId},
             #{prblmExpln},
@@ -69,7 +81,13 @@
             #{prblmCtgryId},
             #{userId},
             #{bookId},
-            #{unitId}
+            #{unitId},
+            #{prblmMtr1},
+            #{prblmMtr2},
+            #{prblmMtr3},
+            #{prblmMtr4},
+            #{prblmMtr5},
+            #{prblmMtr6}
         )
     </insert>
 
@@ -111,7 +129,13 @@
             prblm_ctgry_id = #{prblmCtgryId},
             user_id = #{userId},
             book_id = #{bookId},
-            unit_id = #{unitId}
+            unit_id = #{unitId},
+            prblm_mtr1 = #{prblmMtr1},
+            prblm_mtr2 = #{prblmMtr2},
+            prblm_mtr3 = #{prblmMtr3},
+            prblm_mtr4 = #{prblmMtr4},
+            prblm_mtr5 = #{prblmMtr5},
+            prblm_mtr6 = #{prblmMtr6}
         WHERE prblm_id = #{prblmId}
     </update>
 
@@ -156,7 +180,13 @@
             prblm_ctgry_id,
             user_id,
             book_id,
-            unit_id
+            unit_id,
+            prblm_mtr1,
+            prblm_mtr2,
+            prblm_mtr3,
+            prblm_mtr4,
+            prblm_mtr5,
+            prblm_mtr6
         FROM problem
         WHERE 1 = 1
         <if test="option != null and keyword != null">
@@ -198,7 +228,13 @@
             p.prblm_ctgry_id AS prblmCtgryId,
             p.user_id AS userId,
             p.book_id AS bookId,
-            p.unit_id AS unitId
+            p.unit_id AS unitId,
+            p.prblm_mtr1 AS prblmMtr1,
+            p.prblm_mtr2 AS prblmMtr2,
+            p.prblm_mtr3 AS prblmMtr3,
+            p.prblm_mtr4 AS prblmMtr4,
+            p.prblm_mtr5 AS prblmMtr5,
+            p.prblm_mtr6 AS prblmMtr6
         FROM
             eval_problem ep
         JOIN
src/main/resources/mybatis/mapper/lms/schedule-SQL.xml
--- src/main/resources/mybatis/mapper/lms/schedule-SQL.xml
+++ src/main/resources/mybatis/mapper/lms/schedule-SQL.xml
@@ -44,6 +44,7 @@
 
         FROM schedule
         WHERE std_id = #{stdId}
+        AND schdl_dt::date = CURRENT_DATE
         ORDER BY schdl_dt DESC
     </select>
 
src/main/resources/mybatis/mapper/lms/word_book-SQL.xml
--- src/main/resources/mybatis/mapper/lms/word_book-SQL.xml
+++ src/main/resources/mybatis/mapper/lms/word_book-SQL.xml
@@ -16,6 +16,31 @@
         <result property="bookId" column="book_id"/>
     </resultMap>
 
+    <select id="getWordBooksCount" resultType="int">
+        SELECT COUNT(*)
+        FROM ai_lms.wordbook
+    </select>
+
+    <select id="getWordBooksByBookIdCount" resultType="int">
+        SELECT COUNT(*)
+        FROM wordbook
+        WHERE book_id = #{bookId}
+    </select>
+
+    <select id="getWordBooksByTextTitleCount" resultType="int">
+        SELECT COUNT(*)
+        FROM wordbook wb
+                 JOIN text t ON wb.text_id = t.text_id
+        WHERE t.text_ttl LIKE #{textTitle}
+    </select>
+
+    <select id="getWordBooksByWordCount" resultType="int">
+        SELECT COUNT(DISTINCT wb.wd_book_id)
+        FROM wordbook wb
+                 JOIN word w ON wb.wd_book_id = w.wd_book_id
+        WHERE w.wd_nm LIKE #{word}
+    </select>
+
     <select id="getAllWordBooks" resultMap="WordBookResultMap">
         SELECT
             wd_book_id,
@@ -24,9 +49,11 @@
             user_id,
             book_id
         FROM ai_lms.wordbook
+        ORDER BY wd_book_id DESC
+        LIMIT #{pageSize} OFFSET #{startIndex}
     </select>
 
-    <select id="getWordBooksByBookId" resultMap="WordBookResultMap">  <!-- 수정됨 -->
+    <select id="getWordBooksByBookId" resultMap="WordBookResultMap">
         SELECT
             wd_book_id,
             wd_book_type_id,
@@ -35,6 +62,8 @@
             book_id
         FROM wordbook
         WHERE book_id = #{bookId}
+        ORDER BY wd_book_id DESC
+        LIMIT #{pageSize} OFFSET #{startIndex}
     </select>
 
     <select id="getWordBookById" parameterType="string" resultMap="WordBookResultMap">
@@ -81,6 +110,8 @@
         FROM wordbook wb
         JOIN text t ON wb.text_id = t.text_id
         WHERE t.text_ttl LIKE #{textTitle}
+        ORDER BY wd_book_id DESC
+        LIMIT #{pageSize} OFFSET #{startIndex}
     </select>
 
     <select id="getWordBooksByWord" resultType="WordBookVO">
@@ -88,6 +119,8 @@
         FROM wordbook wb
         JOIN word w ON wb.wd_book_id = w.wd_book_id
         WHERE w.wd_nm LIKE #{word}
+        ORDER BY wd_book_id DESC
+        LIMIT #{pageSize} OFFSET #{startIndex}
     </select>
 
 </mapper>
(파일 끝에 줄바꿈 문자 없음)
Add a comment
List