자바스크립트 DOM 조작하는 법 2026 초보자 입문 가이드
버튼을 눌렀는데 화면이 바뀌지 않거나, 입력한 글자를 목록에 추가하는 방법이 막막한가요? HTML과 CSS를 배운 뒤 실제로 움직이는 웹페이지를 만들려면 자바스크립트 DOM 조작을 이해해야 합니다. 이 글에서는 개발 도구를 처음 여는 초보자도 따라올 수 있도록 요소 선택부터 이벤트 처리, 실습 프로젝트, 디버깅까지 차근차근 설명합니다.
DOM이 무엇인지 기초 개념부터 이해하기
HTML 문서와 DOM의 차이
HTML은 웹페이지의 구조를 작성한 문서이고, DOM(Document Object Model)은 브라우저가 그 문서를 읽어 자바스크립트로 다룰 수 있게 만든 객체 구조입니다. 예를 들어 HTML에 작성한 버튼은 브라우저 안에서 하나의 객체가 되며, 자바스크립트는 이 객체의 글자와 색상, 속성, 표시 상태를 변경할 수 있습니다.
DOM은 흔히 나무 형태로 설명합니다. 최상위의 document 아래에 html, head, body가 놓이고 body 아래에는 제목, 문단, 버튼 같은 요소가 연결됩니다. 부모 요소 안에 자식 요소가 들어가는 HTML의 중첩 관계가 DOM에도 반영되는 것입니다. 코딩이라는 말 자체가 낯설다면 지식백과의 코딩 용어 설명을 함께 읽어 기초 개념을 잡아도 좋습니다.
초보자가 알아야 할 핵심 용어
DOM을 공부할 때는 모든 속성을 외우기보다 자주 등장하는 용어부터 익히는 편이 효율적입니다. 요소를 찾고, 값을 읽고, 바꾼 뒤, 사용자 행동에 반응한다는 네 단계만 기억하면 대부분의 기초 예제를 해석할 수 있습니다.
- 요소(element): 제목, 버튼, 입력창처럼 태그로 표현되는 화면 구성 단위입니다.
- 노드(node): 요소뿐 아니라 텍스트와 주석까지 포함하는 DOM의 구성 단위입니다.
- 속성(attribute): id, class, href처럼 태그에 부가 정보를 지정하는 값입니다.
- 메서드(method): 요소를 찾거나 추가하는 등 객체가 수행하는 기능입니다.
- 이벤트(event): 클릭, 입력, 제출처럼 브라우저에서 발생한 사용자 행동입니다.
처음부터 DOM 트리 전체를 암기할 필요는 없습니다. 개발자 도구의 Elements 패널에서 HTML을 직접 펼쳐 보며 부모와 자식 관계를 확인하는 습관이 훨씬 중요합니다.
자바스크립트로 HTML 요소 선택하고 내용 바꾸기
querySelector로 원하는 요소 찾기
화면을 변경하려면 가장 먼저 대상 요소를 선택해야 합니다. 초보자에게는 CSS 선택자 문법을 그대로 사용하는 document.querySelector()가 이해하기 쉽습니다. 예를 들어 document.querySelector('#title')은 id가 title인 첫 번째 요소를 찾고, document.querySelector('.item')은 item 클래스를 가진 첫 번째 요소를 반환합니다.
같은 클래스를 가진 요소를 모두 가져오고 싶다면 document.querySelectorAll()을 사용합니다. 반환된 결과는 여러 요소가 모인 NodeList이므로 forEach를 이용해 하나씩 처리할 수 있습니다. 선택자에 해당하는 요소가 없으면 querySelector는 null을 돌려주므로, 콘솔에 오류가 보인다면 철자와 스크립트 실행 시점을 먼저 점검해야 합니다.
텍스트와 스타일을 안전하게 변경하기
요소를 찾은 뒤에는 textContent로 글자를 바꿀 수 있습니다. 사용자 입력을 단순한 문장으로 출력할 때는 HTML 태그까지 해석하는 innerHTML보다 textContent를 우선 사용하는 편이 안전합니다. 스타일은 style 속성으로 직접 바꿀 수 있지만, 실제 프로젝트에서는 classList로 CSS 클래스를 추가하거나 제거하는 방식이 관리하기 좋습니다.
- const title = document.querySelector('#title');처럼 요소를 변수에 저장합니다.
- title.textContent = 'DOM 연습 중';으로 화면의 문구를 변경합니다.
- title.classList.add('active');로 미리 만든 CSS 클래스를 적용합니다.
- title.classList.toggle('active');로 클래스의 적용과 해제를 전환합니다.
- 콘솔에서 변수를 출력해 실제 요소가 선택되었는지 확인합니다.
직접 스타일을 지정하는 방식과 클래스 방식의 차이도 알아두세요. element.style.color = 'red'는 한두 속성을 빠르게 시험할 때 편하지만 디자인 규칙이 자바스크립트에 섞입니다. 반면 classList는 디자인을 CSS에 유지하므로 반응형 화면, 다크 모드, 여러 상태를 구현할 때 수정 범위가 작아집니다.
| 목적 | 권장 기능 | 초보자 주의점 |
|---|---|---|
| 첫 요소 선택 | querySelector | 선택 결과가 null인지 확인합니다. |
| 여러 요소 선택 | querySelectorAll | 결과를 단일 요소처럼 사용하지 않습니다. |
| 문구 변경 | textContent | 사용자 입력에 innerHTML을 남용하지 않습니다. |
| 디자인 상태 변경 | classList | CSS 클래스 이름의 철자를 맞춥니다. |
클릭과 입력 이벤트를 연결하는 방법
addEventListener의 동작 원리
버튼을 선택했다고 해서 클릭 기능이 자동으로 생기지는 않습니다. addEventListener를 사용해 어떤 이벤트가 발생했을 때 실행할 함수를 등록해야 합니다. 버튼 변수에 addEventListener('click', 함수)를 연결하면 사용자가 클릭할 때마다 등록한 함수가 호출됩니다.
HTML의 onclick 속성에 코드를 직접 적는 방법도 보이지만, 입문 이후에는 addEventListener를 권장합니다. HTML은 구조, CSS는 표현, 자바스크립트는 동작을 담당하도록 나눌 수 있고 한 요소에 여러 이벤트 처리기도 등록할 수 있기 때문입니다. 자바스크립트 파일을 별도로 관리하면 코드 검색과 테스트도 한결 편해집니다.
입력값 읽기와 폼 제출 처리
input 요소의 현재 입력값은 value로 읽습니다. 사용자가 할 일을 입력하고 추가 버튼을 눌렀다면 value를 읽고, 앞뒤 공백을 trim으로 제거한 다음 빈 문자열인지 확인해야 합니다. 검증하지 않으면 내용 없는 목록 항목이 계속 추가되어 사용성이 떨어집니다.
form의 submit 이벤트를 사용할 때는 브라우저가 페이지를 새로 고치는 기본 동작도 고려해야 합니다. 이벤트 처리 함수가 받은 event 객체에서 event.preventDefault()를 호출하면 새로고침을 막고 현재 화면에서 데이터를 처리할 수 있습니다. 키보드의 Enter 입력도 자연스럽게 지원하므로 단순 click 이벤트만 연결하는 것보다 접근성과 사용성이 좋습니다.
- click: 버튼이나 카드가 눌렸을 때 사용합니다.
- input: 입력창의 값이 바뀔 때마다 검색어 미리보기 등에 사용합니다.
- change: 선택 상자나 체크박스 값의 변경이 확정될 때 활용합니다.
- submit: 로그인, 검색, 할 일 등록처럼 폼을 제출할 때 사용합니다.
- keydown: 단축키를 구현할 때 쓰되 키보드 사용자에게 불편을 주지 않도록 설계합니다.
클릭만 시험하지 말고 Tab 키로 버튼에 이동한 뒤 Enter 또는 Space 키로도 작동하는지 확인하세요. 마우스 없이 사용할 수 있는 화면은 접근성뿐 아니라 전반적인 사용성도 좋아집니다.
이벤트를 너무 많이 연결하면 같은 동작이 중복 실행될 수도 있습니다. 화면을 다시 그리는 함수 안에서 매번 addEventListener를 호출하고 있지 않은지 살펴보세요. 반복 생성되는 목록은 각 항목에 별도 이벤트를 붙이는 대신 부모 요소에서 이벤트를 받고 event.target을 확인하는 이벤트 위임을 익히면 관리가 쉬워집니다.
할 일 목록으로 DOM 조작을 단계별 실습하기
필요한 화면 구조 설계
DOM 기초를 익히기 좋은 첫 프로젝트는 할 일 목록입니다. 입력창, 추가 버튼, 목록 영역만 있으면 시작할 수 있고 요소 선택, 이벤트, 생성, 삭제를 한 번에 연습할 수 있습니다. 코드를 쓰기 전에 화면에서 어떤 행동이 필요한지 문장으로 적으면 구현 순서가 선명해집니다.
예를 들어 “사용자가 내용을 입력한다→추가 버튼을 누른다→빈 값인지 검사한다→새 항목을 만든다→목록에 붙인다→입력창을 비운다”처럼 흐름을 나눠 보세요. 이런 절차적 사고가 프로그래밍의 핵심이며, 다른 관점의 개념 설명은 지식백과의 코딩 설명에서도 참고할 수 있습니다.
요소 생성과 삭제 구현
새 목록 항목은 document.createElement('li')로 만듭니다. 이어서 textContent에 입력값을 넣고 list.appendChild(item) 또는 list.append(item)으로 ul 요소에 추가합니다. 삭제 버튼도 createElement로 만든 뒤 항목 안에 붙이면 각 할 일 옆에 독립적인 삭제 기능을 배치할 수 있습니다.
- form, input, ul 요소를 querySelector로 선택합니다.
- form에 submit 이벤트 처리 함수를 등록합니다.
- preventDefault를 호출하고 input.value.trim()을 변수에 저장합니다.
- 값이 비어 있으면 안내 문구를 보여주고 함수를 종료합니다.
- li와 button 요소를 만들고 각각 문구를 지정합니다.
- 삭제 버튼의 click 이벤트에서 해당 li의 remove()를 호출합니다.
- 완성된 li를 ul에 추가한 뒤 입력창을 비우고 다시 포커스합니다.
여기서 한 단계 더 나아가 완료 상태를 구현할 수 있습니다. 항목을 누르면 completed 클래스를 toggle하고 CSS에서 취소선과 흐린 색을 적용해 보세요. 단, 삭제 버튼을 눌렀을 때 완료 이벤트까지 함께 실행된다면 이벤트 버블링이 원인일 수 있습니다. 삭제 버튼 처리기에서 상황에 따라 stopPropagation을 쓰거나, 클릭 대상을 구분하는 구조로 고치는 연습이 필요합니다.
페이지를 새로 열어도 목록을 유지하려면 localStorage를 활용할 수 있지만, 처음부터 저장 기능까지 한꺼번에 구현하지 않는 편이 좋습니다. 화면 추가와 삭제가 안정적으로 동작한 뒤 배열에 데이터를 저장하고 JSON.stringify와 JSON.parse를 연결하세요. 한 단계씩 실행하고 확인하는 습관이 복잡한 오류를 줄여 줍니다.
- 빈 문자열과 공백만 입력한 경우를 막았는지 확인합니다.
- 같은 내용의 중복 등록을 허용할지 정책을 정합니다.
- 항목 추가 후 input에 focus가 돌아오는지 시험합니다.
- 버튼의 type을 명시해 의도치 않은 폼 제출을 방지합니다.
- 삭제 전에 확인 절차가 필요한 서비스인지 판단합니다.
오류를 찾는 디버깅 순서와 자주 묻는 질문
화면이 작동하지 않을 때 확인할 체크리스트
초보자는 코드 전체를 다시 쓰기 전에 오류가 발생한 지점을 좁혀야 합니다. 브라우저 개발자 도구의 Console을 열고 빨간 오류 메시지의 첫 줄과 파일 위치를 확인하세요. Cannot read properties of null과 비슷한 메시지가 보인다면 요소를 찾지 못했거나 DOM이 만들어지기 전에 스크립트가 실행되었을 가능성이 큽니다.
스크립트 태그를 body 끝부분에 놓거나 defer 속성을 사용하면 HTML 분석이 끝난 뒤 자바스크립트를 실행할 수 있습니다. 또한 console.log로 선택한 요소, 입력값, 함수 실행 여부를 차례대로 출력하면 문제 범위를 빠르게 줄일 수 있습니다. 단순한 오타도 많으므로 id와 class, 대소문자, 괄호가 짝을 이루는지 확인하세요.
- 개발자 도구 Console에 문법 오류가 있는지 봅니다.
- querySelector 결과를 출력해 null 여부를 확인합니다.
- 이벤트 함수 첫 줄에 로그를 넣어 실제 호출 여부를 검사합니다.
- 입력값에 trim을 적용한 결과가 예상과 같은지 확인합니다.
- CSS가 요소를 숨기거나 클릭을 가로막고 있지 않은지 살펴봅니다.
- 수정한 자바스크립트 파일이 현재 HTML에 연결되어 있는지 점검합니다.
자주 묻는 질문 FAQ
Q. getElementById와 querySelector 중 무엇을 써야 하나요?
둘 다 올바른 방법입니다. id 하나만 빠르게 찾을 때는 getElementById가 명확하고, 클래스나 복합 선택자까지 같은 방식으로 다루고 싶다면 querySelector가 편합니다. 입문 단계에서는 한 방식을 중심으로 연습하되 다른 코드도 읽을 수 있도록 두 문법을 모두 알아두세요.
Q. innerHTML은 사용하면 안 되나요?
금지된 기능은 아니며 신뢰할 수 있는 고정 마크업을 넣을 때 편리할 수 있습니다. 그러나 사용자 입력이나 외부 데이터를 그대로 넣으면 원하지 않는 HTML이 해석될 위험이 있으므로 단순 텍스트는 textContent를 사용하고, 동적 구조는 createElement로 만드는 습관이 좋습니다.
Q. NodeList와 배열은 같은가요?
비슷해 보이지만 완전히 같지는 않습니다. querySelectorAll이 반환하는 NodeList는 forEach를 지원하지만 모든 배열 메서드를 똑같이 제공한다고 가정하면 안 됩니다. map이나 filter가 필요하면 Array.from(목록) 또는 펼침 문법으로 배열로 변환할 수 있습니다.
Q. DOM 공부 다음에는 무엇을 배우면 좋나요?
폼 검증, fetch를 이용한 API 통신, 비동기 처리, 모듈 문법 순서로 확장해 보세요. 프레임워크를 먼저 시작해도 되지만 순수 자바스크립트에서 요소 선택과 이벤트 흐름을 이해하면 React나 Vue의 화면 갱신 원리도 더 쉽게 받아들일 수 있습니다.
Q. 스마트폰에서도 개발자 도구를 사용할 수 있나요?
간단한 확인은 가능하지만 초보 학습에는 데스크톱 브라우저가 편합니다. 편집기와 브라우저를 나란히 열고 작은 수정마다 새로고침한 뒤 Console을 확인하세요. 하루에 긴 예제 하나를 복사하기보다 버튼 문구 변경, 클래스 전환, 항목 추가처럼 작은 기능을 직접 변형하는 편이 실력을 빠르게 높여 줍니다.
- 요소 선택 결과를 항상 확인합니다.
- 텍스트에는 textContent를 우선 사용합니다.
- 디자인 변화는 CSS 클래스와 classList로 관리합니다.
- 폼 제출 시 기본 동작과 입력 검증을 함께 처리합니다.
- 오류 메시지를 읽고 한 단계씩 실행 범위를 좁힙니다.

- 이전글TypeScript vs JavaScript 비교 분석 2026 웹개발 가이드 26.08.06
- 다음글2026 여름방학 코딩 프로젝트 완성하는 법 4주 실전 가이드 26.08.04
등록된 댓글이 없습니다.
