Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.TwoSeaU.BaData.domain.trade.controller;

import com.TwoSeaU.BaData.domain.trade.service.PostService;
import com.TwoSeaU.BaData.global.response.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/trades")
public class MockController {
private final PostService postService;

@PostMapping("/mock/posts")
public ResponseEntity<ApiResponse<String>> createMockPost() {
return ResponseEntity.ok().body(ApiResponse.success(postService.generateGifticons()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ public ResponseEntity<ApiResponse<CursorPageResponse<PostResponse>>> getPosts(
return ResponseEntity.ok().body(ApiResponse.success(postSearchService.searchPosts(query, user == null ? null : user.getUsername(), cursor, size)));
}

@GetMapping("/posts/rdb")
public ResponseEntity<ApiResponse<CursorPageResponse<PostResponse>>> getPostsByRDB(
@RequestParam(required = false) Long cursor,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String query,
@AuthenticationPrincipal User user) {
return ResponseEntity.ok().body(ApiResponse.success(postSearchService.searchPostsByRDB(query, user == null ? null : user.getUsername(), cursor, size)));
}

@GetMapping("/posts/{userId}/{isSold}")
public ResponseEntity<ApiResponse<CursorPageResponse<PostResponse>>> getPostsByUserId(
@RequestParam(required = false) Long cursor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import com.TwoSeaU.BaData.domain.trade.dto.response.PostsResponse;
import com.TwoSeaU.BaData.domain.trade.dto.response.SaveRecommendLikesResponse;
import com.TwoSeaU.BaData.domain.trade.service.LikeService;
import com.TwoSeaU.BaData.domain.trade.service.RecommendService;
import com.TwoSeaU.BaData.domain.trade.service.recommend.GlobalRecommendService;
import com.TwoSeaU.BaData.domain.trade.service.recommend.doubleVector.RecommendServiceDouble;
import com.TwoSeaU.BaData.domain.trade.service.recommend.floatVector.RecommendServiceFloat;
import com.TwoSeaU.BaData.domain.trade.service.recommend.pgVector.RecommendServicePg;
import com.TwoSeaU.BaData.global.response.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand All @@ -15,16 +18,40 @@
@RequiredArgsConstructor
@RequestMapping("/api/v1/trades/posts/recommend")
public class RecommendController {
private final RecommendService recommendService;
private final RecommendServiceDouble doubleRecommendServiceDouble;
private final RecommendServiceFloat floatRecommendServiceFloat;
private final RecommendServicePg pgvectorRecommendServicePg;
private final GlobalRecommendService globalRecommendService;
Comment on lines +21 to +24
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

필드명과 타입 불일치

필드명에 타입 정보가 중복되어 있어 가독성이 떨어집니다.

-private final RecommendServiceDouble doubleRecommendServiceDouble;
-private final RecommendServiceFloat floatRecommendServiceFloat;
-private final RecommendServicePg pgvectorRecommendServicePg;
+private final RecommendServiceDouble recommendServiceDouble;
+private final RecommendServiceFloat recommendServiceFloat;
+private final RecommendServicePg recommendServicePg;

이에 따라 메서드 호출부도 수정해야 합니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private final RecommendServiceDouble doubleRecommendServiceDouble;
private final RecommendServiceFloat floatRecommendServiceFloat;
private final RecommendServicePg pgvectorRecommendServicePg;
private final GlobalRecommendService globalRecommendService;
private final RecommendServiceDouble recommendServiceDouble;
private final RecommendServiceFloat recommendServiceFloat;
private final RecommendServicePg recommendServicePg;
private final GlobalRecommendService globalRecommendService;
🤖 Prompt for AI Agents
In
src/main/java/com/TwoSeaU/BaData/domain/trade/controller/RecommendController.java
around lines 21 to 24, the field names redundantly include type information,
reducing readability. Rename the fields to remove type details so that names
clearly represent their purpose without duplicating type info. After renaming,
update all method calls and references to these fields accordingly to match the
new names.

private final LikeService likeService;

@GetMapping("/double")
public ResponseEntity<ApiResponse<PostsResponse>> recommendPostsByDouble(@AuthenticationPrincipal User user, @RequestParam(defaultValue = "true") boolean isStart) {
return ResponseEntity.ok().body(ApiResponse.success(doubleRecommendServiceDouble.recommendPosts(user == null ? null : user.getUsername(), isStart)));
}

@GetMapping("/float")
public ResponseEntity<ApiResponse<PostsResponse>> recommendPostsByFloat(@AuthenticationPrincipal User user, @RequestParam(defaultValue = "true") boolean isStart) {
return ResponseEntity.ok().body(ApiResponse.success(floatRecommendServiceFloat.recommendPostsByFloat(user == null ? null : user.getUsername(), isStart)));
}

//@GetMapping("/pgvector")
@GetMapping
public ResponseEntity<ApiResponse<PostsResponse>> recommendPosts(@AuthenticationPrincipal User user, @RequestParam(defaultValue = "true") boolean isStart) {
return ResponseEntity.ok().body(ApiResponse.success(recommendService.recommendPosts(user == null ? null : user.getUsername(), isStart)));
public ResponseEntity<ApiResponse<PostsResponse>> recommendPostsByPgvector(@AuthenticationPrincipal User user, @RequestParam(defaultValue = "true") boolean isStart) {
return ResponseEntity.ok().body(ApiResponse.success(pgvectorRecommendServicePg.recommendPostsBypgVector(user == null ? null : user.getUsername(), isStart)));
}

@PostMapping("/likes/{postId}")
public ResponseEntity<ApiResponse<SaveRecommendLikesResponse>> likeRecommendation(@AuthenticationPrincipal User user, @PathVariable Long postId) {
return ResponseEntity.ok().body(ApiResponse.success(likeService.likesAtRecommendation(user == null ? null : user.getUsername(), postId)));
}

@PatchMapping("/vector/update/all/double")
public ResponseEntity<ApiResponse<String>> updateAllPostForDouble() {
return ResponseEntity.ok().body(ApiResponse.success(globalRecommendService.updateAllDoubleVector()));
}

@PatchMapping("/vector/update/all/float")
public ResponseEntity<ApiResponse<String>> updateAllPostVectorForPgvector() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

메서드명과 기능 불일치

updateAllPostVectorForPgvector 메서드명이 실제로는 float와 pgVector를 모두 업데이트하는 기능과 일치하지 않습니다.

-public ResponseEntity<ApiResponse<String>> updateAllPostVectorForPgvector() {
+public ResponseEntity<ApiResponse<String>> updateAllPostVectorForFloatAndPg() {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public ResponseEntity<ApiResponse<String>> updateAllPostVectorForPgvector() {
public ResponseEntity<ApiResponse<String>> updateAllPostVectorForFloatAndPg() {
🤖 Prompt for AI Agents
In
src/main/java/com/TwoSeaU/BaData/domain/trade/controller/RecommendController.java
at line 54, the method name updateAllPostVectorForPgvector does not accurately
reflect its functionality, which updates both float and pgVector values. Rename
the method to a name that clearly indicates it updates all post vectors
including both float and pgVector types to improve code clarity and
maintainability.

return ResponseEntity.ok().body(ApiResponse.success(globalRecommendService.updateAllFloatAndPgVector()));
}
Comment on lines +48 to +56
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

벌크 벡터 업데이트 엔드포인트 보안 우려

벌크 벡터 업데이트 엔드포인트들이 인증 없이 노출되어 있어 보안상 위험할 수 있습니다.

관리자 권한 검증을 추가해주세요:

@PatchMapping("/vector/update/all/double")
-public ResponseEntity<ApiResponse<String>> updateAllPostForDouble() {
+public ResponseEntity<ApiResponse<String>> updateAllPostForDouble(@AuthenticationPrincipal User user) {
+    // 관리자 권한 검증 로직 추가
    return ResponseEntity.ok().body(ApiResponse.success(globalRecommendService.updateAllDoubleVector()));
}

또는 별도의 관리자 컨트롤러로 분리하는 것을 고려해주세요.

🤖 Prompt for AI Agents
In
src/main/java/com/TwoSeaU/BaData/domain/trade/controller/RecommendController.java
around lines 48 to 56, the bulk vector update endpoints lack authentication and
authorization checks, posing a security risk. Add an authorization check to
ensure only users with admin privileges can access these endpoints, such as
using a security annotation like @PreAuthorize("hasRole('ADMIN')") or
equivalent. Alternatively, move these endpoints to a separate controller
dedicated to admin operations and secure that controller accordingly.

}
17 changes: 12 additions & 5 deletions src/main/java/com/TwoSeaU/BaData/domain/trade/entity/Gifticon.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ public class Gifticon extends Post{
@Column(nullable = false)
private String partner;

private double[] vector;
private double[] doubleVector;

private float[] floatVector;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id", nullable = false)
Expand All @@ -34,16 +36,21 @@ public class Gifticon extends Post{
public Gifticon(final User user, final String title, final String comment, final BigDecimal price,
final LocalDate deadLine, final String postImage, final Boolean isSold,
final String couponNumber, final String partner, final GifticonCategory category,
final double[] vector) {
final double[] doubleVector, final float[] floatVector) {
super(user, title, comment, price, deadLine, postImage, isSold);
this.couponNumber = couponNumber;
this.partner = partner;
this.category = category;
this.vector = vector;
this.doubleVector = doubleVector;
this.floatVector = floatVector;
}

public void updateDoubleVector(final double[] doubleVector) {
this.doubleVector = doubleVector;
}

public void updateVector(final double[] vector) {
this.vector = vector;
public void updateFloatVector(final float[] floatVector) {
this.floatVector = floatVector;
}
Comment on lines +48 to 54
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

벡터 차원 검증 필요

벡터 업데이트 시 예상 차원과 일치하는지 검증이 없습니다. 잘못된 차원의 벡터가 저장되면 추천 시스템에서 오류가 발생할 수 있습니다.

     public void updateDoubleVector(final double[] doubleVector) {
+        // 예상 벡터 차원 검증 추가
+        if (doubleVector != null && doubleVector.length != EXPECTED_VECTOR_SIZE) {
+            throw new IllegalArgumentException("Invalid vector dimension: " + doubleVector.length);
+        }
         this.doubleVector = doubleVector;
     }
 
     public void updateFloatVector(final float[] floatVector) {
+        if (floatVector != null && floatVector.length != EXPECTED_VECTOR_SIZE) {
+            throw new IllegalArgumentException("Invalid vector dimension: " + floatVector.length);
+        }
         this.floatVector = floatVector;
     }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/entity/Gifticon.java between
lines 48 and 54, the updateDoubleVector and updateFloatVector methods lack
validation for the vector dimensions. Add checks to verify that the input vector
length matches the expected dimension before assigning it to the class fields.
If the dimension does not match, throw an appropriate exception or handle the
error to prevent storing invalid vectors.


public void updateBarcodeViewTime(final LocalDateTime barcodeViewTime) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.TwoSeaU.BaData.domain.trade.entity;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Table(name = "post_vector")
public class PostVector {
@Id
private Long id;

@Column(name = "vector_pg", columnDefinition = "vector(57)")
private float[] vectorPg;
Comment on lines +18 to +19
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

벡터 차원 수를 검증하세요.

vector(57) 차원이 하드코딩되어 있습니다. 실제 벡터화된 특성의 차원 수와 일치하는지 확인이 필요합니다.

벡터 차원을 확인하기 위해 다음 스크립트를 실행하세요:


🏁 Script executed:

#!/bin/bash
# 벡터화 서비스에서 실제 생성되는 벡터 차원 확인
ast-grep --pattern 'vectorizePost($$$) {
  $$$
  return vectorUtils.concatenate($$$);
}'

# 카테고리와 파트너 인덱스 맵의 크기 확인
rg -A 3 "categoryToIndex.*put|partnerToIndex.*put"

Length of output: 2853


🏁 Script executed:

#!/bin/bash
# 전체 PostVectorizer 클래스 내용 및 벡터화 메서드 확인
sed -n '1,200p' src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java

# vectorizePost 메서드 시그니처와 내부 concatenate 호출 위치 확인
rg "vectorizePost" -A5 src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java
rg "concatenate" -A5 src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java

# 카테고리 및 제휴사 리스트 초기화 위치 확인
rg "List<.*categories" -A3 src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java
rg "List<.*partners" -A3 src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostVectorizer.java

Length of output: 4581


벡터 차원 크기 검증 및 상수화 필요

PostVector 엔티티의 @Column(columnDefinition = "vector(57)")에 하드코딩된 57이 실제 벡터화 로직과 일치하는지 반드시 확인하세요.
현재 vectorizePost(...) 메서드는
• 카테고리 수 (categoryToIndex.size())
• 제휴사 수 (partnerToIndex.size())
• 수치형 특성 2개
를 합쳐 벡터를 생성하므로, 총 차원 수는 (카테고리 개수 + 제휴사 개수 + 2)가 됩니다.
이 값이 57과 동일한지 점검하고, 유지보수를 위해 별도 상수 또는 설정값으로 분리하는 것을 권장합니다.

선택 사항:

  • PostVector 생성 전용 factory 메서드를 추가해 엔티티 생성 방식을 일관성 있게 관리할 수 있습니다.

– src/main/java/com/TwoSeaU/BaData/domain/trade/entity/PostVector.java, 18–19번 라인 확인

🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/entity/PostVector.java at lines
18-19, the vector dimension size is hardcoded as 57 in the @Column annotation.
Verify that this matches the actual vector size calculated as
(categoryToIndex.size() + partnerToIndex.size() + 2). To fix, replace the
hardcoded 57 with a constant or configuration value representing the vector
dimension to ensure consistency and maintainability. Optionally, add a factory
method for creating PostVector instances to centralize and standardize entity
creation.


@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
private Post post;
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ public CursorPageResponse<PostResponse> searchPosts(final String query, final St
return searchByTitleAndComment(query, username, cursor, size);
}

public CursorPageResponse<PostResponse> searchPostsByRDB(final String query, final String username, final Long cursor, final int size) {

if (query != null && !query.isEmpty()) {
log.info("event-keyword-search, {}", query);
saveSearchHistoryIfUserExists(username, query);
}

return postRepository.searchPostsByKeyword(query, username, cursor, size);
}

private void saveSearchHistoryIfUserExists(final String username, final String query) {
if (username == null) {
return;
Expand Down
115 changes: 110 additions & 5 deletions src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import com.TwoSeaU.BaData.domain.trade.enums.PaymentStatus;
import com.TwoSeaU.BaData.domain.trade.exception.TradeException;
import com.TwoSeaU.BaData.domain.trade.repository.*;
import com.TwoSeaU.BaData.domain.trade.service.recommend.doubleVector.PostVectorizerDouble;
import com.TwoSeaU.BaData.domain.trade.service.recommend.floatVector.PostVectorizerFloat;
import com.TwoSeaU.BaData.domain.trade.service.recommend.pgVector.VectorUtilsPg;
import com.TwoSeaU.BaData.domain.user.entity.User;
import com.TwoSeaU.BaData.domain.user.exception.UserException;
import com.TwoSeaU.BaData.domain.user.repository.UserRepository;
Expand All @@ -22,9 +25,17 @@
import jakarta.servlet.http.HttpServletResponse;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
Expand All @@ -38,10 +49,14 @@ public class PostService {
private final PostLikesRepository postLikesRepository;
private final PaymentRepository paymentRepository;
private final ELAService elaService;
private final PostVectorizer postVectorizer;
private final PostVectorizerDouble postVectorizerDouble;
private final PostVectorizerFloat postVectorizerFloat;
private final VectorUtilsPg vectorUtilsPg;
private final S3ImageService s3ImageService;
private final OCRService ocrService;
private final PostDocumentRepository postDocumentRepository;
private final JdbcRepository jdbcRepository;
private final PartnerRepository partnerRepository;

private static final String COOKIE_NAME = "View_Post";

Expand Down Expand Up @@ -81,7 +96,15 @@ public SavePostResponse createGifticonPost(final SaveGifticonPostRequest saveGif
}

final String imageUrl = s3ImageService.saveImage(saveGifticonPostRequest.getFile(), "trades/gifticon/", saveGifticonPostRequest.getFile().getOriginalFilename());
final double[] vector = postVectorizer.vectorizePost(

final double[] doubleVector = postVectorizerDouble.vectorizePost(
saveGifticonPostRequest.getPrice(),
saveGifticonPostRequest.getDeadLine(),
category,
saveGifticonPostRequest.getPartner()
);

final float[] floatVector = postVectorizerFloat.vectorizePost(
saveGifticonPostRequest.getPrice(),
saveGifticonPostRequest.getDeadLine(),
category,
Expand All @@ -99,13 +122,19 @@ public SavePostResponse createGifticonPost(final SaveGifticonPostRequest saveGif
saveGifticonPostRequest.getCouponNumber(),
saveGifticonPostRequest.getPartner(),
category,
vector
doubleVector,
floatVector
//floatVector
//byteVector
Comment on lines +127 to +128
Copy link

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out code should be removed. These comment lines don't add value and clutter the codebase.

Suggested change
//floatVector
//byteVector

Copilot uses AI. Check for mistakes.
);

final Gifticon savedGifticon = gifticonRepository.save(gifticon);
final PostDocument postDocument = PostDocument.from(savedGifticon);
postDocumentRepository.save(postDocument);

//TODO: 여기
Copy link

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a TODO comment that should be addressed or removed before merging to production. The comment appears to be in Korean and doesn't provide clear guidance on what needs to be done.

Suggested change
//TODO: 여기

Copilot uses AI. Check for mistakes.
jdbcRepository.insertPostVector(savedGifticon.getId(), floatVector);

return SavePostResponse.builder()
.postId(savedGifticon.getId())
.build();
Expand Down Expand Up @@ -260,7 +289,14 @@ public SavePostResponse modifyPostGifticon(final Long postId, final UpdateGiftic
throw new GeneralException(TradeException.GIFTICON_NOT_FOUND);
}

final double[] vector = postVectorizer.vectorizePost(
final double[] doubleVector = postVectorizerDouble.vectorizePost(
updateGifticonPostRequest.getPrice(),
gifticon.getDeadLine(),
gifticon.getCategory(),
gifticon.getPartner()
);

final float[] floatVector = postVectorizerFloat.vectorizePost(
updateGifticonPostRequest.getPrice(),
gifticon.getDeadLine(),
gifticon.getCategory(),
Expand All @@ -272,14 +308,83 @@ public SavePostResponse modifyPostGifticon(final Long postId, final UpdateGiftic
updateGifticonPostRequest.getPrice()
);

gifticon.updateVector(vector);
gifticon.updateDoubleVector(doubleVector);
gifticon.updateFloatVector(floatVector);
jdbcRepository.updatePostVector(gifticon.getId(), floatVector);

final PostDocument postDocument = PostDocument.from(gifticon);
postDocumentRepository.save(postDocument);

return SavePostResponse.of(post.getId());
}

public String generateGifticons() {
List<GifticonCategory> categories = gifticonCategoryRepository.findAll();
User user = userRepository.findById(2L)
.orElseThrow(() -> new GeneralException(UserException.USER_NOT_FOUND));

List<LocalDate> dates = Stream.iterate(LocalDate.now().plusDays(0), date -> date.plusDays(2))
.limit(60)
.toList();

List<BigDecimal> prices = new ArrayList<>();
for (int price = 1000; price <= 30000; price += 1000) {
prices.add(BigDecimal.valueOf(price));
}

int index = 1;

for (GifticonCategory category : categories) {
log.info("category : " + category.getCategoryName());
List<Partner> partners = partnerRepository.findByCategoryId(category.getId());

for (Partner partner : partners) {
log.info("partner : " + partner.getPartner());

for (LocalDate date : dates) {
for (BigDecimal price : prices) {
final double[] doubleVector = postVectorizerDouble.vectorizePost(
price,
date,
category,
partner.getPartner()
);

final float[] floatVector = postVectorizerFloat.vectorizePost(
price,
date,
category,
partner.getPartner()
);

Gifticon gifticon = new Gifticon(
user,
partner.getPartner() + " 싸게 팔아요",
null,
price,
date,
"temp.png",
false,
index+"",
partner.getPartner(),
category,
doubleVector,
floatVector
);

gifticonRepository.save(gifticon);
jdbcRepository.insertPostVector(gifticon.getId(), floatVector);
log.info("post id : " + index);

index++;
}
}
}
}

return "success";
}
Comment on lines +321 to +386
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

대량 데이터 생성 메서드 성능 우려

generateGifticons 메서드가 중첩된 루프로 인해 매우 많은 데이터를 생성할 수 있어 성능과 메모리 사용량이 우려됩니다.

배치 처리와 트랜잭션 관리를 개선해주세요:

@Transactional
public String generateGifticons() {
    // 현재: categories × partners × dates × prices = 매우 큰 수
    // 예상: 10 × 5 × 60 × 30 = 90,000개 레코드
    
    // 배치 크기 제한 추가
    final int BATCH_SIZE = 1000;
    List<Gifticon> batch = new ArrayList<>(BATCH_SIZE);
    
    // ... existing logic ...
    
    if (batch.size() >= BATCH_SIZE) {
        gifticonRepository.saveAll(batch);
        // JDBC 배치 삽입도 고려
        batch.clear();
    }
}

또한 Mock 데이터 생성용이므로 프로덕션 환경에서는 비활성화하는 방법을 고려해주세요.

🤖 Prompt for AI Agents
In src/main/java/com/TwoSeaU/BaData/domain/trade/service/PostService.java
between lines 321 and 386, the generateGifticons method creates a very large
number of records using nested loops, which can cause performance and memory
issues. To fix this, implement batch processing by accumulating Gifticon
entities in a list and saving them in batches (e.g., every 1000 items) using
gifticonRepository.saveAll, and similarly batch insert vectors via
jdbcRepository. Also, annotate the method with @Transactional to manage
transactions efficiently. Finally, add a mechanism to disable this method in
production to avoid unintended large data generation.


private Post validateAndGetPost(final Long postId, final String username) {
final User user = getUserByUsername(username);
final Post post = getPostById(postId);
Expand Down
Loading
Loading