From fae5896f1c659f295d9e65a722531e3eecbe1fb8 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Thu, 1 Jan 2026 23:07:55 +0900 Subject: [PATCH 01/14] =?UTF-8?q?chore:=20=ED=99=98=EA=B2=BD=EB=B3=80?= =?UTF-8?q?=EC=88=98=EC=97=90=EC=84=9C=20spring=20active=20profile=20?= =?UTF-8?q?=EC=9D=BD=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 20d8468..d62382f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,8 @@ spring.application.name=SearchWeb +# Active profile +spring.profiles.active=${SPRING_PROFILES_ACTIVE} + spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # mybatis settings mybatis.mapper-locations=classpath:mapper/*.xml From 7c0b3eaae8983d00a3c8b16eb46d838f8e4f5dde Mon Sep 17 00:00:00 2001 From: jin2304 Date: Thu, 1 Jan 2026 23:18:20 +0900 Subject: [PATCH 02/14] =?UTF-8?q?feat(db):=20DB=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20init.sql=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/db/init.sql | 155 +++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/main/resources/db/init.sql diff --git a/src/main/resources/db/init.sql b/src/main/resources/db/init.sql new file mode 100644 index 0000000..6a002f1 --- /dev/null +++ b/src/main/resources/db/init.sql @@ -0,0 +1,155 @@ +/* 테이블 초기화 */ +-- member 테이블 생성 +DROP TABLE IF EXISTS `member`; + +CREATE TABLE `member` ( + `memberId` int NOT NULL AUTO_INCREMENT, + `username` varchar(100) NOT NULL, + `password` varchar(100) NOT NULL, + `nickname` varchar(45) DEFAULT NULL, + `job` varchar(45) DEFAULT NULL, + `major` varchar(45) DEFAULT NULL, + `summary` varchar(45) DEFAULT NULL, + `role` varchar(45) DEFAULT 'ROLE_USER', + `email` varchar(100) DEFAULT NULL, + PRIMARY KEY (`memberId`), + KEY `idx_nickname` (`nickname`) +) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb3; + + +-- website 테이블 생성 +DROP TABLE IF EXISTS `website`; + +CREATE TABLE `website` ( + `websiteId` int NOT NULL, + `name` varchar(255) DEFAULT NULL, + `k_name` varchar(255) DEFAULT NULL, + `description` text, + `url` varchar(255) DEFAULT NULL, + `category` varchar(255) DEFAULT NULL, + `subcategory` varchar(255) DEFAULT NULL, + `rating` int DEFAULT '0', + PRIMARY KEY (`websiteId`), + KEY `idx_category` (`category`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + + +-- board 테이블 생성 +DROP TABLE IF EXISTS `board`; + +CREATE TABLE `board` ( + `boardId` int NOT NULL AUTO_INCREMENT, + `member_memberId` int NOT NULL, + `url` varchar(255) DEFAULT NULL, + `title` varchar(45) NOT NULL, + `summary` varchar(150) DEFAULT NULL, + `description` text, + `hashtags` varchar(255) DEFAULT NULL, + `likes_count` int DEFAULT '0', + `comments_count` int DEFAULT '0', + `bookmarks_count` int DEFAULT '0', + `views_count` int DEFAULT '0', + `created_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`boardId`), + KEY `memberId_idx` (`member_memberId`), + KEY `idx_created_date` (`created_date` DESC), + CONSTRAINT `memberId` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) +) ENGINE=InnoDB AUTO_INCREMENT=1000009 DEFAULT CHARSET=utf8mb3; + + +-- likes 테이블 생성 +DROP TABLE IF EXISTS `likes`; + +CREATE TABLE `likes` ( + `likes_Id` int NOT NULL AUTO_INCREMENT, + `board_boardId` int NOT NULL, + `member_memberId` int NOT NULL, + `is_Liked` tinyint(1) DEFAULT '0', + PRIMARY KEY (`likes_Id`), + UNIQUE KEY `unique_board_member` (`board_boardId`,`member_memberId`), + KEY `member_memberId_idx` (`member_memberId`) /*!80000 INVISIBLE */, + KEY `board_boardId` (`board_boardId`), + CONSTRAINT `fk_like_board` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`) ON DELETE CASCADE, + CONSTRAINT `fk_like_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) +) ENGINE=InnoDB AUTO_INCREMENT=112 DEFAULT CHARSET=utf8mb3; + + +-- folder 테이블 생성 +DROP TABLE IF EXISTS `folder`; + +CREATE TABLE `folder` ( + `folderId` int NOT NULL AUTO_INCREMENT, + `member_memberId` int NOT NULL, + `name` varchar(255) NOT NULL, + `tag` varchar(45) DEFAULT NULL, + `created_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`folderId`), + KEY `fk_folder_member_idx` (`member_memberId`), + CONSTRAINT `fk_folder_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + + +-- bookmark 테이블 생성 +DROP TABLE IF EXISTS `bookmark`; + +CREATE TABLE `bookmark` ( + `bookmarkId` int NOT NULL AUTO_INCREMENT, + `member_memberId` int NOT NULL, + `nickname` varchar(45) DEFAULT NULL, + `website_websiteId` int DEFAULT NULL, + `board_boardId` int DEFAULT NULL, + `folder_folderId` int DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `description` text, + `url` varchar(255) DEFAULT NULL, + `modified_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `tag` varchar(45) DEFAULT NULL, + PRIMARY KEY (`bookmarkId`), + KEY `fk_bookmark_member_idx` (`member_memberId`), + KEY `fk_bookmark_website1_idx` (`website_websiteId`), + KEY `fk_bookmark_board_idx` (`board_boardId`), + KEY `fk_bookmark_folder_idx` (`folder_folderId`), + CONSTRAINT `fk_bookmark_board` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`) ON DELETE CASCADE, + CONSTRAINT `fk_bookmark_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`), + CONSTRAINT `fk_bookmark_website1` FOREIGN KEY (`website_websiteId`) REFERENCES `website` (`websiteId`), + CONSTRAINT `fk_bookmark_folder` FOREIGN KEY (`folder_folderId`) REFERENCES `folder` (`folderId`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=1137 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + + +-- likebookmark 테이블 생성 +DROP TABLE IF EXISTS `likebookmark`; + +CREATE TABLE `likebookmark` ( + `likebookmarkId` int NOT NULL AUTO_INCREMENT, + `board_boardId` int NOT NULL, + `member_memberId` int NOT NULL, + `is_Liked` tinyint(1) DEFAULT '0', + `is_Bookmarked` tinyint(1) DEFAULT '0', + PRIMARY KEY (`likebookmarkId`), + UNIQUE KEY `unique_board_member` (`board_boardId`,`member_memberId`), + KEY `member_memberId_idx` (`member_memberId`) /*!80000 INVISIBLE */, + KEY `board_boardId` (`board_boardId`), + CONSTRAINT `board_boardId` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`), + CONSTRAINT `member_memberId` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb3; + + +-- comment 테이블 생성 +DROP TABLE IF EXISTS `comment`; + +CREATE TABLE `comment` ( + `commentId` int NOT NULL AUTO_INCREMENT, + `board_boardId` int NOT NULL, + `member_memberId` int NOT NULL, + `member_nickname` varchar(45) NOT NULL, + `member_job` varchar(45) DEFAULT NULL, + `member_major` varchar(45) DEFAULT NULL, + `content` text, + `created_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`commentId`), + KEY `board_boardId_idx` (`board_boardId`), + KEY `member_memberId_idx` (`member_memberId`), + CONSTRAINT `fk_comment_board` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`) ON DELETE CASCADE, + CONSTRAINT `fk_comment_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) +) ENGINE=InnoDB AUTO_INCREMENT=72 DEFAULT CHARSET=utf8mb3; \ No newline at end of file From 46257d342d739c26b5c6130980c6d618f89f5991 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Fri, 2 Jan 2026 20:33:33 +0900 Subject: [PATCH 03/14] =?UTF-8?q?feat(back):=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=B0=8F=20DTO=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/SearchWeb/folder/domain/Folder.java | 21 ++++++++ .../dto/request/FolderCreateRequestDto.java | 17 ++++++ .../dto/request/FolderSearchRequestDto.java | 16 ++++++ .../dto/request/FolderUpdateRequestDto.java | 17 ++++++ .../dto/response/FolderResponseDto.java | 53 +++++++++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 src/main/java/com/web/SearchWeb/folder/domain/Folder.java create mode 100644 src/main/java/com/web/SearchWeb/folder/dto/request/FolderCreateRequestDto.java create mode 100644 src/main/java/com/web/SearchWeb/folder/dto/request/FolderSearchRequestDto.java create mode 100644 src/main/java/com/web/SearchWeb/folder/dto/request/FolderUpdateRequestDto.java create mode 100644 src/main/java/com/web/SearchWeb/folder/dto/response/FolderResponseDto.java diff --git a/src/main/java/com/web/SearchWeb/folder/domain/Folder.java b/src/main/java/com/web/SearchWeb/folder/domain/Folder.java new file mode 100644 index 0000000..82bdb52 --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/domain/Folder.java @@ -0,0 +1,21 @@ +package com.web.SearchWeb.folder.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ToString +public class Folder { + private int folderId; + private int member_memberId; + private String name; + private String tag; + private String created_date; + private String modified_date; +} \ No newline at end of file diff --git a/src/main/java/com/web/SearchWeb/folder/dto/request/FolderCreateRequestDto.java b/src/main/java/com/web/SearchWeb/folder/dto/request/FolderCreateRequestDto.java new file mode 100644 index 0000000..69d594b --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/dto/request/FolderCreateRequestDto.java @@ -0,0 +1,17 @@ +package com.web.SearchWeb.folder.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Setter +@Getter +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class FolderCreateRequestDto { + private String name; + private String tag; +} diff --git a/src/main/java/com/web/SearchWeb/folder/dto/request/FolderSearchRequestDto.java b/src/main/java/com/web/SearchWeb/folder/dto/request/FolderSearchRequestDto.java new file mode 100644 index 0000000..30b6575 --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/dto/request/FolderSearchRequestDto.java @@ -0,0 +1,16 @@ +package com.web.SearchWeb.folder.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class FolderSearchRequestDto { + private int memberId; + private String tag; + private String sort; +} \ No newline at end of file diff --git a/src/main/java/com/web/SearchWeb/folder/dto/request/FolderUpdateRequestDto.java b/src/main/java/com/web/SearchWeb/folder/dto/request/FolderUpdateRequestDto.java new file mode 100644 index 0000000..8e67567 --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/dto/request/FolderUpdateRequestDto.java @@ -0,0 +1,17 @@ +package com.web.SearchWeb.folder.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Setter +@Getter +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class FolderUpdateRequestDto { + private String name; + private String tag; +} \ No newline at end of file diff --git a/src/main/java/com/web/SearchWeb/folder/dto/response/FolderResponseDto.java b/src/main/java/com/web/SearchWeb/folder/dto/response/FolderResponseDto.java new file mode 100644 index 0000000..db90171 --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/dto/response/FolderResponseDto.java @@ -0,0 +1,53 @@ +package com.web.SearchWeb.folder.dto.response; + +import com.web.SearchWeb.folder.domain.Folder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@ToString +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class FolderResponseDto { + private int folderId; + private String name; + private String tag; + private String created_date; + private String modified_date; + + /** + * Folder Entity -> FolderResponseDto 변환 메서드 + */ + public static FolderResponseDto from(Folder folder) { + if (folder == null) { + return null; + } + return FolderResponseDto.builder() + .folderId(folder.getFolderId()) + .name(folder.getName()) + .tag(folder.getTag()) + .created_date(folder.getCreated_date()) + .modified_date(folder.getModified_date()) + .build(); + } + + /** + * Folder Entity List -> FolderResponseDto List 변환 메서드 + */ + public static List fromList(List folders) { + if (folders == null) { + return null; + } + return folders.stream() + .map(FolderResponseDto::from) + .collect(Collectors.toList()); + } +} + From e5143fd7e38ad9100c166c2ea1d757ccbfad22a8 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Fri, 2 Jan 2026 20:35:15 +0900 Subject: [PATCH 04/14] =?UTF-8?q?feat(back):=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=ED=8F=B4=EB=8D=94=20CRUD=20+=20=ED=83=9C=EA=B7=B8=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../folder/controller/FolderController.java | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/main/java/com/web/SearchWeb/folder/controller/FolderController.java diff --git a/src/main/java/com/web/SearchWeb/folder/controller/FolderController.java b/src/main/java/com/web/SearchWeb/folder/controller/FolderController.java new file mode 100644 index 0000000..91573c8 --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/controller/FolderController.java @@ -0,0 +1,117 @@ +package com.web.SearchWeb.folder.controller; + +import com.web.SearchWeb.aop.OwnerCheck; +import com.web.SearchWeb.folder.dto.request.FolderCreateRequestDto; +import com.web.SearchWeb.folder.dto.request.FolderUpdateRequestDto; +import com.web.SearchWeb.folder.dto.response.FolderResponseDto; +import com.web.SearchWeb.folder.service.FolderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +/** + * 코드 작성자: + * - 서진영(jin2304) + * + * 코드 설명: + * - 사용자의 폴더 관리 API (CRUD + 태그 조회). + * - 모든 요청은 OwnerCheck AOP를 통해 권한을 검증. + * + * 코드 주요 기능: + * - 폴더 생성 + * - 폴더 단일 조회 + * - 폴더 목록 조회 + * - 폴더 수정 + * - 폴더 삭제 + * - 폴더 태그 목록 조회 + * + * 코드 작성일: + * - 2025.12.31 ~ 2026.01.02 + */ +@Controller +public class FolderController { + + private final FolderService folderService; + + @Autowired + public FolderController(FolderService folderService) { + this.folderService = folderService; + } + + + /** + * 폴더 생성 + */ + @PostMapping("/myPage/{memberId}/folder") + @OwnerCheck(idParam = "memberId", service = "memberService") + public ResponseEntity insertFolder(@PathVariable final int memberId, + @RequestBody FolderCreateRequestDto folderCreateRequestDto) { + int folderId = folderService.insertFolder(memberId, folderCreateRequestDto); + return ResponseEntity.ok(folderService.selectFolder(memberId, folderId)); + } + + + /** + * 폴더 단일 조회 + */ + @GetMapping("/myPage/{memberId}/folder/{folderId}") + @OwnerCheck(idParam = "memberId", service = "memberService") + public ResponseEntity getFolder(@PathVariable final int memberId, + @PathVariable final int folderId) { + FolderResponseDto folder = folderService.selectFolder(memberId, folderId); + return ResponseEntity.ok(folder); + } + + + /** + * 폴더 목록 조회 + */ + @GetMapping("/myPage/{memberId}/folders") + @OwnerCheck(idParam = "memberId", service = "memberService") + public ResponseEntity> getFolders(@PathVariable final int memberId, + @RequestParam(required = false, defaultValue = "All") String tag, + @RequestParam(required = false, defaultValue = "Newest") String sort) { + List folders = folderService.selectFolderList(memberId, tag, sort); + return ResponseEntity.ok(folders); + } + + + /** + * 폴더 수정 + */ + @PutMapping("/myPage/{memberId}/folder/{folderId}") + @OwnerCheck(idParam = "memberId", service = "memberService") + public ResponseEntity updateFolder(@PathVariable final int memberId, + @PathVariable final int folderId, + @RequestBody FolderUpdateRequestDto folderUpdateRequestDto) { + int result = folderService.updateFolder(memberId, folderId, folderUpdateRequestDto); + return ResponseEntity.ok(result); + } + + + /** + * 폴더 삭제 + */ + @DeleteMapping("/myPage/{memberId}/folder/{folderId}") + @OwnerCheck(idParam = "memberId", service = "memberService") + public ResponseEntity deleteFolder(@PathVariable final int memberId, + @PathVariable final int folderId) { + int result = folderService.deleteFolder(memberId, folderId); + return ResponseEntity.ok(result); + } + + + /** + * 폴더 태그 목록 조회 + */ + @GetMapping("/myPage/{memberId}/folderTags") + @OwnerCheck(idParam = "memberId", service = "memberService") + public ResponseEntity> getFolderTags(@PathVariable final int memberId) { + List tags = folderService.selectFolderTags(memberId); + return ResponseEntity.ok(tags); + } +} From 0b863645f4cb456f622a0526773bfdb64f4cfba4 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Fri, 2 Jan 2026 20:38:21 +0900 Subject: [PATCH 05/14] =?UTF-8?q?feat(back):=20=ED=8F=B4=EB=8D=94=20CRUD?= =?UTF-8?q?=20+=20=ED=83=9C=EA=B7=B8=EC=A1=B0=ED=9A=8C=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EB=B0=8F=20=EA=B5=AC=ED=98=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FolderService 인터페이스 정의 - FolderServiceImpl 구현 - 폴더 생성/조회/수정/삭제 비즈니스 로직 추가 --- .../folder/service/FolderService.java | 22 ++++++ .../folder/service/FolderServiceImpl.java | 79 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 src/main/java/com/web/SearchWeb/folder/service/FolderService.java create mode 100644 src/main/java/com/web/SearchWeb/folder/service/FolderServiceImpl.java diff --git a/src/main/java/com/web/SearchWeb/folder/service/FolderService.java b/src/main/java/com/web/SearchWeb/folder/service/FolderService.java new file mode 100644 index 0000000..70e3f2b --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/service/FolderService.java @@ -0,0 +1,22 @@ +package com.web.SearchWeb.folder.service; + +import com.web.SearchWeb.folder.dto.request.FolderCreateRequestDto; +import com.web.SearchWeb.folder.dto.response.FolderResponseDto; +import com.web.SearchWeb.folder.dto.request.FolderUpdateRequestDto; + +import java.util.List; + +public interface FolderService { + // 폴더 생성 + int insertFolder(int memberId, FolderCreateRequestDto folderCreateRequestDto); + // 폴더 단일 조회 + FolderResponseDto selectFolder(int memberId, int folderId); + // 폴더 목록 조회 + List selectFolderList(int memberId, String tag, String sort); + // 폴더 수정 + int updateFolder(int memberId, int folderId, FolderUpdateRequestDto folderUpdateRequestDto); + // 폴더 삭제 + int deleteFolder(int memberId, int folderId); + // 폴더 태그 목록 조회 + List selectFolderTags(int memberId); +} \ No newline at end of file diff --git a/src/main/java/com/web/SearchWeb/folder/service/FolderServiceImpl.java b/src/main/java/com/web/SearchWeb/folder/service/FolderServiceImpl.java new file mode 100644 index 0000000..584618b --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/service/FolderServiceImpl.java @@ -0,0 +1,79 @@ +package com.web.SearchWeb.folder.service; + +import com.web.SearchWeb.folder.dao.FolderDao; +import com.web.SearchWeb.folder.domain.Folder; +import com.web.SearchWeb.folder.dto.request.FolderCreateRequestDto; +import com.web.SearchWeb.folder.dto.request.FolderSearchRequestDto; +import com.web.SearchWeb.folder.dto.response.FolderResponseDto; +import com.web.SearchWeb.folder.dto.request.FolderUpdateRequestDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class FolderServiceImpl implements FolderService { + + private final FolderDao folderDao; + + @Autowired + public FolderServiceImpl(FolderDao folderDao) { + this.folderDao = folderDao; + } + + @Override + public int insertFolder(int memberId, FolderCreateRequestDto folderCreateRequestDto) { + Folder folder = Folder.builder() + .member_memberId(memberId) + .name(folderCreateRequestDto.getName()) + .tag(folderCreateRequestDto.getTag()) + .build(); + folderDao.insertFolder(folder); + // useGeneratedKeys로 생성된 folderId가 folder 객체에 자동 설정됨 + System.out.println("folder:" + folder); + return folder.getFolderId(); + } + + + @Override + public FolderResponseDto selectFolder(int memberId, int folderId) { + Folder folder = folderDao.selectFolder(memberId, folderId); + return FolderResponseDto.from(folder); + } + + + @Override + public List selectFolderList(int memberId, String tag, String sort) { + FolderSearchRequestDto searchRequest = FolderSearchRequestDto.builder() + .memberId(memberId) + .tag(tag) + .sort(sort) + .build(); + List folders = folderDao.selectFolderList(searchRequest); + return FolderResponseDto.fromList(folders); + } + + + @Override + public int updateFolder(int memberId, int folderId, FolderUpdateRequestDto folderUpdateRequestDto) { + Folder folder = Folder.builder() + .folderId(folderId) + .member_memberId(memberId) + .name(folderUpdateRequestDto.getName()) + .tag(folderUpdateRequestDto.getTag()) + .build(); + return folderDao.updateFolder(folder); + } + + + @Override + public int deleteFolder(int memberId, int folderId) { + return folderDao.deleteFolder(memberId, folderId); + } + + + @Override + public List selectFolderTags(int memberId) { + return folderDao.selectFolderTags(memberId); + } +} \ No newline at end of file From bd6d33ee74003445f3639b833764a310f48c2625 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Fri, 2 Jan 2026 21:48:47 +0900 Subject: [PATCH 06/14] =?UTF-8?q?feat(back):=20=ED=8F=B4=EB=8D=94=20CRUD?= =?UTF-8?q?=20+=20=ED=83=9C=EA=B7=B8=EC=A1=B0=ED=9A=8C=20DAO=20=EB=B0=8F?= =?UTF-8?q?=20MyBatis=20mapper=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/SearchWeb/folder/dao/FolderDao.java | 21 +++++ .../folder/dao/MybatisFolderDao.java | 57 ++++++++++++++ src/main/resources/mapper/folder-mapper.xml | 78 +++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 src/main/java/com/web/SearchWeb/folder/dao/FolderDao.java create mode 100644 src/main/java/com/web/SearchWeb/folder/dao/MybatisFolderDao.java create mode 100644 src/main/resources/mapper/folder-mapper.xml diff --git a/src/main/java/com/web/SearchWeb/folder/dao/FolderDao.java b/src/main/java/com/web/SearchWeb/folder/dao/FolderDao.java new file mode 100644 index 0000000..f0856dd --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/dao/FolderDao.java @@ -0,0 +1,21 @@ +package com.web.SearchWeb.folder.dao; + +import com.web.SearchWeb.folder.domain.Folder; +import com.web.SearchWeb.folder.dto.request.FolderSearchRequestDto; + +import java.util.List; + +public interface FolderDao { + // 폴더 생성 + int insertFolder(Folder folder); + // 폴더 단일 조회 + Folder selectFolder(int memberId, int folderId); + // 폴더 목록 조회 + List selectFolderList(FolderSearchRequestDto searchRequest); + // 폴더 수정 + int updateFolder(Folder folder); + // 폴더 삭제 + int deleteFolder(int memberId, int folderId); + // 폴더 태그 목록 조회 + List selectFolderTags(int memberId); +} \ No newline at end of file diff --git a/src/main/java/com/web/SearchWeb/folder/dao/MybatisFolderDao.java b/src/main/java/com/web/SearchWeb/folder/dao/MybatisFolderDao.java new file mode 100644 index 0000000..63b109f --- /dev/null +++ b/src/main/java/com/web/SearchWeb/folder/dao/MybatisFolderDao.java @@ -0,0 +1,57 @@ +package com.web.SearchWeb.folder.dao; + +import com.web.SearchWeb.folder.domain.Folder; +import com.web.SearchWeb.folder.dto.request.FolderSearchRequestDto; +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public class MybatisFolderDao implements FolderDao { + + private final FolderDao mapper; + + @Autowired + public MybatisFolderDao(SqlSession sqlSession) { + mapper = sqlSession.getMapper(FolderDao.class); + } + + + @Override + public int insertFolder(Folder folder) { + return mapper.insertFolder(folder); + } + + + @Override + public Folder selectFolder(int memberId, int folderId) { + return mapper.selectFolder(memberId, folderId); + } + + + @Override + public List selectFolderList(FolderSearchRequestDto searchRequest) { + return mapper.selectFolderList(searchRequest); + } + + + @Override + public int updateFolder(Folder folder) { + return mapper.updateFolder(folder); + } + + + @Override + public int deleteFolder(int memberId, int folderId) { + return mapper.deleteFolder(memberId, folderId); + } + + + @Override + public List selectFolderTags(int memberId) { + return mapper.selectFolderTags(memberId); + } +} + diff --git a/src/main/resources/mapper/folder-mapper.xml b/src/main/resources/mapper/folder-mapper.xml new file mode 100644 index 0000000..3f5ab4a --- /dev/null +++ b/src/main/resources/mapper/folder-mapper.xml @@ -0,0 +1,78 @@ + + + + + + + + INSERT INTO folder(member_memberId, name, tag) + VALUES(#{member_memberId}, #{name}, #{tag}) + + + + + + + + + + + + + + UPDATE folder + SET name = #{name}, + tag = #{tag} + WHERE folderId = #{folderId} + AND member_memberId = #{member_memberId} + + + + + + DELETE FROM folder + WHERE folderId = #{folderId} + AND member_memberId = #{memberId} + + + + + + + + From 65970b25a103ef04c5d0eb29cab9fdecca8379ee Mon Sep 17 00:00:00 2001 From: jin2304 Date: Fri, 2 Jan 2026 21:49:48 +0900 Subject: [PATCH 07/14] =?UTF-8?q?refactor(back):=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94=EA=B0=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EB=B6=81=EB=A7=88=ED=81=AC=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EB=B0=8F=20DTO=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SearchWeb/bookmark/domain/Bookmark.java | 1 + .../SearchWeb/bookmark/dto/BookmarkDto.java | 1 + .../dto/request/BookmarkSearchRequestDto.java | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 src/main/java/com/web/SearchWeb/bookmark/dto/request/BookmarkSearchRequestDto.java diff --git a/src/main/java/com/web/SearchWeb/bookmark/domain/Bookmark.java b/src/main/java/com/web/SearchWeb/bookmark/domain/Bookmark.java index 48a6b90..7414e93 100644 --- a/src/main/java/com/web/SearchWeb/bookmark/domain/Bookmark.java +++ b/src/main/java/com/web/SearchWeb/bookmark/domain/Bookmark.java @@ -13,6 +13,7 @@ public class Bookmark { private int member_memberId; private int website_websiteId; private int board_boardId; + private int folder_folderId; private String name; private String description; private String url; diff --git a/src/main/java/com/web/SearchWeb/bookmark/dto/BookmarkDto.java b/src/main/java/com/web/SearchWeb/bookmark/dto/BookmarkDto.java index c57f3f1..4cc7404 100644 --- a/src/main/java/com/web/SearchWeb/bookmark/dto/BookmarkDto.java +++ b/src/main/java/com/web/SearchWeb/bookmark/dto/BookmarkDto.java @@ -13,6 +13,7 @@ public class BookmarkDto { private int member_memberId; private int website_websiteId; private int board_boardId; + private Long folder_folderId; private String name; private String description; private String url; diff --git a/src/main/java/com/web/SearchWeb/bookmark/dto/request/BookmarkSearchRequestDto.java b/src/main/java/com/web/SearchWeb/bookmark/dto/request/BookmarkSearchRequestDto.java new file mode 100644 index 0000000..6c3ab77 --- /dev/null +++ b/src/main/java/com/web/SearchWeb/bookmark/dto/request/BookmarkSearchRequestDto.java @@ -0,0 +1,18 @@ +package com.web.SearchWeb.bookmark.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BookmarkSearchRequestDto { + private int memberId; + private String tag; + private String sort; + private String query; + private Long folderId; +} \ No newline at end of file From ad1471d7efbd953df2d9fdaed1ef168c765d1f7a Mon Sep 17 00:00:00 2001 From: jin2304 Date: Sat, 3 Jan 2026 01:32:38 +0900 Subject: [PATCH 08/14] =?UTF-8?q?refactor(back):=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94=EA=B0=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EB=B6=81=EB=A7=88=ED=81=AC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 북마크 목록 조회 - folderId 파라미터 추가 - 기존 분기 방식을 단일 selectBookmarkList()로 통합 - 북마크 태그 조회 - folderId 파라미터 추가 --- .../controller/BookmarkApiController.java | 2 +- .../mypage/controller/MyPageController.java | 22 +++++-------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/web/SearchWeb/bookmark/controller/BookmarkApiController.java b/src/main/java/com/web/SearchWeb/bookmark/controller/BookmarkApiController.java index ea30430..094374e 100644 --- a/src/main/java/com/web/SearchWeb/bookmark/controller/BookmarkApiController.java +++ b/src/main/java/com/web/SearchWeb/bookmark/controller/BookmarkApiController.java @@ -83,7 +83,7 @@ public ResponseEntity checkBookmark(@PathVariable final int websiteId){ **/ @GetMapping("/{memberId}/bookmarks") public List selectBookmarkList(@PathVariable final int memberId){ - return bookmarkService.selectBookmarkList(memberId, "Oldest"); //JSON 형태로 객체 리스트 반환 + return bookmarkService.selectBookmarkList(memberId, null, "Oldest", null, null); //JSON 형태로 객체 리스트 반환 } diff --git a/src/main/java/com/web/SearchWeb/mypage/controller/MyPageController.java b/src/main/java/com/web/SearchWeb/mypage/controller/MyPageController.java index e8e77fd..7e02f39 100644 --- a/src/main/java/com/web/SearchWeb/mypage/controller/MyPageController.java +++ b/src/main/java/com/web/SearchWeb/mypage/controller/MyPageController.java @@ -87,31 +87,21 @@ public ResponseEntity insertBookmark(@PathVariable final int member public ResponseEntity> getBookmarks(@PathVariable final int memberId, @RequestParam(required = false) String query, @RequestParam(defaultValue = "All") String tag, + @RequestParam(required = false) Long folderId, @RequestParam(defaultValue = "Oldest") String sort) { - List bookmarks; - if ((query == null || query.isEmpty()) && ("All".equals(tag) || tag == null)) { - // 1. 전체 북마크 조회 (태그x, 검색어x) - bookmarks = bookmarkService.selectBookmarkList(memberId, sort); - } else if (query != null && !query.isEmpty()) { //검색어가 있는 경우 - // 2. 검색어로 북마크 조회 (태그x, 검색어o), - // 3. 검색어와 특정 태그로 북마크 조회 (태그o, 검색어o) - bookmarks = bookmarkService.selectBookmarkListByQuery(memberId, tag, sort, query); - } else { - // 4. 특정 태그로 북마크 조회 (태그o, 검색어x) - bookmarks = bookmarkService.selectBookmarkListByTag(memberId, tag, sort); - } - + List bookmarks = bookmarkService.selectBookmarkList(memberId, tag, sort, query, folderId); return ResponseEntity.ok(bookmarks); } /** - * 태그 조회 + * 마이페이지 북마크 태그 조회 */ @GetMapping("/myPage/{memberId}/tags") @OwnerCheck(idParam = "memberId", service = "memberService") - public ResponseEntity> getTags(@PathVariable final int memberId) { - List tags = bookmarkService.selectTags(memberId); + public ResponseEntity> getTags(@PathVariable final int memberId, + @RequestParam(required = false) Long folderId) { + List tags = bookmarkService.selectTags(memberId, folderId); return ResponseEntity.ok(tags); } From 149b79013b1270312982c0c79f55f3c7dafe00f1 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Sat, 3 Jan 2026 01:38:24 +0900 Subject: [PATCH 09/14] =?UTF-8?q?refactor(back):=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94=EA=B0=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EB=B6=81=EB=A7=88=ED=81=AC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 북마크 목록 조회 - folderId 파라미터 추가 - 기존 분기 방식을 단일 selectBookmarkList()로 통합 - 북마크 태그 조회 - folderId 파라미터 추가 --- .../bookmark/service/BookmarkService.java | 10 ++--- .../bookmark/service/BookmarkServiceImpl.java | 43 ++++++------------- 2 files changed, 16 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/web/SearchWeb/bookmark/service/BookmarkService.java b/src/main/java/com/web/SearchWeb/bookmark/service/BookmarkService.java index bb4ad11..c7a98d3 100644 --- a/src/main/java/com/web/SearchWeb/bookmark/service/BookmarkService.java +++ b/src/main/java/com/web/SearchWeb/bookmark/service/BookmarkService.java @@ -17,12 +17,8 @@ public interface BookmarkService { int checkBoardBookmark(BoardBookmarkCheckDto checkDto); //북마크 단일 조회 Bookmark selectBookmark(int memberId, int bookmarkId); - //북마크 목록 조회 (시간) - List selectBookmarkList(int memberId, String sort); - //북마크 목록 조회 (시간, 태그) - List selectBookmarkListByTag(int memberId, String tag, String sort); - //북마크 목록 조회 (검색어) - List selectBookmarkListByQuery(int memberId, String tag, String sort, String query); + //북마크 목록 조회 + List selectBookmarkList(int memberId, String tag, String sort, String query, Long folderId); //북마크 추가 (메인리스트에서 추가) int insertBookmark(BookmarkDto bookmark); //북마크 추가 (마이페이지에서 추가) @@ -40,7 +36,7 @@ public interface BookmarkService { //북마크-웹사이트 조회 List selectBookmarkWebsite(int memberId); //사용자 태그 목록 조회 - List selectTags(int memberId); + List selectTags(int memberId, Long folderId); //게시글 북마크 여부 확인 int isBookmarked(int boardId, int memberId); } diff --git a/src/main/java/com/web/SearchWeb/bookmark/service/BookmarkServiceImpl.java b/src/main/java/com/web/SearchWeb/bookmark/service/BookmarkServiceImpl.java index d2b59cc..cb5f360 100644 --- a/src/main/java/com/web/SearchWeb/bookmark/service/BookmarkServiceImpl.java +++ b/src/main/java/com/web/SearchWeb/bookmark/service/BookmarkServiceImpl.java @@ -6,13 +6,11 @@ import com.web.SearchWeb.bookmark.dto.BookmarkCheckDto; import com.web.SearchWeb.bookmark.dto.BookmarkDto; import com.web.SearchWeb.bookmark.domain.BookmarkWebsite; +import com.web.SearchWeb.bookmark.dto.request.BookmarkSearchRequestDto; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; - -import java.util.HashMap; import java.util.List; -import java.util.Map; @Service public class BookmarkServiceImpl implements BookmarkService { @@ -52,33 +50,18 @@ public Bookmark selectBookmark(int memberId, int bookmarkId) { /** - * 북마크 목록 조회 (시간) - */ - @Override - public List selectBookmarkList(int memberId, String sort) { - return bookmarkDao.selectBookmarkList(memberId, sort); - } - - - /** - * 북마크 목록 조회 (시간, 태그) - */ - @Override - public List selectBookmarkListByTag(int memberId, String tag, String sort) { - Map params = new HashMap<>(); - params.put("member_memberId", memberId); - params.put("tag", tag); - params.put("sort", sort); - return bookmarkDao.selectBookmarkListByTag(params); - } - - - /** - * 북마크 목록 조회 (검색어) + * 북마크 목록 조회 */ @Override - public List selectBookmarkListByQuery(int memberId, String tag, String sort, String query) { - return bookmarkDao.selectBookmarkListByQuery(memberId, tag, sort, query); + public List selectBookmarkList(int memberId, String tag, String sort, String query, Long folderId) { + BookmarkSearchRequestDto searchRequest = BookmarkSearchRequestDto.builder() + .memberId(memberId) + .tag(tag) + .sort(sort) + .query(query) + .folderId(folderId) + .build(); + return bookmarkDao.selectBookmarkList(searchRequest); } @@ -159,8 +142,8 @@ public List selectBookmarkWebsite(int memberId) { * 사용자 태그 목록 조회 */ @Override - public List selectTags(int memberId) { - return bookmarkDao.selectTags(memberId); + public List selectTags(int memberId, Long folderId) { + return bookmarkDao.selectTags(memberId, folderId); } From 3d126d249192859e403eb5033f2a4400f1df4a1f Mon Sep 17 00:00:00 2001 From: jin2304 Date: Sat, 3 Jan 2026 02:01:32 +0900 Subject: [PATCH 10/14] =?UTF-8?q?refactor(back):=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94=EA=B0=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20DAO=20=EB=B0=8F=20Mybatis=20mapper=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 북마크 목록 조회 - folderId 파라미터 추가 - 기존 분기 방식을 단일 selectBookmarkList()로 통합 - 북마크 추가/수정/태그 조회 - folderId 파라미터 추가 --- .../SearchWeb/bookmark/dao/BookmarkDao.java | 12 +-- .../bookmark/dao/MybatisBookmarkDao.java | 30 ++----- src/main/resources/mapper/bookmark-mapper.xml | 78 ++++++------------- 3 files changed, 34 insertions(+), 86 deletions(-) diff --git a/src/main/java/com/web/SearchWeb/bookmark/dao/BookmarkDao.java b/src/main/java/com/web/SearchWeb/bookmark/dao/BookmarkDao.java index c073a1c..435d7cd 100644 --- a/src/main/java/com/web/SearchWeb/bookmark/dao/BookmarkDao.java +++ b/src/main/java/com/web/SearchWeb/bookmark/dao/BookmarkDao.java @@ -5,9 +5,9 @@ import com.web.SearchWeb.bookmark.dto.BookmarkCheckDto; import com.web.SearchWeb.bookmark.dto.BookmarkDto; import com.web.SearchWeb.bookmark.domain.BookmarkWebsite; +import com.web.SearchWeb.bookmark.dto.request.BookmarkSearchRequestDto; import java.util.List; -import java.util.Map; public interface BookmarkDao { //북마크 확인 @@ -16,12 +16,8 @@ public interface BookmarkDao { int checkBoardBookmark(BoardBookmarkCheckDto checkDto); //북마크 단일 조회 Bookmark selectBookmark(int memberId, int bookmarkId); - //북마크 목록 조회 (시간) - List selectBookmarkList(int memberId, String sort); - //북마크 목록 조회 (시간, 태그) - List selectBookmarkListByTag(Map params); - //북마크 목록 조회 (검색어) - List selectBookmarkListByQuery(int memberId, String tag, String sort, String query); + //북마크 목록 조회 + List selectBookmarkList(BookmarkSearchRequestDto searchRequest); //북마크 추가 int insertBookmark(BookmarkDto bookmark); //북마크 추가 (사용자 직접 추가) @@ -39,7 +35,7 @@ public interface BookmarkDao { //북마크-웹사이트 조회 List selectBookmarkWebsite(int memberId); //사용자 태그 목록 조회 - List selectTags(int memberId); + List selectTags(int memberId, Long folderId); //게시글 북마크 여부 확인 int isBookmarked(int boardId, int memberId); } diff --git a/src/main/java/com/web/SearchWeb/bookmark/dao/MybatisBookmarkDao.java b/src/main/java/com/web/SearchWeb/bookmark/dao/MybatisBookmarkDao.java index 12e9b4f..6247e63 100644 --- a/src/main/java/com/web/SearchWeb/bookmark/dao/MybatisBookmarkDao.java +++ b/src/main/java/com/web/SearchWeb/bookmark/dao/MybatisBookmarkDao.java @@ -5,12 +5,12 @@ import com.web.SearchWeb.bookmark.dto.BookmarkCheckDto; import com.web.SearchWeb.bookmark.dto.BookmarkDto; import com.web.SearchWeb.bookmark.domain.BookmarkWebsite; +import com.web.SearchWeb.bookmark.dto.request.BookmarkSearchRequestDto; import org.apache.ibatis.session.SqlSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import java.util.List; -import java.util.Map; @Repository public class MybatisBookmarkDao implements BookmarkDao { @@ -25,29 +25,11 @@ public MybatisBookmarkDao(SqlSession sqlSession) { /** - * 북마크 목록 조회 (시간) + * 북마크 목록 조회 */ @Override - public List selectBookmarkList(int memberId, String sort) { - return mapper.selectBookmarkList(memberId, sort); - } - - - /** - * //북마크 목록 조회 (시간, 태그) - */ - @Override - public List selectBookmarkListByTag(Map params) { - return mapper.selectBookmarkListByTag(params); - } - - - /** - * 북마크 목록 조회 (검색어) - */ - @Override - public List selectBookmarkListByQuery(int memberId, String tag, String sort, String query) { - return mapper.selectBookmarkListByQuery(memberId, tag, sort, query); + public List selectBookmarkList(BookmarkSearchRequestDto searchRequest) { + return mapper.selectBookmarkList(searchRequest); } @@ -153,8 +135,8 @@ public List selectBookmarkWebsite(int memberId) { * 사용자 태그 목록 조회 */ @Override - public List selectTags(int memberId) { - return mapper.selectTags(memberId); + public List selectTags(int memberId, Long folderId) { + return mapper.selectTags(memberId, folderId); } diff --git a/src/main/resources/mapper/bookmark-mapper.xml b/src/main/resources/mapper/bookmark-mapper.xml index a4047d9..870fb18 100644 --- a/src/main/resources/mapper/bookmark-mapper.xml +++ b/src/main/resources/mapper/bookmark-mapper.xml @@ -34,62 +34,28 @@ - - - - - - - select * from bookmark - WHERE member_memberId=#{member_memberId} - + WHERE member_memberId = #{memberId} + + AND folder_folderId = #{folderId} + + AND tag = #{tag} + + AND LOWER(name) LIKE CONCAT('%', LOWER(#{query}), '%') + ORDER BY - - modified_date ASC - modified_date DESC - - - - - - @@ -98,8 +64,8 @@ insert into - bookmark(member_memberId, website_websiteId, name, description, url) - values(#{member_memberId}, #{website_websiteId}, #{name}, #{description}, #{url}); + bookmark(member_memberId, website_websiteId, name, description, url, folder_folderId) + values(#{member_memberId}, #{website_websiteId}, #{name}, #{description}, #{url}, #{folder_folderId}); @@ -107,8 +73,8 @@ insert into - bookmark(member_memberId, name, description, url, tag) - values(#{member_memberId},#{name}, #{description}, #{url}, #{tag}); + bookmark(member_memberId, name, description, url, tag, folder_folderId) + values(#{member_memberId},#{name}, #{description}, #{url}, #{tag}, #{folder_folderId}); @@ -116,8 +82,8 @@ insert into - bookmark(member_memberId, board_boardId, name, description, url, tag) - values(#{member_memberId},#{board_boardId}, #{name}, #{description}, #{url}, #{tag}); + bookmark(member_memberId, board_boardId, name, description, url, tag, folder_folderId) + values(#{member_memberId},#{board_boardId}, #{name}, #{description}, #{url}, #{tag}, #{folder_folderId}); @@ -128,7 +94,8 @@ name = #{bookmarkDto.name}, description = #{bookmarkDto.description}, url = #{bookmarkDto.url}, - tag = #{bookmarkDto.tag} + tag = #{bookmarkDto.tag}, + folder_folderId = #{bookmarkDto.folder_folderId} WHERE bookmarkId = #{bookmarkId} @@ -171,11 +138,14 @@ - - select DISTINCT tag from bookmark - WHERE member_memberId=#{member_memberId} + WHERE member_memberId=#{memberId} + + AND folder_folderId = #{folderId} + AND tag IS NOT NULL And tag != '' From b12de2c7945f67210e9c3a6df1241e8f8d268e10 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Sat, 17 Jan 2026 18:04:48 +0900 Subject: [PATCH 11/14] =?UTF-8?q?refactor/SW-2/DB:=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=B2=A0=EC=9D=B4=EC=8A=A4=20=EC=8A=A4=ED=82=A4?= =?UTF-8?q?=EB=A7=88=20=EC=9D=BC=EA=B4=80=EC=84=B1=20=EB=B0=8F=20=EB=AC=B4?= =?UTF-8?q?=EA=B2=B0=EC=84=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 모든 테이블 문자 셋을 utf8mb4로 통일 - 멤버 삭제 시 외래 키 동작 하이브리드 전략 적용 - folder, bookmark, likes, likebookmark: ON DELETE CASCADE - board, comment: ON DELETE SET NULL (작성자 익명화) - AUTO_INCREMENT 시작값 제거 (초기화 스크립트 정리) --- src/main/resources/db/init.sql | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/resources/db/init.sql b/src/main/resources/db/init.sql index 6a002f1..1ac5c83 100644 --- a/src/main/resources/db/init.sql +++ b/src/main/resources/db/init.sql @@ -5,7 +5,7 @@ DROP TABLE IF EXISTS `member`; CREATE TABLE `member` ( `memberId` int NOT NULL AUTO_INCREMENT, `username` varchar(100) NOT NULL, - `password` varchar(100) NOT NULL, + `password` varchar(255) NOT NULL, `nickname` varchar(45) DEFAULT NULL, `job` varchar(45) DEFAULT NULL, `major` varchar(45) DEFAULT NULL, @@ -14,7 +14,7 @@ CREATE TABLE `member` ( `email` varchar(100) DEFAULT NULL, PRIMARY KEY (`memberId`), KEY `idx_nickname` (`nickname`) -) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb3; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- website 테이블 생성 @@ -39,7 +39,7 @@ DROP TABLE IF EXISTS `board`; CREATE TABLE `board` ( `boardId` int NOT NULL AUTO_INCREMENT, - `member_memberId` int NOT NULL, + `member_memberId` int DEFAULT NULL, `url` varchar(255) DEFAULT NULL, `title` varchar(45) NOT NULL, `summary` varchar(150) DEFAULT NULL, @@ -53,8 +53,8 @@ CREATE TABLE `board` ( PRIMARY KEY (`boardId`), KEY `memberId_idx` (`member_memberId`), KEY `idx_created_date` (`created_date` DESC), - CONSTRAINT `memberId` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) -) ENGINE=InnoDB AUTO_INCREMENT=1000009 DEFAULT CHARSET=utf8mb3; + CONSTRAINT `memberId` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- likes 테이블 생성 @@ -70,8 +70,8 @@ CREATE TABLE `likes` ( KEY `member_memberId_idx` (`member_memberId`) /*!80000 INVISIBLE */, KEY `board_boardId` (`board_boardId`), CONSTRAINT `fk_like_board` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`) ON DELETE CASCADE, - CONSTRAINT `fk_like_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) -) ENGINE=InnoDB AUTO_INCREMENT=112 DEFAULT CHARSET=utf8mb3; + CONSTRAINT `fk_like_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- folder 테이블 생성 @@ -111,10 +111,10 @@ CREATE TABLE `bookmark` ( KEY `fk_bookmark_board_idx` (`board_boardId`), KEY `fk_bookmark_folder_idx` (`folder_folderId`), CONSTRAINT `fk_bookmark_board` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`) ON DELETE CASCADE, - CONSTRAINT `fk_bookmark_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`), + CONSTRAINT `fk_bookmark_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) ON DELETE CASCADE, CONSTRAINT `fk_bookmark_website1` FOREIGN KEY (`website_websiteId`) REFERENCES `website` (`websiteId`), CONSTRAINT `fk_bookmark_folder` FOREIGN KEY (`folder_folderId`) REFERENCES `folder` (`folderId`) ON DELETE SET NULL -) ENGINE=InnoDB AUTO_INCREMENT=1137 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- likebookmark 테이블 생성 @@ -130,9 +130,9 @@ CREATE TABLE `likebookmark` ( UNIQUE KEY `unique_board_member` (`board_boardId`,`member_memberId`), KEY `member_memberId_idx` (`member_memberId`) /*!80000 INVISIBLE */, KEY `board_boardId` (`board_boardId`), - CONSTRAINT `board_boardId` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`), - CONSTRAINT `member_memberId` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) -) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb3; + CONSTRAINT `board_boardId` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`) ON DELETE CASCADE, + CONSTRAINT `member_memberId` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- comment 테이블 생성 @@ -141,7 +141,7 @@ DROP TABLE IF EXISTS `comment`; CREATE TABLE `comment` ( `commentId` int NOT NULL AUTO_INCREMENT, `board_boardId` int NOT NULL, - `member_memberId` int NOT NULL, + `member_memberId` int DEFAULT NULL, `member_nickname` varchar(45) NOT NULL, `member_job` varchar(45) DEFAULT NULL, `member_major` varchar(45) DEFAULT NULL, @@ -151,5 +151,5 @@ CREATE TABLE `comment` ( KEY `board_boardId_idx` (`board_boardId`), KEY `member_memberId_idx` (`member_memberId`), CONSTRAINT `fk_comment_board` FOREIGN KEY (`board_boardId`) REFERENCES `board` (`boardId`) ON DELETE CASCADE, - CONSTRAINT `fk_comment_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) -) ENGINE=InnoDB AUTO_INCREMENT=72 DEFAULT CHARSET=utf8mb3; \ No newline at end of file + CONSTRAINT `fk_comment_member` FOREIGN KEY (`member_memberId`) REFERENCES `member` (`memberId`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; \ No newline at end of file From 0fc0b6a4ac31ac799e2d89d9e086cf28c0db7983 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Sat, 17 Jan 2026 23:28:20 +0900 Subject: [PATCH 12/14] =?UTF-8?q?refactor/SW-2/Back(folder):=20=EB=82=A0?= =?UTF-8?q?=EC=A7=9C/=EC=8B=9C=EA=B0=84=20=EC=97=B0=EC=82=B0=20=EB=B0=8F?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EC=95=88=EC=A0=95=EC=84=B1=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=B4=20date=20=ED=95=84=EB=93=9C=EB=A5=BC=20Strin?= =?UTF-8?q?g=EC=97=90=EC=84=9C=20LocalDateTime=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../folder/controller/FolderController.java | 6 +++--- .../SearchWeb/folder/service/FolderService.java | 2 +- .../folder/service/FolderServiceImpl.java | 14 ++++++-------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/web/SearchWeb/folder/controller/FolderController.java b/src/main/java/com/web/SearchWeb/folder/controller/FolderController.java index 91573c8..d0220cb 100644 --- a/src/main/java/com/web/SearchWeb/folder/controller/FolderController.java +++ b/src/main/java/com/web/SearchWeb/folder/controller/FolderController.java @@ -49,9 +49,9 @@ public FolderController(FolderService folderService) { @PostMapping("/myPage/{memberId}/folder") @OwnerCheck(idParam = "memberId", service = "memberService") public ResponseEntity insertFolder(@PathVariable final int memberId, - @RequestBody FolderCreateRequestDto folderCreateRequestDto) { - int folderId = folderService.insertFolder(memberId, folderCreateRequestDto); - return ResponseEntity.ok(folderService.selectFolder(memberId, folderId)); + @RequestBody FolderCreateRequestDto folderCreateRequestDto) { + FolderResponseDto folder = folderService.insertFolder(memberId, folderCreateRequestDto); + return ResponseEntity.ok(folder); } diff --git a/src/main/java/com/web/SearchWeb/folder/service/FolderService.java b/src/main/java/com/web/SearchWeb/folder/service/FolderService.java index 70e3f2b..6731961 100644 --- a/src/main/java/com/web/SearchWeb/folder/service/FolderService.java +++ b/src/main/java/com/web/SearchWeb/folder/service/FolderService.java @@ -8,7 +8,7 @@ public interface FolderService { // 폴더 생성 - int insertFolder(int memberId, FolderCreateRequestDto folderCreateRequestDto); + FolderResponseDto insertFolder(int memberId, FolderCreateRequestDto folderCreateRequestDto); // 폴더 단일 조회 FolderResponseDto selectFolder(int memberId, int folderId); // 폴더 목록 조회 diff --git a/src/main/java/com/web/SearchWeb/folder/service/FolderServiceImpl.java b/src/main/java/com/web/SearchWeb/folder/service/FolderServiceImpl.java index 584618b..232ce4e 100644 --- a/src/main/java/com/web/SearchWeb/folder/service/FolderServiceImpl.java +++ b/src/main/java/com/web/SearchWeb/folder/service/FolderServiceImpl.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; import java.util.List; @Service @@ -22,26 +23,26 @@ public FolderServiceImpl(FolderDao folderDao) { } @Override - public int insertFolder(int memberId, FolderCreateRequestDto folderCreateRequestDto) { + public FolderResponseDto insertFolder(int memberId, FolderCreateRequestDto folderCreateRequestDto) { + LocalDateTime now = LocalDateTime.now(); Folder folder = Folder.builder() .member_memberId(memberId) .name(folderCreateRequestDto.getName()) .tag(folderCreateRequestDto.getTag()) + .created_date(now) + .modified_date(now) .build(); folderDao.insertFolder(folder); // useGeneratedKeys로 생성된 folderId가 folder 객체에 자동 설정됨 - System.out.println("folder:" + folder); - return folder.getFolderId(); + return FolderResponseDto.from(folder); } - @Override public FolderResponseDto selectFolder(int memberId, int folderId) { Folder folder = folderDao.selectFolder(memberId, folderId); return FolderResponseDto.from(folder); } - @Override public List selectFolderList(int memberId, String tag, String sort) { FolderSearchRequestDto searchRequest = FolderSearchRequestDto.builder() @@ -53,7 +54,6 @@ public List selectFolderList(int memberId, String tag, String return FolderResponseDto.fromList(folders); } - @Override public int updateFolder(int memberId, int folderId, FolderUpdateRequestDto folderUpdateRequestDto) { Folder folder = Folder.builder() @@ -65,13 +65,11 @@ public int updateFolder(int memberId, int folderId, FolderUpdateRequestDto folde return folderDao.updateFolder(folder); } - @Override public int deleteFolder(int memberId, int folderId) { return folderDao.deleteFolder(memberId, folderId); } - @Override public List selectFolderTags(int memberId) { return folderDao.selectFolderTags(memberId); From 8329ae8c9fa7d30efe51351bd28c6051849c5402 Mon Sep 17 00:00:00 2001 From: jin2304 Date: Sat, 17 Jan 2026 23:28:25 +0900 Subject: [PATCH 13/14] =?UTF-8?q?refactor/SW-2/Back(folder):=20=EB=82=A0?= =?UTF-8?q?=EC=A7=9C/=EC=8B=9C=EA=B0=84=20=EC=97=B0=EC=82=B0=20=EB=B0=8F?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EC=95=88=EC=A0=95=EC=84=B1=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=B4=20date=20=ED=95=84=EB=93=9C=EB=A5=BC=20Strin?= =?UTF-8?q?g=EC=97=90=EC=84=9C=20LocalDateTime=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/web/SearchWeb/folder/domain/Folder.java | 6 ++++-- .../SearchWeb/folder/dto/response/FolderResponseDto.java | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/web/SearchWeb/folder/domain/Folder.java b/src/main/java/com/web/SearchWeb/folder/domain/Folder.java index 82bdb52..15ec109 100644 --- a/src/main/java/com/web/SearchWeb/folder/domain/Folder.java +++ b/src/main/java/com/web/SearchWeb/folder/domain/Folder.java @@ -1,5 +1,7 @@ package com.web.SearchWeb.folder.domain; +import java.time.LocalDateTime; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -16,6 +18,6 @@ public class Folder { private int member_memberId; private String name; private String tag; - private String created_date; - private String modified_date; + private LocalDateTime created_date; + private LocalDateTime modified_date; } \ No newline at end of file diff --git a/src/main/java/com/web/SearchWeb/folder/dto/response/FolderResponseDto.java b/src/main/java/com/web/SearchWeb/folder/dto/response/FolderResponseDto.java index db90171..ae3e9b5 100644 --- a/src/main/java/com/web/SearchWeb/folder/dto/response/FolderResponseDto.java +++ b/src/main/java/com/web/SearchWeb/folder/dto/response/FolderResponseDto.java @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; import lombok.ToString; +import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @@ -19,8 +20,8 @@ public class FolderResponseDto { private int folderId; private String name; private String tag; - private String created_date; - private String modified_date; + private LocalDateTime created_date; + private LocalDateTime modified_date; /** * Folder Entity -> FolderResponseDto 변환 메서드 @@ -50,4 +51,3 @@ public static List fromList(List folders) { .collect(Collectors.toList()); } } - From f79a890770374cb8247f74f0d20a3cae25fcc6da Mon Sep 17 00:00:00 2001 From: jin2304 Date: Sun, 18 Jan 2026 00:10:17 +0900 Subject: [PATCH 14/14] =?UTF-8?q?refactor/SW-2/Back(bookmark):=20sort=20?= =?UTF-8?q?=EA=B0=92=EC=9D=B4=20'Newest'=20=EB=98=90=EB=8A=94=20'Oldest'?= =?UTF-8?q?=EA=B0=80=20=EC=95=84=EB=8B=8C=20=EA=B2=BD=EC=9A=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=EA=B0=92=20=EB=B0=A9=EC=96=B4=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/mapper/bookmark-mapper.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/mapper/bookmark-mapper.xml b/src/main/resources/mapper/bookmark-mapper.xml index 870fb18..ce69228 100644 --- a/src/main/resources/mapper/bookmark-mapper.xml +++ b/src/main/resources/mapper/bookmark-mapper.xml @@ -56,6 +56,9 @@ modified_date ASC + + modified_date DESC +