[BB-JS] 2. HTML 속의 JavaScript

본 글은 자바스크립트 공부를 위해 프론트엔드 개발자를 위한 자바스크립트 프로그래밍를 정리한 글입니다.

들어가며

자바스크립트는 웹의 지배적인 언어인 HTML에 포함되어있는데, 넷스케이프는 자바스크립트에 대한 작업의 일환으로 자바스크립트가 다른 브라우저의 HTML 페이지 렌더링을 방해하지 않으면서 공존할 길을 모색했다고 한다.

브라우저 페이지 렌더링 방해요소와 관련된 내용은 Critical Rendering Path 최적화 도전기을 참고하자.

<script>요소

<script>요소는 자바스크립트를 HTML 페이지에 삽입하는 일차적인 방법이다. 초기에는 넷스케이프에서 구현했으며, 이후 공식 HTML 명세에 추가되었다.

속성

  • src
    • 옵션
    • 실행할 코드를 포함한 외부 파일의 위치를 지정
  • type
    • 옵션
    • language를 대체할 의도로 만들어짐
    • 스크립트의 언어의 콘텐츠 타입(마임 타입)을 지정
    • "text/javascript"을 습관적으로 또는 브라우저 호환성을 위해 표기
    • 이 속성은 생략했을 때 기본 값이 "text/javascript"이므로 생략해도 안전
  • defer
    • 옵션
    • 문서의 콘텐츠를 완전히 파싱하고 표시할 때까지 스크립트 실행을 지연해도 안전함을 나타냄
    • 외부 스크립트 파일을 불러올 때만 유효하거나, 일부 브라우저에서는 인라인 스크립트에서도 허용
  • async(HTML5)
    • 옵션
    • 자원을 즉시 내려받음
    • 다른 페이지 작업을 방해하지 않음
    • 외부 스크립트 파일을 불러올 때만 유효
  • charset
    • 옵션
    • src속성으로 명시한 코드의 문자셋을 지정
    • 브라우저는 대게 이 속성을 무시
  • language
    • 폐기
    • 코드 블록에서 사용한 스크립트 언어를 나타낼 목적
    • 브라우저는 대게 이 속성을 무시
    • 대신 type속성을 사용
<!-- HTML4 and (x)HTML -->
<script type="text/javascript" src="javascript.js">

<!-- HTML5 -->
<script src="javascript.js"></script>

<!-- ETC -->
<script>document.write("Hello, world");</script>
<script src="app.js"></script>
<script src="app.js" defer></script>
<script src="app.js" async></script>

Speed up Google Maps(and everything else) with async & defer

사용

Inline

<script>
function sayHi() {
  alert("Hi");
  alert("</script>"); // 사용할 수 없다.
  alert("<\/script>"); // 사용할 수 있다.
}
</script>
  • 위에서 부터 차례로 해석
  • 함수의 정의가 해석되어 인터프리터 환경 내부에 저장
  • 내부의 코드 전체를 평가하기 전에는 페이지의 나머지 콘텐츠를 불러오지 않고 표시도 하지 않음(렌더링 차단 요소)
  • "</script>"을 쓸 수 없음

External

<script src="example.js"></script>
  • 외부 파일에서 불러오려면 src속성을 사용
  • 파일에는 자바스크립트 코드만 들어가며, script태그를 사용할 수 없음
  • 외부 파일의 코드를 해석하는 동안에는 페이지 처리가 중단됨(파일을 내려받는 시간도 포함)
  • Inline과 External을 함께 사용한다면 Inline은 무시됨
  • 다른 도메인에 있는 자바스크립트 파일을 불러올 수 있음(img태그와 유사) - 악의적인 공격에 유의
  • 페이지에 나타난 순서대로 실행되나 deferasync속성이 있을 때는 예외

태그 위치

  • 전통적으로 head태그 안에 쓰는 것이 일반적(외부 파일에 대한 참조를 한곳에서 관리하기 위해서)
  • 자바스크립트는 렌더링 차단 요소이기 때문에 head태그에서 불러온다면 렌더링 차단이 발생
  • 최신 웹 애플리케이션에서는 일반적으로 body태그 안쪽의 페이지 콘텐츠 마지막 앞에 위치시켜, 페이지 렌더링을 모두 마친 다음 자바스크립트 코드를 처리

스크립트 처리 지연(defer)

<!DOCTYPE html>
<html>
  <head>
    <title>Example HTML Page</title>
    <script defer src="example1.js"></script>
    <script defer src="example2.js"></script>
  </head>
  <body>
    <!-- 페이지 콘텐츠 -->
  </body>
</html>
  • defer속성의 목적은 스크립트에서 페이지 구조를 바꾸지 않는다고 명시하는 것
  • 따라서 페이지 전체를 파싱한 후에 스크립트를 실행해도 상관이 없음
  • defer속성을 설정하면 브라우저는 해당 요소를 만나는 즉시 코드를 내려받지만 실행은 지연
  • 상단의 예제에서 head태그에 script를 설정하였지만, 이는 페이지 렌더링을 방해하지 않고 브라우저가 </html>을 만날 때 실행
  • HTML5 명세는 스크립트를 요소 순서대로 실행하도록 정의했으므로 스크립트는 선언된 순서되로 실행되며, 모든 스크립트는 DOMContentLoaded이벤트보다 먼저 실행
  • 현실적으로 스크립트가 항상 순서대로 실행된다거나 DOMContentLoaded이벤트보다 먼저 실행된다고 보장할 수 없기 때문에 스크립트를 하나만 쓰는 것이 최선
  • HTML5 명세는 인라인 스크립트의 defer속성을 무시(외부 스크립트에만 유효)
  • defer를 지원하지 않는 브라우저는 이 속성을 무시
  • 따라서 지연시킬 스크립트는 페이지 맨 마지막에 놓는 편이 최선

비동기 스크립트(async)

<!DOCTYPE html>
<html>
  <head>
    <title>Example HTML Page</title>
    <script async src="example1.js"></script>
    <script async src="example2.js"></script>
  </head>
  <body>
    <!-- 페이지 콘텐츠 -->
  </body>
</html>
  • async속성은 defer속성과 비슷한 방법으로 스크립트를 처리
  • 외부 스크립트에만 적용되며, 브라우저에게 파일을 즉시 내려받으라고 지시
  • async속성과 defer속성과의 차이점은 스크립트가 마크업 순서대로 실행된다는 보장이 없음
  • 비동기적으로 불러오는 파일 사이에 의존성이 있으면 안됨
  • async속성의 목적은 스크립트를 모두 내려받아 실행할 때까지 기다릴 필요 없이 페이지 렌더링을 시작해도 좋으며 앞선 스크립트 파일을 기다리지 않고 뒤에 있는 스크립트 파일을 내려받아 실행해도 좋다고 명시하는 것
  • DOM을 조작하는 스크립트는 비동기적으로 불어오지 않는 편이 최선
  • load이벤트 전에는 반드시 실행되지만 DOMContentLoaded이벤트보다 앞설 수도 있고 그 이후에 실행될 수도 있음
  • async를 지원하지 않는 브라우저는 이 속성을 무시

XHTML에서 스크립트 사용

<script type="text/javascript">
function compare(a, b) {
  if (a < b) {
    alert("A is less than B");
  } else if(a > b) {
    alert("A is greater than B");
  } else {
    alert("A is equal to B");
  }
}
</script>

HTML에는 스크립트의 콘텐츠를 파싱하는 특별한 규칙이 있지만 XHTML에는 해당 규칙이 적용되지 않는다. 따라서 상단의 예제에서 <기호를 태그의 시작으로 간주하며, <기호 다음에는 공백 문자가 올 수 없기 때문에 문법 에러가 발생한다.

<script type="text/javascript">
function compare(a, b) {
  if (a &lt; b) {
    alert("A is less than B");
  } else if(a > b) {
    alert("A is greater than B");
  } else {
    alert("A is equal to B");
  }
}
</script>

<기호를 HTML엔티티 &lt;로 바꿔줌으로써 해결할 수 있다.

<script type="text/javascript">
//<![CDATA[
function compare(a, b) {
  if (a < b) {
    alert("A is less than B");
  } else if(a > b) {
    alert("A is greater than B");
  } else {
    alert("A is equal to B");
  }
}
//]]>
</script>

코드 가독성을 확보하고자 한다면 CDATA 섹션을 사용하여 해당 콘텐츠가 있는 그대로의 텍스트이며 파싱하면 안된다고 명시하도록 한다. 단, 많은 브라우저가 아직 XHTML 비호환이며 CDATA 섹션을 지원하지 않으므로, CDATA 마크업 앞에 자바스크립트 주석 기호를 넣는 핵을 사용하여야 한다.

구식 문법

<script><!--
function sayhi() {
  alert("Hi!");
}
//--></script>
  • 자바스크립트를 지원하지 않는 브라우저에서 인라인 자바스크립트 코드를 숨길 수 있는 방법
  • 더 이상 필요하지 않으므로 사용을 말아야함

인라인 코드와 외부 파일

  • HTML파일에 자바스크립트를 직접 써도 되긴 하지만 일반적으로 가능한 한 자바스크립트는 외부 파일로 분리하는 방법을 모범 사레로 간주
  • 외부 파일을 사용함으로써 얻는 이점
    • 관리에 용이 : 자바스크립트를 한 곳에 모아두면, 마크업과 무관하게 코드를 수정할 수 있어 관리에 용이
    • 캐싱 : 브라우저는 특정한 설정에 따라 외부에서 연결된 자바스크립트 파일을 모두 캐시하여, 서로 다른 페이지에서 같은 파일을 사용하면 한 번만 내려받아 페이지를 불러오는 시간이 짧아짐
    • 미래에도 안전 : 자바스크립트를 외부 파일로 작성한다면 XHTML에서 CDATA 섹션이나 주석 편법을 사용하지 않아도 됨

문서 모드

문서 모드는 브라우저 상단에 있는 DTD(Document Type Defination)을 보고 쿼크모드, 표준모드 혹은 거의 표준 모드 중 사용된다.

문서 모드 종류

  • 쿼크 모드(Quirks mode) : 이전 세대 브라우저에 맞는 비표준적 기능을 사용
  • 표준 모드(Standard mode) : 표준에 가까운 기능을 사용
  • 거의 표준 모드(Almost standard mode) : 대부분 표준 모드의 기능을 지원하지만 표준 모드만큼 엄격하지 않음

DTD의 구성

DTD의 구성은 PUBLIC 문자열과 FPI(formal public identifier), FSI(formal system identifier)로 이루어져 있다.

FPI와 FSI 모두를 포함하는 doctype 선언 예

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  • FPI와 FSI가 동시에 기술되어 있을 경우 표준모드 사용
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

FPI만 선언되어있는 doctype 선언 예

  • FSI가 기술되어 있지 않은 경우 쿼크모드 사용되며, DTD를 적지 않은 경우에도 쿼크 모드 사용

HTML5 일때 표준모드 사용

<!DOCTYPE html>

DTD Switching에 따른 웹 브라우저별 렌더링 모드 전환 표(참조문서)

  • Q : 쿼크모드(Quirks mode)
  • S : 표준모드(Standard mode)
  • A : 거의표준모드(Almost Standard mode)
문서 DTD IE6,7 FF2 OP9 SF2
None DTD가 없는 경우 Q Q Q Q
HTML 4.01 아래 참조 Q Q Q Q
HTML 4.01 아래 참조 A A A A
HTML 4.01 아래 참조 A S S S
HTML 4.01 아래 참조 A S S S
XHTML 1.0 아래 참조 A A A A
XHTML 1.0 아래 참조 A S S S
HTML 4.01
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
HTML 4.01
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
HTML 4.01
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
HTML 4.01
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
XHTML 1.0
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
XHTML 1.0
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  • 쿼크 모드라고 해서 모든 브라우저가 동일하게 렌더링하는 것은 아니며, 브라우저마다 쿼크 모드일 때 호환시키려고 하는 요소가 다르다.

Rendering Mode에 따른 주요 이슈별 표준 지원 현황(참조문서)

  • S : W3C Standard
  • N : None Standard
Browser IE6 IE6 IE7 IE7 FF2 FF2 OP9 OP9 SF2 SF2
Mode Quirks Strict Quirks Strict Quirks Strict Quirks Strict Quirks Strict
width & padding, border
> width값에 padding, border값이 포함되지 않는것이 표준
N S N S S S S S S S
margin:0 auto
width값이 적용된 block-lebel 요소는 가운데로 정렬되는 것이 표준
N S N S S S S S S S
.test:hover
가상선택자는 모든 선택자(type selector, id selector, class selector)와 조합될 수 있음
N N N S N S S S S S

<noscript>요소

  • 자바스크립트를 지원하지 않는 초기 브라우저에서 대한 단계적 후퇴에 대한 달성을 위해 제공
  • 자바스크립트를 지원하지 않을 때 대체 콘텐츠를 제공하기 위해 만들어짐
  • noscript태그는 script태그를 제외한 모든 HTML요소를 포함
  • noscript가 표시되는 상황
    • 브라우저가 스크립트를 지원하지 않는 경우
    • 브라우저의 스크립트 지원이 꺼져 있을 때
  • 적절한 낮춤 대 점진적 향상
<!DOCTYPE html>
<html>
  <head>
    <title>Example HTML Page</title>
    <script defer src="example1.js"></script>
    <script defer src="example2.js"></script>
  </head>
  <body>
    <noscript>
      <p>This page requires a JavaScript-enabled browser.</p>
    </noscript>
  </body>
</html>

SmileCat

SmileCat
How do you define yourself?

[Openlayers] Render Event 정리

## 이벤트### [Map](http://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html)| event | module | note || :--: | -- | -- || [postcompose](...… Continue reading