[JavaScript/브라우저] DOM

KIM DA MI·2023년 3월 7일
0

JS/브라우저

목록 보기
1/2
post-thumbnail

1. DOM 기초


  • DOMDocument Object Model의 약자로, HTML 요소를 Object(JavaScript Object)처럼 조작(Manipulation)할 수 있는 모델이다.

  • javaScript를 이용하여 DOM으로 HTML을 조작할 수 있다.

  • DOM을 이용하면 HTML로 구성된 웹 페이지를 동적으로 움직이게 만들 수 있다.

  • HTML과 DOM의 구조

HTML에 JavaScript를 적용하는 방법

  • HTML은 프로그래밍을 위해서 만들어진 언어가 아니다.
    따라서 JavaScript라는 프로그래밍 언어와 DOM을 활용하여 HTML에 접근하고 조작한다.
  • <script> 태그를 이용하여 HTMLJavaScript를 적용한다.
    <script src="myScriptFile.js"></script>
    • 예시 : HTML 파일과 같은 디렉토리에 존재하는 myScriptFile.js을 불러옴

DOM 구조를 조회하기

  • DOM 구조를 조회할 때에는 console.dir 이 유용하다.
    console.dirconsole.log 와 달리 DOM을 객체의 모습으로 출력한다.
  • html 파일
  • console.log, console.dir의 차이
    • HTML 엘리먼트에 지정할 수 있었던 다양한 속성이 이미 객체 내에 존재한다는 것을 알 수 있음.

body 요소의 자식 요소(element)찾기 👶

  • console.dir(document.body) 를 통해 출력된 객체에서, children 속성을 찾을 수 있다.
  • document.body.children 으로 바로 조회할 수도 있다.

id의 이름이 news-contents<div> 요소의 부모 요소찾기 👩👨

  • idnews-contentsdiv 요소는 <body> 요소의 자식 요소이다.
    반대로 <body> 요소는 idnews-contents div 요소의 부모 요소이다.
  • querySelector()는 HTML 엘리먼트 정보를 가져올 수 있다.
  • parentElement 속성은 DOM 노드의 부모를 반환한다.
  • 따라서 아래의 코드로 입력하면 해당 요소의 부모요소를 찾을 수 있다.
    console.dir(document.querySelector('#news-contents').parentElement);



2. DOM 다루기


  • document 객체에는 많은 속성과 메서드가 존재한다.
  • 그 중에서 오늘은 가장 중요한 CRUD(Create, Read, Update and Delete)와 APPEND에 대해 먼저 알아보도록 하자!

CREATE

  • DOM을 이용하여 HTML Element를 추가하는 방법을 알아보자.
  • 예시 html 파일
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <link rel="stylesheet" href="style.css" />
            <title>Document</title>
        </head>
        <body>
            <div id="container">
                <h2>Tweet List</h2>
                <div class="tweet">hello</div>
                <div class="tweet">world</div>
                <div class="tweet">code</div>
                <div class="tweet">states</div>
            </div>
        </body>
    </html>
  • html 파일을 브라우저에서 연다.
  • 개발자도구의 console 탭에서 예시 코드를 입력하여 document 객체의 createElement 메서드를 이용하여 <div> 요소를 만든다.
    document.createElement('div')
  • 작업의 결과를 담기 위해 변수를 선언하고 어떤 작업의 결과를 변수에 할당한다.
    여기서는 div element를 변수 tweetDiv 에 할당하였다.
    const tweetDiv = document.createElement('div')
  • 그리고 이렇게 createElement 메서드로 생성된 엘리먼트는 공중에 떠있는 상태이다.
    따라서 화면에는 어떠한 변화가 없는 것이 당연하다.
    • 생성된 엘리먼트가 아무것도 연결이 되어 있지 않은 모습
    • 위 그림처럼 공중에 떠있는 엘리먼트를 확인하기 위해서는 APPEND를 하여 트리 구조에 연결해야 한다.



APPEND

  • 이전 콘텐츠 CREATE에서 생성한 tweetDiv를 트리 구조와 연결해보자.

  • CREATE에서 만든 tweetDiv 라는 변수는 아직 "공중부양"을 하고 있다.

  • 이번에는 append 라는 메서드를 사용해서, 변수 tweetDiv<body> 에 넣어보자.

    document.body.append(tweetDiv)
    • 변수 tweetDiv에 담긴 새로운 <div> 요소를 <body> 요소에 append 한다.
    • 이번에도 역시 눈에 띄는 결과가 보이지 않는다. 뭐가 잘못된 걸까?
    • 아니다. 새롭게 생성한 <div> 요소에 아무런 내용을 입력하지 않아서 보이는 내용이 없을 뿐 크롬의 개발자 도구 Elements 탭에서 확인하면 <div> 요소가 추가된 것을 확인할 수 있다.

특정 엘리먼트 안에 특정 요소를 append 하기!! 🙋‍♀️

  • 특정 엘리먼트 안에 생성한 요소를 넣고 싶을 땐 어떻게 해야 할까?
  • 예시코드를 기준으로 이야기하자면, 넣고 싶은 HTML 엘리먼트 정보를 querySelector()로 가져와 새로운 <div> 요소가 담긴 변수 tweetDivappend한다.
    • 방법1.
      const tweetDiv = document.createElement('div')
      document.querySelector("#container").append(tweetDiv);


    • 방법2: container의 맨 마지막 자식 요소로 tweetDiv를 추가한다.
      const container = document.querySelector('#container')
      const tweetDiv = document.createElement('div')
      container.append(tweetDiv)


  • 결과 (브라우저)
    • 새롭게 추가된 tweetDiv 는 별도의 class 가 지정되어 있지 않아, CSS를 이용한 스타일링이 적용되지 않았다.

  • 결과 (그림)



READ

  • DOM으로 HTML 엘리먼트의 정보를 조회하기 위해서는 querySelector의 첫 번째 인자로 셀렉터(selector)를 전달하여 확인할 수 있다고 하였다.
  • 셀렉터로는 HTML 요소("div"), id("#tweetList"), class(.tweet) 세 가지가 가장 많이 사용된다.

querySelector

  • querySelector'.tweet' 을 첫 번째 인자로 넣으면, 클래스 이름이 tweetHTML 엘리먼트 중 첫 번째 엘리먼트를 조회할 수 있다.
    const oneTweet = document.querySelector('.tweet')
    • querySelector로 클래스 이름이 tweetHTML 요소를 조회

querySelectorAll

  • 여러 개의 요소를 한 번에 가져오기 위해서는, querySelectorAll 을 사용한다.
  • 이렇게 조회한 HTML 요소들은 배열처럼 for문을 사용하실 수 있다.
    그러나 앞서 조회한 HTML 요소들은 배열이 아니다! 이런 '배열 아닌 배열'을 유사 배열, 배열형 객체 등 다양한 이름으로 부른다. 정식 명칭은 Array-like Object 이다.
    Array-like Object 같이 개념을 설명하는 용어는 영어로도 명확하게 기억해두는 게 좋다.
    const tweets = document.querySelectorAll('.tweet')
    • querySelectorAll로 클래스 이름이 tweet 인 모든 HTML 요소를 유사 배열로 받아옴.



UPDATE

  • 앞서 진행한 CREATE, APPEND, READ를 통해 새로운 DOM 객체를 만들고, 기존의 DOM 객체에 붙이고, DOM 객체를 선택해서 조회하는 방법을 학습했다.
  • 이번 UPDATE에서는 기존에 생성한 빈 div 태그를 업데이트하여, 보다 다양한 작업을 해보자.
  • 먼저 oneDiv라는 이름의 <div> 요소를 만들었다.
    const oneDiv = document.createElement('div');
    console.log(oneDiv) // <div></div>

  • 그리고 textContent 를 사용해서, 비어있는 div 엘리먼트에 문자열을 입력한다.
    oneDiv.textContent = 'dev';
    console.log(oneDiv) // <div>dev</div>
    • textContent를 이용해 문자열을 입력할 수 있다.
    • 주의❗ : innerHTML을 사용할 수도 있지만 이 방법은 꼭 필요하지 않으면 지양하는 것이 좋다.
      (HTML tag를 직접 삽입하여 실행하는 형태의 메서드는 늘 이런 위험을 가지고 있다. <script> tag를 활용하여 강제로 해커가 원하는 스크립트를 실행시키는 XSS Attack이 대표적이다. 공격의 여지를 주지 않게 개발하는 것이 가장 좋다.)

  • 앞서 생성한 div 엘리먼트를 containerappend 했을 때, CSS 스타일링이 적용되지 않았다. CSS 스타일링이 적용하려면, div 엘리먼트에 해당 class를 추가해야 한다.
    • 방법1 : classList.add를 이용해 'tweet' 클래스를 추가한다.
      oneDiv.classList.add('tweet')
      console.log(oneDiv) // <div class="tweet">dev</div>

    • 방법2 : className 속성를 이용해 'tweet' 클래스를 추가한다.
      oneDiv.className = 'tweet'
      console.log(oneDiv) // <div class="tweet">dev</div>
      (아이디를 추가할 경우에는 id 속성을 이용한다. ex - oneDiv.id = 'tweet')

  • 생성한 엘리먼트에 텍스트를 채웠고, 클래스를 추가하여 스타일링을 적용했다.
    이번에는 append를 이용해 container의 자식 요소로 추가해보자.
    const container = document.querySelector('#container')
    container.append(oneDiv)
    • append를 이용해 container의 자식 요소에 oneDiv를 추가한다.

  • 결과 (브라우저)



DELETE

  • 마지막으로 HTML Element를 삭제하는 방법에 대해 알아보자.
  • 삭제하는 방법에도 여러 가지가 있다.

삭제하려는 요소의 위치를 알고 있는 경우

  • remove 메서드를 사용하여 앞서 생성하고 추가한 oneDiv 를 삭제한다.
    const container = document.querySelector('#container')
    const oneDiv = document.createElement('div')
    container.append(oneDiv)
    oneDiv.remove() // 이렇게 append 했던 요소를 삭제할 수 있다.
    • idcontainer인 요소 아래에 oneDiv를 추가하고, remove로 삭제한다.

    • 결과 (브라우저)
    • 결과 (그림)

여러 개의 자식 요소를 지우려는 경우

  • removeChild 는 자식 요소를 지정해서 삭제하는 메서드이다.
  • 모든 자식 요소를 삭제하기 위해, 반복문(while, for, etc.)을 활용할 수 있다.
    다음의 코드는 자식 요소가 남아있지 않을 때까지, 첫 번째 자식 요소를 삭제하는 코드이다.
    const container = document.querySelector('#container');
    while (container.firstChild) {
      container.removeChild(container.firstChild);
    }
    • container의 첫 번째 자식 요소가 존재하면, 첫 번째 자식 요소를 제거한다.
  • innerHTML 을 이용하는 방법도 있지만(간편하고 편리한 방식이긴 함), innerHTML은 보안에서 몇 가지 문제를 가지고 있기 때문에 지양한다. 🙅‍♀️

  • 이렇게 removeChildwhile 을 이용해 자식 요소를 삭제하면, 제목에 해당하는 H2 "Tweet List"까지 삭제되어 버린다. (위 이미지 참고)
  • 이를 방지하기 위한 방법은 여러 가지가 있다.
  • 자식 요소가 담고 있는 문자열을 비교해 "Tweet List"만 남기거나,
    새로운 변수를 생성하고 Tweet List를 할당해뒀다가 반복문이 끝난 뒤에 새롭게 추가할 수도 있다.
    또는 자식 요소를 하나만 남기게 할 수도 있다.

  • 방법1 : container의 자식 요소가 1개만 남을 때까지, 마지막 자식 요소를 제거하는 방법

    const container = document.querySelector('#container');
    while (container.children.length > 1) {
      container.removeChild(container.lastChild);
    }
  • 방법2 : 직접 클래스 이름이 tweet인 요소만 찾아서 지우는 방법

    const tweets = document.querySelectorAll('.tweet')
    tweets.forEach(function(tweet){
        tweet.remove();
    })
    // or
    for (let tweet of tweets){
        tweet.remove()
    }
    • 클래스 이름이 tweet인 요소만 찾아서 제거한다.

0개의 댓글