관련지식
html, javascript, css

이 내용은 브라우저의 렌더링 절차와 관련된 내용입니다. 따라서 직접 코딩이 필요한 소스는 없으니 편한 마음으로 읽어보시면 될것 같습니다.

먼저 아래 소스를 보겠습니다.

  1. <html>
  2. <head>
  3. <link type="text/css" rel="stylesheet" href="aaa.css" />
  4. <script src="https://code.jquery.com/jquery-3.3.1.min.js" ></script>
  5. <script>
  6. //script 내용
  7. </script>
  8. </head>
  9. <body>
  10. ...
  11. ...
  12. <link type="text/css" rel="stylesheet" href="aaa.css" />
  13. <script src="https://code.jquery.com/jquery-3.3.1.min.js" ></script>
  14. <script>
  15. //script 내용
  16. </script>
  17. </body>
  18. </html>

특별한 내용이 없는 간단한 형태의 HTML 템플릿입니다. 그런데 ‘aaa.css’ 파일과 ‘jquery-3.3.1.min.js’ 파일이 <head> 태그와 <body> 태그의 하단에 각각 존재 합니다. 물론 동일한 파일을 두군데서 호출할 필요는 없으니 한쪽의 소스는 지워야 할 것입니다. 어디를 지우고 어디를 남겨야 할까요?

CSS 작성은 어디에?

이것을 제대로 이해하기 위해서는 브라우저 동작방식에 대해 번역된 https://d2.naver.com/helloworld/59361 글을 먼저 읽어보시는 것이 좋습니다. 작성된지 몇년 된 글이지만 브라우저의 큰 동작방식을 이해하기엔 부족함이 없습니다. 양이 많고 후반부 내용은 특히 복잡하므로 ‘동작 과정 예’ 까지만 보시고 그 이후 내용은 필요에 따라 보시기 바랍니다.

간단하게 정리하면 브라우저에 HTML파서와 CSS파서가 있는데 각각 DOM과 스타일 규칙을 분석하면서 분석이 된 내용끼리 결합한다는 내용입니다.

아래 예를 보겠습니다.

  1. <html>
  2. <head>
  3. <style>
  4. div {background-color:#880;}
  5. div.content {font-size:14px;}
  6. </style>
  7. </head>
  8. <body>
  9. <div class="content">
  10. <p>
  11. 이 글씨는 폰트 크기가 몇일까요?
  12. </p>
  13. </div>
  14. <style>
  15. p {font-size:12px;}
  16. </style>
  17. </body>
  18. </html>

파서는 HTML 문서의 위에서 아래로 분석을 합니다. <html> 태그와 <head><style> 태그를 지나며 CSS파서가 본격적으로 분석을 시작합니다. 먼저 ‘div’ 선택자에 대한 스타일 규칙을 분석하고 다음으로 ‘div.content’ 선택자에 대한 분석을 합니다.

CSS파서가 분석을 하는동안 다른 작업이 멈춰있는 것은 아닙니다. <style> 태그에 대한 분석을 CSS파서에게 던져놓고 HTML파서는 계속 일을 하게 됩니다. 따라서 HTML파서가 <div> 태그를 분석할 시점에 <style> 태그의 분석이 끝났을 거라는 보장은 없습니다. 모든 분석이 끝났을수도 있고 ‘div’ 스타일 분석을 막 시작했을수도 있습니다.

만약 HTML파서가 <p> 태그를 분석할때까지도 스타일 분석이 되지 않은 상태라면 흰색 배경을 가진 보이지 않는 박스 안에 ‘이 글씨는 폰트 크기가 몇일까요?’ 문장이 보일것 입니다. 그 이후에 스타일 분석이 끝나면 바로 디자인이 적용될 것입니다. 폰트는 14px이 적용되겠죠.

스타일 분석 시작전)

스타일 분석 후)

하지만 보통 이렇게 되진 않습니다. 스타일 태그의 파싱이 먼저 시작되었고 내용도 매우 간단하기 때문에 화면에 렌더링 될 시점엔 ‘div’에 관한 스타일 분석은 이미 끝나있을 것입니다. 그러나 하단에 있는 스타일 태그는 상황이 좀 다릅니다. HTML 본문의 가장 밑에 있기 때문에 모든 DOM에 대한 렌더링 후 스타일 분석을 하게 되고 렌더링중인/렌더링된 DOM요소에 스타일을 다시 입히게 될 것입니다. 즉 가장 늦게 동작하게 됩니다. 만약 HTML 문서가 10만줄은 되는 긴 내용이고, 브라우저 엔진이 느리다면 폰트크기가 14px->12px로 바뀌는 것을 육안으로 확인할 수도 있을것 같네요.

css는 무조건 HTML의 상단에 정의 하세요! 그래야만 HTML DOM 요소가 화면에 보일때 원하는 디자인이 적용된 형태로 나타날 것입니다.

스크립트 작성은 어디에?

사실 CSS도 그렇지만 Javascript 작성이 상단 혹은 하단에만 고정하여 작성하는 경우는 많지 않습니다. GNB, LNB, Footer, Content 등으로 역할을 나누어 페이지를 개발하여 하나로 머지된 화면을 보일때도 그렇고 SPA로 개발할때도 그렇고 필요한 화면에서 스크립트를 개발하다보면 최종 결과물에는 상단, 하단, 중간에도 스크립트 코드가 보일수 있습니다. 하지만 일관된 규칙은 있어야겠죠. 스크립트 작성은 어디에 해야 할까요?

만약 텍스트 필드에 ‘JQuery’를 이용하여 값을 세팅하려고 할 경우 아래와 같이 코딩할 수 있습니다.

  1. $("input[type='text']").val("세팅하고싶은값1");

위 소스를 HTML의 어디에 추가할까요?

  1. <html>
  2. <head>
  3. <script>
  4. $("input[type='text']").val("세팅하고싶은값1");
  5. $(document).ready(function() {
  6. $("input[type='text']").val("세팅하고싶은값2");
  7. });
  8. </script>
  9. </head>
  10. <body>
  11. ...
  12. ...
  13. <script>
  14. $("input[type='text']").val("세팅하고싶은값3");
  15. </script>
  16. </body>
  17. </html>

CSS와 마찬가지로 스크립트 실행 또한 위에서 아래로 차례대로 실행됩니다. 따라서 실행 순서는 ‘세팅하고싶은값1’ -> ‘세팅하고싶은값3’ -> ‘세팅하고싶은값2’ 순서로 합니다.(편의상 1,3,2로 부르겠습니다.)

1이 제일 빨리 실행되는 위치니 거기에 작성하는 것이 좋을까요? 아닙니다. <body>에 있는 DOM 요소가 파싱되기 전이기 때문에 스크립트는 실행되지만 값을 세팅할 수 없습니다.

2번은 어떨까요? 두번째 순서로 실행하지만 그 안의 콜백함수는 실제로 이벤트가 발생되는 시점인 모든 document가 파싱된 후에 실행됩니다. 따라서 실행 속도로만 봤을때는 가장 느립니다.

3번은 모든 DOM 요소가 파싱된 후에 실행되는 코드입니다. DOM을 제어하는 코드를 가장 빠르게 실행할수 있는 위치입니다.

자 그러면 3번 위치에 스크립트를 작성하는것이 제일 좋을까요? 결정을 내리기 전에 링크 https://jsfiddle.net/pivotseven/cqgvmxa8/ 을 한번 실행해 보는것이 좋습니다. 이 링크의 스크립트에는 3개의 alert이 있습니다. 위 샘플의 1,2,3의 위치에 ‘first’, ‘document ready’, ‘last’ 문자열을 찍는 alert입니다. 각 alert이 출력 되었을때 jsfiddle 우측의 실행화면을 주목하셔야 합니다. ‘first’가 출력 되었을때는 실행화면이 아무것도 보이지 않고, ‘last’ 가 출력 되었을때는 실행화면이 보이지만 디자인이 덜 입혀진 상태로 보입니다. ‘document ready’ 가 출력된 시점에선 모든 디자인이 적용되어 있네요.

자바스크립트는 싱글스레드로 동작합니다. 그 뜻은 한가지 일을 하고 있을때 모든 작업이 block 된다는 것입니다. 만약 3번 위치에 많은 코드가 들어있고 코드중 일부의 속도가 느리다면 어떨까요? 최초 화면 로딩이 느려 사용자에게 답답함을 유발할 것입니다. 따라서 스크립트는 고정된 위치가 아니라 상황에 맞춰 적절히 분배해야 합니다.

DOM 요소를 접근할 일이 없고 가장 빠르게 실행하고 싶은 경우 - 1번 위치
가장 빠르게 DOM 접근 하고 싶은 경우 - 3번 위치
화면을 block 시킬 요소가 있어서 화면 로딩에 영향없이 실행하고 싶은경우 - 2번 위치

이상입니다.