프로그래밍/JS

8장) 브라우저 객체 모델

소복 2016. 4. 6. 17:31

BOM은 웹 페이지 콘텐츠와 무관하게 브라우저 기능을 노출하는 객체이다.

제대로 된 명세가 없는 기간이 길었기에 브라우저 제조사들은 자신들이 원하는 대로 BOM을 확장했고,

이는 흥미로운 결과를 낳기도 했지만 문제도 많이 생겼다.

HTML5 명세에서 BOM의 주요 부분을 다룹니다.

 

8.1 window 객체

BOM의 핵심에는 브라우저의 인스턴스인 window 객체가 있다.

window 객체는 브라우저 창의 자바스크립트 인터페이스 구실을 하고 다른 한 편으로는 ECMAScript Global 객체로 기능한다.

따라서 웹 페이지에서 정의한 모든 객체, 변수, 함수에서는 window가 Global 객체 구실을 하며 window에 정의된 parseInt()등의 메서드를 이용한다.

 

8.1.1 전역 스코프

전역에서 선언한 변수와 함수는 모두 window 객체의 프로퍼티 및 메서드가 된다.

전역 변수가 window 객체의 프로퍼티가 되면 delete 연산자로 제거할 수 는 없다.

하지만 직접 window에 정의하면 delete로 제거할 수 있다.

선언한 적이 없는 변수에 접근하려 하면 에러가 발생하지만 window.[선언하지 않은 변수명]은 undefined를 반환할 뿐이다.

 

8.1.2 창 사이의 관계와 프레임

페이지의 각 프레임은 독자적인 window 객체를 가지며 이 객체들은 frames 컬렉션에 저장된다.

각 객체는 인덱스와 프레임 이름 두 가지로 색인할 수 있다. 각 객체는 프레임의 name을 프로퍼티로 가진다.

ex)

<frameset rows="160,*">

<frame name="topFrame">

<frameset cols="50%,50%">

<frame name="leftFrame">

<frame name="rightFrame">

</frameset>

</frameset>

위 예제에서 topFrame은 window.frames[0]으로도, window.frames["topFrame"]으로도 참조할 수 있다.

항상 최상위(가장 바깥) 프레임을 가리키는 top 객체가 있다.

따라서 top.frames[0]으로 topFrame을 가리킬 수 있다.

 

window 객체 중에는 항상 현재 프레임의 바로 상위 부모 프레임을 가르키는 parent도 있다.

topFrame의 parent는 최상위 프렘임이므로 top을 가리킨다.

 

최상위 window에는 name 프로퍼티 값이 존재하지 않는다. (뒤에서 설명할 window.open()을 통해 창을 열었을 때는 예외이다.)

 

마지막 window 객체는 self이다. 이 객체는 항상 window를 가리킨다.

사실 window와 self는 서로 바꿔서 써도 된다.

 

8.1.3 창의 위치

창의 위치를 가져오거나 설정하는 프로퍼티와 메서드는 다양하다.

인터넷 익스플로러, 사파리, 오페라, 크롬은 모두 screenLeft/screenTop라는 화면을 기준으로 창이 왼쪽/위에서 각각 얼마나 떨어졌는지를 나타내는 프로퍼티를 지원한다.

파이어폭스는 이 기능을 screenX/screenY로 지원하며 사파리와 크롬도 이 프로퍼티를 지원한다.

오페라에서도 지원하긴 하지만 screenLeft/screenTop과 값이 다르므로 screenX/screenY를 쓰지 말아야 한다.

이 값은 브라우저에 무관하게 일관적으로 구하는 방법이 없다.

 

하지만 moveTo()/moveBy() 메서드로 정확한 위치로 옮기는 일은 가능하다.

moveTo()는 이동할 x, y좌표를 받고 moveBy()는 각 방향으로 몇 px을 이동할지를 받는다.

대부분의 브라우저에서 이 메서드들은 기본적으로 비활성화되어 있다.

또한 이 메서드들은 오직 최상위 창에서만 동작한다.

 

8.1.4 창 크기

창 크기를 알아내는 방법은 어떤 브라우저든 복잡하다. (따라서 생략하도록 하겠습니다. ^^)

창 크기를 조절할 때는 resizeTo()/resizeBy() 메서드를 사용한다.

resizeTo()는 변경할 너비, 높이를 받고 resizeBy()는 너비, 높이를 얼만큼 바꿀지를 받는다.

창의 크기를 바꾸는 메서드 역시 대부분의 브라우저에서 기본적으로 금지되어 있으며 최상위 window 객체에만 적용된다.

 

8.1.5 내비게이션과 열기

window.open() 메서드는 URL로 이동한 후 브라우저 창을 새로 연다.

window.open(이동할 URL, 대상 창, 새 창의 기능을 나타내는 문자열, 브라우저 히스토리에서 현재 페이지를 대체할지 나타내는 불리언 값)

으로 매개변수를 받으며 일반적으로 세 번째 매개변수까지만 사용하며, 마지막 매개변수는 새 창을 열 때는 적용되지 않는다.

두 번째 매개변수가 이미 존재하는 창이나 프레임 이름이라면 URL은 해당 이름의 창이나 프레임에서 열린다.

그렇지 않다면 새 창을 생성하고 이름을 새로이 지정한다. (특별한 창 이름인 _self, _parent, _top, _blank도 쓸 수 있다.)

 

팝업 창

두 번째 매개변수가 기존의 창/프레임 이름이 아니라 새 창이나 탭이 생성된다.

이 때 세 번째 매개변수는 새 창의 설정 정보를 나타내며 쉼표로 구분된 문자열이다. (새 창을 열 때에만 적용된다.)

옵션 종류

- fullscreen : 브라우저 창을 최대 크기로 생성할지

- height : 새 창의 높이

- left : 새 창의 x 좌표

- location : 주소 표시줄을 표시할지

- menubar : 메뉴 바를 표시할지

- resizeable : 새 창의 크기를 조절할 수 있는지

- scrollbars : 스크롤을 허용할지

- status : 상태 바를 표시할지

- toolbar : 툴바를 표시할지

- top : 새 창의 y 좌표

- width : 새 창의 너비

 

window.open()은 새로 생성한 창에 대한 참조를 반환한다.

반환된 객체는 다른 window 객체와 같지만 좀 더 세밀히 조절할 수 있다.

예를 들어 기본적으로 금지된 기능인 창의 위치나 크기를 바꾸는 기능을 사용할 수 있다.

반환된 객체는 사용자 확인을 거치지 않고서도 close() 메서드를 사용해서 닫을 수 있다.

창을 닫으면 창에 대한 참조는 여전히 존재하지만, closed 프로퍼티를 확인하는 용도 이외에는 쓸 수 없다.

새로 생성된 window 객체에는 자신을 연 창을 참조하는 opener 프로퍼티가 있다.

크롬에서는 새 탭을 생성할 때 opener 프로퍼티를 null로 설정하여 프로세스를 분리할 수 있다.

 

보안 제한

브라우저 제조사들은 팝업 창 설정을 제한하여 사용자가 혼동하는 일을 줄이려 했다.

따라서 일부 브라우저에서 주소 표시줄이나 상태 바를 숨길 수 없는 경우가 있다.

또한 브라우저들은 팝업 창을 사용자의 행동에 의해서만 열 수 있게 한다.

 

팝업 차단

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

외부 프로그램이 팝업을 차단한 경우라면 window.open()은 일반적으로 에러를 반환한다.

따라서 다음과 같이 try-catch문을 사용해야한다.

ex)

var blocked = false;

 

try{

var a = window.open("http://naver.com");

if(a == null)

blocked=true;

}catch(ex){

blocked=true;

}

 

if(blocked)

alert("The popup was blocked!");

 

8.1.6 인터벌과 타임아웃

자바스크립트는 단일 스레드로 실행되지만 타임아웃과 인터벌을 통해 코드가 특정 시간에 실행되게끔 조절할 수는 있다.

타임아웃은 일정 시간 뒤에 코드를 실행하는 것이고, 인터벌을 일정 시간마다 코드를 반복 실행하는 것이다.

 

타임아웃은 window의 setTimeout() 메서드로 설정한다.

이 메서드는 두 개의 매개변수를 받는다. 하나는 실행할 코드이고 다른 하나는 코드를 실행할 때까지 기다리는 시간(밀리초)이다.

실행할 코드는 문자열로도 가능하며 함수도 가능하다. 하지만 문자열을 넘기면 성능이 떨어지므로 좋은 방법이 아니다.

자바스크립트는 큐를 이용해 코드의 실행을 관리한다. 각 작업은 큐에 추가된 순서대로 실행된다.

setTimeout()은 해당 밀리초만큼 기다린 다음 작업을 큐에 추가하도록 한다.

setTimeout()은 숫자형 ID를 반환하며 타임아웃을 취소할 때 사용한다. ex) clearTimeout(timeoutID);

 

인터벌은 타임아웃과 비슷하지만 페이지가 종료되거나 인터벌을 취소하기 전에는 일정한 시간마다 코드를 반복 실행한다는 점이 다르다.

setInterval() 메서드로 인터벌을 설정하며 첫 번째 매개변수는 실행할 코드이고,

두 번째 매개변수는 각 실행 사이에 대기할 시간(밀리초)을 받는다.

이 역시 인터벌 ID를 반환하며 ID로 인터벌을 취소할 수 있다.

인터벌은 취소하지 않으면 페이지를 종료하지 않는한 계속 실행되므로 중요하다. ex) clearInterval(intervalID);

 

일반적으로 인터벌을 쓰지 않는 편이 낫다.

 

8.1.7 시스템 대화상자

브라우저는 alert(), confirm(), prompt() 메서드를 통해 사용자에게 시스템 대화상자를 표시한다.

대화상자의 외관은 CSS가 아니라 OS/브라우저 설정에 따라 다르다.

또한 대화상자는 동기적이고 모달(modal)성질이 있어서 대화상자가 떠 있을 때는 코드 실해이 중지되고 대화상자를 닫아야 재개된다.

 

find, print 두 가지 대화상자를 더 표시할 수 있다.

두 대화상자 모두 비동기적으로 표시되며 대화상자 차단 기능에 영향 받지도 않는다.

 

window.print(); // 인쇄 대화상자 표시

window.find() // 찾기 대화상자 표시

 

8.2 location 객체

BOM에서 가장 유용한 객체 중 하나이다.

 

 

[출처: 프론트엔드 개발자를 위한 자바스크립트 프로그래밍]