(N)월 마지막 주차 👉 (N + 1)월 1주차의 버그..... 해결기

애이용·2021년 12월 25일
1

개발일지

목록 보기
1/1
post-thumbnail

주차마다 리더보드가 갱신되는 게임을 개발하는 과정에서 생긴 버그에 대한 내용이다.
월~일이 하나의 주차로 보고, 월요일 오전 12시가 될 때마다 리더보드가 리셋되어야 한다.

하 지 만!!!!
11월 30일(화) -> 12월 1일(수)이 되는 날...
프론트 개발자분에게 연락이 왔다..

제이슨: 젠희.. 리더보드가 이상해요....
젠희(나): 녜,...,?

정말 심쿵 그자체였다. 리더보드가 갑자기 리셋이 되어버린 이 상황 말이다..
나는 리더보드 Id를 yyyy_m_n (yyyy년 m월 n주차) 이런식으로 저장했다.
그래서 화요일 리더보드는 2021_11_5 였고, 12월 1일이 된 수요일의 리더보드 Id는 2021_12_1이 된 것이다.10월부터 게임을 배포한 상황에 계속해서 개선을 하고 있었는데 왜 이제야 알았냐면..허허 10월 31일에서 11월 1일이 되는 날이 딱 월!요일이어서 이때는 문제가 발생하지 않았다. 이때 같은 문제가 생겼더라면.... 일찍 알아챘을텐데 말이닷 ^^.!

일단 이걸 어떻게 일시적으로 해결했느냐!

나는 LeaderboardIdGenerator라는 이름으로 leaderboardId를 생성하는 역할을 하는 클래스로 따로 분리했었다.

그래서 오늘 날짜의 리더보드, 몇월 몇주차의 리더보드, 몇 주전 리더보드 Id 만드는 것을 모두 이 클래스에서 관리했다.

class LeaderboardIdGenerator {
    companion object {
        fun generate(): String {
            // ...
            return if (leaderboardId == "2021_12_1") "2021_11_5" else leaderboardId
        }
        
        fun generateBeforeWeek(week: Int): String {
            // ...
            return if (leaderboardId == "2021_12_1") "2021_11_5" else leaderboardId
        }
        
        fun generate(year: Int?, month: Int?, week: Int?): String {
            // ...
            return if (leaderboardId == "2021_12_1") "2021_11_5" else leaderboardId
        }
    }
}

휴우 그래서 이 4개의 메서드에서2021_12_1 일 때 2021_11_5 이렇게 일시적으로 고쳤다 ㅋㅋㅋ
진짜 리더보드 Id를 생성하는 역할만 하는 클래스로 만들어서 너무 다행이었다 정말!! ...
그래서 버그를 알아챈 5분동안 2021_12_1로 저장된 데이터를 한 1시간 동안 수동으로 옮겼다.. 유저분들 너무 죄송해요.. (전국 풍피 돌리기 전에 알아채서 넘 다행)

쨋든 여기까지 일시적 해결기!


이제 정말 이 버그를 고쳐보도록 하자.

일단 처음에 설계를 할 때 멘토님이 해당 주차를 월 단위가 아니라 년 단위로 하면 어떻냐는 조언을 해주셨다. (ex) 52주차)
하지만.. 나는 이런 버그가 생길 줄이야 왜 생각도 못했을까.. 월 단위나 년 단위나 똑같을 것 같아서 나의 마음 가는 대로.. 월 단위로 했다..!
(역시 멘토님의 조언은 새겨듣는 게 답인 듯 ㅋㅋㅎㅎㅎ)

이 버그를 마주쳤으니 년 단위의 주차로 바꾸기로 했다!
처음엔 yyyy_m로 바꿀 때
val week = cal.get(Calendar.WEEK_OF_MONTH)val week = cal.get(Calendar.WEEK_OF_YEAR)로 수정했다.
하지만 여기서 또 문제인 것. 지금 12월 말이다 이제 1월이 되면 년도도 바뀐다. 이렇게 된다면 또 같은 버그가 생길 것이라고 예상할 수 있다.
(월 단위로 생기는 버그 👉 년 단위로 생기는 버그로 바뀌는 것...)

하지만 테스트를 하면서 이상한 점이 있었다.
2021년 11월 29일인데 2021년 1주차로 나오는 것이다.
너무 의아했다.
그래서 2021년 1월 1일도 확인했는데 2021년 6주차인 것이다.
너무 이상했다...

이런 고민을 나혼자만 했을까? 생각하고 서칭을 했다.

그러다 찾게 된!

WeekFields의 week based year

WeekFieldsweekOfWeekBasedYear는 무조건 한 주는 7일로 채워서 끊는 방법을 사용하는 방식이다.

weekOfWeekBasedYear이 아닌weekOfYear 는 Week based year를 고려하지 않고 해당 년도의 주차를 계산한다. 즉, weekOfYear은 2021년 12월 31일에서는 2021년의 해당 주차를 구하지만, 1월 1일이 되면 2022년의 주차를 구한다.

우선
weekOfYearlocaldate.getYear()weekFields.weekOfYear()이 짝이다.
weekOfWeekBasedYearweekFields.weekBasedYear()weekFields.weekOfWeekBasedYear()이 짝이다.

날짜 예시를 보면서 이해를 해보자

2021.12.31 금요일

weekOfYear: 2021_52
weekOfWeekBasedYear: 2021_52

2022.1.1 토요일

weekOfYear: 2022_0
weekOfWeekBasedYear: 2021_52

2022.1.2 일요일

weekOfYear: 2022_0
weekOfWeekBasedYear: 2021_52

2022.1.3 월요일

weekOfYear: 2022_1
weekOfWeekBasedYear: 2022_1


2022년 1월 1일을 보자. 2021년 12월 27일 ~ 2022년 1월 2일이 한 주차 세트(나는 월요일을 한 주차의 시작으로 설정했다.)인데, 2022년 1월 1일 - 2일은 어느 년도에도 속하지 못해서 2022년도의 0주차로 되었다.
이렇게 되면 또 금에서 토로 넘어가면 리더보드는 리셋이 되어있을 것이다....!

이 문제를 해결하기 위해 weekBasedYear와 weekOfWeekBasedYear가 나왔다.
위의 예시를 보면 어떻게 나의 고민이 풀렸는지 알 것이다!

이제 LeaderboardId를 만드는 클래스를 수정해보자!

class LeaderboardIdGenerator {
    companion object {
        private val weekFields = WeekFields.of(Locale.UK) // 월요일이 한 주차의 시작이다.
        
        fun generate(): String {
            val today = LocalDate.now()
            return "%d_%d".format(today.get(weekFields.weekBasedYear()), today.get(weekFields.weekOfWeekBasedYear()))
        }
        
        fun generateBeforeWeek(week: Int): String {
            val beforeWeekDate = LocalDate.now().minusWeeks(week.toLong())
            return "%d_%d".format(beforeWeekDate.get(weekFields.weekBasedYear()), beforeWeekDate.get(weekFields.weekOfWeekBasedYear()))
        }
        
        fun generate(year: Int?, weekOfYear: Int?): String {
            return if (year != null && weekOfYear != null) "%d_%d".format(year, weekOfYear) else generate()
        }
    }
}

WeekFields.of(Locale.UK)가 아닌 WeekFields.of(Locale.KOREA)로 하면 월요일이 아닌 일요일이 주차의 첫 시작으로 설정된다. 나는 월요일을 주차의 시작으로 해야하기 때문에 WeekFields.of(Locale.UK)로 설정했다.

이건 나의 엄청난 고민이 담긴 낙서장이다... ^_^

참고 링크

https://nidev.gitlab.io/2021/01/01/2020%EB%85%84-12%EC%9B%94-30%EC%9D%BC%EC%9D%80-%EB%AA%87%EB%B2%88%EC%A7%B8-%EC%A3%BC%EC%9D%B8%EA%B0%80-feat-Java/

profile
로그를 남기자 〰️

0개의 댓글