목차
팻말에 적힌 +9가 정확히 무슨 뜻인지 이번 글에서 못 박는다. 시리즈에서 가장 자주 헷갈리는 자리다.
0을 어디에 둘 것인가
큰 시계가 세는 수는 그 자체로 몇 시가 아니다. 사람이 읽으려면 어딘가를 기준선으로 정해야 한다.
세상이 고른 기준선이 UTC다. 큰 시계의 값을 달력 시각으로 펼칠 때 아무것도 더하거나 빼지 않은 상태, 그게 UTC 시각이다.
큰 시계 값 1759208400
↓ 아무것도 안 더하고 펼치면
UTC 2025-09-30 06:00:00UTC는 어느 나라의 시각도 아니다. 재는 자에 가깝다. 지구 위 어느 지점의 생활 시간이 아니라, 모든 팻말이 자기 숫자를 매길 때 기준으로 삼는 0점이다.
GMT와 UTC는 왜 이름이 둘인가
같은 것을 가리키는 것처럼 쓰이지만 출신이 다르다.
- GMT는 천문에서 왔다. 그리니치에서 해를 관측해 정한 시각이다
- UTC는 원자시계에서 왔다. 세슘 원자의 진동을 세어 정한다
원자시계가 훨씬 고르기 때문에 기준이 UTC로 옮겨 갔다. 다만 원자시계가 세는 시간과 지구 자전은 서서히 어긋나므로, 가끔 윤초를 끼워 둘의 차이를 1초 안으로 붙잡아 둔다.
일상에서는 둘을 같은 것으로 봐도 거의 문제가 없다. 다만 글로 적을 때는 UTC를 쓴다. GMT는 영국의 겨울철 지역 시각 이름으로도 쓰여서, 여름이 되면 영국은 GMT가 아니라 한 시간 앞선 시각을 쓴다. 이름 하나가 두 가지를 가리키면 그 자리에서 사고가 난다.
팻말의 숫자가 오프셋이다
오프셋은 UTC에서 몇 시간 몇 분을 더하거나 빼면 그 지역 시각이 되는지를 적은 숫자다.
UTC 2025-09-30 06:00
+09:00 2025-09-30 15:00 (서울)
-04:00 2025-09-30 02:00 (뉴욕, 이 시점 기준)적는 꼴은 +09:00처럼 부호와 시:분이다. 오프셋이 0이면 +00:00이라 적거나 Z 한 글자로 줄여 적는다. 2025-09-30T06:00:00Z에서 끝의 Z가 그것이다.
그리고 오프셋이 시간 단위로 딱 떨어지지 않는 곳도 많다. 인도는 +05:30, 네팔은 +05:45, 뉴펀들랜드는 -03:30이다. “시차는 정수 시간”이라고 가정한 코드는 이 지역들에서 깨진다.
오프셋은 시간대가 아니다
이 시리즈에서 가장 중요한 구분이다. 그리고 비유가 크게 깨지는 자리이기도 하다.
공항 벽의 팻말은 한 번 붙이면 그대로일 것 같다. 실제로는 같은 도시의 팻말 숫자가 계절마다 바뀐다.
America/New_York
규칙 묶음 - 시기마다 값이 정해져 있다
−05:00
값 하나 - 찍은 순간에 묶인다
지역 이름은 시기마다 값이 달라지는 규칙이고, 오프셋은 한 순간을 찍어 굳힌 값이다. 같은 것으로 알고 저장하면 반년이 밀린다.
+09:00은 어느 한 순간의 차이만 적은 값이다. 사진 한 장이다. 반면 Asia/Seoul은 규칙 묶음이다. 어느 기간에 오프셋이 얼마이고 언제 바뀌는지가 전부 들어 있다.
| 무엇을 담나 | 언제 쓰나 | |
|---|---|---|
오프셋 +09:00 | 그 순간의 차이 하나 | 이미 일어난 순간을 적을 때 |
시간대 Asia/Seoul | 시기별 오프셋 규칙 전부 | 앞으로 일어날 시각을 정할 때 |
서울은 지금 1년 내내 +09:00이라 이 구분이 잘 안 느껴진다. 뉴욕은 다르다. 여름에는 -04:00, 겨울에는 -05:00이다. 뉴욕의 오프셋을 하나로 적을 방법이 없다.
지나간 순간에는 오프셋으로 충분하다
그렇다고 오프셋이 열등한 것은 아니다. 이미 일어난 일을 적을 때는 오프셋이면 완전하다.
2025-09-30T15:00:00+09:00은 어떤 순간인지가 하나로 정해진다. 큰 시계의 값 하나로 되돌릴 수 있고, 나중에 규칙이 바뀌어도 이 값의 뜻은 변하지 않는다. 로그, 결제 시각, 생성 시각처럼 일어난 일은 이 꼴이면 충분하다.
문제는 앞으로 일어날 일이다.
미래를 오프셋으로 적으면 틀어진다
“2026년 3월 20일 뉴욕 시각 오전 9시에 회의”를 저장한다고 하자.
지금이 겨울이라 뉴욕 오프셋이 -05:00이니, 이걸 그대로 굳혀서 2026-03-20T09:00:00-05:00으로 저장했다. 그런데 3월 20일은 이미 서머타임이 시작된 뒤라 그날 뉴욕의 오프셋은 -04:00이다.
저장된 값이 가리키는 순간은 현지 오전 8시가 된다. 한 시간 일찍 알림이 가고, 아무도 없는 회의실이 열린다.
여기서 필요한 건 오프셋이 아니라 “뉴욕이라는 장소” 그 자체다. 규칙이 바뀌더라도 그 시점의 규칙으로 다시 계산되어야 하기 때문이다.
실무에서: 무엇을 저장할지가 갈린다
정리하면 저장할 값은 그 값이 과거를 가리키냐 미래를 가리키냐로 갈린다.
// 일어난 일: 순간 하나면 끝난다
Instant paidAt = Instant.now();
// 앞으로 일어날 일: 장소를 같이 저장한다
LocalDateTime localWhen = LocalDateTime.of(2026, 3, 20, 9, 0);
ZoneId where = ZoneId.of("America/New_York");
// 실제 순간은 필요할 때마다 규칙으로 다시 계산한다
Instant actual = localWhen.atZone(where).toInstant();경계에서 지킬 것은 셋이다.
- 주고받을 때는 오프셋을 반드시 붙인다. 오프셋 없는
2026-03-20 09:00은 값의 뜻이 안 정해진 상태다 - 미래 일정은 오프셋만 굳히지 않는다. 지역 이름을 같이 남긴다
Z로 끝나는 값을 지역 시각으로 착각하지 않는다.Z는 UTC 기준이라는 표시지 서울 시각이 아니다
반대 실수도 흔하다. 이미 일어난 일에까지 지역 이름을 붙여 저장하면 값이 무거워지고 비교가 번거로워진다. 지나간 순간은 수 하나가 가장 정확하고 가장 싸다.
정리
- UTC는 기준선이다. 어느 나라의 시각도 아니고, 모든 팻말이 숫자를 매기는 0점이다.
- GMT는 천문, UTC는 원자시계에서 왔다. 글로 적을 때는 UTC를 쓴다.
- 오프셋은 그 순간의 차이 하나다.
+09:00,Z, 그리고 30분·45분짜리도 있다. - 오프셋과 시간대는 다르다. 오프셋은 사진 한 장, 시간대는 규칙 묶음이다.
- 지나간 일은 오프셋으로 충분하고, 앞으로 일어날 일은 장소가 필요하다.
다음 글은 그 규칙 묶음을 연다. 팻말의 숫자를 누가 정하고, 왜 그 목록을 컴퓨터가 따로 들고 다녀야 하는지를 본다.