상세 컨텐츠

본문 제목

[javascript] 문서 객체 다루기

Web/Javascript

by 클리엘 클리엘 2020. 5. 27. 02:51

본문

HTML 문서는 다수의 HTML 태그를 이용하고 구성됩니다. 이들 중 어떤 태그를 javascript상에서 다룰 수 있도록 요소로 가져오게 되면 그것을 '문서 객체'라고 할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var myspan = document.getElementsByTagName('span');
			alert(myspan[0].innerText);
		};
	</script>
</head>
<body>
	<span>document</span>
</body>
</html>

예제에서는 HTML문서의 span태그를 가져와 내부의 텍스트를 alert으로 표시하고 있습니다. getElementsByTagName은 요소를 배열로 반환하므로 myspan [0]처럼 가져올 요소의 인덱스를 지정해야 하는데

var myspan = document.getElementsByTagName('span');

처럼 하게되면 이때부터 myspan을 하나의 문서 객체로서 취급하게 되는 것입니다.

 

참고로 위의 문서를 아래와 같이 도식화 하여 표현할 수 있으며

 

위와 같이 표현된 문서전체의 구조를 '문서 객체 모델'이라고 합니다. 문서 객체 모델에서 표현되는 각각의 HTML 요소를 '노드'라고 하며 이때 요소 내부에 들어간 문자열을 별도로 '텍스트 노드'라고 부릅니다.

 

1. 요소 추가

 

문서객체는 기존에 존재하는 요소를 가지고 다룰 수 있지만 처음부터 존재하지 않는 HTML 요소를 아래와 같이 임의로 추가할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var myspan_node = document.createElement('span');
			var myspan_text = document.createTextNode('document');
			myspan_node.appendChild(myspan_text);

			document.body.appendChild(myspan_node);
		};
	</script>
</head>
<body>
	
</body>
</html>

처음에 body는 아무런 하위 요소도 가지고 있지 않습니다. 하지만 javascript를 통해 임의의 span요소 노드와 document라는 텍스트 노드를 생성해 span의 자식 요소로 텍스트 노드를 추가하고 있으며 최종적으로 body의 자식 요소로 span을 추가함으로써 처음 예제와 동일한 문서 구조를 갖도록 하고 있습니다.

 

어떤 경우는 위와 같이 메서드를 사용하는 것보다 아예 문자열로 태그를 생성해 통째로 추가시켜 주는 경우도 있습니다. 물론 이때도 메서드를 사용한것과 완전히 동일한 결과를 얻을 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var tag = '<span>document</span>';
			document.body.innerHTML = tag;
		};
	</script>
</head>
<body>
	
</body>
</html>

innerHTML 속성은 문자열로 지정된 내용을 HTML 요소로서 추가시켜주는 속성입니다. 이와는 좀 다르게 innerText 속성도 존재하는데 이 속성은 텍스트 노드로서 요소를 추가하게 됩니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var tag = '<span>document</span>';
			document.body.innerText = tag;
		};
	</script>
</head>
<body>
	
</body>
</html>

참고로 innerText속성은 문자열을 그대로 표현한다는 특징을 가지고 있지만 HTML 태그자체를 그대로 표현하기 위한 것이라면 textContent속성을 사용해야 합니다.

 

다시 본론으로 돌아와 위와 같은 방식으로 요소를 생성하는 경우 노드에 특정한 속성을 함께 부여해야 한다면 다음과 같이 할 수 있습니다. 다른 부분은 생략하고 필요한 내용만 추가하였습니다.

var myspan_node = document.createElement('span');
myspan_node.style = 'color:red;';

span 노드를 생성하면서 해당 노드에 style의 속성과 'color:red;'라는 값을 할당하였습니다.

 

기본적으로 제공하는 속성은 위와 같이 추가할 수 있으나 표준이 아닌 임의의 속성을 할당해야 한다면 setAttribute메서드를 사용해야 합니다.

var myspan_node = document.createElement('span');
myspan_node.style = 'color:red;';
myspan_node.setAttribute('data-myvalue', 'cliel.com');

예제에서 사용된 data-myvalue속성은 표준으로 제공하는 속성이 아니므로 setAttribute메서드를 사용해 'cliel.com'이라는 값으로 임의 생성하였습니다.

 

참고로 setAttribute라는 메서드와 반대로 getAttribute라는 메서드도 존재하는데 이 메서드는 지정한 속성의 값을 가져오는 메서드입니다.

 

2. 요소 추출

 

javascript에서는 문서에서 기존에 존재하는 요소를 가져올 수 있는 몇 가지 메서드를 제공하고 있습니다.

 

getElementById(id) 지정한 id의 요소를 가져옵니다.
getElementsByName(name) 지정한 name의 요소를 가져옵니다.
getElementsByTagName(tagName) 지정한 tagName에 해당하는 요소를 가져옵니다.

 

문서 안에서 HTML요소는 하나의 id값을 가질 수 있으며 이 id는 고유해야 합니다. 이러한 특징을 알면 getElementById메서드는 하나의 요소만을 가져온다는 것을 알 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var ms = document.getElementById('myspan');
			alert(ms.innerHTML);
		};
	</script>
</head>
<body>
	<span id="myspan">hello</span>
</body>
</html>

반면 name이라는 속성은 여러 요소에서 동일한 값을 가질 수 있으므로 getElementsByName메서드 또한 여러 개의 요소를 가져오게 되는 것이죠.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var ms = document.getElementsByName('food');
			alert(ms[1].value);
		};
	</script>
</head>
<body>
	<input type="radio" name="food" value="라면">
	<input type="radio" name="food" value="김밥">
	<input type="radio" name="food" value="순대">
</body>
</html>

예제에서는 getElementsByName에 의해 name이 food인 3개의 요소를 가져오게 되며 그중 2번째(배열 인덱스 상으로는 1번)의 value값을 출력하고 있습니다.

 

마지막으로 getElementsByTagName메서드는 매개변수로 지정한 태그명과 동일한 요소를 가져오게 됩니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var ms = document.getElementsByTagName('span');
			alert(ms[0].innerHTML);
		};
	</script>
</head>
<body>
	<span>aaa</span>
	<p>bbb</p>
	<h1>ccc</h1>
</body>
</html>

예제는 span과 p, h1태그를 놓았는데 모두 하나씩만 존재합니다. 하지만 대부분의 문서에서는 동일한 태그가 여러 개일 수 있으므로 getElementsByTagName메서드 또한 여러 개의 요소를 가져올 수 있습니다.

 

여러개의 태그를 가져온다는 특징을 이용하면 [인덱스] 방식으로 요소에 접근하는 대신 for문을 활용해 모든 요소를 순회할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var ms = document.getElementsByName('food');
			
			for (var i = 0; i < ms.length; i++)
				alert(ms[i].value);
		};
	</script>
</head>
<body>
	<input type="radio" name="food" value="라면">
	<input type="radio" name="food" value="김밥">
	<input type="radio" name="food" value="순대">
</body>
</html>

물론 요소의 배열을 순회할 수 있는 다른 방법으로 for in을 사용할 수 있지만 요소의 다른 속성까지 순회하게 되므로 for in을 사용할 때는 주의가 필요합니다.

 

위와 같이 가져온 요소는 innerHTML처럼 단순히 특정 속성을 확인하는 것뿐만 아니라 속성 혹은 스타일등을 변경할 수도 있습니다. 아마도 위와 같은 메서드나 기타 다른 방법으로 요소를 가져오는 대부분의 이유가 이러한 목적 때문일 것입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var o = document.getElementsByTagName('span');
			
			o[0].style.color = 'red';
			o[1].style.backgroundColor = 'blue';
			o[2].innerHTML = '오토바이';
		};
	</script>
</head>
<body>
	<span>자동차</span>
	<span>트럭</span>
	<span>자전거</span>
</body>
</html>

참고로 예제에서 사용된 backgroundColor은 CSS에서 background-color에 해당합니다. CSS에서 사용되는 -문자는 -문자로 연결되는 첫 글자를 javascript에서 대문자로 표현한 것인데 이는 javascript에서 -문자를 사용할 수 없기 때문에 생긴 규칙입니다.

 

위 3가지 메서드는 javascript에서 요소를 가져오기 위한 기본적인 메서드에 해당합니다. 이 외에도 HTML5에서는 아래와 같은 2가지 속성을 추가로 제공하고 있습니다.

 

querySelector(CSS선택자) 선택자에 해당하는 첫번째 요소를 가져옵니다.
querySelectorAll(CSS선택자) 선택자에 해당하는 모든 요소를 가져옵니다.

 

CSS선택자는 CSS에서 원하는 요소에 CSS효과를 적용하기 위한 선택 자이며 Jquery에서도 사용됩니다. 자세한 내용은 아래 글에서 확인하실 수 있습니다.

 

[Web/HTML5 & CSS3] - [HTML5&CSS3] CSS선택자 -1

[Web/HTML5 & CSS3] - [HTML5&CSS3] CSS선택자 -2

[Web/HTML5 & CSS3] - [HTML5&CSS3] CSS선택자 -3

 

querySelector나 querySelectorAll메서드는 바로 이러한 선택자를 통해 원하는 요소를 가져올 수 있도록 하는 메서드입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var o = document.querySelector('#span2');
			alert(o.innerHTML);

			var oa = document.querySelectorAll('span');
			for (var i = 0; i < oa.length; i++)
				alert(oa[i].innerHTML);
		};
	</script>
</head>
<body>
	<span id="span1">자동차</span>
	<span id="span2">트럭</span>
	<span id="span3">자전거</span>
</body>
</html>

3. 요소 삭제

 

마지막으로 요소를 삭제하는 메서드는 다음과 같습니다.

 

removeChild(child) 지정한 자식 요소 삭제
<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script>
		window.onload = function() {
			var o = document.getElementsByTagName('span');
			o[1].parentNode.removeChild(o[1]);
		};
	</script>
</head>
<body>
	<span>자동차</span>
	<span>트럭</span>
	<span>자전거</span>
</body>
</html>

예제는 문서의 모든 span요소를 가져온 다음 그중에서 2번째(인덱스 1) span요소를 삭제하고 있습니다. 이때 removeChild메서드는 자식 요소를 삭제하는 메서드이므로

o[1].parentNode.removeChild(o[1]);

위와 같이 부모 노드를 확인한 다음 부모 노드에서 removeChild메서드를 호출해야 합니다. 따라서 결과적으로 아래와 같은 코드로 동작하게 됩니다.

document.body.removeChild(o[1]);

 

관련글 더보기

댓글 영역