📓 위치에 따른 렌더링

😫 반드시 알고 가자 이거 나중에 모르면 개고생한다.

웹 브라우저는 서버로부터 웹 페이지를 이루고 있는 여러 파일을 전달 받은 후 HTML 문서를 위에서부터 한 줄씩 읽으며(Parsing) 화면에 보여준다.

HTML에 적용하는 CSS, JS 같은 파일들은 해당 파일을 링크하는 코드가 읽힌 후 다운로드된다.

🏷️ head 태그에 JS가 있는 경우

<head>
    <title>Document</title>
    <script src="js/app.js"></script>
</head>
<body>
    <div></div>
</body>
  • 진행 방향
    • HTML 파싱 시작
    • HTML 파싱 stop
      • JS 호출
      • JS 실행
    • HTML 파싱 이어서
    • 파싱 끝
    • 페이지 Render

head 태그부터 차례대로 파싱하다가 script 태그를 만나면 해당 파일을 로드하기 위해 잠시 HTML 파싱 과정을 멈춘다.
JS 다운로드가 완료되면 해당 JS 파일을 실행한 후 이어서 나머지 HTML 파일을 파싱한다.
이러한 경우 JS의 파일 용량이 매우 크다면 웹 페이지를 화면에 나타내기까지 비교적 오랜 시간이 소요된다.


🏷️ head 태그가 body 태그 안에 있는 경우

<head>
    <title>Document</title>
</head>
<body>
    <div><div>
    <script src="js/app.js"></script>
</body>
  • 진행 방향
    • HTML 파싱 시작
    • 파싱 끝
      • JS 호출
      • JS 실행
    • 페이지 Render

HTML 파싱을 모두 마친 후 JS 파일을 다운로드한다. head에 있는 것보다 빠르게 페이지 화면에 나타낼 수 있다. 하지만 해당 웹 사이트의 주된 컨텐츠가 JS를 통해 생성되는 등 JS에 의존적인 경우 정상적인 웹 페이지를 화면에 나타내기까지 시간이 소요된다는 단점이 있다.






📓 스크립트 로드 전략 : HTML 파싱 (DOM 생성 중) JS 파일 로드 시점 조율

HTML에서 자바스크립트를 포함할때 어떻게 포함하는게 더 효율적인가??
결과 반환 시점 지정으로 Defer과 Async가 있다.

웹 페이지를 렌더할 때 브라우저는 HTML 파일 위에서 아래 순서로 읽으며 DOM Tree를 생성한다.
중간에 script 태그를 만나면 이것도 DOM요소 이기 때문에 해석하고 실행한다. 즉 해당 스프립트 파일을 모두 해석하기 전까지 나머지 HTML 렌더를 일시적으로 멈춘다.

문제점

  • 다운받은 JS파일을 모두 실행하는데 오랜 시간이 걸린다. (DOM 로드 지연)
  • 다운받은 JS 파일 실행 시 아래 HTML DOM 영역은 접근이 불가능하다.
  • 스크립트를 맨 아래로 내린다해도 HTML이 너무 크면 스크립트 실행 시기는 늦다.


🏷️ 비/동기

서버간 통신할 때의 방식으로 실시간성과 비실시간성.
동기 요청 : 작업이 완료될 때까지 하던 작업 멈추고 대기.
응답이 즉각적이어야 하는 경우

비동기 요청 : 작업이 완료되든말든 하던 작업 그대로 진행.
- 작업이 완료되면, 완료되었다는 응답을 받음 -> Callback이라고 함.
응답이 즉각적이지 않아도 되는 경우. (요청에 대한 응답이 절대 누락되어서는 안됨.)



🏷️ Defer(지연 스크립트)


병렬 : HTML 파싱 -> 스크립트 호출 -> HTML 파싱 후 실행
브라우저가 페이지의 파싱을 모두 끝낸 후에 스크립트가 실행된다.

예시)



🏷️ Async(비동기 스크립트)

병렬 : HTML 파싱 -> 스크립트 호출 + 바로 실행 -> 스크립트 호출이 끝나면 HTML 파싱 을 잠시 멈추고, 스크립트 실행
특정 코드가 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행!!
브라우저가 페이지를 파싱되는 동안에도 스크립트가 실행됨.




🏷️ module

외부 JS 파일들을 가져옴. 모듈에 export, import를 적용하면 다른 모듈을 불러와 함수를 호출할 수 있다고 함.






📓 head 태그 안 async 렌더링 시간

defer과 async에 대해 배워봤으니 실제 코드에서 어떻게 진행이 되는지 확인해보자.

<head>
    <title>Document</title>
    <script async src="js/app.js"></script>
</head>
<body>
    <div></div>
</body>
  • 진행 방향
    • HTML 파싱 시작
      • JS 호출
    • HTML 파싱 stop
      • JS 실행
    • HTML 파싱 이어서
    • 파싱 끝
    • 페이지 Render

HTML 파싱 도중 script 태그를 만나면 HTML 파싱과 JS 파일 다운로드를 병렬적으로 수행한다.
다운로드가 완료된 이후 파싱을 멈추고 해당 JS를 실행한다. 이어서 JS실행이 종료된 후 파싱을 재개한다.

파일 다운로드를 병렬적으로 수행하여 다운로드 시간을 절약할 수 있다. 하지만 JS 파일은 파싱이 완료되기 전에 실행되므로 아직 파싱되지 않는 DOM에 접근하는 경우 오류를 발생시킬 수 있다.
웹 페이지를 화면에 나타내기까지 시간이 걸리는 건 여전함.






📓 head 태그 안 defer 렌더링 시간

async처럼 병렬적으로 수행하지만 다운로드가 완료된 이후 JS 파일을 실행하지 않고 HTML파싱을 마친다.
그 다음 렌더링 준비가 완료된 이후 다운로드 받은 JS를 실행한다.

<head>
    <title>Document</title>
    <script defer src="js/app.js"></script>
</head>
<body>
    <div></div>
</body>
  • 진행 방향
    • HTML 파싱 시작
      • JS 호출
    • 파싱 끝
    • 페이지 Render
      • JS 실행

웹 페이지를 화면에 보여주고, 바로 JS를 실행시키므로 가장 효율적인 방법이다.






📓 조금 난이도를 높인 async와 defer 예제

🏷️ async의 경우

<head>
    <title>Document</title>
    <script async src="js/a.js"></script>
    <script async src="js/b.js"></script>
    <script async src="js/c.js"></script>
</head>
<body>
    <div></div>
</body>

다운로드는 병렬 수행, 다운로드가 완료된 파일을 바로 실행시키므로 먼저 다운로드 완료된 순으로 JS파일 실행

😵 근데 위와 같은 코드에서 JS 파일이 a->b->c 가 아닌 c->a->b 순으로 다운로드가 된다면 어떻게 될까??

  • 진행 방향
    • HTML 파싱 시작
      • a.js 호출
      • b.js 호출
      • c.js 호출
    • HTML 파싱 stop
      • c.js 실행
    • HTML 파싱 이어서
    • HTML 파싱 stop
      • a.js 실행
    • HTML 파싱 이어서
    • HTML 파싱 stop
      • b.js 실행
    • HTML 파싱 이어서
    • 파싱 끝
    • 페이지 Render

c.js가 a.js에 의존적인 경우 아직 a.js를 불러오지 못했으므로 오류 발생.

의존적?? :



🏷️ defer의 경우

  • 진행 방향

    • HTML 파싱 시작

      • a.js 호출
      • b.js 호출
      • c.js 호출
    • 파싱 끝

    • 페이지 Render

      • a.js 실행
      • b.js 실행
      • c.js 실행

HTML 파싱과 JS 다운로드가 병렬 수행, HTML 파싱을 완료한 이후에 JS를 실행.
그러면 HTML에 명시한 순서대로 코드 실행된다.


결론
HTML에서 JS를 적용할 때 head 태그 안에 defer 속성을 적용시키는게 가장 효율적이다.






참고 자료
🔗 https://choewy.tistory.com/146 - JavaScript 위치 및 async/defer 속성에 따른 HTML 렌더링 효율성

🔗 https://fe-j.tistory.com/entry/async-defer-javascript-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%88%9C%EC%84%9C-%EB%B0%94%EA%BF%94-%EC%84%B1%EB%8A%A5%EB%86%92%EC%9D%B4%EA%B8%B0 - async , defer - javascript 렌더링 순서 바꿔 성능높이기

🔗 https://www.youtube.com/watch?v=tJieVCgGzhs - 콘솔에 출력, script async 와 defer의 차이점 및 앞으로 자바스크립트 공부 방향

profile
일상의 인연에 감사하라. 기적은 의외로 가까운 곳에 있을지도 모른다.

0개의 댓글