윈도우만 최신 순서로 조회가 안 된다? 서러운데요🥲

지송·2024년 11월 1일

방끗

목록 보기
8/9

안녕하세요
오늘은 우아한테크코스 6기 방끗 팀 프로젝트를 진행하며
BE 팀에서 유일한 윈도우로 겪었던 문제 상황에 대해 말씀드려 보고자 합니다

제목으로 유추하기 힘든 오늘의 주제는 바로 아래와 같습니다

LocalDateTime NonoSecond와 OS 간의 상관 관계

사실 우테코를 진행하며 수많은 윈도우 동지들이 있었는데요
Lv1을 진행하며 그 수는 급감해 버렸어요
거의 아래 함수와 같은 수렴률...

그럼에도 불구하고 저는 꿋꿋하게 윈도우 유저로써 자리를 지켰는데요
방끗 팀을 만나고 BE 구성에서 윈도우 3 맥북 1 조합에 내심 기뻐했었죠
하지만 한 달이 지나자

어라? 왜 나 혼자 윈도우야?

맥북 2명이 자연 발생하여 윈도우 1 맥북 3 조합이 되었습니다
그리하여 슬퍼진 윈도우 유저의 글 시작합니다

LocalDateTime NonoSecond와 OS 간의 상관 관계

문제 상황은 다음과 같습니다

이렇게 간헐적으로 최신식으로 조회하는 테스트가 깨지는 상황이 발생하였습니다
최신순으로 조회하는 테스트가 대략 4개정도 있는데,
1개부터 4개까지 랜덤하게 깨지는 문제점이 있었어요

이러한 테스트가 있으면 아티클이 1번부터 4번까지 차례대로 저장되고
조회했을 때는 4번부터 1번까지 최신순인 역순으로 조회되어야 하는데
실제로 조회할 때는 순서가 뒤죽박죽인 문제가 있었어요

특히 이 문제는 저에게만 발생하고 방끗 BE 타 크루에게는 발생하지 않으며
간헐적 발생으로 재현이 쉽지도 않아서 해결에 어려움을 겪었습니다

저는 실제로 블로그 글 작성을 위해 10번 테스트를 돌렸으나 한 번만 재현에 성공했으며

위와 같이 createdAt으로 정렬하기 때문에 해당 값의 문제일 거라 생각하고 로그를 찍어 보았습니다

재현하지 못한 관계로 지금은 정상적으로 값이 식별 가능하게 찍히지만
당시에는 뒤에 부분 00을 제외한 모든 시간이 일치했어요

반면 맥북에서 로그를 찍었을 때는 6자리만 노출되는 것을 볼 수 있습니다

위 사안들로 추측해 볼 때 LocalDateTime 클래스가 OS 별로 다르게 동작하고 이에 관련한 문제가 있구나! 를 알 수 있었어요

이를 위해서 AuditingEntityListener.class를 파 보았습니다
해당 클래스는

영속성을 하기 전에 markedCreated 함수를 호출하는데요

해당 함수는 AuditingHandler에 구현되어 있고 이것은 AuditingHandlerSupport를 extends 합니다

AuditingHandlerSupport 함수에는 setDateTimeProvider가 있는데
이 함수는 CurrentDateTimeProvider를 사용하고 있고

해당 함수는 바로 LocalDateTime.now()를 사용하고 있어요!

그렇다면 이것이 OS에 종속적인 걸까? 추측해 볼 수 있는데요

구현체를 보면 LocalDateTime.now()를 구현할 때 해당 함수를 사용하고 있는데 해당 함수는 "the granularity of the value depends on the underlying operating system" 라는 언급에 따라 정밀도가 OS에 따라 달라질 수 있음을 알 수 있어요

그렇다면 WINDOW와 MAC은 어떻게 다를까요?

Window의 경우 default timer가 15.6ms 임을 알 수 있습니다
즉, 15.6ms의 오차가 발생할 가능성이 있으며 위 로그와 같이 아래 2자리수는 반올림되어 00으로 채워집니다

반면에 MacOS의 경우, 오차에 관한 자료를 찾지 못하였으나 대략 1ms까지 정확성을 보장해 준다는 자료를 보았습니다
MacOS에서 Mach라는 커널을 이용해서 TIMER를 측정한다고 합니다
하지만 위 로그와 같이 아래 3자리수는 반올림되어 000으로 채워집니다

따라서 OS에 따라 정밀도가 달라 오류가 발생했다

위와 같이 정리하고 갈 수 있을 것 같네요

macOS에서 타이머 해상도가 1ms 단위까지 측정되기 때문에, 반올림 과정에서 insert 활동에 따른 지연이 발생하고 이로 인해 값이 식별 가능할 정도의 오차가 있었던 것으로 추측돼요

반면, 윈도우에서는 기본 타이머 해상도가 15.6ms로, 이로 인해 측정 시 발생하는 오차가 크기 때문에 여러 값이 동일하게 나타날 가능성이 높아졌을 것이라고 추측됩니다

해당 부분에 대해 더 탐구해 보고 싶었으나 low level의 자료라 서치가 쉽지 않았어요
혹시 자료를 보충해 주실 수 있는 분은 댓글 남겨 주세요

그렇다면 이 문제를 어떻게 해결했나?

시간이 모두 같으면 정렬을 랜덤으로 해 주어서 테스트가 실패했습니다
해당 상황을 방지하기 위해 저리는 쿼리에 ID로 정렬한다는 부분을 추가해 주었어요

이를 통해 늘 같은 순서를 보장할 수 있었습니다

추후 자료 보충이 있을 예정입니다! (확실치는 않아요)
탐구 끝!

profile
💻 늘 공부하고 발전하는 개발자

0개의 댓글