HTML 표준 탐방기

ECMAScript 스펙은 웹조삼륜 중 최약체다.

형사법정에 법조삼륜이 있다면 웹 프론트엔드에는 웹조삼륜이 있다. 내용을 담당하는 HTML, 표현을 담당하는 CSS, 동작을 담당하는 자바스크립트를 이르는 말이다. 요즘 웹사이트가 고도화되면서 자연스럽게 프로그래밍 언어인 자바스크립트가 주목받게 됐지만, 나머지 두 기술의 중요성을 무시해서는 안 될 것이다.

웹 표준이 다 그렇듯, HTML과 CSS 표준도 폭주하고 있다. 자바스크립트는 좀 상식적인 프로그래밍 언어가 되기만 하면 되었고, 상대적으로 무엇을 해야 하는지 분명했다. 그러나 HTML과 CSS의 변화는 그렇게 간단하지 않았다.

다양한 표준을 읽는 것이 내 업무의 상당한 시간을 차지한다. 지금까지의 경험을 바탕으로 생각해 봤을 때, 자바스크립트 스펙은 웹조삼륜 중 최약체다.

HTML과 CSS가 열심히 레거시를 걷어내고 새로운 기능을 추가하는 동안, 그 변화를 제대로 이해하지 않고 않았던 것이 사실이다. 또, 프론트엔드 작업을 직접 하지 않더라도 웹의 기본적인 기술로서 HTML의 모델은 알 필요가 있다는 생각이 들었다. 이런 점을 반성하면서, HTML 스펙을 읽고 그 중에서 흥미로운 부분을 찾는 시간을 가졌다.

  • 단순히 HTML의 내용을 표현하는 요소 등은 주목하지 않았다.
  • HTML의 기본 개념 정의, 특히 보안 모델 관련한 내용에 주목했다.
  • 웃기면 모두 읽었다.

CSS 표준도 최근에 회사에서 읽어야 하는 상황이 있었는데, 이건 다음에 기회가 되면 더 자세히 알아보도록 한다. 일단 백엔드 엔지니어링과는 상관이 없었다😅

HTML Living Standard는 여기서 확인할 수 있다. 표준을 빠르게 읽는 것이 목적이라 평소처럼 한국어로 번역해 쓰기보다 원문의 영어 표현을 그대로 쓰는 경우가 많은 점에 대해 양해를 구한다.

1 Introduction

1.7.1 Serializability of script execution

스크립트는 다른 스크립트의 동시 실행을 감지할 수 없다. 즉, 싱글쓰레드처럼 작동한다. 이는 웹 워커가 있어도 동일하다.

단, SharedArrayBuffer는 다른 에이전트와 공유할 수 있어 멀티쓰레드로 쓸 수 있다. 그리고 JS 메모리 모델상 문 단위 직렬 실행이 보장되지 않는 경우가 있다고 한다. (어떤 상황?)

사족으로, 내 생각으로는 입문자한테 JS의 실행 맥락이나 환경 레코드 같은 걸 가르칠 거면 에이전트나 렐름도 가르쳐야 하지 않나 싶은데 다들 환경 레코드를 오개념 섞어 가르치는 데만 관심이 있고 에이전트랑 렐름은 관심이 없더라.

1.8 HTML vs XML syntax

HTML에는 HTML 구문과 XML 구문(통칭 XHTML)이 있는데, 둘은 모두 DOM으로 해석된다. 두 구문이 항상 동일한 내용을 나타낼 수 있는 것은 아니다. (XML에만 있는 네임스페이스 개념, HTML에만 있는 noscript 기능 등)

HTML 구문만 신경써도 무방해 보인다.

2 Common infrastructure

2.1 Terminology

HTML이 사용된 것을 문서라 한다. 이는 HTML로 만든 UI 등을 포함한다.

2.1.8 Conformance classes

"이 표준에서 저자라고 하면 HTML 생성하는 프로그램도 포함임"이라는 취지의 문장이 있다. 이 문장을 안 써놓으면 "이 HTML에는 저자가 없으므로 저자가 이 요소를 사용하면 안 된다고 규정한 조항의 영향을 받지 않습니다"라는 궤변이 가능해지나보다.

2.3.2 Boolean attributes

HTML 요소에 불 어트리뷰트, 예를 들어 checked가 있다고 하자. 아래와 같이 쓸 수 있으며, 모두 true를 나타낸다.

  • checked (값 생략)
  • checked="" (빈 문자열)
  • checked="checked" (이름과 같음. 대소문자 구별 없음)

다른 경우는 (브라우저에서 보통 true로 받아주지만) 모두 비표준이다. 예를 들어 checked="true"는 비표준이다.

제 감상도 그러합니다

3 Semantics, structure, and APIs of HTML documents

3.1 Documents

Document 객체의 URL은 fragment로의 항행이나 pushState()에 의해 바뀔 수 있다.

Document 객체의 origin은 생성될 때 정해지며, deprecate된 document.domain 변경으로만 바꿀 수 있다. URL의 origin과는 다를 수 있다.

아래쪽 내용을 읽어보니까 Document 객체 자체는 HTML 문서와 상관 없는 아무 XML 같은 것에도 생성될 수 있다. 특히, SVG를 나타내는 Document 객체 등이 존재한다.

7 Loading web pages

7.1.1 Origins

웹 보안 모델은 "같은 출처면 서로 신뢰한다"는 가정에 기반한다. 각 자원의 URL을 바탕으로 출처를 배정하여, 다른 출처의 자원에 접근할 수 없도록 한다.

일반적으로 출처는 튜플 출처라 하여, (스킴, 호스트, 포트) 튜플로 정의된다. 포트는 null일 수 있다. 이 튜플이 같으면 같은 오리진이다.

튜플 출처 중에는 저 튜플에 더하여 도메인까지 있는 경우가 있는데 이들의 특수 취급이 재밌다. 우선 이 글에서는 이 경우는 기본적으로 무시하고, 흥미로울 때만 언급할 것이다.

튜플 출처가 아닌 출처는 불투명 출처이며, 스킴이 https 등이 아닐 때가 해당한다. 이 경우 자기 자신이 아닌 다른 어떤 출처와도 일치하지 않는다. file 스킴이나 기타 일반적이지 않은 스킴을 쓸 때 보게 될 것이다. 불투명 출처면 다른 자원에 접근하기 어렵고 최신 웹 기술을 쓰는 데 제약이 있기 때문에, 요즘 웹뷰에서 문서를 로드할 때는 로컬 자원에 가짜로라도 https 주소를 정하는 것을 권장하고 있다.

출처 비교가 아니라 사이트 비교라는 표현을 쓸 때도 있는데, 이건 포트를 비교하지 않고 때로는 등록 가능한 도메인 개념을 사용하는 별로 좋지 못한 비교다. 레거시 때문에 표준 일부에 남아 있다.

7.1.2 Origin-keyed agent clusters

기본적으로, 각 Document의 에이전트는 같은 사이트(바로 위 설명 참조)에 있으면 같은 에이전트 무리에 배정된다. 즉, SharedArrayBuffer를 써서 서로 메모리를 공유할 수 있다.

Origin-Agent-Cluster HTTP 응답 헤더를 쓰면 에이전트 무리 기준을 사이트에서 오리진으로 바꾼다. 즉, 더 엄격하게 비교하도록 하는 보안 강화 기능이다.

7.1.5 Sandboxing

샌드박스 플래그 집합은 신뢰받지 않는 리소스의 능력을 제한하는 플래그 모음이다. CSP sandbox 지시자나 <iframe> 요소의 sandbox 어트리뷰트로 정해진다.

7.3.1 Navigables

navigable은 브라우저 탭이나 iframe처럼 문서로 항행할 수 있는 것들을 말한다. 이 중 traversable navigable은 뒤로가기/앞으로가기를 할 수 있도록 히스토리를 리스트와 현재 인덱스로 관리한다.

navigable은 각각 parent를 가져 트리 구조인데, 현재 traversable navigable과 최상위 navigable은 일치하는 개념이다. traversable navigable만이 히스토리를 가지고, 자식 navigable의 항행도 traversable navigable의 히스토리 목록에 기록된다.

7.3.2 Browsing Contexts

browsing context는 문서 일련의 프로그램적 표현이다. 한 navigable 안에서 여러 browsing context가 생겨날 수 있다. WindowProxy 객체에 대응된다. 항행해도 변하지 않는 어떤 맥락을 나타내려고 한 것 같은데, 또 어떤 항행에서는 변하기도 하고, 여러 모로 복잡하다. Document와 navigable 개념을 대신 사용하기를 권하고 있다.

일반적으로, Document 객체의 browsing context가 null이 아니면 이 Document에 일대일 대응되는 Window 객체가 존재한다. 단, about:blank로 시작한 browsing context가 다른 문서로 항행할 때는 Window 객체가 유지되므로 1 대 2가 된다.

7.4 Navigation and session history

Welcome to the dragon's maw. Navigation, session history, and the traversal through that session history are some of the most complex parts of this standard.

정말 엄청나게 길고 복잡하다. 웹 브라우저에서 발생할 수 있는 수많은 에지 케이스를 고려하는 알고리즘 설명이기 때문에, 우선은 개발자가 알 필요는 없어 보인다. 흥미가 있는 사람은 읽어 보면 재밌을 것이다.


HTML 표준에서 사용되는 다양한 용어에 대해 탐구했고, 특히 정확히 몰랐던 것들은 글로 정리했다. 7장의 내용이 자주 필요했는데 그 이해를 위한 기반을 다진 것 같다.

레거시를 없애고 싶으나 기존 웹 애플리케이션들이 많아서 선택사항으로 열어 놓은 기능들이 알던 것보다 훨씬 많다. <!DOCTYPE html> 같이 HTML 파일 내에 들어가는 것들은 MDN을 통해 코드 예제가 많이 퍼져서 다들 습관처럼 모던하게 잘 짜는 것 같은데, HTTP 헤더로 열리는 기능들은 많이 알려지지 않은 것 같다.

이 중에는 Cross-Origin-Opener-Policy처럼 중요해 보이는 것도 있고, 사이트 기준을 출처 기준으로 바꾸는 것 같은 조금 부수적인 것들도 있는데, 그래도 최대한 모던한 설정으로 해둬야 뒤탈이 없을 것이다.

여기까지 공부한 것으로도 대충 감이 잡히기는 하지만, 8장이 본격적으로 자바스크립트 환경을 만드는 내용이라 시간이 된다면 이 부분도 읽어봐야겠다. 또, 접근성 관련된 내용은 CSS 표준과 함께 공부해 볼 생각이다.

마지막으로, HTTP QUERY 메서드가 Proposed Standard까지 올라왔다. GET이지만 내용(본문)을 넣을 수 있다는 매우 유용한 메서드이니 다들 많은 관심과 오픈소스 지원을 부탁드린다.