Conversation
* fix: 피버타임 검증 시 점수가 두배가 되지 않는 문제 해결 * refactor: 바뀐 dto에 맞게 BIZ 및 test 수정
* fix: 피버타임 검증 시 점수가 두배가 되지 않는 문제 해결 * refactor: 바뀐 dto에 맞게 BIZ 및 test 수정 * fix: 피버타임중 일시정지 시 피버타임도 멈추게 한다 * refactor: 인터페이스로 묶는다
* fix: 점수 증가 로직 오류 해결 * fix: 스트릭 발생 시각을 받는다 * refactor: 네이밍 수정 * fix(test): 스트릭 발생 시각 추가
* fix: 치팅 및 네트워크 지연 해결 * comment: 디버깅을 위한 로그 추가 * fix: session과 fevertime 일시정지 동기화
* fix: 치팅 및 네트워크 지연 해결 * comment: 디버깅을 위한 로그 추가 * fix: session과 fevertime 일시정지 동기화 * fix: 세션 예외 오류 해결 * feat: multipart 예외 핸들링 * refactor: CD 파이프라인 OCI로 마이그레이션 * fix: end response 분리
* fix: 치팅 및 네트워크 지연 해결 * comment: 디버깅을 위한 로그 추가 * fix: session과 fevertime 일시정지 동기화 * fix: 세션 예외 오류 해결 * feat: multipart 예외 핸들링 * refactor: CD 파이프라인 OCI로 마이그레이션 * fix: end response 분리 * fix: oci 경로 수정
There was a problem hiding this comment.
Code Review
This pull request introduces a 'Fever Time' mechanic with server-side validation, multiplier logic, and event-driven state management for pausing and resuming sessions. It also adds containerization support using Jib and provides deployment scripts for development and rolling production updates. Feedback highlights a logic error in the SQL percentile calculation, a missing pause-state check in the fever validation logic, and significant code duplication across the game domain classes. Furthermore, the removal of the allOpen plugin is noted as a potential risk for JPA lazy loading if the manual 'open' keywords are not consistently applied to entities.
I am having trouble creating individual review comments. Click here to see my feedback.
src/main/java/com/snackgame/server/game/snackgame/core/domain/SnackgameRepository.kt (16-19)
현재 쿼리는 WHERE 절에서 session_id = :sessionId로 먼저 필터링을 수행한 뒤 percent_rank()를 계산합니다. 이 경우 결과 셋에는 해당 세션 하나만 포함되므로 percentile은 항상 0.0이 반환됩니다. 의도한 대로 백분위를 구하려면 전체 만료된 세션들에 대해 순위를 먼저 계산한 후, 특정 세션의 결과를 추출해야 합니다.
SELECT percentile FROM (
SELECT session_id, percent_rank() over (order by score desc) as percentile
FROM snackgame
WHERE expires_at <= now() + INTERVAL 1 SECOND
) t WHERE session_id = :sessionId
src/main/java/com/snackgame/server/game/snackgame/core/domain/item/FeverTime.kt (16-32)
isFeverTime 메서드에서 피버 타임이 일시정지(paused) 상태인지 확인하는 로직이 누락되었습니다. 피버 타임이 일시정지된 상태에서 발생한 이벤트는 피버 효과가 적용되지 않아야 하므로 paused != true 조건이 추가되어야 합니다.
fun isFeverTime(occurredAt: LocalDateTime, serverNow: LocalDateTime = LocalDateTime.now()): Boolean {
if (paused == true) {
return false
}
// 1. 서버 시간 기준 합리성 검증 (치팅 방지)
if (occurredAt.isBefore(serverNow.minus(MAX_PAST_ALLOWED)) ||
occurredAt.isAfter(serverNow.plus(MAX_FUTURE_ALLOWED))
) {
return false
}
// 2. 피버타임 범위 검증 (서버 연산 및 네트워크 지연 고려)
val validEndAt = feverEndAt.plus(BUFFER_DURATION)
val validStartedAt = feverStartedAt.minus(BUFFER_DURATION)
if (occurredAt.isBefore(validStartedAt) || occurredAt.isAfter(validEndAt)) {
return false
}
return true
}build.gradle.kts (18-22)
allOpen 설정이 제거되면서 JPA 엔티티들이 기본적으로 final 클래스가 됩니다. 이로 인해 Hibernate의 프록시 생성이 불가능해져 지연 로딩(Lazy Loading) 등이 정상적으로 동작하지 않을 수 있습니다. 현재 PR에서 수동으로 open 키워드를 추가하고 있으나, 이는 누락하기 쉽고 번거로우므로 플러그인 설정을 유지하는 것을 권장합니다.
src/main/java/com/snackgame/server/game/snackgame/biz/domain/SnackgameBiz.kt (54-77)
remove(StreakWithFever)와 calculateMultiplier 로직이 SnackgameBiz, SnackgameBizV2, Snackgame 클래스에 동일하게 중복되어 있습니다. 중복 코드는 유지보수 시 실수를 유발할 수 있으므로, 공통 로직을 별도의 클래스나 인터페이스의 디폴트 메서드 등으로 추출하는 것이 좋습니다.
src/main/java/com/snackgame/server/game/snackgame/core/domain/item/FeverTime.kt (12-13)
paused와 feverStreakCount 필드가 기본값을 가지고 있음에도 nullable 타입(Boolean?, Int?)으로 선언되어 있습니다. 불필요한 null 체크를 줄이기 위해 primitive 타입으로 선언하는 것이 좋습니다.
var paused: Boolean = false,
var feverStreakCount: Int = 0
No description provided.