LocalDateTime 어이없는 실수

Gyeongjae Ham
3 min readJul 23, 2024

--

항상 고정된 시간이 출력된다?? nano 초도 아예 똑같이??

문제 상황

유저의 활동 스트림을 최근 3일로 요약해서 보여주는 탭에서 날짜가 도커 컨테이너가 시동되는 시점에 고정되는 버그를 발견했습니다

해결 시도

컨테이너 시간 서버 로컬 시간과 일치 시키기

원래 컨테이너 내부의 localtime과 서버의 localtime을 일치 시켜서 컨테이너 내부의 시간을 맞추도록 했었습니다. 이번 이슈가 발생하고 서버에서 date 명령어를 찍었을 땐 KST로 설정대로 잘 나오고 있었습니다. 그런데 컨테이너 내부의 시간은 UTC로 출력이 되고 있었습니다. Docker Compose의 설정은 /etc/localtime:/etc/localtime 이었습니다.

Timezone으로 일치 시키기

구글링을 좀 해보니 컨테이너 내부의 시간을 맞출 경우 /etc/localtime보다는 /etc/timezone으로 맞추는게 더 좋다는 피드백을 보았습니다. 바로 적용해보았더니 여전히 UTC로 출력이 되고 있었습니다.

Dockerfile에서 tzdata 설치하기

컨테이너 내부의 시간을 동적으로 사용하려면 tzdata를 설치하고, 서버의 원하는 TZ의 zoneinfo를 컨테이너 내부의 localtime으로 복사하고, timezone에 TZ를 덮어써주는 설정을 진행했습니다.

ENV TZ=Asia/Seoul
RUN apk add --no-cache tzdata && \
cp /usr/share/zoneinfo/$TZ /etc/localtime && \
echo $TZ > /etc/timezone

이렇게 생성한 이미지로 컨테이너를 시동하니 내부의 시간이 서버와 동일하게 동작하기 시작했습니다

문제 다시 파악

그럼에도 API 동작을 했을 때는 시간이 고정적으로 출력되고 있었습니다. ‘분명 System의 시간을 불러오는 LocalDateTime인데 어떻게 고정값일 수가 있는걸까’ 고민을 하다가 나노초까지 고정값인게 이상해서 생각하던 중 머리를 스치는 게 있었습니다. 프로젝트 전체에서 사용한다고 Util Class로 Date 관련 정의를 할 때 해당 변수들을 final로 지정한 것이었습니다.

굉장히 멍청하다고 자책하면서 해당 final 키워드를 모두 제거한 후에 @Component를 붙이고 Bean에 등록되도록 했습니다?? 값은 여전히 고정이 될 수밖에 없었습니다 싱글톤 객체가 생성되면서 초기화된 값을 인스턴스 변수가 들고 있을테니까요. 너무 생각없이 디버깅을 했고, 다시 반성하면서 그냥 Class로 선언 후 사용지점에서 초기화해서 사용하도록 변경했습니다.

테스트 코드 검증을 다 돌리고 나서 개발 서버 배포 후 API 테스트를 진행했습니다 잘 동작한 것을 확인했습니다ㅜㅜ

회고로 남겨놓고 좀 더 생각하면서 개발하도록 다짐하겠습니다. 저번 로그인 이슈 때도 그렇고 습관적으로 Bean 등록하려는 태도를 고쳐야겠습니다.

--

--