Skip to content

Conversation

@hyoinkang
Copy link
Contributor

@hyoinkang hyoinkang commented Dec 30, 2025

🚩 관련사항

성능 테스트를 위해 Post Seed 코드를 추가합니다.
#1024

📢 전달사항

  • 쿼리 성능 테스트를 위해 게시판 20개, 게시물 10만개, 댓글/대댓글 20만개, 좋아요 50만개를 시딩하는 것을 목표로 합니다.
  • 실제 상황과 비슷한 데이터를 넣을 수 있도록 시딩 전략을 구성하였습니다.
  • 로컬에서 테스트 하고 싶으시면 application.yml 다음과 같이 설정해서 돌리시면 됩니다.
spring:
  profiles:
    active: local
    include: seed

📸 스크린샷

한 번 돌릴 때, 제 로컬 환경에서는 총 80만개의 데이터를 시딩하는데 약 3분 53초 정도 걸렸습니다.
보드는 20개 시딩하기 때문에 얼마 안 걸렸던 것 같고 유저 시딩 고려하였을 때 5분 정도 걸릴 것으로 예상됩니다.
image

📃 진행사항

  • BoardSeeder 작성
  • PostSeeder 작성
  • CommentSeeder 작성
  • InteractionSeeder 작성

⚙️ 기타사항

커뮤니티라는 도메인의 특성을 고려하여 파레토 법칙과 90:9:1 법칙을 시딩 전략으로 사용하였습니다.
또한, 네트워크 내에서 발생하는 부익부 빈익빈 현상을 고려하여 댓글/대댓글 및 좋아요를 시딩하였습니다.
https://mediabrain.news/4884/

시딩 전략 관련한 자세한 내용 및 검증 내역은 노션에 따로 문서 작성해 두었습니다.

개발기간: 약 3일

- 게시판 생성 신청에 대해 승인이 완료된 일반게시판 20개를 생성하는 시딩 코드를 추가하였습니다.
- 유저가 존재하지 않는 경우 시딩에 실패합니다.
- 게시판이 이미 존재하는 경우 시딩에 실패합니다.
@hyoinkang hyoinkang self-assigned this Dec 30, 2025
@hyoinkang hyoinkang linked an issue Dec 30, 2025 that may be closed by this pull request
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @hyoinkang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 시스템의 성능 테스트를 지원하기 위해 대량의 더미 데이터를 생성하는 시딩 기능을 도입합니다. 현재는 다양한 게시판을 생성하는 BoardSeeder가 구현되었으며, 향후 게시물, 댓글, 좋아요 등으로 시딩 범위를 확장하여 실제 서비스 환경과 유사한 데이터 분포를 시뮬레이션할 예정입니다. 이는 시스템의 부하 테스트 및 최적화에 중요한 기반을 마련할 것입니다.

Highlights

  • 성능 테스트를 위한 데이터 시딩: 성능 테스트를 위해 게시판, 게시물, 댓글/대댓글, 좋아요 등 대량의 데이터를 시딩하는 기능을 추가합니다.
  • 시딩 목표: 게시판 20개, 게시물 10만개, 댓글/대댓글 20만개, 좋아요 50만개 시딩을 목표로 합니다.
  • 시딩 전략: 실제 상황과 유사한 데이터를 생성하기 위해 파레토 법칙과 90:9:1 법칙을 시딩 전략으로 활용합니다.
  • BoardSeeder 추가: 20개의 다양한 게시판을 생성하는 BoardSeeder 클래스가 새로 추가되었습니다.
  • PostSeedRunner 추가: 애플리케이션 시작 시 시딩 프로세스를 실행하는 PostSeedRunner (CommandLineRunner 구현체)가 추가되었습니다.
  • UserRepository 변경: UserRepository에 첫 번째 사용자를 조회하는 findTopBy() 메서드가 추가되었습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

postSeeder 추가를 위한 BoardSeeder 및 관련 코드 변경사항을 검토했습니다. 시딩 로직의 일관성과 코드 품질 향상을 위해 몇 가지 개선점을 제안합니다. BoardSeeder에서 중복되는 em.persist() 호출을 제거하고, 사용되지 않는 변수 및 파라미터를 정리하는 것을 권장합니다. 또한, PostSeedRunner에서 Lombok의 @requiredargsconstructor를 사용하여 생성자 코드를 간소화할 수 있습니다.

@github-actions
Copy link

github-actions bot commented Dec 30, 2025

Test Results Summary

 54 files   54 suites   14s ⏱️
250 tests 250 ✅ 0 💤 0 ❌
288 runs  288 ✅ 0 💤 0 ❌

Results for commit 7e4dcb8.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Dec 30, 2025

Migration Result 📦

Status Count
✅ Success 27
❌ Failed 0
⏳ Pending 0

Schema Validation Result 🔍

✅ No schema mismatches detected.

Results for commit 7e4dcb8

♻️ This comment has been updated with latest results.

- 파레토 법칙 및 Zipfian 분포(Skew) 적용을 위한 확률 유틸리티 작성
- 행동별(게시글, 댓글, 좋아요) 유저 분포 및 가중치 정의
- 전체 유저의 활동량 기반 분류 로직 구현
- BasePostSeeder: 시딩 전략 및 공통 로직 작성
- PostSeeder 일부 구현 및 설계/로직 검증 완료
- 기존 게시물 생성 로직과 비슷하게 데이터가 시딩되도록 구체화함
- 알림 발송 로직은 무시하였습니다.
1. 게시글 생성
1-1. 이미지가 있을 경우 uuidFile 저장 및 매핑
2. 게시글 작성자를 해당 게시글의 구독자로 설정
3. 게시물 생성에 대한 BOARD 알림 생성
- 기존 댓글 생성 로직과 비슷하게 데이터가 시딩되도록 코드 작성
- 네트워크 내에서 발생하는 선호적 연결 현상을 구현하기 위해 HotPostSampler를 활용
- 알림 발송 로직은 무시하였으며, 댓글 생성 로직은 아래와 같음
1. 댓글 생성
2. 댓글 작성자를 해당 게시물의 구독자로 설정
3. 댓글 생성에 대한 POST 알림 생성
- 기존 대댓글 생성 로직과 비슷하게 데이터가 시딩되도록 코드 작성
- 기존 좋아요 생성 로직과 비슷하게 데이터가 시딩되도록 코드 작성
- 네트워크 내에서 발생하는 선호적 연결 현상을 구현하기 위해 HotPostSampler를 활용 (좋아요)
- 대댓글 시딩은 댓글 시딩에서의 낙수 효과를 고려하여 랜덤하게 부모 댓글을 선택함
- 알림 발송 로직은 무시하였으며, 대댓글 생성 로직은 아래와 같음
1. 대댓글 생성
2. 댓글 생성에 대한 COMMENT 알림 생성
@hyoinkang hyoinkang marked this pull request as ready for review January 1, 2026 14:53
@bingle625 bingle625 added the D-1 label Jan 4, 2026
@github-actions github-actions bot added D-0 and removed D-1 labels Jan 5, 2026
Copy link
Contributor

@bingle625 bingle625 left a comment

Choose a reason for hiding this comment

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

수고 많으셨습니다!

  • 로컬에서 수행되는 것 확인했습니다.

Comment on lines +4 to +15
// Whale(70%), Dolphin(25%), Minnow(5%)
POST(0.70, 0.70 + 0.25, 3.0),

// Whale(40%), Dolphin(40%), Minnow(20%)
COMMENT(0.40, 0.40 + 0.40, 2.0),

// Whale(20%), Dolphin(30%), Minnow(50%)
LIKE(0.20, 0.20 + 0.30, 1.0);

// 누적 임계값 (0.0 ~ 1.0)
public final double whaleThreshold; // 이 값보다 작으면 Whale
public final double dolphinThreshold; // 이 값보다 작으면 Dolphin, 아니면 Minnow
Copy link
Contributor

Choose a reason for hiding this comment

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

[P5]
시딩 전략을 파레토 법칙, 메트칼프 법칙등을 사용하신게 흥미롭습니다.
어떤 관점에서 해당 전략들이 필요하다고 보셨나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

테스트 환경 구축 관련하여 자료 조사를 하다가 테스트 시나리오(데이터)가 실제 환경과 비슷한가가 환경 구축에 있어 중요하다는 글을 봤습니다. 커뮤니티라는 도메인의 데이터를 실제 환경과 맞도록 잘 반영하기 위해서 참고할만한 지표나 법칙들이 있는지 AI와의 대화나 서치 등을 통해 알아보았고, 이를 시딩 전략으로 적용하고자 하였습니다! 해당 시딩 전략을 통해 실제 환경과 비슷한 데이터들을 만들어, 실제로 나타날 수 있는 부하나 성능 병목을 더욱 정확히 측정하고자 하였습니다.

Comment on lines +63 to +79
jdbcTemplate.batchUpdate(sqlChildComment, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ChildCommentItem item = items.get(i);

ps.setString(1, item.id());
ps.setString(2, item.content());
ps.setString(3, item.parentId());
ps.setString(4, item.writerId());
ps.setTimestamp(5, Timestamp.valueOf(item.createdAt()));
ps.setTimestamp(6, Timestamp.valueOf(item.createdAt()));
}

@Override
public int getBatchSize() {
return items.size();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

[P5]
jdbc 템플릿을 이용하여 batch insert 진행하신 점 좋습니다,,!
이건 궁금한 점인데, 별도의 jdbc 설정 없이 batch insert가 진행되나요?
batch insert 일때랑 아닐 때랑 성능 차이가 있는지 확인할 수 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

DB url 설정 시 rewriteBatchedStatements=true 해당 옵션 붙여줘야하는 것으로 알고 있습니다..! 로그 찍어보니 현재 환경에서 배치는 적용이 되는데 Bulk Insert는 제대로 적용이 안 되고 있는 것 같아 그 부분은 추가로 확인해보겠습니다.

Copy link
Contributor Author

@hyoinkang hyoinkang Jan 5, 2026

Choose a reason for hiding this comment

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

rewriteBatchedStatements=true 해당 옵션을 켜서 Bulk Insert했을 때와 옵션이 꺼져있어 개별 Insert로 처리했을의 성능 차이를 로컬에서 분석한 결과, 유저와 보드만 시딩되어있고 나머지 테이블은 비어있는 상태에서 PostSeedRunner를 수행한 시간이 각각 148초와 230초로 약 1.55배의 성능 향상을 보였습니다. (35.6% 시간 단축)

url: jdbc:mysql://localhost:3306/seed_test?rewriteBatchedStatements=true

설정은 다음과 같이 옵션만 붙여주면 됩니다.

다만, 데이터가 쌓임에 따라 UUID 설정 방식으로 인해 오히려 Bulk Insert의 성능이 개별 Insert보다 느려지는 결과를 발견했습니다. 이는 병목 지점이 네트워크에서 Disk I/O로 변경됨에 따른 현상으로 보이며, TSID를 도입하여 해결할 수 있다고 하여 해당 라이브러리의 도입을 검토해볼까 합니다!

Copy link
Contributor

@KEEKE132 KEEKE132 left a comment

Choose a reason for hiding this comment

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

[P4]
로컬에서 제대로 동작 확인하였습니다.
다만 성능테스트 중 Post들의 created_at 데이터가 중복되는경우 특정 쿼리에서 문제가 발생하는데
해당 쿼리문을 수정하고 테스트해도 되지만 시딩코드에도 created_at이 중복되지 않도록 해도 좋을 것 같습니다.

관련 문서 링크입니다
https://www.notion.so/Post-2de3d138d33c8073b3bec635992bbbe7?source=copy_link

- CommandLineRunner 간의 실행 순서를 Order 어노테이션 활용하여 보장함
- PostSeeder에서 이미지 시딩 시 createdAt이 동일한 문제를 해결함
@hyoinkang hyoinkang merged commit d5a863a into dev Jan 6, 2026
6 checks passed
@hyoinkang hyoinkang deleted the chore/#1024/post-seed branch January 6, 2026 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Infra] post seeding

4 participants