이 DOM 을 알기 전에 먼저 자바스크립트가 왜 생겼는지에 대해서 먼저 이해해야 한다.
간단히 말해서 '브라우저를 동작하기 위해' 태어난 언어인데, 이 브라우저는 다른 프로그램보다 가볍고 빠른 만큼, 그에 맞게 가벼운 프로그래밍 언어를 만들려고 하였다.
해서 자바스크립트의 목적이란, 정적이었던 웹페이지(브라우저)를 동적으로 만들기 위해서 이다.
클라이언트가 서버로부터 이 웹페이지를 이루는 HTML 문서를 수집하면 자바스크립트가 해석한 내용을 토대로 DOM Tree 를 구축한다.
그래서 DOM 이 무엇인가?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<nav>
<li>첫번째 메뉴</li>
<li>두번째 메뉴</li>
<li>세번째 메뉴</li>
</nav>
<main>
<h1>메인 영역의 제목입니다.</h1>
<img src="data:image/jpeg;base64,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"
alt="이미지없음">
</main>
<footer>
copyright.
</footer>
</body>
</html>
간단한 HTML 문서다.
브라우저를 구성하는 이 HTML 문서가 만들어지고 페이지를 만들면,
이와 같은 구성으로 DOM Tree 가 만들어진다.
DOM 은 Document Object Modeling, 즉 문서를 객체처럼 모델링한 구성을 말한다.
이 DOM 은 브라우저에 기본적으로 내장되어 있는 API 중 하나이다.
API는 무엇일까?
예를 들어 설명하자면 음식점의 메뉴판과 같다고 할 수 있다.
고객은 메뉴판을 보고 음식을 주문하는 과정을 거치기에 메뉴판은 고객과 가게 사이의 인터페이스 라고 할 수 있다.
이와 같은 api는 해당 시스템과 사용자간의 인터페이스 역할로, 다른 시스템에서 제공하는 기능을 사용할 수 있도록 도와주는 중간자 역할이라고 보면 된다.
다시 DOM 으로 돌아와서, 모든 브라우저에는 DOM 객체가 있는데, 이를 어떻게 확인할 수 있을까?
브라우저 접속 후 F12 - document 를 입력해보면 알 수 있다.
VSCode에서는
console.log(document);
이 코드 출력을 통해 확인해볼 것인데,
다음 출력 상태를 보면 알 수 있듯이 노드환경에서는 document 가 정의되지 않았다. 즉 DOM 객체는 브라우저에만 내장된 객체라는 것을 알 수 있다.
이 DOM 객체를 통해 1. 접근 가능, 2. 제어 가능 이라는 두가지 기능을 가질 수 있다.
DOM Tree 의 모습니다.
이 구성 요소 하나하나를 Node 라고 부르는데, 이 웹 페이지를 구성하는 모든 속성들을 하나의 블럭으로 취급하여 부르는 것이다.
이 '속성' 이라는 말에서 주의할 것으로, 속성과 메서드를 서로 다른 것이다.
document.getElementById("demo").innerHTML = "Hello World!";
이 코드를 봤을 때 속성과 메서드를 구분지어서 볼 수 있다.
1. 속성 : innerHTML ...
2. 메서드 : getElement ...
위의 DOM Tree 에서 볼 수 있듯이, HTML 문서는 계층 구조로 구성되어 있다.
먼저 이 계층 구조를 돌아다니면서 탐색해보는 과정을 거친다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<nav>
<li>첫번째 메뉴</li>
<li>두번째 메뉴</li>
<li>세번째 메뉴</li>
</nav>
<main>
<h1>메인 영역의 제목입니다.</h1>
<img src="data:image/jpeg;base64,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"
alt="이미지없음">
</main>
<footer>
copyright.
</footer>
</body>
</html>
이 코드로 웹페이지를 만들어서 이용할 것이다.
console 창에서 document 를 먼저 쳐보자
DOM 객체가 정상적으로 출력되는 것을 볼 수 있다.
이 DOM 객체의 코드를 수정할 것이다.
<nav>
<ul id = "test">
<li>첫번째 메뉴</li>
<li>두번째 메뉴</li>
<li>세번째 메뉴</li>
</ul>
</nav>
위 사진에서의 코드 [ document.getElementByID("test") ] 메서드를 통해 test 아이디값을 호출할 수있다.
이러한 방식으로 특정 노드에 접근이 가능하다.
이 getElementById 메서드보다 더 많이 쓰이는 방법은 [ querySelector ] 가 있다.
test 의 id 값을 가진 노드를 호출한 모습이다.
이 구조상 ul 밑에 3개의 li 를 가진 것을 볼 수 있는데, 이 li 에도 접근해보도록 한다.
document.querySelector("#test").children[1]
children 의 인덱스를 0 ~ 2 로 바꾸면 브라우저 화면에서 이 인덱스에 해당하는 곳이 표시되는 것을 볼 수 있다.
이 동작은 children 이라는 속성에서도 알 수 있듯이, 해당 노드(id = test인 노드) 의 자식 노드를 탐색한 것이다.
이제 그럼 부모 노드도 탐색해보자.
document.querySelector("#test").parentNode
document.querySelector("#test").parentElement
ul의 부모 노드 nav 가 반환되는 것을 확인할 수 있다.
여기까지가 DOM 객체에 접근하는 방법이었다. 다음으로 볼 것은 DOM 객체를 제어하는 방법이다.
1. 추가
기존에 없던 요소를 추가한다.
const newDiv = document.createElement('div');
document.body.append(newDiv);
해당 코드를 입력하면
다음과 같이 새로운 div 요소가 추가된 것을 볼 수 있다.
간단한 동작이지만 이를 통해 HTML 문서에서 만든 적 없는 코드를 JS 를 통해 제어할 수 있다는 것을 볼 수 있다.
2. 편집
기존에 존재하던 요소를 새롭게 편집한다.
document.querySelector('ul').children[1].innerText = '두번째 메뉴 변경'
'두번째 메뉴' 였던 속성을 '두번째 메뉴 변경' 으로 바꾸었다.
이렇게 1. 추가 2. 편집의 과정을 통해 DOM 객체의 개념 및 제어 방법까지 학습할 수 있다.
이 클래스에 대한 설명은 다른 파트에서도 진행한 적이 있어 먼저 같이 첨부한다.
2024.07.17 - [유니티 학습/세미나 자료] - #3. 클래스와 오브젝트
JS에서는 ES6에 와서 클래스 문법이 도입되었다.
이 도입 이유조차 사실 조금 웃긴데, 다른 언어는 클래스 기반 문법을 통해 객체 지향 방식을 사용해왔었다. 이에 다른 언어를 사용하던 개발자들이 JS 로 넘어오면서 클래스 개념처럼 알고리즘을 구성하다보니, 이 편의에 맞추기 위해 늦게나마 클래스 개념을 도입하게 된 것이라고 한다.
개인적으로 이전 호이스팅 과정에서 느꼈던 구조적으로 허술한 언어지 않나.. 라는 생각이 다시 드는 순간이었다.
아무튼 다시 설명으로 넘어간다.
이 클래스를 설명할 때는 반드시 '인스턴스' 가 동반된다.
클래스는 설계도 라면, 인스턴스는 설계도를 기반으로 만들어진 책상, 탁자 등 실제 물건으로 비유할 수 있다.
//클래스
class Person
{
//생성자 함수 <- 매개변수에 필수로 들어가야 하는 갑 할당
constructor (name, age)
{
//this : 인스턴스, 우측 name = 외부 대입 요소
this.name = name;
this.age = age;
}
}
//인스턴스
const person1 = new Person('Jane', 30);
console.log(person1.name);
console.log(person1.age);
이렇게 Person 이라는 클래스를 만들고, 그를 기반한 인스턴스 person1 을 만들었다.
코드 출력을 통해 객체의 속성을 확인할 수도 있다.
이 하나의 클래스를 가지고 여러개의 인스턴스를 생성할 수도 있다.
이 여러개를 생성한다 는 과정에서 쉽게 예상 가능한 것이 foreach 와 같은 반복문을 혼합할 수 있다는 것이다.
클래스의 내부에는 메서드(기능)을 만들 수 있다.
class Person
{
//생성자 함수 <- 매개변수에 필수로 들어가야 하는 갑 할당
constructor (name, age)
{
//this : 인스턴스, 우측 name = 외부 대입 요소
this.name = name;
this.age = age;
}
//메서드 형태의 기능 표현
sayHello()
{
console.log(this.name + " : Hello");
}
}
person1.sayHello();
Hello 를 출력하는 sayHello 메서드를 만든 모습이다.
1. Car 라는 클래스를 만들되, 처음 객체를 만들 때 [1. modleName, 2. modelYear, 3. type, 4. price ] 의 값이 필수로 입력되어야 한다.
2. makeNoise() 라는 메서드로 클락션을 출력한다.
3. 자동차를 3개 만들어보자.
1번에서 설명하는 '값이 필수로 입력되어야 한다' 는 생성자의 변수로, 2번은 말 그대로 메서드, 3번은 인스턴스를 3개 생성하라는 말로 이해할 수 있다.
class Car
{
constructor(modelName, modelYear, type, price)
{
this.modelName = modelName;
this.modelYear = modelYear;
this.type = type;
this.price = price;
}
makeNoise()
{
console.log("hit the Klaxon");
}
}
const ferrari = new Car('Ferrari', 2005, 'middle', 3000);
const audi = new Car('Audi', 2006, 'middle', 2000);
const avente = new Car('Avente', 2007, 'middle', 1000);
다음과 같이 만들 수 있다.
해당 자동차가 몇년도 모델인지 출력하는 메서드를 작성하라.
whenMade()
{
console.log("This Car Made in : "+ this.modelYear);
}
ferrari.whenMade();
this 를 사용하여 해당 객체의 modelYear 값을 출력하는 메서드를 만들 수 있다.
이 객체의 값은 같은 클래스를 기반으로 만들어졌다 하더라도 인스턴스마다 다른 속성을 가질 수 있어 이를 반환하거나 변경하는 과정이 반드시 필요하다.
이를 Getter 와 Setter 라고 부른다.
모든 객체지향 언어에는 이 get/set 에 대한 메서드가 있다.
위에서 설명했듯이 이를 통해 클래스 속성에 접근하여 인스턴스를 정해진 규격 안에서 자유자재로 변경 가능하다.
get 는 반환, 받아오기의 기능을 하고 set 은 쓰기 의 기능을 갖는다.
class Rectangle
{
constructor(height, width)
{
this.height = height;
this.width = width;
}
get width () { return this.width; }
set width (value)
{
if(value < 0) console.log("error : width value");
else if(typeof value !== 'number') console.log("error : width type");
else this.width = value;
}
get height () { return this.height; }
set height(value)
{
{
if(value < 0) console.log("error : height value");
else if(typeof value !== 'number') console.log("error : height type");
else this.height = value;
}
}
}
const rect1 = new Rectangle(10, 5);
rect1.height = 30;
console.log(rect1.height);
다음과 같이 Rectangle 클래스의 getter 와 setter 를 만들 수 있다.
다만 이렇게 작성하게 될 경우 에러가 발생하는데,
이 출력 상태를 보는 것처럼 set에만 에러가 발생하는 것이 아니라, 사실 get 에도 모두 동일한 에러를 가지고 있다.
오류 표기는 [ Maximum call stack size exceeded ], 무한 루프 오류이다.
왜 무한루프가 되는 것일까?
처음에 객체를 const rect1 = new Rectangle(10, 5) 로 생성할 때 height 가 10 으로 할당된다.
this.height = height 에서 값을 적용하기 위해 set height(value) 메서드로 값을 전달하는데, 이 안에서 this.height = value 코드를 통해 또 다시 set 함수를 호출한다.
자신이 자신을 호출하는 무한루프에 빠지게 되어 콜스택 사이즈보다 더 사용 범위가 커지는 오류가 발생하는 것이다.
이는 변수의 표기를 구분짓는 것으로 해결할 수 있다.
바로 this 뒤에 오는 변수에 _(underscore) 를 추가하는 것이다.
constructor(height, width)
{
this._height = height;
this._width = width;
}
이 생성자 뿐만 아니라 클래스 내의 모든 this 변수에 동일하게 적용해주어야 한다.
이 underscore 는 암묵적인 표기로 private 라는 의미를 내포한다. 이 인스턴스 내에서만 사용하겠다는 뜻으로, 외부에서 할당하는 값과 내부에서의 값을 분리하기 위해 사용한다.
다른 메서드를 하나 더 추가해서 확인하자면
getArea()
{
return this._height * this._width;
}
150 값이 정상적으로 출력되는 것을 확인할 수 있다.
클래스의 기능을 하위 클래스에 내려주는 주요 기능 중 하나인 '상속' 이다.
이 또한 C# 과정에서 같은 내용을 다룬 적 있어 같이 첨부한다.
2024.07.17 - [유니티 학습/세미나 자료] - #12. 상속 심화
예를 들어 '동물' 이라는 부모 클래스에서 '강아지' 나 '고양이' 라는 자식 클래스를 만들면서, 하위 노드로 내려갈 수록 구체화되는 과정이라고 볼 수 있다.
class Animal
{
constructor(name)
{
this._name = name;
}
speak()
{
console.log(this._name + " : speak");
}
}
const newAnimal = new Animal('newName');
newAnimal.speak();
먼저 Animal 이라는 동물 부모 클래스를 만들었다.
이 클래스를 기반으로 하위 클래스를 만들 것인데, JS에서의 상속을 뜻하는 키워드는 'extends' 이다.
class Dog extends Animal
{
//부모 메서드 오버라이드
speak()
{
console.log(this._name + "is Dog, and Bark");
}
}
const newDog = new Dog("boob");
newDog.speak();
부모 클래스에서 speak 메서드를 만들고, 자식 Dog 클래스에서 같은 speak 메서드를 정의하였다.
이렇게 부모의 기능을 덮어씌우는 행위를 '오버라이딩(overriding)' 이라고 부른다.
자식 클래스에서 오버라이딩을 진행할 경우, 자식 클래스로 만든 인스턴스에서는 재정의 한 기능을 사용하게 된다.
이 코드에서 Dog 클래스의 생성자의 경우 부모의 특성을 그대로 사용할 것이기에 따로 재정의하는 과정을 진행하지 않았다.
이렇게 클래스의 기본 구조와 하위 클래스까지 사용하는 상속에 대해 살펴볼 수 있다.
#13. Closure (0) | 2024.11.19 |
---|---|
#11. 콜백 함수 (Call Back Func) (6) | 2024.11.12 |
#10. 3주차 숙제 (1) | 2024.11.08 |
#9. This (0) | 2024.11.08 |
#8. 실행 컨텍스트 (3) | 2024.11.07 |