앞 편에서 브라우저가 문서를 읽어 나무 모양의 구조를 세우는 과정을 다루었다. 그런데 이 나무만으로는 화면이 완성되지 않는다. 나무는 무엇이 어디에 있는지를 알려줄 뿐, 그것이 어떤 색과 크기와 모양으로 보일지는 담고 있지 않기 때문이다. 이번 편은 이 겉모습을 결정하는 스타일 정보가 브라우저 안에서 어떻게 해석되어 또 하나의 구조를 이루는지를 다룬다.


스타일 처리는 문서 처리 못지않게 중요한데도 상대적으로 덜 주목받는다. 스타일은 단순히 예쁘게 꾸미는 장식이 아니라, 브라우저가 화면을 그리기 위해 반드시 갖춰야 하는 필수 재료다. 이 재료가 준비되는 방식과 그것이 첫 화면 속도에 미치는 영향을 이해하면, 왜 어떤 페이지는 스타일 때문에 늦게 뜨는지를 정확히 짚어낼 수 있다.

스타일도 하나의 구조가 된다

브라우저는 스타일 정보를 문서와 마찬가지로 그냥 쌓아 두지 않고 다룰 수 있는 구조로 바꾼다. 스타일 규칙들을 읽어 해석한 뒤, 어떤 대상에 어떤 모양을 입힐지를 정리한 별도의 구조를 만드는 것이다. 이렇게 만들어진 스타일 구조는 문서 나무와 짝을 이뤄 화면을 그리는 두 기둥이 된다.


이 스타일 구조 역시 나무와 비슷한 계층을 이룬다. 일반적인 규칙이 위에 있고 더 구체적인 규칙이 아래에 놓이며, 서로 겹치는 규칙들 사이에서 무엇이 우선하는지가 이 구조 안에서 정리된다. 브라우저는 어떤 요소에 어떤 값을 적용할지를 이 정리된 구조에서 찾아 계산한다.


스타일은 한 곳에서만 오지 않는다. 문서 안에 직접 적힌 스타일도 있고, 바깥에서 따로 내려받는 스타일도 있으며, 브라우저가 기본으로 가진 스타일도 있다. 브라우저는 이 여러 출처의 스타일을 모두 모아 하나의 구조로 합친다. 이 여러 출처가 서로 다른 값을 말할 때, 브라우저는 정해진 규칙에 따라 누구의 말을 따를지 결정한다. 더 구체적으로 대상을 지목한 규칙이 대체로 우선하고, 같은 조건이라면 나중에 적힌 것이 앞선 것을 덮는다.


브라우저가 이렇게 스타일을 구조로 정리해 두는 이유는 효율 때문이다. 매번 화면을 그릴 때마다 흩어진 규칙을 처음부터 뒤지는 대신, 잘 정리된 구조에서 필요한 값을 빠르게 찾아 쓰기 위함이다. 이 스타일 구조는 문서 나무의 짝꿍이다. 하나는 무엇이 있는지를, 다른 하나는 그것이 어떻게 보일지를 담고 있어서, 이 둘이 만나야 비로소 화면이라는 결과물이 나온다. 그래서 둘 중 하나라도 준비가 늦으면 화면 전체가 기다려야 한다.

스타일이 화면을 붙잡는 까닭

문서 나무가 다 세워졌어도 스타일 구조가 준비되지 않으면 브라우저는 화면을 그리지 못한다. 정확히 말하면 그리지 않고 기다리는 쪽을 택한다. 만약 스타일이 없는 상태로 일단 화면을 그렸다가 스타일이 도착한 뒤에 다시 그린다면, 사용자는 아주 잠깐 꾸며지지 않은 엉성한 모습을 보게 된다. 그러다 갑자기 제대로 된 모습으로 바뀌면 화면이 번쩍이는 것처럼 느껴져 불쾌하다.


브라우저는 이 어색한 번쩍임을 피하려고 스타일이 갖춰질 때까지 그리기를 미룬다. 그래서 스타일 정보는 화면 그리기를 붙잡는 성격을 가진다. 특히 바깥에서 내려받아야 하는 스타일이라면, 그 파일이 도착하고 해석이 끝날 때까지 첫 화면이 나오지 않는다. 스타일 때문에 첫 화면이 늦는 사례는 실무에서 자주 나타난다.


문제가 커지는 경우는 스타일 파일이 여러 개로 쪼개져 줄줄이 이어져 있을 때다. 하나를 받아 해석한 뒤에야 다음이 필요하다는 것을 알게 되면, 이 연쇄가 길어질수록 첫 화면은 계속 미뤄진다. 이런 스타일의 사슬은 가장 먼저 끊어내야 한다. 여러 파일을 서로 불러들이는 방식보다, 필요한 것을 미리 한데 모아 한 번에 내려받게 만드는 편이 첫 화면에는 훨씬 유리하다.


다만 스타일이 화면 그리기는 붙잡아도 문서 읽기 자체는 대체로 막지 않는다. 그래서 브라우저는 스타일을 기다리는 동안에도 문서 나무는 계속 세워 나간다. 이 미묘한 차이를 알면 스크립트와 스타일이 각각 무엇을 붙잡는지를 구분해 다룰 수 있다. 첫 화면에 꼭 필요한 스타일과 나중에 필요한 스타일을 나눠서 앞의 것만 서둘러 갖추면 붙잡히는 시간을 크게 줄일 수 있다.

규칙이 요소를 찾아 입혀지는 원리

스타일 구조가 준비되면 브라우저는 문서 나무의 각 마디를 돌면서, 그 마디에 어떤 스타일 규칙이 해당되는지를 찾아 값을 입힌다. 하나의 규칙은 어떤 대상에 적용될지를 가리키는 조건과, 그 대상에 입힐 모양을 담고 있다. 브라우저는 각 요소에 대해 여러 규칙 중 조건이 들어맞는 것들을 골라 낸다.


어떤 요소에는 여러 규칙이 동시에 해당될 수 있는데, 이때 앞서 말한 우선순위에 따라 최종 값이 정해진다. 서로 다투는 값들 사이에서 하나를 고르는 이 과정이 스타일 계산의 핵심이다. 스타일이 예상과 어긋날 때는 대개 이 다툼의 결과가 짐작과 다른 경우인데, 원리를 알면 어느 규칙이 이겼는지를 차분히 추적할 수 있다.


어떤 값들은 부모에게서 자식으로 자연스럽게 물려받는다. 글자 색이나 글꼴 같은 것들이 대표적인데, 부모에 정해 두면 특별히 다시 정하지 않는 한 자식들도 그 값을 따른다. 이 물려받음 덕분에 모든 요소에 일일이 값을 정하지 않아도 된다. 반대로 여백이나 테두리처럼 각 요소가 독립적으로 가져야 하는 값들은 부모의 것이 자식에게 넘어가지 않는다. 어떤 값이 물려받고 어떤 값이 그렇지 않은지를 알면 스타일을 훨씬 예측 가능하게 다룰 수 있다.


브라우저는 이렇게 각 요소의 최종 스타일을 계산할 때, 상대적인 값들을 실제 값으로 바꾸는 작업도 함께 한다. 부모 크기에 대한 비율이나 화면 크기에 따른 값들이 이 단계에서 구체적인 크기로 정해진다. 이 계산된 최종 스타일이 다음 단계인 배치의 입력이 된다. 값이 이상하게 나올 때는 대개 여러 규칙이 다투는 우선순위 문제이거나, 물려받음을 잘못 예상한 경우다.

첫 화면에 필요한 스타일을 앞세우기

스타일이 화면을 붙잡는다면, 자연스러운 해법은 첫 화면에 꼭 필요한 스타일만 서둘러 갖추는 것이다. 사용자가 처음 마주하는 화면 윗부분을 그리는 데 필요한 스타일을 골라, 그것만 먼저 준비하고 나머지는 뒤로 미루는 전략이다. 이 핵심 스타일을 문서 안에 직접 담아 두면, 바깥 파일을 기다릴 필요 없이 문서와 함께 도착하므로 첫 화면을 곧바로 그릴 수 있다.


이 방법으로 첫 화면이 눈에 띄게 빨라진다. 관건은 무엇이 정말로 첫 화면에 필요한지를 정확히 골라내는 것이다. 나머지 스타일, 곧 화면을 스크롤해야 나오는 부분이나 사용자가 어떤 동작을 해야 나타나는 부분의 스타일은 뒤로 미룬다. 이런 스타일은 첫 화면을 그린 뒤에 배경에서 조용히 내려받아 적용하면 되고, 사용자는 이 지연을 거의 느끼지 못한다.


이렇게 나누는 방식의 핵심은 사용자가 첫 내용을 마주하는 순간을 다른 어떤 것보다 앞세우는 것이다. 전체 스타일을 다 갖춰야만 화면을 보여줄 수 있다는 생각을 버리고, 지금 당장 보이는 부분에 필요한 것만 먼저 챙기는 발상의 전환이다. 완벽하게 다 갖춘 화면을 늦게 보여주는 것보다, 조금 부족해도 빠르게 첫 내용을 보여주고 나머지를 채워 가는 편이 사용자에게는 나은 경험이다.


다만 이 방법에는 손이 많이 가는 면이 있다. 무엇이 첫 화면에 필요한지를 매번 정확히 골라내는 일이 쉽지 않고, 화면이 바뀌면 그 목록도 다시 손봐야 한다. 그래서 이 작업은 사람이 매번 손으로 하기보다 자동으로 뽑아내는 도구의 도움을 받는 편이 낫다. 붙잡음을 피할 수 없다면, 붙잡히는 대상을 최소한으로 줄여 붙잡히는 시간을 짧게 만드는 것이 이 전략의 요체다.

상황에 따라 갈리는 규칙

스타일 규칙 중에는 특정 조건에서만 적용되는 것들이 있다. 화면의 너비가 어떤 값보다 클 때만, 또는 인쇄할 때만, 또는 어두운 화면 설정일 때만 적용되도록 조건이 붙은 규칙이다. 브라우저는 이런 조건을 평가해 지금 상황에 맞는 규칙만 골라 적용한다. 같은 문서가 화면 크기에 따라 전혀 다른 배치로 보이는 것이 이 조건부 규칙 덕분이다.


다만 조건에 맞지 않는다고 해서 브라우저가 그 규칙을 아예 무시하고 넘어가는 것은 아니다. 조건을 평가하려면 일단 규칙 전체를 받아서 읽어야 하기 때문이다. 지금 화면에 해당하지 않는 규칙도 내려받고 해석하는 비용은 그대로 든다. 그래서 쓰지 않는 조건의 규칙이 잔뜩 쌓이면, 당장 적용되지 않더라도 첫 화면을 준비하는 시간에 부담을 더한다.


여기서 한 가지 유용한 성질이 나온다. 지금 상황에 해당하지 않는 조건의 규칙은 화면 그리기를 붙잡지 않게 만들 수 있다. 어떤 조건에서만 필요한 스타일임을 브라우저에 미리 알려 주면, 브라우저는 그 조건이 아닐 때는 그 스타일을 급하게 기다리지 않고 첫 화면을 먼저 그린다. 조건이 맞을 때만 그 스타일이 화면을 붙잡는 것이다.


이 성질을 활용하면 다양한 상황에 대응하는 스타일을 갖추면서도 첫 화면의 속도를 지킬 수 있다. 인쇄용 스타일이나 특정 화면 크기 전용 스타일처럼 지금 당장 필요하지 않은 것들을 조건 뒤로 분리해 두면, 그것들이 첫 화면을 붙잡는 일이 사라진다. 조건을 명확히 다는 것은 겉모습을 나누는 일일 뿐 아니라 붙잡힘을 나누는 일이기도 하다.


다만 조건을 너무 잘게 나누면 관리가 어려워진다. 화면 크기의 경계를 여러 개로 쪼개고 각 구간마다 다른 규칙을 두면, 어느 구간에서 무엇이 적용되는지를 추적하기가 점점 힘들어진다. 경계를 몇 개의 분명한 기준으로 추리고, 각 기준 사이에서 자연스럽게 늘어나거나 줄어드는 값을 쓰면, 규칙의 수를 줄이면서도 여러 화면 크기에 매끄럽게 대응할 수 있다.

쓰지 않는 스타일을 덜어내기

스타일 최적화에서 또 하나 중요한 것은 실제로 쓰이지 않는 스타일을 덜어내는 것이다. 프로젝트가 오래되면 어느새 아무도 쓰지 않는 규칙들이 잔뜩 쌓여, 브라우저가 매번 이 쓸모없는 것까지 받아서 해석하게 된다. 쓰지 않는 스타일이 많으면 파일이 무거워져 내려받는 데 시간이 더 걸리고, 브라우저가 해석하고 정리할 양도 늘어난다.


이 모든 것이 첫 화면을 붙잡는 시간에 더해진다. 그래서 주기적으로 실제로 쓰이는 규칙만 남기고 나머지를 걷어내는 정리가 필요하다. 다만 무엇이 쓰이고 무엇이 안 쓰이는지를 판단하는 일은 조심스럽다. 어떤 스타일은 특정 상황에서만 나타나는 화면에 쓰여, 겉으로는 안 쓰이는 것처럼 보여도 실제로는 필요한 경우가 있다. 걷어내기 전에 충분히 확인하고, 한꺼번에 지우기보다 조심스럽게 진행해야 한다.


스타일을 구조화하는 방식도 관리에 큰 영향을 준다. 규칙들이 뒤죽박죽 얽혀 있으면 무엇이 무엇에 영향을 주는지 알기 어려워, 무서워서 손을 못 대고 쓸모없는 규칙이 계속 쌓인다. 스타일을 일정한 원칙에 따라 정리해 두면 나중에 걷어내기 쉬워진다. 여기에 더해, 스타일 규칙을 지나치게 복잡한 조건으로 짜면 브라우저가 매칭하는 데도 더 많은 일을 하게 된다.


대상을 간결하고 명확하게 가리키는 규칙은 브라우저가 빠르게 처리한다. 화려한 조건보다 단순하고 분명한 조건이 성능에 이롭다. 정리하면, 스타일은 문서와 짝을 이뤄 화면을 그리는 필수 재료이자 화면 그리기를 붙잡는 요인이기도 하다. 첫 화면에 필요한 것을 앞세우고, 쓰지 않는 것을 덜어내며, 규칙을 간결하게 유지하는 세 가지가 스타일 최적화의 기본이다. 다음 편에서는 문서 나무와 스타일 구조가 만나 실제로 배치를 계산하는 단계로 넘어간다.