diff --git a/build.gradle b/build.gradle index 1d26fe12..94d4ae88 100644 --- a/build.gradle +++ b/build.gradle @@ -64,6 +64,7 @@ dependencies { implementation 'com.google.code.findbugs:jsr305:3.0.2' // webflux implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'io.netty:netty-resolver-dns-native-macos:4.1.68.Final:osx-aarch_64' } dependencyManagement { diff --git a/src/main/java/com/server/capple/config/security/SecurityConfig.java b/src/main/java/com/server/capple/config/security/SecurityConfig.java index 2410ca51..59104c32 100644 --- a/src/main/java/com/server/capple/config/security/SecurityConfig.java +++ b/src/main/java/com/server/capple/config/security/SecurityConfig.java @@ -58,6 +58,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/reports", "/reports/**").authenticated() .requestMatchers("/boards", "/boards/**").authenticated() .requestMatchers("/boardComments", "/boardComments/**").authenticated() + .requestMatchers("/dummy","/dummy/**").permitAll() .anyRequest().denyAll()); http .addFilterBefore(new JwtFilter(jwtService), UsernamePasswordAuthenticationFilter.class); diff --git a/src/main/java/com/server/capple/domain/board/repository/BoardHeartRedisRepository.java b/src/main/java/com/server/capple/domain/board/repository/BoardHeartRedisRepository.java index 7f1432fa..4ac19316 100644 --- a/src/main/java/com/server/capple/domain/board/repository/BoardHeartRedisRepository.java +++ b/src/main/java/com/server/capple/domain/board/repository/BoardHeartRedisRepository.java @@ -9,6 +9,7 @@ import java.io.Serializable; import java.time.LocalDateTime; import java.util.HashSet; +import java.util.Random; import java.util.Set; import static java.lang.Boolean.FALSE; @@ -26,7 +27,7 @@ public class BoardHeartRedisRepository implements Serializable { public Boolean toggleBoardHeart(Long boardId, Long memberId) { String key = BOARD_HEART_KEY_PREFIX + boardId.toString(); String member = MEMBER_KEY_PREFIX + memberId.toString(); - String createAtKey = key + ":" + member + ":createAt"; // member ID를 포함한 createAtKeyㄱ + String createAtKey = key + ":" + member + ":createAt"; // member ID를 포함한 createAtKey SetOperations setOperations = redisTemplate.opsForSet(); ValueOperations valueOperations = redisTemplate.opsForValue(); @@ -71,4 +72,22 @@ public Set getMemberHeartsBoard(Long memberId) { } return boardIds; } + + + //더미 데이터 생성용 + public void generateDummyBoardLikes(int boardCount) { + SetOperations setOperations = redisTemplate.opsForSet(); + ValueOperations valueOperations = redisTemplate.opsForValue(); + + Random random = new Random(); + for (int boardId = 0; boardId < boardCount; boardId++) { + for (int memberId = 1; memberId <= 10; memberId++) { + if(random.nextBoolean()) { + String key = BOARD_HEART_KEY_PREFIX + boardId; + String member = MEMBER_KEY_PREFIX + memberId; + setOperations.add(key, member); + } + } + } + } } \ No newline at end of file diff --git a/src/main/java/com/server/capple/domain/board/repository/BoardRepository.java b/src/main/java/com/server/capple/domain/board/repository/BoardRepository.java index 789beffb..c624ce94 100644 --- a/src/main/java/com/server/capple/domain/board/repository/BoardRepository.java +++ b/src/main/java/com/server/capple/domain/board/repository/BoardRepository.java @@ -6,6 +6,7 @@ import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import java.util.List; @@ -17,4 +18,7 @@ public interface BoardRepository extends JpaRepository { @Query("SELECT b FROM Board b WHERE b.content LIKE %:keyword%") List findBoardsByKeyword(String keyword); + + @Query(value = "SELECT generate_dummy_boards(:num)", nativeQuery = true) + void generateDummyBoards(@Param("num") int num); } diff --git a/src/main/java/com/server/capple/dummy/DummyController.java b/src/main/java/com/server/capple/dummy/DummyController.java new file mode 100644 index 00000000..c8ce6703 --- /dev/null +++ b/src/main/java/com/server/capple/dummy/DummyController.java @@ -0,0 +1,40 @@ +package com.server.capple.dummy; + +import com.server.capple.global.common.BaseResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "더미데이터 생성 API", description = "더미데이터 생성을 위한 API입니다.") +@RestController +@RequiredArgsConstructor +@RequestMapping("/dummy") +public class DummyController { + + private final DummyService dummyService; + + @Operation(summary = "게시글,게시글 좋아요 더미 생성 API", description = "게시글과 게시글 좋아요 더미를 생성합니다." + + "멤버 더미 먼저 생성 후 실행해주세요.") + @ApiResponses(value = { + @ApiResponse(responseCode = "COMMON200", description = "성공"), + }) + @PostMapping("/board") + private BaseResponse generateDummyBoards(@RequestParam("num") int num) { + return BaseResponse.onSuccess(dummyService.generateDummyBoards(num)); + } + + @Operation(summary = "멤버 더미 생성 API", description = "멤버 더미를 생성합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "COMMON200", description = "성공"), + }) + @PostMapping("/member") + private BaseResponse generateDummyMembers() { + return BaseResponse.onSuccess(dummyService.generateDummyMembers()); + } +} diff --git a/src/main/java/com/server/capple/dummy/DummyService.java b/src/main/java/com/server/capple/dummy/DummyService.java new file mode 100644 index 00000000..5c4b9bcd --- /dev/null +++ b/src/main/java/com/server/capple/dummy/DummyService.java @@ -0,0 +1,56 @@ +package com.server.capple.dummy; + + +import com.server.capple.domain.board.repository.BoardHeartRedisRepository; +import com.server.capple.domain.board.repository.BoardRepository; +import com.server.capple.domain.member.entity.Member; +import com.server.capple.domain.member.repository.MemberRepository; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +import static com.server.capple.domain.member.entity.Role.ROLE_ACADEMIER; + +@Service +@RequiredArgsConstructor +public class DummyService { + private final BoardRepository boardRepository; + private final BoardHeartRedisRepository boardHeartRedisRepository; + private final MemberRepository memberRepository; + + @PersistenceContext + private EntityManager em; + + @Transactional + public Object generateDummyBoards(int num) { + boardRepository.generateDummyBoards(num); + em.flush(); + boardHeartRedisRepository.generateDummyBoardLikes(num); + return null; + } + + @Transactional + public Object generateDummyMembers() { + List members = new ArrayList<>(); + + for (long i = 1; i <= 10; i++) { + Member member = Member.builder() + .id(i) + .nickname("User" + i) + .email("user" + i + "@example.com") + .sub("sub" + i) + .role(ROLE_ACADEMIER) + .build(); + + members.add(member); + } + + memberRepository.saveAll(members); + return null; + } +}