'분류 전체보기'에 해당되는 글 336건

DOM

2014. 12. 8. 15:03 나홀로스터디/JS For Web Dev


10장 DOM

이 포스팅은 "프론트엔드 개발자를 위한 자바스크립트(2013 인사이트, 한선용 옮김)"에서 발췌 요약한 것입니다.
 
- DOM을 노드의 계층 구조로 이해
- 다양한 노드타입
- 브라우저들 간의 비호환성을 우회하는 DOM 코딩



문서 객체 모델 DOM은 HTML과 XML 문서에 대한 애플리케이션 프로그래밍 인터페이스(API)다. 넷스케이프와 마이크로소프트에서 초기에 사용하던 동적 HTML을 계승한 DOM은 이제 진정으로 플랫폼과 언어에 독립적인 페이지 표현 및 조작 방법이 되었다.

DOM 레벨 1은 1998년 10월에 W3C 권고가 되었고 기본적인 문서구조와 쿼리 인터페이스를 제공한다.

※ 인터넷 익스플로러8 및 이전 버전에서는 DOM 객체를 COM 객체로 구현했다. 따라서 이들 객체는 네이티브 자바스크립트 객체와는 다른 방식으로 동작한다.

 

10.1 노드의 계층 구조
HTML과 XML 문서는 모두 DOM을 통해 노드의 계층 구조로 표현 가능하다. 노드 타입에는 여러가지가 있으며 각 노트 타입은 서로 다른 특징, 데이터, 메서드를 가지고 각 노드는 다른 노드와 관계가 있을 수도 있다. 이런 계층 구조를 생성하며 특정 노드에 뿌리(root)를 둔 트리 구조로 표현된다.

문서 요소는 문서의 최상위 요소로 문서 하나에 문서 요소 하나만 존재하며 다른 요소는 모두 이 안에 존재한다. HTML 페이지에서 문서 요소는 항상 <html> 요소이고 XML에서는 미리 지정된 문서 요소가 없으면 어떤 요소든 문서 요소가 될 수 있다.


10.1.1  Node 타입
Node 인터페이스는 자바스크립트에서 Node 타입으로 구현되며 인터넷 익스플로러를 제외한 모든 브라우저에서 Node 타입에 접근할 수 있다. 자바스크립트의 노드 타입은 모두 Node를 상속하므로 모든 노드 타입에서 같은 기본 프로퍼티와 메서드를 공유한다.
모든 노드에는 타입을 나타내는 nodeType 프로퍼티가 있고 노드 타입은 다음 12가지 숫자형 상수 중 하나이다

Node.ELEMENT_NODE(1)
Node.ARRTIBUTE_NODE(2)
Node.TEXT_NODE(3)
Node.CDATA_SECTION_NODE(4)
Node.ENTITY_REFERENCE_NODE(5)
Node.ENTITY_NODE(6)
Node.PROCESSING_INSTRUCTION_NODE(7)
Node.COMMENT_NODE(8)
Node.DOCUMENT_NODE(9)
Node.DOCUMENT_TYPE_NODE(10)
Node.DOCUMENT_FRANMENT_NODE(11)
Node.NOTATION_NODE(12)


nodeName, nodeValue 프로퍼티
nodeName과 nodeValue 프로퍼티는 해당 노드의 정보를 제공한다. 프로퍼티 값은 노드 타입에 따라 완전히 다르므로 이 값을 사용하기 전에 항상 노트 타입을 테스트하길 권장한다.

if (someNode.nodeType == 1){
  value = someNode.nodeName;  // 요소의 태그 이름
} 

노드가 요소라면 nodeName 값을 변수에 할당한다. 요소의 nodeName은 항상 요소의 태그 이름과 일치하며 nodeValue는 항상 null이다.

 

노드 사이의 관계
모든 노드는 다른 노드와 관계가 있다. 각 노드에는 childNodes 프로퍼티가 있는데 이 프로퍼티에는 NodeList가 저장된다. NodeList는 배열 비슷한 객체인데 노드를 순서 있는 목록으로 저장하여 위치 기반으로 접근할 수 있다. NodeList에 length 프로퍼티가 있고 저장된 데이터를 대괄호 표기법으로 접근할 수 있긴 하지만 NodeList는 Array의 인스턴스가 아니다. NodeList 객체는 사실 DOM 구조에 대한 쿼리 결과이며 문서가 바뀌면 NodeList 객체에도 자동으로 반영되어 '살아있는' 객체라고 부르기도 한다.

각 노드에는 문서 트리에서 부모를 가리키는 parentNode 프로퍼티가 있고 childNodes 목록의 각 노드는 형제 관계이다. 같은 목록에 있는 노드 사이를 previousSiblingnextSibling 프로퍼티로 이동할 수 있다. 그 외에 편리한 메서드로 hasChildNodes()가 있는데 이 메서드는 노드에 자식 노드가 있다면 true를 반환하며 매번 childNodes 목록에서 length를 호출하는 것보다 효과적이다.
ownerDocument 프로퍼티는 전체 문서를 표현하는 문서 노드에 대한 포인터이다.

※ 노트 타입이 모두 Node를 상속하긴 하지만 노드 타입이 모두 자식 노드를 가질 수 있는 건 아니다.


노드조작
노드 사이의 관계 포인터는 모두 읽기 전용이므로 노드를 조작하는 메서드는 따로 있다. 가장 자주 쓰이는 메서드는 appendChild()인데 이 메서드는 childNodes 목록에 노드를 추가하고 새로 추가한 노드, 부모 노드, childNodes 목록에 포함된 모든 관계 포인터가 업데이트 되면 appendChild()는 새로 추가한 노드를 반환한다.

한 노드를 childNodes 목록 마지막이 아니라 특정 위치로 옮겨야 할 때insertBefore() 메서드를 사용한다. insertBefore() 메서드는 삽입할 노드기준 노드 두 가지를 매개변수로 받는데 삽입한 노드는 기준 노드의 이전 형제가 되며 이동이 끝나면 메서드는 삽입한 노드를 반환한다. 기준 노드가 null 이라면 insertBefore()는 appendChild()와 똑같이 동작한다.

appendChild()와 insertBefore()는 모두 기존의 노드를 제거하는 일 없이 삽입하기만 하는 반면 replaceChild() 메서드는 기존 노드를 교체한다.  replaceChild() 메서드는 매개변수로 삽입할 노드(A)와 교체할 노드(B) 두 개를 받아서 B를 문서 트리에서 제거해 반환하며 B가 있던 자리에 A를 대신 삽입한다. replaceChild()로 노드를 삽입하면 B의 관계 포인터를 모두 A에 복사한다.

노드를 제거할 때removeChild() 메서드를 사용한다. 이 메서드는 제거할 노드 하나만 매개변수로 받는데 제거된 노드는 함수 값으로 반환된다.

이들 네가지 메서드는 모두 특정 노드의 자식에서만 동작하므로 parentNode 프로퍼티에 해당하는 부모 노드를 정확히 알아야 한다.

 

기타 메서드
cloneNode() 메서드는 자신을 호출한 노드의 복제본을 생성한다. cloneNode() 메서드는 매개변수를 하나 받는데 이는 자손 노드까지 복제할지 나타내는 불리언으로 true를 넘기면 자손 노드 전체를 복제하며 false를 넘기면 해당 노드 하나만 복제한다.복제된 노드는 appendChild()나 insertBefore(), replaceChild()를 통해 문서에 추가하기 전에는 트리 안에 존재하지 않는다.

※ cloneNode() 메서드는 이벤트 핸들러처럼 DOM 노드에 추가한 자바스크립트 프로퍼티는 복사하지 않는다. 이 메서드는 속성과 자식 노드만 복사하며 다른 것은 모두 사라진다. 인터넷 익스플로러에는 이벤트 핸들러까지 복제하는 버그가 있으므로 복제하기 전에 이벤트 핸들러를 모두 제거하길 권한다.


 

10.1.2 Document 타입
자바스크립트는 문서 노드를 Document 타입으로 표현한다. 브라우저에서 전체 HTML 페이지를 표현하는 문서 객체는 HTMLDocument의 인스턴스이며 HTMLDocument는 Document를 상속한다. document 객체는 window의 프로퍼티이므로 전역에서 접근할 수 있다.  Document 노드에는 다음 특징이 있다.

- nodeType은 9이다.
- nodeName은 "#document"이다.
- nodeValue는 null이다
- parentNode는 null이다
- ownerDocument는 null이다
- 자식 노드로 DocumentType(최대 1개) Element(최대 1개), Processing Instruction, Comment를 가질 수 있다.


Document 타입은 HTML 페이지 또는 XML 기반 문서를 표현하며 가장 자주 쓰이는 용도는 document 객체를 통한 HTMLDocument의 인스턴스이다.

※  파이어폭스와 사파리, 크롬, 오페라에서는 스크립트에서 Document 타입 생성자 및 프로토타입에 접근할 수 있다. 인터넷 익스플로러는 버전 9에서도 Document를 노출하지 않는다. HTMLDocument 타입 생성자 및 프로토타입은 인터넷 익스플로러 버전 8 이후 및 기타 브라우저에서 접근할 수 있다.



Document의 자식 노드
DOM 명세에서는 Document 노드가 자식으로 DocumentType, Element, ProcessingInstruction, Comment를 가질 수 있다고 명시하는데 그중 두 가지 자식 노드에는 단축 표기도 있다. 첫 번째는 documentElement 프로퍼티인데 이는 항상 HTML 페이지의 <html> 요소를 가리킨다.  childNodes 목록에는 항상 document 요소가 있지만 documentElement 프로퍼티는 해당 요소에 더 빨리 더 직접적으로 접근한다.

document 객체는 HTMLDocument 의 인스턴스이므로 <body> 요소를 직접적으로 가리키는 body 프로퍼티를 갖는다. 주요 브라우저는 모두 document.documentElementdocument.body를 둘 다 지원한다. Document가 가질 수 있는 또다른 자식 노드는 DocumentType이다. <!DOCTYPE> 태그는 문서의 다른 부분과는 별도의 엔티티로 간주하며 포함된 정보는 doctype 프로퍼티(브라우저에서는 document.doctype)를 통해 접근할 수 있지만 브라우저마다 document.doctype을 달리 지원하므로 유용하게 쓰기 어렵다.
<html> 요소 밖에 있는 주석은 기술적으로는 문서의 자식 노드이지만 브라우저마다 다르게 처리한다.


문서정보
document 객체는 HTMLDocument의 인스턴스이므로 표준 Document 객체에는 현재 불러드린 웹 페이지에 대한 프로퍼티를 갖는다. title 프로퍼티는 브라우저 창 또는 탭의 제목인 <title> 요소 텍스트가 들어 있다. 이 프로퍼티로 현재 페이지 제목을 읽을 수 있고 설정도 가능한데 title 프로퍼티의 값을 바꿔도 <title> 요소는 변함이 없다.


요소 위치
DOM 관련해서 가장 자주 하는 일은 특정 요소나 요소 그룹에 대한 참조를 얻는 일인데 document 객체에는 getElementById()getElementsByTagName() 두가지 메서드를 제공한다. getElementById() 메서드는 찾으려는 요소 ID를 매개변수로 받고 해당 요소를 찾아 반환하며 그런 ID 요소가 존재하지 않으면 null을 반환한다.
getElementByTagName() 메서드는 요소의 태그 이름을 매개변수로 받고 해당하는 요소가 담긴 NodeList를 반환한다.

var images = document.getElementByTagName("img"); 

HTMLCollection 객체는 images 변수에 저장되고 객체에 담긴 요소 숫자는 length 프로퍼티에 저장된다. HTMLCollection 객체에는 namedItem() 메서드도 있는데 이 메서드는 name 속성을 통해 컬렉션 데이터에 대한 참조를 얻는다. HTMLCollection 객체에서는 대괄호 표기법에 숫자형 색인과 문자형 색인을 모두 쓸수 있는데 숫자형 색인을 쓰면 이면에서 item()을 호출하고 문자열 색인을 쓰면 namedItem()을 호출한다.

※ 명세에서는 태그 이름이 대소문자를 구분하는 것으로 정의되어 있지만 getElementByTagName() 메서드는 기존의 HTML 페이지와 최대한 호환되게 하기 위해 대소문자를 구분하지 않는다. XHTML이나 XML페이지에서는 getElementByTagName() 메서드가 대소문자를 구분한다.

세번째 메서드는 HTMLDocument 타입에만 정의된 getElementByName()으로 name 속성 값이 주어진 문자열에 일치하는 요소를 반환한다. getElementByTagName()와 마찬가지로 getElementByName() 메서드 역시 HTMLCollection을 반환한다. name() 메서드는 항상 첫 번째 버튼만 가져오는데 name 속성이 모두 같기 때문이다.


특별한 컬렉션

document.anchors - name 속성이 있는 <a> 요소를 모두 가져온다
document.form - <form> 요소를 모두 가져온다. document.getElementsByTagName("form")과 같다
document.images - <img> 요소를 모두 가져온다. document.getElementsByTagName("img")와 같다.
document.links - href 속성이 있는 <a> 요소를 모두 가져온다.



문서에 쓰기
웹페이지에 출력을 직접 조작하는 기능을 담당하는 메서드는 write(). writeIn(), open(), close() 네 가지다. write(), writeIn() 메서드는 문자열을 매개변수로 받는데 write()는 넘겨 받은 텍스트를 그대로 추가하고, writeIn()은 줄바꿈 문자(\n)를 마지막에 추가한다.

※ XHTML 문서에서는 문서에 쓰는 기능을 지원하지 않는다. application/xml_xhtml 마임 타입으로 전송되는 페이지에서는 이 메서드가 동작하지 않는다.

 


10.1.3 Element 타입
Element 타입은 XML/HTML 요소를 표현하며 이를 통해 태그 이름이나 자식, 속성 같은 정보에 접근 가능하다.

nodeType은 1이다.
nodeName은 요소의 태그 이름이다.
nodeValue는 null이다.
parentNode는 Document 또는 Element이다.
자식 노드로 Element나 Text, Comment, ProcessingInstruction, CDATA Section, EntityRefernce를 가질수 있다.

요소의 태그 이름은 nodeName 프로퍼티나 tagName 프로퍼티로 얻을수 있고 두 프로퍼티는 같은 값을 반환하는데 후자가 더 직관적이다.
HTML에서 tagName을 사용하면 태그 이름은 항상 대문자로 반환되므로 element.tagName.toLowerCase()를 사용하는 것이 안전하다

※ Element 타입 생성자와 프로토타입은 인터넷 익스플로러 버전 8을 포함해 모든 최신 브라우저에서 스크립트를 통해 접근할 수 있다. 사파리 버전2 미만이나 오페라 버전 8미만 같은 오래된 브라우저는 Element 타입 생성자를 스크립트에 노출하지 않는다.


HTML 요소
HTML요소는 모두 HTMLElement 타입을 통해 표현된다. HTMLElement는 Element를 직접적으로 상속하며 몇가지 프로퍼티가 추가되는데 각 프로퍼티는 모든 HTML 요소에서 사용가능한 표준 속성중 하나를 나타낸다.

id - 요소의 고유한 식별자
title - 요소에 대한 추가 정보, 일반적으로 툴팁으로 표현된다.
lang -  요소 콘텐츠의 언어 코드
dir - 언어의 표기 방향
className -  요소의 CSS 클래스인 class 속성을 나타냄, class가 ECMAScript의 예약어이기 때문에 class라고 부르지 못함

각 프로퍼티는 속성 값을 읽는 용도로도, 값을 설정하는 용도로도 사용한다.


속성얻기
속성에 대한 DOM 메서드는 getAttribute(), setAttribute(), removeAttribute() 이다.
getAttribute()에는 속성 이름을 그대로 써야 하고 주어진 속성이 존재하지 않으면 항상 null을 반환한다. getAttribute() 메서드는 HTML 언어에 공식적으로 포함되지 않는 커스텀 속성의 값을 가져오는 데도 쓸 수 있다.
요소 속성은 모두 DOM 요소 객체의 프로퍼티를 통해서도 접근할 수 있다. HTMLElement에 정의된 다섯 가지 프로퍼티는 해당 속성과 직접 연결되며, 그 외에도 브라우저에서 인식하는(커스텀이 아닌) 속성은 모두 객체 프로퍼티로 추가된다.

두번째 속성은 onclick 같은 이벤트 핸들러 속성인데 요소의 onclick 속성은 자바스크립트 코드이며 getAttribute()는 해당 코드 문자열을 반환한다. 반면 onclick 프로퍼티는 이벤트 처리 프로퍼티가 자신에게 할당된 함수에 접근할 수 있기 때문에 자바스크립트 함수를 반환하고 해당 속성이 없을 때는 null을 반환한다.
이런 차이로 개발자들은 DOM을 다룰 때 객체 프로퍼티를 사용하고 getAttribute() 메서드는 주로 커스텀 속성의 값을 가져올 때 사용한다.


속성 설정
getAttribute()의 형제 메서드인 setAttribute()는 속성 이름과 설정할 값 두 가지를 매개변수로 받는다. 속성이 존재하면 setAttribute()는 해당 속성의 값을 교체하며 존재하지 않을 때는 속성을 새로 생성하고 값을 설정한다. setAttribute() 메서드는 HTML 속성과 커스텀 속성을 같은 방식으로 다룬다. 속성은 모두 프로퍼티이므로 프로퍼티에 직접 할당하는 것은 속성 값을 설정하는것과 마찬가지다.
커스텀 프로퍼티를 추가하면 대부분의 브라우저에서 요소 속성이 되지 않지만 인터넷 익스플로러에서는 가능하다.

※ 인터넷 익스플로러 7 및 이전 버전에서는 setAttribute()가 좀 이상하게 동작한다. class나 style속성을 설정해도 효과가 없으며 setAttribute()로 이벤트 핸들로 프로퍼티를 설정하려 해도 아무 효과가 없다. 이 문제가 인터넷 익스플로러8에서 고쳐지긴 했지만 이들 속성을 설정할 때는 항상 프로퍼티를 이요하는 편이 좋다.


removeAttribute() 메서드는 속성의 값만 지우는 것이 아니라 요소에서 속성을 완전히 제거한다.

※ 인터넷 익스플로러 6 이전버전은 지원하지 않는다.

 

attributes 프로퍼티
Element 타입은 DOM 노드 타입 중에서 attribute 프로퍼티를 갖는 유일한 타입이다. attribute 프로퍼티에는 "살아있는" 컬렉션(NodeList와 비슷한) NamedNodeMap이 저장된다. 요소의 속성은 모두 Attr 노드로 표현되며 각 Attr 노드는 NameNodeMap객체에 저장된다.

getNamedItem(name) - nodeName 프로퍼티가 name인 노드를 반환한다.
removeNamedItem(name) - nodeName 프로퍼티가 name인 노드를 목록에서 제거한다.
setNamedItem(node) - node를 목록에 추가하고 nodeName 프로퍼티에 따라 색인한다
item(pos) - 인덱스가 pos인 노드를 반환한다.

attributes 프로퍼티 안의 각 노드는 nodeName이 속성 이름이며 nodeValue는 속성 값이다.

element.attributes.getNamedItem("id").nodeValue
element.attributes["id"].nodeValue; 

removeNamedItem() 메서드는 요소의 removeAttribute() 메서드와 마찬가지로 주어진 이름의 속성을 제거한다.
setNamedItem() 메서드는 속성 노드를 넘겨 요소에 새 속성을 추가하는 메서드인데 속성 메서드보다는 getAttribute(). removeAttribute(), setAttribute() 메서드가 더 많이 쓰인다.


요소 생성
document.ceateElement() 메서드를 통해 새 요소를 생성할 수 있다. 이 메서드는 생성할 요소의 태그 이름 하나만 매개변수로 받는다. createElement() 메서드는 새 요소를 생성하고 ownerDocument 프로퍼티를 설정한다.

인터넷 익스플로러7 및 이전 버전에서 동적으로 요소를 생성할 때 발생하는 문제점은 다음과 같다.

- 동적으로 생성한 <iframe> 요소의 name 속성을 설정할 수 없다.
- 동적으로 생성한 <input> 요소는 폼의 reset() 메서드로 리셋되지 않는다.
- 동적으로 생성한 <button> 요소에 타입 속성 "reset"이 있어도 이 버튼은 폼을 리셋하지 못한다.
- 동적으로 생성한 라디오 버튼은 같은 name 속성의 라디오 버튼과 연결되지 않는다.

인터넷 익스플로러7 및 이전 버전의 이런 문제는 createElement()에 완전한 HTML 태그를 넘겨서 해결 가능하다


요소의 자식
요소는 자식 요소나 자손 요소를 가질 수 있으며 그 숫자에는 제한이 없다. 특정 태그 이름의 자식 노드나 자손 요소를 가져올 때는 getElementByTagName() 메서드도 사용한다. 이 메서드를 요소에서 호출하면 document에서 호출한 것과 똑같이 동작하지만 해당 요소에서 검색을 시작한다는 점만 다르며 따라서 자손 요소만 반환한다.



10.1.4 Text 타입
Text 노드는 Text 타입으로 표현된다. 이 노드는 평범한 텍스트가 포함되고 글자 그대로 사용되며 이스케이프된 HTML 문자는 포함할 수 있지만 HTML 코드는 포함할 수 없다.

- nodeType은 3이다.
- nodeName은 "#text"이다.
- nodeValue는 노드에 포함된 텍스트이다
- parentNode는 Element 이다.
- 자식 노드를 가질 수 없다.

Text 노드에 포함된 텍스트는 nodeValue 프로퍼티나 data 프로퍼티로 가져올 수 있으며 두 프로퍼티에는 같은 값이 저장되고 nodeValue나 data 둘 중 하나를 바꾸면 노드에 반영된다.

- appendData(text) - 노드 마지막에 text를 추가한다.
- deleteData(offset, count) - offset부터 count 만큼 삭제한다.
- insetDate(offset, text) - offset 위치에 text를 삽입한다.
- replaceData(offset, count, text) - offset부터 (offset + count)까지의 텍스트를 text로 교체한다.
- splitText(offset) - offset 위치를 기준으로 텍스트 노드를 둘로 나눈다.
- substringData(offset, count) - offset 위치부터 (offset + count) 까지의 텍스트를 꺼낸다.

이들 메서드 외에도 length 프로퍼티도 지원되며 노드의 글자 개수를 반환한다. 이값은 nodeValue.length나 data.length와 같다.


텍스트 노드 생성
새 텍스트 노드를 생성할 때는 document.createTextNode() 메서드를 사용한다. 이 메서드는 매개변수로 삽입할 텍스트를 받는다. 새 텍스트 노드를 생성하면 ownerDocument 프로퍼티가 설정되지만 문서 트리에 삽입하기 전에는 브라우저 창에 표시되지 않는다. 텍스트 토드를 다른 텍스트 노드의 형제로 추가하면 두 텍스트 노드는 사이의 공백이 없는것으로 표시된다.


텍스트 노드 통일
형제 텍스트 노드를 하나로 합치는 메서드로 normalize()가 있고 Node 타입에 존재하므로 모든 노드에서 사용가능하다. 노드에서 normalize()를 호출하면 자식 노드를 텍스트 노드 하나로 병합하며 합쳐진 텍스트 노드의 nodeValue는 각 텍스트 노드의 nodeValue 프로퍼티를 하나로 합친 값과 같다.  브라우저가 문서를 파싱하면 형제 텍스트 노드는 생성되지 않고 DOM을 조작할 때만 생긴다.

※ 인터넷 익스플로러 6에서는 normalize() 메서드가 간혹 충돌한다. 확인할 수는 없었지만 이 문제는 패치를 통해 수정되었을수 있다.


텍스트 노드 분할
Text 타입에는 normalize() 의 반대 역할을 하는 splitText() 메서드가 있다. 이 메서드는 주어진 오프셋을 기준으로 텍스트 노드를 둘로 나눈다. 이 메서드가 반환하는 새 텍스트 노드의 parentNode는 원래 텍스트 노드의 parentNode와 같다. 텍스트 노드 분할은 텍스트 노드에서 데이터를 추출하는 DOM 파싱 테크닉에서 가장 자주 쓰인다.



10.1.5 Comment 타입
주석은 DOM에서 Comment 타입으로 표현된다.

- nodeType는 8이다.
- nodeName은 "#comment"이다.
- nodeValue는 주석 콘텐츠이다
- parentNode는 Document  또는 Element이다.
- 자식 노드는 가질 수 없다.

Commenet 타입은 Text 타입과 같은 원형을 상속하므로 Text 타입에 있는 문자열 메서드를 대부분 갖고 있는데 splitText()는 예외다. 또한 Text 타입과 마찬가지로 nodeValue나 data 프로퍼티로 주석의 콘텐츠를 가져올 수 있다.

※ Comment 타입 생성자와 프로토타입에 접근할 수 잇는 브라우저는 파이어폭스, 사파리, 크롬, 오페라다. 인터넷 익스플로러8은 태그 이름에 "!"가 들어가는 요소를 주석 노드로 간주한다. 즉 getElementsByTagName()이 주석 노드를 반환할 수 있다는 뜻이다. 인터넷 익스플로러 9에서는 커스텀 생성자 HTMLCommentElement가 주석을 나타낸다. 이 생성자에서 주석을 요소로 취급하는건 아니다.




10.1.6 CDATASection 타입
CDATA 섹션은 XML 기반 문서 전용이며 CDATASection 타입으로 표현된다. Comment와 마찬가지로 CDATASection 타입 역시 Text 타입과 같은 원형을 상속하므로 splitText()를 제외한 문자열 메서드를 모두 가진다. CDATASection 노드에는 다음 특징이 있다.

- nodeType은 4이다.
- nodeName은 "#cdata-section"이다.
- nodeValue는 CDATA 섹션의 콘텐츠이다.
- parentNode는 Document 또는 Element이다.
- 자식 노드는 가질 수 없다.

CDATA 섹션은 XML 문서에서만 유효하므로 대부분의 브라우저에서 CDATA 섹션을 부정확한 Comment 나 Element 로 잘못 파싱한다.

※ CDATASection  타입 생성자와 프로토타입에 접근할 수 잇는 브라우저는 파이어폭스와 사파리, 크롬, 오페라다. 인터넷 익스플로러는 버전 9까지 아직 이 타입을 지원하지 않는다.




10.1.7 DocumentType 타입
DocumentType 타입은 자주 쓰이지 않으며 이를 지원하는 웹 브라우저는 파이어폭스와 사파리, 오페라 뿐이다.

- nodeType은 10이다
- nodeName은 독타입 이름이다.
- nodeValue는 null이다.
- parentNode는 Document이다.
- 자식 노드는 가질 수 없다.




10.1.8 DocumentFragment 타입
DocumentFragment 타입은 마크업에 표현되지 않는 유일한 노드 타입이다. DOM에서는 문서 버퍼를 노드를 가지며 조작할 수 있을 뿐이고 그 외 복잡한 기능은 전부 제거된 "경량화된" 문서로 정의한다.

- nodeType은 11이다.
- nodeName은 "#document-fragment"이다.
- nodeValue는 null이다.
- parentNode는 null이다.
- 자식노드로 Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference를 가질수 있다.

문서 버퍼는 document.createDocumentFragment() 메서드로 생성하고 콘텐츠는 appendChild(), insetBefore()로 문서에 추가한다.



10.1.9 Attr 타입
요소의 속성은 DOM에서 Attr 타입으로 표현된다. Attr 타입 생성자와 프로토타입에 접근할 수 있는 브라우저는 인터넷 익스플로러 버전 8 이후 브라우저이고 기술적으로 속성은 요소의 attributes 프로퍼티 안에 존재하는 노드이다.

- nodeType은 11이다.
- nodeName은 속성이름이다.
- nodeValud는 속성 값이다.
- parentNode는 null이다.
- HTML에서는 자식노드를 가질 수 없다.
- XML에서는 자식 노드로 Text, EntityReference를 가질 수 있다.

Attribute 노드를 직접 참조하는 경우는 드물며 개발자들은 보통 getAttribute(), setAttribute(), removeAttribute()를 더 선호한다.
Attr 객체에는 세 가지 프로퍼티가 있는데 name은 속성 이름이며 nodeName과 같다. value는 속성 값이고 nodeValue와 같다. specified는 해당 속성이 코드에 명시되었는지 기본 값인지 나타내는 불리언이다.
새 attribute 노드를 생성할 때는  document.createAttribute()에 속성 이름을 넘겨 호출한다.

 


10.2 DOM 다루기

10.2.1 동적 스크립트
동적 스크립트에는 외부 파일을 불러오거나 텍스트를 직접 삽입하는 두 가지 방법이 있다. 동적으로 외부 파일을 불러오는 과정은 <scrtipt> 요소를 사용하는 것이고 직접 삽입하는 방법은 인라인 스크립트이다.


10.2.2 동적 스타일
css 스타일을 HTML 페이지에 삽입하는 요소는 두 가지이다. <link> 요소는 외부 CSS 파일을 불러올 때 사용하고 <style> 요소는 인라인 스타일에 사용한다. DOM 코드로 생성하는 link 요소가 제대로 동작하려면 body가 아니라 <head> 요소에 추가해야 한다.
스타일을 정의하는 다른 방법은 <style> 요소로 인라인 CSS 를 사용하는 것이 있는데 인터넷 익스플로러는 <style> 노드를 특별 취급하여 자식 노드에 대한 접근을 허용하지 않기 때문에 styleSheet를 써야한다. 이 프로퍼티에는 cssText라는 프로퍼티가 존재하며 이를 통해 css 코드를 설정할 수 있다.


10.2.3 테이블 조작
<table> 요소는 DOM 코어 메서드로 생성하기 어렵기 때문에 공식화할 수 있게끔 몇가지 프로퍼티와 메서드를 추가했다.

<table> 요소에 추가된 내용

- caption - <caption> 요소를 가리키는 포인터이다.
- tBodies - <tbody> 요소의 HTMLCollection이다.
- tBoot - <tfoot> 요소를 가리키는 포인터이다.
- tHead - <thead> 요소를 가리키는 포인터이다.
- rows - 테이블의 모든 행에 대한 HTMLCollection 이다.
- createThead() - <thead> 요소를 생성해 테이블에 삽입하고 그 참조를 반환한다.
- createTFoot() - <tfoot> 요소를 생성해 테이블에 삽입하고 그 참조를 반환한다.
- createCaption() - <caption> 요소를 생성해 테이블에 삽입하고 그 참조를 반환한다.
- deleteTHead() - <thead> 요소를 삭제한다.
- deleteTFoot() - <tfoot> 요소를 삭제한다.
- deleteCaption() - <caption> 요소를 삭제한다.
- deleteRow() - 주어진 위치의 행을 삭제한다.
- insertRow(pos) - rows 컬렉션에서 주어진 위치에 행을 삽입한다.


<tbody> 요소에 추가된 내용

- rows - <tbody> 요소에 포함된 행의 HTMLCollection이다.
- deleteRow(pos) - 주어진 위치의 행을 삭제한다.
- insertRow(pos) - rows 컬렉션에서 주어진 위치에 행을 삽입하고 그에 대한 참조를 반환한다.


<tr> 요소에 추가된 내용

- cells - <tr> 요소에 포함된 셀의 HTMLCollection이다.
- deleteCell(pos) - 주어진 위치의 셀을 삭제한다.
- insertCell(pos) - cells 컬렉션의 주어진 위치에 셀을 삽입하고 새 셀에 대한 참조를 반환한다.




10.2.4 노드리스트 사용
NodeList 객체와 이와 관련된 NamedNodeMap, HTMLCollection을 이해하면 DOM을 전체적으로 이해하는데 큰 도움이 된다. 문서 구조가 바뀔 때마다 컬렉션도 업데이트되므로 항상 정확한 정보를 반환한다는 뜻으로 NodeList 객체는 해당 객체에 접근할 때마다 수행되는 쿼리라고 말할수 있다.

 

 

 


 

'나홀로스터디 > JS For Web Dev' 카테고리의 다른 글

이벤트  (0) 2015.01.07
DOM 확장  (0) 2014.12.18
클라이언트 감지  (0) 2014.11.20
브라우저 객체모델  (0) 2014.11.12
함수 표현식  (0) 2014.10.23

문서 스크립팅

2014. 11. 26. 17:05 나홀로스터디/JS 완벽가이드

15장 문서 스크립팅

이 포스팅은 "자바스크립트 완벽 가이드(인사이트, 송인철,이동기,이유원,황인석 옮김)"에서 발췌 요약한 것입니다.
 
15.1 동적인 문서 내용
15.2 Document의 프로퍼티
15.3 레거시 DOM : Document 객체의 집합
15.4 W3C DOM의 개요
15.5 문서순회
15.6 문서 내 엘리먼트 찾기
15.7 문서 수정하기
15.8 문서에 새로운 내용 추가하기


클라이언트 측 자바스크립트는 정적인 HTML문서를 대화식 웹 애플리케이션으로 만들기 위해 존재한다.
모든 웹 브라우저 창(또는 프레임)은 HTML 문서를 화면에 나타내고 Window 객체는 이 창을 표현하기 위한 객체이며 여기에는 Document 객체를 참조하는 document 프로퍼티가 있다.
Document Object Model(DOM)은 문서를 구성하는 객체에 어떻게 접근할 것인가를 정의하는 API다.


15.1 동적인 문서 내용
Document 객체에 있는 write() 메서드는 두가지 방법으로 사용할 수 있는데 첫 번째 방법은 현재 파싱되고 있는 문서에 HTML을 출력하기 위해 스크립트 안에서 이 메서드를 사용하는 것이다. 하지만 현재 문서에 HTML을 출력하기 위해 write()를 사용하는 것은 이 문서가 파싱되는 동안에만 가능하기 때문에 document.write()를 <script> 태그에 있는 최상위 레벨의 코드 안에서만 호출할 수 있다.
다른 창이나 프레임에 완전히 새로운 문서를 생성하기 위해 (Document 객체의 open()과 close() 메서드와 함께) 이 write() 메서드를 사용할 수 있다. 일반적으로 문서는 이벤트 처리기 안에서 절대 자신에 대해 write()를 호출해서는 안된다.

write() 메서드는 두 개 이상의 전달인자를 받을 수 있다.
Document 객체는 writeIn() 메서드를 지원한다. 이 메서드는 전달인자를 출력한 후 끝에 줄바꿈 문자를 붙여 넣는다는 점만 제외하면 write() 메서드와 동일하다.

 


15.2 Document의 프로퍼티

bgColor
문서의 배경색이다. 이 프로퍼티는 <body> 태그의 bgcolor(권장하지 않는 프로퍼티) 어트리뷰트다.


cookie
자바스크립트 프로그램이 HTTP 쿠키를 읽거나 쓸 수 있게 해주는 특수한 프로퍼티다.


domain
이 프로퍼티는 같은 인터넷 도메인 안에 있는 서로 신용하는 웹 서버의 웹 페이지들끼리 서로 정보를 주고받을 때 동일 출처 정책을 완화할 수 있게 해준다.


lastModified
문서가 수정된 날자를 저장한 문자열이다.


location
URL 프로퍼티와 동의어인데 지금은 제외되었다.


referrer
웹 브라우저를 현재 페이지로 연결시켜준 링크가 있는 문서의 URL이다.


title
현재 문서의 <title>과 </title> 태그 사이에 있는 텍스트다.


URL
문서가 위치한 주소가 어디인지 나타내는 문자열이다. 이 프로퍼티의 값은 서버 리다이렉트(redirect)가 발생한 경우를 제외하면 Window 객체의 location.href 프로퍼티와 같다.

 

 

15.3 레거시 DOM : Document 객체의 집합
배열값을 가지는 Document 객체의 집합 프로퍼티들은 레거시(legacy) DOM의 심장부다.


anchors[]
문서 내의 앵커들을 표현하는 Anchor 객체의 배열이다. (앵커란 문서 내에서 이름이 붙여진 위치, <a>태그에 href 대신 name 어트리뷰트를 적어서 생성한다) Anchor 객체의 name 프로퍼티 값은 태그에 있는 name 어트리뷰트의 값이다.


applets[]
문서 내의 자바 애플릿을 표현하는 Applet 객체의 배열이다.


forms[]
문서 내의 <form> 원소를 표현하는 Form 객체의 배열이다. 각 Form 객체에는 폼 내에 포함되어 있는 폼 원소들을 표현하는 집합 프로퍼티인 elements[ ]가  있다. Form 객체는 폼이 제출되기 전에 onsubmit 이벤트 처리기를 호출한다.


imgaes[]
문서 내의 <img> 원소를 표현하는 Image 객체의 배열이다. Image 객체의 src 프로퍼티는 읽고 쓸수 있는 프로퍼티이고, 어떤 URL을 이 프로퍼티에 할당하면 브라우저가 새로운 이미지를 읽어 들여 화면에 표시한다.


links[]
문서 내의 하이퍼텍스트 링크를 표현하는 Link 객체의 배열이다. 하이퍼텍스트 링크는 <a> 태그와, 경우에 따라서는 클라이언트 측 이미지 맵에 있는 <area> 태그를 통해 생성된다. Link 객체의 href 프로퍼티는 <a> 태그의 href 어트리뷰트에 해당하고 이 어트리뷰트의 값은 링크의 URL이다. 또한 Link 객체는 protocol, hostname, pathname 같은 프로퍼티를 통해 URL의 다양한 컴포넌트를 사용할 수 있게 한다.

이 프로퍼티들의 원소 각각은 문서의 소스코드에 나타나는 순서대로 저장된다.
레거시 DOM의 집합에 속하는객체들을 사용해 스크립팅 할 수는 있찌만 이를 사용하여 문서의 구조를 변경할 수는 없다는 사실을 이해하는 것이 중요하다.

 


15.3.1 Document 객체 이름 짓기
번호로 인덱싱되는 Document 객체의 집합에서 생기는 문제점은 위치 기반의 인덱스가 잘못 사용되기 쉽다는 것이다. 이를 해결하기 위한 안정적인 방법은 문서 내의 중요한 원소에 이름을 부여한 후 이런 원소에 접근할 때는 각 원소에 부여된 이름을 사용하는 것이다.

<form name="f1"><input type="button" value="Push Me"></form>
document.forms[0]; // 문서 내의 위치를 통해 폼을 참조 document.forms.f1;  // 프로퍼티로 이름을 통해 폼을 참조 document.forms["f1"]  // 배열 인덱스로 이름을 통해 폼을 참조

<form>이나 <img>, <applet>(<a> 태그에는 해당되지 않는다)의 name 어트리뷰트를 설정하는 것은 각각에 해당하는 Form이나 Image, Applet 객체(Link나 Anchor 객체에는 해당되지 않는다)를 Document 객체의 프로퍼티로서 접근할 수 있게 해준다.

document.f1 

만약 한 문서에서 두 원소의 name 어트리뷰트 값이 같으면 프로퍼티는 두 원소에 대한 참조를 가지는 배열이 된다. 일반적으로 HTML 폼에서 서로 관련된 라디오 버튼의 이름이나 체크박스의 이름은 같다. 이렇게 하면 이 이름은 라디오 버튼과 체크 박스들을 가지는 Form 객체의 프로퍼티가 되고, 이 프로퍼티의 값은 다양한 라디오 버튼이나 체크 박스 객체들에 대한 참조를 가진 배열이 된다.

 

15.3.2 Document 객체에 대한 이벤트 처리기
사용자와 정보를 주고받기 위해서는 HTML문서나 이 문서 내의 원소들이 사용자 이벤트에 반응할 수 있어야 한다.
document.links와 같이 객체 집합을 통해 접근되는 Document 객체에는 HTML 태그의 어트리뷰트에 해당하는 프로퍼티가 있다.
HTML에서 이벤트 처리기는 이벤트 처리기 어트리뷰트에 자바스크립트 코드 문자열을 할당하는 작업을 통해 정의된다. 하지만 자바스크립트에서는 이벤트 처리기 프로퍼티에 함수를 할당하는 작업을 통해 이벤트 처리기를 정의한다.

 


15.4 W3C DOM의 개요

15.4.1 문서를 트리로 표현
HTML 문서의 중첩된 태그는 DOM에서 트리로 표현되는 계층적 구조이다. HTML 문서의 트리 표현은 <body>와 <p> 같은 HTML 태그와 원소를 나타내는 노드, 텍스트의 문자열을 표현하는 노드를 가진다.


15.4.2 노드
Node 인터페이스에는 트리를 순회하거나 조작하기 위한 프로퍼티와 메서드가 정의되어 있다. Node 객체의 childeNodes 프로퍼티는 자기 자식들의 목록을 반환하고 firstChild와 lastChild, nextSibling, previousSibling, parentNode는 노드로 구성된 트리를 순회하기 위한 수단을 제공한다.  appendChild()와 removeChild(), replaceChilde(), insertBefore() 같은 메서드는 여러분이 문서 트리에 노드를 삽입하거나 제거할 수 있게 해준다.


15.4.2.1 노드의 타입
문서를 나타내는 트리의 여러 노드는 각 노드의 특정한 하위 인터페이스를 통해 표현된다. 모든 Node 객체에는 노드가 어떤 타입에 속하는지를 나타내는 nodeType 프로퍼티가 정의되어 있다. DOM 트리의 최상위에 있는 노드는 Document 객체다. 이 객체의 documentElement 프로퍼티는 문서의 최상위 원소를 표현하는 Element 객체를 참조하는데 HTML 문서에서는 문서 내에 명시적이거나 비명시적으로 적혀있는 <html> 태그가 이에 해당한다.
DOM 트리에는 Document 원소가 단 한개만 존재한다. 트리 내의 대다수 노드들은 <html> 이나 <i> 같은 태그를 표현하는 Element 객체와 텍스트의 문자열을 표현하는 Text 객체다. 문서를 분석하는 파서가 문서에 있는 주석을 유지하고 있다면 이 주석은 Comment 객체를 통해 DOM 트리상에 표현된다.


15.4.2.2 어트리뷰트
Element 인터페이스에 있는 getAttribute()와 setAttribute(), removeAttribute() 메서드를 사용하여 원소의 어트리뷰트 값을 읽거나 설정, 삭제할수 있다. HTML 태그의 표준 어트리뷰트는 각 태그를 표현하는 Element 객체의 프로퍼티로도 존재한다.
어트리뷰트를 사용하여 작업을 하는 다른 방법은 어트리뷰트와 그 값을 표현하는 Attr 객체를 반환해주는 getAttributeNode() 라는 메서드를 사용하는 것이다. (이 방법을 사용하는 이유는 Attr 인터페이스에 어트리뷰트의 값이 문서상에 리터럴로 기술되어 있는지 혹은 기본값인지 판단할 수 있게 해주는 specified라는 프로퍼티가 정의되어 있기 때문이다.)
하지만 Attr 객체는 원소의 childNodes[] 배열에는 나타나지 않고 Element나 Text 노드처럼 문서 트리 상에 직접 나타나는 것도 아니라는 사실을 유의하라.

15.4.3 DOM HTML API
DOM 표준은 XML이나 HTML과 함께 사용하려는 목적으로 만들어졌다.
HTMLDocument 인터페이스에는 W3C 표준화이전에 만들어진 브라우저들이 지원했던 다양한 프로퍼티와 메서드가 정의되어 있고 id와 style, title, lang, dir, className 프로퍼티가 정의되어 있다. ('class'는 자바스크립트의 예약어이기 때문에 HTML의 class 어트리뷰트가 자바스크립트에서는 className이 되었다.) HTML 태그는 여섯가지 어트리뷰트들 이외에 다른 어트리뷰트는 추가할 수 없다.

DOM 표준은 스크립트 작성자의 편의를 도모하기 위해 HTML 어트리뷰트에 대한 프로퍼티를 정의하고 있다는 점을 유념하라. 어트리뷰트 값을 얻어내거나 설정하는 일반적인 방법은 Element 객체의  getAttribute()setAtrribute() 메서드를 사용하는 것이고 HTML 표준이 아닌 어트리뷰트를 사용하여 작업할 때는 이 메서드를 사용해야 한다.


15.4.3.1 HTML 작명법
HTML은 대소문자를 구분하지 않지만 자바스크립트는 대소문자를 구분한다. HTML에 특화된 인터페이스의 프로퍼티 이름은 소문자로 시작하고 프로퍼티 이름이 여러 개의 단어로 이루어졌다면 두 번째 단어부터는 대문자로 시작한다.


 

15.4.4 DOM 레벨과 기능
DOM 표준에는 두 가지 버전(혹은 레벨)이 있다.
DOM 레벨 1은 1998년 10월에  표준화 되었고  여기엔 Node와 Element, Attr, Document 같은 코어 DOM 인터페이스들이 정의되어 있고 HTML에 특화된 다양한 인터페이스들도 정의되어 있다.  DOM 레벨 2는 2000년 11월에 표준화 되었고 이 DOM은 코어 인터페이스에 몇가지를 수정하는것 외에도 문서 이벤트와 CSS 스타일시트에 대해서 작업할수 있는 추가적인 도구도 제공한다.  그러나 마이크로소프트는 DOM event 모듈을 구현하지 않으며 레거시 DOM, W3C DOM, IE DOM은 서로 다른 방법으로 이벤트를 처리한다.




15.4.5 DOM 인증
현재 브라우저의 수가 너무 많아졌고 표준 지원 범위도 급격하게 빨리 변화하고 있어 이 책에서 어떤 브라우저가 어떤 DOM 기능을 지원하는지 명확한 정보를 알려주기 어렵다. 따라서 웹 브라우저가 DOM을 얼마나 잘 구현하고 있는지 판단하려면 지원 여부를 확인하는 것이 필요하다.


15.4.5.1 인터넷 익스플로러에서 DOM 인증
IE는 Node 인터페이스가 정의하는 node 타입의 상수를 지원하지 않는다. 문서 내의 각 노드에는 자신이 어떤 타입인가를 나타내는 nodeType 이라는 프로퍼티가 있다는 사실을 기억하라.


 

15.4.6 언어에 독립적인 DOM 인터페이스
이 책은 DOM API의 자바스크립트 구현에 대해 설명하지만 구현의 객체 프로퍼티는 일반적으로 다른 언어에 있는 get/set 메서드의 쌍에 매핑된다. DOM API의 자바스크립트 구현에서 또 다른 중요한 점은 특정 DOM 객체가 자바스크립트 배열처럼 작동한다는 것이다.
DOM 객체에 namedItem() 메서드가 있다면 메서드에 문자열을 전달하는 것은 객체의 배열 인덱스로 문자열을 사용하는 것과 같다. 다음 코드는 모두 폼 원소에 접근하는 동일한 방법이다.

var f = document.forms.namedItem["myform"];
var g = document.forms["myform"];
var h = document.forms.myform; 

NodeList의 원소에 접근하기 위해 배열 표현법을 사용할 수는 있지만, NodeList가 단지 배열과 유사한 객체이며 실제 Array는 아니라는 점을 반드시 기억해야 한다. DOM의 구현은 어떤 클래스를 정의하든지 상관이 없지만 다양한 DOM 인터페이스의 메서드와 프로퍼티는 반드시 정의해야 한다.



 

15.5 문서순회
DOM은 HTML문서를 Node 객체의 트리로  표현한다. 트리구조를 사용하여 가장 많이 이루어지는 작업은 트리의 각 노드를 차례대로 검사하면서 트리를 순회하는 것이다.


 

15.6 문서 내 엘리먼트 찾기
Document 객체는 모든 DOM 트리의 최상위 노드이지만 트리에 있는 HTML 엘리먼트는 표현하지 않는다. document.documentElement 프로퍼티는 문서의 최상위 엘리먼트인 <html> 태그를 참조하고 document.body 프로퍼티는 <body> 태그를 참조하는데 이 태그는 자신의 부모인 <html> 태그보다 유용하게 사용된다.
특정 타입의 HTML 엘리먼트 목록을 얻기 위해 getElementsByTagName()을 사용할수 있는데 html 태그는 대소문자를 구분하지 않기 때문에 전달되는 문자열도 대소문자가 구분되지 않는다는 점을 명심하라.
getElementByTagName()은 엘리먼트들의 배열을 반환하는 데 반해 getElementById() 메서드는 단지 id 어트리뷰트에 매칭되는 단일 엘리먼트만 반환한다.
HTML 문서의 HTMLDocument 객체에는 getElementByName() 메서드도 정의되어 있는데 이것은 엘리먼트 name 어트리뷰트를 조사하며 name 어트리뷰트는 문서 내에서 유일한 값을 가지지 않을 수도 있기 때문에 엘리먼트들의 배열을 반환한다.
클래스나 태그 이름을 통해 엘리먼트를 선택할 수 있게 해주는 getElements() 메서드에는 주어진 HTML 엘리먼트가 주어진 클래스의 멤버인지 검사하는 isMember() 메서드가 포함되어 있다.


 

15.7 문서 수정하기
코어 DOM API의 진정한 힘은 자바스크립트를 사용하여 문서를 동적으로 수정할 수 있다는데 있다.  Text 노드 내에 있는 텍스트에는 appendData(), inserData(), deletetData(), replaceData() 메서드를 사용하여 텍스트를 덧붙이거나 새 텍스트를 추가할 수 있고 기존 텍스트를 삭제하거나 교체할 수 있다.


15.7.1 어트리뷰트 수정하기
element.setAttribute() 메서드는 텍스트 교체와 부모 바꾸기, 노드 재배열하기를 통해 문서를 수정하는것 외에도 문서의 엘리먼트에 있는 어트리뷰트를 설정하여 문서를 다양하게 변형할 수 있다.


15.7.2 DocumentFragment를 사용하여 작업하기
DocumentFragment는 문서 내에서 실제로 나타나지는 않고 노드의 집합을 저장하고 저장된 노드들의 임시 저장소 역할을 담당한다.  또한 DocumentFragment에 저장된 노드들은 DocumentFragment를 통해 마치 단일 객체인 것처럼 조작할 수 있다. DocumentFragment가 문서에 삽입되면 (Node 객체의 appendChild()나 insertBefore(), replaceChild() 메서드 중 하나를 사용하여) 그때부터는 DocumentFragment는 자신의 노드들로 대체된다.


 

15.8 문서에 새로운 내용 추가하기
Document.createElemnet()Document.createTextNode() 메서드는 새로운 Element와 Text 노드를 생성하고 이렇게 생성한 노드는 Node.appendChild(), Node.insertBefoe(), Node.replaceChild() 메서드로 문서에 추가한다.


15.8.1 노드를 생성할 때 편리하게 사용할 수 있는 메서드
테이블을 생성하기 위해 Element를 생성하고 이것의 어트리뷰트를 설정한 후 Text 노드를 생성하고 이 Text 노드를 Element에 추가하고 이것을 부모 Element에 추가하는 과정은 복잡했다. 이것은  make()라는 함수를 통해 할수 있는데 이 이름으로 Element를 생성하고 이 객체에 대한 어트리뷰트를 설정한 후 자식들을 추가한다.


15.8.2 innerHTML 프로퍼티
HTMLElement 노드의 innerHTML을 W3C에서 공식적으로 DOM의 일부분으로 승인한 적은 없지만 현대의 모든 브라우저가 지원하는 중요하고도 강력한 프로퍼티다. HTML 엘리먼트에 대해 이 프로퍼티 값을 요청했을 때 얻는것은 그 엘리먼트 자식을 표현하는 HTML 텍스트 문자열이다. 대체로 HTML 문서를 HTML 텍스트 문자열로 기술하는 것이 createElement()와 appendChild()의 호출을 나열하는 것보다 훨씬 간편하고 간단하다.
웹 브라우저는 HTML 파싱 능력이 뛰어나다. += 연산자를 사용하여 아주 적은 양의 텍스트를 innerHTML 프로퍼티에 추가하는 것은 직렬화 과정과 파싱 과정을 모두 필요로 하기 때문에 그다지 효율적이지 않다.


 

15.9 예: 동적으로 생성되는 목차
문서 내에서 사용자가 선택한 텍스트가 무엇인지 알아내는 기능은 표준화가 진행되진 않았지만 현재 모든 브라우저에서 기능을 제공하고 있다. Window와 Document 객체의 getSelection() 메서드가 <input>이나 <textarea> 내에 있다면 선택된 텍스트를 반환하지 않고 브라우저별 호환성 문제가 있다.



 

'나홀로스터디 > JS 완벽가이드' 카테고리의 다른 글

쿠키와 클라이언트 측 지속성  (0) 2014.12.23
CSS와 DHTML  (0) 2014.12.15
웹 브라우저와 자바스크립트  (0) 2014.11.18
함수  (0) 2014.10.27
객체와 배열  (0) 2014.10.20

클라이언트 감지

2014. 11. 20. 11:15 나홀로스터디/JS For Web Dev


9장 클라이언트 감지

이 포스팅은 "프론트엔드 개발자를 위한 자바스크립트(2013 인사이트, 한선용 옮김)"에서 발췌 요약한 것입니다.
 
9.1 기능 탐지 사용
9.2 브라우저 탐지의 역사
9.3 어떤 타입의 탐지를 사용할 것인가


클라이언트 탐지는 웹 개발에서 가장 논란이 많은 주제이지만 개발 전략에서 빼놓을 수 없는 중요 파트이다.



9.1 기능 탐지
클라이언트 탐지 중에서 가장 널리 쓰이는 방법은 '기능탐지'라는 방법인데 이것은 어떤 브라우저를 사용 중인지에는 관심이 없고 어떤 기능이 지원되는지에 주목한다. 기능 탐지에서 매우 중요한 두가지 개념이 있는데 같은 결과를 얻을 수 있는 가장 일반적인 방법을 제일 먼저 테스트해야 한다는 것이고, 두 번째로 중요한 개념은 사용하려는 기능을 정확히 테스트해야 한다는 것이다.


9.1.1 안전한 기능 탐지
기능 탐지는 단순히 원하는 기능이 존재하는지만이 아니라 그 기능이 정확히 동작함을 확힌할 수 있을 때 가장 효과적이다. 함수의 존재여부를 확인하기 위해 typeof 를 써야 하지만 일부 브라우저에서는 정확한 연산자를 반환하지 않을수 있으므로 브라우저와 객체를 가리지 않고 함수의 존재 여부를 확인하려면 isHostMethod() 함수를 써야한다.
// 피터 마이콕스가 개발
function isHostMethod(object, property){   var t = typeof object[property];   return t == 'function' ||     (!! (t == 'object' && object[property])) ||     t == 'unknown'; }
result = isHostMethod(xhr, "open"); // true result = isHostMethod(xhr, "foo"); // false

9.1.2 기능 탐지는 브라우저 탐지가 아니다
특정 기능이나 기능 집합을 탐지할 때 어떤 브라우저에서 실행 중인지 알 필요는 없다. 애플리케이션에서 특정 브라우저 기능이 필요하다면 기능 탐지를 반복하기보다는 몇가지 기능을 묶어서 브라우저 그룹을 만드는 방법이 적절하다.
※ 기능 탐지는 해결책을 찾지 못했을 때 쓰는 보험 같은 것이지, 어떤 브라우저에서 실행 중인지 알기 위함이 아니다.
 




9.2 쿽스 탐지
쿽스탐지는 브라우저의 특정 동작방식을 찾아내려는 것이다. 쿽스 탐지는 보통 짧은 코드를 실행하고 기능이 정확히 동작하는지 확인한다. 쿽스 탐지는 코드를 실행해야 하므로 직접적인 영향이 있는 버그만 테스트하고 가능한 스크립트 첫 부분에서 테스트해서 이를 배제하는 편이 좋다.
 



9.3 브라우저 탐지
브라우저 탐지는 사용자 에이전트 문자열을 통해 어떤 브라우저에서 실행중인지 확인한다. 사용자 에이전트 문자열은 HTTP 요청을 보낼 때마다 받는 응답 헤더에 포함되어 있으며 자바스크립트에서는 navigator.userAgent를 통해 접근한다. 서버에서는 사용자 에이전트 문자열을 보고 어떤 브라우저를 사용 중인지 확인하고 그에 맞게 반응하도록 프로그램 하는 일이 일반적이며 문제도 없지만 브라우저 탐지는 기능 탐지나 쿽스 탐지로 해결되지 않을때만 사용하는 수단으로 여겨진다.
사용자 에이전트 문자열에서 가장 심한 논란거리는 브라우저가 사용자 에이전트 문자열에 잘못된, 또는 착각을 유도하는 정보를 넣어서 서버를 속이는 소위 '위장'의 역사다


9.3.1 역사
명세는 추가적으로 사용자 에이전트 문자열을 토큰/제품 버전의 목록 형태로 만들길 요구하지만 현실에서 사용자 에이언트 문자열은 그리 단순하지 않다

초기 브라우저
첫번째 웹 브라우저인 모자이크는 1993년 NCSA(국립 슈퍼컴퓨터 애플리케이션 센터)에서 만들어졌다. 운영체제와 플랫폼에 따라 매우 다르긴 했지만 모자이크 사용자 에이전트 문자열은 매우 단순해서 다음과 같은 형태였다
Mosaic/0.9 
슬래시 앞에 있는 텍스트는 제품 이름(NCSA 모자이크 또는 변형)이고 뒤에 있는 텍스트는 제품 버전이다.
넷스케이프 커뮤니케이션즈에서 웹 브라우저 개발을 처음 시작했을 때 그 코드 네임은 모질라("모자이크 킬러")였다.
Mozilla/Version [Language] (Platform; Encryption) 
넷스케이프는 제품 이름과 버전을 사용자 에이전트 문자열 맨 앞에 두는 형식을 받아들였지만 언어, 플랫폼(운영체제), Encryption(암호화타입)을 추가했다.


넷스케이프 내비게이터3과 인터넷 익스플로러3
페이지를 인터넷 익스플로러에서 보면 브라우저를 판단할 수 없어서 페이지가 깨지곤 했으므로 마이크로소프트는 사용자 에이전트 문자열을 넷스케이프 사용자 에이전트 문자열과 호환되게 만들기로 결정했다.
Mozilla/2.0 (compatible; MSIE Version; Operating System) 

넷스케이프 커뮤니케이터4와 인터넷 익스플로러 4-8
사용자 에이전트 문자열을 업데이트하여 형식을 자주 바꾼 것은 과거에 사용하던 브라우저 탐지 스크립트와의 호환성을 유지하면서도 새 스크립트에는 다른 정보를 제공하기 위함이다.


게코
게코가 처음 개발되던 당시에는 이후 넷스케이프6이 된 범용 모질라 브라우저의 일부분이었다. 넷스케이프6을 위해 만들어진 명세에는 미래 버전에서 사용자 에이전트 문자열을 어떻게 만들어야 하는지 정의하는 내용이 들어있다.
Mozilla/MozillaVersion (Platform; Encryption; OS-or-CPU; Language;
  PrereleaseVersion) Gecko/GeckoVertion ApplicationProduct/ApplicationProductVersion 

웹킷
애플은 2003년 사파리라는 웹 브라우저를 발표했다. 사파리의 렌더링 엔진은 웹킷인데 웹킷은 리눅스 기반 웹 브라우저인 컨터러의 엔더링 엔진 KHTML에서 분기하면서 시작했고 몇 년이 지난 후 웹킷은 독자적인 오픈 소스 프로젝트가 되었고 렌더링 엔진 개발에 초점을 맞추었다.
사파리는 인기 브라우저와 호환된다고 판단할만한 정보를 사용자 에이전트 문자열에 제공하가 위해 사용자 에이전트 문자열 형식을 만들었고, 모든 웹킷 기반 브라우저는 게코 기반 브라우저와 마찬가지로 자신을 모질라 5.0이라 칭한다.


컨커러
KDE 리눅스 데스크톱 환경에 따라오는 컨커러 브라우저는 오픈 소스 렌더링 엔진인 KHTML을 렌더링 엔진으로 사용한다. 호환성을 위해 컨커러 사용자 에이전트 문자열 형식을 인터넷 익스플로러와 비슷하게 만들기로 정했다.
Mozilla/5.0 (compatible; Konqueror/Version; OS-or-CPU) 

크롬
구글의 크롬 웹 브라우저는 렌더링 엔진으로 웹킷을 사용하지만 자바스크립트 엔진은 독자적으로 개발했다. 크롬의 사용자 에이전트 문자열에는 웹킷이 들어가는 모든 정보와 함께 크롬 버전도 포함된다.


오페라
오페라의 기본 자용자 에이전트 문자열은 최신 브라우저 중에서는 가장 논리적이어서 이름과 버전을 정확히 표시한다.


IOS와 안드로이드
모바일 운영체제인 iOS와 안드로이드의 기본 웹 브라우저는 모두 웹킷이므로 데스크톱과 같은 기본 사용자 에이전트 문자열 형식을 공유한다.
 


9.3.2 브라우저 탐지 사용
사용자 에이전트 문자열을 가지고 특정 브라우저인지 판단하는 것은 대단히 복잡한 문제이다.

렌더링 엔진 식별
렌더링 엔진을 정확히 식별하려면 정확한 순서로 테스트해야 한다. 브라우저의 비일관성 때문에 테스트 순서가 틀리면 부정확한 결과를 얻게 된다.
첫 번째로 오페라인지 판단해야 하는데 오페라의 사용자 에이전트 문자열이 다른 브라우저와 완전히 똑같을 수 있기 때문이다. 오페라에서 실행 중인지 판단하려면 window.opera  객체가 있는지 확인해야 하는데 버전 7.6 이후에는 브라우저 버전 번호를 문자열로 반환하는 version() 메서드가 있다.
두 번재로 테스트할 렌더링 엔진은 KHTML이다. KHTML의 사용자 에이전트 문자열에도 "Gecko"가 들어 있으므로 웹킷과 KHTML 을 모두 배제한 뒤에 게코를 체크하면 안전하다. 케코 버전 번호는 "rv:"와 닫는 괄호()) 사이에 있으므로 버전 번호를 추출하는 정규 표현식은 닫는 괄호가 아닌 모든 문자를 캡처 해야한다.
마지막 렌더링 엔진은 인터넷 익스플로러이다. 버전 번호는 "MSIE"와 세미콜론 사이에 있으므로 이를 찾는 정규 표현식은 단순하다.


브라우저 확인
렌더링 엔진만으로 자바스크립트 기능에 대해 알 수 없을때가 있다. 애플의 사파리 브라우저와 구글의 크롬 브라우저는 모두 웹킷 렌더링 앤진을 쓰지만 자바스크립트 엔진은 서로 다르다. 오페라와 인터넷 익스플로러의 경우 browser 객체에 저장된 값은 engine 객체에 저장된 값과 같다.


플랫폼 감지
여러 플랫폼에서 동작하도록 만들어진 브라우저는 플랫폼별로 다른 문제가 있을 수 있다.
렌더링 엔진과는 달리 플랫폼 정보는 일반적으로 매우 제한적이며 운영체제나 버전 정보를 쉽게 얻기는 힘들다.


윈도 운영체제 식별
플랫폼이 윈도일 경우 사용자 에이전트 문자열에서 운영체제 정보를 더 얻을 수 있다. XP 이전의 윈도는 가정용과 비즈니스용 두 가지 버전이 있었는데 가정용 버전은 윈도라고 불렀고 버전은 95, 98, ME가 있다. 비즈니스 버전은 윈도 NT와 윈도2000이 있다. 윈도 XP는 두 버전을 윈도 NT에서 발전한 공통 코드로 통합했다. 윈도 비스타는 윈도 XP를 기반으로 만들어졌다.


모바일 장치 식별
주요 브라우저는 모두 모바일 버전이 있고 다른 장치에서 동작하는 버전도 있으므로 이를 구분할 수 있어야 한다. 모바일 장치 식별의 첫 단계는 모든 모바일 장치가 해당하는 프로퍼티를 추가하는 것이다.
iOS 장치 탐지는 문자열 "iPhone", "iPod", "iPad" 만 검색되므로 정규 표현식을 써서 사용자 에이전트 문자열에 iOS 버전이 들어 있는지 확인한다.
안드로이드 운영체제는 문자열 "안드로이드"를 검색하기만 하면 되고 버전 번호는 바로 뒤에 있다.
노키아 N 시리즈 스마트폰도 웹킷을 이용하고 사용자 에이전트 문자열에 "Safari"가 들어있긴 하지만 실제 사파리 브라우저는 아니다. 이 스마트폰은 사용자 에이전트 문자열 "NokiaN"만 체크해도 된다.
마지막 주요 모바일 장치 플랫폼은 포켓 PC와 스마트폰용 윈도 모바일(이전에는 윈도CE라고 불린)이다. 이 장치들은 윈도 플랫폼에 속하므로 윈도 운영체제와 비슷한 값을 반환한다.


게임 시스템 식별
Wii 브라우저는 오페라 커스텀 버전이므로 Wii는 단순히 문자열 "Wii"를 테스트 하는 것으로 충분하다.  플레이스테이션에서는 정규 표현식을 써서 사용자 에이전트 문자열을 테스트하되 대소문자를 가리지 않게 했다.
 


9.3.4 사용법
브라우저 탐지는 클라이언트 탐지에서 가장 마지막 옵션으로 생각해야 한다. 가능하다면 기능 탐지나 쿽스 탐지를 먼저 시도해야 하고 다음과 같은 상황에 사용하는것이 알맞다.
- 기능이나 쿽스를 직접 정확히 탐지할 수 없을때
- 같은 브라우저의 기능이 플랫폼별로 다를 때
- (사용자 통계 등의) 정보 수집 목적으로 정확히 어떤 브라우저인지 알아야 할때
 



9.4 요약
기능탐지 - 특정 브라우저 기능을 사용하기 전에 먼저 테스트하는 이 접근법에서는 개발자가 브라우저 타입이나 버전에 신경 쓰지 않고 단순히 원하는 기능이 존재하는지만 알면된다. 기능탐지로는 특정 브라우저나 버전을 정확히 알수 없다.

쿽스탐지 - 쿽스는 사실 브라우저 구현상의 버그인데 쿽스 탐지는 보통 짧은 코드를 실행해서 브라우저에 해당 버그가 있는지 확인하는 방식이다. 쿽스 탐지는 특정 버그가 스크립트 진행을 방해할 소지가 있을 때만 사용한다.

브라우저 탐지 -  사용자 에이전트 문자열을 통해 브라우저를 식별한다. 자용자 에이전트 문자열에는 브라우저에 관한 정보가 매우 많은데 브라우저, 플랫폼, 운영체제, 브라우저 버전 등이 이에 속한다. 브라우저 탐지는 어려운 작업이지만 사용자 에이전트 문자열을 통해 모바일장치나 게임 시스템을 포함한 모든 브라우저에서 렌더링 엔진과 플랫폼을 파악할 수 있다.

 
 
 

'나홀로스터디 > JS For Web Dev' 카테고리의 다른 글

DOM 확장  (0) 2014.12.18
DOM  (0) 2014.12.08
브라우저 객체모델  (0) 2014.11.12
함수 표현식  (0) 2014.10.23
참조타입  (0) 2014.10.17

웹 브라우저와 자바스크립트

2014. 11. 18. 18:05 나홀로스터디/JS 완벽가이드


13장 웹 브라우저와 자바스크립트

이 포스팅은 "자바스크립트 완벽 가이드(인사이트, 송인철,이동기,이유원,황인석 옮김)"에서 발췌 요약한 것입니다.
 
13.1 웹 브라우저 환경
13.2 HTML에 스크립트 내장하기
13.3 HTML의 이벤트 처리기
13.4 URL 안의 자바스크립트
13.5 자바스크립트 프로그램의 실행
13.6 클라이언트 측 호환성
13.7 접근성
13.8 자바스크립트 보안
13.9 웹과 관련된 다른 자바스크립트 내장 기법들


자바스크립트를 웹 브라우저 안에 내장하면 브라우저가 공개하는 강력하고 다영한 기능들을 스크립트 안에서 제어할수 있다.

13.1 웹 브라우저 환경
자바스크립트를 이해하려면 웹 브라우저가 제공하는 프로그래밍 환경을 이해해야만 한다.

13.1.1 전역 실행 컨텍스트로서의 Window 객체
클라이언트 측 자바스크립트에서는 Document 객체가 HTML 문서를 나타내며 Window 객체는 브라우저 창(또는 프레임)을 나타낸다. 모든 자바스크립트 구현에는 유효 범위 체인의 가장 앞에 항상 전역 객체가 위치하며 이 전역 객체의 프로퍼티들은 전역 변수들이다. 클라이언트 측 자바스크립트에서 전역 객체는 Window 객체고 이 객체에는 두 개의 자기 참조 프로퍼티 windowself 가 있다.
Window 객체는 클라이언트 측 자바스크립트의 전역 객체이기 때문에 모든 전역 변수는 이 객체의 프로퍼티로 정의된다.
애플리케이션에 속한 각 창은 고유한 Window 객체를 가지며 클라이언트 측 자바스크립트 코드의 고유한 실행 컨텍스트를 정의한다.

13.1.2 클라이언트 측 객체 계층 구조와 DOM
웹 브라우저가 프레임으로 구분된 문서를 표시할 때에는 최상위 Window 객체의 frames[] 배열이 각 프레임을 표현하는 Window 객체들에 대한 참조를 저장한다.

13.1.3 이벤트 구동 프로그래밍 모델
클라이언트 측 자바스크립트에서 웹 브라우저는 사용자 입력이 들어올 때 이벤트를 생성하여 프로그램에게 알려준다. 이벤트가 발생하면 웹 브라우저는 이벤트에 반응하기 위해 적절한 이벤트 처리기 함수를 찾아 호출하려고 시도한다. 따라서 동적이며 상호 작용할 수 있는 클라이언트 측 자바스크립트 프로그램을 작성하기 위해선 알맞은 이벤트 처리기를 구현하여 등록함으로써 적절한 시점에 이를 호출할수 있게 해야한다.
이벤트 처리기는 사용자 입력에 의해 구동되기 때문에 예측할 수 없는 시점에 비동기적으로 호출된다.

13.1.4 웹상에서 자바스크립트의 역할
자바스크립트의 역할은 정보의 획득과 전달을 용이하게 함으로써 사용자의 브라우징 경험을 증대시키는 일이다.
- 이미지 롤오버 같은 시각 효과를 생성하여 사용자의 페이지 탐색을 넌지시 도울수 있다.
- 표의 열을 정렬함으로써 사용자가 원하는 것을 빨리 찾게 할 수 있다.
- 사용자가 문서의 내용을 깊이 파고 들어감에 따라 선택적으로 어떤 내용은 감추고 또 어떤 내용은 더 자세히 노출하는 등의 작업을 할 수 있다.
- 웹 서버와 직접 통신하여 전체 페이지를 다시 읽어오지 않고도 새로운 정보가 표시될 수 있게 함으로써 브라우징 경험이 끊이지 않고 물 흐르듯 진행되게 할 수 있다.

13.1.5 겸손한 자바스크립트
겸손한 자바스크립트의 첫 번째 목표는 자바스크립트 코드와 HTML 마크업을 분리하는 것이고 두번째 목표는 단계적으로 성능을 축소하는 것이다. 자바스크립트는 html내용을 강화하기 위한 용도로써 이해되고 설계되어야 하며 그 내용은 자바스크립트 코드가 없이도 사용할 수 있어야 한다.
자바스크립트의 세 번째 목표는 html 페이지의 접근성을 해치지 않게 하는것이다.(또한 이상적으로 접근성을 강화해 줄 수 있어야만 한다.)

 

13.2 HTML에 스크립트 내장하기
- <script>와 < /script> 태그 사이에서
- <script> 태그의 src 어트리뷰트로 지정되는 외부 파일에서
- onclick이나 onmouseover 같은 HTML 어트리뷰트의 값으로 지정되는 이벤트 처리기 안에서
- 특수한 javascript: 프로토콜을 사용하는 URL안에서

13.2.1 <script> 태그
XHTML에서 <script> 태그의 내용은 다른 문서 내용들과 똑같이 다뤄지는데 만약 < 또는 & 문자를 포함한다면 이들 문자는 XML 마크업으로 해석된다. 이런 이유로 XHTML을 사용할 때는 모든 자바스크립트 코드를 CDATA 구역 안에 두는 것이 가장 좋다.
<script><![CDATA[
]]></script>
하나의 HTML문서는 임의 개수의 <script> 엘리먼트를 포함할 수 있다.
비록 한 파일의 분리된 스크립트들이 HTML 파일을 읽고 파싱하는 과정에서 서로 다른 시간에 실행되지만 결국 같은 자바스크립트 프로그램의 일부를 구성하기 때문에 한 스크립트에서 정의한 변수와 함수는 같은 파일에서 뒤따라 나오는 다른 모든 스크립트에서도 사용할 수 있다.
스크립트가 HTML 문서에 삽입되는 출력물을 생성할 수 있다는 것은 HTML 파서가 문서 파싱 프로세스의 일부로서 자바스크립트 스크립트를 해석해야만 한다는 것을 의미한다.

13.2.2 외부 파일에 저장된 스크립트
<script> 태그는 자바스크립트 코드를 담은 파일의 URL을 지정하는 src 어트리뷰트를 지원한다.
 <script src = "../../script/utill.js"></script>
- 커다란 블록의 자바스크립트 코드를 HTML 파일에서 제거할 수 있기 때문에 결과적으로 HTML 파일을 간단히 만들 수 있다.
- 서로 다른 HTML 파일들이 공유하며 사용하는 함수나 자바스크립트 코드가 있다면 이들을 하나의 파일로 저장하고 필요로 하는 HTML파일에서 읽어서 사용할 수 있으므로 코드의 유지와 보수에 용이하다.
- 자바스크립트 함수들이 하나 이상의 페이지에 의해 사용된다면 이들을 분리된 자바스크립트 파일에 놓아둠으로써 브라우저가 캐시에 저장하여 더 빨리 불러오게 할 수 있다.


13.2.3 스크립트 언어 지정하기

브라우저 벤더는 어떠한 스크립트 언어라도 선택하여 지원할 수 있다. 파일의 기본 스크립트 언어는 HTTP Content-Script-Type 헤더를 사용해 지정할 수 있으며, HTML의 <meta> 태그를 사용해 이 헤더를 흉내낼 수 있다.
기본 스크립트 언어를 지정하지 않았거나 또는 기본으로 설정된 사항을 번복하고 싶을때는 <script> 태그의 type 어트리뷰트를 시용해야 한다. 그러나 type 어트리뷰트를 지원하지 않던 시절 스크립트 언어는 language 어트리뷰트를 통해 지정했다.

13.2.4 defer 어트리뷰트
스크립트에서는 document.write() 메서드를 사용해 문서에 동적으로 내용을 첨가할 수 있는데 이 때문에 HTML 파서는 문서의 파싱 작업 중에 스크립트를 만났을 때 파싱 작업을 일단 멈추고 스크립트가 실행되기를 기다려야 한다. HTML4 표준은 이러한 문제를 다루기 위하여 <script> 태그에 defer 어트리뷰트를 정의했다.
스크립트의 실행을 미루는 것은 스크립트를 외부 파일에서 불러야 할 때 특히 유용하나 브라우저에서는 이 기능이 정확하게 구현되어 있지 않음에 주의해야 한다.

13.2.5 <noscript> 태그
HTML은 자바스크립트가 브라우저에서 비활성화된 경우에만 렌더링할 내용을 담는 용도로 <noscript> 엘리먼트를 정의한다. 이상적으로는 페이지를 정교하게 만들어서 자바스크립트는 성능 향상을 위한 용도로만 사용하게 해야 하지만 이러한 작업이 여의치 않다면 <noscrip> 태그를 사용하여 사용자로 하여금 자바스크립트가 꼭 필요하다는 사실을 알리거나 대신 보여줄 내용의 링크를 제공할 수도 있다.

13.2.6 </script> 태그
document.write() 메서드나 innerHTML 프로퍼티를 사용하여 다른 스크립트를(보통 다른 창이나 프레임으로) 출력하는 스크립트를 작성할 수도 있다.  HTML파서는 코드안에 "</script>"문자열을 스크립트를 끝내는 태그를 발견한 것이라 생각하기 때문에 이를 방지하기 위해서는 "</" + "script>" 같은 표현식을 사용해 출력하거나 </script>의 / 문자를 백슬래시를 사용하여 이스케이프 시퀀스로 표현할 수도 있다.

13.2.7 오래된 브라우저에서 스크립트 감추기
자바스크립트가 해로운 것이던 시절 브라우저들의 렌더링으로 HTML 주석을 사용하는 간단한 방법(<!-- // -->)이 사용되었다.

13.2.8 비공식 스크립트 어트리뷰트
eventfor 어트리뷰트를 사용하면 <script> 태그를 사용해서 이벤트 처리기를 정의할 수 있다. 이 어트리뷰트들은 오직 IE에서만 작동하며 이러한 기능은 다른 방법을 사용하여 쉽게 구현할 수 있으므로 이 어트리뷰트는 사용하지 않는것이 좋다.



 

13.3 HTML의 이벤트 처리기
스크립트 안의 자바스크립트 코드는 이 스크립트를 포함한 HTML 파일이 웹 브라우저로 읽혀 들어올 때 한 번 실행된다. 이벤트 처리기 정의안에는 자바스크립트 문장을 얼마든지 넣을 수 있지만 일반적으로 사용되는 기법은 <script>태그로 정의한 함수를 단순히 호출만 하는 용도로 사용하는 것이다. 겸손한 자바스크립트 패러다임을 위해서라면 문서 내용과 동작을 완전히 분리해야만 한다.

onclick
이 처리기는 <a>와 <area> 태그를 비롯해 버튼과 유사한 모든 폼 엘리먼트에서 지원하며 사용자가 엘리먼트를 클릭할 떄 구동된다.
onmousedown, onmouseup
이 이벤트 처리기는 onclick과 매우 유사하지만 사용자가 마우스를 눌렀을때와 놓았을때를 구분하여 구동된다는 것이 다르다.
onmouseover, onmouseout
이 이벤트 처리기는 마우스 포인터가 문서 엘리먼트의 위로 올라올때와 엘리먼트를 벗어날 때 구동된다.

onchange
이 이벤트 처리기는 <input>과 <select>, <textarea> 엘리먼트에서 지원하며 엘리먼트에 의해 표시된 값을 사용자가 변경한 뒤 탭이나 다른 방법을 사용해서 엘리먼트로부터 입력 포커스를 다른 곳으로 이동할 때 구동된다.
onload
<body> 태그 안에 등장하며 문서와 문서에 연결된 외부 내용들을 완전히 불러온 후에 구동된다.



 

13.4 URL 안의 자바스크립트

자바스크립트 코드를 클라이언트 측에 포함시키기 위한 또 다른 방법은 javascript: 모조 프로토콜로 지정된 URL을 사용하는 것이다. 이 특별한 프로토콜 타입은 URL의 몸체가 자바스크립트 인터프리터에 의해 실행될 자바스크립트 코드를 담은 문자열임을 알리는 역할을 한다.

13.4.1 북마클릿
자바스크립트의 URL의 특별히 중요한 용도 중 하나는 북마클릿이라 부르는 즐겨찾기 툴바나 메뉴에서 손쉽게 실행할수 있게 하는것이다.
 

13.5 자바스크립트 프로그램의 실행
13.5.1 스크립트 실행
<script>와 </script> 태그 사이에 위치한 자바스크립트 문장들은 스크립트에 나타난 순서대로 실행된다.
스크립트는 HTML 문서의 <head>나 <body> 안에 나타날수 있는데 <head>안의 스크립트는 보통 다른 코드에 의해 호출될 함수들을 정의하며 또한 다른 코드에 의해 사용될 변수들을 선언하고 초기화하기도 한다. 일반적으로 문서 <head>안의 스크립트는 함수 하나를 정의하여 차후 실행을 위해 onload 이벤트 처리기에 등록한다.
문서 <body> 안의 스크립트는 <head>안의 스크립트가 하는 모든 일을 할 수 있다.
만약 스크립트가 차후에 사용할 함수와 변수들을 단순히 정의하기만 하고 document.write() 호출과 같이 문서 내용을 바꾸는 어떠한 시도도 하지 않는다면 관습에 따라 이 스크립트 문서의 <body>가 아니라 <head> 안에 위치해야만 한다.

13.5.2 onload 이벤트 처리기
문서의 파싱이 끝나고 모든 스크립트가 실행된 후 모든 보조내용이 전부 불려온 후에 브라우저는 onload 이벤트를 발생시켜 Window 객체에 onload 이벤트 처리기로 등록된 모든 자바스크립트 코드를 실행한다.
onload 처리기는 <body> 태그의 onload 어트리뷰트를 설정함으로써 등록할 수 있는데 onload 처리기가 구동되는 때는 문서의 읽기 작업과 파싱 작업이 완전히 끝난 후이기 때문에 모든 문서 엘리먼트는 자바스크립트 코드를 사용하여 조작할 수 있다.
onload 이벤트 처리기는 문서 파싱 작업이 완료된 다음에 호출되기 때문에 document.write()를 호출해선 안된다.

13.5.3 이벤트 처리기와 자바스크립트 URL
문서의 읽기와 파싱 작업이 끝난 후에는 onload 처리기가 구동되며 자바스크립트 실행은 이벤트 구동 단계로 진입한다. 이 단계에서는 마우스 움직임, 클릭, 키입력과 같은 사용자 입력에 의한 비동기적 이벤트 처리기가 실행되고 자바스크립트 URL 또한 이 단계에서 비동기적으로 호출될 수 있는데 javascript:모조 프로토콜을 사용하는 href 어트리뷰트를 가진 링크를 클릭하는 경우가 이에 해당한다.

13.5.4 onunload 이벤트 처리기
사용자가 웹 페이지를 떠나 다른 곳으로 이동할 때 브라우저는 현재 페이지에 대한 자바스크립트 코드의 마지막 실행 기회로 onunload 이벤트 처리기를 구동한다.  onunload 이벤트를 처리하면 웹 페이지의 onload 처리기나 다른 스크립트에 의한 효과를 되돌릴수 있다.

13.5.5 실행 컨텍스트와 Window 객체
문서의 모든 스크립트와 이벤트 처리기, 자바스크립트 URL은 그들의 전역 객체로 하나의 Winodw 객체를 공유한다. 새 문서가 창으로 불려올 때는 언제나 그 창의 Window 객체가 기본 상태로 복원된다. Window 객체에 있는 프로퍼티들의 수명은 그 프로퍼티를 정의한 자바스크립트가 포함된 문서의 수명과 같다. 하지만 Window 객체는 이 객체가 나타내는 창이 존재하는 한 계속해서 남는다. Window 객체에 대한 참조는 이 창이 얼마나 많은 웹 페이지를 읽고 버렸는지에 상관없이 항상 유효한 상태로 남아있다.

13.5.6 클라이언트 측 자바스크립트 쓰레드 모델
클라이언트 측 자바스크립트는 단일 쓰레드다(또는 마치 그러한 것처럼 작동한다). 스크립트를 읽고 실행하는 도중에는 문서 파싱이 중단되고, 이벤트 처리기가 실행되는 중에는 웹 브라우저도 사용자 입력에 반응하지 않는다. 단일 쓰레드 실행은 코드작성시 두 이벤트가 절대로 동시에 실행되지 않음을 보장받는 동시에 스크립트나 이벤트 처리기가 절대로 오랜시간 동안 실행되어선 안됨을 의미한다.

13.5.7 읽기 중인 문서 조작하기
문서에 대한 읽기와 파싱 작업이 진행되는 동안 <script> 엘리먼트 안의 자바스크립트 코드는 document.write()를 사용하여 문서에 내용을 삽입할 수 있다. 하지만 이 작업에 대해선 표준화가 진행된바 없으며 막연한 불안이 있기도 하다. 이것에 대해 일치하는 의견이 하나 있다면 그것은 onload 이벤트가 구동된 다음의 문서 조작은 안전하다는 것이다.
문서에 포함된 이미지의 크기가 크거나 개수가 많다면 이미지에 대한 읽기 작업이 전부 완료되어 onload 이벤트가 구동되기 전에도 주요 문서의 파싱 작업은 충분히 완료될 수 있다.
 
 
13.6 클라이언트 측 호환성
웹 브라우저는 애플리케이션들을 실행하기 위한 보편적 플랫폼이며 자바스크립트는 그 애플리케이션들을 개발하기 위해 사용되는 언어다. 모든 웹 브라우저가 HTML을 출력하지만 CSS와 DOM 같은 표준을 지원하는 방식들에는 서로 차이가 있다.
온라인에서 브라우저 호환성 정보를 검색할 수 있는 사이트를 소개한다.
- http://www.quirksmode.org/dom/


13.6.1 비호환의 역사
웹 프로그래밍의 초창기는 넷스케이프와 마이크로소프트 간의 '브라우저 전쟁'으로 특징 지을수 있다. 브라우저 전쟁은 마이크로소프트가 압도적인 시장 점유를 달성하며 끝이 났고 DOM이나 CSS 같은 웹 표준들이 자리를 잡아가기 시작했다.

13.6.3 기능테스트
기능 테스트의 중요한 점은 이것이 특정 브라우저 벤더나 특정 브라우저 버전에 종속되지 않는 코드를 만들 수 있게 해준다는 것이다. 기능테스트는 어떤 기능들을 구현하는지에 관계없이 오늘날 존재하는 브라우저들과 작동함은 물론 미래의 브라우저들과도 계속하여 작동할 수 있게 한다.
document.all[] 배열은 마이크로소프트가 IE4에서 제안한것인데 이것은 자바스크립트 코드로 하여금 문서의 모든 엘리먼트를 가리킬 수 있게 했지만 표준으로 채택되지는 못했고 document.getElementById() 가 그 자리를 대신하게 되었다.

13.6.4 브라우저 테스트
기능테스트는 넓은 범위의 기능 검사를 수행할 때 잘 어울린다. 현재 브라우저 벤더나 버전을 판별하기 위한 코드는 종종 브라우저 스니퍼나 클라이언트 스니퍼라 불리기도 한다. 클라이언트 스니퍼는 넷스케이프와 IE가 서로 호환되지 않고 막 나가던 시절의 웹에서 흔히 사용되던 기법이다.

13.6.5 인터넷 익스플로러 조건부 주석
실무에서 클라이언트 측 자바스크립트 프로그래밍의 많은 비호환 문제들이 IE에 한정된 것임을 보게 될것이다. IE는 HTML과 자바스크립트 모두에서 유용하게 사용할 수 있는 조건부 주석을 지원한다.
조건부 주석은 또한 IE의 자바스크립트 인터프리터에서도 지원된다. 조건부 주석 안에서는 @if, @else, @end 키워드들이 IE의 자바스크립트 인터프리터에 의해 조건부로 실행될 코드들을 구분한다.
 
 


13.7 접근성
웹은 정보를 널리 퍼뜨리는데 매우 훌륭한 도구이며 자바스크립트 프로그램은 이러한 정보들로의 접근성을 강화하는데 사용할수 있다. 그러나 시각장애 혹은 신체장애가 있는 방문자에게 정보를 줄수 없는 코드를 작성하기 쉬우니 각별히 주의해야한다. 자바스크립트 접근성과 관련된 가장 기본적인 규칙은 자바스크립트 인터프리터가 비활성화된 상태에서도 여전히 웹 페이지가 기능을 다할 수 있게 코드를 작성하는 것이다.
접근성과 관련된 또 다른 중요한 점은 키보드는 사용할 수 있으나 마우스 같은 포인팅 장치는 사용할 수 없는 사용자들을 배려하는 것이다. 접근성을 위해서는 가능한 장치 독립적인 이벤트의 사용을 선호해야만 한다.
 




13.8 자바스크립트 보안
13.8.1 자바스크립트가 할 수 없는 것
웹 브라우저에 자바스크립트 인터프리터가 도입되었다는 말은 웹 페이지를 읽어들이는 과정에서 임의의 자바스크립트 코드를 이용하는 컴퓨터에서 실행할 수 있음을 의미한다. 유해한 코드에 맞서기 위한 자바스크립트의 첫 번재 대응책은 단순히 이 언어가 특정 기능들을 지원하지 않게 하는 것이다. 두번재 대응책은 자바스크립트가 지원하는 기능들을 제약하는 것이다.

13.8.2 동일 출처 정책
동일 출처 정책은 자바스크립트 코드가 상호 작용할 수 있는 웹 문서 내용에 관한 광범위한 보안 제약이다. 이것은 보통 웹 페이지가 <iframe> 태그를 사용하여 어러 프레임으로 구성되었거나 다른 브라우저 창을 열 때 적용된다. 명확히 말하면 스크립트는 그 자신이 포함된 문서와 출처가 동일한 문서나 창의 프로퍼티들만 읽을 수 있다. 동일 출처 정책은 XMLHttpRequest 객체와 함께 HTTP를 스크립트 안에서 직접 제어할 때에도 적용된다.
다른 서버에서 불러온 문서를 포함하는 창은 사실상 스크립트가 출입할 수 없는 구역이라고 생각해야 한다. 동일 출처 정책은 스크립트가 개인 소유의 정보를 빼돌리는 것을 방지하기 위해 필요하다

13.8.3 플러그인과 ActiveX 컨트롤 스크립팅
많은 웹 브라우저에서 자바스크립트는 인터넷 익스플로러의 ActiveX 컨트롤이나 다른 브라우저들의 플러그인 같은 소프트웨어 컴포넌트들을 실행하기 위한 '스크립트 엔진'으로 사용되곤 한다. 만약 스크립트에서 어떤 플러그인을 직접 제어할 수 있다면 웹 브라우저의 보안 아키텍처를 신뢰하는 데에서 나아가 플러그인 그 자체의 보안 아키텍처도 신뢰할 수 있어야만 한다는 것이다.

13.8.4 크로스 사이트 스크립팅
크로스 사이트 스크립팅 또는 XSS는 공격자가 공격의 대상이 된 웹 사이트로 HTML 태그나 스크립트를 주입해 넣는 종류의 보안 쟁점을 일컫는 용어다. 웹 페이지는 사용자가 전송해온 데이터에 기반하여 동적으로 문서 내용을 생성하는데 이에 앞서서 우선 사용자의 데이터에서 내장된 HTML 태그를 제거하는 식의 '검열' 과정을 거치지 않으면 이 웹 페이지는 크로스 사이트 스크립팅에 대해 취약해진다.

13.8.5 서비스 거부 공격
사악한 사이트는 무한 루프나 의미없는 계산을 끊임없이 수행함으로써 여러분의 CPU를 불통으로 만들어버릴 수도 있다. 웹 브라우저의 공격을 방어하기 위한 일반적인 방법론은 존재하지 않는다.
 



13.9 웹과 관련된 다른 자바스크립트 내장 기법들
클라이언트 측 자바스크립트 외에도 자바스크립트 언어를 웹에 내장하기 위한 다른 방법들이 있다.

사용자 스크립팅
사용자 스크립팅을 사용하면 HTML 문서가 브라우저에 의해 렌더링되기 전에 우선 사용자가 정의한 스크립트를 거쳐서 조작될 수 있다. 가장 널리 알려진 사용자 스크립팅의 예는 파이어폴스 웹 브라우저의 Greasemonkey 확장 기능이다.

SVG
SVG(Scalable Vector Graphics, 가변 벡터 도형 처리)는 XML 기반의 그래픽 포맷으로 자바스크립트 스크립트를 포함할 수 있다.  클라이언트 측 자바스크립트는 자신이 내장된 HTML 문서를 스크립팅 할수 있고 이와 마찬가지로 SVG 파일에 끼워 넣어진 자바스크립트 코드는 그 문서의 XML 엘리먼트들을 스크립트로 직접 제어할 수 있다.

XUL
XUL은 사용자 인터페이스를 기술하기 위한 XML 기반의 문법이다. 파이어폭스 웹 브라우저의 GUI는 XUL 문서로 정의되어 있다. XUL 문서 안의 자바스크립트 코드는 클라이언트 측 자바스크립트 코드와는 다른 객체와 API들을 사용하며 또한 다른 보안 모델을 따른다.

액션스크립트
액션스크립트는 자바스크립트와 유사한 언어이며(동일한 ECMAscript 명세서에서 유래했으나 객체지향적인 방향으로 진화했다) 플래시 무비에서 사용된다. 플래시는 XML이나 HTML에 기반을 두지 않으며 플래시에 의해 제공되는 API들은 이책에서 논의되는 것과는 관련이 없다.
 
 
 

 

'나홀로스터디 > JS 완벽가이드' 카테고리의 다른 글

CSS와 DHTML  (0) 2014.12.15
문서 스크립팅  (0) 2014.11.26
함수  (0) 2014.10.27
객체와 배열  (0) 2014.10.20
문장  (0) 2014.10.16

브라우저 객체모델

2014. 11. 12. 11:30 나홀로스터디/JS For Web Dev


8장 브라우저 객체 모델

이 포스팅은 "프론트엔드 개발자를 위한 자바스크립트(2013 인사이트, 한선용 옮김)"에서 발췌 요약한 것입니다.
 
8.1 BOM의 핵심인 window 객체에 대한 이해
8.2 창과 프레임, 팝업 컨트롤
8.3 location 객체에서 얻는 페이지 정보
8.4 navigator 객체를 통한 브라우저 이해



8.1 window 객체
window 객체는 브라우저 창의 자바스크립트 인터페이스 구실을 하고 다른 한편으로는 ECMAScript Global 객체로 기능하며 window에 정의된 parseInt() 등의 메서드를 이용한다.


8.1.1 전역 스코프
window 객체가 ECMAScript의 Global 객체 구실을 하므로 전역에서 선언한 변수와 함수는 모두 window 객체의 프로퍼티 및 메서드가 된다.


8.1.2 창 사이의 관계와 프레임
페이지에 프레임이 들어있으면 각 프레임은 독자적인 window 객체를 가지며 이 객체들은 frames 컬렉션에 저장된다.
각 window 객체는 프레임의 name을 프로퍼티로 가진다.
top 객체는 항상 최상위(즉, 가장 바깥에 있는) 프레임을 가리키는데 이는 곧 브라우저 창이다.
window 객체 중에는 parent도 있는데 parent 객체는 항상 현재 프레임의 바로 상위인 부모 프레임이다.

최상위 window에는 name 프로퍼티 값이 존재하지 않는데 window.open() 메서드를 통해 창을 열었을 때는 예외다. self 객체는 항상 window를 가리키므로 window 객체는 self와 서로 바꿔서 써도 된다.

8.1.3 창의 위치
창의 위치를 가져오거나 설정하는 프로퍼티와 메서드도 다양한데 IE/Safari/Opera/Chrome은 모두 화면 왼쪽위에서 각각 얼마나 떨어졌는지를 나타내는 screenLeft/screenTop 프로퍼티를 지원한다.
FF는 이 기능을 screenX/screenY 프로퍼티로 지원하는데 Safari/Chrome도 이 프로퍼티를 지원한다.

var leftPos = (typeof window.screenLefr == "number") ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ? window.screenTop  window.screenY;

이 예제는 사용해도 브라우져마다 지원하는 위치값의 차이가 있기 때문에 일관적으로 구할 방법은 없다.
하지만 moveTo()/moveBy() 메서드로 정확한 위치로 옮기는 일은 가능하다. 각 메서드는 두개의 매개변수를 받는데 moveTo()는 이동할 x/y 좌표를 받고 moveBy()는 각 방향으로 몇 픽셀 이동할지 나타내는 숫자를 받는다.
브라우저에서 이 메서드를 금지할 가능성이 있다.


8.1.4 창 크기
창크기를 알아내는 방법은 IE9/FF/Safari/Opera/Chrome 모두 innerWidth, innerHeight, outerWidth, outerHeight 네가지 프로퍼티를 지원한다.
outerWidth, outerHeight 브라우저 창 크기를 반환하고  innerWidth, innerHeight 프로퍼티는 브라우저 창 내부의 페이지 뷰포트 크기를 나타낸다.
IE/FF/Safari/Opera/Chrome 에서 document.documentElement.clientWidthdocument.documentElement.clientHeight 프로퍼티는 각각 페이지 뷰포트의 너비와 높이를 나타낸다.

8.1.5 네비게이션과 열기
window.open() 메서드는 URL 로 이동한 후 브라우저 창을 새로 연다.
이 메서드는 이동할 URL, 대상 창, 기능을 나타내는 문자열, 새 페이지가 브라우저 히스토리에서 현재 페이지를 대체할지 나타내는 불리언 값 네가지 매개 변수를 받는데 일반적으로 세번째 매개변수까지만 사용하며 마지막 매개변수는 새 창을 열때는 적용되지 않는다.
window.open()의 두 번째 매개변수가 이미 존재하는 창이나 프레임 이름이라면 주어진 URL은 해당 이름의 창이나 프레임에서 열린다.

팝업창
두 번재 매개변수가 기존의 창/프레임 이름이 아니라면 세 번재 매개변수에 지정한 문자열로 새 창이나 탭을 생성하고 세번째 매개변수가 없다면 새 브라우져 창이 열리고 기본 브라우저 창 설정(툴바, 주소표시 줄, 상태 바 등)이 적용된다. 세 번째 매개변수는 새 창을 열 때에만 적용되고 새 창의 정보를 나타내는 쉼표로 구분된 문자열이다.

fullscreen = "yes" or "no" : 브라우저 창을 최대 크기로 생성할지 나타냄(IE전용)
height = 숫자 : 새창의 높이를 나타냄, 최소값은 100
left = 숫자 : 새 창의 x 좌표로 음수는 쓸수 없음
location = "yes" or "no" : 주소 표시줄을 표시할지 나타냄, 기본값은 브라우저에 따라 다름
menubar = "yes" or "no"  : 메뉴바를 표시할지 나타냄, 기본값은 "no"
resizable = "yes" or "no"  : 새 창의 테두리를 드래그해서 크기를 조절할수 있는지 나타냄, 기본값은 "no"
scrollbas = "yes" or "no"  : 새 창 컨텐츠가 뷰포트를 넘칠 때 스크롤을 허용할지 나타냄, 기본값은 "no"
status = "yes" or "no"  : 상태바를 표시할지 나타냄, 기본값은 브라우저에 따라 다름
toolbar = "yes" or "no"  : 툴바를 표시할지 나타냄, 기본값은 "no"
top = 숫자  : 새 창의 y 좌표, 음수는 쓸 수 없음
width = 숫자 : 새 창의 너비, 최소값은 100


이름- 값  쌍은 등호(=)로 구분하며 각 쌍은 공백을 포함할 수 없다.
window.open("http://www.wrox.com/","wroxWindow","height=400,width=400,top=10,left=10,resizable=yes");

팝업 차단
브라우저에 내장된 팝업 차단기가 동작했다면 window.open()은 대개 null을 반환한다.


8.1.6 인터벌과 타임아웃(setTimeout(), clearTimeout())
브라우저에서 자바스크립트는 단일 스레드로 실행되지만 타임아웃과 인터벌을 통해 코드가 특정 시간에 실행되게끔 조절할 수 있다.
타임아웃은 일정 시간 뒤에 코드를 실행하는 것이고, 인터벌은 일정 시간마다 코드를 반복 실행하는 것이다.
타임아웃은 window의 setTimeout() 메서드로 설정한다. 이 메서드는 매개 변수를 두 개 받는데 하나는 실행할 코드이고 하나는 코드를 실행할 때까지 기다리는 시간(밀리초)이다.
setTimeout()을 호출하면 해당 타임아웃의 숫자형 ID를 반환하고 대기중인 타임아웃을 취소하려면 다음 예제처럼 clearTimeout() 메서드에 타임아웃 ID를 넘긴다.

타임아웃으로 실행하는 코드는 항상 전역 스코프에서 실행되므로 함수의 this값은 스트릭트 모드가 아닐 때는 항상 window이고 스트릭트 모드에서는 항상 undefined이다.

인터벌은 타임아웃과 비슷하지만 페이지가 종료되거나 인터벌을 취소하기 전에는 일정한 시간마다 코드를 반복 실행한다는 점이 다르다. setInterval() 메서드로 인터벌을 설정하며 이 메서드는 setTimeout()과 같은 매개변수, 즉 실행할 코드(문자열 또는 함수)와 각 실행 사이에 대기할 시간을 밀리초로 받는다.
setInterval() 메서드 역시 인터벌 ID를 반환하며 clearInterval() 메서드는 이 ID를 매개변수로 받아 해당 인터벌을 취소한다. 인터벌을 취소하지 않으면 페이지가 떠 있는 동안 계속 실행되므로 인터벌 취소는 타임아웃 취소보다 중요하다.


8.1.7 시스템 대화상자
브라우저는 alert(), confirm(), prompt() 메서드를 통해 사용자에게 시스템 대화상자를 표시한다.
얼럿 대화상자는 일반적으로 에러처럼 사용자가 할수 있는 일이 없지만 반드시 알려야 할때 쓴다.
컨펌 대화상자는 확인과 취소버튼이 있어서 사용자가 선택할 수 있고, true 또는 false 불리언 값을 반환한다.
프롬프트 대화상자는 확인과 취소버튼 외에도 사용자가 데이터를 입력하는 텍스트 박스가 있다. prompt() 메서드는 매개변수를 두개 받는데 하나는 대화상자에 표시할 텍스트이며 하나는 텍스트 박스의 기본값(빈 문자열 가능)이다.

 

8.2 location 객체
location 객체는 현재 창에 불러온 문서 정보와 함께 일반적인 네비게이션 기능을 제공한다. location 객체는 window 의 프로퍼티인 동시에 document의 프로퍼티다. location은 현재 문서에 대한 정보를 갖고 있으며 URL 을 파싱해서 몇가지 조각으로 분리해 각각을 프로퍼티로 저장한다.


8.2.1 쿼리스트링 확장
URL 정보중 쿼리스트링은 다루기 쉬운 형태로 제공되지는 않으므로 쿼리스트링을 파싱해서 각 매개변수를 프로퍼티로 갖는 객체를 반환한다.


8.1.2 location 조작
다양한 방법으로 location 객체를 조작해서 페이지를 이동할 수 있다. 가장 많이 쓰이는 것은 assign() 메서드다.

location.assign("http://www.wrox.com"); 


이렇게하면 즉시 새 URL로 이동하며 브라우저의 히스토리 스택에 기록이 추가되는데 lacation.href이나 window.lacation에 URL을 지정하면 그 값으로 assign() 메서드를 호출한다.  헤이지를 이동하는 이 세가지 방법중에서 lacation.href을 설정하는 방법이 가장 자주 쓰인다.
location 객체의 프로퍼티를 변경하면 현재 페이지에도 영향이 있다. hash, search, hostname, port 프로퍼티를 변경하면 현재 URL에 새 값이 반영되며 새 URL로 페이지를 다시 읽는데 hash 프로퍼티를 바꿀 때는 예외이다.

 location.hash ="#section1";
 location.search = "?q=javascript";
 location.hostname = "www.yahoo.com";
 location.patname = "mydir"; 

이와 같은 방법으로 URL을 수정하면 브라우저의 히스토리 스택에 기록이 남아 사용자가 뒤로가기 버튼을 클릭해 이전 페이지로 돌아갈 수 있다. replace() 메서드를 쓰면 매개변수로 URL을 받아 이동하지만 히스토리 스택에 기록을 남기지 않기 때문에 뒤로가기 버튼을 클릭해 이전 페이지로 돌아갈 수 없다.

현재 위치를 다시 불러오는 reload() 메서드는 매개변수 없이 호출하면 페이지를 가능한 한 가장 효과적인 방법으로 다시 읽는다. 마지막 요청이후 페이지가 바뀌지 않았다면 브라우저 캐시에서 읽어오는데 서버에서 읽어오도록 강제하려면 true를 매개변수로 넘긴다.

location.reload(); // 가능하면 캐시에서
location.reload(true); // 항상 서버에서 

reload() 호출 이후에 있는 코드는 네트워크 지연이나 시스템 자원 같은 요인의 영향으로 코드 마지막에 두는 것이 최선이다.

 


8.3 navigator 객체
navigator 객체의 프로퍼티는 일반적으로 웹 페이지를 실행중인 브라우저 타입을 판단하는데 사용한다.
브라우저에 따라 navigator 객체에서 지원하는 프로퍼티가 다르다.


8.3.1 플러그인 감지
스크립트로 가장 많이 탐지하는 것 중 하나는 브라우저에 특정 플러그인이 설치되어 있는지이다. IE 이외의 브라우저에서는 plugins 배열에서 이 정보를 얻을수 있다.

name - 플러그인 이름
description - 플러그인 설명
filename - 플러그인 파일 이름
length - 플러그인이 처리하는 마임 타입 숫자

일반적으로 name만 있으면 플러그인을 식별하기 충분하지만 항상 그렇지는 않다.


각 plugin 객체는 MineType 객체의 배열이기도 하며 대괄호 표기법으로 접근 가능하다. 각 Mime Type 객체에는 프로퍼티가 네개 있는데 마임 타입 설명인 description, plugin, 객체를 가리키는 포인터인 enablePlugin, 마임 타입의 파일 확장자를 쉼표로 구분한 문자열인 suffixes, 마지막으로 완전한 마임 타입 문자열인 type이다.


IE는 넷스케이프 스타일 객체를 지원하지 않으므로 플러그인 탐지가 어렵다. IE는 플러그인을 COM 객체로 구현했고 이들을 고유한 문자로 식별하기 때문에 hasIEPlugin() 함수로 IE 전용타입인 ActiveXObject를 사용해서 플러그인을 인스턴스화 하는 방법으로 플러그인 설치여부를 판단하는 함수를 만들수 있다.

plugins 컬렉션에는 refresh() 라는 메서드가 있는데 이 메서드는 새로 설치된 플러그인이 반영되도록 plusgins을 갱신한다. 이 메서드는 매개변수로 페이지를 새로고침해야 하는지 나타내는 불리언 값을 받는다.





8.3.2 처리기 등록
FF2는 navigator 객체에 registerContentHangler()와  regitorProtocalHandler() 메서드를 도입했다.
이 메서드는 웹사이트가 특정한 타입의 정보를 처리할 수 있음을 나타낸다.
registerContentHangler() 메서드는 처리할 마임타입, 해당 마임 타입을 처리할 페이지 URL, 애플리케이션 이름 세가지 매개변수를 받는다.
regitorProtocalHandler()은 처리할 프로토콜("mailto", "ftp" 등), 프로토콜을 처리할 페이지 URL, 애플리케이션 이름을 매개변수로 받는다. 




8.4 screen 객체
screen 객체 역시 window의 프로퍼티인데 이 객체에는 픽셀 너비와 높이 등 클라이언트 화면에 관한 정보가 들어있고 브라우저별로 screen 객체에서 지원하는 프로퍼티가 다르다.




8.5 historty 객체
history 객체는 창을 첫 번째 연 이후 사용자의 네비게이션 히스토리를 보관한다.
history는 window의 프로퍼티이므로 브라우저 창, 탭, 프레임은 각각 자신의 window 객체에 속한 history 객체를 가진다.

go() 메서드는 사용자의 이동 히스토리에서 앞으로 또는 뒤로 이동한다. 이 메서드는  매개변수로 이동할 페이지 수를 나타내는 하나의 정수를 받는데,음수를 받으면 히스토리에서 뒤로 이동하고 양수를 받으면 앞으로 이동한다.
매개변수로 문자열을 받는 경우 브라우저는 히스토리에서 해당 문자열을 포함한 첫 번째 위치로 이동한다.
go() 메서드 대신 단축 메서드인 back()forward() 메서드를 쓸수 있다.

history 객체의 length  프로퍼티는 history 스택에 기록이 얼마나 많이 있는지 나타낸다.

페이지의 URL이 바뀔 때마다 히스토리 스택에 새 기록이 추가된다. IE8 이상, Opera FF Safari3 이상, 크롬에서는  이 기록에 URL 해시가 포함되며 따라서 이들 브라우저에서 location.hash를 설정하면 히스토리 스택에 새 기록이 추가된다




 

'나홀로스터디 > JS For Web Dev' 카테고리의 다른 글

DOM  (0) 2014.12.08
클라이언트 감지  (0) 2014.11.20
함수 표현식  (0) 2014.10.23
참조타입  (0) 2014.10.17
객체에 대한 이해  (0) 2014.10.15
Copyright © HuckleberryM All Rights Reserved | JB All In One Designed by CMSFactory.NET