왜 css <link>는 <head>내에 선언하고, js <script>는 <body> 직전에 위치시키나요?
- <head>
안에 <link>
를 넣는 이유
<link>
를 <head>
안에 넣는 것은 최적화된 웹사이트를 구출할 때 적절한 스펙이다.
페이지가 처음 로드되면, HTML과 CSS가 동시에 파싱되는데, HTML은 DOM(Document Object Model)을 만들고, CSS는 CSSOM (CSS Object Model) 을 만든다.
2가지 모두 웹 사이트에서 시각적인 부분을 만드는데 필요하므로, 빠른 first meaningful paint를 할 수 있게 해준다.
(first meaningful paint은 사이트의 성능 지표중 하나)
문서 최하단에 stylescheet를 두는 것은 이에 반하는 행동이다.
또한, 점진적인 렌더링을 하는 경우 몇몇 브라우저는 스타일이 변경되면 페이지 요소를 다시 그리는 것을 막기위해 렌더링을 차단하는데,
문서 최하단에 stylescheet가 있다면 사용자는 빈화면을 보게될 것이다.
- 직전에 <script>
를 넣는 이유
<script>
는 다운로드되고 실행되는 동안 html 파싱을 차단한다.
스크립트를 맨 아래에 두면 html를 먼저 파싱하여 사용자에게 노출시킬 수 있다.
스크립트에 document.write()
가 있을 때에는 <script>
를 아래쪽에 두는 것이 예외적일 수 있으나, 요즘은 document.write()
를 사용하지 않는 것이 좋다.
또한, <script>
를 하단에 위치 시키면, 브라우저가 전체 문서 파싱완료될 때 까지 스크립트 다운로드를 할 수 없다.
이를 통해 DOM을 핸들링하는 코드가 오류를 발생시키지 않도록 해준다.
*<script>
를 <head>
에 넣어야 하는 경우엔 defer를 사용하자.
+ defer란 무엇인가?
<script>
태그의 defer 속성은, 페이지가 모두 로드된 후에 해당 외부 스크립트가 실행됨을 명시한다.
defer 속성은 불리언(boolean) 속성으로 명시하지 않으면 false 값을 가지게 되고, 명시하면 true 값을 가지게 된다.
이 속성은 <script>
요소가 외부 스크립트를 참조하는 경우에만 사용할 수 있으므로, src 속성이 명시된 경우에만 사용할 수 있다.
참조된 외부 스크립트 파일을 다음과 같이 여러 가지 방법으로 실행시킬 수 있다.
- async 속성이 명시된 경우 : 브라우저가 페이지를 파싱되는 동안에도 스크립트가 실행됨.
- async 속성은 명시되어 있지 않고 defer 속성만 명시된 경우 : 브라우저가 페이지의 파싱을 모두 끝내면 스크립트가 실행됨.
- async 속성과 defer 속성이 모두 명시되어 있지 않은 경우 : 브라우저가 페이지를 파싱하기 전에 스크립트를 가져와 바로 실행시킴.
+ 왜 document.write
를 사용하지 않는 것이 좋은가?
document.write는 페이지가 로드되는 동안에 만 작동한다. 페이지 로드가 완료된 후에 호출하면 전체 페이지를 덮어쓴다.
즉, 인라인 스크립트 블록에서만 호출해야 하는데 그러면 브라우저가 다음 페이지의 일부를 처리하지 못한다. 쓰기 블록이 완료될 때까지 스크립트와 이미지는 다운로드되지 않는다. 이벤트 핸들러 적용 시에는 innerHTML을 사용하는 것이 좋다.