TIL

[TIL] HTML의 파싱 feat. ChatGPT

youngble 2023. 2. 26. 22:25

오늘은 간단하게 면접때 질문 받은것 중에서도 실제 사례의 사이트를 보여주며 물어봤던게 신선해서 적어볼려고한다.
해당사이트는 spotify 였는데 지금들어가면 그러진 않은데 조금 변형해서 보여줬는지는 모르겠지만 메인화면 로드에서만 5초정도의 로딩후 내용물들이 보이는 현상이 있었다.
 

위의 빨간 체크박스 부분이 뜨지 않다가 생성이 되는데 이러한 현상이 왜 발생하는지에 대해서 이유를 말하는 것이였다. 
 
두가지로 추론을 했는데 첫번재는 html, css, js 등의 리소스를 한번에 불러오는데 많은양이거나 거기에 걸리는 시간으로 인해서 뜨지 않는다는 추정이였지만 그러기에는 많은 리소스가 없을거 같았고 두번째로는 api 요청부분이 있기 때문이라고 생각했다.
 
그런데 메인페이지에서 api요청할게 있을까? 또는 있다고 하더래도 그게 그렇게 오래걸릴 문제인가 라고 생각하니 답이 나오지 않았다.
힌트를 준부분이 GA를 설정하거나 데이터를 보낼때에는 이러한 현상이 없을거냐는 것이였다. 대답은 "가능성이 있다" 라고 하였고 "실질적으로 코드나 분석을 하지 않았기때문에 확실하진 않지만 보내는 요청의 서버가 물리적으로 멀거나 데이터양이 많으면 그럴 가능성이 있다 하지만 실제 제 경험상에서는 이러한 문제가 없었다." 라고 대답했었다.
 
그러다가 deep dive 책을 보면서 렌더링 부분이나 html 파싱부분을 정확하게 이해하고싶어서 보다가 아 이부분이구나 했던거 같다.
html을 파싱을할때 dom 트리, cssom트리, js abstract syntax tree 를 생성하는데 이때 동기적으로 작업을 진행하는지 비동기적으로 진행되는지에 따라서 달라지게 된다.


수정: html 파싱과 렌더링 시점 (레이아웃, 페인트)이 달르므로 화면에 보여지는 시점과 비동기 처리와 관련이 있는지는 좀더 구체적으로 테스트를 해봐야할거 같다. 

찾아본결과 FCP가 실질적으로 빈화면이 아닌 첫번째 컨텐츠 부분을 사용자에게 보여지는 부분(정확히는 이부분이후 렌더링된 부분)을 보여주기때문에 이부분을 알아야한다. 그전에 올렸던 글 https://youngble.tistory.com/211  참고 해야한다. 

 

그리고 FCP 이후 FMP, First Meaningful Paint 까지의 시간과 렌더링과정이 위의 부분과 일치하지 않을까 생각한다.

 

따라서 아래 내용은 개인적인 파싱과정과 script를 비동기 처리하는걸로 일단 생각해야할거같다. 

  
기본적인 html 파싱순서와 그로인한 로딩, 혹은 화면에 랜더링 되는 부분을 제대로 생각을 못했었다.
html을 파싱을하며 dom tree를 생성하면서 linkscript 태그들을 통해 외부나 내부에서 리소스를 만나면 html파싱을 중단하고 해당 작업을 진행한다. 그리고 완료가 되면 중지된 html을 다시 진행하게 된다는 것인데, head부분에 넣어 defer를 사용, 또는 body맨아래에 넣었을때는 파싱을 완료한 시점에서 진행하게 되는데 이때 이미 파싱이 완료되어 렌더링까지 진행하다가 로드가 완료되어 스크립트를 진행한다면 렌더링이 중간에 멈추고 스크립트가 완료된후 다시 렌더링이 진행될수도 있을거 같다.
 
따라서 head에나 bodyscriptmeta 태그를 사용할때는 비동기적으로 작동하도록 해야하는데 script경우는 asyncdefer가 있고,  DOMContentLoaded 가 될때 실행되도록 해야 이러한 CLS 현상을 최적화할수 있다는 것을 좀더 자세히 알게 되었다. 병렬 작업, DOM API 오류 등을 최적화할 수 있다.
html파싱과 js 로드가 비동기적으로 작업하기위해서 asyncdefer를 사용하는데 차이가 있다.

 

async의 경우는 script가 여러가지 있다고 해도 비동기적으로 등록을하고 로드를 하는데 js를 실행하는 시점은 js로드가 끝나면(백그라운드에서 다운로드가 완료되면) 바로 실행을

하게 된다. 이때 html파싱 완료가 되지 않았다면 html파싱을 일시중지하고 이 js실행을 시작하고 완료가 된 시점에서 다시 html파싱을 진행한다는 것이다. 또한 다운로드가 완료된 순서대로 실행이 되기 때문에 script와 DOM에 종속적이고 의존적이라면 원하는 순서로 조작하기 어렵다.


defer의 경우는 똑같이 비동기적으로 병렬로 js 파일을 로드하는데 로드가 완료되어도 바로 실행하는 것이 아닌 html파싱이 완료된 시점에 실행된다는 것이다. 또한 defer를 사용하면 다운 받은 순서와 상관없이 파싱 순서에 따라 실행 되기 떄문에 원하는 순서에 맞게 조작이 가능하다

 

 

 

2022/3/2 추가 내용:

궁금하기도하고 정확한 답이 아닌 애매하게 알게되고 이론만 이렇다 하니깐 답답해서 계속 찾아보았고 먼저 FCP 와 FMP 까지 걸리는데 소요시간이 지연되는게 해당 부분이라는 걸 알게 되었다. 이를 위해 chatGPT를 활용하여 FCP와 FMP 차이와 영향을 끼칠수 있는 부분에 대해서 Google Analytics가 영향을 미치는지 물어보았고 이에 영향을 끼친다고 했다. 더 정확히 알기위해서 간단한 코드로 예시를 보여달라고 하였고 일반적인 Javascript 추적코드를 등록하는 코드를 보여주고 이에 대한 최적화 방법을 알려주었다.

하지만 기본적인 브라우저 로딩과 렌더링 원리는 위의처럼 HTML 파싱부분과 렌더링 부분은 별개의 단계로 나눠져있는데 spotify처럼 부분적인 렌더링과 script 실행은 별개라고 생각했고 이에 대해서 다시 질문을 하였고 해당 부분에 대해서 defer, async등을 사용하면 FMP 완료시점을 최적화 할수있따고 한다. 또한 렌더링 엔진마다 다르지만 일부 렌더링 엔진은 파싱과 렌더링 과정을 동시에 진행하게도 한다고한다. 음... 실제로 내 눈에 볼수있는 테스트가 없어서 좀 한계가 있는데 이부분은 추후에 사수나 물어볼수있는 사람이 있다면 물어보고싶다.

 

마지막 추측으로는 async를 사용함으로써 내용이 큰 js를 로드를 비동기적으로 처리하는동안 파싱이 완료되고 그래서 렌더링까지 진행하다가 큰파일의 js를 로드를 완료한시점에서 렌더링을 중지하고 js를 실행한다면 이러한 현상이 날수있을거같다.

 

 

테스트 결과 defer와 async의 또다른 차이점을 알았는데, defer를 사용하게되면 parsing이 끝나면 로드하고 실행되지만 DomContentLoaded 전에 로드되고 실행된다는 것이다 이것이 끝나야지만 DomContentLoaded가 진행된다는 것은 화면을 흰화면만 보여주다가 해당 script가 완료되어야지 렌더링하여 보여준다는 것이였다. 

위의 스크린샷을 보면 빨간박스에서 Network 탭의 test 라고 써있는 js파일을 다운로드후 로드하였고 아래 빨간박스를 보면  Evaluate Script가 실행되는데 이때동안 흰화면만 보이다가 스크립트 실행이 완료되면 DCL(DomContentLoaded) 부분에서 렌더링된 화면을 보여준다.

 

async의 경우는 DomContentLoaded 전에 진행되고 안되고에 대한 내용은 없고 단지 다운로드하여 로드가 완료되는 시점에서 실행한다라는 것이기 떄문에 DomContentLoaded가 진행된후에도 실행이 가능하다는 것이다. 

위에 처럼 network탭에서의 빨간박스로 해당 test.js를 다운로드하고 완료된 시점에서 Evaluate Script를 진행한다. 하지만 defer와는 달리 DomContentLoaded 전에 실행되야한다는 제약이 없기 때문에 스크린샷처럼 FC, FCP ~~ DCL 까지 진행되는 동안에 스크립트를 실행하였고 이때 빈화면이 아닌 이미 파싱되고 렌더링을 하여 보여주고 있고 스크립트가 완료된후의 L(Load, onLoad, 모든 리소스 다운,실행완료)시점에서 스크립트로 조작된 DOM을 보여준다.

 

파싱과 렌더링되는 화면이 비동기로 진행할때 어떠한 방식을 사용하는지에 따라 어떤 렌더링된 화면을 보여줄지는 다르다는 것이다.


마지막으로 좀더 다양한 시각이나 진지하게 생각해야할 부분이 ui/ux 부분이라고 느꼈다. 실제 서비스들에서 마음에 드는 ui/ux를 가진 사이트가 있는지 그리고 그 이유가 무엇인지에 대해서 생각해보고, 이미지가 좀더 뚜렷하게 보이는것과 조금이라도 흐리게 보이는 현상이 있다면 그 이유는 무엇인지에 대해서 좀더 공부해야할거 같다.
그전 서비스는 토스의 브랜딩을 모티브로 했기때문에 그러한 색이나 ui/ux를 가진다고 대답해서 토스라고 대답했지만 그것을 깊게 생각하거나 리서치하지 않았던 부분도 있었고, 프론트엔드가 어느정도로 ui/ux를 관여한다고 생각하는지도 해봐야할거같다.
 
ui/ux 부분을 고려하는건 디자이너 파트에 좀더 중점이 되면서 맡기는것을 리스펙이라고 생각했는데 이러한 질문들을 보면 디자이너나 퍼블리셔가 프론트엔드로 전향하거나 또는 디자이너가 원하는 내용물, 그리고 프론트엔드로서 사용자에게 좀더 편하고 제대로된 화면을 보여줘야한다는 관점이 필요하기 때문에 추후에 관련 서적을 볼 예정이다(나의 상황에서 우선순위는 살짝 뒤지만..)