BOM(Browser Object Model) 개요
BOM은 웹 브라우저의 다양한 기능에 자바스크립트가 접근하고 제어할 수 있도록 하는 객체 모델입니다. 웹 표준에 포함되지는 않지만, 모든 브라우저에서 공통적으로 지원하는 객체들을 포함하고 있습니다. 이 모델을 통해 자바스크립트는 브라우저 창, 히스토리, 화면 정보 등에 상호작용할 수 있습니다.
window 객체
모든 브라우저 환경에서 window 객체는 최상위 객체로 존재하며, 현재 브라우저 창 자체를 나타냅니다. 모든 전역 변수, 함수 선언은 사실상 window 객체의 속성 또는 메서드가 됩니다. HTML 문서 내부에 <frame>이나 <iframe> 같은 프레임이 있다면, 각 프레임마다 별도의 window 객체가 생성됩니다. 우리가 흔히 사용하는 document 객체 또한 window 객체의 속성 중 하나입니다.
주요 window 객체 메서드 및 속성:
window.innerHeight: 브라우저 뷰포트의 내부 높이(픽셀)window.innerWidth: 브라우저 뷰포트의 내부 너비(픽셀)window.open(): 새 브라우저 창이나 탭을 엽니다.window.close(): 현재 브라우저 창을 닫습니다.
window.open() 메서드 사용 예시:
window.open('https://www.example.com/', '_blank', 'width=1000,height=600,left=100,top=100');
// 첫 번째 인자는 URL, 두 번째 인자는 창 열기 방식(_blank는 새 탭), 세 번째 인자는 창의 크기 및 위치 설정
window 객체의 주요 하위 객체
window 객체는 여러 유용한 하위 객체들을 포함합니다.
navigator 객체
사용자 브라우저와 운영체제에 대한 정보를 제공합니다. 주로 사용자 에이전트(User Agent) 문자열을 통해 브라우저 종류, 버전, 운영체제 정보를 얻을 수 있습니다.
console.log(navigator.userAgent); // 예: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/..."
history 객체
브라우저의 세션 히스토리(방문 기록)를 관리합니다. 보안상의 이유로 정확한 URL 목록은 접근할 수 없지만, 사용자가 이전 또는 다음 페이지로 이동하도록 제어할 수 있습니다.
history.back(); // 이전 페이지로 이동
history.forward(); // 다음 페이지로 이동
screen 객체
사용자의 화면(디스플레이) 정보를 제공합니다.
console.log(`사용 가능한 화면 너비: ${screen.availWidth}px`);
console.log(`사용 가능한 화면 높이: ${screen.availHeight}px`);
location 객체
현재 웹 페이지의 URL 주소에 대한 정보를 제공하며, URL 변경을 통해 페이지 이동도 가능합니다.
console.log(location.href); // 현재 페이지의 전체 URL 가져오기
location.href = "https://newsite.com"; // 특정 URL로 페이지 이동
location.reload(); // 현재 페이지 새로 고침
브라우저 팝업 대화상자
사용자와의 간단한 상호작용을 위한 팝업을 제공합니다.
alert('메시지'): 사용자에게 경고 메시지를 표시합니다. 반환 값은 없습니다.confirm('질문?'): 사용자에게 확인/취소 질문을 하고, 선택에 따라true또는false를 반환합니다.prompt('질문', '기본값'): 사용자로부터 텍스트 입력을 받고, 입력된 값을 문자열로 반환합니다. 취소 시null을 반환합니다.
타이머 함수
일정 시간 후 또는 일정 시간 간격으로 특정 코드를 실행할 수 있습니다.
- 지연 실행 타이머 (
setTimeout): 한 번만 지정된 시간 후에 함수를 실행합니다.
const delayedActionId = setTimeout(() => {
alert("3초 후에 이 메시지가 나타납니다!");
}, 3000); // 3초 (3000 밀리초) 지연
// 필요하다면, 타이머를 취소할 수 있습니다.
// clearTimeout(delayedActionId);
setInterval): 지정된 시간 간격마다 함수를 반복적으로 실행합니다.let counter = 0;
const repeatedActionId = setInterval(() => {
counter++;
console.log(`반복 실행: ${counter}회`);
if (counter >= 5) {
clearInterval(repeatedActionId); // 5회 실행 후 타이머 중지
console.log("반복 타이머가 종료되었습니다.");
}
}, 2000); // 2초마다 실행
| 메서드 | 설명 |
|---|---|
setTimeout(callback, delay) |
delay 밀리초 후에 callback 함수를 한 번 실행합니다. |
clearTimeout(id) |
setTimeout으로 설정된 타이머(id로 식별)를 취소합니다. |
setInterval(callback, interval) |
interval 밀리초 간격으로 callback 함수를 반복 실행합니다. |
clearInterval(id) |
setInterval으로 설정된 반복 타이머(id로 식별)를 중지합니다. |
DOM(Document Object Model) 이해
DOM은 HTML, XML 문서를 프로그래밍적으로 접근하고 조작할 수 있도록 트리 구조로 표현하는 인터페이스입니다. W3C 표준에 의해 정의되며, 웹 페이지의 모든 요소(태그, 텍스트, 속성 등)를 "노드(Node)"라는 객체로 간주하여 자바스크립트가 이 노드들을 동적으로 생성, 수정, 삭제할 수 있게 합니다.
HTML DOM 트리 구조
DOM은 HTML 문서를 다음과 같은 노드 타입으로 구성합니다.
- 문서 노드 (
Document객체): 전체 HTML 문서를 나타내는 최상위 노드입니다. - 요소 노드 (
Element객체):<div>,<p>,<a>와 같은 HTML 태그 하나하나를 나타냅니다. - 텍스트 노드 (
Text객체): HTML 태그 내의 순수한 텍스트 콘텐츠를 나타냅니다. - 속성 노드 (
Attribute객체): 요소 노드의 속성(예:id="myId",href="url")을 나타냅니다. - 주석 노드 (
Comment객체): HTML 주석(<!-- ... -->)을 나타냅니다.
노드 탐색 (Element Selection)
자바스크립트에서 특정 HTML 요소를 조작하려면, 먼저 해당 요소를 DOM 트리에서 찾아야 합니다. 노드 탐색 메서드는 주로 document 객체에서 호출됩니다.
직접 탐색
ID, 클래스, 태그 이름 등을 사용하여 요소를 직접 찾습니다.
- ID로 탐색: 문서 내에서 유일한 ID 값을 가진 요소를 찾습니다.
- 클래스 이름 및 태그 이름으로 탐색: 여러 요소를 포함하는 HTML 컬렉션(
HTMLCollection)을 반환합니다. - CSS 선택자로 탐색 (
querySelector,querySelectorAll): CSS 선택자를 사용하여 요소를 탐색합니다.
const myContainer = document.getElementById('main-container');
if (myContainer) {
console.log(myContainer.tagName); // 예: DIV
}
const infoBoxes = document.getElementsByClassName('info-box'); // 'info-box' 클래스를 가진 모든 요소
const allParagraphs = document.getElementsByTagName('p'); // 모든 <p> 태그 요소
// 첫 번째 'highlight' 클래스 또는 'article' ID를 가진 요소를 찾음
const firstHighlight = document.querySelector('.highlight, #article-content');
// 모든 'item' 클래스 내부의 'button' 태그 요소를 찾음
const actionButtons = document.querySelectorAll('.item button');
간접 탐색 (관계 기반 탐색)
이미 선택된 노드를 기준으로 부모, 자식, 형제 노드를 탐색합니다.
parentElement: 부모 요소 노드children: 모든 자식 요소 노드의HTMLCollectionfirstElementChild: 첫 번째 자식 요소 노드lastElementChild: 마지막 자식 요소 노드nextElementSibling: 다음 형제 요소 노드previousElementSibling: 이전 형제 요소 노드
const currentItem = document.getElementById('current-item');
if (currentItem) {
const parentList = currentItem.parentElement; // 부모 <ul> 또는 <ol>
const nextSibling = currentItem.nextElementSibling; // 다음 <li>
console.log(`부모 태그: ${parentList ? parentList.tagName : '없음'}`);
console.log(`다음 형제 태그: ${nextSibling ? nextSibling.tagName : '없음'}`);
}
노드 조작 (Element Manipulation)
노드 생성
새로운 HTML 요소를 동적으로 생성합니다.
const newDiv = document.createElement("div"); // <div> 태그 생성
newDiv.textContent = "새롭게 추가된 요소입니다.";
newDiv.className = "dynamic-content";
노드 추가
생성된 노드를 DOM 트리의 특정 위치에 추가합니다.
parentNode.appendChild(childNode):parentNode의 마지막 자식으로childNode를 추가합니다.parentNode.insertBefore(newChild, referenceChild):parentNode의referenceChild앞에newChild를 삽입합니다.
const container = document.getElementById('content-area');
const firstChild = container.firstElementChild; // 컨테이너의 첫 번째 자식 요소
container.appendChild(newDiv); // newDiv를 마지막에 추가
const anotherElement = document.createElement("p");
anotherElement.textContent = "첫 번째 요소 앞에 삽입됩니다.";
container.insertBefore(anotherElement, firstChild); // 첫 번째 자식 앞에 삽입
노드 삭제 및 교체
기존 노드를 제거하거나 다른 노드로 교체합니다.
const parentElem = document.getElementById('list-container');
const itemToRemove = document.getElementById('item-delete'); // 삭제할 특정 요소
if (parentElem && itemToRemove) {
parentElem.removeChild(itemToRemove); // 'item-delete' 요소 삭제
}
const oldParagraph = document.getElementById('old-para');
const updatedParagraph = document.createElement('p');
updatedParagraph.textContent = "새로운 내용으로 대체되었습니다!";
if (parentElem && oldParagraph) {
parentElem.replaceChild(updatedParagraph, oldParagraph); // 'old-para'를 새로운 <p>로 교체
}
노드 속성 설정
요소의 텍스트 콘텐츠, HTML 콘텐츠, 사용자 정의 속성 등을 조작합니다.
텍스트/HTML 콘텐츠 조작:
| 속성 | 설명 | 예시 (가져오기) | 예시 (설정하기) |
|---|---|---|---|
element.innerText |
요소 내부의 순수 텍스트 콘텐츠(스타일 고려) | myDiv.innerText |
myDiv.innerText = '새로운 순수 텍스트'; |
element.innerHTML |
요소 내부의 HTML 콘텐츠(태그 포함) | myDiv.innerHTML |
myDiv.innerHTML = '<strong>새로운</strong> HTML 콘텐츠'; |
innerHTML은 태그를 인식하여 HTML 구조를 변경할 수 있는 반면, innerText는 텍스트만을 처리합니다.
일반 속성 조작:
element.setAttribute(name, value): 새로운 속성을 추가하거나 기존 속성 값을 설정합니다.element.getAttribute(name): 지정된 속성의 현재 값을 가져옵니다.element.removeAttribute(name): 지정된 속성을 제거합니다.
const userProfile = document.getElementById('profile-card');
userProfile.setAttribute('data-user-id', '12345'); // 'data-user-id' 속성 설정
console.log(userProfile.getAttribute('data-user-id')); // '12345'
userProfile.removeAttribute('data-user-id'); // 속성 제거
자주 사용되는 일부 속성들은 직접 접근할 수 있습니다.
const usernameInput = document.getElementById('username');
usernameInput.value = 'guest'; // <input> 요소의 value 속성 설정
console.log(usernameInput.value); // 현재 입력 필드의 값 가져오기
클래스(class) 조작:
const statusBox = document.getElementById('status-box');
statusBox.classList.add('active'); // 'active' 클래스 추가
statusBox.classList.remove('inactive'); // 'inactive' 클래스 제거
console.log(statusBox.classList.contains('active')); // 'active' 클래스 포함 여부 확인 (true/false)
statusBox.classList.toggle('highlight'); // 'highlight' 클래스가 있으면 제거, 없으면 추가
스타일(style) 조작:
CSS 속성은 자바스크립트에서 카멜 케이스(camelCase)로 변환하여 접근합니다.
const targetElement = document.getElementById('styled-element');
targetElement.style.backgroundColor = 'lightblue'; // 배경색 변경
targetElement.style.fontSize = '20px'; // 글꼴 크기 변경
targetElement.style.padding = '10px 15px'; // 패딩 설정
이벤트 처리 (Event Handling)
웹 페이지에서 발생하는 사용자의 상호작용(클릭, 키 입력 등)이나 브라우저의 변화(페이지 로드 등)를 "이벤트"라고 합니다. 자바스크립트는 이러한 이벤트가 발생했을 때 특정 코드를 실행하도록 연결할 수 있습니다.
주요 이벤트 유형
onclick: 요소가 클릭되었을 때 발생합니다. 버튼이나 링크 등에 주로 사용됩니다.onfocus: 요소가 포커스를 얻었을 때 발생합니다. 주로 폼 입력 필드에 사용됩니다.onblur: 요소가 포커스를 잃었을 때 발생합니다. 폼 입력 필드의 유효성 검사 등에 활용됩니다.onchange: 폼 요소의 값이 변경되고 포커스를 잃었을 때 발생합니다.<select>,<input type="checkbox">등에 유용합니다.onload: 웹 페이지의 모든 콘텐츠(HTML, 이미지, 스크립트 등)가 완전히 로드되었을 때 발생합니다.window.onload로 페이지 로드 완료 시점을 알 수 있습니다.
더 많은 이벤트 유형
onkeydown: 키보드 키가 눌렸을 때 발생합니다.
onkeypress: 키보드 키가 눌렸다가 해제되었을 때 발생합니다. (onkeydown과 유사하지만 일부 키는 다르게 처리)
onkeyup: 키보드 키가 해제되었을 때 발생합니다.
onmousedown: 마우스 버튼이 눌렸을 때 발생합니다.
onmousemove: 마우스 포인터가 요소 위에서 이동할 때 발생합니다.
onmouseout: 마우스 포인터가 요소 밖으로 이동했을 때 발생합니다.
onmouseover: 마우스 포인터가 요소 위로 진입했을 때 발생합니다.
onselect: 텍스트 입력 필드의 텍스트가 선택되었을 때 발생합니다.
onsubmit: 폼이 제출되었을 때 발생합니다. (form 요소에 적용)
이벤트 바인딩 (Event Binding)
이벤트와 실행할 함수를 연결하는 방법은 여러 가지가 있습니다.
1. HTML 인라인 속성 방식:
HTML 태그의 속성으로 직접 자바스크립트 코드를 작성합니다. 간편하지만 유지보수성이 낮고 HTML과 JS의 분리가 어려워 권장되지 않습니다.
<button id="myBtn" onclick="handleClick(this)">클릭하세요</button>
<script>
function handleClick(element) {
element.style.backgroundColor = 'salmon';
element.textContent = '클릭됨!';
}
</script>
this 키워드는 이벤트가 발생한 현재 요소를 참조합니다.
2. 자바스크립트 속성 할당 방식:
자바스크립트 코드 내에서 요소의 이벤트 속성에 함수를 할당합니다. 가장 흔하게 사용되는 방법 중 하나입니다.
<button id="jsBtn">JS로 이벤트 등록</button>
<script>
const jsButton = document.getElementById("jsBtn");
jsButton.onclick = function() {
this.style.backgroundColor = 'lightgreen';
this.textContent = '등록된 이벤트!';
console.log("버튼이 자바스크립트로 클릭되었습니다.");
};
</script>
이 방식에서도 함수 내부의 this는 이벤트가 발생한 요소를 가리킵니다.
3. addEventListener() 방식 (권장):
하나의 요소에 여러 개의 이벤트 핸들러를 등록할 수 있으며, 이벤트 전파(캡처링/버블링)를 더 세밀하게 제어할 수 있어 가장 유연하고 강력한 방법입니다.
<button id="modernBtn">최신 이벤트 등록</button>
<script>
const modernButton = document.getElementById("modernBtn");
// 첫 번째 핸들러
modernButton.addEventListener('click', () => {
console.log("첫 번째 클릭 이벤트 발생!");
modernButton.style.border = '2px solid blue';
});
// 두 번째 핸들러
modernButton.addEventListener('click', function() {
console.log("두 번째 클릭 이벤트 발생!");
this.textContent = '두 번 등록!';
});
// 이벤트 제거 (필요시)
// modernButton.removeEventListener('click', firstHandlerFunction);
</script>