-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat/#828] gen 생성 bulk insert로 변경 #859
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
- GenRepository에 saveAll 메서드 명시적 선언 - ProvisioningContentsRepository에 saveAll 메서드 명시적 선언 - RawContentsRepository에 saveAll 메서드 명시적 선언 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- RawContentsService에 createRawContent, createAll 메서드 추가 - ProvisioningService에 createProvisioningContent, createAll 메서드 추가 - GenService에 createGen, createAll 메서드 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- AbstractGenSchedulingUseCase의 create 메서드를 3단계 bulk insert 방식으로 변경 1. RawContents 객체 생성 후 bulk insert 2. ProvisioningContents 객체 생성 후 bulk insert 3. Gen 객체 생성 후 bulk insert - AbstractGenSchedulingUseCaseTest를 변경된 Service 메서드에 맞게 수정 - 성능 개선: N개 콘텐츠에 대해 3N번 개별 INSERT → 3번 bulk INSERT로 개선 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Walkthrough서비스 계층에서 생성과 저장을 분리하고, 개별 생성 메서드를 배치 저장용 createAll 메서드로 보완했습니다. 저장소 인터페이스에 Changes
Sequence Diagram(s)sequenceDiagram
participant Scheduler
participant RawService as RawContentsService
participant RawRepo as RawContentsRepository
participant ProvService as ProvisioningService
participant ProvRepo as ProvisioningContentsRepository
participant GenService
participant GenRepo as GenRepository
Scheduler->>Scheduler: URL 수집 및 RawContents 객체 생성 루프
loop 각 URL
Scheduler->>RawService: createRawContent(url, category, region)
RawService-->>Scheduler: RawContents (미저장)
Scheduler->>Scheduler: rawContentsList에 추가
end
Scheduler->>RawService: createAll(rawContentsList)
RawService->>RawRepo: saveAll(rawContentsList)
RawRepo-->>Scheduler: 저장된 RawContents 리스트 (ID 포함)
Scheduler->>Scheduler: ProvisioningContents 객체 생성 루프
loop 각 RawContents
Scheduler->>ProvService: createProvisioningContent(rawContents)
ProvService-->>Scheduler: ProvisioningContents (미저장)
Scheduler->>Scheduler: provisioningList에 추가
end
Scheduler->>ProvService: createAll(provisioningList)
ProvService->>ProvRepo: saveAll(provisioningList)
ProvRepo-->>Scheduler: 저장된 ProvisioningContents 리스트
Scheduler->>Scheduler: Gen 객체 생성 루프
loop 각 조합
Scheduler->>GenService: createGen(rawContents, provisioningContents)
GenService-->>Scheduler: Gen (미저장)
Scheduler->>Scheduler: gensList에 추가
end
Scheduler->>GenService: createAll(gensList)
GenService->>GenRepo: saveAll(gensList)
GenRepo-->>Scheduler: 저장된 Gen 리스트
Scheduler-->>Scheduler: 완료 / 결과 반환
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (3 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
domain/generator/src/main/kotlin/com/few/generator/usecase/AbstractGenSchedulingUseCase.kt (2)
155-165:rawContentsMap구성 위치가 비효율적입니다.
rawContentsMap은provisioningContentsToInsert에 추가되는 항목에 대해서만 구성되므로, Step 2에서 예외가 발생한 RawContents는 맵에 포함되지 않습니다. 이는 의도된 동작이지만, 맵 구성을savedRawContents순회 시작 전에 먼저 수행하는 것이 더 명확합니다.또한 Line 159의
rawContent.id!!비-null 단언은saveAll이 ID를 설정하지 못하는 경우 NPE를 발생시킬 수 있습니다. JPA의saveAll은 일반적으로 ID를 설정하지만, 방어적 프로그래밍 관점에서 null 체크를 고려해 보세요.🔎 rawContentsMap 구성을 분리하는 제안
val provisioningContentsToInsert = mutableListOf<ProvisioningContents>() - val rawContentsMap = mutableMapOf<Long, RawContents>() + val rawContentsMap = savedRawContents.associateBy { it.id!! } savedRawContents.forEach { rawContent -> try { val provisioningContent = provisioningService.createProvisioningContent(rawContent) provisioningContentsToInsert.add(provisioningContent) - rawContentsMap[rawContent.id!!] = rawContent } catch (e: Exception) {
42-43: 주석 처리된 코드를 정리해 주세요.
Thread.sleep로직이 주석 처리되어 있습니다. 이 기능이 더 이상 필요하지 않다면 완전히 제거하고, 필요하다면 주석을 해제해 주세요. 주석 처리된 코드는 코드베이스의 가독성을 저해합니다.domain/generator/src/test/kotlin/com/few/generator/usecase/AbstractGenSchedulingUseCaseTest.kt (1)
183-240: Step 2/3 실패 시나리오에 대한 테스트 추가를 권장합니다.현재
일부 카테고리에서 실패하는 경우테스트는 RawContents 생성 실패만 테스트합니다. 새로운 3단계 벌크 플로우에서 ProvisioningContents 생성 실패(Step 2)나 Gen 생성 실패(Step 3) 시나리오도 테스트하면 더 완전한 커버리지를 확보할 수 있습니다.예:
provisioningService.createProvisioningContent()가 특정 RawContents에 대해 예외를 던지는 경우, 나머지 항목들은 정상적으로 처리되어야 합니다.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
domain/generator/src/main/kotlin/com/few/generator/repository/GenRepository.kt(1 hunks)domain/generator/src/main/kotlin/com/few/generator/repository/ProvisioningContentsRepository.kt(1 hunks)domain/generator/src/main/kotlin/com/few/generator/repository/RawContentsRepository.kt(1 hunks)domain/generator/src/main/kotlin/com/few/generator/service/GenService.kt(2 hunks)domain/generator/src/main/kotlin/com/few/generator/service/ProvisioningService.kt(1 hunks)domain/generator/src/main/kotlin/com/few/generator/service/RawContentsService.kt(2 hunks)domain/generator/src/main/kotlin/com/few/generator/usecase/AbstractGenSchedulingUseCase.kt(4 hunks)domain/generator/src/test/kotlin/com/few/generator/usecase/AbstractGenSchedulingUseCaseTest.kt(7 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-07T09:30:34.652Z
Learnt from: eden6187
Repo: few-letter/few-be PR: 762
File: domain/generator/src/main/kotlin/com/few/generator/service/MailSendService.kt:69-76
Timestamp: 2025-09-07T09:30:34.652Z
Learning: In the few-be codebase, Gen entity's id field is guaranteed to be non-null when retrieved from the database, so gen.id!! is safe to use without additional null checking.
Applied to files:
domain/generator/src/main/kotlin/com/few/generator/repository/GenRepository.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: api-test
- GitHub Check: lint
- GitHub Check: Build and analyze
🔇 Additional comments (12)
domain/generator/src/main/kotlin/com/few/generator/repository/ProvisioningContentsRepository.kt (1)
7-8: LGTM!
JpaRepository에서 이미 제공하는saveAll메서드를 명시적으로 오버라이드 선언하여 벌크 저장 API를 명확하게 노출했습니다. 일관성 있는 패턴 적용입니다.domain/generator/src/main/kotlin/com/few/generator/repository/RawContentsRepository.kt (1)
7-8: LGTM!다른 리포지토리와 일관성 있게
saveAll오버라이드가 추가되었습니다.domain/generator/src/main/kotlin/com/few/generator/service/ProvisioningService.kt (2)
26-46: 생성과 저장 로직 분리가 잘 되었습니다.
createProvisioningContent가 이제 엔티티를 생성만 하고 저장하지 않으므로, 호출부에서 여러 엔티티를 모아createAll로 일괄 저장할 수 있습니다. 벌크 인서트 최적화에 적합한 패턴입니다.
48-49: LGTM!
createAll메서드가 배치 저장을 위해 올바르게 구현되었습니다.domain/generator/src/main/kotlin/com/few/generator/repository/GenRepository.kt (1)
10-11: LGTM!다른 리포지토리들과 일관성 있게
saveAll오버라이드가 추가되었습니다.domain/generator/src/main/kotlin/com/few/generator/service/GenService.kt (2)
31-62: 생성과 저장 로직 분리가 적절합니다.
createGen이 엔티티 생성만 담당하고 저장은createAll에서 처리하도록 분리되었습니다.provisioningContent.id!!사용은 use case 워크플로우상ProvisioningContents가 먼저 저장된 후 호출되므로 안전합니다.
64-64: LGTM!
createAll메서드가 배치 저장을 위해 올바르게 구현되었습니다.domain/generator/src/main/kotlin/com/few/generator/usecase/AbstractGenSchedulingUseCase.kt (2)
110-112: 성공/실패 카운트가 전체 파이프라인을 반영하지 않습니다.
successCnt와failCnt는 Step 1(RawContents 생성)에서만 업데이트되며, Step 2(ProvisioningContents)와 Step 3(Gen) 실패는 로그에만 남고 카운트에 반영되지 않습니다. 이벤트 결과 메시지생성(N) / 스킵(M)이 실제 Gen 생성 결과와 다를 수 있습니다.의도된 동작이라면 현재 상태로 괜찮지만, 정확한 메트릭이 필요하다면 Step 2/3 실패도 추적하는 것을 고려해 주세요.
Also applies to: 196-196
107-196: 벌크 인서트 플로우가 잘 구성되었습니다.3단계 벌크 인서트 패턴(RawContents → ProvisioningContents → Gen)이 명확하게 분리되어 있고, 각 단계에서 빈 리스트 체크와 예외 처리가 적절히 구현되어 있습니다. 기존 3N개의 개별 INSERT가 3개의 벌크 INSERT로 줄어들어 성능 개선 목표를 달성할 것입니다.
domain/generator/src/test/kotlin/com/few/generator/usecase/AbstractGenSchedulingUseCaseTest.kt (2)
114-154: 테스트 모킹이 새로운 벌크 API에 맞게 잘 업데이트되었습니다.
id와rawContentsId속성이 모킹에 포함되어 있고,createRawContent,createAll,createProvisioningContent,createGen등 새로운 메서드들이 적절히 모킹되었습니다.
52-72: 리플렉션 사용은 테스트 목적으로 허용됩니다.
doExecute메서드 호출을 위해 리플렉션을 사용하는 것은 프로덕션 코드에서는 권장되지 않지만, 추상 클래스의 protected 동작을 테스트하기 위한 용도로는 적절합니다.InvocationTargetException언래핑도 올바르게 처리되어 있습니다.domain/generator/src/main/kotlin/com/few/generator/service/RawContentsService.kt (1)
25-48: 동일 배치 내 중복 URL로 인한 제약 조건 위반 가능성생성과 저장 로직의 분리는 잘 설계되었으나, 배치 insert 시 URL 중복이 발생할 수 있습니다. Line 32-34의
findByUrl검사는 DB에 저장된 기존 데이터만 확인하고, 현재 스케줄링 실행 중 동일 배치에 포함된 중복 URL은 검사하지 않습니다. 같은 URL이 여러 카테고리에서 반환되거나 동일 배치 내에 중복되면,createAll호출 시 URL unique constraint 위반으로 인한 데이터베이스 오류가 발생할 수 있습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
.claude/CLAUDE.md (2)
50-50: 프로덕션 프로필(prd) 추가 문서화.프로덕션 환경 설정 지원을 명시적으로 문서화한 점은 좋습니다. 향후 로컬/프로덕션 간 설정 차이가 있을 경우 각 모듈의
application-{module-name}-prd.yml파일 구조를 간단히 예시로 추가하면 더욱 명확할 것 같습니다.
57-61: UseCase 패턴 문서 업데이트: DTOs 명명 및 예제 코드 정확성 확인 필요.문서에서
UseCaseInt/UseCaseOutDTO 용어를 명시하고execute메서드 시그니처를 예시로 제공한 점은 개선입니다. 다만, PR 배경에 따른 실제 변경 사항과의 일관성 확인이 필요합니다:
- 예제 메서드명:
BrowseContentsUseCaseIn/BrowseContentsUsecaseOuts(대소문자 불일치: "UsecaseOuts" vs "UseCaseOut")- 실제 구현에서 사용되는 네이밍 컨벤션(특히 "Out" vs "Outs")이 일관되게 적용되었는지 확인 필요
추가로, 이 PR의 핵심인 RawContents, ProvisioningContents, Gen의 벌크 생성 흐름(createAll 패턴)이 문서화되면, 향후 팀원들이 새로운 UseCase 작성 시 참고할 수 있을 것 같습니다.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.claude/CLAUDE.md(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: api-test
- GitHub Check: Build and analyze
- GitHub Check: lint
🔇 Additional comments (2)
.claude/CLAUDE.md (2)
46-46: 테스트 가이드라인 추가는 적절함.코드 수정 시 테스트도 함께 업데이트해야 한다는 지침이 명확하게 추가되었습니다. 다만, 이 PR의 배경이 성능 개선을 위한 벌크 insert 변경인 만큼, 테스트 코드가 현재 존재하지 않는다면 향후 테스트 작성 시 고려할 사항을 문서화하는 것도 도움이 될 것 같습니다.
64-64: 트랜잭션 어노테이션 문서 업데이트: 모듈 명확화.
@ProviderTransactional에서@GeneratorTransactional로 변경된 점이 반영되었습니다. 다만, 이 변경이 provider 모듈 제거(line 9~18의 Module Structure)와 연관된 것이라면, 문서에서 일관되게 generator 도메인 중심으로 재구성되었음을 명시하면 좋을 것 같습니다.
|


🎫 연관 이슈
resolved #828
💁♂️ PR 내용
🙈 PR 참고 사항
🚩 추가된 SQL 운영계 실행계획
Summary by CodeRabbit
릴리스 노트
Refactor
Tests
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.