Skip to content

운영 배포#235

Merged
Hwanvely merged 7 commits intomainfrom
dev
Apr 6, 2026
Merged

운영 배포#235
Hwanvely merged 7 commits intomainfrom
dev

Conversation

@Hwanvely
Copy link
Copy Markdown
Collaborator

@Hwanvely Hwanvely commented Apr 6, 2026

No description provided.

* 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 분리
@Hwanvely Hwanvely self-assigned this Apr 6, 2026
Copy link
Copy Markdown

@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

This pull request introduces a "Fever Time" mechanic, featuring a new domain model, event-driven state management for pausing and resuming fever periods, and updated scoring logic. It also adds deployment scripts, Jib containerization, and refactors domain models to support inheritance and proxying. Feedback identifies a critical bug in the percentile calculation query, significant code duplication across business logic classes, and opportunities to improve deployment script robustness and test stability.

Comment on lines +16 to +28
SELECT percent_rank() over (order by score desc) as percentile
FROM snackgame
WHERE expires_at <= now() + INTERVAL 1 SECOND
AND session_id = :sessionId

UNION ALL

SELECT 0.0 as percentile
FROM snackgame
WHERE session_id = :sessionId
AND expires_at > now() + INTERVAL 1 SECOND
LIMIT 1
""",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

현재 findPercentileOf의 네이티브 쿼리는 WHERE 절에 session_id = :sessionId 조건이 포함되어 있어 percent_rank() 함수가 항상 단일 행에 대해 실행됩니다. 이로 인해 백분위수는 항상 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
        ) as ranked_sessions
        WHERE session_id = :sessionId

        UNION ALL

        SELECT 0.0 as percentile
        FROM snackgame
        WHERE session_id = :sessionId
          AND expires_at > now() + INTERVAL 1 SECOND
        LIMIT 1

Comment on lines +54 to +77
fun remove(streakWithFever: StreakWithFever) {
val streak = streakWithFever.streak
val removedSnacks = board.removeSnacksIn(streak)

val multiplier = calculateMultiplier(streakWithFever)
increaseScore(streak.length * multiplier)

if (removedSnacks.any(Snack::isGolden)) {
this.board = board.reset()
}
}

private fun calculateMultiplier(streakWithFever: StreakWithFever): Int {
val serverFever = feverTime ?: return NORMAL_MULTIPLIER

if (streakWithFever.clientIsFever &&
serverFever.isFeverTime(streakWithFever.occurredAt) &&
serverFever.canApplyFeverMultiplier()
) {
serverFever.incrementFeverStreak()
return FEVER_MULTIPLIER
}
return NORMAL_MULTIPLIER
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

remove(streakWithFever: StreakWithFever)calculateMultiplier(streakWithFever: StreakWithFever) 메서드 로직이 SnackgameBiz, SnackgameBizV2, Snackgame 클래스에 중복되어 있습니다. 코드 중복은 유지보수 비용을 높이고 잠재적인 버그를 유발할 수 있습니다. 이 로직을 공통 상위 클래스나 별도의 컴포넌트로 추출하여 DRY 원칙을 따르는 것을 고려해 보세요.

image = "ghcr.io/snack-game/server"
auth {
username = "snack-game"
password = System.getenv("GHCR_PASSWORD") ?: ""
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

GHCR_PASSWORD 환경 변수가 설정되지 않은 경우, 인증이 항상 실패하게 되는 빈 문자열 ""을 비밀번호로 사용하게 됩니다. 이로 인해 빌드 실패 원인을 파악하기 어려울 수 있습니다. 환경 변수가 없을 때 빌드를 즉시 중단시키고 명확한 오류 메시지를 표시하는 것이 좋습니다.

            password = System.getenv("GHCR_PASSWORD") ?: error("GHCR_PASSWORD 환경변수가 설정되어야 합니다.")

local http_code="000"

while [ "$elapsed" -lt "$HEALTH_CHECK_TIMEOUT" ]; do
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_CHECK_URL" 2>/dev/null || echo "000")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

cURL 요청 시 -f 또는 --fail 옵션을 추가하여 HTTP 상태 코드가 200-299 범위가 아닐 경우 스크립트가 즉시 실패하도록 하는 것이 좋습니다. 이렇게 하면 http_code를 수동으로 확인하는 것보다 더 안정적으로 오류를 처리할 수 있습니다. set -e가 설정되어 있으므로 cURL이 0이 아닌 종료 코드를 반환하면 스크립트가 중단됩니다.

Suggested change
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_CHECK_URL" 2>/dev/null || echo "000")
http_code=$(curl -s -o /dev/null -w "%{http_code}" -f "$HEALTH_CHECK_URL" 2>/dev/null || echo "000")

echo "[헬스체크] 컨테이너가 종료됨, 즉시 롤백"
return 1
fi
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_CHECK_URL" 2>/dev/null || echo "000")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

cURL 요청 시 -f 또는 --fail 옵션을 추가하여 HTTP 상태 코드가 200-299 범위가 아닐 경우 스크립트가 즉시 실패하도록 하는 것이 좋습니다. 이렇게 하면 http_code를 수동으로 확인하는 것보다 더 안정적으로 오류를 처리할 수 있습니다. set -e가 설정되어 있으므로 cURL이 0이 아닌 종료 코드를 반환하면 스크립트가 중단됩니다.

Suggested change
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_CHECK_URL" 2>/dev/null || echo "000")
http_code=$(curl -s -o /dev/null -w "%{http_code}" -f "$HEALTH_CHECK_URL" 2>/dev/null || echo "000")

Comment on lines +12 to +13
var paused: Boolean? = false,
var feverStreakCount: Int? = 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

pausedfeverStreakCount 속성이 nullable로 선언되어 있어 불필요한 null 검사가 발생합니다. 기본값을 제공하여 non-nullable 타입으로 변경하면 코드가 더 안전하고 간결해집니다.

Suggested change
var paused: Boolean? = false,
var feverStreakCount: Int? = 0
var paused: Boolean = false,
var feverStreakCount: Int = 0

}

fun pause(at: LocalDateTime) {
if (paused != true) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

paused 속성을 non-nullable Boolean으로 변경하면, 이 조건문을 if (!paused)로 더 간결하게 표현할 수 있습니다.

Suggested change
if (paused != true) {
if (!paused) {

snackgameService.useFeverTime(땡칠().id, game.sessionId)

snackgameService.pause(game.ownerId, game.sessionId)
Thread.sleep(1000)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

테스트 코드에서 Thread.sleep()을 사용하면 테스트 실행 시간이 길어지고, 실행 환경에 따라 테스트가 불안정해질 수 있습니다. java.time.Clock을 주입받아 시간을 제어하는 방식을 사용하면 더 안정적이고 빠른 테스트를 작성할 수 있습니다.

@Hwanvely Hwanvely merged commit 299864b into main Apr 6, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant