개요
HTML과 JS를 쓰면서 DOM을 찾지 못한 에러를 많이 겪었다
개발자 도구로 봤을때는 해당 돔이 있었지만 에러가 나고 있었고 이를 해결하기 위한 script 속성 defer 와 async를 정리했다
속성이 없을때 예외상황
// render.js console.log('render1',document.getElementById("render1")) console.log('render2',document.getElementById("render2")) // render.html <body> <p id="render1"> render 1<p/> <script src="render.js"></script> <p id="render2"> render 2<p/>
브라우저
개발자 도구
위의 코드로 작성시 브라우저에 HTML콘텐츠는 모두 표기 되었으나 개발자도구에서 console.log로 보았을때 render2는 null로 표기되어 예상했던 결과와는 다르게 예외상황이 발생했다
defer 속성으로 예외처리
// render.js console.log('render1',document.getElementById("render1")) console.log('render2',document.getElementById("render2")) // render.html <body> <p id="render1"> render 1<p/> <script defer src="render.js"></script> <p id="render2"> render 2<p/>
브라우저
개발자 도구
“<script defer src=”… “ 위의 코드와 같이 script태그에 defer 속성만 주었는데 내가 원하는 결과와 같이 redner1 과 render2 두개의 엘리먼트가 리턴되었다
async 속성도 사용해보자
// render.js console.log('render1',document.getElementById("render1")) console.log('render2',document.getElementById("render2")) // render.html <body> <p id="render1"> render 1<p/> <script async src="render.js"></script> <p id="render2"> render 2<p/>
브라우저
개발자 도구
defer와 결과가 같다 .. 이지만 같을수도 있고 아닐수도 있다 그 이유는 3개의 로딩방식 차이에 있다
3가지 로드방식의 차이
속성이 없는경우 동작방식graph LR START --> START_RENDER[브라우저 랜더링 <p>render1</p>] START_RENDER --> STOP_RENDER[랜더링 중지] STOP_RENDER --> SCRIPT_DOWN[스크립트 다운로드] SCRIPT_DOWN --> SCRIPT_START[스크립트 실행] SCRIPT_START --> START_RENDER2[브라우저 랜더링 <p>render2</p>] --> END
위의 실행순서와 같이 속성이 없이 실행했던 첫번째 경우 render1만 랜더링 된후 스크립트가 실행이 되었다
defer 속성을 추가했을때 동작방식graph LR START --> START_RENDER[브라우저 랜더링 <p>render1</p>] START_RENDER --> DOWN_SCRIPT[스크립트 다운로드] DOWN_SCRIPT --> START_RENDER2 START_RENDER --> START_RENDER2[브라우저 랜더링 render2] START_RENDER2 --> START_SCRIPT[스크립트 실행] START_SCRIPT --> END
defer 속성을 추가하게 되면 모든 HTML코드 랜더링이 다 끝난후 랜더링 과정중 다운받았던 스크립트를 실행하기 떄문에 <p>render1</p>,<p>render2</p> 가 모두 생성되고 console.log 스크립트가 실행되기 때문에 모든 엘리먼트를 찾을 수 있었다
async 속성을 추가했을때 동작방식graph LR START --> START_RENDER[브라우저 랜더링 <p>render1</p>] START_RENDER --> DOWN_SCRIPT[스크립트 다운로드] DOWN_SCRIPT --> START_SCRIPT[스크립트 실행] START_RENDER --> START_RENDER2[브라우저 랜더링 render2] -->|stop render| START_SCRIPT START_RENDER2 --> END
async는 다운로드가 끝날때 까지 랜더링하다가 다운로드가 끝나면 스크립트를 실행하고 다시 남은 콘텐츠를 랜더링 하는 방식이다 그래서 <p>render2</p> 에 대해 실행순서를 보장하지 않는다다른 스크립트에 의존하지 않는 독립적인 스크립트로서 사용할때 async 키워드를 사용하면 최대한 빠르게 스크립트를 로드 할 수있다
정리
- defer 와 sync 속성을 명시해서 사용한다
- 현재 스크립트와 연관된 로직은 defer를 그렇지 않으면 빠른 실행을 위해 sync를 사용한다