HTML
웹 문서를 적는 마크업 언어입니다. 글의 어느 부분이 제목이고 어느 부분이 문단인지를 태그로 표시합니다. 표시가 붙은 텍스트를 파일에 그대로 저장하고 그대로 전송합니다. 브라우저는 그 텍스트를 읽어 문서를 화면에 올립니다.
쉽고 빠른 이해
HTML 은 문서 안의 글 조각이 무엇인지 태그로 표시해 두는 규칙입니다. <p> 로 감싼 글자는
한 문단이라는 뜻이고, 브라우저는 그 표시를 보고 문단으로 그립니다.
표시가 없으면 브라우저는 어떤 글자 덩어리가 제목이고 어떤 것이 문단인지 구별하지 못합니다.
어떻게 표시하는지는 세 가지로 요약됩니다.
- 시작 태그와 끝 태그로 내용을 감쌉니다 (
<p>~</p>) - 시작 태그 안에 이름=값 꼴 속성을 붙여 세부 정보를 더합니다
- 문서 맨 앞줄에 정해진 문구를 적어 브라우저에 규칙을 알립니다
대가도 있습니다. 문법 자신이 쓰는 문자(< > & 등)는 텍스트에 그대로 못 쓰고
돌아서 적어야 합니다. 태그를 규칙과 다르게 두면 오류로 멈추는 대신 브라우저가
알아서 태그를 끼워 넣어, 적은 것과 실제로 만들어지는 구조가 달라질 수 있습니다.
상세
HTML(HyperText Markup Language, 하이퍼텍스트 마크업 언어)은 웹의 핵심 마크업 언어입니다. 처음에는 과학 문서를 의미로 기술하는 언어로 주로 설계됐습니다. 그 설계가 일반적이어서 이후 여러 해에 걸쳐 다른 종류의 문서, 나아가 애플리케이션까지 기술하도록 적응해 왔습니다.
이름 앞의 「하이퍼텍스트」는 웹 페이지를 서로 잇는 링크를 가리킵니다. 같은 웹사이트 안에서 잇기도 합니다. 웹사이트끼리 잇기도 합니다. 링크는 웹의 근본을 이루는 측면입니다. 내용을 인터넷에 올려 남이 만든 페이지에 링크로 이으면 그 사람도 월드 와이드 웹의 참여자가 됩니다. 링크로 이어지는 문서를 적는 규칙이라서 이름에 하이퍼텍스트가 붙습니다. 1995년의 RFC(Request for Comments) 1866 도 HTML 을 플랫폼에 얽매이지 않는 하이퍼텍스트 문서를 만드는 데 쓰는 언어로 소개했습니다.
HTML 이 정의하는 것은 웹 콘텐츠의 의미와 구조입니다. 겉모습은 CSS(Cascading Style Sheets, 캐스케이딩 스타일 시트)가 대개 맡습니다. 동작은 JavaScript 가 대개 맡습니다. HTML 은 그 사이에서 무엇이 제목이고 무엇이 문단이며 어디가 다른 문서로 가는 링크인지를 표시합니다.
요소는 원문에서 시작 태그와 끝 태그로 표시됩니다. <body> 가 시작 태그이고 </body> 가 끝
태그입니다. 어떤 시작 태그와 끝 태그는 경우에 따라 생략할 수 있습니다. 그때는 다른 태그가
그것을 암시합니다. 태그는 요소들이 서로 완전히 안에 들어가도록 중첩해야 합니다. 겹치면 안 됩니다.
명세는 HTML 에서 쓸 수 있는 요소의 집합을 정의합니다. 그리고 그 요소들을 어떤 식으로 중첩할 수 있는지에 대한 규칙을 함께 정의합니다. HTML 문서는 요소와 텍스트로 이루어진 트리입니다.
flowchart TD
A["html 요소"] --> B["body 요소"]
B --> C["p 요소"]
C --> D["텍스트: 문단 내용"]
속성은 시작 태그 안에 놓입니다. 이름과 값을 = 문자로 잇습니다. 값에 ASCII(American
Standard Code for Information Interchange, 미국 정보 교환 표준 부호) 공백이 없고 " '
` = < > 도 없으면 따옴표를 생략해도 됩니다. 그렇지 않으면 작은따옴표나
큰따옴표로 감싸야 합니다.
문서 하나는 정해진 순서의 부분들로 이루어집니다. 그중 doctype 은 필수 서두입니다. 옛것
때문에 필요합니다. 빠뜨리면 브라우저는 일부 명세와 호환되지 않는 다른 렌더링 모드를 쓰는
경향이 있습니다. doctype 을 넣으면 브라우저가 관련 명세를 따르려고 최선을 다합니다. 형태는
<!doctype html> 이고 대소문자를 가리지 않습니다.
U+FEFF 처럼 「U+」 뒤에 오는 십육진 숫자는 유니코드 코드 포인트를 가리키는 표기입니다. U+FEFF 가 가리키는 코드 포인트가 BOM(Byte Order Mark, 바이트 순서 표시) 문자입니다.
| 순서 | 부분 | 몇 개 |
|---|---|---|
| 1 | U+FEFF 바이트 순서 표시(BOM) | 선택. 하나까지 |
| 2 | 주석과 ASCII 공백 | 몇 개든 |
| 3 | doctype | 하나 |
| 4 | 주석과 ASCII 공백 | 몇 개든 |
| 5 | 문서 요소. html 요소 꼴 |
하나 |
| 6 | 주석과 ASCII 공백 | 몇 개든 |
이 문법은 SGML(Standard Generalized Markup Language, 표준 일반화 마크업 언어)·XML (Extensible Markup Language, 확장 가능한 마크업 언어)과 닮았습니다. 그래도 자기 파싱 규칙을 따로 갖는 별개의 언어입니다. HTML2 부터 HTML4 까지의 몇몇 판은 SGML 에 기반해 SGML 파싱 규칙을 썼습니다. 그러나 HTML 문서에 진짜 SGML 파싱을 구현한 웹 브라우저는 거의 없었습니다.
명세가 정의하는 것은 문서와 애플리케이션을 기술하는 추상 언어 — 실제로 어떤 문자로 적을지는 정하지 않고 뜻과 구조만 정하는 언어 — 와, 그 언어를 쓰는 자원의 메모리 표현을 다루는 몇몇 API(Application Programming Interface, 응용 프로그램 인터페이스)입니다. 메모리 표현은 DOM(Document Object Model, 문서 객체 모델)이라고 부릅니다.
그 추상 언어를 실제 문자로 적는 규칙이 구체 문법이고, 둘입니다. 하나는 지금 쓰는 HTML 문법이고, 다른 하나는 XML 문법입니다 — 여기서부터 「HTML」은 표제어 전체가 아니라 이 둘 중 하나를 가리키는 좁은 뜻으로도 쓰입니다. 두 구체 문법이 정확히 무엇인지는 갈래에서 각각 다룹니다. 문서가 text/html MIME(Multipurpose Internet Mail Extensions, 다목적 인터넷 메일 확장) 타입으로 전송되면 웹 브라우저가 그것을 HTML 문서로 처리합니다.
표현 한계
무엇을 못 담는지부터 봅니다. 값이 조용히 바뀌는 자리가 먼저입니다. 오류로 드러나는 자리가 나중입니다.
문법에 쓰이는 문자
< > " ' & 는 HTML 문법 자신의 일부입니다. 그래서 텍스트에 그대로 적을 수 없습니다.
이 문자들은 문자 참조로 적습니다. 문자 참조는 텍스트에 그대로 적을 수 없는 문자를 다른
표기로 대신 적는 장치입니다. & 로 시작해 ; 로 끝납니다.
빠뜨려도 오류로 멈추지 않습니다. 문법으로 해석될 뿐입니다. 아래 두 문단은 같은 말을 적었지만 첫 줄만 어긋납니다.
<p>in HTML, you define a paragraph using the <p> element.</p>
<p>in HTML, you define a paragraph using the <p> element.</p>
첫 문단은 브라우저가 두 번째 <p> 를 새 문단의 시작으로 해석해서 어긋납니다. 둘째 문단은
내용의 꺾쇠가 문자 참조로 적혀 있어 그대로 나옵니다.
문자 참조에는 세 갈래가 있습니다. 이름 문자 참조는 & 뒤에 명세가 정한 이름을 같은
대소문자로 적고 ; 으로 끝냅니다. 십진 숫자 문자 참조는 &# 뒤에 ASCII 숫자를 하나 이상
적고 ; 으로 끝냅니다. 십육진 숫자 문자 참조는 &# 뒤에 x 나 X 를 놓고 ASCII 십육진
숫자를 하나 이상 적은 다음 ; 으로 끝냅니다.
우회는 우회입니다. 문자 참조로 적은 문서가 그 문자를 바이트로 담은 것은 아닙니다.
시작 태그 뒤의 개행
pre 와 textarea 요소는 시작 태그 바로 뒤에 개행 하나를 놓을 수 있습니다. 그 개행은 요소의
처리에 영향을 주지 않습니다. 그래서 내용 자신이 개행으로 시작하면 이 선택적 개행을 반드시
넣어야 합니다. 안 넣으면 내용의 앞 개행이 선택적 개행으로 취급되어 무시됩니다. 적은 것과
남는 것이 조용히 달라지는 자리입니다.
콘텐츠 모델 제약
명세는 문법 너머에서 요소와 속성을 어떻게 적을 수 있는지에도 제한을 겁니다. 이 제한이
콘텐츠 모델입니다 — 요소마다 무엇을 자식으로 담을 수 있는지 정하는 규칙입니다. 뜻이 정해진
요소를 잘못 쓰는 것을 피하려고, 중첩이 미심쩍은 자리에 콘텐츠 모델이 걸립니다. kbd 요소
안에 section 요소를 넣는 것은 허용되지 않습니다. 절 전체를 키로 입력하라고 저자가 표시할
일은 거의 없기 때문입니다. ul 요소는 li 요소 자식만 허용합니다. 목록은 정의상 0개 이상의
목록 항목으로만 이루어지므로, ul 이 li 가 아닌 것을 담으면 무엇을 뜻하는지 분명하지
않습니다.
역사적 이유로 콘텐츠 모델을 넘어서는 제약이 더 붙은 요소도 있습니다. table 요소는 tr
요소를 담으면 안 됩니다. 명세가 기술한 콘텐츠 모델상으로는 기술적으로 허용되는데도
그렇습니다. 마크업에서 table 안에 tr 을 넣으면 실제로는 그 앞에 tbody 시작 태그가
암시됩니다. 적은 것과 만들어진 트리가 달라집니다.
flowchart TD
subgraph 적은 마크업
A1["table"] --> A2["tr"]
end
subgraph 파서가 만든 트리
B1["table"] --> B2["tbody · 암시됨"] --> B3["tr"]
end
파서의 오류 복구
여기부터는 오류로 드러나는 자리입니다. 다만 명세가 문법을 어긴 경우까지도 처리 규칙을 미리 정해 뒀다는 점이 한계입니다 — 그 규칙을 그대로 따르면 문법에 어긋난 값도 파싱이 끝까지 진행되므로, 오류가 있었다는 사실이 문서 자체에는 남지 않습니다.
명세는 문서가 문법적으로 맞든 틀리든 HTML 문서의 파싱 규칙을 정합니다. 파싱 규칙을 적용하다가 문법이 어긋난 것을 알아채는 지점마다 이름이 붙는데, 그 이름이 parse error 입니다. parse error 에 대한 오류 처리도 잘 정의돼 있습니다. 명세 전반에 걸쳐 기술된 처리 규칙이 그것입니다. 명세는 브라우저를 사용자 에이전트라고도 부릅니다. 다만 사용자 에이전트는 문서를 파싱하다가, 명세의 처리 규칙을 따르고 싶지 않은 parse error 를 처음 만나면 그 자리에서 파서를 중단해도 됩니다. 이 회피는 통제된 환경에서 쓰이는 사용자 에이전트가 더 기묘하고 뒤얽힌 오류 처리 규칙까지 구현하지 않아도 되게 하려는 것입니다.
오류를 보고할 의무를 지는 것은, 문서가 명세를 지키는지 검사해 사용자에게 알리는 도구인 적합성 검사기입니다. 문서에 parse error 조건이 하나 이상 있으면 적어도 하나를 사용자에게 보고해야 합니다. 하나도 없으면 보고해서는 안 됩니다. parse error 는 HTML 문법의 오류만 가리킵니다.
raw text 요소 안의 문자열
raw text 요소는 script·style 처럼 안의 텍스트를 문법으로 해석하지 않고 그대로 읽는
요소입니다. 이런 요소의 텍스트에는 못 넣는 문자열이 있습니다. </ 다음에 그 요소의 태그
이름과 대소문자를 무시하고 일치하는 문자가 옵니다. 그 뒤에 탭·LF(Line Feed, 줄 바꿈)·FF(Form Feed, 폼 피드)·
CR(Carriage Return, 캐리지 리턴)·공백·>·/ 중 하나가 오는 문자열입니다. 이 문자열은
생김새가 끝 태그와 같아서, 텍스트 안에 그대로 적으면 파서가 그 자리에서 요소를 닫힌 것으로
읽습니다.
<script>
const s = "</script>";
</script>
script 요소 안의 문자열 </script> 가 이 금지된 문자열입니다. 파서는 이것을 마주치면
script 의 텍스트가 거기서 끝난 것으로 읽어, 뒤에 남은 따옴표와 세미콜론이 텍스트가 아닌
마크업 취급을 받습니다.
예시
최소 문서 한 벌
MDN(Mozilla Developer Network)이 완전한 웹 페이지의 최소 형태로 싣는 문서입니다.
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<title>My test page</title>
</head>
<body>
<p>This is my page</p>
</body>
</html>
<!doctype html> 이 doctype 입니다. 적법한 doctype 으로 인정되는 문자열 중 가장
짧습니다. 모든 웹 페이지의 맨 위에 넣는 것이 좋습니다. <html></html> 요소는 페이지의 모든
내용을 감쌉니다. 루트 요소라고도 부릅니다. <head></head> 요소는 사용자가 볼 내용이 아닌, 페이지에
관한 정보를 담는 그릇입니다. <meta charset="utf-8"> 은 페이지를 기술하는 메타데이터를
나타내는 meta 요소입니다. charset 속성이 이 문서가 쓸 문자 인코딩을 지정합니다.
<title></title> 은 페이지의 제목을 정합니다. 페이지가 열린 브라우저 탭에 나오는 제목이
이것입니다.
문자 참조 표
특수 문자를 텍스트에 넣을 때 쓰는 짝입니다.
| 문자 그대로 | 문자 참조 |
|---|---|
< |
< |
> |
> |
" |
" |
' |
' |
& |
& |
갈래
HTML 은 두 축으로 갈립니다. 하나는 명세의 관리 방식이 얼린 판이냐 살아있는 판이냐입니다. 다른 하나는 같은 문서 언어를 어느 구체 문법으로 적느냐입니다.
아래 소절이 각 판을 하나씩 짚습니다.
HTML 2.0
한 번 발행하고 얼린 판입니다. RFC 1866 입니다. 1995년 11월, T. Berners-Lee 와 D. Connolly 가 썼습니다. 플랫폼에 얽매이지 않는 하이퍼텍스트 문서를 만드는 데 쓰는 단순한 마크업 언어로 자신을 소개합니다. HTML 문서는 넓은 범위의 분야에서 온 정보를 나타내기에 적절한 일반 의미론을 가진 SGML 문서라고 적습니다. 이 명세가 대략 대응하는 것은 1994년 6월 이전에 흔히 쓰이던 HTML 의 능력입니다. 얼린 판이라 고쳐 쓰는 대신 통째로 폐기됐습니다. RFC 2854 가 그 자리를 대신합니다.
HTML 4.01
이것도 얼린 판입니다. W3C(World Wide Web Consortium, 월드 와이드 웹 컨소시엄) 권고입니다. 1999년 12월 24일자이고 2018년 3월 27일에 대체됐습니다. 앞선 판인 HTML 3.2 와 HTML 2.0 의 텍스트·멀티미디어·하이퍼링크 기능에 더해, 더 많은 멀티미디어 선택지와 스크립팅 언어·스타일 시트·더 나은 인쇄 설비를 지원합니다. 장애가 있는 사용자가 접근하기 쉬운 문서도 여기서 다룹니다. 문서의 국제화로도 크게 나아갔습니다. HTML 4 는 국제 표준 ISO(International Organization for Standardization) 8879 를 따르는 SGML 응용입니다.
XHTML 1.0
관리 방식으로는 여전히 얼린 판입니다. 여기서 갈리는 것은 두 번째 축인 구체 문법입니다. XHTML(Extensible HyperText Markup Language, 확장 가능한 하이퍼텍스트 마크업 언어) 계열의 첫 문서 타입입니다. 2000년에 완성됐습니다. HTML 4 의 세 문서 타입을 XML 1.0 의 응용으로 다시 정식화한 것입니다. 새 구체 문법 말고는 새 기능을 더하지 않았습니다. XML 을 따르는 문서가 되므로 표준 XML 도구로 보고 편집하고 검증할 수 있습니다. HTML 문서 객체 모델과 XML 문서 객체 모델 중 어느 쪽에 기대는 스크립트나 애플릿이든 쓸 수 있습니다.
HTML5 와 Living Standard
축이 얼린 판에서 살아있는 판으로 넘어간 자리입니다.
1998년에 W3C 회원들은 HTML 을 더 발전시키지 않고 XML 기반의 대응물인 XHTML 작업을 시작하기로 정했습니다. 그 뒤 HTML 자신의 진화가 멈춘 상태가 이어졌습니다. 2003년에 XForms 가 발행됩니다. 웹 폼의 차세대 기술로 자리매김한 것이었습니다. XForms 가 나오자, HTML 의 대체물을 찾기보다 HTML 자체를 진화시키자는 관심이 오히려 되살아났습니다. 곧 Apple·Mozilla·Opera 가 WHATWG(Web Hypertext Application Technology Working Group) 라는 새 자리에서 그 작업을 이어가겠다고 함께 밝혔습니다. 2006년에 W3C 가 참여 의사를 보였고 2007년에 WHATWG 와 함께 HTML5 를 개발할 워킹 그룹을 꾸렸습니다.
2011년에 두 그룹은 목표가 다르다는 결론에 이릅니다. W3C 는 "완성된" HTML5 판을 내려 했고, WHATWG 는 알려진 문제를 안은 상태로 명세를 얼리는 대신 계속 관리하는 Living Standard 를 이어가려 했습니다. 2019년에 둘은 앞으로 하나의 HTML 판을 함께 만들기로 합의했습니다. 지금의 Living Standard 가 그 문서입니다. Living Standard 는 완성되지 않습니다. 웹이 계속 변하기 때문입니다. 대신 명세에 가해진 변경 하나하나가 얼린 스냅샷의 발행을 촉발합니다. WHATWG 는 그 스냅샷을 발행된 URL(Uniform Resource Locator, 통합 자원 위치 지정자)에 영구히 남겨 두려 합니다.
HTML 문법
첫 번째 구체 문법입니다. 대부분의 저자에게 권하는 형식입니다. 대다수 옛 웹 브라우저와 호환됩니다. 문서가 text/html MIME 타입으로 전송되면 웹 브라우저가 HTML 문서로 처리합니다. 지금 명세가 정의하는 최신 문법이 이것입니다. 그냥 "HTML" 이라고 부릅니다.
XML 문법
두 번째 구체 문법입니다. 문서가 application/xhtml+xml 같은 XML MIME 타입으로 전송되면 웹 브라우저가 XML 문서로 다루고 XML 처리기가 파싱합니다. 처리 방식이 HTML 문법과 다릅니다. XML 로 표시된 문서는 사소한 문법 오류만 있어도 온전히 렌더되지 못합니다. 같은 오류를 HTML 문법에서는 무시합니다. 명세는 XML 문법을 쓰는 것을 권하지 않는다고 적습니다. XML 파서가 바이트나 문자의 열을 문서 객체로 어떻게 옮겨야 하는지 정의한 명세가 없다는 점, 그리고 XML 문법이 사실상 관리되지 않는다는 점을 이유로 듭니다. HTML 문법에 기능이 더해질 때도 XML 문법에는 더 이상 어떤 기능도 추가되지 않으리라 보는 것입니다. 이 문법을 예전에는 XHTML 이라 불렀지만 지금 명세는 그 말을 쓰지 않습니다.
관련 항목
문서를 이루는 구성 요소
CSS · JavaScript · DOM · Web IDL(Interface Definition Language, 인터페이스 정의 언어) · 문자 인코딩 · UTF-8(8-bit Unicode Transformation Format, 8비트 유니코드 변환 형식) · Unicode · MIME 타입 · URL
문서를 나르고 여는 기술
HTTP(HyperText Transfer Protocol) · TLS(Transport Layer Security, 전송 계층 보안) · Fetch · 브라우저 · 사용자 에이전트 · 렌더링 · 프론트엔드 · 서비스 워커 · IndexedDB · CSP(Content Security Policy, 콘텐츠 보안 정책)
뿌리와 이웃 문서 언어
SGML · XML · SVG(Scalable Vector Graphics, 스케일러블 벡터 그래픽스) · MathML(Mathematical Markup Language, 수학 마크업 언어) · 마크다운
문서에 얹히는 이웃 기술
접근성 · ARIA(Accessible Rich Internet Applications, 접근 가능한 리치 인터넷 애플리케이션) · PNG(Portable Network Graphics, 휴대용 네트워크 그래픽) · AV1 · Opus
명세에 관여하는 기구·문서·도구
WHATWG · W3C · IETF(Internet Engineering Task Force, 국제 인터넷 표준화 기구) · Living Standard · 적합성 검사기
다른 이름: HyperText Markup Language · 하이퍼텍스트 마크업 언어