-
Notifications
You must be signed in to change notification settings - Fork 18
[5주차] - Read Optimization - 박주닮 #46
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: dami325
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,13 @@ | ||
| package com.loopers.domain.like | ||
|
|
||
| import com.loopers.domain.product.ProductService | ||
| import org.springframework.stereotype.Component | ||
| import org.springframework.transaction.annotation.Transactional | ||
|
|
||
| @Component | ||
| class LikeService( | ||
| private val likeRepository: LikeRepository, | ||
| private val productService: ProductService, | ||
| ) { | ||
|
Comment on lines
1
to
11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Get the full LikeService.kt file to understand the changes
find . -name "LikeService.kt" -type fRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Find Product entity and like_count field references
find . -name "Product.kt" -o -name "Product.java" -type fRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Search for migration files and SQL schemas
find . -name "*.sql" -o -name "*migration*" -o -name "*schema*" | head -20Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Look for data initialization or test data files
find . -name "data.sql" -o -name "test-data.sql" -o -name "*init*.sql" -type fRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# List repository structure to understand layout
ls -laRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 1563 🏁 Script executed: #!/bin/bash
# Check git status and recent changes to understand PR scope
git log --oneline -10Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 110 🏁 Script executed: #!/bin/bash
# Search for all .kt files in the repository
find . -name "*.kt" -type f | head -30Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 2542 🏁 Script executed: #!/bin/bash
# Search for SQL and database related files
find . -name "*.sql" -o -name "*.xml" | grep -E "(sql|database|schema|migration)" | head -20Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Check all git branches
git branch -aRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 203 🏁 Script executed: #!/bin/bash
# Check current branch and status
git statusRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 297 🏁 Script executed: #!/bin/bash
# Look for any like-related files in the commerce-api
find ./apps/commerce-api -name "*ike*" -o -name "*product*" -o -name "*like*" 2>/dev/nullRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Check git diff to see what's being changed in this PR
git diff --name-only HEADRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Check for untracked files
git ls-files --others --exclude-standardRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 108 🏁 Script executed: #!/bin/bash
# Check out coderabbit_46 branch and look for LikeService.kt
git checkout coderabbit_46 2>&1
find . -name "LikeService.kt" -o -name "Product.kt" 2>/dev/null | head -20Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 321 🏁 Script executed: #!/bin/bash
# Check git log to see commits in the PR
git log --oneline -20Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 110 🏁 Script executed: #!/bin/bash
# Show git diff with stats
git diff main... --stat | head -30Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Look for all changes related to like or product
git diff main... --name-only | grep -E "(like|product|Like|Product)" -iRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/antml/bash
# Show files that differ between main and coderabbit_46
git log --oneline main..coderabbit_46Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 1362 🏁 Script executed: #!/bin/bash
# Read the LikeService.kt file
cat -n ./apps/commerce-api/src/main/kotlin/com/loopers/domain/like/LikeService.ktRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 1471 🏁 Script executed: #!/bin/bash
# Read the Product.kt file
cat -n ./apps/commerce-api/src/main/kotlin/com/loopers/domain/product/Product.ktRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 2763 🏁 Script executed: #!/bin/bash
# Search for migration files related to like or product
find . -path "*/db/migration/*" -o -path "*/resources/db/*" -o -name "*Like*" -o -name "*Product*" | grep -E "\.(sql|xml)" | head -20Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Look for JPA entity files
find ./apps/commerce-api -name "*Entity.kt" -o -name "*Jpa*.kt" | grep -E "(like|product)" -iRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 273 🏁 Script executed: #!/bin/bash
# Look for Flyway or Liquibase migration files
find . -path "*/db/migration*" -type dRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Search for all SQL files in the project
find . -name "*.sql" -type f 2>/dev/null | grep -v node_modulesRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Check the resources directory structure
find ./apps/commerce-api/src/main/resources -type f 2>/dev/null | head -30Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 144 🏁 Script executed: #!/antml/bash
# Look for schema or initialization files
ls -la ./apps/commerce-api/src/main/resources/ 2>/dev/null || echo "resources dir not found"Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 265 🏁 Script executed: #!/bin/bash
# Read application.yml to understand JPA configuration
cat ./apps/commerce-api/src/main/resources/application.ymlRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 1049 🏁 Script executed: #!/bin/bash
# Search for CommandLineRunner or ApplicationRunner beans that might handle initialization
rg -n "CommandLineRunner|ApplicationRunner|@PostConstruct" --type=ktRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 116 🏁 Script executed: #!/bin/bash
# Look for any test data or initialization classes
find ./apps/commerce-api -name "*Init*" -o -name "*Fixture*" -o -name "*Seed*" 2>/dev/nullRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 328 🏁 Script executed: #!/bin/bash
# Check the commit that added the likeCount denormalization to see if migration was included
git show 89cedec --statRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 683 🏁 Script executed: #!/bin/bash
# Check the commit for like feature implementation
git show bbe4e98 --statRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 1095 🏁 Script executed: #!/bin/bash
# Find and read jpa.yml
find . -name "jpa.yml" -type fRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 130 🏁 Script executed: #!/bin/bash
# Search for any file that contains jpa configuration
rg -l "hibernate.ddl-auto|spring.jpa" --type=yamlRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Look at the modules structure for shared JPA config
ls -la ./modules/jpa/src/main/resources/ 2>/dev/null || echo "no resources"Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 257 🏁 Script executed: #!/bin/bash
# Check if there are any schema initialization files
find ./modules -name "*.sql" -o -name "*schema*" -o -name "*init*" 2>/dev/nullRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 72 🏁 Script executed: #!/bin/bash
# Look at the full Product entity to understand initialization
git show 89cedec:apps/commerce-api/src/main/kotlin/com/loopers/domain/product/Product.kt | head -40Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 1062 🏁 Script executed: #!/bin/bash
# Read jpa.yml configuration
cat ./modules/jpa/src/main/resources/jpa.ymlRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 2236 🏁 Script executed: #!/bin/bash
# Check the full git history of Product.kt to see when likeCount was added
git log --oneline --all -- "**/Product.kt" | head -10Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 253 🏁 Script executed: #!/bin/bash
# Look at the LikeService test to understand the expected behavior
find ./apps/commerce-api -name "*LikeServiceTest*" -o -name "*LikeService*Test*" 2>/dev/nullRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 168 🏁 Script executed: #!/bin/bash
# Check when the Like entity was first introduced
git log --oneline --all -- "**/Like.kt" | head -10Repository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 230 🏁 Script executed: #!/bin/bash
# Read the LikeServiceTest to understand test coverage
cat -n ./apps/commerce-api/src/test/kotlin/com/loopers/domain/like/LikeServiceTest.ktRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 3313 🏁 Script executed: #!/bin/bash
# Check the detailed changes in commit 89cedec to see if migration was mentioned
git show 89cedecRepository: Loopers-dev-lab/loopers-spring-kotlin-template Length of output: 8050 기존 데이터의 일관성 확보가 필수입니다. 이 변경사항을 배포하기 전에 데이터 마이그레이션이 반드시 필요합니다. 이 커밋 (89cedec)은 상품 좋아요 수를 문제점:
필요한 마이그레이션: UPDATE loopers_product p
SET like_count = (
SELECT COUNT(*)
FROM loopers_like l
WHERE l.product_id = p.id
);🤖 Prompt for AI Agents |
||
|
|
||
| @Transactional(readOnly = true) | ||
|
|
@@ -20,11 +22,17 @@ class LikeService( | |
| } | ||
|
|
||
| likeRepository.save(Like.of(userId, productId)) | ||
|
|
||
| val product = productService.getProduct(productId) | ||
| product.incrementLikeCount() | ||
| } | ||
|
|
||
| @Transactional | ||
| fun removeLike(userId: Long, productId: Long) { | ||
| val like = likeRepository.findByUserIdAndProductId(userId, productId) ?: return | ||
| likeRepository.delete(like) | ||
|
|
||
| val product = productService.getProduct(productId) | ||
| product.decrementLikeCount() | ||
| } | ||
|
Comment on lines
30
to
37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 동일한 동시성 문제가 좋아요 취소에도 존재합니다.
@Transactional
fun removeLike(userId: Long, productId: Long) {
val like = likeRepository.findByUserIdAndProductId(userId, productId) ?: return
likeRepository.delete(like)
-
- val product = productService.getProduct(productId)
+ val product = productService.getProductWithLock(productId)
product.decrementLikeCount()
} |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,11 +5,18 @@ import com.loopers.support.error.CoreException | |
| import com.loopers.support.error.ErrorType | ||
| import jakarta.persistence.Column | ||
| import jakarta.persistence.Entity | ||
| import jakarta.persistence.Index | ||
| import jakarta.persistence.Table | ||
| import java.math.BigDecimal | ||
|
|
||
| @Entity | ||
| @Table(name = "loopers_product") | ||
| @Table( | ||
| name = "loopers_product", | ||
| indexes = [ | ||
| Index(name = "idx_product_brand_id", columnList = "brand_id"), | ||
| Index(name = "idx_product_like_count", columnList = "like_count"), | ||
| ], | ||
| ) | ||
| class Product( | ||
| @Column(nullable = false, length = 200) | ||
| var name: String, | ||
|
|
@@ -19,13 +26,26 @@ class Product( | |
|
|
||
| @Column(nullable = false) | ||
| var brandId: Long, | ||
|
|
||
| @Column(nullable = false) | ||
| var likeCount: Long = 0, | ||
| ) : BaseEntity() { | ||
|
|
||
| init { | ||
| validateName(name) | ||
| validatePrice(price) | ||
| } | ||
|
|
||
| fun incrementLikeCount() { | ||
| this.likeCount++ | ||
| } | ||
|
|
||
| fun decrementLikeCount() { | ||
| if (this.likeCount > 0) { | ||
| this.likeCount-- | ||
| } | ||
| } | ||
|
Comment on lines
+39
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 증가/감소 메서드 구현이 적절합니다.
다만, 동시성 제어를 위해 +@Version
+var version: Long = 0
+
@Column(nullable = false)
var likeCount: Long = 0,
🤖 Prompt for AI Agents |
||
|
|
||
| fun update(name: String?, price: BigDecimal?, brandId: Long?) { | ||
| name?.let { | ||
| validateName(it) | ||
|
|
||
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.
캐시 키 생성 로직에 안정성 문제가 있습니다.
cacheKey() 메서드에 다음 문제가 있습니다:
이는 캐시 효율성을 저하시키고 불필요한 캐시 미스를 유발합니다.
다음 diff를 적용하여 안정적인 캐시 키를 생성하세요:
fun cacheKey(): String { - return "${brandId}_${pageNumber}_${pageSize}_$sort" + val sortKey = sort + .sortedWith(compareBy({ it.field }, { it.direction })) + .joinToString(",") { "${it.field}:${it.direction}" } + return "${brandId}_${pageNumber}_${pageSize}_${sortKey}" }📝 Committable suggestion
🤖 Prompt for AI Agents