ㅎㅇ JS 데이터 타입에 대해 알아보자.

크게 두 가지로 나뉨:

  1. 원시타입 (Primitive type)
  2. 참조타입 (Reference type)

원시타입
그냥 값 자체를 저장하는 애들임.
얘네가 있음:

  • string (문자)
  • number (숫자)
  • boolean (true/false)
  • undefined (값이 없음)
  • symbol (ES6에서 추가됨)
  • bigint (엄청 큰 숫자)

특징이 뭐냐면:

  • 불변임 (한번 만들어지면 그 값이 절대 안 바뀜)
  • 복사하면 값 자체를 복사함

예시로 보면 이렇게 됨:

let a = 100;
let b = a;
a = 50;

console.log(b) // 100이 나옴

 

왜 100이 나올까?

b가 a를 복사할 때 값 자체를 복사했기 때문임.

 

100이 들어가 있던 변수가 50으로 바뀌는 게 아니라
그냥 50을 새로 메모리에 할당해버림.

 

b도 같은 100이 아니라 새로운 메모리에 100을 할당함.

 

같은 값이고 심지어 (=) 대입까지 했지만

같은 값을 가진 다른 주소를 가리키고 있다는 게 중요함.

 

참조타입은 뭐임.


원시타입 빼고 전부 다 참조타입임.
대표적으로:

  • 배열 []
  • 객체 {}
  • 함수

특징:

  • 값의 크기가 막 바뀔 수 있음
  • 복사하면 주소만 복사됨 (실제 값이 아님)

보면 이렇게 됨:

예시:

let myArr = [];
let copyArr = myArr;

myArr.push("hello");

console.log(copyArr); // ["hello"]가 나옴

 

왜 copyArr에도 "hello"가 들어갔을까?
참조타입은 주소만 복사하기 때문임.


말 그대로 주소만 복사한 거임.

그렇기 때문에 주소가 100개고 1000개고 모두 다 같은 집을 가리키고 있는 거임.

집 주소니깐.

 

원시타입과는 다르게 값이 계속 할당되는 게 아님.

주소만 생길 뿐 결국 가리키는 곳은 주소에 있는 값임.

(코드형 견망지월ㄷㄷ)

 

참조타입 다룰 때 원본이 바뀔 수 있다는 걸 항상 기억해야 됨.

 

'JS' 카테고리의 다른 글

1-1 JavaScript 변수  (1) 2024.11.21
DOM(Document Object Model) 쉽게 알기 JS  (1) 2024.11.19

ㅎㅇ JS 관련 글도 쓸 생각이다.

 

완전 쌩 초보도 이해할 수 있게 쉽게 쓰려고 노력했음.

(이게 내 최선임)

 

DOM에 관련된 글이고

도대체 DOM이 뭔지에 대한 감을 잡는 간단한 글이다.

 

바로 본론

 

웹 개발을 만지다보면 DOM DOM 많이 들어봤을 텐데.

 

" Document Object Model "의 약자다

 

조선말로 " 문서 객체 모델 "이라는 뜻인데

 

문서(Document)의 모든 요소를 프로그래밍에서 다룰 수 있는 객체(Object)로 만들고,

이러한 객체들을 계층화된 트리 구조의 모델(Model)로 정의하기 때문이다.

 

무슨 말인지 모르겠는데요.

 

그래서 Document / Object /  Model 하나하나 알아볼 거다.


Object (객체)

객체는 정보와 기능이 담긴 상자라고 생각하면 된다.

 

객체는 대충 이런 느낌으로 생겼다. (별로 어려운 내용도 아니니 그냥 넘어가지 말고 주의 깊게 한 줄 한줄 읽는 거 추천)

let 강아지 = {
    // 강아지의 정보
    이름: "초코",
    나이: 3,
    색깔: "갈색",
    
    // 강아지가 할 수 있는 행동
    짖기: function() {
        console.log("멍멍!");
    },
    앉기: function() {
        console.log("앉았습니다");
    }
}

// 강아지 정보 보기
console.log(강아지.이름);    // "초코" 출력
console.log(강아지.나이);    // 3 출력

// 강아지 행동시키기
강아지.짖기();             // "멍멍!" 출력
강아지.앉기();             // "앉았습니다" 출력

 

보면 강아지의 정보와 이 강아지가 할 수 있는 행동들이 모여 있다.

다시 말하지만 객체는 정보와 기능이 담긴 상자다.

 

오잉 그러면 저 강아지가 객체라는 상자라는 건가요?

 

ㅇㅇ 맞음

  • 강아지 = 객체
  • 강아지 정보 = 속성
  • 강아지가 할 수 있는 행동 = 메소드

속성과 메소드는 추후에 블로그에 적을 수도 있지만

내 귀찮음이 성실함을 툭 치면 죽어버려서 본인이 직접 찾아보는 것을 추천.

 

간단하게

강아지.이름(속성) 하면 강아지의 객체에 저장된 이름이 나오고

강아지.짖기() (메소드) 하면 강아지의 객체에 저장된 행동을 함. 메소드는 뒤에 ()가 붙음 그게 실행한다는 뜻임.

 

객체 끝

 


MODEL(모델)

Model은 웹 문서를 프로그래밍적으로 다룰 수 있도록 만든 인터페이스이자 문서의 구조화된 표현 방식을 의미함.

 

뭐라는 거야

 

조금 더 쉽게

여기서 MODEL은 포괄적인 개념인데

  • HTML을 JS로 조작할 수 있는 인터페이스이자. (리모컨 같은 거임)
  • HTML의 구조화된 표현 방식을 의미한다는 거임. (지도 같은 거임)

저 두 가지 의미를 둘 다 포함하고 있음 리지도모컨임 ㅇㅇ

 

일단 구조화된 표현 방식인 트리 구조부터

 

이게 트리구조

    O  ← 이것이 하나의 '매듭점(node)'
   / \  ← 이것들은 '연결선(edge)'
  O   O ← 다른 '매듭점들(nodes)'


그리고 저 하나하나를 노드(node)라고 부름.

매듭점, 연결점, 교차점 대충 이런 뉘앙스를 가짐.

 

저 동글뱅이들이 노드임.

이렇게 생긴 걸 트리 모델이라고 함.

 

근데 왜 이 구조를 써야 하는데요

 

맞는 말임 분명 다른 구조도 가능했을 거임 이런 식으로

<!-- 실제 HTML -->
<div>
    <h1>제목</h1>
    <p>내용</p>
</div>

// 1. 트리 모델 
div
 ├── h1 ("제목")
 └── p ("내용")

// 2. 리스트 모델 (다른 방식)
1. div 시작
2. h1 시작
3. "제목"
4. h1 끝
5. p 시작
6. "내용"
7. p 끝
8. div 끝

 

근데 트리구조를 채택하면 다음과 같은 이점이 있음:

  1. 부모-자식 관계를 직관적으로 표현
  2. 요소 찾기/수정이 쉬움
  3. HTML의 계층구조와 잘 맞음

ㅇㅇ 그래서 트리구조를 선택한 거임.

 

근데 도대체 누가 멀쩡한 HTML을 트리구조로 바꿔준다는 거임 자꾸

 

님이 보고 있는 이 브라우저가 그걸함.

이를파싱(Parsing)이라고 함.

정보를 대충 가공하는걸 파싱이라고 보면 됨.

 

그리고 그 파싱을 하는 놈들을 파서(Parser)라고 부름.

 

브라우저에는 엔진들이 있는데

그중 HTML 파서가 HTML을 파싱 해서 트리구조를 만듦.

 

참고로 CSS 파서가 CSS를 파싱 하면 CSSOM임 ㅋㅋ

 

JavaScript 엔진 (예: V8)

 

렌더링 엔진

 

이런 애들도 있음.

 

그럼 이제 또 의문이 생김.

 

도대체 누구 좋으라고 HTML을 파싱 해서 트리구조로 만드니 마니

이 난리부르스 다이아몬드 스텝을 밟고 있는 걸까?

 

정답은

1. 렌더링 엔진을 위해 (처음에 말한 지도 기능)

2. JS 조작을 위해. (처음에 말한 리모컨 기능임)

 

1. 은 위에서 언급한 렌더링 엔진이 만약 HTML 텍스트 그대로 사용하게 되면

허벌나게 뛰댕겨야됨.

  1. 부모-자식 관계 파악이 안돼서 폐륜이 발생할 수도 있고
  2. 스타일 상속 계산이 어려워서 재벌가처럼 상속분쟁이 일어날수도 있음.
  3. 레이아웃 계산도 어려워짐

암튼 렌더링 엔진이 힘들어함.

그래서 좀 효율적으로 뛰어다니라고 지도를 쥐어주는 거임.

(사실상 더 돌아다니기 편하게 맵자체를 변경한다는 표현이 조금 더 정확하지만)

 

결론 : 렌더링 편하자고 트리 구조로 바꾼 거임.

 

이론상 트리구조 없이 렌더링을 할 수 있음. 렌더링 엔진이 힘들 뿐 (렌엔 지켜 엉엉)

 

2. JS는 추후 설명함


NODE

아까 위에서 트리구조는 노드들을 가진다고 말했음.

1. 요소 노드(Element Node): <div>, <p> 등의 HTML 태그
2. 텍스트 노드(Text Node): 텍스트 내용
3. 속성 노드(Attribute Node): class, id 같은 속성
4. 문서 노드(Document Node): 문서 전체를 나타내는 노드
5. 주석 노드(Comment Node): HTML 주석

 

그래서 파싱 된 HTML은 이런 식으로 노드를 가지고 있음. 트리구조니깐.

 

밑은 더 자세한 예시임. (자세히 보셈)

 

// HTML 구조
<html>
  <head>
    <title>DOM 예시</title>
  </head>
  <body>
    <div id="container">
      <h1>제목</h1>
      <p>텍스트 내용</p>
    </div>
  </body>
</html>

// 위 HTML의 DOM 트리 구조:
document (문서 노드)
└── html (요소 노드)
    ├── head (요소 노드)
    │   └── title (요소 노드)
    │       └── "DOM 예시" (텍스트 노드)
    └── body (요소 노드)
        └── div (요소 노드)
            ├── h1 (요소 노드)
            │   └── "제목" (텍스트 노드)
            └── p (요소 노드)
                └── "텍스트 내용" (텍스트 노드)

 

이런 식으로 HTML이 트리구조로 변경되고
해당방식으로 노드들이 생김.

 

(변환된 트리구조 맨 위 주목)

어 근데 맨 위에 저 Document는 뭘까.

DOM

O(객체)에 대해서 설명했고
M(모델)에 대해서 설명했다.

 

마지막 남은 D(문서)


저 Document가 D다.

 


모델 끝


Document(문서)

Doucument는 객체다.

맨 위에 말한 그 object 객체.

 

지금 우리가 지지고 볶은 트리화 구조가 이 Document 객체에 들어간다.

 

결국 DOM이란

 

파싱 된 HTML이 트리 구조의 객체 모델로 변환되어

Document에 저장되어 이를 조작할 수 있는 인터페이스를 제공하는 것.

 

이라고 이해할 수 있다.

 

조금 더 자세히 알아보자

 

Document의 트리구조는 다음과 같다.

 

Document
    ├── DOCTYPE
    └── <html>
         ├── <head>
         │    ├── <title>
         │    ├── <meta>
         │    └── ...
         └── <body>
              ├── <div>
              ├── <p>
              └── ...

 

이 Document라는 객체 안에 트리 구조로 HTML이 들어가 있다.

 

실제 Document 객체의 구조는 어떻게 생겼을까?

 

document = {
    documentElement: HTMLHtmlElement, // <html> 태그
    head: HTMLHeadElement,           // <head> 태그
    body: HTMLBodyElement,           // <body> 태그
    
    // 주요 메서드들
    getElementById(): Element,
    getElementsByClassName(): HTMLCollection,
    getElementsByTagName(): HTMLCollection,
    querySelector(): Element,
    querySelectorAll(): NodeList,
    
    // 문서 관련 속성들
    title: String,
    URL: String,
    documentURI: String,
    characterSet: String,
    
    // 이벤트 관련
    addEventListener(): void,
    removeEventListener(): void
    
    // DOM 조작 메서드들
    createElement(): Element,
    createTextNode(): Text,
    // ... 기타 여러 속성과 메서드들
}

 

대략적으로 이렇게 생겼다.

 

Document는 객체이기 때문에

위에 설명한 강아지처럼

속성과 메소드가 있다.

 

위에 언급한 객체의 메소드 사용법을 떠올려보자.

 

강아지를 짓게 하려면 강아지.짖기() 를 사용해야 했다.

 

강아지.짖기()

  • 강아지 = 객체
  • 짖기() = 메소드

 

지금 나는 html 태그를 하나 선택하고 싶다고 가정해 보자.

(그때 필요한 메소드는 querySelector() 다.)

 

document.querySelector('p')

  • document = 객체
  • querySelector() =  메소드

이러면 p 태그를 선택할 수가 있다.

 

이렇게 객체를 조작하는 방식으로 JS로 간편하게 우리는 HTML을 조작할 수 있다.

 

왜냐

 

우리가 document라는 객체를 만들고 그 안에 HTML을 파싱 해서 넣었을 뿐 아니라

그 안에 유용한 메소드들이 있기 때문이다.

 

(참고로 메서드들은 브라우저가 추가해 준다.)

 

이게 모델에서 언급한 리모컨 기능이다. (인터페이스)

JS를 통해 쉽게 HTML을 조작할 수 있다.

 

근데 이렇게 안 하면 얼마나 더럽고 귀찮게 조작해야 되는데요?

 

// 1. DOM 구조가 없다고 가정하면 (HTML이 그냥 문자열)
let html = "<div><h1>제목</h1><p>내용</p></div>";

// HTML을 수정하려면 문자열 처리를 해야 함
html = html.replace("<h1>제목</h1>", "<h1>새로운 제목</h1>");
html = html.replace("<p>내용</p>", "<p>새로운 내용</p>");

------------------------------------------------------------

// 2. DOM 구조일 때 (현재 브라우저처럼)
let 제목 = document.querySelector('h1');
let 내용 = document.querySelector('p');

제목.textContent = "새로운 제목";
내용.textContent = "새로운 내용";

 

1번처럼 코드가 혼파망이 되어버린다.

DOM이 있음에 감사하자.

 

다시 document 객체로 돌아와 보자.

document = {
    documentElement: HTMLHtmlElement, // <html> 태그
    head: HTMLHeadElement,           // <head> 태그
    body: HTMLBodyElement,           // <body> 태그
    
    // 주요 메서드들
    getElementById(): Element,
    getElementsByClassName(): HTMLCollection,
    getElementsByTagName(): HTMLCollection,
    querySelector(): Element,
    querySelectorAll(): NodeList,
    
    // 문서 관련 속성들
    title: String,
    URL: String,
    documentURI: String,
    characterSet: String,
    
    // 이벤트 관련
    addEventListener(): void,
    removeEventListener(): void
    
    // DOM 조작 메서드들
    createElement(): Element,
    createTextNode(): Text,
    // ... 기타 여러 속성과 메서드들
}

 

뭐야 트리라더니 생긴 게 하나도 트리처럼 안 생겼잖아.

 

왜냐면 JS 객체를 표현하는 방식이 그렇게 보이지 않기 때문이다.

실제로는 트리 구조를 가진다.

 

더 자세한 예시를 보자

 

HTMLHtmlElement은 이렇게 생겼다.

HTMLHtmlElement = {
    // 속성들
    id: String,
    className: String,
    // ... 다른 속성들

    // 자식 요소들이 여기에 저장됨
    children: {
        0: HTMLHeadElement,  // <head>
        1: HTMLBodyElement,  // <body>
        length: 2
    }
}

 

children은 자식 요소들을 저장하는 곳이다

그중 자식 요소인 HTMLHeadElement 객체는 어떻게 생겼을까?

 

HTMLHeadElement 객체 구조

HTMLHeadElement = {
    // HTMLElement로부터 상속받은 속성들
    id: String,
    className: String,
    
    // head 요소의 자식들
    children: {
        0: HTMLMetaElement,      // <meta>
        1: HTMLTitleElement,     // <title>
        2: HTMLLinkElement,      // <link>
        length: 3
    },
    
    // 부모-자식 관계 속성/메서드
    firstChild: Node,
    lastChild: Node,
    appendChild(): Node,
    removeChild(): Node
}

 

보면 자식을 타고 들어가면 또 자식이 있고 또 자식이 있고 이런 식으로

트리 구조를 이루고 있다.

 

이를 조금 더 구조적으로 표현하면 다음과 같은 구조를 이루고 있다. 

 

반갑 트리

이래서 트리구조라는 거임.

 

다시 돌아와서

 

위에 나열한 Document(문서) / Object(객체) / Model(모델) 을 전부 연결해서 생각하면

 

D.O.MDOM이 된다!

 

수미상관 간다.

 

DOM이 DOM인 이유는 다음과 같다.

 

 문서(Document)의 모든 요소를 프로그래밍에서 다룰 수 있는 객체(Object)로 만들고,

이러한 객체들을 계층화된 트리 구조의 모델(Model)로 정의하기 때문이다.

 

이제는 이 문장이 조금 더 친숙하게 당신에게 다가왔을 거라 믿는다.

 

 

P.S.

내가 글을 못써서 DOM의 장점을 다 못 적었다.

DOM이 어떤 방식으로 작동하는지

DOM이 뭔지 어느 정도 감이 잡혔다면 나는 그걸로 만족.

 

기회가 된다면 DOM을 쓰게 됨으로써 얻게 된 장점도 써보도록 하겠다.

(안쓰겠다는 뜻)

'JS' 카테고리의 다른 글

1-2 메모리구조  (0) 2024.11.26
1-1 JavaScript 변수  (1) 2024.11.21

+ Recent posts