모든 강의를 무료로 볼 수 있어요. 회원가입 없이도 학습 가능합니다.

20강 / 전체 22강

요소 생성·삭제

11분 읽기 조회 10

createElement로 요소 생성, append·prepend·insertBefore로 삽입, remove·replaceWith로 삭제·교체, insertAdjacentHTML과 DocumentFragment로 성능 최적화, 데이터 기반 동적 리스트 렌더링까지 배웁니다.

🎯 학습 목표

이 강을 마치면 다음을 할 수 있습니다.

  • createElement로 새 요소를 만들고 속성과 내용을 설정할 수 있습니다.
  • append, prepend, insertBefore로 원하는 위치에 요소를 삽입할 수 있습니다.
  • remove, replaceWith로 요소를 삭제하거나 교체할 수 있습니다.
  • 데이터 배열로 DOM 목록을 동적으로 렌더링할 수 있습니다.

🏗️ createElement — 요소 만들기

이 섹션에서는 자바스크립트로 HTML 요소를 새로 생성하고 속성과 내용을 설정하는 방법을 살펴보겠습니다.

17강에서 innerHTML을 사용해 HTML 문자열로 요소를 추가했습니다. 하지만 더 안전하고 권장되는 방법은 document.createElement()로 요소 객체를 직접 만드는 것입니다. innerHTML은 XSS 위험이 있고 기존 내용을 모두 교체하지만, createElement는 필요한 요소만 정확히 만들 수 있습니다.

// 기본 사용법
const div = document.createElement("div");
console.log(div);  // <div></div>

// 속성 설정
div.id = "new-box";
div.className = "card highlighted";
div.textContent = "새로운 내용";

// setAttribute 사용
div.setAttribute("data-id", "42");
div.setAttribute("aria-label", "카드 요소");

// 스타일 설정
div.style.padding = "16px";
div.style.borderRadius = "8px";

// 이벤트 리스너 추가 — DOM에 삽입 전에도 가능
div.addEventListener("click", () => {
  console.log("카드 클릭!");
});

// 더 복잡한 요소 만들기
function createCard({ title, description, imageUrl }) {
  const card = document.createElement("article");
  card.className = "card";

  const img = document.createElement("img");
  img.src = imageUrl;
  img.alt = title;

  const h2 = document.createElement("h2");  // 주의: 실제 페이지에선 레벨 맞게
  h2.textContent = title;

  const p = document.createElement("p");
  p.textContent = description;

  // 자식으로 추가
  card.append(img, h2, p);  // 여러 요소 한 번에 추가 가능

  return card;  // 완성된 요소 반환
}

const newCard = createCard({
  title: "자바스크립트 강좌",
  description: "기초부터 실전까지",
  imageUrl: "/images/js.png"
});

createElement로 만든 요소는 아직 메모리 안에만 있습니다. DOM에 삽입하기 전까지 화면에 보이지 않습니다. 삽입 전에 속성, 클래스, 스타일, 이벤트 리스너를 모두 설정해두는 것이 효율적입니다. 함수로 요소 생성 로직을 캡슐화하면 재사용성이 높아집니다. 이는 React 컴포넌트의 개념과 매우 유사합니다. 실제로 React는 내부적으로 비슷한 방식으로 DOM을 관리합니다.

📍 요소 삽입 — append, prepend, insertBefore

이 섹션에서는 생성한 요소를 DOM의 원하는 위치에 삽입하는 다양한 방법을 살펴보겠습니다.

요소를 만들었으면 DOM 트리에 삽입해야 화면에 보입니다. 삽입 위치에 따라 여러 메서드를 사용합니다.

const container = document.querySelector(".container");
const newEl = document.createElement("div");
newEl.textContent = "새 요소";

// append — 마지막 자식으로 추가
container.append(newEl);

// 문자열도 직접 추가 가능 (텍스트 노드 생성)
container.append("텍스트 추가");

// prepend — 첫 번째 자식으로 추가
const firstEl = document.createElement("div");
firstEl.textContent = "맨 앞 요소";
container.prepend(firstEl);

// insertBefore — 특정 요소 바로 앞에 삽입
const referenceEl = container.querySelector(".reference");
const beforeEl = document.createElement("div");
beforeEl.textContent = "기준 요소 앞"
container.insertBefore(beforeEl, referenceEl);

// insertAdjacentHTML — HTML 문자열로 4가지 위치에 삽입
// beforebegin: 요소 바로 앞 (형제)
// afterbegin: 첫 번째 자식
// beforeend: 마지막 자식
// afterend: 요소 바로 뒤 (형제)
container.insertAdjacentHTML("beforeend", "<p>HTML 삽입</p>");

// 요소 이동 — 이미 DOM에 있는 요소도 추가 가능 (자동으로 이동됨)
const existingEl = document.querySelector(".existing");
container.append(existingEl);  // 원래 위치에서 제거 후 여기로 이동

append는 여러 요소나 문자열을 한 번에 추가할 수 있는 현대적인 메서드입니다. 구형 브라우저에서는 appendChild를 사용했는데, 이는 노드 하나만 추가할 수 있습니다. 흥미로운 점은 이미 DOM에 있는 요소를 다른 곳에 append하면 자동으로 원래 위치에서 제거되고 새 위치로 이동됩니다. DOM 요소는 두 군데 동시에 존재할 수 없기 때문입니다. insertAdjacentHTML은 성능이 좋고 위치 지정이 유연해, 간단한 HTML 삽입에 유용합니다.

🗑️ 요소 삭제·교체

이 섹션에서는 DOM에서 요소를 제거하거나 다른 요소로 교체하는 방법을 살펴보겠습니다.

const target = document.querySelector(".to-remove");

// remove — 요소 자체 삭제
target.remove();

// 구형 방법 — 부모에서 제거
// target.parentNode.removeChild(target);

// replaceWith — 요소 교체
const newVersion = document.createElement("div");
newVersion.textContent = "교체된 요소";
target.replaceWith(newVersion);

// 자식 요소 모두 제거
const parent = document.querySelector(".parent");
// 방법 1: innerHTML 비우기 (빠르지만 이벤트 리스너가 있는 요소엔 주의)
parent.innerHTML = "";

// 방법 2: 개별 제거
while (parent.firstChild) {
  parent.removeChild(parent.firstChild);
}

// 방법 3: replaceChildren
parent.replaceChildren();  // 인수 없으면 모두 제거
parent.replaceChildren(newEl1, newEl2);  // 새 자식으로 교체

el.remove()는 요소 자신에서 호출하는 간결한 현대적 메서드입니다. 자식 요소를 모두 지울 때 innerHTML = ""이 가장 빠르지만, 이벤트 리스너가 붙은 요소는 메모리 누수를 일으킬 수 있습니다. replaceChildren()은 더 안전하게 자식을 제거하거나 교체합니다.

⚡ DocumentFragment — 성능 최적화

이 섹션에서는 많은 요소를 한 번에 추가할 때 성능을 높이는 DocumentFragment 패턴을 살펴보겠습니다.

DOM 조작은 브라우저의 렌더링을 유발해 비용이 큽니다. 요소를 하나씩 DOM에 추가하면 매번 레이아웃을 재계산합니다. 여러 요소를 추가할 때는 DocumentFragment에 모아서 한 번에 삽입하면 렌더링 횟수를 줄일 수 있습니다.

const ul = document.querySelector("ul");
const items = ["사과", "바나나", "포도", "딸기", "수박"];

// ❌ 비효율적 — 매번 DOM 재렌더링
items.forEach(item => {
  const li = document.createElement("li");
  li.textContent = item;
  ul.appendChild(li);  // 5번 DOM 수정
});

// ✅ DocumentFragment 사용 — DOM 수정 1번
const fragment = document.createDocumentFragment();
items.forEach(item => {
  const li = document.createElement("li");
  li.textContent = item;
  fragment.appendChild(li);  // 메모리 안에서만 추가
});
ul.appendChild(fragment);  // 한 번만 DOM 수정

// 실전: 데이터 배열로 카드 목록 렌더링
const products = [
  { id: 1, name: "노트북", price: 1200000, category: "전자제품" },
  { id: 2, name: "의자",   price: 350000,  category: "가구" },
  { id: 3, name: "책상",   price: 450000,  category: "가구" }
];

function renderProducts(products) {
  const container = document.querySelector(".products");
  container.innerHTML = "";  // 기존 내용 초기화

  const fragment = document.createDocumentFragment();

  products.forEach(product => {
    const card = document.createElement("div");
    card.className = "product-card";
    card.dataset.id = product.id;

    const name = document.createElement("h3");
    name.textContent = product.name;

    const price = document.createElement("p");
    price.textContent = `${product.price.toLocaleString()}원`;

    card.append(name, price);
    fragment.append(card);
  });

  container.append(fragment);
}

renderProducts(products);

// 카테고리 필터링 후 재렌더링
const furniture = products.filter(p => p.category === "가구");
renderProducts(furniture);

DocumentFragment는 실제 DOM 트리와 분리된 경량 컨테이너입니다. 여기에 요소를 추가해도 화면 렌더링이 발생하지 않습니다. append(fragment)로 DOM에 삽입하는 순간 모든 자식이 한 번에 이동됩니다. 데이터 배열로 DOM을 렌더링하는 함수 패턴은 매우 중요합니다. 데이터가 바뀔 때마다 이 함수를 다시 호출하면 UI가 항상 데이터와 동기화됩니다. React, Vue 같은 프레임워크가 이 원리를 더 세련되게 자동화한 것입니다.

📝 핵심 요약

20강에서 배운 내용을 정리해 보겠습니다.

작업메서드특징
요소 생성document.createElement(tag)메모리 내 요소 객체 생성
끝에 삽입parent.append(el, el2, ...)여러 요소·문자열 동시 추가
앞에 삽입parent.prepend(el)첫 번째 자식으로
위치 지정parent.insertBefore(el, ref)ref 요소 바로 앞
삭제el.remove()자기 자신 제거
교체el.replaceWith(newEl)해당 요소를 새 요소로 교체
성능 최적화document.createDocumentFragment()DOM 수정 횟수 최소화

다음 강인 21강 — 이벤트 위임과 버블링에서는 18강의 이벤트 처리를 심화합니다. 이벤트가 DOM 트리를 거슬러 올라가는 버블링 현상과, 이를 이용해 부모 요소 하나로 수많은 자식의 이벤트를 효율적으로 처리하는 이벤트 위임 패턴을 배웁니다. 20강에서 만든 동적 리스트와 결합하면 완전한 대화형 UI를 완성할 수 있습니다!

관련 주제

  • createElement
  • append prepend insertBefore
  • remove replaceWith
  • DocumentFragment
  • 동적 리스트 렌더링
  • 개발·프로그래밍
  • 개발·프로그래밍 강의
  • 자바스크립트 기초 30강 — 웹을 움직이는 언어
  • 무료강의
  • 무료 온라인 강의
  • NUGUNA
  • 누구나

📚 시리즈 전체 공유

자바스크립트 기초 30강 — 웹을 움직이는 언어

이 강의가 속한 시리즈는 총 22강, 모두 무료입니다. 처음부터 배우려는 동료에게 시리즈 전체를 알려 주세요.

댓글

0/1000

불러오는 중...