웹브라우저의 구성요소들은 객체화되어있다. window라는 전역 객체 밑에 DOM, BOM, JavaScript가 있다.
DOM은 웹페이지 내용을 제어한다. window의 document 프로퍼티에 할당된 Document 객체의 프로퍼티와 메소드를 활용하여 제어한다. (document.body, document.getElementByTagName() 등)
BOM은 웹페이지의 내용을 제외한 브라우저의 각종 요소들을 객체화한 것이다. window의 프로퍼티에 객체로서 속해있다. (alert(), window.open() 등)
window의 프로퍼티나 메소드를 사용할 때 window 식별자를 생략할 수도 있다.
ex) alert();
전역에서 객체와 변수, 함수 등을 선언하면 이는 곧 전역 객체의 프로퍼티 및 메소드로 저장되는 것과 같다.
window는 전역 객체이면서 동시에 웹브라우저의 창이나 프레임을 제어하는 역할을 한다.
alert('text'); // 알림
confirm('text'); // 확인, 취소
prompt('text'); // 텍스트 입력
window 객체의 프로퍼티, 즉 전역에 존재하는 객체이다.
문서의 주소와 관련된 객체로, 윈도우의 문서 URL을 변경할 수도 있고, 문서 위치 관련 정보를 다양하게 얻을 수 있다.
location.toString() or location.href : 현재 윈도우의 문서가 위치하는 경로 URL을 리턴한다.
URL 파싱 : URL에서 특정 의미를 갖는 부분들을 프로퍼티로서 접근할 수 있다.
protocol, host, port, pathname, search, hash
(ex- location.protocol)
URL 변경 : 현재 문서의 주소를 변경하거나 리로드할 수 있다.
location.href = 'http://www.naver.com';
location = 'http://www.naver.com';
location.reload();
브라우저의 정보를 제공하는 객체이다. 주로 호환성 문제 등을 위해 사용된다.
주요한 프로퍼티 몇 가지를 알아보자.
appName
: 웹 브라우저의 이름이다. IE는 Microsoft Internet Explorer, 파이어폭스와 크롬 등은 Netscape로 표시된다.
appVersion
: 브라우저의 버전을 의미한다.
userAgent
: 브라우저가 서버 측으로 전송하는 User-Agent HTTP header의 내용이다. 스크래핑할 때 requests.get의 headers 파라미터로 이 값을 같이 넘겨주면 bot으로 인식되는걸 방지할 수도 있다.
platform
: 브라우저가 동작하고 있는 운영체제에 대한 정보이다.
Navigator 객체를 활용하여 브라우저 별로 코드를 다르게 동작하게하여 호환성을 보장할 수 있지만, 브라우저들의 수도 많고 새로운게 나올 수도 있고, 유지보수되면서 계속 바뀌기때문에 쉬운 일이 아니다.
그래서 기능 테스트라는 방법이 더 선호되고 있다.
기능 테스트로 해당 브라우저가 특정 기능을 갖고 있는지 여부를 판단할 수 있다.
예를 들어서 Object.keys() 라는 메소드는 ECMAScript5에 추가된 메소드이므로 그 전의 버전에는 존재하지 않는 메소드이다.
따라서 특정 브라우저에서 이 메소드가 존재하는지 검사하고 없다면 그 메소드를 직접 구현해주는 기능 테스트를 한다.
만약 직접 구현한 메소드도 브라우저마다 정상 작동의 유무가 갈린다면, 그 때는 Navigator 객체를 활용하여 브라우저 별로 또 if문을 분기하면 된다.
ex)
if (!Object.keys) {
Object.keys = (function () {
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
}());
}
window.open();
첫 번째 인자 : 문서의 주소 (현재 위치라면 demo2.html 이런식으로 파일명만)
두 번째 인자 : 창을 어떻게 띄울것인지(_self, _blank, text(창 이름 지정) 등)
세 번째 인자 : 창의 속성 지정(width, height, resizable(boolean값) 등)
ex)
window.open('demo2.html', '_blank', 'width=200, height=200, resizable=yes');
해당 코드는 서버를 띄우고 같은 도메인에서 실행해야 작동하는 코드이다.
<!DOCTYPE html>
<html>
<body>
<input type="button" value="open" onclick="winopen();" />
<input type="text" onkeypress="winmessage(this.value)" />
<input type="button" value="close" onclick="winclose()" />
<script>
function winopen(){
win = window.open('demo2.html', 'ot', 'width=300px, height=500px');
}
function winmessage(msg){
win.document.getElementById('message').innerText=msg;
}
function winclose(){
win.close();
}
</script>
</body>
</html>
winopen()을 살펴보자.
window.open으로 demo2.html을 새 창으로 띄운다. 이 때 open 메소드는 새 창의 전역 객체인 window를 리턴하여 win에 담게 된다.
winmessage()에서는 input 태그에 입력된 text 값을 인자로 받아와서(msg), msg를 새 창의 전역 객체가 담긴 win을 활용하여 새 창의 ID가 message인 element에 접근하여 그 것의 텍스트를 msg로 설정한다. 즉 원래의 창에서 입력한 텍스트를 새 창의 어떤 element의 텍스트로 설정해주는 상호작용을 한다.
winclose()는 새 창을 닫는다.(새 창의 전역 객체 window의 close 메소드 호출)
웹 브라주에서 사용자의 상호 작용없이 창을 열려고 하면 팝업이 차단된다.
window.open(); 를 스크립트 태그에 넣어놓은 html을 실행해보자. 팝업이 차단되는 것을 볼 수 있을 것이다.
브라우저에서 보안성은 아주 중요하다.
브라우저는 사용자의 로컬 환경에 접근할 수 있는 권한이 있는데, 만약 어떤 웹 사이트에 접속했을 때 그 웹 사이트가 내 컴퓨터에 자유롭게 접근하게 된다면 상당한 보안 취약점이 될 것이다. 그래서 이를 미연에 방지하고자 사용자의 상호 작용없이 실행하려는 스크립트를 미리 차단하거나 동의를 얻는다. 시대의 흐름을 거쳐 사용자를 위해 브라우저 측에서 정립한 정책의 일환이다.
이 전의 새 창 띄우고 상호작용하는 코드가 같은 도메인에서만 실행되는 이유도, 다른 도메인의 사이트끼리는 이를 보안상의 문제로 차단하기 때문임.
물론 사용자가 직접 클릭을 하는 등의 명시적인 상호 작용 의도가 있는 경우에는 해당 스크립트를 실행해준다.
Document Object Model
웹 페이지를 JS로 제어하기 위한 객체 모델을 의미한다.
브라우저의 전역 객체 window의 프로퍼티를 통해 사용할 수 있다. (window.document)
window 객체가 창을 의미한다면 Document 객체는 로드된 문서를 의미한다고 할 수 있다.
이를 통해 문서를 제어해보자.