TOML v1.0.0 =========== Tom's Obvious, Minimal Language. By Tom Preston-Werner, Pradyun Gedam, et al. 목표 ---------- TOML은 명확한 의미를 가져 읽기 쉬운 최소한의 구성 파일 포맷을 목표로 합니다. TOML은 해시 테이블에 분명하게 대응되도록 설계되었습니다. TOML은 여러 언어에서 데이터 구조로 변환하기에 용이할 것입니다. 목차 ----------------- - [명세](#명세) - [주석](#주석) - [키/값 쌍](#키값-쌍) - [키](#키) - [문자열](#문자열) - [정수](#정수) - [부동소수점](#부동소수점) - [불리언](#불리언) - [오프셋 된 날짜-시간](#오프셋-된-날짜-시간) - [로컬 날짜-시간](#로컬-날짜-시간) - [로컬 날짜](#로컬-날짜) - [로컬 시간](#로컬-시간) - [배열](#배열) - [테이블](#테이블) - [인라인 테이블](#인라인-테이블) - [테이블의 배열](#테이블의-배열) - [파일 확장자](#파일-확장자) - [MIME 타입](#mime-타입) - [ABNF 문법](#abnf-문법) 명세 ---- * TOML은 대소문자를 구별합니다. * TOML 파일은 UTF-8으로 인코딩된 유효한 유니코드 문서여야 합니다. * 공백은 탭(0x09)과 스페이스(0x20)를 의미합니다. * 개행은 LF(0x0A)와 CRLF(0x0D 0x0A)를 의미합니다. 주석 ------- 해시 기호는 문자열의 일부일 때를 제외하면 줄의 뒷부분을 주석으로 표시합니다. ```toml # 이 줄은 전부 주석입니다 key = "value" # 이건 줄 끝에 붙은 주석입니다 another = "# 이건 주석이 아닙니다" ``` 탭이 아닌 제어 문자(U+0000에서 U+0008까지, U+000A에서 U+001F까지, U+007F)는 주석의 일부가 될 수 없습니다. 키/값 쌍 -------------- TOML 문서를 구성하는 주요 요소는 키/값 쌍입니다. 키는 등호의 왼쪽에, 값은 오른쪽에 위치합니다. 키 이름과 값을 둘러싼 공백은 무시됩니다. 키, 등호, 값은 같은 줄에 있어야 합니다만, 일부 값은 여러 줄에 걸쳐 위치할 수 있습니다. ```toml key = "value" ``` 값은 다음 중 하나의 타입을 가져야 합니다. - [문자열](#문자열) - [정수](#정수) - [부동소수점](#부동소수점) - [불리언](#불리언) - [오프셋 된 날짜-시간](#오프셋-된-날짜-시간) - [로컬 날짜-시간](#로컬-날짜-시간) - [로컬 날짜](#로컬-날짜) - [로컬 시간](#로컬-시간) - [배열](#배열) - [인라인 테이블](#인라인-테이블) 지정되지 않은 값은 유효하지 않습니다. ```toml key = # 유효하지 않음 ``` 키/값 쌍 다음에는 개행(또는 EOF)이 와야 합니다. (예외로, [인라인 테이블](#인라인-테이블)을 보세요.) ``` first = "Tom" last = "Preston-Werner" # 유효하지 않음 ``` 키 ---- 키에는 기본 키, 따옴표를 씌운 키, 점을 찍은 키가 있습니다. **기본 키**(**Bare keys**)는 ASCII 문자, ASCII 숫자, 언더스코어, 그리고 대시로만 구성됩니다(`A-Za-z0-9_-`). ASCII 숫자로만 구성된 기본 키(예를 들어, `1234`)도 유효하지만, 항상 문자열로 해석됨에 주의해야 합니다. ```toml key = "value" bare_key = "value" bare-key = "value" 1234 = "value" ``` **따옴표를 씌운 키**(**Quoted keys**)는 기본 문자열이나 리터럴 문자열과 정확히 같은 규칙을 따르며, 더 다양한 키 이름을 사용할 수 있게 해줍니다. 정말 필요할 때를 제외하면 기본 키를 사용하는 것이 권장됩니다. ```toml "127.0.0.1" = "value" "character encoding" = "value" "ʎǝʞ" = "value" 'key2' = "value" 'quoted "value"' = "value" ``` 기본 키는 비어 있을 수 없지만, 따옴표를 씌운 키는 비어 있을 수 있습니다(권장되지는 않습니다). ```toml = "no key name" # 유효하지 않음 "" = "blank" # 유효함, 권장되지 않음 '' = 'blank' # 유효함, 권장되지 않음 ``` **점을 찍은 키**(**Dotted keys**)는 점으로 연결된 기본 또는 따옴표를 씌운 키의 나열입니다. 점을 찍은 키를 이용하면 비슷한 속성들을 서로 묶을 수 있습니다. ```toml name = "Orange" physical.color = "orange" physical.shape = "round" site."google.com" = true ``` 이는 다음 JSON과 대응됩니다. ```json { "name": "Orange", "physical": { "color": "orange", "shape": "round" }, "site": { "google.com": true } } ``` 점을 찍은 키가 정의하는 테이블에 대한 자세한 사항은 아래의 [테이블](#테이블) 섹션을 참조하세요. 점으로 구분된 각 부분을 둘러싼 공백은 무시됩니다만, 공백을 쓰지 않는 것이 권장됩니다. ```toml fruit.name = "banana" # 권장됨 fruit. color = "yellow" # fruit.color와 같음 fruit . flavor = "banana" # fruit.flavor와 같음 ``` 들여쓰기는 공백으로 처리되며, 무시됩니다. 같은 키를 여러 번 정의하는 것은 유효하지 않습니다. ``` # 이렇게 하지 마세요 name = "Tom" name = "Pradyun" ``` 기본 키와 따옴표를 씌운 키는 동등합니다. ``` # 이래도 안됩니다 spelling = "favorite" "spelling" = "favourite" ``` 키가 직접 정의되지 않은 한, 그 키나 키 안의 이름에 값을 쓰는 것이 가능합니다. ``` # 이러면 키 "fruit"에 테이블이 대응됩니다. fruit.apple.smooth = true # 그러므로 테이블 "fruit"에 다음과 같이 값을 추가할 수 있습니다. fruit.orange = 2 ``` ``` # 다음은 유효하지 않습니다 # 여기서는 fruit.apple의 값을 정수로 정의합니다. fruit.apple = 1 # 하지만 여기선 fruit.apple이 테이블인 것처럼 다룹니다. # 정수를 테이블로 바꿀 수는 없습니다. fruit.apple.smooth = true ``` 점을 찍은 키를 어긋난 순서로 정의하는 것은 권장되지 않습니다. ```toml # 유효하지만 권장되지 않음 apple.type = "fruit" orange.type = "fruit" apple.skin = "thin" orange.skin = "thick" apple.color = "red" orange.color = "orange" ``` ```toml # 권장됨 apple.type = "fruit" apple.skin = "thin" apple.color = "red" orange.type = "fruit" orange.skin = "thick" orange.color = "orange" ``` ASCII 숫자만으로도 기본 키를 구성할 수 있으므로, 부동소수점 같아 보이는 점을 찍은 키를 정의하는 것이 가능합니다. 그럴만한 이유가 있는게 아니라면, 그러지 마세요(아마 없을 겁니다). ```toml 3.14159 = "pi" ``` 위 TOML은 다음 JSON에 대응됩니다. ```json { "3": { "14159": "pi" } } ``` 문자열 ------ 문자열을 나타내는 방법은 총 네 가지, 즉 기본, 여러 줄 기본, 리터럴, 그리고 여러 줄 리터럴이 있습니다. 문자열에는 유효한 UTF-8 문자만이 포함되어야 합니다. **기본 문자열**(**Basic strings**)은 큰 따옴표(`"`)로 둘러싸여집니다. 이스케이프될 필요 없는 문자는 모두 사용될 수 있습니다. 이스케이프되어야 하는 문자로는 따옴표, 백슬래시, 탭이 아닌 제어 문자(U+0000에서 U+0008, U=000A에서 U+001F, U+007F)가 있습니다. ```toml str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." ``` 편의를 위해, 자주 사용되는 문자들에 대한 짧은 이스케이프 문자열이 제공됩니다. ``` \b - 백스페이스 (U+0008) \t - 탭 (U+0009) \n - 라인 피드 (U+000A) \f - 폼 피드 (U+000C) \r - 캐리지 리턴 (U+000D) \" - 큰따옴표 (U+0022) \\ - 백슬래시 (U+005C) \uXXXX - 유니코드 (U+XXXX) \UXXXXXXXX - 유니코드 (U+XXXXXXXX) ``` `\uXXXX` 또는 `\UXXXXXXX` 형태를 이용해 어느 유니코드 문자든 이스케이프할 수 있습니다. 이스케이프 코드는 유효한 유니코드 [스칼라 값](https://unicode.org/glossary/#unicode_scalar_value) 이어야 합니다. 다른 모든 이스케이프 문자열은 예약되어 있습니다. 사용된 경우, TOML 구현은 에러를 발생시켜야 합니다. 경우에 따라, 긴 문단을 나타내거나 (예를 들어, 번역 파일) 매우 긴 문자열을 여러 줄에 걸쳐 나타내고 싶을 때가 있습니다. TOML에서는 이를 쉽게 할 수 있습니다. **여러 줄 기본 문자열**(**Multi-line basic strings**)은 양 쪽에 3개의 큰따옴표로 둘러싸이며, 안에 개행을 포함할 수 있습니다. 여는 큰따옴표 바로 다음에 오는 개행은 제거됩니다. 모든 다른 공백과 개행은 유지됩니다. ```toml str1 = """ Roses are red Violets are blue""" ``` TOML 파서는 개행을 플랫폼에 따라 적절한 문자열로 변환해도 됩니다. ```toml # 유닉스 시스템에서는, 위 여러 줄 문자열은 아마 다음과 같을 것입니다. str2 = "Roses are red\nViolets are blue" # 윈도우 시스템에서는, 아마 다음과 같을 것입니다. str3 = "Roses are red\r\nViolets are blue" ``` 공백을 추가하지 않고 긴 문자열을 쓰려고 한다면, "줄 끝 백슬래시(line ending backslash)"를 사용하십시오. 줄에서 공백이 아닌 마지막 글자가 이스케이프되지 않은 `\`일 경우, 이 백슬래시는 다음 공백이 아닌 문자 또는 닫는 따옴표가 나올 때까지의 모든 공백(개행 포함)과 함께 제거됩니다. 기본 문자열에서 유효한 모든 이스케이프 문자열은 여러 줄 기본 문자열에서도 유효합니다. ```toml # 다음 문자열들은 바이트 단위로 동일합니다. str1 = "The quick brown fox jumps over the lazy dog." str2 = """ The quick brown \ fox jumps over \ the lazy dog.""" str3 = """\ The quick brown \ fox jumps over \ the lazy dog.\ """ ``` 이스케이프할 필요가 없는 유니코드 문자는 모두 사용할 수 있습니다. 이스케이프되어야 하는 문자로는 백슬래시와, 탭이나 라인 피드나 캐리지 리턴이 아닌 제어 문자들이 있습니다 (U+0000에서 U+0008, U+000B, U+000C, U+000E에서 U+001F, U+007F). 여러 줄 기본 문자열 안에는 큰따옴표나 2개의 인접한 큰따옴표가 어디에나 나타나도 됩니다. 열거나 닫는 큰따옴표와 인접하게도 나타날 수 있습니다. ```toml str4 = """Here are two quotation marks: "". Simple enough.""" # str5 = """Here are three quotation marks: """.""" # 유효하지 않음 str5 = """Here are three quotation marks: ""\".""" str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\".""" # "This," she said, "is just a pointless statement." str7 = """"This," she said, "is just a pointless statement."""" ``` Windows 경로나 정규표현식을 자주 사용한다면, 백슬래시를 항상 이스케이프하는 것은 매우 귀찮고 틀리기 쉬운 일입니다. 이러한 상황을 위해, TOML은 이스케이프를 아예 처리하지 않는 리터럴 문자열을 포함합니다. **리터럴 문자열**(**Literal strings**)은 작은따옴표로 둘러싸입니다. 기본 문자열과 같이, 리터럴 문자열은 한 줄로 표현되어야 합니다. ```toml # What you see is what you get. winpath = 'C:\Users\nodejs\templates' winpath2 = '\\ServerX\admin$\system32\' quoted = 'Tom "Dubs" Preston-Werner' regex = '<\i\c*\s*>' ``` 이스케이프가 없으므로, 작은따옴표로 둘러싸인 리터럴 문자열은 작은따옴표를 포함할 수 없습니다. 다행히도, TOML은 이 문제를 해결하는 여러 줄 리터럴 문자열을 지원합니다. **여러 줄 리터럴 문자열**(**Multi-line literal strings**)는 양 쪽에 세 개의 작은따옴표로 둘러 싸이며, 개행을 포함할 수 있습니다. 리터럴 문자열과 같이, 이스케이프는 지원하지 않습니다. 여는 작은따옴표 바로 다음에 오는 개행은 제거됩니다. 작은따옴표 사이의 다른 모든 내용은 있는 그대로 해석됩니다. ```toml regex2 = '''I [dw]on't need \d{2} apples''' lines = ''' The first newline is trimmed in raw strings. All other whitespace is preserved. ''' ``` 여러 줄 리터럴 문자열 안 어디에든 1개나 2개의 연속된 작은따옴표가 포함될 수 있지만, 3개 이상의 연속된 작은따옴표는 허용되지 않습니다. ```toml quot15 = '''Here are fifteen quotation marks: """""""""""""""''' # apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # 유효하지 않음 apos15 = "Here are fifteen apostrophes: '''''''''''''''" # 'That,' she said, 'is still pointless.' str = ''''That,' she said, 'is still pointless.'''' ``` 리터럴 문자열에 탭이 아닌 제어 문자는 허용되지 않습니다. 그러므로, 이진 데이터를 표현하려 한다면, Base64나 다른 적절한 ASCII 또는 UTF-8 인코딩을 이용할 것이 권장됩니다. 해당 인코딩을 다루는 방식은 응용 프로그램이 정의합니다. 정수 ------- 양수 앞에는 플러스 기호가 올 수 있으며, 음수 앞에는 마이너스 기호가 옵니다. ```toml int1 = +99 int2 = 42 int3 = 0 int4 = -17 ``` 큰 수를 쓸 때는, 가독성을 위해 숫자 사이에 언더스코어를 쓸 수 있습니다. 각 언더스코어의 양 쪽에는 적어도 하나의 숫자가 와야 합니다. ```toml int5 = 1_000 int6 = 5_349_221 int7 = 53_49_221 # 인도식 표기법 int8 = 1_2_3_4_5 # 유효하지만 권장되지 않음 ``` 0이 아닌 수의 맨 앞에 0이 오는 것은 허용되지 않습니다. 정수 값 `+0`과 `-0`은 유효하며, 접두사 없는 0과 동일합니다. 음이 아닌 정수는 16진수, 8진수, 또는 2진수로도 나타낼 수 있습니다. 이 경우, 앞에 `+`가 오는 것은 허용되지 않으며, 접두사 다음에 `0`이 오는 것은 허용됩니다. 16진수 값은 대소문자를 구분하지 않습니다. 숫자 사이에 언더스코어가 오는 것이 허용되지만, 접두사와 값 사이에 오는 것은 허용되지 않습니다. ```toml # 16진수의 접두사는 `0x` hex1 = 0xDEADBEEF hex2 = 0xdeadbeef hex3 = 0xdead_beef # 8진수의 접두사는 `0o` oct1 = 0o01234567 oct2 = 0o755 # 유닉스 파일 권한을 표기할 때 유용함 # 2진수의 접두사는 `0b` bin1 = 0b11010110 ``` 임의의 64비트 부호 있는 정수(−2^63에서 2^63−1까지) 값은 오차 없이 나타낼 수 있어야 합니다. 오차 발생 없이 정수를 표현할 수 없다면, 에러가 발생해야 합니다. 부동소수점 ----- 부동소수점은 IEEE binary64 값으로 구현되어야 합니다. 부동소수점은 정수 부분(10진 정수와 같은 규칙을 따릅니다), 그리고 그 뒤의 소수 부분 및 지수 부분으로 표현됩니다. 소수 부분과 지수 부분이 모두 있다면, 소수 부분이 앞에 와야 합니다. ```toml # 소수 flt1 = +1.0 flt2 = 3.1415 flt3 = -0.01 # 지수 flt4 = 5e+22 flt5 = 1e06 flt6 = -2E-2 # 둘 다 flt7 = 6.626e-34 ``` 소수 부분은 점, 그리고 그 뒤의 하나 혹은 그 이상의 숫자들입니다. 지수 부분은 E 또는 e, 그리고 그 뒤의 정수 부분(10진 정수 값과 같은 규칙을 따르지만, 앞에 0이 오는 것이 허용됩니다)입니다. 점이 사용된다면, 점 양 쪽에 적어도 하나의 숫자가 와야 합니다. ``` # 유효하지 않은 부동소수점 값들 invalid_float_1 = .7 invalid_float_2 = 7. invalid_float_3 = 3.e+20 ``` 정수와 비슷하게, 언더스코어를 이용해 가독성을 높일 수 있습니다. 각 언더스코어의 양 쪽에는 적어도 하나의 숫자가 와야 합니다. ```toml flt8 = 224_617.445_991_228 ``` 부동소수점 값 `-0.0`과 `+0.0`은 유효하며, IEEE 754에 따르는 값을 가집니다. 특수한 부동소수점 값 또한 표현할 수 있습니다. 항상 소문자입니다. ```toml # 무한대 sf1 = inf # 양의 무한대 sf2 = +inf # 양의 무한대 sf3 = -inf # 음의 무한대 # not a number sf4 = nan # sNaN/qNaN 인코딩은 구현에 맡김 sf5 = +nan # `nan` 과 같음 sf6 = -nan # 유효, 실제 인코딩은 구현에 맡김 ``` 불리언 ------- 불리언은 익숙한 토큰들입니다. 항상 소문자입니다. ```toml bool1 = true bool2 = false ``` 오프셋 된 날짜-시간 ---------------- 특정 순간을 명확하게 표현하기 위해, [RFC 3339](https://tools.ietf.org/html/rfc3339) 형식 오프셋 된 날짜-시간을 사용할 수 있습니다. ```toml odt1 = 1979-05-27T07:32:00Z odt2 = 1979-05-27T00:32:00-07:00 odt3 = 1979-05-27T00:32:00.999999-07:00 ``` 가독성을 위해, 날짜와 시간 사이의 T 구분자를 스페이스 문자로 대체할 수 있습니다 (RFC 3339 5.6 섹션에 의해 허용됩니다). ```toml odt4 = 1979-05-27 07:32:00Z ``` 밀리초 정밀도는 필수적으로 지원되어야 합니다. 그 이상의 정밀도는 구현에 따라 지원될 수도 있습니다. 값의 정밀도가 구현이 지원하는 것 이상인 경우, 지원되지 않는 정밀도 부분은 반올림하지 말고 버려야 합니다. 로컬 날짜-시간 --------------- [RFC 3339](https://tools.ietf.org/html/rfc3339) 형식 날짜-시간에서 오프셋을 생략하면, 타임존이나 오프셋과 무관하게 해당 날짜-시간을 나타내는 값이 됩니다. 추가 정보 없이는 특정한 순간으로 변환될 수 없습니다. 필요한 경우, 특정 순간으로 변환은 구현에 따라 다를 수 있습니다. ```toml ldt1 = 1979-05-27T07:32:00 ldt2 = 1979-05-27T00:32:00.999999 ``` 밀리초 정밀도는 필수적으로 지원되어야 합니다. 그 이상의 정밀도는 구현에 따라 지원될 수도 있습니다. 값이 구현이 지원하는 것 이상의 정밀도를 포함할 경우, 지원되지 않는 정밀도 부분은 반올림하지 말고 버려야 합니다. 로컬 날짜 ---------- [RFC 3339](https://tools.ietf.org/html/rfc3339) 형식 날짜-시간에서 날짜 부분만을 쓸 경우, 타임 존이나 오프셋과 무관하게 그날 전체를 나타내는 값이 됩니다. ```toml ld1 = 1979-05-27 ``` 로컬 시간 ---------- [RFC 3339](https://tools.ietf.org/html/rfc3339) 형식 날짜-시간에서 시간 부분만을 쓸 경우, 타임 존, 오프셋과 날짜와 무관하게 그 시각을 나타내는 값이 됩니다. ```toml lt1 = 07:32:00 lt2 = 00:32:00.999999 ``` 밀리초 정밀도는 필수적으로 지원되어야 합니다. 그 이상의 정밀도는 구현에 따라 지원될 수도 있습니다. 값이 구현이 지원하는 것 이상의 정밀도를 포함할 경우, 지원되지 않는 정밀도 부분은 반올림하지 말고 버려야 합니다. 배열 ----- 배열은 대괄호와 그 안에 든 값들입니다. 공백은 무시됩니다. 배열의 값들은 쉼표로 구분됩니다. 배열은 키/값 쌍에 포함될 수 있는 모든 타입의 값을 가질 수 있습니다. 서로 다른 타입의 값들을 섞을 수 있습니다. ```toml integers = [ 1, 2, 3 ] colors = [ "red", "yellow", "green" ] nested_arrays_of_ints = [ [ 1, 2 ], [3, 4, 5] ] nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ] string_array = [ "all", 'strings', """are the same""", '''type''' ] # 서로 다른 타입을 섞을 수 있습니다 numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ] contributors = [ "Foo Bar ", { name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" } ] ``` 배열은 여러 줄에 걸쳐 나타날 수 있습니다. 배열의 마지막 값 뒤에 쉼표가 오는 것이 허용됩니다 (terminating comma 또는 trailing comma). 값, 쉼표, 그리고 닫는 대괄호 앞에 개행과 주석이 몇 개든 올 수 있습니다. 배열의 값들과 쉼표들 사이의 들여쓰기는 공백으로 처리되며, 무시됩니다. ```toml integers2 = [ 1, 2, 3 ] integers3 = [ 1, 2, # 이래도 됩니다 ] ``` 테이블 ----- 테이블(해시 테이블 또는 딕셔너리라고도 함)은 키/값 쌍의 모음입니다. 테이블의 헤더는 줄에 홀로 있는 대괄호로 둘러싸인 값을 말하며, 테이블은 헤더에 의해 정의됩니다. 배열은 항상 값으로만 나타나므로, 헤더와 구분할 수 있습니다. ```toml [table] ``` 그 아래로부터 다음 헤더나 EOF까지는 그 테이블의 키/값 쌍이 나타납니다. 테이블의 키/값 쌍은 특정한 순서로 나타난다고 보장할 수 없습니다. ```toml [table-1] key1 = "some string" key2 = 123 [table-2] key1 = "another string" key2 = 456 ``` 테이블의 이름을 정하는 규칙은 키의 이름을 정하는 규칙과 같습니다(위에서 [키](#키)의 정의를 볼 수 있습니다). ```toml [dog."tater.man"] type.name = "pug" ``` 이는 다음 JSON과 대응됩니다. ```json { "dog": { "tater.man": { "type": { "name": "pug" } } } } ``` 키 주변의 공백은 무시됩니다. 공백을 쓰지 않는 것이 권장됩니다. ```toml [a.b.c] # 권장됨 [ d.e.f ] # [d.e.f]와 같음 [ g . h . i ] # [g.h.i]와 같음 [ j . "ʞ" . 'l' ] # [j."ʞ".'l']와 같음 ``` 들여쓰기는 공백으로 취급되며 무시됩니다. 상위 테이블을 모두 정의할 필요는 없습니다. TOML이 알아서 해줍니다. ```toml # [x] 이거 # [x.y] 필요 # [x.y.z] 없음 [x.y.z.w] # 이것만 있어도 됨 [x] # 상위 테이블을 나중에 정의해도 괜찮음 ``` 빈 테이블은 허용되며, 안에 키/값 쌍을 포함하지 않습니다. 키와 비슷하게, 같은 테이블을 한 번 이상 정의할 수 없습니다. 그렇게 하는 것은 유효하지 않습니다. ``` # 하지 마세요 [fruit] apple = "red" [fruit] orange = "orange" ``` ``` # 이것도 하지 마세요 [fruit] apple = "red" [fruit.apple] texture = "smooth" ``` 테이블을 어긋난 순서로 정의하는 것은 권장되지 않습니다. ```toml # 유효하지만 권장되지 않음 [fruit.apple] [animal] [fruit.orange] ``` ```toml # 권장됨 [fruit.apple] [fruit.orange] [animal] ``` 최상위 테이블(또는 루트 테이블)은 문서가 시작되는 지점에서 시작되어 첫 테이블 헤더 (또는 EOF) 바로 전에 끝납니다. 다른 테이블들과는 달리, 최상위 테이블에는 이름이 없으며 다시 지정될 수 없습니다. ```toml # 최상위 테이블 시작 name = "Fido" breed = "pug" # 최상위 테이블 끝 [owner] name = "Regina Dogman" member_since = 1999-08-04 ``` 점이 찍힌 키는 마지막을 제외한 정의되지 않은 각 부분에 대해 새 테이블을 정의합니다. ```toml fruit.apple.color = "red" # fruit이라는 테이블을 정의함 # fruit.apple이라는 테이블을 정의함 fruit.apple.taste.sweet = true # fruit.apple.taste라는 테이블을 정의함 # fruit과 fruit.apple은 이미 정의되어 있음 ``` 테이블을 한 번 이상 정의하는 것은 금지되므로, 이러한 테이블을 `[테이블]` 헤더를 사용해 재정의하는 것은 허용되지 않습니다. 비슷하게, `[테이블]` 형식으로 정의된 테이블을 점이 찍힌 키를 사용해 재정의하는 것도 허용되지 않습니다. 하지만, 점이 찍힌 키를 사용해 정의된 테이블 안의 하위 테이블을 `[테이블]` 형태를 이용해 정의하는 것은 허용됩니다. ```toml [fruit] apple.color = "red" apple.taste.sweet = true # [fruit.apple] # 유효하지 않음 # [fruit.apple.taste] # 유효하지 않음 [fruit.apple.texture] # 하위 테이블을 추가할 수 있음 smooth = true ``` 인라인 테이블 ------------ 인라인 테이블은 테이블을 표현하는 데에 쓸 수 있는 더 단순한 구문을 제공합니다. 그냥 쓰기엔 너무 장황한 테이블 데이터를 작성하는데에 특히 유용합니다. 인라인 테이블은 중괄호 `{`와 `}` 사이에 정의됩니다. 중괄호 사이에는 0 또는 그보다 많은 키/값 쌍이 쉼표로 구분되어 나타날 수 있습니다. 키/값 쌍은 일반 테이블의 키/값 쌍과 같은 형태를 가집니다. 값들은 인라인 테이블을 포함한 모든 타입을 가질 수 있습니다. 인라인 테이블은 한 줄에 나타나도록 의도되었습니다. 인라인 테이블의 마지막 키/값 쌍 뒤에 쉼표가 올 수 없습니다. 값의 일부로 유효하게 나타나는 것이 아닌 한, 중괄호 사이에는 개행이 올 수 없으며, 개행이 유효한 경우에도 인라인 테이블을 여러 줄에 걸쳐 작성하는 것은 권장되지 않습니다. 만일 인라인 테이블을 여러 줄에 쓰고 싶다면, 일반 테이블을 써야한다는 뜻입니다. ```toml name = { first = "Tom", last = "Preston-Werner" } point = { x = 1, y = 2 } animal = { type.name = "pug" } ``` 위 인라인 테이블 정의는 아래의 테이블 정의와 동일합니다. ```toml [name] first = "Tom" last = "Preston-Werner" [point] x = 1 y = 2 [animal] type.name = "pug" ``` 인라인 테이블은 그 자체로 완전하며, 모든 키와 하위 테이블을 안에 정의해야 합니다. 중괄호 밖에서 키나 하위 테이블을 추가할 수는 없습니다. ```toml [product] type = { name = "Nail" } # type.edible = false # 유효하지 않음 ``` 비슷하게, 인라인 테이블을 이용해 이미 정의된 테이블에 키나 하위 테이블을 추가할 수 없습니다. ```toml [product] type.name = "Nail" # type = { edible = false } # 유효하지 않음 ``` 테이블의 배열 --------------- 마지막 구문을 이용해 테이블의 배열을 정의할 수 있습니다. 이는 이름이 대괄호 2개로 둘러싸인 헤더를 이용해 표현할 수 있습니다. 첫 헤더는 배열과 그 배열의 첫 테이블 값을 정의하고, 뒤에 따라오는 헤더는 같은 배열의 새 값을 정의합니다. 테이블은 나타나는 순서대로 배열에 삽입됩니다. ```toml [[products]] name = "Hammer" sku = 738594937 [[products]] # 배열 안의 빈 테이블 [[products]] name = "Nail" sku = 284758393 color = "gray" ``` 이는 다음 JSON과 같은 구조입니다. ```json { "products": [ { "name": "Hammer", "sku": 738594937 }, { }, { "name": "Nail", "sku": 284758393, "color": "gray" } ] } ``` 테이블의 배열의 이름을 사용해 그 배열의 가장 최근에 정의된 값을 참조할 수 있습니다. 이를 이용해 가장 최근에 정의된 테이블 안에 하위 테이블, 또는 테이블의 하위 배열을 정의할 수 있습니다. ```toml [[fruits]] name = "apple" [fruits.physical] # 하위 테이블 color = "red" shape = "round" [[fruits.varieties]] # 중첩된 테이블의 배열 name = "red delicious" [[fruits.varieties]] name = "granny smith" [[fruits]] name = "banana" [[fruits.varieties]] name = "plantain" ``` 위 TOML은 다음 JSON과 같습니다. ```json { "fruits": [ { "name": "apple", "physical": { "color": "red", "shape": "round" }, "varieties": [ { "name": "red delicious" }, { "name": "granny smith" } ] }, { "name": "banana", "varieties": [ { "name": "plantain" } ] } ] } ``` 테이블이나 테이블의 배열의 상위 요소가 배열이라면, 그 배열은 하위 요소가 정의되기 전에 먼저 정의되어 있어야 합니다. 이 순서를 거꾸로 하려고 하는 경우, 파싱 시 에러가 발생해야 합니다. ``` # 유효하지 않은 TOML 문서 [fruit.physical] # 서브 테이블, 하지만 상위 요소는? color = "red" shape = "round" [[fruit]] # 파서는 "fruit"이 테이블이 아닌 배열이라는 것을 확인한 시점에 # 에러를 발생시켜야 함 name = "apple" ``` 정적으로 정의된 배열에 값을 추가하려고 하는 것이 발견되면, 파싱 시에 에러가 발생해야 합니다. ``` # 유효하지 않은 TOML 문서 fruits = [] [[fruits]] # 허용되지 않음 ``` 이미 정의된 배열과 같은 이름의 테이블을 정의하려고 하는 경우 파싱 시에 에러가 발생해야 합니다. 동일하게, 테이블을 배열로 재정의하고자 하는 경우에도 파싱 시 에러가 발생해야 합니다. ``` # 유효하지 않은 TOML 문서 [[fruits]] name = "apple" [[fruits.varieties]] name = "red delicious" # 유효하지 않음: 이 테이블은 직전의 테이블의 배열과 충돌함 [fruits.varieties] name = "granny smith" [fruits.physical] color = "red" shape = "round" # 유효하지 않음: 이 테이블의 배열은 직전의 테이블과 충돌함 [[fruits.physical]] color = "green" ``` 인라인 테이블을 적절히 사용할 수도 있습니다. ```toml points = [ { x = 1, y = 2, z = 3 }, { x = 7, y = 8, z = 9 }, { x = 2, y = 4, z = 8 } ] ``` 파일 확장자 ------------------ TOML 파일의 확장자는 `.toml`이어야 합니다. MIME 타입 --------- TOML 파일을 인터넷을 통해 전송하는 경우, 적절한 MIME 타입은 `application/toml`입니다. ABNF 문법 ------------ TOML의 구문에 대한 엄밀한 정의는 다른 [ABNF 파일][abnf]에 나타나 있습니다. [abnf]: https://github.com/toml-lang/toml/blob/1.0.0/toml.abnf