사전 RFC 3339
포맷

RFC 3339

gabury1고친 사람 github-actions[bot]

RFC 3339 는 시스템끼리 날짜와 시각을 주고받을 때 받는 쪽이 한 가지로만 읽게 해 줍니다. 2026-09-24T14:30:00+09:00 같은 문자열 한 줄이 이 규칙을 따른 값입니다. 날짜 표기 국제 표준에서 꼴을 하나만 골라 인터넷에서 쓰도록 정해 두었습니다.

쉽고 빠른 이해

RFC 3339 는 날짜와 시각을 문자열로 적는 꼴을 하나로 못박은 규칙입니다. 서울에서 9월 24일 오후 2시 30분은 2026-09-24T14:30:00+09:00 한 가지로만 적습니다.

이게 없으면 보내는 쪽과 받는 쪽이 서로 다른 꼴로 적고 읽습니다. 10/11/1996 은 나라에 따라 10월 11일로도, 11월 10일로도 읽힙니다. 어느 지역 시각인지 안 적힌 값은 어느 순간인지 가릴 수 없습니다.

적는 차례는 셋입니다.

  1. 연·월·일을 하이픈으로 잇고 자릿수를 다 채웁니다
  2. 글자 T 를 두고 시·분·초를 콜론으로 잇습니다
  3. 끝에 세계 기준 시각과 몇 시간 차이 나는지를 붙입니다

대가는 고를 수 있는 것이 거의 없다는 점입니다. 주 단위 날짜나 기간은 적지 못합니다. 「서울」 같은 지역 이름도 담지 못합니다.

상세

이 절은 RFC 3339 문자열 한 줄을 조각으로 나눠 읽는 데서 시작합니다. 이어서 조각마다 붙은 제약, 끝에 붙는 꼬리, 글자 순서로 정렬되는 성질을 차례로 봅니다. 마지막으로 원본 국제 표준에서 무엇을 덜어냈는지, RFC 3339 로 담지 못하는 값이 무엇인지 봅니다.

RFC(Request for Comments)는 인터넷 기술의 규칙을 번호를 붙여 펴내는 문서 묶음입니다. 3339 는 그 번호입니다. 이 문서의 제목은 「인터넷의 날짜와 시각: 타임스탬프」입니다.

타임스탬프는 어떤 일이 일어난 순간을 적어 둔 값입니다. 로그 한 줄 맨 앞의 시각이나 서버 응답의 createdAt 필드가 그런 값입니다. RFC 3339 는 이 값을 글자로 적는 방식을 정합니다.

날짜 표기가 갈리는 문제

날짜를 적는 차례는 나라마다 다릅니다. 10/11/1996 한 줄은 미국에서는 10월 11일로, 유럽 여러 나라에서는 11월 10일로 읽힙니다. 사람이 읽기 편한 꼴이 시스템끼리 주고받기에도 맞는 것은 아닙니다.

이 갈림을 없애려고 만든 국제 표준이 ISO 8601 입니다. ISO(International Organization for Standardization, 국제표준화기구)가 펴낸 날짜·시각 표기 표준입니다. 8601 은 그 문서 번호입니다. 연·월·일처럼 큰 단위부터 적게 해서 차례를 하나로 맞춥니다.

그런데 ISO 8601 은 같은 순간을 여러 꼴로 적게 허용합니다. 구분 기호를 빼거나, 뒤쪽 조각을 떼거나, 날짜를 주 단위로 세어도 됩니다. 쓰는 쪽에는 편하지만 읽는 쪽에는 짐이 됩니다.

문자열을 읽어 값으로 바꾸는 코드를 파서라고 부릅니다. 받는 쪽 파서가 이 여러 표기를 전부 읽으려면 코드가 복잡해집니다. 드물게 쓰는 표기일수록 시험을 덜 받아서 그 표기를 읽는 코드에 버그가 숨기 쉽습니다.

ISO 8601 의 프로파일

RFC 3339 는 ISO 8601 에서 한 벌만 골라냅니다. 큰 규격에서 일부만 골라 쓰기로 정한 묶음을 프로파일이라고 부릅니다. RFC 3339 는 ISO 8601 의 프로파일입니다.

아래 본문에서 괄호 안의 대문자 낱말은 요구가 얼마나 센지를 나타냅니다. 이 세 낱말은 여러 RFC 가 같은 뜻으로 함께 씁니다. 그 뜻을 모아 둔 문서가 RFC 2119 입니다.

낱말 뜻
MUST 반드시 지켜야 한다
SHOULD 이유가 있으면 어겨도 되는 권고다
MAY 해도 되고 안 해도 되는 선택이다

새로 만드는 인터넷 프로토콜에는 날짜와 시각을 이 형식으로 적기를 권합니다(SHOULD).

문자열 한 줄의 조각

먼저 값 하나를 조각으로 나눠 봅니다. 아래는 서울에서 찍은 한 순간을 1000분의 1초까지 적은 값입니다.

2026-09-24T14:30:00.250+09:00

이 줄은 날짜와 시각 둘로 나뉩니다. 그 사이를 글자 T 가 가릅니다. 시각 쪽은 다시 시·분·초와 끝에 붙는 꼬리로 나뉩니다. 그 꼬리가 오프셋입니다. 이 시각이 세계 기준 시각과 몇 시간 차이 나는지를 적은 값입니다. 자세한 뜻은 아래 소절에서 봅니다.

flowchart TD
    DT["date-time · 2026-09-24T14:30:00.250+09:00"]
    DT --> FD["full-date · 날짜 · 2026-09-24"]
    DT --> T["구분 글자 · T"]
    DT --> FT["full-time · 시각 · 14:30:00.250+09:00"]
    FT --> PT["partial-time · 시·분·초 · 14:30:00.250"]
    FT --> TO["time-offset · 오프셋 · +09:00"]

그림의 영어 이름은 조각마다 붙은 문법 이름입니다. 한 줄 전체가 date-time 입니다. 날짜 부분은 full-date, 시각 부분은 full-time 입니다. full-time 은 시·분·초인 partial-time 과 오프셋인 time-offset 으로 이루어집니다. 다른 규격이 「RFC 3339 의 date-time」이라고 쓰면 이 한 줄 전체를 가리킵니다.

조각 하나하나에는 자릿수와 쓸 수 있는 값이 정해져 있습니다.

조각 예 숫자 개수와 범위
연 2026 숫자 넷
월 09 숫자 둘, 01~12
일 24 숫자 둘, 01 부터 그달의 마지막 날까지
시 14 숫자 둘, 00~23
분 30 숫자 둘, 00~59
초 00 숫자 둘, 보통 00~59
초 아래 .250 점 뒤에 숫자 하나 이상. 생략할 수 있다
오프셋 +09:00 Z, 또는 부호·시·콜론·분

표에서 생략할 수 있는 조각은 초 아래 하나뿐입니다. 나머지는 모두 적어야 합니다. 9월처럼 숫자 하나로 끝나는 값은 앞에 0 을 채워 09 로 맞춥니다.

빈칸 없이 채우는 칸

RFC 3339 는 조각을 거의 다 필수로 만들어서 단순해집니다. 이 소절은 자릿수를 채워야 하는 까닭과 값의 범위가 좁혀진 대목을 봅니다.

연도는 반드시 숫자 넷으로 적습니다(MUST). 옛 프로그램에는 저장 공간을 아끼려고 연도를 끝 두 자리로만 다루는 것이 많았습니다. 그렇게 99 를 받은 쪽은 1999년인지 2099년인지 짐작해야 합니다.

연도를 1900 을 뺀 값으로 들고 있다가 그대로 적는 프로그램도 있었습니다. 1999년은 99 로 나오지만 2000년에는 100 이라는 숫자 셋이 나옵니다. 숫자 넷을 강제하면 이런 값이 모양 검사에서 바로 걸립니다.

시는 00 부터 23 까지만 씁니다. ISO 8601 은 하루의 끝을 24:00 으로 적는 것도 허용합니다. RFC 3339 는 헷갈림을 줄이려고 그 값을 뺐습니다.

일의 상한은 달과 해에 따라 바뀝니다. 2월은 평년이면 28일까지입니다. 윤년이면 29일까지입니다. 그래서 2026-02-30 은 모양은 맞아도 올바른 날짜가 아닙니다. 파서는 모양을 본 뒤 달력까지 확인해야 합니다.

초 칸에는 60 도 들어갑니다. 지구 자전에 맞춰 시계를 고치려고 한 분을 61초로 늘리는 날이 있습니다. 그 끼워 넣은 1초를 윤초라고 부릅니다. 1990-12-31T23:59:60Z 가 그런 1초입니다. 거꾸로 1초를 빼는 날에는 58 이 그 분의 마지막 초가 됩니다.

요일은 적지 않습니다. 요일은 날짜에서 계산으로 나오므로, 같이 적으면 둘이 어긋난 값이 생길 수 있습니다. 2026년 9월 24일은 목요일입니다. 여기에 「수요일」이 붙어 오면 받는 쪽은 어느 쪽을 믿을지 정할 수 없습니다.

끝에 붙는 오프셋

같은 14시 30분도 서울과 런던에서는 다른 순간입니다. 이 소절은 시각 끝의 꼬리가 어느 순간인지를 어떻게 못박는지 봅니다.

기준은 UTC(Coordinated Universal Time, 협정 세계시)입니다. 세계가 함께 기준으로 삼는 시각입니다. 지역마다 쓰는 시각은 UTC 보다 몇 시간 앞서거나 뒤집니다. 서울 시각은 UTC 보다 9시간 앞섭니다.

오프셋은 지역 시각에서 UTC 를 뺀 값입니다. 그러니 적힌 시각에서 오프셋을 빼면 UTC 시각이 나옵니다. 오프셋이 마이너스이면 빼는 대신 그 절댓값을 더합니다.

2026-09-24T14:30:00+09:00   // 서울 시각
2026-09-24T05:30:00Z        // 같은 순간
2026-09-23T22:30:00-07:00   // 같은 순간

세 줄은 글자가 달라도 한 순간을 가리킵니다. 둘째 줄 끝의 Z 는 오프셋이 0 이라는 표시입니다. 가리키는 순간은 +00:00 과 같습니다. 셋째 줄은 UTC 보다 7시간 늦은 지역에서 읽은 시각이라 날짜가 하루 이릅니다(23일).

오프셋은 숫자로만 적습니다. 한국 표준시를 뜻하는 KST 처럼 글자로 지역 시각을 적는 방식은 받는 쪽이 모르는 약칭이 섞여 서로 못 읽는 일이 잦았습니다. 그래서 RFC 3339 는 글자 약칭을 받지 않습니다.

date-time 에는 오프셋이 꼭 붙습니다. 어느 지역 시각인지 모르는 값은 지구 대부분의 지역에서 틀리게 읽히기 때문입니다. 오프셋 없이 시·분·초만 적은 partial-time 은 다른 규격이 조각으로 가져다 쓰는 부품일 뿐입니다.

Z 와 +00:00 과 -00:00

UTC 와의 차이가 0 이라고 적는 방법은 셋입니다. 가리키는 순간은 셋 다 같습니다. 이 소절은 RFC 3339 가 셋에 어떤 뜻을 따로 얹는지, 그 뜻이 어떻게 바뀌었는지 봅니다.

처음 나온 판에서는 Z 와 +00:00 이 같은 뜻이었습니다. 둘 다 「이 시각은 UTC 를 기준으로 삼았다」는 표시였습니다. UTC 시각은 알지만 원래 지역의 오프셋을 모를 때는 -00:00 을 쓰게 했습니다. 이메일 헤더의 날짜에서 쓰던 관례를 가져온 것입니다.

그런데 ISO 8601 은 -00:00 이라는 오프셋을 허용하지 않습니다. 그래서 ISO 8601 파서가 이 값을 받아 주리라 기대하기 어렵습니다. 같은 뜻을 적어야 하는 구현들은 대신 Z 를 쓰는 경향이 있었습니다. 2024년에 나온 RFC 9557 이 이 관행에 맞춰 RFC 3339 의 뜻풀이를 고쳤습니다.

꼬리 지금의 뜻
Z UTC 시각은 알지만 원래 지역의 오프셋은 모른다
+00:00 그 일이 일어난 곳의 지역 시각이 UTC 와 같다
-00:00 Z 와 같은 뜻이다. 대신 Z 를 쓰기를 권한다

표에서 뜻이 바뀐 것은 Z 하나입니다. +00:00 은 지역 시각이 실제로 UTC 와 같은 곳에서 찍은 시각이라고 밝힙니다. 겨울의 런던이 그런 곳입니다. 거기서 오전 9시에 찍은 값과, 지역을 모르는 값을 나란히 두면 이렇습니다.

2026-01-15T09:00:00+00:00 // 지역도 9시
2026-01-15T09:00:00Z      // 지역 모름

두 줄은 같은 순간입니다. 첫 줄은 그 일이 일어난 곳에서도 시계가 9시를 가리켰다는 것까지 알려 줍니다. 둘째 줄은 UTC 로 9시였다는 것만 알려 줍니다. 어느 지역인지는 비워 둡니다.

서버가 모든 시각을 UTC 로 바꿔 Z 로 내보내면, 받는 쪽은 그 일이 원래 어느 지역에서 일어났는지 알 수 없습니다. 원래 오프셋이 필요한 값은 +09:00 처럼 남겨 두어야 그 정보가 살아남습니다.

대소문자와 빈칸

구분 글자 T 와 Z 는 소문자 t·z 로 적어도 문법에 맞습니다. 값을 만드는 쪽에는 대문자를 권합니다(SHOULD). 대소문자를 가리는 환경에서는 RFC 3339 를 가져다 쓰는 규격이 대문자만 받도록 더 좁힐 수 있습니다(MAY).

날짜와 시각 사이에 T 대신 빈칸을 넣는 것도 허용합니다. 사람이 읽기 쉽게 하려는 선택지입니다. 2026-09-24 14:30:00+09:00 처럼 적습니다. 받는 쪽 파서가 T 만 기대하고 짜여 있으면 이 값을 못 읽습니다. 그래서 빈칸을 쓰려면 주고받는 양쪽이 미리 맞춰야 합니다.

글자 순서가 곧 시간 순서

큰 단위를 앞에 두고 자릿수를 고정하면 쓸모 있는 성질이 하나 생깁니다. 문자열을 글자 순서로 정렬한 결과가 시간 순서와 같아집니다. 날짜를 숫자로 바꾸지 않고 문자열 비교만으로 앞뒤를 가릴 수 있다는 뜻입니다.

2026-09-24T09:05:00Z
2026-09-24T14:30:00Z
2026-10-01T00:00:00Z

세 줄은 글자 순서로도 시간 순서로도 이 차례입니다. 연·월·일·시가 늘 같은 칸에 같은 자릿수로 서 있습니다. 그래서 왼쪽부터 한 글자씩 견주면 큰 단위부터 비교하는 셈이 됩니다.

이 성질에는 조건이 셋 붙습니다.

  1. 모든 값의 오프셋이 같아야 합니다
  2. 같은 오프셋은 같은 글자로 적어야 합니다. Z 와 +00:00 이 섞이면 안 됩니다
  3. 초 아래 자릿수가 모두 같아야 합니다

셋째 조건을 어기면 이렇게 됩니다. 아래 두 줄을 글자 순서로 정렬한 결과입니다.

2026-09-24T09:00:00.5Z   // 더 늦은 시각
2026-09-24T09:00:00Z     // 더 이른 시각

두 줄은 초 바로 뒤의 첫 글자에서 갈립니다. 점 . 이 글자 Z 보다 앞 순서라서 0.5초 늦은 값이 앞에 섭니다. 그래서 로그처럼 문자열로 정렬할 값은 흔히 전부 UTC 로 맞추고 초 아래 자릿수를 고정합니다.

ISO 8601 에서 덜어낸 선택지

RFC 3339 는 ISO 8601 확장 형식의 부분집합으로 설계됐습니다. 확장 형식은 하이픈과 콜론으로 조각을 가르는 표기입니다. 앞 소절의 -00:00 과 빈칸 구분은 여기서 벗어나는 예외입니다.

덜어낸 선택지를 모으면 이렇습니다.

ISO 8601 이 허용하는 것 RFC 3339 에서
20260924T143000 처럼 구분 기호를 뺀 꼴 하이픈과 콜론을 넣는다
2026-09 처럼 월까지만 적기 날짜는 연·월·일을 다 적는다
오프셋 없는 시각 date-time 에는 오프셋을 붙인다
하루의 끝을 24:00 으로 적기 시는 00~23
2026-W39-4 처럼 몇째 주 무슨 요일로 적는 주 날짜 없다
2026-267 처럼 그해 몇째 날로 적는 서수 날짜 없다
사흘을 뜻하는 P3D 같은 기간 없다
두 시각을 / 로 이어 적는 구간 없다

덜어낸 기준은 둘입니다. 첫째, 드물게 쓰는 꼴은 시험을 덜 받아 파서 버그가 숨기 쉽습니다. 둘째, 요일처럼 겹치는 정보는 서로 어긋날 수 있습니다. 그래서 거의 모든 칸을 필수로 만들었습니다.

적을지 말지 고를 수 있는 조각은 초 아래 자릿수 하나만 남겼습니다. 소문자 t·z 와 빈칸 구분은 조각을 빼는 선택이 아닙니다. 같은 조각을 다른 글자로 적는 예외입니다.

RFC 3339 가 못 담는 값

RFC 3339 값은 달력 위의 한 순간을 적는 데 맞춰져 있습니다. 이 소절은 여기에 적을 수 없는 값과 그럴 때 쓰는 다른 수단을 봅니다.

먼저 지역 이름입니다. 시간대는 「서울」처럼 한 지역이 따르는 시각 규칙 전체를 가리킵니다. 오프셋은 한 순간의 UTC 와의 차이 하나뿐입니다. 시간대는 그 차이가 언제 어떻게 바뀌는지까지 담습니다.

서머타임은 여름철에 시계를 한 시간 앞당기는 제도입니다. 이 제도를 쓰는 지역은 철마다 오프셋이 바뀝니다. 그래서 여름에 적은 오프셋 숫자 하나로는 같은 지역의 겨울 날짜 시각을 계산할 수 없습니다.

RFC 9557 은 값 끝에 대괄호로 시간대 이름을 덧붙이는 표기를 더했습니다. 2026-09-24T14:30:00+09:00[Asia/Seoul] 처럼 적으면 오프셋과 함께 지역 이름이 실립니다. 대괄호 앞부분은 손대지 않은 RFC 3339 값입니다.

나머지 한계는 표로 모읍니다.

못 담는 값 까닭 대신 쓰는 수단
시간대 이름 오프셋 숫자만 적는다 RFC 9557 의 대괄호 꼬리 · 이름을 따로 저장
기간과 구간 한 순간만 적는다 ISO 8601 의 기간·구간 표기
0000년 앞이나 9999년 뒤 연도가 숫자 넷으로 고정이다 다른 표기
분 단위로 안 떨어지는 옛 오프셋 오프셋이 시와 분만 담는다 담을 수 있는 오프셋으로 바꿔 적기

표 마지막 줄의 옛 오프셋은 표준시를 정하기 전에 쓰던 지역 시각에서 나옵니다. 그때는 도시마다 해의 움직임에 맞춘 시각을 썼습니다. 그래서 UTC 와의 차이가 몇 분 몇 초처럼 딱 떨어지지 않았습니다.

RFC 3339 를 쓰는 값과 안 쓰는 값

JSON(JavaScript Object Notation)에는 날짜 타입이 따로 없습니다. 그래서 날짜는 문자열로 담깁니다. 그 문자열은 흔히 RFC 3339 를 따릅니다. 서로 다른 언어로 짠 시스템도 같은 순간으로 읽습니다.

HTTP(HyperText Transfer Protocol) 헤더의 날짜는 RFC 3339 가 아닙니다. Sun, 06 Nov 1994 08:49:37 GMT 처럼 요일과 달 이름을 적는 HTTP-date 형식을 씁니다. 같은 순간이어도 적는 글자 배열이 다릅니다.

벽시계는 달력 날짜와 시각을 알려 주는 시계입니다. 컴퓨터에서는 운영체제가 들고 있는 현재 시각이 그렇습니다. RFC 3339 문자열에 담는 것은 이 시계가 읽은 시각입니다.

단조 시계는 임의의 시점부터 흐른 시간만 세는 시계입니다. 달력의 어느 순간인지는 모르므로 그 값은 RFC 3339 로 적지 않습니다.

계산이 잦은 값도 문자열로 들고 있지 않습니다. 두 시각의 차이를 구하려면 문자열을 매번 숫자로 되돌려야 하기 때문입니다. 그런 값은 유닉스 시간처럼 기준 시각부터 흐른 초를 세는 숫자로 둡니다. 밖으로 내보낼 때만 RFC 3339 문자열로 적습니다.

관련 항목

RFC 3339 가 기대거나 고치는 표준과 기구

RFC · IETF · ISO · ISO 8601 · RFC 9557 · RFC 2119 · ABNF · RFC 2822 · RFC 5322

RFC 3339 문자열이 기대는 시간 기준

UTC · UTC 오프셋 · 시간대 · 서머타임 · 그레고리력 · 윤초 · 윤년 · 타임스케일 · IANA 시간대 데이터베이스

RFC 3339 가 담거나 덜어낸 시간 값

타임스탬프 · 달력 날짜 · ISO 주 날짜 · 서수 날짜 · 기간 · 시간 구간

같은 순간을 다른 꼴로 적는 표현 수단

유닉스 시간 · 에포크 · HTTP-date · IXDTF

RFC 3339 문자열에 찍히는 시각을 내는 시계

벽시계 · 단조 시계 · 시간과 시계 · NTP · 시계 동기화

RFC 3339 문자열을 싣거나 읽는 데이터 형식과 작업

JSON · 프로파일 · 직렬화 · 파서 · 로그 · 상호운용성 · 문자열 정렬

다른 이름: 인터넷 날짜·시각 형식 · Internet Date/Time Format