들어가기 전에
웹 클라이언트 코드는 브라우저 안에서 동작합니다.
HTML, CSS, JavaScript의 실제 소스코드를 보면서 웹페이지 소스의 구성을 살펴봅니다.
학습 목표
- HTML 요청 이후 브라우저에서 해석되는 웹페이지(HTML) 안의 내용구성과 소스코드를 어떻게 위치시키면
될지 이해한다.
핵심 개념
- Browser 안에서 동작할 수 있는 HTML, CSS, JavaScript의 코드구현 방법
학습하기
들어가기 전에
웹 클라이언트 코드는 브라우저 안에서 동작합니다.
HTML, CSS, JavaScript의 실제 소스코드를 보면서 웹페이지 소스의 구성을 살펴봅니다.
학습 목표
핵심 개념
학습하기
HTML 문서구조
뜯어보자 웹사이트!
알게 된 몇 가지 특징
<tag class="title">안녕하세요</tag>
참고 자료
http://www.jsbin.com
https://www.edwith.org
comment
현업자 입장에서 HTML안에서
`CSS, Javascript는 왜 곳곳이 존재하는가?`에 대해 생각해보았습니다. 재미삼아 읽어주시면 감사하겠습니다^_^
실제 개발에서는 보통 외부 파일을 import 하는 형식으로 사용합니다. 하지만 불가피하게 html 코드 안에서 css, javascript가 선언되어야 할 때가 있죠.
1) 하나의 페이지는 분리된 페이지들의 결합.
거의 모든 프로젝트가 파일을 나눠 임포트하여 개발합니다. 예를 들어, header 부분, side 부분, content 부분, footer 부분 등으로 나눌수 있죠. 이러한 파트들을 코드로 나누어 개발합니다. 해당 페이지가 각각 css, javascript를 사용하고 있습니다. 실제 아마존 사이트에서 이러한 구문들이 곳곳이 나타나는 이유는 여러개의 파일들이 압축되었기 때문이죠. 우리가 보고 있는 amazon 웹 사이트는 몇개의 파일로 이루어져 있을지 궁금하네요.
2) legacy 코드
사실상 대규모 프로젝트 오래동안 운영되어 유지보수되는 경우가 많습니다. 소규모 프로젝트도 사실 저런 코드를 리팩토링 하기 어렵죠. 특히나 예전에 작성된 코드의 경우, 파일로 분리하여 규칙을 정해두고 깔끔한 코드를 작성했을 경우가 적습니다. 이런 프로젝트의 경우, 실제 운영되고 있는 코드는 수정에 굉장히 예민합니다. 잘돌아가는 서버를 하나 수정해서 죽이면 안되기 때문이죠. 즉, 리팩토링은 꿈도 꾸기 힘들단 소리입니다. 아마도 아마존도 오랫동안 운영되어 왔기 때문에 legacy 코드를 제거하지 못했을 가능성이 크리라 예상합니다.
3) 분석하기 어렵게하기 위한 노림수
이건 웃자고 하는 소리기도 한데 제추측상 입니다.^^ 웹 사이트는 보시다 시피 사용자가 쉽게 접근할 수 있습니다. 웹 개발자들은 이러한 공격을 염두에 두고 개발해야 합니다. 이러한 사이트들을 분석하여 공격에 이용하는 나쁜 해커들이 있기 때문이죠.
결론적으로 실제 개발에서는 저렇게 소스코드가 중구난방으로 위치하지 않습니다. 오랫동안 개발해온 서비스라면 가능한 이야기일지 몰라도(실제로 JSP 코드안에 html, css, java 소스를 박아놓은 코드를 봤습니다.^^;) 신규 서비스라면 더더욱이요.
실습 내용을 공유합니다.
1. 크롬/파이어폭스 브라우저에서 albert 명령어 위치를 body 영역 앞 뒤로 옮겨가며 결과 확인
크롬에서는 </body> 뒤에 자바스크립트를 두어도 내용이 표시되기 전에 albert()가 실행되고, 파이어폭스 브라우저에서는 내용이 표시된 이후 albert()가 실행됩니다. 이유가 궁금해 검색해봤습니다.
=> albert()(또는 비슷한 confirm(), prompt() 등)은 rendering을 검사하기에 부적절한 도구입니다. 브라우저들은 점점 albert가 렌더링을 막지 못하도록 하고 있습니다. 파이어폭스와 크롬은 비슷한 방향성을 가졌으나 아직 차이점이 있습니다. 보자하니 파이어폭스는 이어서 렌더링하도록 허용하고, 크롬은 이 경우에 허용하지 않습니다.
자바 스크립트 태그가 렌더링을 막는지 확인할 때 1990년대부터 사용된 오래된 방법은 좋지 않습니다. 제가 쓰는 방법은 로드하는데 시간이 오래 걸리도록 지연하는 것입니다.
출처: https://stackoverflow.com/questions/59468048/render-blocking-javascript-at-end-of-body-tag-firefox-renders-some-visual-cont
2. 렌더링을 위한 브라우저의 parsing 스레드를 확실히 블로킹(동기적 실행)하기 위해 while문으로 시간지연하는 자바스크립트 코드를 사용해 다시 실험했습니다. (코드 출처: https://multifrontgarden.tistory.com/157) 참고로 chrome, firefox 모두 설치 기본값입니다.
=> 결과
2-1. 화면이 먼저 출력되고 자바 스크립트가 실행되는 경우
- </body> 뒤에 위치 / external script / 크롬: 화면 출력된 후 자바 스크립트 실행
2-2. 스크립트가 먼저 실행되고 화면이 출력되는 경우
- <body> 앞에 위치했다면 전부
- </body> 뒤에 위치 / inline script / 크롬
- </body> 뒤에 위치 / inline script / 파이어폭스
- </body> 뒤에 위치 / external script / 파이어폭스
단순히 위치만 뒤로 놓는다고 처리가 되는 게 아니었습니다. 브라우저에 따라 실행 결과 차이가 있었으며, 스크립트를 내부/외부에 정의하는지도 영향을 미쳤습니다. inline/external script 차이가 궁금하여 스택오버플로우에 직접 질문했습니다.
https://stackoverflow.com/questions/60999653/why-doesnt-parsing-html-stop-when-i-use-an-inline-script-tag
=> 기본적으로 모든 html 문서가 파싱되고 inline javascript가 실행된 이후 first paint(rendering)을 시작합니다. 그런데 외부 js 파일을 가져오는 external script 경우, 스크립트 파일을 download/fetch 하는 동안 렌더링이 허용됩니다. 그 기준에서 여태껏 파싱해온 것을 렌더링하고나서 스크립트 파일 실행, 다시 파싱을 재개합니다. (그럼에도 파이어폭스에서 안되는 건 브라우저의 차이 같습니다)
=> 아마 https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/ 여기 사이트에서 말한 내용이 위의 설명을 말하는 것 같습니다 ... 렌더링 엔진은 좀 더 나은 사용자 경험을 위해 가능하면 빠르게 내용을 표시하는데 모든 HTML을 파싱할 때까지 기다리지 않고 배치와 그리기 과정을 시작한다. 네트워크로부터 나머지 내용이 전송되기를 기다리는 동시에 받은 내용의 일부를 먼저 화면에 표시하는 것이다. ...
=> 렌더링을 지연시키는 코드라면 가능한 external script + defet/async 옵션을 넣는 게 좋고, 코드 크기가 작으며 렌더링 전에 꼭 실행되어야 하면 inline script로 하는 게 좋은 것 같습니다.
다른 참고 링크
- https://stackoverflow.com/questions/59468048/render-blocking-javascript-at-end-of-body-tag-firefox-renders-some-visual-cont
- https://stackoverflow.com/questions/18292974/why-do-inline-scripts-block-rendering-when-put-at-the-bottom-of-a-page
- https://developers.google.com/web/tools/lighthouse/audits/blocking-resources