15. 자바스크립트와 브라우저

브라우저는 웹 개발에서 핵심 역할을 하며, 자바스크립트는 이 브라우저 환경에서 실행되는 주요 프로그래밍 언어이다. 브라우저가 더욱 발전하고, 다양해지는 요즘 웹 개발자로서 브라우저의 동작 과정을 이해하면 웹 애플리케이션을 다양한 플랫폼과 브라우저에서 일관되게 작동하도록 보장할 수 있다. 다양한 브라우저와 버전에서 테스트하고 디버깅하기 위해서는 브라우저 동작 과정에 대한 지식은 필수적이다. 악의적인 코드나 보안 취약점을 찾아내고 이를 해결하는 것 역시 브라우저 동작 원리를 숙지하는 것이 필수적이다.
 

15-1. 브라우저란

브라우저는 웹페이지를 표시하고 상호작용하는 소프트웨어다. 브라우저는 웹 표준에 따라 HTML, CSS, 자바스크립트를 해석하고 렌더링하여 사용자에게 웹을 이용할 수 있게 한다. 브라우저의 동작 과정을 이해하기 위해 기능과 구조에 대해 살펴보고자 한다.
 

15-1-1. 브라우저의 기능적 이해

  • HTML, CSS, 자바스크립트 해석 및 실행
    • 브라우저는 웹페이지의 HTML, CSS 및 자바스크립트 코드를 해석하고 실행한다. HTML은 페이지의 구조와 내용을 정의하고, CSS는 스타일과 레이아웃을 제어하며, 자바스크립트는 동적 기능과 상호작용을 추가한다.
  • DOM 조작
    • 브라우저는 순수한 텍스트인 HTML에서 DOM(Document Object Model)을 생성하고 관리한다. 자바스크립트를 사용하여 DOM을 조작하여 웹페이지의 요소를 추가, 수정, 삭제한다.
  • CSSOM 생성
    • CSSOM(CSS Object Model)은 CSS 스타일 정보를 표현하는 객체 모델이다. 브라우저는 HTML 문서와 연결된 CSS 파일을 해석하여 CSSOM을 생성하며, 이를 통해 스타일을 동적으로 변경한다.
  • 렌더링 엔진을 통한 페이지 표시
    • 브라우저의 렌더링 엔진은 DOM과 CSSOM을 결합하여 렌더 트리를 생성한다. 이 렌더 트리는 화면에 어떻게 페이지 요소가 배치되고 표시되어야 하는지를 정의한다. 이후, 렌더링 엔진은 화면에 웹페이지를 렌더링한다.
  • 네트워크 요청과 응답 처리
    • 브라우저는 웹페이지를 로드하기 위해 서버로부터 HTML, CSS, 자바스크립트 및 이미지와 같은 자산을 요청하고 응답을 받는다. 이 과정에서 HTTP 요청 및 응답을 처리하며, 필요한 자원을 다운로드하고 표시한다.
  • 캐싱 및 저장소 관리
    • 브라우저는 이전에 방문한 웹페이지의 자원을 캐싱하여 성능을 향상시킬 수 있다. 또한 브라우저에 내장된 Web Storage를 이용해 데이터를 클라이언트 측에 저장하고 관리할 수 있다.
  • 보안 기능
    • 브라우저는 사용자의 개인 정보를 보호하기 위한 보안 기능을 제공한다. 이러한 기능에는 HTTPS 연결, 쿠키 관리, 크로스 사이트 스크립팅(XSS) 및 크로스 사이트 요청 위조(CSRF) 방어가 포함된다.
  • 브라우저 개발자 도구
    • 개발자 도구는 웹 개발자가 웹페이지를 디버깅하고 프로파일링하는 데 도움을 주는 기능을 제공한다. 이 도구를 사용하여 소스 코드를 검사하고 성능 문제를 해결할 수 있다.
  • 다국어 및 다국적 지원
    • 브라우저는 다국어 및 다국적 웹 사이트를 지원하기 위한 다양한 언어 및 문자 인코딩을 처리한다. 또한 지리적 위치를 기반으로 서비스 및 콘텐츠를 제공할 수 있는 기능을 제공한다.
  • 사용자 인터페이스
    • 브라우저는 사용자에게 웹페이지를 효과적으로 표시하고 사용할 수 있도록 다양한 사용자 인터페이스 요소를 제공한다. 이에는 주소 표시줄, 북마크, 탭 관리, 히스토리 관리 등이 포함된다.
       

15-1-2. 브라우저의 구조적 이해

  • 사용자 인터페이스
    • 브라우저의 사용자 인터페이스(User Interface)는 주소 표시줄, 뒤로/앞으로 가기 버튼, 북마크, 탭 관리 등과 같은 요소를 말한다.
  • 브라우저 엔진
    • 브라우저 엔진(Browser Engine)은 사용자 인터페이스와 렌더링 엔진 간의 상호작용을 관리한다. 예를 들어, 사용자가 주소를 입력하면 브라우저 엔진은 해당 페이지를 로드하도록 지시한다.
  • 렌더링 엔진
    • 렌더링 엔진(Rendering Engine)은 웹페이지를 표시하는 역할을 한다. HTML 및 CSS 문서를 해석하고 화면에 그린다. 가장 널리 사용되는 렌더링 엔진으로는 Gecko(파이어폭스), WebKit(사파리, 크롬), Trident(구버전의 인터넷 익스플로러), Blink(최신 버전의 크롬) 등이 있다.
  • 통신
    • 통신(Networking) 부분은 HTTP 요청을 보내고, 서버로부터 리소스를 다운로드한다. 브라우저는 이를 통해 웹페이지의 HTML, CSS, 자바스크립트, 이미지 등을 가져온다.
  • 자바스크립트 해석기
    • 자바스크립트 해석기(Javascript Engine) 자바스크립트 코드를 해석하고 실행한다. 각 브라우저는 고유한 자바스크립트 엔진을 사용한다. 예를 들어, 크롬은 V8 엔진을 사용하고, 파이어폭스는 SpiderMonkey를 사용한다.
  • UI 백엔드
    • 사용자 인터페이스(User Interface)를 생성하고 제어하며, 사용자가 클릭하고, 입력하는 등의 이벤트를 처리한다.
 

15-2. 브라우저의 렌더링 과정

15-2-0. 통신

브라우저가 본격적으로 동작하기 앞서서 서버의 요청이 우선된다. 이에 따른 응답에는 리소스가 포함되어 있고 브라우저는 이를 화면에 그린다.
서버에 요청을 하는 방식 중 하나로 브라우저의 주소창을 이용할 수 있다. 사용자가 빈 브라우저 화면에 주소를 입력하는 행위는 서버에 요청을 보내는 행위와 같은데, 입력된 주소의 도메인은 DNS 서비스를 통해 IP 주소로 변환되고, 이 IP 주소로 특정 서버를 찾아내 요청과 응답을 주고 받을 수 있다.
 

15-2-1. 파싱과 DOM 생성

본격적인 브라우저의 동작은 여기서 시작한다. 웹 브라우저에서 파싱(Parsing)과 DOM 생성은 웹페이지 렌더링 프로세스의 초기 단계로, HTML 문서를 해석하고 웹페이지의 구조를 표현하는 핵심 과정이다.
  • 파싱
    • 파싱은 브라우저가 서버로부터 받은 HTML 문서를 이해하고 분석하는 과정이다. 브라우저가 HTML 코드를 파싱함으로써 문서의 각 요소, 속성, 텍스트 내용 등을 인식하고 구조화된 데이터로 변환한다. 이 과정에서 브라우저는 다음과 같은 단계를 거친다.
    • 토크화(Tokenization): 소스 코드를 분석하여 작은 코드 단위인 토큰(token)으로 분해한다.
    • 토큰화된 데이터를 트리로 변환: 파싱 과정에서 생성된 토큰들로 AST(Abstract Syntax Tree, 추상 구문 트리)를 생성한다. AST는 토큰의 문법적 형태를 반영한 트리 형태의 자료 구조다. 이 트리를 파싱 트리 또는 문서 트리(Document Tree)라고 하며, DOM 트리의 기반을 형성한다.
    • DOM 트리 구축: 트리 구조의 노드들은 각각 HTML 문서의 요소, 속성, 텍스트 등과 연결되며, 문서의 계층 구조를 반영한다.
  • DOM 생성
    • DOM 생성 단계에서는 파싱된 데이터를 기반으로 마크업과 매칭되는 형태의 DOM 트리를 구축한다. DOM은 웹페이지의 구조와 내용을 표현하는 자료 구조로, 웹페이지의 모든 요소를 객체로 나타낸다. 이 객체는 웹페이지에 있는 모든 요소를 조작하고 접근할 수 있는 인터페이스를 제공한다.
       

15-2-2. CSS 파싱과 CSSOM 생성

CSS(Cascading Style Sheets)는 웹페이지의 스타일과 레이아웃을 정의하는 스타일 시트 언어다. 브라우저는 웹페이지를 렌더링할 때 HTML과 함께 CSS도 해석하고 적용해야 한다. 이 과정은 파싱과 DOM 생성과 비슷하지만 별도로 진행되며, CSS 파싱과 CSSOM 생성으로 나눌 수 있다.
브라우저는 HTML을 위에서부터 한 줄씩 파싱하다가 link나 style 태그를 만나면 CSS를 로드하고 파싱한다. 그러나 스크립트가 문서를 파싱하는 동안 스타일 정보를 요청하는 경우라면 DOM 생성을 중단 후 외부 CSS 파일과 내장 스타일을 파싱하여 CSSOM 트리를 구축한다.
CSS 파싱 역시 브라우저가 CSS 코드를 해석하고 이해하는 과정이다. 토크나이징을 통해 CSS 코드를 잘게 쪼개어 구조를 분석하고 CSS 규칙에 맞추어 요소에 해당하는 스타일을 결정한다. CSSOM은 웹페이지의 스타일 정보를 표현하는 별도의 객체 모델이며 DOM과 유사한 구조를 가진다.
 

15-2-3. 렌더 트리 구축

웹 브라우저가 웹 페이지를 표시하기 위한 중요한 단계 중 하나는 렌더 트리를 구축하는 것이다. 렌더 트리는 DOM과 CSSOM을 결합하여 웹 페이지를 화면에 그리기 위한 구조를 정의한다. 이 과정은 웹 페이지의 시각적 표현을 정의하고 브라우저가 어떻게 렌더링해야 하는지를 결정하는 중요한 부분이다.
  • DOM 트리와 CSSOM 트리 결합
    • 렌더 트리 구축은 DOM 트리와 CSSOM 트리를 결합하며 시작된다. 두 트리는 각각 HTML 문서의 구조와 스타일 정보를 표현한다.
  • 스타일 계산
    • 렌더 트리 구축은 DOM 트리와 CSSOM 트리를 결합하며 시작된다. 두 트리는 각각 HTML 문서의 구조와 스타일 정보를 표현한다.
  • 레이아웃 계산
    • 레이아웃을 계산하여 요소의 위치와 크기를 정한다. 이러한 정보는 렌더 트리에 저장되며, 어떤 요소가 어떻게 배치되어야 하는지를 정의한다.
  • 렌더 트리 생성
    • 스타일과 레이아웃 계산이 완료되면, 이 정보를 기반으로 렌더 트리를 구축한다. 렌더 트리는 화면에 렌더링하기 위해 생성되는 자료 구조이므로 화면에 나타나지 않는 요소나 숨겨진 요소는 제외된다.
브라우저가 렌더 트리를 완성하면 각 요소는 화면에 어떻게 표시되어야 하는지에 대한 정보를 가지고 있게 된다. 이 정보로 브라우저는 화면에 콘텐츠를 배치하고 스타일을 적용한다.
 

15-2-4. 자바스크립트 파싱과 실행

자바스크립트는 웹 페이지를 동적으로 만들고 상호작용을 가능하게 하는 핵심 언어이다. 자바스크립트 코드 역시 브라우저에서 파싱(Parsing) 및 실행(Execution)되어야 한다.
  • 자바스크립트 파싱
    • 스코프와 변수 결정
      • 변수의 선언과 할당을 스코프에 따라 처리하고, 변수의 유효 범위를 결정한다. 이 과정에서 스코프 체인을 구성하고 변수 이름을 해결한다.
    • 실행 컨텍스트 생성
      • 코드 실행을 관리하기 위한 실행 컨텍스트를 생성한다. 실행 컨텍스트에는 변수, 함수, this 값 등의 정보가 포함된다.
  • 실행
    • 파싱된 자바스크립트 코드는 실행되어 웹 페이지의 동작을 구현한다.
    • 코드 실행
      • 추상 구문 트리를 기반으로 자바스크립트 엔진은 코드를 실행한다. 함수 호출, 변수 할당, 연산 등이 이루어진다.
    • 스코프 체인 활용
      • 실행 중에 변수와 함수에 접근할 때 스코프 체인을 활용하여 유효한 변수를 찾는다.
    • 비동기 작업 처리
      • 자바스크립트는 비동기적인 작업을 처리할 수 있다. setTimeout, AJAX 요청, 이벤트 핸들링 등 비동기 작업은 실행 스택을 차단하지 않고 백그라운드에서 처리된다.
    • 이벤트 루프
      • 자바스크립트는 단일 스레드로 동작하면서 비동기 작업을 처리하기 위해 이벤트 루프를 사용한다. 이벤트 루프는 실행 스택과 메시지 큐를 관리하여 비동기 작업을 조절한다.
         

15-2-5. 배치 및 리플로우와 리페인트

웹 브라우저가 웹 페이지를 표시하는 과정에서 중요한 단계 중 하나는 배치(Layout) 단계이다. 이 단계에서는 렌더 트리에 있는 각 요소의 정확한 위치와 크기를 계산한다. 리플로우(Reflow)와 리페인트(Repaint)는 DOM이 변경될 때 추가되는 렌더링 과정의 일부로, 화면에 변경된 부분을 다시 그리는 작업을 수행한다.
  • 배치
    • 요소의 크기와 위치 결정
      • 배치는 렌더 트리의 각 요소에 대해 화면 내의 정확한 위치와 크기를 계산하는 프로세스다. 이 과정에서 각 요소의 상대적인 위치, 블록 레이아웃 및 인라인 레이아웃 등을 고려한다.
    • 계산 과정
      • 브라우저는 렌더 트리의 루트 요소부터 시작하여 하위 요소로 이동하며 크기와 위치를 계산합니다. 이 계산은 요소의 스타일, 상위 요소의 크기, 박스 모델, 플로팅 요소, 포지셔닝 등을 고려하여 수행된다.
  • 리플로우와 리페인트
    • 리플로우
      • 리플로우는 요소의 크기 또는 위치 변경으로 인해 레이아웃이 다시 계산되어야 할 때 발생한다. HTML 요소의 크기, 위치, 구조 등의 변경으로 인해 발생하며, 브라우저 창의 크기가 변경되거나 스크롤바를 조작하는 것도 포함한다. 아래는 리플로우를 유발할 수 있는 요소의 예시이다.
      • 요소의 크기 변경
      • 폰트 크기 변경
      • 요소의 추가, 제거, 숨김
      • 윈도우 리사이즈
    • 리페인트
      • 리페인트는 화면에 표시되는 요소의 시각적 속성(색상, 배경, 텍스트 등)이 변경될 때 발생한다. 레이아웃 변경 없이 시각적인 업데이트를 수행한다. 다음과 같은 요소 변경이 리페인트를 유발할 수 있다.
      • 배경색, 텍스트 색상 변경
      • 그림자 효과 적용
      • 요소의 가시성(visible) 변경
      • CSS 클래스의 스타일 변경
💡
리플로우, 리페인트의 최소화 브라우저에서는 성능 최적화와 사용자 경험 향상을 위해 리플로우와 리페인트를 최소화해야 한다. 리플로우와 리페인트는 웹 페이지의 배치와 그리기를 다시 계산하는 비용이 큰 작업이며, 빈번한 발생은 페이지의 반응성과 속도를 저하한다. 따라서 개발자는 개발 요소 중 리플로우와 리페인트를 발생시키는 요소가 무엇인지 이해하고, 이에 주의해야 한다.
레이아웃, 리플로, 리페인트는 웹 페이지의 성능에 영향을 미치는 핵심 요소 중 하나이다. 웹 개발자는 효율적인 CSS 및 레이아웃 설계를 통해 리플로와 리페인트를 최소화하고 웹 페이지의 렌더링 성능을 최적화하는 데 기여할 수 있다.