Skip to content

[Refactor] SLO에 영향을 미치는 쿼리 개선 작업 Prod 적용#209

Merged
lvalentine6 merged 10 commits intomainfrom
develop
Oct 10, 2025
Merged

[Refactor] SLO에 영향을 미치는 쿼리 개선 작업 Prod 적용#209
lvalentine6 merged 10 commits intomainfrom
develop

Conversation

@lvalentine6
Copy link
Member

@lvalentine6 lvalentine6 commented Oct 10, 2025

✨ 개요

  • dev 환경에 적용된 쿼리 개선을 prod 환경에 적용합니다.
  • dev 환경이 prod 환경과 동일하지 않아 정확한 레이턴시 개선 측정은 어려우나
    레이턴시 개선, 1 + N 쿼리 문제가 발생하지 않는것을 확인했습니다.
  • prod 환경 적용 후 레이턴시 측정 예정입니다.

🧾 관련 이슈

#205

🔍 참고 사항 (선택)

Summary by CodeRabbit

  • 신기능
    • 가게/응원 목록에 페이지네이션을 도입해 더 빠르고 부드러운 목록 탐색을 제공합니다.
  • 성능 개선
    • 데이터 일괄 페치 최적화로 목록/피드 로딩 속도와 안정성이 향상되었습니다.
    • 응원 항목의 태그 구조 정비로 태그 기반 필터링의 일관성이 개선되었습니다.
  • 운영/작업
    • 웹 방화벽 규칙을 조정해 정상 트래픽 호환성을 높이고 특정 도메인/헤더 기반 요청 처리를 개선했습니다.
    • 개발/운영 환경 설정을 정리해 배포 안정성을 높였습니다.

@coderabbitai
Copy link

coderabbitai bot commented Oct 10, 2025

Walkthrough

리포지토리 전반에서 목록 반환 타입을 List에서 Page로 변경하고 @entitygraph를 제거했습니다. Cheer 엔티티에 @Embedded CheerTags 필드를 추가했습니다. 서비스와 테스트는 페이지네이션에 맞게 수정되었습니다. dev/prod 환경에 Hibernate default_batch_fetch_size=30을 설정했습니다. Terraform WAF 규칙이 헤더 기반 문자열 매칭으로 재구성되었습니다.

Changes

Cohort / File(s) Summary
Domain Model
src/main/java/eatda/domain/cheer/Cheer.java, src/main/java/eatda/domain/store/Store.java
Cheer에 @Embedded 필드 cheerTags 추가 및 생성자 초기화. Store의 cheers 필드 주변에 배치 사이즈/미래 점검 관련 주석 추가(코드 변화 없음).
Repository Pagination & EntityGraph 제거
src/main/java/eatda/repository/cheer/CheerRepository.java, src/main/java/eatda/repository/store/StoreRepository.java, src/main/java/eatda/repository/story/StoryRepository.java
주요 조회 메서드 반환 타입을 ListPage로 변경. @EntityGraph 삭제. cheerTags/태그 조인 시 query != null 체크 후 distinct(true) 설정. Page 임포트 추가.
Service 적응(페이지네이션)
src/main/java/eatda/service/cheer/CheerService.java, src/main/java/eatda/service/store/StoreService.java
레포 호출 결과를 Page로 수신하고 .getContent()를 사용하여 응답 리스트 생성. 메서드 시그니처 변경 없음.
Configuration (JPA Batch Fetch)
src/main/resources/application-dev.yml, .../application-prod.yml, .../application-local.yml
dev/prod에 spring.jpa.properties.hibernate.default_batch_fetch_size: 30 추가. local에는 비교 목적의 주석만 추가(설정 변화 없음).
Tests 업데이트(페이지네이션 대응)
src/test/java/eatda/repository/cheer/CheerRepositoryTest.java, src/test/java/eatda/repository/store/StoreRepositoryTest.java
테스트 내 반환 타입을 ListPage로 변경하고 사용부를 Page API에 맞게 수정. Page 임포트 추가.
Terraform WAF 규칙 재구성
terraform/common/waf/main.tf
Allow-Browser-Requests 규칙의 size_constraint_statement를 다수의 byte_match_statement(origin/referer 헤더, 다양한 매칭: ENDS_WITH/CONTAINS/EXACTLY/STARTS_WITH, LOWERCASE 변환 포함)로 교체. AWS-Managed-Bot-Control-Rule-Set 제거.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant S as CheerService
  participant R as CheerRepository
  participant DB as Database

  C->>S: getCheers(filters, page, size)
  S->>R: findAllByConditions(filters, Pageable)
  R->>DB: SELECT ... WHERE ... ORDER BY created_at DESC LIMIT/OFFSET
  DB-->>R: Page<Cheer> (content + metadata)
  R-->>S: Page<Cheer>
  S->>S: map page.getContent() to DTOs
  S-->>C: CheerListResponse (items, page info)
  note over S, C: 변경사항: List → Page 기반 흐름
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

refactor

Suggested reviewers

  • leegwichan

Poem

귀 쫑긋, 페이지 넘겨 본다—퐁퐁
리스트는 접고, Page로 쏙—총총
태그는 속에, 임베드 꽉—콩콩
배치로 묶어, 쿼리 살짝—둥둥
WAF는 깐깐, 헤더 맞장—퐁당
코드밭 뛰는 토끼 한 마리: “리팩터링 완!” 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.55% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed 제목이 PR의 핵심 변화인 SLO에 영향을 미치는 쿼리 개선을 프로덕션 환경에 적용하는 작업을 명확하게 요약하고 있어 변경 내용과 일치하며 간결하고 구체적입니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

📄 Terraform Plan Summary

🛡️ Common Infrastructure


No plan summary

Status: ✅ No Changes


🚀 Production Environment


No plan summary

Status: ✅ No Changes


📋 Full Results: View in Actions

@sonarqubecloud
Copy link

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b01e5a4 and c96438f.

📒 Files selected for processing (13)
  • src/main/java/eatda/domain/cheer/Cheer.java (1 hunks)
  • src/main/java/eatda/domain/store/Store.java (1 hunks)
  • src/main/java/eatda/repository/cheer/CheerRepository.java (3 hunks)
  • src/main/java/eatda/repository/store/StoreRepository.java (3 hunks)
  • src/main/java/eatda/repository/story/StoryRepository.java (0 hunks)
  • src/main/java/eatda/service/cheer/CheerService.java (3 hunks)
  • src/main/java/eatda/service/store/StoreService.java (2 hunks)
  • src/main/resources/application-dev.yml (1 hunks)
  • src/main/resources/application-local.yml (1 hunks)
  • src/main/resources/application-prod.yml (1 hunks)
  • src/test/java/eatda/repository/cheer/CheerRepositoryTest.java (6 hunks)
  • src/test/java/eatda/repository/store/StoreRepositoryTest.java (6 hunks)
  • terraform/common/waf/main.tf (1 hunks)
💤 Files with no reviewable changes (1)
  • src/main/java/eatda/repository/story/StoryRepository.java
🧰 Additional context used
🪛 GitHub Actions: Notify Discord on `/noti` Comment
src/main/java/eatda/domain/cheer/Cheer.java

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/main/resources/application-dev.yml

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/main/resources/application-local.yml

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/main/java/eatda/service/store/StoreService.java

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/test/java/eatda/repository/cheer/CheerRepositoryTest.java

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

terraform/common/waf/main.tf

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/test/java/eatda/repository/store/StoreRepositoryTest.java

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/main/resources/application-prod.yml

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/main/java/eatda/domain/store/Store.java

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/main/java/eatda/service/cheer/CheerService.java

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/main/java/eatda/repository/store/StoreRepository.java

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

src/main/java/eatda/repository/cheer/CheerRepository.java

[error] 1-1: No such file or directory. The CI script attempted to process this path but it does not exist in the repository.

⏰ 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). (1)
  • GitHub Check: test
🔇 Additional comments (13)
src/main/resources/application-local.yml (1)

25-25: 명확한 주석 추가 감사합니다.

Local 환경에서 batch size를 제외한 이유가 바로 이해됩니다.

src/main/resources/application-dev.yml (1)

30-32: 동일한 배치 페치 크기 적용 확인 완료
dev 환경에서도 default_batch_fetch_size: 30을 맞춰 주어 prod와 일관성이 확보되었습니다. 추가 수정 없이 이대로 적용해도 무방해 보입니다.

src/main/java/eatda/domain/store/Store.java (1)

60-65: LGTM! 배치 페칭 전략에 대한 명확한 문서화

현재 데이터 규모와 향후 성능 모니터링 필요성을 명확히 문서화했습니다. 배치 크기 설정에 대한 근거와 향후 검토 시점을 잘 설명하고 있습니다.

src/test/java/eatda/repository/store/StoreRepositoryTest.java (1)

17-17: LGTM! 페이지네이션 API 변경에 맞춘 테스트 업데이트

Repository가 Page<Store>를 반환하도록 변경됨에 따라 테스트도 올바르게 업데이트되었습니다. PageStream을 지원하므로 기존 assertion 로직이 그대로 작동합니다.

Also applies to: 65-69, 91-95, 104-108, 138-142, 161-164

src/main/java/eatda/service/store/StoreService.java (2)

22-22: LGTM! Repository의 페이지네이션 변경 사항 반영

Page<Store>를 사용하도록 올바르게 변경되었으며, 스트리밍 로직도 정상적으로 작동합니다.

Also applies to: 49-59


46-46: TODO 주석 추적 권장

N+1 문제 해결에 대한 TODO가 남아있습니다. 현재 PR에서 부분적으로 개선되었지만, 추가 작업이 필요할 수 있습니다.

이 TODO를 별도 이슈로 추적하여 향후 개선 작업을 관리하시겠습니까?

src/test/java/eatda/repository/cheer/CheerRepositoryTest.java (1)

16-16: LGTM! Repository API 변경에 맞춘 테스트 업데이트

CheerRepositoryPage<Cheer>를 반환하도록 변경됨에 따라 모든 테스트가 올바르게 업데이트되었습니다.

Also applies to: 68-72, 94-99, 114-119, 149-154, 173-177

src/main/java/eatda/domain/cheer/Cheer.java (1)

52-59: LGTM! 성능 트레이드오프를 명확히 문서화한 설계 결정

@Embedded CheerTags 도입과 함께 배치 페칭 제약사항을 명확히 문서화했습니다. 현재 데이터 규모에서는 적절하며, 향후 필요시 @OneToMany로 재설계할 수 있음을 명시했습니다.

Also applies to: 69-69

src/main/java/eatda/service/cheer/CheerService.java (1)

28-28: LGTM! 페이지네이션을 올바르게 처리

Repository의 Page<Cheer> 반환을 적절히 처리하고 있습니다. getContent()를 통해 실제 데이터를 추출하여 응답 객체로 변환하는 로직이 올바릅니다.

Also applies to: 119-129, 147-153

src/main/java/eatda/repository/store/StoreRepository.java (2)

11-11: LGTM! 페이지네이션 지원을 위한 API 변경

List<Store>에서 Page<Store>로의 변경이 올바르게 적용되었습니다. 이는 대용량 데이터 조회 시 메모리 효율성과 성능을 개선합니다.

Also applies to: 36-44


54-59: query null-check 패턴 일관성 확인
CheerRepository(38–40)와 StoreRepository(55–57) 모두 if (query != null) query.distinct(true); 패턴이 적용되어 있어, count 쿼리 생성 시 query가 null일 수 있는 상황을 대비한 방어 로직이 코드베이스 전반에 일관되게 적용된 것을 확인했습니다.

src/main/java/eatda/repository/cheer/CheerRepository.java (2)

11-11: LGTM! 페이지네이션 API로의 일관된 마이그레이션

StoreRepository와 동일한 패턴으로 Page<Cheer> 반환 타입을 적용했습니다. 이는 전체 리포지토리 레이어에서 일관된 페이지네이션 전략을 제공합니다.

Also applies to: 20-27, 51-51


38-40: LGTM! StoreRepository와 동일한 방어 패턴 적용

StoreRepository와 동일하게 count 쿼리 생성 시 query null 상황을 대비한 방어 코드를 적용했습니다. 일관성 있는 구현입니다.

Copy link
Member

@leegwichan leegwichan left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! 쿼리 개선 상황 파악되셨다면 머지해도 좋을 것 같습니다!

@lvalentine6 lvalentine6 merged commit 3e42ddb into main Oct 10, 2025
20 of 22 checks passed
@github-actions
Copy link

🎉 This PR is included in version 1.9.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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.

2 participants