Basic <HTML />

HTML 다시보기

John Cho
15 min readAug 16, 2020
HTML Specification의 포지션

HTML, HyperText Markup Language로 대변되는 이 언어는 단순히 Markup Language라는 이유로 많은 개발자들에게 HTML은 프로그래밍 언어가 아니다! 라는 식으로 조롱받고는 한다.

재미있는 점은 그런 사람들 중 대부분이 HTML에 대해 명확히 이해하고 있지 못하다는 점이다. HTML에서 Markup Language 라고 부르는 지식은 HTML 4.01 까지, 그러니까 웹을 Document로만 바라보던 시절에 머물러 있다.

HTML 4.01이 1999년 12월 표준이 되었고, HTML 5가 2008년 1월 22일 처음 시작되어 2014년 10월 W3C 권고안이 되었으니 HTML을 단순히 사전적 의미의 Markup Language로 바라보는 시대는 지난 지 오래다.

2020년 현재 기준, 최신 HTML 표준안은 WHATWG (Web Hypertext Application Technology Working Group)에서 HTML Living Standard 라는 이름으로 관리하고 있으며, WHATWG에 참여 중인 기업체는 Apple, Google, Mozilla, Microsoft 등이다.

이 글에서는 HTML Living Standard를 바탕으로 HTML Specification에 어떤 것들이 포함되어있는 지 살펴보고자 한다.

WHATWG HTML Specification TOC

이 글에서는 Rendering, HTML Syntax, XML Syntax 등은 다루지 않으며, 개별 스펙에 대한 상세한 내용도 다루지 않을 예정이다. 다만 추후에 개별 스펙에 대한 교육 과정을 오픈해볼까 생각은 하고 있다.

HTML as Document

어떻게 보면 HTML이라는 마크업 언어의 최초 목표였던 문서를 표현하기 위한 HTML이라고 할 수 있다. HTML Specification 에서 문서를 위한 HTML은 크게 세가지 카테고리로 분류된다.

  1. Semantics, structure, APIs of HTML documents
  2. The elements of HTML
  3. Microdata

이 영역들이 ‘명확하게 문서만을 위한’ 것이라고 말하기에는 다소 문제가 있다. 왜냐하면 HTML의 여러가지 요소와 속성, 인터페이스들을 Web Application에서도 함께 사용할 수 있기 때문이다.

Contents Model

HTML의 각 요소에는 콘텐츠를 나타내기 위한 Contents Model을 가지고 있으며, Contents Model에 따라서 요소간 포함관계를 나타내고, 어떤 요소가 어떤 콘텐츠를 포함할 수 있는 지에 대해서 나타내준다.

하나씩 다루기 시작하면 밑도 끝도 없이 글이 길어질 수 있어, 여기서 Contents Model에 대해서 상세히 다루지는 않겠다.

예를 들어 Sectioning Content는 Heading과 Footer의 스코프를 생성해주고, Sectioning Content를 바탕으로 문서 전체의 아웃라인을 생성해주기 때문에 문서에서 Sectioning Content를 어떻게 사용하느냐에 따라서 문서 전체의 컨텍스트가 달라질 수 있다.

Interactive Content는 다른 Interactive Content를 자식으로 둘 수 없기 때문에 a 요소 밑에 button 요소를 둘 수 없고, a 요소 밑에 input 요소를 둘 수 없다.

하지만 이건 문법상의 문제고, 문법을 제대로 지키지 않았다고 해서 브라우저가 렌더링을 포기하지는 않는다. 다만 언젠가 이상하게 동작하면 높은 확률로 HTML을 잘못 작성한 것이다.

The elements of HTML

말 그대로 HTML에는 어떤 요소가 존재하며, 개별 요소들이 표현하는 의미는 무엇이며 어떤 속성을 사용할 수 있는가에 대해 정의되어있다. 또한 특정 요소들에 한해서는 특수한 메커니즘이 적용되어있기 때문에, 어떤 식으로 렌더링이 이루어지는 지에 대해서도 정의되어 있다.

여러분들이 생각하는 ‘마크업 영역’ 은 대부분 여기에서 끝난다.

특정한 인터페이스를 보여주기 위해 section 요소를 쓸 지 article 요소를 쓸 지, form 에서 action 속성을 어떻게 처리해야하는 지 등에 대한 모든 내용이 이 섹션에서 정의되어있다.

그래서 분량도 많고, 중요한 내용임은 사실이기 때문에 여러분들이 HTML에 대해 공부할 때 어떤 요소를 사용할 지 이해하는 것은 당연히 중요하다. 하지만 HTML이 여기서 끝나지 않는 점에 대해서만 알아주었으면 한다.

Microdata

Microdata는 HTML에서 콘텐츠를 더 명확히 나타내기 위해 추가된 스펙이다. Microdata를 통해 사이트 개발자는 ‘이 코드가 정확히 어떤 객체를 나타내는 지’ 설명할 수 있다.

예를 들어, 여러분들이 상품을 판매하는 사람이고, 쇼핑몰을 운영하고 있다고 가정해보자. 여러분들이 작성한 상품에 대한 마크업은 아마 이런 식일 거다.

<div>
<span>Panasonic White 60L 냉장고</span>
<img src="panasonic-white-fridge.jpg" alt="">
<div>
<meter min=0 value=3.5 max=5>별점 3.5/5</meter>
(<span>11</span>명이 리뷰했습니다)
</div>
</div>

우리는 인간이기 때문에 적당히 텍스트를 읽어들여서 마크업이 무엇을 나타내는 지 알 수 있지만, 만약 로봇이 마크업을 읽어들인다고 했을 때 이 마크업이 무엇을 나타내는 지 알 수 있을까?

그래서 Microdata는 더 명확하게 이 마크업이 어떤 콘텐츠를 나타내는 것인 지 정의할 수 있게 한다.

<div itemscope itemtype="http://schema.org/Product">
<span itemprop="name">Panasonic White 60L 냉장고</span>
<img src="panasonic-white-fridge.jpg" alt="">
<div itemprop="aggregateRating"
itemscope itemtype="http://schema.org/AggregateRating">
<meter itemprop="ratingValue"
min=0 value=3.5 max=5>별점 3.5/5</meter>
(<span itemprop="reviewCount">11</span>명이 리뷰했습니다)
</div>
</div>

Microdata로 표현 가능한 것들은 Schema.org 에 미리 정의되어 있으며, 본인이 생각하기에 본인의 제품에 가장 적절하다고 생각되는 것들을 정의하여 사용하면 된다.

HTML as Application

HTML이 발전하면서 HTML을 문서를 표현하기 위해 사용하는 게 아니라 애플리케이션을 구현하기 위해 사용할 필요가 있었고, 그를 위해서 HTML에서 웹 애플리케이션을 개발하기 위한 여러가지 API를 설계해야 했다.

여기서는 사실 위에서 다루지 않은 모든 영역을 포함하여 복잡한 내용이 많지만, 가능한 한 단순하게 설명해보도록 하겠다.

  • User interaction
  • Loading web pages
  • Web application APIs
  • Communication
  • Web workers
  • Web storage

문서 때와 마찬가지로 이 모든 스펙들이 반드시 웹 애플리케이션을 위한 거라 한정하기는 어렵다. 예를 들어 문서도 Loading은 발생해야하기 때문에 Loading web pages에 관한 내용은 알아야 하고, 최적화를 위해서 Web storage나 worker를 사용할 수 있기 때문이다.

User interaction

HTML 상에서 유저와 상호작용하는 내용을 다룬다. 유저의 행동에 따라 콘텐츠를 가리거나 (hidden 속성), 노드의 비활성화 상태, 일부 API의 활성 상태 제어, 요소의 동작에 관한 정의, Focus의 동작 방식 + 관리 API, 키보드 단축키 정의, 에디터와 관련된 내용 등을 다룬다.

예를 들어 페이지 내에서 WYSIWYG 에디터를 만들고자 하면 유저가 입력하는 커맨드를 캐치하고, 미리 지정해둔 단축키에 따라 움직이게 하는 방식이 있으며, OS가 자동으로 spellcheck 등을 하는 경우에 따른 처리 등을 진행할 수 있다.

inputmode 를 정의하면 가상 키보드의 배열을 변경할 수 있는데, 이를 바탕으로 유저에게 더 나은 UX를 제공하는 것도 가능하다.

또한 과거에는 Plain JavaScript와 DOM 조합으로만 구현 가능했던 Drag and Drop도 이제 브라우저에서 제공하는 Drag and Drop API를 사용해서 구현하는 것이 가능하다.

아래 예제는 web.dev 에서 제공하는 HTML Drag and Drop 가이드라인의 예제 코드이다.

User Interaction 섹션은 특히나 복잡한 웹 애플리케이션을 개발하는 사람이라면 꼭 봐야하는 영역이고, 특히 User Input 을 제어하는 사람이라면 꼭 한번쯤 해당 섹션을 읽어보는 걸 추천한다.

Loading web pages

여러분들이 지금 보고있는 페이지를 노출시키기 위해서 브라우저에서는 꽤 많은 일을 수행한다. 이런 알고리즘이 복잡해진 데에는 Web의 특성이 반영되어있는 데, 어디서든 사용 가능하며 하나의 Page 내에서 다른 Page를 불러오는 등의 일도 가능하기 때문에 Context 분리를 명확히 하지 않으면 여러 동작이 제대로 이루어지지 않을 수 있다.

우선 브라우저가 웹 페이지를 로딩하면 제일 먼저 Browsing Context를 생성하여 해당 페이지의 Scope를 생성한다. Window 객체는 생성되는 순간 바로 Document 객체와 연결되고, Window의 Browsing Context는 Document의 Browsing Context와 연결된다.

WindowDocument는 비슷한 듯 다른데, 자세한 내용은 DOM 스펙을 더 살펴보기를 추천한다.

History 인터페이스를 사용해서 유저가 방문했던 사이트의 기록을 제어할 수 있고, Location 인터페이스를 활용해서 페이지 이동을 시키는 행위도 가능하다. 위 두 인터페이스는 주로 SPA에서 많이 쓰이지만, 그렇지 않은 경우에도 종종 쓰인다.

Offline web applications 라는 스펙도 존재하지만, 이 스펙은 제거될 예정이며 현재는 Service Worker를 이용한 스펙으로 대체되고 있다. 간략히 요약하자면 로컬에서 캐시로 저장할 파일들을 Manifest 파일을 이용해서 정의해두자는 거였는 데, Service Worker로 캐시와 Response를 제어할 수 있기 때문에 Service Worker를 이용하기를 권장한다.

Web application APIs

이 섹션은 주로 Script를 어떻게 불러오는 지, 비동기로 불러올 건 지 동기 방식으로 불러올 건 지에 대해 다루는 부분 + HTML 내의 iFrame 내부의 스크립트를 어떻게 제어하는가에 관한 항목 등을 다루는 Scripting 섹션.

동적으로 마크업을 넣을 때 사용하는 document.write() , DOM Parsing에 관한 내용, HTML 내의 타이머(setTimeout, setInterval, clearInterval 등) 제어법과 동작 방식, 콜백을 호출하기 위한 마이크로 태스크를 queue에 쌓는 queueMicrotask 와 콜백의 동작 방식, prompt (alert, confirm, prompt 등), 시스템 상태를 나타내는 Navigator, 비트맵 기반 이미지를 생성할 수 있는 ImageBitmap, 애니메이션을 동작시키기 위한 AnimationFrame 등이 있다.

사실 여기서 정의하고 있는 API들도 하나하나가 너무 중요하지만 여기서 다루기엔 분량이 너무 많아 생략한다.

특히 이해하면 좋다고 생각하는 건 타이머의 동작 방식, queueMicrotask 의 동작 원리, Navigator, AnimationFrame 이다. 만약 본인이 이미지 처리를 하고 있다면 ImageBitmap 인터페이스도 보면 좋으리라 생각된다.

Communication

이 섹션에서는 주로 실시간 통신을 위한 인터페이스를 정의한다.

MessegeEvent 인터페이스는 서버에서 전달한 이벤트, 웹 소켓, 문서간 통신, 채널 메시징 등 여러 채널을 통해 전달받은 메시지를 받아서 처리하는 이벤트다.

Web Socket은 서버측 프로세스와 양방향으로 통신할 수 있게 만드는 스펙으로, 보통 실시간 기반의 메신저나 게임을 만들 때에 사용된다. 서버와 클라이언트 사이에 소켓을 열어둔 상태로 메시지를 받거나 전달할 때마다 이벤트가 발생하고, MessageEvent 인터페이스를 통해 클라이언트에서 처리하게 된다.

문서간 통신은 postMessage 라는 스펙을 기반으로 한 여러 사이트간 통신을 의미한다. 원래 Web application은 보안을 위해 cross-site scripting을 허용하지 않는데, 서로 허용했다는 걸 전제로 postMessage를 통해 다른 사이트에 콘텐츠를 전달하는 게 가능하다. 물론 모든 케이스에서 가능한 건 아니고 굉장히 제한적인 환경에서만 동작한다.

또한 같은 브라우징 컨텍스트 (windows, tabs, iframes) 사이에 동일한 origin 끼리는 BroadcastChannel API를 바탕으로 서로간 통신이 가능하다. 이 API는 postMessage API를 기반으로 동작하고, 브라우징 콘텍스트 내에서 동시에 동작한다는 점 외에는 크게 차이가 없다.

예를 들어 여러 탭에서 YouTube를 띄워둔 상태로 웹 브라우징을 하다가 YouTube에서 로그아웃을 진행했을 때, 여러 탭의 YouTube에서 동시에 Logout을 실행해야하는 상황이 있다면 broadcastChannel을 사용할 수 있다.

Web workers

JavaScript는 그 설계가 기본적으로 싱글 스레드로 돌아가도록 되어있고, 런타임에서만 돌아가도록 되어있어서, 연산해야하는 양이 많아지면 많아질 수록 JavaScript 자체의 성능을 보장하기 어렵다는 단점이 있었다.

특히 UI를 제어하는 JavaScript 코드가 많다보니 단순 연산을 위해서 JavaScript 런타임을 너무 많이 사용하게 되면 UI가 느려지는 현상이 있었고, 이 문제를 해결하기 위해서 Web worker 스펙이 나왔다.

쉽게 생각하면 JavaScript의 Main Thread가 아닌 Worker Thread에서 동작하는 별도의 스크립트로, Client와 밀접하지 않은 연산 등을 수행할 수 있는 인터페이스다.

worker를 잘 활용하면 연산에 들어가던 Main Thread를 Worker Thread에서 동작시킬 수 있기 때문에 그 활용도가 무궁무진하고, Background 에서도 동작하기 때문에 Service Worker 등을 활용한 Network 제어, Cache 제어 등을 수행할 수 있다.

더 자세한 worker 활용법에 대해서는 web.dev를 살펴보거나 MDN을 살펴보길 바란다:

Web storage

HTTP에서 상태를 저장하기 위한 전통적인 방식으로 Cookie나 Session을 사용한다. Web storage는 아주 단순하게 생각하면 기존의 Cookie와 Session이 하던 역할을 더 광범위하게 클라이언트로 가져왔다고 생각하면 좋을 듯 하다.

기존과 많이 다르지는 않지만, Web storage는 기본적으로 클라이언트에서 그 상태를 공유하기 때문에, 유저가 여러 창을 띄워둔 상태로 작업을 수행하고 있을 때 Web Storage에 그 값을 저장해두면 여러 창에서 동시에 그 상태를 제어하는 것이 가능하다.

또한 Cookie는 4KB의 데이터만 포함 가능한 데 비해 Web Storage는 5MB를 저장하는 게 가능하기 때문에, 유저에게 필요한 일부 상수값들을 Web Storage에 저장해두고 사용하면 불필요한 서버 요청을 막을 수 있다.

Web Storage는 크게 LocalStorage와 SessionStorage로 구분되며, 동작 방식은 기존과 거의 동일하니 참고해보면 좋을 듯 하다.

결론

이 글에서는 많은 사람들이 HTML로 알고 있는 부분, 그리고 많은 사람들이 JavaScript 인 줄 알았지만 사실 HTML인 부분들에 대해서 다루어보았다.

이 글에서 HTML의 상세한 부분에 대해서는 다루지 않았지만, 아마 이정도면 충분히 앞으로 어떤 걸 공부해야할 지 이해하리라 생각한다.

앞으로도 HTML의 발전이 기대된다.

--

--