본문 바로가기

CS 학습 정리

Parser와 웹 브라우저의 HTML분석 방식 및 정규표현식에 대하여

728x90

https://ko.wikipedia.org/wiki/%EA%B5%AC%EB%AC%B8_%EB%B6%84%EC%84%9D

 

구문 분석 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전.

ko.wikipedia.org

 

컴퓨터 과학에서 파싱((syntactic) parsing)은 일련의 문자열을 의미있는 토큰(token)으로 분해하고 이들로 이루어진 파스 트리(parse tree)를 만드는 과정을 말한다.

 

 

 

tokenizer, lexer, parser 역할과 책임

1. 토크나이저 (Tokenizer)

역할:

  • 입력 텍스트를 의미 있는 단위인 토큰(token)으로 분할합니다.

책임:

  • 텍스트 스트림을 공백, 구두점, 특수 기호 등을 기준으로 나누어 개별 토큰을 생성합니다.
  • 언어에 따라 다를 수 있는 토큰화 규칙을 적용합니다. 예를 들어, 영어 텍스트에서는 공백과 구두점 등을 기준으로, 한글 텍스트에서는 단어 단위나 음절 단위로 나눌 수 있습니다.

예:

  • 입력: int x = 42;
  • 출력: ["int", "x", "=", "42", ";"]

2. 렉서 (Lexer)

역할:

  • 토크나이저가 생성한 토큰을 받아들여 각 토큰의 유형(토큰 타입)을 결정합니다.

책임:

  • 각 토큰을 분석하여 그것이 어떤 종류의 토큰인지 식별합니다. 예를 들어, 식별자(identifier), 숫자(literal), 연산자(operator) 등을 구분합니다.
  • 종종 토크나이징 과정도 포함하여, 텍스트를 처음부터 끝까지 한 번에 처리하면서 토큰을 생성하고 분류합니다.

예:

  • 입력: ["int", "x", "=", "42", ";"]
  • 출력: [("KEYWORD", "int"), ("IDENTIFIER", "x"), ("OPERATOR", "="), ("NUMBER", "42"), ("SEMICOLON", ";")]

3. 파서 (Parser)

역할:

  • 렉서가 생성한 토큰 스트림을 받아들여 문법 규칙에 따라 구조적인 구문 트리(syntax tree)를 생성합니다.

책임:

  • 문법을 정의하는 문맥 자유 문법(context-free grammar)에 따라 토큰의 순서와 조합이 유효한지 확인합니다.
  • 토큰이 주어진 언어의 문법 규칙에 맞는지 검사하여 구문 오류를 탐지합니다.
  • 유효한 경우, 구문 트리 또는 추상 구문 트리(AST)를 생성합니다. 이 트리는 소스 코드의 계층적 구조를 나타내며, 이후 단계에서 사용됩니다.

웹 브라우저 DOM 파서가 HTML 문서를 분석하는 방식, Document를 재구성하는 방식

1. HTML 문서 수신

웹 브라우저가 HTML 문서를 서버로부터 수신합니다. 이는 네트워크를 통해서 이루어지며, 문서는 일반적으로 스트리밍 방식으로 점진적으로 수신됩니다.

2. 토큰화 (Tokenization)

HTML 문서는 스트리밍 방식으로 한 번에 한 문자씩 읽혀집니다. 브라우저의 HTML 파서(tokenizer)는 이 문자를 하나씩 처리하여 토큰(token)으로 변환합니다. 토큰은 태그, 속성, 텍스트 노드 등을 포함합니다.

  • 태그 토큰: <html>, </body>, <img src="image.jpg">
  • 텍스트 토큰: 태그 외의 모든 텍스트

3. 트리 구성 (Tree Construction)

토큰이 생성되면, 파서는 이를 기반으로 DOM(Document Object Model) 트리를 구성하기 시작합니다. DOM 트리는 HTML 문서의 계층적 구조를 반영하며, 각 요소는 노드(node)로 표현됩니다.

  • 시작 태그 토큰이 파싱되면, 새로운 요소 노드가 생성되고 트리에 추가됩니다.
  • 종료 태그 토큰이 파싱되면, 현재 노드의 부모 노드로 돌아갑니다.
  • 자식 노드는 현재 노드의 자식으로 추가됩니다.

4. 속성 처리 (Attributes Processing)

시작 태그 토큰에 속성이 포함되어 있으면, 해당 속성들도 노드에 추가됩니다.

  • 예: <img src="image.jpg" alt="Description"> 태그는 src와 alt 속성을 가진 img 노드를 생성합니다.

5. 텍스트 노드 처리 (Text Node Processing)

텍스트 토큰은 텍스트 노드로 변환되어 현재 노드의 자식으로 추가됩니다.

  • 예: <p>Hello, world!</p>는 p 요소의 자식으로 "Hello, world!" 텍스트 노드를 가집니다.

6. 트리 수정 (Tree Modification)

HTML 문서의 일부는 파서가 트리를 수정하도록 지시할 수 있습니다. 예를 들어, <table> 요소 내의 <tr> 요소는 <tbody> 요소로 자동으로 감싸질 수 있습니다. 이는 HTML5 명세에 정의된 암묵적인 트리 수정 규칙에 따릅니다.

7. 스크립트 처리 (Script Execution)

HTML 문서 내의 <script> 태그는 파싱이 일시 중단되고, 해당 스크립트가 실행됩니다. 스크립트는 DOM 트리를 수정할 수 있습니다.

  • 동기 스크립트: 스크립트가 로드되고 실행될 때까지 파싱이 중단됩니다.
  • 비동기 스크립트: 파싱과 병렬로 로드되고 실행됩니다.

8. 마무리 (Completion)

문서의 끝에 도달하면, 파싱이 완료되고 최종적인 DOM 트리가 생성됩니다. 이 트리는 JavaScript를 통해 조작되거나 브라우저 렌더링 엔진에 의해 렌더링됩니다.

 

** 스크립트를 만났을 때 파싱이 중단? **

스크립트 처리의 기본 원칙

  1. 동기 스크립트 처리: <script> 태그를 만나면 브라우저는 HTML 파싱을 중단하고 스크립트를 로드하여 실행합니다.
  2. 비동기 스크립트 처리: <script> 태그에 async 또는 defer 속성이 있는 경우, 스크립트 로드 및 실행 방식이 달라집니다.

동기 스크립트 처리

  1. 토큰화 중단: 파서가 <script> 태그를 만나면 HTML 토큰화를 중단합니다.
  2. 스크립트 로드: <script src="...">로 외부 스크립트 파일을 로드하거나 <script>...</script>로 인라인 스크립트를 읽습니다.
  3. 스크립트 실행: 스크립트가 로드되면 즉시 실행됩니다.
  4. 파싱 재개: 스크립트 실행이 완료된 후 HTML 파싱이 재개됩니다.

 

정규 표현식에 대해

정규표현식(正規表現式, Regular Expression, regex 또는 regexp)은 문자열에서 특정 패턴을 찾거나 조작하기 위해 사용하는 강력한 도구입니다. 정규표현식은 텍스트의 일부분을 매칭하는 데 사용되며, 주로 문자열 검색, 대체, 검증 작업에 활용됩니다. 정규표현식은 다양한 프로그래밍 언어와 도구에서 지원됩니다.

 

메타문자 (Metacharacters)

  • 특별한 의미를 가지며, 특정 패턴을 나타냅니다.
  • 주요 메타문자: . ^ $ * + ? { } [ ] \ | ( )

메타문자의 의미

  • .: 임의의 단일 문자와 매칭합니다.
  • ^: 문자열의 시작을 나타냅니다.
  • $: 문자열의 끝을 나타냅니다.
  • *: 0회 이상 반복을 나타냅니다.
  • +: 1회 이상 반복을 나타냅니다.
  • ?: 0회 또는 1회 나타남을 의미합니다.
  • {n}: 정확히 n번 반복을 나타냅니다.
  • {n,}: n번 이상 반복을 나타냅니다.
  • {n,m}: n번 이상 m번 이하 반복을 나타냅니다.
  • []: 문자 클래스, 대괄호 안에 있는 문자 중 하나와 매칭합니다.
  • \: 이스케이프 문자, 메타문자나 특별한 의미를 가진 문자를 문자 그대로 매칭할 때 사용합니다.
  • |: OR 연산자, 선택 패턴을 나타냅니다.
  • () : 그룹화, 특정 패턴을 그룹으로 묶어 하나의 단위로 취급합니다.

 

문자 클래스

  • [abc]: a, b, 또는 c 중 하나와 매칭
  • [a-z]: 소문자 알파벳 중 하나와 매칭
  • [A-Z]: 대문자 알파벳 중 하나와 매칭
  • [0-9]: 숫자 중 하나와 매칭

반복

  • a*: 'a'가 0번 이상 반복 (빈 문자열도 매칭)
  • a+: 'a'가 1번 이상 반복
  • a?: 'a'가 0번 또는 1번 나타남
  • a{3}: 'a'가 정확히 3번 나타남
  • a{3,}: 'a'가 3번 이상 나타남
  • a{3,5}: 'a'가 3번 이상 5번 이하 나타남

그룹화와 OR 연산자

  • (abc): 'abc'와 정확히 매칭
  • a|b: 'a' 또는 'b'와 매칭
  • (abc|def): 'abc' 또는 'def'와 매칭

앵커

  • ^abc: 문자열의 시작에서 'abc'와 매칭
  • abc$: 문자열의 끝에서 'abc'와 매칭
  • ^abc$: 정확히 'abc'와 매칭되는 전체 문자열

이메일 주소 검증

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

 

 

 

  • ^: 문자열의 시작
  • [a-zA-Z0-9._%+-]+: 알파벳, 숫자, 몇몇 특수문자 중 하나 이상
  • @: '@' 문자
  • [a-zA-Z0-9.-]+: 알파벳, 숫자, '.', '-' 중 하나 이상
  • \.: '.' 문자
  • [a-zA-Z]{2,}: 알파벳 두 글자 이상
  • $: 문자열의 끝

정규 표현식을 사용하면 한편하게 Validation Check 를 진행할 수 있고, SQL Injection 공격을 막을 때도 자주 쓰인다.