인터넷정보

Internet Explorer에서 Mozilla로 애플리케이션 마이그레이션 하기

알 수 없는 사용자 2007. 10. 11. 16:41

Internet Explorer에서 Mozilla로 애플리케이션 마이그레이션 하기

Internet Explorer 기반 웹 애플리케이션을 Mozilla 기반 브라우저에서 작동시키는 방법

developerWorks
문서 옵션
<FORM name=email action=https://www.ibm.com/developerworks/secure/email-it.jsp> <SCRIPT language=JavaScript type=text/javascript> </SCRIPT> </FORM>
이 페이지를 이메일로 보내기

이 페이지를 이메일로 보내기

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.


제안 및 의견
피드백

난이도 : 초급

Doron Rosenberg, 소프트웨어 엔지니어, IBM

2005 년 7 월 26 일

Internet Explorer 기반 웹 애플리케이션을 Mozilla 로 접근했을 때 어려움을 느껴본 적이 있었는가? 이 글에서 오픈 소스 Mozilla 기반 브라우저로 애플리케이션을 마이그레이션 할 때 발생하는 일반적인 문제들을 다루고자 한다. 우선 기본적인 크로스 브라우저 개발 기술을 배우고 나서 Mozilla와 Internet Explorer의 차이를 극복하는 전략을 모색한다.

Netscape가 Mozilla 브라우저를 시작했을 때, W3C 표준을 지원하겠다는 의식적인 결정을 내렸다. 결과적으로, Mozilla는 Netscape Navigator 4.x와 Microsoft Internet Explorer 레거시 코드와 완벽하게 하위 호환이 되지 않는다. 예를 들어, Mozilla는 <layer> 태그를 지원하지 않는다. Internet Exploere 4 와 같이 W3C 표준 이전에 만들어진 브라우저들은 표준에서 지원하지 않는 많은 쿼크(Quirk)들을 가지고 있다. 본 기사에서는 Internet Explorer 와 다른 레가시 브라우저에 대해 강력한 HTML 하위호환성을 제공하는 Mozilla의 쿼크 모드에 대해 설명할 예정이다.

또한 XMLHttpRequest와 리치 텍스트 편집 같은 비표준 기술에 대해서도 설명하겠다. W3C 비슷한 것도 그 당시 존재하지 않았기 때문에 Mozilla가 지원하게 되었다.

일반 크로스-브라우저 코딩 팁

웹 표준이 존재하더라도 브라우저 마다 다르게 작동한다. (사실, 같은 브라우저도 플랫폼에 따라 다르게 작동한다.) Internet Explorer 같은 많은 브라우저들 역시 W3C 이전의 API를 지원하고, W3C 표준 API 에 대한 지원까지 결코 확장하지 않았다.

Mozilla와 Internet Explorer의 차이점을 설명하기에 앞서, 나중에 새로운 브라우저 지원을 추가할 수 있도록 웹 애플리케이션을 확장하는 몇 가지 기본적인 방법을 설명하겠다.

브라우저마다 같은 기능에 다른 API를 사용하기 때문에 브라우저들을 차별화 시키는 if() else() 블록을 종종 보았을 것이다. 다음 코드는 Internet Explorer의 블록이다.

 
. . . 

var elm; 

if (ns4) 
  elm = document.layers["myID"]; 
else if (ie4) 
  elm = document.all["myID"]; 
 

 

위 코드는 확장할 수 없기 때문에 새로운 브라우저를 지원하려면 웹 애플리케이션의 처음부터 끝까지 이러한 블록을 업데이트 해야 한다.

코드를 변경하지 않고 새로운 브라우저를 지원하는 가장 쉬운 방법은 기능을 추상화 하는 것이다. 즉, 여러개의 if() else() 블록을 사용하는 대신, 공통적인 작업들을 모아 각각을 함수형태로 만들어 추상화함으로써 효율을 향상시킬 수 있다. 이러한 방법은 단순히 코드를 읽기 쉽게 만들 뿐만 아니라, 새로운 브라우저에 대한 지원도 간단히 추가할 수 있다.

 
var elm = getElmById("myID"); 

function getElmById(aID){ 
  var element = null; 

  if (isMozilla || isIE5) 
    element = document.getElementById(aID) 
  else if (isNetscape4) 
    element = document.layers[aID] 
  else if (isIE4) 
    element = document.all[aID]; 

  return element; 
} 

위 코드는 여전히 브라우저 스니핑(browser sniffing) 이나 사용자가 어떤 브라우저를 사용하고 있는지 탐지해야 하는 이슈가 있다. 브라우저 스니핑은 일반적으로 사용자에이전트를 이용하여 아래와 같은 형태로 수행된다.

 
  Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016 
  

사용자 에이전트를 사용하여 브라우저를 스니핑 하면, 사용중인 브라우저에 대한 상세한 정보가 나온다. 새로운 브라우저 버전이 나타날 때 사용자 에이전트가 실수할 수 있는 코드, 코드 변경이 필요한 것이 무엇인지를 알 수 있다.

브라우저 유형이 문제가 되지 않는다면(아마도 웹 애플리케이션에 접근을 못하도록 비 지원 브라우저를 막았을 수도 있다.) 브라우저 기능에 따라 스니핑 하는 것이 더 낫다. 아래와 같이 하는 것 보다는 JavaScript에 필요한 기능을 테스트하여 이를 수행하는 것이 더 낫다.

 
 
   if (isMozilla || isIE5) 
 

다음과 같이 하라.

 
 
   if (document.getElementById) 
 

이렇게 하면 그 메소드를 지원하는 다른 브라우저(Opera 또는 Safari)가 변경 없이도 작동할 수 있다.

하지만 사용자 에이전트 스니핑은 정확성이 중요한 문제가 될 때 사용하는 것이 좋다. 브라우저가 웹 애플리케이션의 버전 요구 사항들을 충족시키는지, 버그를 해결하는지 등을 확인할 때 사용하는 것이 좋다.

JavaScript는 인라인 조건문도 허용한다. 이것으로 코드 읽기가 쉬워진다.

 
 
   var foo = (condition) ? conditionIsTrue : conditionIsFalse; 
 

엘리먼트를 검색하려면 다음을 사용하라.

 
   function getElement(aID){ 
     return (document.getElementById) ? document.getElementById(aID)
                                      : document.all[aID];
   } 






Mozilla와 Internet Explorer의 차이점

우선, HTML이 Mozilla와 Internet Explorer 사이에서 작동하는 방법의 차이를 설명하겠다.

툴팁(Tooltips)

레거시 브라우저들은 툴팁을 HTML에 도입했다. 이들을 링크상에 보여주고 툴팁의 콘텐트로서 alt 애트리뷰트 값을 사용한다. 최신 W3C HTML 스팩은 title 애트리뷰트를 만들었는데, 여기에는 링크에 대한 상세한 설명이 포함될 것이다. 요즘의 브라우저들은 title 애트리뷰트를 사용하여 툴팁을 디스플레이 하고, Mozilla만이 alt 애트리뷰트가 아닌 그러한 애트리뷰트를 이용하여 툴팁을 보여준다.

엔터티(Entities)

HTML 마크업은 여러 엔터티들을 포함할 수 있다. 이는 W3 표준 위원회가 정의한 것이다. 숫자 레퍼런스 또는 문자 레퍼런스를 통해 엔터티들을 참조할 수 있다. 예를 들어,  로 #160 이라는 빈 공간 문자를 참조할 수 있다. 또는 이것과 비슷한 문자인  로도 참조할 수 있다.

Internet Explorer 같은 몇몇 브라우저들은 끝에 있는 세미 콜론(;)을 정상 텍스트로 대체하여 엔터티를 사용할 수 있도록 한다.

 
 
     Foo 
      Foo 
 

Mozilla는 W3C 스팩에 반하더라도 위   를 공백으로 렌더링한다. 이 브라우저는   뒤에 더 많은 문자가 붙으면,  를 파싱하지 않는다.

 
 
   12345 
 

이 코드는 Mozilla에서 작동하지 않는다. W3 표준에 부합하지 않기 때문이다. 언제나 정확한 형식 ( )을 사용하여 브라우저 불일치 문제를 피한다.






DOM의 다른 점

Document Object Model (DOM)은 문서 엘리먼트를 포함하고 있는 트리 구조이다. W3C가 표준화 한 JavaScript API를 통해 이를 조작할 수 있다. 하지만 W3C 표준화 이전에 Netscape 4와 Internet Explorer 4는 비슷한 API를 구현했다. Mozilla는 W3C 표준으로 할 수 없다면 기존 API만 구현한다.

접근 엘리먼트

크로스 브라우저 방식을 따르는 엘리먼트 레퍼런스를 검색하려면 Internet Explorer 5.5+와 Mozilla에서 작동하고, DOM Level 1 스팩의 일부인 document.getElementById(aID)를 사용한다.

Mozilla는 document.elementName이나 Internet Explorer 방식(global namespace polluting) 인 엘리먼트의 이름을 통해 엘리먼트로 접근하는 것을 지원하지 않는다. 또한 Netscape 4 document.layers 메소드와 Internet Explorer의 document.all도 지원하지 않는다. document.getElementById 를 통해 한 개의 엘리먼트를 검색할 수 있고, document.layersdocument.all 을 사용하여 모든 <div> 엘리먼트 같은 특정 태그 이름을 가진 모든 문서 엘리먼트 리스트를 얻을 수 있다.

W3C DOM Level 1 메소드는 getElementsByTagName()을 통해 같은 태그 이름으로 모든 엘리먼트들을 참조한다. 이 메소드는 JavaScript에 어레이를 리턴하고, document 엘리먼트나 다른 노드에 대해서도 호출될 수 있다. DOM 트리에 있는 모든 엘리먼트들의 어레이를 받으려면, getElementsByTagName(*)을 사용한다.

표 1에 나오는 DOM Level 1 메소드들은 한 엘리먼트를 특정 위치로 옮기고, 이것의 가시성(메뉴, 애니메이션)을 토글링하는데 사용된다. Netscape 4는 <layer> 태그를 사용했다. 이것은 어디에나 놓일 수 있는 HTML 엘리먼트로서 Mozilla는 지원하지 않는 것이다. Mozilla에서 <div> 태그를 사용하여 어떤 엘리먼트 라도 배치할 수 있다. 이것은 Internet Explorer 역시 사용하고 있고, HTML 스팩에도 있다.

표 1. 엘리먼트 접근에 사용되는 메소드

메소드(Method) 설명
document.getElementById( aId ) 지정된 ID를 가진 엘리먼트에 대한 레퍼런스를 리턴한다.
document.getElementsByTagName( aTagName ) 문서에 지정된 이름을 가진 엘리먼트의 어레이를 리턴한다.

DOM의 트래버스

Mozilla는 JavaScript를 통해 DOM 트리를 횡단하는 W3C DOM API를 지원한다. (표 2 참조). 이 API는 문서의 각 노드에 존재하고, 어떤 방향으로든 트리를 이동시킬 수 있다. Internet Explorer 역시 이 API를 지원하지만, DOM 트리를 이동시키는 경우에는 레거시 API를 지원한다. children 속성을 사용한다.

표 2. DOM 트래버스에 사용되는 메소드

속성/메소드 설명
childNodes 엘리먼트의 모든 자식 노드 어레이를 리턴한다.
firstChild 엘리먼트의 첫 번째 자식 노드를 리턴한다.
getAttribute( aAttributeName ) 지정된 애트리뷰트의 값을 리턴한다.
hasAttribute( aAttributeName ) 현재 노드가 특정 이름으로 정의된 애트리뷰트를 갖고 있는지의 여부를 기술하는 부울을 리턴한다.  
hasChildNodes() 현재 노드가 자식 노드들을 갖고 있는지를 기술하는 부울을 리턴한다. 
lastChild 엘리먼트의 마지막 자식 노드를 리턴한다.
nextSibling 현재 노드 바로 뒤에 나오는 노드를 리턴한다.
nodeName 현재 노드의 이름을 스트링으로 리턴한다.
nodeType 현재 노드의 유형을 리턴한다.  

   

설명
1 엘리먼트 노드
2 애트리뷰트 노드
3 텍스트 노드
4 CDATA 섹션 노드
5 엔터티 레퍼런스 노드
6 엔터티 노드
7 처리 지시 노드
8 주석 노드
9 문서 노드
10 문서 유형 노드
11 문서 조각 노드
12 표기법 노드
 

   
nodeVal!!ue 현재 노드의 값을 리턴한다. 텍스트 노드와 문서 노드 같이 텍스트를 포함하고 있는 노드의 경우 스트링 값을 리턴한다. 애트리뷰트 노드의 경우 애트리뷰트 값이 리턴된다. 다른 모든 노드들의 경우, null이 리턴된다.
ownerDocument 현재 노드를 포함하고 있는 document 객체를 리턴한다.
parentNode 현재 노드의 부모 노드를 리턴한다.
previousSibling 현재 노드 바로 전 노드를 리턴한다.
removeAttribute( aName ) 현재 노드에서 특정 애트리뷰트를 제거한다.
setAttribute( aName, aValue ) 지정된 값으로 지정된 애트리뷰트의 값을 설정한다.

Internet Explorer는 비표준 쿼크를 갖고 있고, 이들 API 중 많은 것들이 새로운 라인 문자로 만들어진 빈 공간 텍스트 노드를 지나친다. Mozilla는 이들을 지나치지 않기 때문에 이들 노드들을 구별해야 한다. 모든 노드들은 노드 유형을 지정하는 nodeType속성을 갖고 있다. 예를 들어, 엘리먼트 노드는 유형 1, 텍스트 노드는 유형 3, 주석 노드는 유형 8 이다. 엘리먼트 노드를 처리하는 최상의 방법은 전체 자식 노드들을 반복하고, 1의 nodeType으로 이들을 처리하는 것이다.

 
  HTML: 
    <div id="foo"> 
      <span>Test</span> 
  c </div> 

  JavaScript: 
    var myDiv = document.getElementById("foo"); 
    var myChildren = myXMLDoc.childNodes; 
    for (var i = 0; i < myChildren.length; i++) { 
      if (myChildren[i].nodeType == 1){ 
        // element node
      }
    }

콘텐트 생성 및 조작

Mozilla는 콘텐트를 DOM에 동적으로 추가할 때 document.write, document.open, document.close 같은 레거시 메소드를 지원한다. Mozilla는 Internet Explorer의 InnerHTML 메소드도 지원하는데 이는 거의 모든 노드를 호출할 수 있다. 하지만 OuterHTML(엘리먼트 주위에 마크업을 추가함. 이와 관련한 표준이 없다.)과 innerText(노드의 텍스트 값을 설정하고, Mozilla에서는textContent를 사용하면 된다.)를 지원하지 않는다.

Internet Explorer에는 여러 콘텐트 조작 메소드가 있다. 이들은 비 표준이고 Mozilla에서는 지원되지 않는다. 값 검색하기, 텍스트 삽입하기, getAdjacentElementinsertAdjacentHTML 같은 노드에 인접한 엘리먼트 삽입하기 등도 지원되지 않는다.

표 3. Mozilla가 콘텐트 조작에 사용하는 메소드

메소드 설명
appendChild( aNode ) 새로운 자식 노드를 만든다. 새로운 자식 노드에 대한 레퍼런스를 리턴한다.
cloneNode( aDeep ) 호출되는 노드의 카피를 만들고 그 카피를 리턴한다. aDeep이 true 라면 노드의 전체 하위 트리를 복사한다.
createElement( aTagName ) aTagName에서 지정된 유형의 부모 노드가 없는 새로운 DOM 노드를 만들어 리턴한다.
createTextNode( aTextValue ) aTextValue에서 지정된 데이터 값을 가진 부모 노드가 없는 새로운 DOM 텍스트 노드를 만들어 리턴한다.
insertBefore( aNewNode, aChildNode ) 현재 노드의 자식이 될 aChildNode에 앞서 aNewNode를 삽입한다.
removeChild( aChildNode ) aChildNode를 제거하고 여기에 레퍼런스를 리턴한다.
replaceChild( aNewNode, aChildNode ) aChildNode를 aNewNode로 대체하고 제거된 노드에 대한 레퍼런스를 리턴한다.

문서 조각

퍼포먼스 때문에 기존 문서의 DOM에서 작업하기 보다는 메모리에 문서를 만들 수 있다. DOM Level 1 Core는 정상적인 문서의 인터페이스 하위 세트를 포함하고 있는 경량의 문서인 문서 조각을 도입했다. 예를 들어, getElementById는 존재하지 않지만, appendChild는 존재한다. 기존 문서에 문서 조각을 쉽게 추가할 수 있다.

Mozilla는 document.createDocumentFragment()를 통해 문서 조각을 만든다. 이것은 빈 문서 조각을 리턴한다.

Internet Explorer 구현의 문서 조각은 W3C 표준에 순응하지 않고 정상 문서를 리턴한다.






JavaScript의 다른 점

Most Mozilla와 Internet Explorer의 차이점은 보통 JavaScript 때문에 생긴다. 하지만 이 문제는 브라우저가 DOM 후크(hook) 같은 JavaScript를 노출하는 API에 있다. 이 두 개의 브라우저는 몇 개의 핵심 차이점을 갖고 있다. 문제는 타이밍과 관련이 있다.

JavaScript date 차이

유일한 Date 차이는 getYear 메소드이다. ECMAScript 스팩에 따라(JavaScript가 따르는 스팩), 이 메소드는 Y2k 호환이 되지 않으며, new Date().getYear()를 실행한다. 2004년에 getYear는 "104"를 리턴한다. ECMAScript 스팩에 의해 getYear는 마이너스 1900년을 리턴한다. 원래는 1998에 "98" 을 리턴 하려고 했다. getYear는 ECMAScript Version 3에서 없어지고, getFullYear()로 대체되었다. Internet Explorer는 getYear()를 변경하여 getFullYear()처럼 작동하게 하고, 이것을 Y2K에 호환되도록 했고, Mozilla는 표준 작동을 유지시켰다.

JavaScript execution differences

브라우저 마다 JavaScript를 다르게 실행한다. 예를 들어, 아래 코드는 script블록이 실행되던 때에 DOM에 div노드가 이미 존재하고 있다고 간주한다.

 
 
... 
<div id="foo">Loading...</div> 

<script> 
  document.getElementById("foo").innerHTML = "Done."; 
</script> 
 

하지만 이것도 보장할 수 없다. 모든 엘리먼트가 확실히 존재한다는 것을 보장하려면 <body> 태그에 onload 이벤트 핸들러를 사용한다.

 
<body onload="doFinish()"> 

<div id="foo">Loading...</div> 

<script> 
  function doFinish() { 
    var element = document.getElementById("foo");
	  element.innerHTML = "Done."; 
  } 
</script> 
... 

이와 같은 타이밍 관련 문제들 역시 하드웨어와 관련이 있다. 느린 시스템은 빠른 시스템이 숨기는 버그를 찾아낼 수 있다. 한 가지 예는 window.open이다. 이것은 새로운 창을 연다.

 
 
<script> 
  function doOpenWindow(){ 
 var myWindow = window.open("about:blank"); 
 myWindow.location!!.href = "http://www.ibm.com"; 
  }   
</script> 
 

이 코드의 문제는 window.open이 비동기식이란 점이다. 창에서 로딩이 끝나기 전까지 JavaScript 실행을 막지 않는다. 따라서 새로운 창이 끝나기 전에 window.open 라인 뒤에 라인을 실행한다. 이때에는 새로운 창에 onload 핸들러를 사용하여 처리한 다음, 오프너 윈도우 (window.opener사용)로 콜백한다.

JavaScript에서 생성한 HTML의 차이점

JavaScript는 document.write를 통해 스트링에서 HTML을 만든다. 여기서 중요한 문제는 HTML 문서 내부 (<script>태그 내부)에 삽입된 JavaScript가 태그를 포함하고 있는 HTML 을 만든다. 이 문서가 스트릭트 렌더링 모드(strict rendering mode)에 있다면 스트링 내부에서 <script>의 닫기 태그인 </script>를 파싱한다.

 
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
... 
<script> 
  document.write("<script>alert!!("Hello")</script>") 
</script> 
 

이 페이지는 스트릭트 모드에 있기 때문에 Mozilla의 파서는 먼저 <script> 를 보고 이것이 닫기 태그(</script>)를 찾을 때까지 파싱한다. 스트릭트 모드에 있을 때에는 이 파서가 JavaScript(또는 다른 언어)에 대해 모르기 때문이다. 쿼크 모드에서, 이 파서는 파싱할 때 JavaScript를 인식한다. Internet Explorer는 언제나 쿼크 모드에 있다. 이것은 순수 XHTML을 지원하지 않기 때문이다. Mozilla의 스트릭트 모드에서 실행시키려면 스트링을 두 부분으로 나눈다.

 
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
... 
<script> 
  document.write("<script>alert!!("Hello")</" + "script>") 
</script> 
 

JavaScript 디버그

Mozilla는 Internet Explorer에서 만든 애플리케이션에서 발견된 JavaScript 관련 문제들을 디버깅하는 여러 방법들을 제공한다. 첫 번째 툴은 빌트인 JavaScript 콘솔이다. (그림 1). 여기에서 에러와 경고가 기록된다. Mozilla에서 Tools -> Web Development -> JavaScript Console로, Firefox(Mozilla의 스탠드얼론 브라우저 제품)에서는 Tools -> JavaScript Console로 간다.



그림 1. JavaScript 콘솔
JavaScript  console

JavaScript 콘솔은 전체 로그 리스트를 보여주거나 또는 에러, 경고, 메시지만 보여줄 수 있다. 그림 1의 에러 메시지에서는 aol.com 에서 95 번째 줄에서 is_ns70이라는 미정의 변수에 접근을 시도한다는 것을 알 수 있다. 링크를 클릭하면 Mozilla의 내부 뷰 소스 창이 여리고 문제가 되는 라인이 표시된다.

또한 이 콘솔에서는 JavaScript를 확인할 수 있다. 입력된 JavaScript 문법을 확인하려면 인풋 필드에 1+1을 타이핑하고 Eval!!uate을 누른다. (그림 2)



그림 2. JavaScript 콘솔 확인
JavaScript console eval!!uating

Mozilla의 JavaScript 엔진은 빌트인 디버깅 지원이 되기 때문에 JavaScript 개발자를 위한 강력한 툴을 제공할 수 있다. 그림 3의 Venkman은 강력한, 크로스 플랫폼 JavaScript 디버거이다. 이것은 Mozilla와 통합된다. 보통 Mozilla 릴리스와 함께 번들 되기 때문에 Tools -> Web Development -> JavaScript Debugger에서 찾을 수 있다. Firefox의 경우 이 디버거가 번들 되지 않는다. 대신 http://www.mozilla.org/projects/venkman/에서 다운로드 하여 설치한다. 또한 http://www.hacksrus.com/~ginda/venkman/의 개발 페이지에는 튜토리얼도 있다.



그림 3. Mozilla의 JavaScript 디버거
Mozilla's  JavaScript debugger

JavaScript 디버거는 Mozilla 브라우저 창에서 실행되는 JavaScript를 디버깅 한다. 이것은 중단점 관리, 콜 스택 검사, 변수/객체 검사 같은 표준 디버깅 기능을 지원한다. 모든 기능은 사용자 인터페이스 또는 디버거의 콘솔을 통해 접근할 수 있다. 이 콘솔을 사용하여 현재 디버깅되고 있는 JavaScript와 같은 범위로 임의의 JavaScript를 실행한다.






CSS의 다른 점

Mozilla는 CSS1, CSS2, CSS3의 일부 등 Cascading Style Sheets (CSS)에 대한 강력한 지원 기능이 된다. 이것은 Internet Explorer와 다른 모든 브라우저들과 비교된다.

Mozilla는 JavaScript 콘솔에 에러 또는 경고 엔트리를 추가한다. CSS 관련 문제가 생기면 JavaScript 콘솔을 검사하라.

Mimetype (CSS 파일이 적용되지 않을 때)

가장 일반적인 CSS 관련 문제는 참조된 CSS 파일들 내부에 있는 CSS 정의가 적용되지 않는다는 점이다. 이는 CSS 파일에 잘못된 mimetype을 보내는 서버 때문이다. CSS 스팩에 따르면, CSS 파일은 text/css 으로 제공되어야 한다. Mozilla는 이것에 순응하여 웹 페이지가 엄밀한 표준 모드일 때 CSS 파일만 로딩한다. Internet Explorer는 언제나 CSS 파일을 로딩한다. 어떤 mimetype이든 상관이 없다. 웹 페이지들은 엄격한 doctype으로 시작할 때 정확한 표준 모드로 간주된다. 이 문제를 해결하려면 서버가 올바른 mimetype을 보내도록 하거나 doctype을 제거한다. 다음 섹션에서 doctype을 자세히 다루겠다.

CSS와 단위

많은 웹 애플리케이션들은 CSS와 단위를 함께 사용하지 않는다. 특히 JavaScript를 사용하여 CSS를 설정할 때 그렇다. Mozilla는 페이지가 스트릭트 모드에서 렌더링 되지 않는 한 이를 참아낸다. Internet Explorer는 순수 XHTML을 지원하지 않기 때문에 단위가 지정되지 않아도 신경 쓰지 않는다. 페이지가 엄격한 표준 모드에 있고, 단위가 사용되지 않는다면 Mozilla는 이 스타일을 무시한다.

 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html> 
  <body> 
    // works in strict mode 
    <div style="width:40px; border:1px solid black;">
      Text
    </div>

    // will fail in strict mode 
         <div style="width:40; border:1px solid black;">
                  Text
         </div>
  </body> 
</html> 

위 예제는 엄밀한 doctype을 갖고 있기 때문에 이 페이지는 정확한 표준 모드로 렌더링된다. 첫 번째 div는 단위를 사용하기 때문에 40px 넓이이다. 하지만 두 번째 div는 넓이가 없다. 따라서 디폴트인 100% 비율로 넓이가 조정된다. JavaScript를 통해 넓이가 설정되면 똑 같이 적용된다.

JavaScript와 CSS

Mozilla는 CSS 표준을 지원하기 때문에 JavaScript를 사용하여 CSS를 설정하는 CSS DOM 표준도 지원한다. 이 엘리먼트의 style 멤버를 통해 엘리먼트의 CSS 규칙에 접근, 제거, 변경할 수 있다.

 
<div id="myDiv" border:1px solid black;">
  Text
</div> 

<script> 
  var myElm = document.getElementById("myDiv"); 
  myElm.style.width = "40px"; 
</script> 

그러한 방식으로 모든 CSS 애트리뷰트에도 접근할 수 있다. 웹 페이지가 strict 모드이면 단위를 설정해야 한다. 그렇지 않으면 Mozilla는 이 명령어를 무시한다.

 

Mozilla와 Internet Explorer에서 .style.width를 통해 값을 쿼리하면 리턴 값에는 스트링이 리턴 되었다는 것을 의미하는 단위가 포함된다. 이 스트링을 parseFloat("40px")를 통해 숫자로 변환할 수 있다.

CSS 오버플로우 차이점

CSS는 오버플로우 개념을 추가했다. 이것으로 오버플로우를 핸들하는 방법을 정의할 수 있다. 예를 들어, 높이가 지정된 div의 콘텐츠가 그 높이 보다 더 클 경우가 있다. 이 경우에 CSS 표준은 어떤 오버플로우 작동도 설정되지 않으면 div 콘텐츠가 오버플로우 된다고 정의하고 있다. 하지만 Internet Explorer는 이를 따르지 않고, div를 설정 높이 이상으로 확장하여 콘텐츠를 보유할 수 있도록 한다. 다음은 이러한 차이점을 보여주는 예제이다.

 
<div style="height:100px; border: 1px solid black;"> 
  <div style="height:150px; border: 1px solid red; 
                 margin:10px;">
    a
  </div> 
</div> 

그림 4에서 보듯, Mozilla는 표준이 정하는 대로 작동한다. 이 표준은, 내부 콘텐트가 그 부모 보다 크기 때문에, 내부 div가 아래쪽으로 오버플로우 된다고 언급하고 있다. Internet Explorer 작동이 더 좋다고 생각하면 외부 엘리먼트의 높이를 지정하지 않으면 된다.



그림 4. DIV 오버플로우
DIV  overflow

hover 차이점

Internet Explorer에서 비표준 CSS a:hover 작동은 극소수의 IBM 웹 사이트에서 발생한다. Internet Explorer가 아닌, Mozilla에서 머무를 때 텍스트 스타일을 변경하여 이를 나타낸다. Internet Explorer의 a:hover CSS 섹터가 <a name="" />이 아닌 <a href="" />와 맞기 때문이다. 이것은 HTML에서 앵커를 설정한다. 작성자가 이 영역을 앵커 설정 마크업으로 캡슐화 하기 때문에 텍스트가 변경된다.

 
 
 CSS: 
a:hover {color:green;} 

 HTML: 
<a href="foo.com">This should turn green when you hover over it.</a> 

<a name="anchor-name"> 
  This should change color when hovered over, but doesn't 
   in Internet Explorer. 
</a> 
 

Mozilla는 CSS 스팩을 정확히 따르고 이 예제에서 색깔을 녹색으로 바꿀 것이다. 이 두 가지 방식을 사용하여 Mozilla가 Internet Explorer와 비슷하게 작동하도록 하고, 계속 머무를 경우 텍스트의 색깔이 변하지 않도록 한다.

  • 먼저 a:link:hover {color:green;}이 되도록 CSS 규칙을 변경한다. 이것은 엘리먼트가 링크라면 href 애트리뷰트를 갖고 있다면) 색깔만 바꿀 것이다.
  • 또는, 마크업을 변경하여 텍스트 시작 전에 개방된 <a />를 닫는다. 앵커는 이러한 방식으로 계속 작동할 것이다.





쿼크(Quirk) 모드와 표준 모드

Internet Explorer 4 같은 기존 브라우저는 특정 환경에서 소위 말하는 쿼크(quirk)로 렌더링되었다. Mozilla는 표준에 순응하는 브라우저를 모토로 하기 때문에, 이러한 쿼크 작동으로 만들어진 오래된 웹 페이지들에 세 가지 모드를 지원한다. 페이지의 콘텐트와 딜리버리가 Mozilla가 사용 할 모드를 결정한다. Mozilla는 렌더링 된 모드를 View -> Page Info(또는 Ctrl-i)에 리스팅 할 것이다. 페이지가 배치될 모드는 doctype에 의존한다.

 

doctype은 다음과 같다

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

파란색의 섹션은 공식 식별자고, 녹색 부분은 시스템 식별자(URI) 이다.

표준 모드

표준 모드는 가장 엄격한 렌더링 모드이다. W3C HTML과 CSS 스팩에 따라 페이지를 렌더링하며 어떤 쿼크도 지원하지 않는다. Mozilla는 다음과 같은 조건에서 이 모드를 사용한다.

  • 페이지가 text/xml mimetype 또는 XML / XHTML mimetype 으로 전송된 경우
  • IBM doctype을 제외한 모든 "DOCTYPE HTML SYSTEM" doctype (예를 들어, <!DOCTYPE HTML SYSTEM "http://www.w3.org/TR/REC-html40/strict.dtd">)
  • 알려지지 않은 doctype 또는 DTD가 없는 doctype

표준에 가까운 모드

Mozilla는 한 가지 이유 때문에 표준에 가까운 모드를 도입했다. CSS 2 스팩의 한 섹션이 테이블 셀에서 정밀한 레이아웃의 작은 이미지 때문에 디자인을 갈라낸 경우이다. 하나의 이미지를 만드는 대신 각각의 작은 이미지 사이를 공백으로 처리한다. 옛날 IBM 홈페이지(그림 5)가 그 예제이다.



그림 5. 이미지 갭
Image gap

이미지 갭 문제가 발생할 때를 제외하고는, 표준에 가까운 모드는 표준 모드와 거의 비슷하게 작동한다. 이러한 문제는 표준에 순응하는 페이지에서 종종 발생하고 부정확한 디스플레이를 만들어 낸다.

Mozilla는 다음과 같은 상황에서 표준에 가까운 모드를 사용한다.

  • "느슨한(loose)" doctype (예를 들어, <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">, <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">)
  • IBM doctype (<!DOCTYPE html SYSTEM "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd">)

자세한 내용은 이미지 갭 문제를 참조하라.

쿼크 모드

현재 웹은 유효하지 않거나 브라우저의 버그로 인해 작동되는 HTML 마크업이 상당히 많다. 옛날 Netscape 브라우저가 시장을 지배했을 때도 버그는 있었다. Internet Explorer가 탄생했을 때 그 당시의 콘텐트와도 작동해야 했기 때문에 그러한 버그 조차도 모방했다. 새로운 브라우저가 시장에 진입하면서 이러한 오래된 버그들(쿼크(quirks))은 백워드 호환을 위해 유지되었다. Mozilla는 쿼크 렌더링 모드에서 이를 지원한다. 이런 쿼크 때문에 완전히 표준에 순응하더라도 페이지 렌더링이 느려지는 것이다. 대부분의 웹 페이지들은 이 모드에서 렌더링 된다.

Mozilla는 다음 상황에서 쿼크 모드를 사용한다.

  • 어떤 doctype도 지정되지 않을 경우
  • doctype에 시스템 식별자가 없는 경우 (예를 들면, <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">)

List of QuirksList of Doctypes and What Modes They Cause를 참조하라.  






이벤트 차이점

Mozilla와 Internet Explorer는 이벤트 분야에서 거의 다르다. Mozilla 이벤트 모델은 W3C와 Netscape 모델을 따르고 있다. Internet Explorer에서 함수가 이벤트에서 호출되면 window.event를 통해 event 객체에 액세스 할 수 있다. Mozilla는 event 객체를 이벤트 핸들러로 전달한다. 이들은 인자를 통해 호출되는 함수에 대한 객체를 정확히 전달해야 한다. 크로스 브라우저 이벤트 핸들링 예제는 다음과 같다.

 
 
 <div onclick="handleEvent(event)">Click me!</div> 

 <script> 
function handleEvent(aEvent){ 
  // if aEvent is null, means the Internet Explorer event model, 
  // so get window.event. 
  var myEvent = aEvent ? aEvent : window.event; 
}   
 </script> 
 

이벤트 객체가 노출하는 속성과 함수들은 Mozilla와 Internet Explorer가 다르게 이름을 붙이고 있다. 표 4를 보자.  

표 4. Mozilla와 Internet Explorer의 이벤트 속성

Internet Explorer Name Mozilla Name 설명
altKey altKey alt 키가 이벤트가 발생하는 동안 전달되었는지의 여부를 리턴하는 부울 속성.
cancelBubble stopPropagation() 이벤트를 트리에서 떼어내어 중지시킬 때 사용.
clientX clientX 클라이언트와 관련된 이벤트의 X 좌표.
clientY clientY 클라이언트와 관련된 이벤트의 Y 좌표.
ctrlKey ctrlKey Ctrl 키가 이벤트 동안 전달되었는지를 리턴하는 부울 속성.
fromElement relatedTarget 마우스 이벤트의 경우, 마우스의 이동되기 전의 엘리먼트.
keyCode keyCode 키보드 이벤트의 경우, 눌려진 키의 수. 마우스 이벤트의 경우는 0이다.
returnValue preventDefault() 이벤트의 디폴트 작동이 발생하지 않도록 하는데 사용.
screenX screenX 스크린과 관련된 이벤트의 X 좌표.
screenX screenY 스크린과 관련된 이벤트의 Y 좌표.
shiftKey shiftKey Shift 키가 이벤트 때 눌러졌는지 여부를 리턴하는 부울 속성.
srcElement target 이벤트가 처음으로 전달된 엘리먼트.
toElement currentTarget 마우스 이벤트의 경우, 마우스가 이동했던 엘리먼트.
type type 이벤트의 이름을 리턴함.

이벤트 핸들러 붙이기

Mozilla는 JavaScript를 통해 이벤트를 첨부할 때 두 가지 방식을 사용할 수 있다. 첫 번째 방법은 모든 브라우저에서 지원된다. 객체에 직접 이벤트 속성을 설정하는 것이다. click 이벤트 핸들러를 설정하려면 함수 레퍼런스가 객체의 onclick 속성으로 전달된다.

 
 
 <div id="myDiv">Click me!</div> 

 <script> 

function handleEvent(aEvent){ 
  // if aEvent is null, means the Internet Explorer event model, 
  // so get window.event. 
  var myEvent = aEvent ? aEvent : window.event; 
} 


function onPageLoad(){ 
  document.getElementById("myDiv").onclick = handleEvent; 
} 

 </script> 
 

Mozilla는 DOM 노드에 리스너를 붙일 때 W3C 표준 방식을 지원한다. addEventListener()removeEventListener() 메소드를 사용하고, 같은 이벤트 유형에 여러 리스너를 설정할 수 있다. 두 메소드 모두 세 개의 매개변수들이 필요하다. 이벤트 유형, 함수 레퍼런스, 리스너가 캡쳐 단계에서 이벤트를 잡았는지의 여부를 알려주는 부울이 그것이다. 부울이 false로 설정되면 버블링 이벤트만 잡을 것이다. W3C 이벤트는 세 단계(캡쳐, 목표, 버블링)이다. 모든 이벤트 객체는 eventPhase 애트리뷰트가 있다. 이것은 단계를 숫자로 나타낸다. 이벤트를 발생시킬 때 마다 이벤트는 DOM의 가장 바깥쪽의 엘리먼트에서 시작한다. 목표로 가는 가장 직접적인 루트를 사용하여 DOM은 작동한다. 이것이 캡쳐 단계이다. 목표에 도착한 후에 DOM 트리는 가장 외부의 노드로 다시 돌아간다. 이것이 버블링(bubbling)이다. Internet Explorer의 이벤트 모델은 오직 이 버블링 단계만 있다. 따라서 false 결과에 대해 제 3의 매개변수를 설정하면 Internet Explorer에서는 다음과 같이 작동한다.

 
<div id="myDiv">Click me!</div> 

<script> 

  function handleEvent(aEvent) { 
    // if aEvent is null, it is the Internet Explorer event model, 
    // so get window.event. 
    var myEvent = aEvent ? aEvent : window.event; 
  } 

  function onPageLoad() {
        var element = document.getElementById("myDiv");
    element.addEventListener("click", handleEvent, false); 
  } 
</script> 

속성을 설정할 때 addEventListener()removeEventListener()의 한 가지 장점은 같은 이벤트에 또 다른 함수를 호출하는 다중 이벤트 리스너들을 가질 수 있다는 점이다. 따라서 이벤트 리스너를 제거하려면 이 세 개의 매개변수 모두 리스너에 추가할 때 사용했던 것과 같아야 한다.

Internet Explorer에서 <script> 태그를 이벤트 핸들러로 변환하는 방식을 Mozilla는 지원하지 않는다. 그 방식은 이벤트 핸들러가 <script> 를 forevent 애트리뷰트로 확장하는 것이다. (표 5). 또한 attachEventdetachEvent 메소드도 지원하지 않는다. 대신 addEventListenerremoveEventListener 메소드를 사용할 수 있다. Internet Explorer는 W3C 이벤트 스팩을 지원하지 않는다.

표 5. Mozilla와 Internet Explorer의 이벤트 메소드 차이점  

Internet Explorer 메소드 Mozilla 메소드 설명
attachEvent(aEventType, aFunctionReference) addEventListener(aEventType, aFunctionReference, aUseCapture) 이벤트 리스너를 DOM 엘리먼트에 추가한다.
detachEvent(aEventType, aFunctionReference) removeEventListener(aEventType, aFunctionReference, aUseCapture) DOM 엘리먼트에서 이벤트 리스너를 제거한다.






리치 텍스트 편집

Mozilla는 W3C 표준에 가장 잘 순응하는 브라우저라고 자부하지만, W3C에는 없는 innerHTML과 리치 텍스트 편집 같은 비표준 기능을 지원한다.

Mozilla 1.3은 Internet Explorer의 designMode 기능을 도입했다. 이것은 HTML 문서가 리치 텍스트 에디터 필드로 변환되는 것이다. 일단 에디터로 바뀌면 명령어는 execCommand 명령어를 통해 문서에서 작동할 수 있다. Mozilla는 Internet Explorer의 contentEditable 애트리뷰트를 지원하지 않는다. iframe 을 사용하여 텍스트 에디터에 추가할 수 있다.

리치 텍스트 차이점

 

Mozilla는 iframe의 문서 객체에 IFrameElm.contentDocument를 통해 접근하는 W3C 표준을 지원한다. 하지만 Internet Explorer에서는 document.frames["name"]를 통해 접근하여 결과 document에 액세스한다.

 
 
  function getIFrameDocument(aID){ 
 var rv = null; 

 // if contentDocument exists, W3C compliant (Mozilla) 
 if (document.getElementById(aID).contentDocument){ 
   rv = document.getElementById(aID).contentDocument; 
 } else { 
   // IE 
   rv = document.frames[aID].document; 
 } 

 return rv; 
  } 
 

Mozilla와 Internet Explorer의 또 다른 차이점은 리치 텍스트 에디터를 만드는 HTML이다. Mozilla는 기본적으로 마크업을 생성할 때 CSS를 사용한다. 하지만 Mozilla에서는 HTML과 CSS 모드를 토글링 할 수 있다. useCSS execCommand 를 사용하여 true 와 false 사이에서 이것을 토글링 하는 것이다. Internet Explorer는 언제나 HTML 마크업을 사용한다.

 
 
  Mozilla (CSS): 
 <span style="color: blue;">Big Blue</span> 

  Mozilla (HTML): 
 <font color="blue">Big Blue</font> 

  Internet Explorer: 
 <FONT color="blue">Big Blue</FONT> 
 

아래 표는 Mozilla의 execCommand 가 지원하는 명령어 리스트이다.

표 6. 리치 텍스트 편집 명령어  

명령어 설명 인자
bold 선택된 것의 볼드체 애트리뷰트를 토글링. ---
createlink 선택된 텍스트에서 HTML 링크를 만듦. 링크에 사용할 URL
delete 선택을 삭제. ---
fontname 선택된 텍스트에 사용된 폰트를 변경함. 폰트 종류(Arial)
fontsize 선택된 텍스트에 사용된 폰트 사이즈 변경. 폰트 사이즈
fontcolor 텍스트에 사용된 폰트 색 변경.
indent 탈자 기호가 있는 블록 들여쓰기. ---
inserthorizontalrule 커서 위치에 <hr> 삽입하기. ---
insertimage 커서 위치에 이미지 삽입하기. 커서 위치에 이미지 삽입하기. 이미지의 URL
insertorderedlist 커서 위치에 ordered list (<ol>) 삽입하기. ---
insertunorderedlist 커서 위치에 unordered list (<ul>) 삽입하기. ---
italic 이탤릭체로 된 애트리뷰트 토글링. ---
justifycenter 현재 라인에서 콘텐트 센터링하기. ---
justifyleft 현재 라인에서 왼쪽으로 콘텐트 정렬하기. ---
justifyright 현재 라인에서 오른쪽으로 콘텐트 정렬하기. ---
outdent 탈자 기호가 있는 블록 내어쓰기. ---
redo 이전의 실행취소 명령어 재실행. ---
removeformat 선택된 것에서 모든 포맷팅 제거. ---
selectall 리치 텍스트 에디터에 있는 모든 것 선택. ---
strikethrough 선택된 택스트의 중앙(strikethrough)을 토글링. ---
subscript 현재 선택을 첨자로 변환. ---
superscript 현재 선택을 윗첨자로 변환. ---
underline 선택된 텍스트의 밑줄을 토글링. ---
undo 마지막 실행 명령어의 실행취소. ---
unlink 선택된 것에서 모든 링크 정보 제거. ---
useCSS 생성된 마크업에서 CSS의 사용을 토글링. 부울 값

자세한 정보는 DevEdge를 참조하기 바란다.






XML의 차이점

Mozilla는 XSLT와 웹 서비스 같은 XML과 XML 기반 기술을 지원한다. 또한 XMLHttpRequest 같은 비표준 Internet Explorer 확장도 지원한다.

XML을 핸들하는 방법

 

표준 HTML 처럼, Mozilla는 W3C XML DOM 스팩을 지원한다. 따라서 모든 XML 문서를 조작할 수 있다. Internet Explorer의 XML DOM과 Mozilla의 차이점은 Internet Explorer의 비표준 작동에서 기인한다. 가장 큰 차이점은 공백 텍스트 노드를 핸들하는 방식이다. XML이 생성되면 여기에는 XML 노드들 간 공백이 포함된다. Internet Explorer에서 XMLNode.childNodes[]가 사용될 때에는 이러한 공백 노드가 포함되지 않는다. 당연히 Mozilla에는 있다.

 
 
  XML: 
 <?xml version="1.0"?> 
 <myXMLdoc xmlns:myns="http://myfoo.com"> 
   <myns:foo>bar</myns:foo> 
 </myXMLdoc> 

  JavaScript: 
 var myXMLDoc = getXMLDocument().documentElement; 
 alert!!(myXMLDoc.childNodes.length); 
 

JavaScript의 첫 번째 줄에서는 XML 문서가 로딩되고 documentElement 를 검색하여 루트 엘리먼트(myXMLDoc)에 액세스 된다. 두 번째 줄은 자식 노드의 수를 알려준다. W3C 스팩에 따라 공백과 새로운 라인들은 하나의 텍스트 노드로 합병된다. Mozilla의 경우 myXMLdoc 노드에는 세 개의 자식이 포함되어 있다. 새로운 라인과 두 개의 공백을 포함하는 텍스트 노드, myns:foo 노드, 새로운 라인이 있는 또 다른 텍스트 노드가 바로 자식 노드이다. 하지만 Internet Explorer는 이에 순응하지 않고 위 코드에 대해 "1" 을 리턴할 것이다. myns:foo 노드만 갖고 있다. 따라서 자식 노드들을 실행시키고 텍스트 노드들을 무시하려면 그와 같은 노드들을 구별해야 한다.

앞에 언급했듯이, 모든 노드들은 노드 유형(nodeType)을 나타내는 애트리뷰트를 갖고 있다. 예를 들어, 엘리먼트 노드가 1이란 유형을 갖고 있고 문서 노드가 유형 9를 갖고 있을 때, 텍스트 노드를 무시하려면 유형 3(텍스트 노드)와 8(주석 노드)를 검사해야 한다.

 
 
  XML: 
 <?xml version="1.0"?>   
 <myXMLdoc xmlns:myns="http://myfoo.com"> 
   <myns:foo>bar</myns:foo> 
 </myXMLdoc>   

  JavaScript: 
 var myXMLDoc = getXMLDocument().documentElement; 
 var myChildren = myXMLDoc.childNodes; 
 for (var run = 0; run < myChildren.length; run++){ 
   if ( (myChildren[run].nodeType != 3) && 
(myChildren[run].nodeType != 8) ){ 
  // not a text or comment node 
   } 
 } 
 

XML 데이터 섬(island)

Internet Explorer에는 XML 데이터 섬(island)이라는 비표준 기능이 있다. 비표준 HTML 태그 <xml>을 사용하여, HTML 문서 내에 XML을 삽입할 수 있다. Mozilla는 XML 데이터 섬을 지원하지 않고, 이들을 알려지지 않은 HTML 태그로 처리한다. XHTML을 사용하여 같은 효과를 얻을 수 있다. 하지만 Internet Explorer의 XHTML 지원은 미미하기 때문에 옵션이라고 볼 수 없다.

크로스 브라우저 솔루션 중에는 DOM 파서를 사용하는 것이 있다. 이 파서는 직렬화된 XML 문서를 포함하고 있고, 파싱된 XML을 위해 이 문서를 만드는 스트링을 파싱한다. Mozilla는 DOMParser 클래스를 사용한다. 이것은 직렬화된 스트링을 취해서 XML 문서를 만든다. Internet Explorer에서는 ActiveX가 비슷한 기능을 한다. 새로운 Microsoft.XMLDOMloadXML 메소드를 만들어낸다.

 
 
  IE XML data island: 
 .. 
 <xml id="xmldataisland"> 
   <foo>bar</foo> 
 </xml>   

  Cross-browser solution: 
 var xmlString = "<xml 
id=\"xmldataisland\"><foo>bar</foo></xml>"; 
 var myDocument; 
  
 if (document.implementation.createDocument){ 
   // Mozilla, create a new DOMParser 
   var parser = new DOMParser(); 
   myDocument = parser.parseFromString(xmlString, "text/xml"); 
 } else if (window.ActiveXObject){ 
   // Internet Explorer, create a new XML document using ActiveX 
   // and use loadXML as a DOM parser. 
   myDocument = new ActiveXObject("Microsoft.XMLDOM") 
   myDocument.async="false"; 
   myDocument.loadXML(xmlString);   
 } 
 

XML HTTP 요청

Internet Explorer에서는 MSXML의 XMLHTTP 클래스를 사용하여 XML 파일들을 보내고 검색할 수 있다. 이것은 new ActiveXObject("Msxml2.XMLHTTP") 또는 new ActiveXObject("Microsoft.XMLHTTP")를 사용하는 ActiveX를 통해 인스턴스화 된다. 표준 방식이 따로 없기 때문에 Mozilla는 글로벌 자바스크립트인 XMLHttpRequest 객체를 사용한다. 이 객체는 기본적으로 비동기식 요청을 만든다.

 

new XMLHttpRequest()를 사용하여 객체를 인스턴스화 한 후에 open 메소드를 사용하여 요청 유형(GET 또는 POST), 로딩할 파일, 비동기식 여부 등을 지정한다. 비동기식 호출일 경우 onload 멤버를 함수 레퍼런스에 준다. 이것은 요청이 완료되면 호출된다.

 
Synchronous request: 

  var myXMLHTTPRequest = new XMLHttpRequest(); 
  myXMLHTTPRequest.open("GET", "data.xml", false); 
  myXMLHTTPRequest.send(null); 

  var myXMLDocument = myXMLHTTPRequest.responseXML; 

Asynchronous request: 

  var myXMLHTTPRequest; 

  function xmlLoaded() { 
    var myXMLDocument = myXMLHTTPRequest.responseXML; 
  } 

  function loadXML(){ 
    myXMLHTTPRequest = new XMLHttpRequest();

    myXMLHTTPRequest.open("GET", "data.xml", true);

    myXMLHTTPRequest.onload = xmlLoaded; 

    myXMLHTTPRequest.send(null); 
  } 

표 7은 Mozilla의 XMLHttpRequest의 메소드 및 속성 리스트이다.

표 7. XMLHttpRequest 메소드와 속성  

이름 설명
void abort() 여전히 실행 중이면 요청을 중단한다.  
string getAllResponseHeaders() 모든 응답 헤더를 하나의 스트링으로 리턴한다.  
string getResponseHeader(string headerName) 지정된 헤더의 값을 리턴한다.  
functionRef onerror 이것이 설정되었을 경우, 레퍼런스 함수는 요청 시 오류가 발생할 때 마다 호출된다.  
functionRef onload 이것이 설정되었을 경우, 요청이 성공적으로 수행되고 응답을 받으면 레퍼런스 함수가 호출된다. 비동기식 요청일 경우 사용한다.  
void open (string HTTP_Method, string URL)

void open (string HTTP_Method, string URL, boolean async, string userName, string password)  
HTTP 메소드로서 GET 또는 POST를 사용하여 지정된 URL에 대한 요청을 초기화한다. 요청을 보내려면 초기화 후에 send() 메소드를 호출한다. async가 false 라면 요청은 동기식이고, 그 외에는 기본적으로 비동기식이다. 선택 사항으로 주어진 URL에 사용자 이름과 패스워드를 설정할 수 있다.  
int readyState 다음은 요청 상태이다.    
0 UNINITIALIZED - open()이 아직 호출되지 않았음.
1 LOADING - send()가 아직 호출되지 않았음.
2 LOADED - send()가 호출되었고 헤더와 상태 모두 사용할 수 있다.
3 INTERACTIVE - 다운로드, responseText가 부분 데이터를 갖고 있다.
4 COMPLETED - 모든 연산이 완료되었다.
 
string responseText 응답을 포함하고 있는 스트링.  
DOMDocument responseXML 응답을 포함하고 있는 DOM 문서.    
void send(variant body) 요청을 시작한다. body가 정의되면, 이것은 POST 요청의 바디로서 보내진다. body는 XML 또는 XML 문서를 직렬화 한 스트링이 될 수도 있다.  
void setRequestHeader (string headerName, string headerValue) HTTP 요청에 사용될 HTTP 요청 헤더를 설정한다. open()이 호출된 후에 호출되어야 한다.  
string status HTTP 응답의 상태 코드.  

XSLT 차이점

Mozilla는 XSL Transformations (XSLT) 1.0을 지원한다. 자바스크립트가 XSLT를 변형할 수 있으며, 문서 상에 XPAT 실행도 가능하다.

Mozilla에서는 스타일시트와 XML mimetype(text/xml 또는 application/xml)을 갖고 있는 XML과 XSLT를 보내야 했다. XSLT가 Mozilla에서는 실행되지 않지만, Internet Explorer에서는 작동되기 때문이었다. Mozilla는 이 방식을 엄격히 준수한다.

Internet Explorer 5.0과 5.5는 XSLT의 실행 초안을 지원했다. 이것은 최종 1.0 권고안과는 매우 다르다. 어떤 버전으로 XSLT 파일이 쓰여졌는지를 구분할 수 있는 가장 쉬운 방법은 네임스페이슬 보는 것이다. 1.0 권고안의 네임스페이스는 http://www.w3.org/1999/XSL/Transform이다. 반면 초안 네임스페이스는 http://www.w3.org/TR/WD-xsl이다. Internet Explorer 6은 백워드 호환에 이 실행 초안을 지원한다. 하지만 Mozilla는 이를 지원하지 않는다.

XSLT에서 브라우저를 구별해야 한다면 "xsl:vendor" 시스템 속성을 쿼리하면 된다. Mozilla의 XSLT 엔진은 "Transformiix"를, Internet Explorer는 "Microsoft."를 리턴할 것이다.  

 
 
 <xsl:if test="system-property('xsl:vendor') = 'Transformiix'"> 
<!-- Mozilla specific markup --> 
 </xsl:if> 
 <xsl:if test="system-property('xsl:vendor') = 'Microsoft'"> 
 <!-- Internet Explorer specific markup --> 
 </xsl:if> 
 

Mozilla는 또한 XSLT용 자바스크립트 인터페이스를 제공하여 웹 사이트가 메모리에서 XSLT 변형을 수행할 수 있도록 한다. 글로벌 자바스크립트 XSLTProcessor 객체를 사용하면 된다. XSLTProcessor는 XML과 XSLT 파일을 로딩해야 하는데, 이는 DOM 문서들이 필요하기 때문이다. XSLTProcessor에서 반입된 XSLT 문서를 사용하여 XSLT 매개변수들을 조작할 수 있다. XSLTProcessortransformToDocument()를 사용하여 스탠드얼론 문서를 만들거나, transformToFragment()를 사용하여 문서를 만들 수 있다. 이것은 또 다른 DOM 문서에 쉽게 첨부될 수 있다.

 
var xslStylesheet; 
var xsltProcessor = new XSLTProcessor(); 

// load the xslt file, example1.xsl 
var myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xsl", false); 
myXMLHTTPRequest.send(null); 

// get the XML document and import!! it 
xslStylesheet = myXMLHTTPRequest.responseXML; 

xsltProcessor.import!!Stylesheet(xslStylesheet); 

// load the xml file, example1.xml 
myXMLHTTPRequest = new XMLHttpRequest(); 
myXMLHTTPRequest.open("GET", "example1.xml", false); 
myXMLHTTPRequest.send(null); 

var xmlSource = myXMLHTTPRequest.responseXML; 

var resultDocument = xsltProcessor.transformToDocument(xmlSource); 
 

XSLTProcessor를 만든 후에 XMLHttpRequest를 사용하여 XSLT 파일을 로딩한다. XMLHttpRequest의 responseXML 멤버에는 XSLT 파일의 XML 문서가 포함된다. 이것은 import!!Stylesheet로 전달된다. XMLHttpRequest를 다시 사용하여 변형되어야 할 소스 XML 문서를 로딩한다. 왜냐하면 그 문서는 XSLTProcessortransformToDocument 메소드로 전달되기 때문이다. 표 8은 XSLTProcessor 메소드 리스트이다.

표 8. XSLTProcessor 메소드  

메소드 설명
void import!!Stylesheet(Node styleSheet) XSLT 스타일시트를 반입한다. styleSheet 인자는 XSLT 스타일시트의 DOM 문서의 루트 노드이다.
DocumentFragment transformToFragment(Node source, Document owner) import!!Stylesheet 메소드를 사용하여 반입된 스타일시트를 사용하여 source 노드를 변형하고 DocumentFragment를 만든다. owner는 DocumentFragment가 어떤 DOM 문서에 속해야 하는지를 지정하면서 이것을 DOM 문서에 붙일 수 있는 속성으로 만든다.  
Document transformToDocument(Node source) import!!Stylesheet 메소드를 사용하여 반입된 스타일 시트를 사용하여 source 노드를 변형하고 스탠드얼론 DOM 문서를 리턴한다.  
void setParameter(String namespaceURI, String localName, Variant value) 반입된 XSLT 스타일시트에 매개변수를 설정한다.  
Variant getParameter(String namespaceURI, String localName) 반입된 엑셀시트 스타일시트에 매개변수 값을 얻는다.  
void removeParameter(String namespaceURI, String localName) 반입된 XSLT 스타일시트에서 설정된 모든 매개변수들을 제거하고 XSLT로 정의된 디폴트로 지정한다.  
void clearParameters() 모든 설정 매개변수들을 제거하고 XSLT 스타일시트에서 지정된 디폴트로 지정한다.  
void reset() 모든 매개변수들과 스타일시트를 제거한다.  






요약

애플리케이션을 모질라 기반 브라우저에서 실행하려고 할 때 발생하는 일반적인 문제들을 설명했다. 웹 애플리케이션을 개발할 때에는 여러 브라우저들의 차이점을 항상 생각하고 이해해야 한다. 아래 참고자료 섹션에서 크로스 브라우저 개발에 대한 자세한 내용을 참조하기 바란다.






참고자료

반응형