UTC 시간과 timezone, DB설정

Joowon Jang·2025년 7월 28일

최근 현업에서 일하면서 많은 것들을 공부하는 중...
프로젝트에 큰 문제가 있었으니...

Next.js 로 만든 프로젝트 하나에서 어떤 곳에는 시간이 정상적으로 표시되고,
어떤 곳에서는 등록한 시간과 9시간이 차이가 나고...
파헤쳐보니, DB에 시간을 저장할 때 쓰는 코드나 테이블의 컬럼 타입이 모두 다르고 개발자마다 제각각으로 쓰고 있었고, 아무도 모르고 있었다;;
내가 먼저 발견하고 왜 이런 문제가 발생하는지, 어떻게 해결해야 좋을지 공부하고 있었던 내용을 말했더니 자연스럽게 내가 맡아서 표준을 만들기로 했다.
(이 사람들 지금까지 어떻게 진행한거지? 싶었지만 아무튼 이 기회에 배워가자)

문제 상황

  • 브라우저, 서버, DB 간 시간대(timezone)의 차이가 있음
  • 코드에서 시간 데이터를 처리하는 방식이 일정하지 않음
  • pg-promise 라이브러리를 사용해 DB를 조작하는데, timestamp without timezone 컬럼을 UTC로 해석함에 따라 조회 시 9시간이 줄어듬
// 예시 상황
18시에 DB에 현재 시각을 삽입한다면,

/* timestamp without timezone 컬럼 (DB 시간대 설정 상관x) */
// JavaScript 기본 Date 객체
- new Date().toISOString() -> 9시로 저장됨 -> 조회하면 00시로 보임
// moment 라이브러리
- moment().mormat() -> 18시로 저장됨 -> 조회하면 09시로 보임
// SQL
- NOW() -> 9시로 저장됨 -> 조회하면 00시로 보임

/* timestamp with timezone (timestamptz) 컬럼 - DB 시간대 UTC */
- 모든 방법이 동일하게 09시로 저장됨 -> 조회하면 09시로 그대로 보임

/* timestamp with timezone (timestamptz) 컬럼 - DB 시간대 Asia/Seoul */
- 모든 방법이 동일하게 18시로 저장됨 -> 조회하면 09시로 보임

여러 케이스가 있고, pg-promise 라이브러리의 시간 처리 때문에 너무 헷갈렸다...
(JavaScript의 기본 Date 객체로 처리한다고 한다. timestamp without timezone을 한국 시간으로 인식한건지 9시간을 줄여버림)
"DB와 통신하는 라이브러리를 바꾸면 되지 않을까?" 했지만, PostgreSQL 자체의 문제라고 해서 바로 기각!

해결

  • 이미 진행된 개발에 영향을 최소화하기 위해, 여러 방식으로 시간 데이터를 처리하더라도 문제가 발생하지 않도록 하기
  • DB에서 조회한 시간 데이터를 수정하여 다시 DB에 저장할 때 기준이 변경되지 않도록 하기

DB 설정

timestamptz 타입 컬럼 사용

timezone이 없는 일반 timestamp 타입의 컬럼을 사용하면 JavaScript코드에서 어떤 방식을 사용하는지에 따라 예상과 다르게 변경되는 문제가 있기 때문에 모든 시간 데이터는 timestamptz타입을 사용하기로 했다.

UTC 시간대로 설정

DB의 시간대를 Asia/Seoul로 설정하게 되면 여러 상황에 문제가 발생할 수 있음

예를 들어, 아래와 같이 클라이언트 또는 API 서버가 UTC 시간 문자열을 전달한다면,

const now = new Date().toISOString(); 
// "2025-07-25T03:00:00.000Z" (UTC)

이 문자열을 DB에 바로 저장한다면:
(DB 세션 시간대: Asia/Seoul)

DB는 이 값을 UTC 기준으로 해석하지 않고 → Asia/Seoul 기준 시간으로 잘못 해석

→ 9시간 밀린 값이 실제로 저장됨

📌 즉, 2025-07-25T03:00:00Z2025-07-25 03:00:00 +09:00 으로 저장됨
→ 실제로는 9시간 뒤인 시간으로 저장됨

이런 예상하기 힘든 오류를 예방하기 위해 DB의 시간대를 UTC시간으로 설정하고, 모든 시간 연산을 UTC 기준으로만 처리한다.

SET TIME ZONE 'UTC'; // DB 시간대 변경
SHOW TIME ZONE; // DB 시간대 설정 확인

그리고 클라이언트 화면에 보여줄 때에만 Date.prototype.toLocaleString() 등으로 처리하여 한국 시간에 맞게 보여주기로 함.
(formatDate라는 이름으로 공통 유틸함수를 만들어 YYYY-MM-DD, YYYY-MM-DD HH:MM 등의 형태로 출력하기로 했다.)

마치며

어떤 케이스에서 시간이 달라지는지, 또 예상치못한 오류가 발생할만한 상황이 어떤 것들이 있을지 모두 고려하면서 고민을 많이 했었다.
팀원들에게 개발에 불편함을 최소화하고 타당한 이유를 설명해주기 위해, 여러 방법을 찾고, 사람들이 많이 사용하는 방법은 왜 그렇게 사용하는지도 꼼꼼하게 정리하면서 나중에 같은 문제가 발생하지 않게 미리 방지할 수 있게 되었다고 생각하니 "개발은 역시 이런 뿌듯함에 하는거지"하고 또 재미를 찾은 것 같다.

하지만 아직 브라우저, 서버, DB의 시간을 어떻게 사용해야 좋을지 완벽하게는 모르겠다...

다음에는 실무에서 겪은 또 다른 문제 해결 포스팅 예정!
진짜 내가 만들었지만 기가 막힙니다 크...

profile
깊이 공부하는 웹개발자

0개의 댓글