HLS란 무엇인가?


HLS (HTTP Live Streaming) 이며 주문형 스트리밍 이자 라이브 스트리밍 입니다. 일반적으로 우리는 웹상에서 동영상을 볼 때 한 동영상파일의 전체크기를 다운받고 시청을 하지 않습니다. 한 동영상파일을 잘게 분리한다음 한 조각조각씩 사용자가 순서대로 다운받아와서 동영상을 시청할 수 있는 방식입니다.

실제로 일상생활에서도 동영상을 보다가 HTTP통신환경이 좋지않아 동영상이 끊길 경우가 종종 생깁니다. 저는 이 경우를 버퍼링이 걸리는 경우로 기억하고있습니다. 항상 한 가지 개념을 기억하기 가장 좋은 예시는 본인의 경험의 한 상황으로 연결짓는다면 기억에 오래남는 것 같습니다. 실제로 버퍼링의 의미는 말 그대로 버퍼에 데이터를 담는다는 뜻으로 쓰이고 버퍼링이 걸린다 라는 것은 네트워크 통신이 약해져서 우리가 보고있는 (동영상 데이터)가 버퍼에 담기지않아 지금까지 버퍼에 담아두었던 영상의 부분까지만 시청하고 대기상태에 이르는 상황인 것입니다.

다시 HLS의 얘기로 돌아와서 HLS는 비디오 스트리밍 프로토콜로 Apple사가 개발했고 현재는 다양한 장치에서 이 프로토콜이 활용되고 있습니다.

다양한 장치에서까지 이 프로토콜을 사용하는 이유는 무엇일까요?

HLS의 장점으로는 모든 인터넷 연결 장치가 HTTP를 지원하기 때문에 전용 서버가 필요한 스트리밍 프로토콜보다 간단하게 실행할 수 있다는 것입니다.

또 다른 장점은 HLS스트리밍은 재생에 지장을 주지 않으며 네트워크 상태에 따라 비디오품질을 높이거나 낮출 수 있다는 것입니다. 여기까지 읽었을 때 가끔 영상을 보다가 화질이 안좋아지는 경험을 해보신 분이라면 공감을 하실 수 있을 것 같습니다.

이 때문에 사용자는 시청중 품질이 나빠지거나 좋아질 수 있고(네트워크 상황에 따라) 이 기능은 "적응 비트 전송률 비디오 전송", "적응비트 전송률 스트리밍" 이라고 알려져 있으며 이 기능이 없으면 네트워크가 느려진 경우 비디오 재생이 완전히 멈출 수 있습니다.

여기서 스트리밍에 대한 개념을 한번 짚고 넘어가겠습니다.

스트리밍은 무엇이냐?

  • 스트리밍은 인터넷을 통해 비디오, 오디오 미디어를 전달하는 방식으로 미디어파일을 한 번에 모두 보내는 대신 한 번에 조금씩 지속적으로 사용자 장치에 보냅니다. 원 미디어 파일은 멀리 떨어진 곳에 저장되어 있거나 라이브 스트리밍의 경우 원격 카메라나 마이크를 이용하여 실시간으로 제작됩니다.
  • 위 특징을 읽어보면 HLS의 이야기와 같게 느껴질 수 있습니다. 결론적으로 맞습니다 스트리밍의 방식을 그대로 적용하기 때문입니다.
  • 그리고 이 작은 데이터조각들을 지속적으로 사용자가 다운로드받는 것을 버퍼링 이라고 합니다.

그래서 이 HLS는 적응 비트레이트 스트리밍 방식의 스트리밍을 제공합니다.

그렇다면 이제 HLS 중 H에 대한 이야기가 남아있습니다.

H는 HTTP입니다.

HTTP(Hyper Text Transfer Protocol)는 무엇이냐?

  • HTTP는 네트워크에 연결된 장치사이 정보를 전송하기 위한 어플리케이션 계층 프로토콜입니다. 일반적인 사용자가 액세스할 수 있는 모든 웹사이트와 어플리케이션은 HTTP에서 실행됩니다. HTTP를 통한 데이터 전송은 일반적으로 용청과 응답에 따라 이루어지며 이 HTTP의 통신방식은 추후 다른 게시글을 통해 자세하게 설명해드리겠습니다. 현재는 이 HTTP는 목적지와 편지를 주고 받는 개념이라고 생각하시면 좋을 것 같습니다.
  • 그리고 이 HTTP를 스트리밍의 경우 표준 요청 응답 패턴이 적용되지 않습니다. 클라이언트와 서버 사잉의 연결은 스트리밍 기간 동안 열려 있고 서버는 비디오 데이터를 클라이언트는 비디오 데이터 세그먼트마다 요청하지 않아도 됩니다.
  • 또한 HTTP통신 중 데이터를 주고 받을 때 흔히 발생하는 CORS, CORB 에러가 있습니다. 이 에러는 HTTP의 구조를 조금 더 명확하게 알고 있다면 수월하게 해결할 수 있으며 이 문제역시나 다른 게시글에서 조금 더 깊게 다루어 보겠습니다.

이 HLS의 또 다른 특징으로는 스트리밍 데이터를 .m3u8 확장자와 .ts확장자를 가진 파일로 분리한다는 특징이 있습니다.

저는 이것을 직접 구현하기위해 우선 ffmpeg 프로그램을 이용해 동영상 파일은 분리하는 작업을 진행했습니다.

코드는 다음과 같고 ffmpeg파일은 HLS관련 코드를 검색하시면 쉽게 구하실 수 있습니다.

const ffmpeg = require('fluent-ffmpeg');

const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg');

//ffmpegInstaller는 ffmpeg만 사용했을 때 생겼던 오류를 해결하기 위해 사용.
ffmpeg.setFfmpegPath(ffmpegInstaller.path);

ffmpeg('videos/고등어조림.mp4', {timeout : 432000}).addOptions([
    '-profile:v baseline',
    '-level 3.0',
    '-start_number 0',
    '-hls_time 10', // hls_time : 몇 초 단위로 동영상을 분할할 것인지 설정
    '-hls_list_size 0',
    '-f hls' // 포맷을 설정 -> HLS사용.
]).output('videos/output.m3u8').on('end',() =>{
    console.log('end');
}).run();

소스를 보시면 fluent-ffmpeg라는 것을 처음 불러오고 이 ffmpeg를 통해 "videos/고등어조림.mp4" 라는 동영상 파일을 옵션에 맞게 분할하는 것을 생각해볼 수 있습니다. 그리고 output부분을 확인해보시면 m3u8의 확장자로 뽑아내는 것을 확인할 수 있습니다.

이렇게 m3u8파일만 뽑는 것처럼 읽을 수 있으나 m3u8뿐만 아니라 ts파일 역시 같이 만들어지게되고 이 m3u8은 ts파일들의 순서를 기록하는 설명서역할을 합니다.

즉 웹 브라우저는 HTTP통신을 통해 처음 m3u8파일을 최초로 가져오게되고 이 m3u8의 내용을 읽어 0번째의 ts(동영상 분할 파일)을 가지고와서 영상데이터를 제공하는 방식입니다.

저는 이 HLS protocol을 이용하는 방식을 React X Spring Boot에서 이용해 보았습니다. 처음 설계를 진행할 때는 이 Spring Boot가 스트리밍 서버의 목적에 맞지 않고 조금더 범용적인 여러 기능을 핸들링할 수 있는 백엔드서버의 역할성 때문에 또 다른 백엔드서버인 Nodejs를 활용해 스트리밍서버를 구성하려고 했으나 해당 프로젝트를 진행할 때 강사님의 조언으로는 백엔드서버가 여러개 있는 것보단 현재 프로젝트 기준으로써는 하나의 백엔드 서버가 맞다는 이야기에 Spring Boot 백엔드 API서버와 React의 react-hls-player를 통해 이 프로토콜을 활용하게 되었습니다.

해당 프로젝트의 소스코드가 궁금하신 분들을 위해 아래 깃허브 링크를 남겨두겠습니다.

이상으로 HLS Protocol에 대한 간단한 개념 정리글을 마치겠습니다.

https://github.com/ukjinlee66/metanet_internship_project

HLS에 대한 기초적인 소스코드를 확인하고싶다면 root위치에 streaming_server/HLSTest 를 확인해주시면 감사하겠습니다.

Reference

'지식 창고' 카테고리의 다른 글

MSA란 무엇일까?  (0) 2023.01.10
REST API란?  (0) 2022.09.12
프레임워크랑 라이브러리는 뭐가 다를까??  (0) 2022.09.03

[JAVA]JAVA 언어의 특징


자바언어를 이용한 자바 프로그래밍을 생각해보면 객체지향 프로그래밍 OOP(Object Oriented Programming)이라 해도 상관없습니다. 그 이유는 자바언어의 특징을 소개하며 설명을 이어나가겠습니다.

자바 언어는 크게 5가지 특징을 가지는데 아래와 같습니다

  • 객체 지향 프로그래밍(OOP)
  • 자동 메모리 관리(GC)(가비지 컬렉터)
  • 운영체제에 독립적
  • 멀티쓰레드 지원
  • 동적 로딩 지원

첫번째로 객체 지향 프로그래밍의 대표적인 특징은 아래 4가지가 존재합니다.

  • 상속 (Inheritance) : 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게 하고 기능의 일 부분을 변경해야 할 경우 상속받은 자식클래스에서 해당기능을 재정의(수정)해 사용할 수 있는 것입니다.

  • 다형성 (Polymorphism) : 다형성은 상속을 통해 기능을 확장하거나 변경하는 것을 가능하게 해줍니다. 이를 통해 코드의 재사용, 코드길이 감소, 유지보수가 용이해지는 특징이 있습니다. 여기서 크게 두가지 개념으로 오버라이딩(Overriding)과 오버로딩(Overloading)이 있습니다.

    • /*
      **오버라이딩 (Overriding)
      ** - 상위 클래스가 가지고 있는 메소드를 하위 클래스가 재정의해서 사용합니다.
      */
      
      //부모클래스
      class Parent{
        public String name;
        public int age;
        public void Speak(){
          System.out.println("일어나 ~ 학교 가야지 ~");
        }
      }
      //자식클래스
      class Child extends Parent{
        public String name;
        public int age;
        public void Speak(){
          System.out.println("10분만 더 잘게요 ~ ");
        }
      }
      public class Test{
        public static void main(String[] args){
          //자식 클래스의 객체 생성
          Child ch = new Child();
      
          //자식 객체의 변수 설정
          ch.name = "아무개";
          ch.age = 10;
      
          //오버라이딩 함수 호출
          ch.Speak();
        }
      }
      /*
      **오버로딩 (Overloading)
      ** - 같은 이름의 메서드 여러개를 가지면서 매개변수의 유형과 개수가 다르도록 하는 기술
      */
      
      class marine
      {
        public void attack(){
          System.out.println("일어나 ~ 학교 가야지 ~");
        }
        public void attack(int damage){
          System.out.println(damage + "만큼의 피해를 입힙니다.");
        }
        public void attack(String class_name, int damage){
          System.out.println(class_name+"이"+damage"만큼의 피해를 입힙니다.");
        }
      }
      public class Test{
        public static void main(String[] args){
          //marine 클래스의 객체 생성
          marine m = new marine();
      
          //매개변수가 없는 attack 메소드 호출
          m.attack();
      
          //매개변수가 1개 있는 attack 메소드 호출
          m.attack(10);
      
          //매개변수가 2개 있는 attack 메소드 호출
          m.attack("warrior", 30);
        }
      }
  • 캡슐화 (Encapsulation, information Hiding) : 캡슐화는 한 객체에 대해 그 객체가 특정 목적을 위해 필요한 변수나 메소드를 하나로 묶는것을 의미합니다. 즉 접근제한자로 변수를 설정해 함부로 변수의 값을 변경할 수 없게 만들고 대신 getter, setter와 같은 메소드를 통해서 접근할 수 있도록 구현할 수 있습니다.

  • 추상화 (Abstraction) : 공통의 속성, 기능들을 묶어 클래스로구성해 확장성을 넓히는 것을 의미합니다. 추상클래스(추상 메소드를 하나이상 포함한 클래스)를 구성하고 추후의 이 class 또는 interface를 상속받아 구현하여 사용하는 것입니다. 공통 기능으로 묶어서 처음 클래스 또는 인터페이스를 구성했기 때문에 설계에 따라서 확장성이 크게 올라갈 수 있습니다. ex)동물이라는 추상 클래스는 행동 이라는 추상 메소드를 가지고 있고 추후에 양서류 등등으로 나뉘어지더라도 이 행동이라는 추상메소드는 계속 상속받아 각 종류에따라서 다르게 구현될 수 있습니다.

그렇다면 이러한 객체지향 프로그래밍을 쓰는 이유는 무엇인가요? 라는 궁금증이 생길 수 있습니다.

객체지향 프로그래밍은 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법입니다.

장단점은 무엇이 있을까? 생각해볼 수 있습니다.

  • 장점
    • 코드 재사용성 증가 - 상속을 통한 확장성 증가
    • 유지보수가 쉬워짐 - 절차 지향 프로그래밍 에서는 코드를 수정해야할 때 하나하나 수정해야하지만 객체지향프로그래밍은 상속받은 부모 클래스의 내용만 수정하면 하위 상속받은 자식클래스의 코드수정을 하지 않아도 됩니다.
    • 대형 프로젝트에 적합 - 클래스 단위로 모듈화시켜 개발할 수 있기 때문에 업무분담하기 쉬워집니다.
  • 단점
    • 처리속도가 상대적으로 느려집니다.
    • 객체가 많으면 용량이 커질 수 있습니다.
    • 설계시 많은 시간과 노력이 필요합니다.

두번째로 자동메모리관리(GC) 가비지 컬렉션을 설명하겠습니다.

Garbage collection(GC)는 메모리관리 기법 중 하나로 프로그램이 동적으로 할당했던 메모리 영역 중 필요없게 된 영역을 해제하는 기능입니다.

C,C++언어같은 경우 동적할당을 받아 배열또는 객체를 생성하게 될 경우 힙메모리 영역에 저장되고 이 부분의 메모리가 할당된 걸 해제하기위해 개발자가 직접 free해주어야합니다. 그러나 자바언어의 경우에는 모든 객체가 클래스기반이며 참조변수 같은경우에는 기본으로 힙에 저장되기때문에 애초에 힙에 저장되는 값들이 많습니다. 이러한 값들을 주기적으로 관리해주기위해 GC가 존재하기도하며 직접 개발자가 System.gc() 를 호출해서 해제할 수 있으나 권장되지 않는것으로 알고있습니다.

세번째로는 운영체제에 독립적입니다.

이말의 의미를 명확하게 이해하려면 JVM(Java Virtual Machine)을 이해하고 있어야 합니다. 자바의 개발 환경과 배포환경이 다를 경우 프로그램을 다시 컴파일 할 필요 없이 실행가능합니다. 그 이유는 JVM은 별도의 Java Compiler를 통해 사용자의 코드를 Byte코드로 변환하고 모든 자바 프로그램은 이론적으로 CPU나 운영체제의 종류와 무관하게 동일하게 동작합니다.

마지막으로 동적로딩, 멀티쓰레드 지원 입니다.

자바는 한 프로그램 내에서 여러 쓰레드가 동작할 수 있는 환경을 제공합니다. C,C++은 운영체제의 도움을 받아 멀티쓰레드를 지원하지만 자바는 이런 운영체제의 지원없이 멀티쓰레드를 이용한 프로그래밍이 가능합니다.

멀티쓰레드를 구현하는 방식음 다음과 같이 두가지가 있습니다.

1) Thread Class (화이트박스 방식)

  • 자바에서 쓰레드를 만들기위해 Thread Class 를 상속받아 쓰레드를 생성합니다.
    2) Runnable Interface (블랙박스 방식)
  • 위 화이트박스 방식과 비슷하게 Thread class와 같이 자바에서 스레드를 실행시키는 인터페이스 이며 다중상속이 지원되기 때문에 Thread class보다 많이 사용됩니다.

추가로 저는 C,C++에서 철학자 문제를 가지고 멀티쓰레드와 멀티 프로세스개념을 이해하며 학습한 적이 있는데 이러한 멀티쓰레드와 멀티프로세싱은 교착상태(데드락)문제를 중요하게 다루고있습니다. 여러개의 쓰레드 또는 프로세스가 공유자원을 이용할 때의 문제점을 다루는 것인데 그당시는 뮤텍스, 세마포어를 활용해 이러한 공유자원문제를 해결하는 방식을 학습했던 적이 있었습니다. 중요한 개념인 만큼 밑에 깃허브 링크를 남겨두겠습니다.

지금은 이런게 있구나 기억하고 넘어가시는게 좋을 것 같습니다.

철학자 문제 - https://github.com/ukjinlee66/42_Philosophers

동적로딩(Dynamic Loading)은 어플리케이션이 실행될 때 모든 객체가 처음부터 생성되지 않고 필요한 시점에서 동적로딩을 통해 생성되는 개념입니다. 이러한 동적 로딩은 클래스를 일부 변경하더라도 재 컴파일을 하지 않아도 되는 장점이 있고 적은 작업으로 처리할 수 있는 유연성을 동적로딩이 제공합니다. 그러나 말 그대로 시점에 따라서 그때그때마다 생성이된다면 당연히 그 시점에 메모리에서 불러오기에 속도가 정적로딩에 비해 느린 편이고 이런 느린 속도를 해결하기위해 Static 키워드를 사용합니다.

Reference

'JAVA' 카테고리의 다른 글

Java - Logging 이란?  (1) 2024.11.12
[JAVA & Database] JDBC, MyBatis, JPA 의 차이점  (1) 2022.09.26
[JAVA]직렬화 - Serializable란?  (0) 2022.05.16
[JAVA]DAO, DTO, VO 정리.  (0) 2021.12.25

처음 외부활동을 마치고 취업을 처음부터 준비를 하기도 전 활동했던 외부활동 단체에서 인턴쉽 프로그램 관련 공고문을 확인하게 되었다.

살면서 인턴이란 것을 한번도 경험해보지 못했던 나로써 실무경험을 해볼 수 있다는 매력적인 특징 때문에 깊게 고민해보지 않고 바로 지원해보았던 것 같다

 

어느곳인지는 말할 수 없으나 처음 인턴쉽 실무에 들어가기 전 교육을 받으며 같이 인턴쉽 프로그램을 진행하는 동기들과 친해지는 시간을 가지며 팀프로젝트도 진행해 보았다. 일정 기간동안 실무를 경험하게 되었다. 무엇보다 회사를 선택하는 기준이라는 것이 없던 나에게 첫 실무경험을 접해보며 원래 개발자란 이런 일은 하는 것인가..? 실 업무를 하며 항상 스스로에게 질문을 던져보았던 것 같다.

 

처음부터 원하는 일을 할 수 있을거란 생각(인턴 실무를 다같이 하는 줄 알았다..) 그러나 실제로는 뿔뿔이 흩어졌다.. 같이 인턴쉽 프로그래밍을 진행했던 동기들 대부분도 묶여서 흩어졌으나 특별하게 나는 혼자서 배정받게 되었다(이때부터 힘들어지기 시작했던 것 같다)

 

첫 출근날.. 급하게 자리를 만들어서 배정을 받게 되었고 이어서 실무 업무를 진행하기 위한 기초 도메인지식에 대한 간략한 설명을 상사분께 듣게 되었다. 처음부터 이쪽을 원해서 온 것도 아니었으며 이런 도메인이 있는지는 알았으나 실제로 내가 해보게 될줄 몰랐다.

처음부터 한번에 많은 이야기를 듣게 되어서인지 명확하게 들리지도 기억에 남지도않았던 것 같다. 이후 협력업체의 보안프로그램과 IP설정등을 진행해야했기에 첫주차 포함해서 두번째주차 절반까지는 실무에서 사용되는 기초 데이터베이스개념과 도메인관련한 개념을 핸드폰검색을통해서 계속 공부했던 것 같다..(이때 정말 시간이 안갔던 것 같다) 주변에 바쁘게 일하시는 분들이 대부분이었기에 따로 질문을 하기에도 어려웠으며 하루 질문을 두번? 정도밖에 못했던 것 같다.

 

이후 PC환경 세팅이 마치는대로 실무에서 사용되는 프로그램등을 설치하고 개발을 시작할 줄 알았으나 실제로 진행되었던 일은 이미짜여진 코드를 활용하는 위주의 업무였다. 개발적인 지식뿐만아니라 개발을 하기위한 프로그램관련 공부도 많이했다.. 이 프로그램을 잘 다루어야 내가 개발할 수 있기에..

 

물론 코드 분석을 잘 해야 하는 것도 필요했고 코드수정에 필요한 해당 개념을 알고있어야 하는것도 꼭 필요했다고 느낀다(도메인 지식, 개발 지식 등)

 

그러나 내가 원했던 스킬셋과는 전혀 연관되어지지 않았던것 때문인지 재미가 없었다 다만 남은 인턴기간을 끝까지 채우기 위해 최소한의 공부를 진행했던 것 같다.. (1인분은 해야겠다 라는 생각..) 그래서 욕심도 크지 않았을 뿐더러 발전시키고 싶지도 않았던 것 같다.

 

계속해서 기초적인 업무숙제(?) 를 받으며 생활하며 퇴근 후 직무와 관련된 많은 정보를 찾아보았던 것 같다.. 인턴쉽이 끝나고 정규직보다는 바로 다른 회사를 가야겠다 생각하게 되었다.

 

솔루션 개발, SI 개발, SM 등등..

 

그리고 한 가지 명확하게 피부로 느낄 수 있었던 것은 나는 SI쪽의 방향과 맞지 않았던 것 같다. 한 프로젝트를 위한 스킬셋과 도메인지식 등을 공부할 수 있었고 다음 프로젝트도 연계해서 진행한다면 물론 이어서 공부할 수 있겠으나 기본적으로 협력업체와의 갑 을 관계에 따라 필요기능만 따라서 구현하게 되고 그 기능마저도 특별하게 확장성과 유지보수등을 고려해서 개발되는것이 아닌 프로젝트의 기간에 급급하게 개발되는 것이 대부분이었다.(확실히 내가 원하는 스킬셋으로 성장할 수 있는 환경이 아니라는것 하나는 명확했다)

 

그러면서 지금까지 클린코드는 어떻게 작성해야하는지.. 확장성있는 코드를 작성하는 방식은 무엇인지.. 이런것을 고집해야한다는 내 생각이 많이 무너졌다.

 

그래서 이 글을 읽는 사람들에게 한 가지 말해주고싶었던 것은 회사의 이름만 보고도 물론 취업을 준비할 수 있으나 직무에 대한 정보를 많이 찾아보고 지원하길 바란다. ( 특히 회사가 어느 방식의 개발을 진행하는지도 중요한 것 같다 )

 

그리고 내가느낀 첫 인턴이었기 때문에 확실히 한 부분만 보고 전체를 판단할 수는 없다고 생각한다.

 

다른 SI회사는 또 다를지도 모르고 성장할 수도 있다. 얻어가는 건 분명히 있다고 생각한다. 그것이 내가 원하는 것일지 원하지않는 것일지 이것은 잘 모르겠으나..

 

새로운 지식을 많이 배우며 프로젝트위주의 개발을 진행해야하기에 마감기한 안에 코드를 빠르게 개발할 수 있는 능력자분들은 조금더 이쪽분야와 맞을 수도 있겠다 생각한다.

 

인턴쉽프로그램을 통해 직무에 관한 많은 정보를 찾아보게 된 계기가 있었던 것 같고 현재는 스타트업과 중견기업 면접을 기다리고 있다. 이후 9월 말쯤에 다시한번 이 카테고리에 글을 남길 수 있을 것같다.

 

 

 

 

'취업 이야기' 카테고리의 다른 글

의도치 않았던 이직  (0) 2023.06.03
스타트업 신입 개발자 후기  (2) 2022.12.16

문서 객체 모델(DOM)


DOM의 개념


  • 문서 객체 모델 (DOM : Document Object Model) 은 XML, HTML 문서의 각 항목을 계층적으로 표현해 생성, 변형, 삭제 를 할 수 있도록 돕는 인터페이스이다.
  • 쉽게말해 웹 브라우저에서 HTML문서의 요소를 제어하기위해 생겨났으며, DOM은 동적으로 문서의 내용, 구조, 스타일에 접근할 수 있다.
  • 브라우저 사이에 DOM 구현이 호환되지 않음에 따라 W3C에서 DOM의 표준 규격을 작성하게 되었다.
  • DOM의 역사는 1990년 초반 넷스케이프와 마이크로 소프트사의 IE사이에서 브라우저 전쟁과 밀접한 관련이 있다. 이 전쟁 중 최전선에 있던것이 웹 브라우저의 레이아웃 엔진으로 사용했던 JavaScript, JScript였고 이 스크립트 엔진이 DOM을 주 API로 사용했던 것이다.

DOM은 W3C의 표준이며 W3C의 표준화한 API들의 기반이 된다.

DOM의 구조는 트리구조형태로 이루어지며 다음사진과 같다.

DOM-model.svg

W3C DOM표준은 세 가지 모델로 구분된다.

  • Core DOM : 모든 문서 타입을 위한 DOM 모델
  • HTML DOM : HTML문서를 위한 DOM 모델
    • HTML DOM은 HTML문서를 조작하고 접근하는 표준화된 방법을 정의합니다. 모든 HTML요소는 HTML DOM을 통해 접근할 수 있다.
  • XML DOM : XML 문서를 위한 DOM 모델
    • XML DOM은 XML문서에 접근해 그 문서를 다루는 표준화된 방법을 정의하고, 모든 XML요소는 XML DOM을 통해 접근 가능하다.

그렇다면 웹페이지에서 이 DOM은 어떻게 사용될까?

DOM이 사용되기 전 브라우저와 서버사이에서 화면이 그려지는 과정을 먼저 확인해보자.

Critical Rendering Path(CRP)라는 개념을 먼저 알아보자.

이 CRP는 브라우저에서 서버로부터 HTML문서를 받아서 랜더링을 진행할 시 진행되며 다음과같이 6단계로 나누어져있다.

  1. DOM 트리 생성
  2. CSSOM 트리 생성
  3. JavaScript 실행
  4. Render 트리 생성
  5. 레이아웃 생성
  6. 페인팅

과정이 있다.

여기에서 위에 설명한 DOM트리 생성과정이 진행되고 이 DOM트리로부터 html, element, text 에 대한 노드가 생성된다.

이후 CSSOM이라는 DOM과 유사한 트리가 생성되는데 이 CSSOM은 DOM과는 다르게 구조는 비슷하지만 상속관계와 선언관계등을 상관하지않고 각 노드에 관련되어서 생성된다. CSS의 특징으로는 상속된 계단식 특성을 가지고있음으로 부분적으로 실행이 불가능하고 문서의 뒷부분에 스타일이 재정의 될 경우 의도치않게 CSS가 적용되는 문제가 발생할 수도 있다.

JavaSciprt는 파서 차단 리소스로 간주되는데 흔히 html파일을 작성 중 script영역의 태그를 선언하고 스크립트 코드를 작성하게된다. 이 sciprt부분 부터는 기존 DOM의 파싱이 차단되기때문에 항상 HTML태그에 따른 내용을 전부 작성한 후 sciprt태그와 코드를 작성해야 한다. 혹은 이 JavaScript가 파서를 차단하지 않도록 하기 위해서 async옵션을 주기도 한다.

이후 Render Tree가 만들어지는데 이 Render Tree는 위에서 파싱된 DOM, CSSOM을 조합하여 결과적으로 랜더링 될 내용을 나타내는 트리이다.

레이아웃 생성에서는 뷰포트의 크기를 설정하는 단계이고 meta태그에 설정된 뷰포트에 맞게 설정된다.

마지막으로 페인팅으로는 페이지의 가시적인 내용을 픽셀로 변환해 화면에 나타나는 작업을 진행한다.

Reference

+ Recent posts