Command Palette

Search for a command to run...

1편에서는 프론트엔드가 왜 복잡해졌는지 큰 흐름을 봤다. 웹은 문서 공유에서 출발했지만, 시간이 지나면서 구조, 표현, 동작, 상태, API 통신, 성능, 접근성, 배포까지 더 많은 책임을 맡게 됐다.

2편에서는 그중 가장 먼저 내려가야 할 바닥을 본다. 브라우저는 HTML 파일을 받으면 바로 화면을 보여주는 것처럼 보이지만, 실제로는 여러 내부 모델을 만든 뒤 화면을 계산한다. 그 중심에 DOM이 있다.

이번 글의 핵심 문장은 이것이다.

DOM은 화면 자체가 아니라, 브라우저가 HTML을 JavaScript로 읽고 수정할 수 있게 만든 문서 객체 모델이다.

이 문장을 붙잡으면 여러 개념이 한 줄로 이어진다. innerHTML이 왜 위험할 수 있는지, event delegation이 왜 가능한지, reflow가 왜 성능 비용인지, DevTools Performance panel에서 Layout과 Paint를 왜 보는지 이해하기 쉬워진다.

HTML 파일은 바로 화면이 아니라 DOM으로 먼저 바뀐다

브라우저가 서버에서 HTML을 받았다고 해서 그 문자열을 그대로 화면에 붙이는 것은 아니다.

브라우저는 HTML source를 읽고 파싱한다. 태그의 중첩 관계를 해석하고, 요소와 속성과 텍스트를 노드로 만든다. 그 결과가 DOM tree다.

<main>
  <h1>프론트엔드 공부</h1>
  <button id="save">저장</button>
</main>

이 HTML은 브라우저 안에서 대략 이런 tree로 이해된다.

document
└─ html
   └─ body
      └─ main
         ├─ h1
         │  └─ "프론트엔드 공부"
         └─ button#save
            └─ "저장"

여기서 중요한 점은 DOM이 HTML source와 같지 않다는 것이다.

HTML source는 서버에서 받은 문자열에 가깝다. DOM은 브라우저가 그 문자열을 해석해 만든 객체 tree다. JavaScript가 document.querySelector("#save")로 찾고, textContent를 바꾸고, event listener를 붙이는 대상은 HTML 파일의 문자열이 아니라 이 DOM tree다.

const button = document.querySelector("#save");
button.textContent = "저장 중...";
button.addEventListener("click", save);

그래서 "JavaScript가 화면을 바꾼다"는 말은 반쯤 맞다. 더 정확히는 JavaScript가 DOM을 바꾸고, 브라우저가 그 변경을 바탕으로 화면을 다시 계산한다.

HTML source
-> browser parsing
-> DOM tree
-> JavaScript가 DOM 읽기/수정
-> browser가 rendering 결과 갱신

이 구분은 초보자에게 매우 중요하다. DOM을 화면 픽셀이라고 생각하면 reflow, event bubbling, XSS, React의 rendering 모델까지 계속 헷갈린다.

DOM, CSSOM, render tree는 서로 다른 질문에 답한다

브라우저는 HTML만 읽지 않는다. CSS도 읽는다.

HTML이 문서의 구조를 만들면, CSS는 각 요소가 어떻게 보일지 결정한다. 브라우저는 CSS도 파싱해 CSSOM이라는 구조로 만든다. DOM은 문서 구조를 담고, CSSOM은 style 규칙을 담는다.

둘은 서로 다른 질문에 답한다.

DOM:
무엇이 있는가?
어떤 요소가 어떤 자식 요소를 가지는가?
어떤 텍스트와 속성이 있는가?

CSSOM:
각 요소에 어떤 style 규칙이 적용되는가?
최종 color, display, font-size, margin은 무엇인가?

브라우저는 DOM과 CSSOM을 바탕으로 render tree를 만든다. Render tree는 화면에 실제로 그릴 대상만 모은 tree에 가깝다.

예를 들어 display: none인 요소는 DOM에는 있을 수 있지만 화면에는 그려지지 않는다. 그래서 render tree에서는 빠질 수 있다. 반대로 visibility: hidden인 요소는 보이지 않아도 layout 공간을 차지한다. 이런 차이는 DOM만 봐서는 알 수 없고 CSS까지 함께 봐야 한다.

큰 흐름은 이렇게 잡으면 된다.

HTML source
-> DOM

CSS source
-> CSSOM

DOM + CSSOM
-> render tree
-> layout
-> paint
-> composite
-> screen

여기서부터 성능 이야기가 시작된다. 화면은 한 번에 뚝딱 나오는 것이 아니라, 구조를 만들고, style을 계산하고, layout을 잡고, pixel을 칠하고, layer를 합성하는 과정을 거친다.

Accessibility tree는 같은 DOM에서 나오는 또 다른 출력이다

브라우저가 DOM을 쓰는 곳은 화면 rendering만이 아니다.

1편에서 semantic HTML을 다루면서 봤듯이, HTML은 tag 목록이 아니라 브라우저가 읽는 의미 구조다. 브라우저는 DOM, native HTML semantics, ARIA, 일부 CSS 상태를 바탕으로 accessibility tree도 만든다.

DOM + HTML semantics + ARIA + 일부 CSS 상태
-> accessibility tree
-> screen reader 같은 보조기술

예를 들어 <button>저장</button>은 DOM node이면서 동시에 접근성 트리에서는 "저장이라는 이름을 가진 button"으로 노출될 수 있다. 반대로 <div onclick="save()">저장</div>는 시각적으로 버튼처럼 보여도, 기본 의미는 div다.

이 차이는 테스트 관점에서도 드러난다. 화면에 보이는 글자만 찾는 테스트보다, "이 요소가 button role과 저장이라는 accessible name으로 노출되는가"를 확인하는 테스트가 접근성 tree에 더 가까운 질문이다.

바이브코딩에서도 이 구분은 실용적이다. AI에게 "버튼처럼 보이게 만들어줘"라고만 하면 clickable div가 나올 수 있다. "semantic HTML로 만들고, accessible name과 keyboard 조작 가능성을 확인해줘"라고 말하면 결과가 달라진다.

DOM은 화면의 입력이기도 하지만, 접근성 의미의 입력이기도 하다.

JavaScript는 DOM API로 문서를 읽고 바꾼다

JavaScript가 DOM을 다룰 때 쓰는 표면을 DOM API라고 부른다.

자주 보이는 API는 이런 것들이다.

document.querySelector(".item");
document.querySelectorAll("button");
element.textContent = "완료";
element.innerHTML = "<strong>완료</strong>";
element.classList.add("active");
element.setAttribute("aria-expanded", "true");
element.addEventListener("click", handleClick);
document.createElement("li");

이 API들은 모두 DOM tree를 읽거나 바꾼다.

버튼을 찾는다. 텍스트를 바꾼다. class를 붙인다. ARIA 상태를 갱신한다. 클릭 event listener를 등록한다. 새 요소를 만든다. 그리고 이런 변경이 쌓이면 브라우저는 화면과 접근성 트리를 다시 갱신한다.

예를 들어 메뉴 버튼을 눌렀을 때 열림 상태를 바꾸는 코드는 단순한 style 변경이 아니다.

const button = document.querySelector("#menu-button");
const panel = document.querySelector("#menu-panel");

button.addEventListener("click", () => {
  const expanded = button.getAttribute("aria-expanded") === "true";

  button.setAttribute("aria-expanded", String(!expanded));
  panel.hidden = expanded;
});

여기서는 두 가지 일이 동시에 일어난다.

panel.hidden 변경:
화면 표시 상태가 바뀐다

aria-expanded 변경:
보조기술에 노출되는 상태 의미가 바뀐다

프론트엔드 코드는 종종 이렇게 화면과 의미를 동시에 갱신한다. 그래서 DOM API를 단순히 "요소를 찾고 바꾸는 함수"로만 보면 부족하다. DOM은 UI 구조, 상태, 접근성 의미가 만나는 작업 모델이다.

reflow는 느린 느낌이 아니라 layout을 다시 계산하는 비용이다

DOM이나 style을 바꾸면 브라우저가 화면을 다시 계산할 수 있다.

특히 요소의 크기나 위치에 영향을 주는 변경은 layout을 다시 계산하게 만든다. 이 layout 재계산 비용을 흔히 reflow라고 부른다. 최신 문서에서는 layout이라는 용어를 더 직접적으로 쓰는 경우가 많지만, 입문 단계에서는 reflow를 "layout을 다시 계산하는 비용"으로 이해하면 된다.

예를 들어 아래 변화는 layout에 영향을 줄 수 있다.

.card {
  width: 320px;
  padding: 24px;
  margin-top: 20px;
}

width, height, padding, margin, font-size, display, position, top, left처럼 geometry에 영향을 주는 값은 주변 요소의 위치와 크기까지 바꿀 수 있다. 브라우저는 "이 요소가 어디에 있어야 하는가", "다음 요소는 어디로 밀리는가"를 다시 계산해야 한다.

리스트 화면을 생각해보면 더 쉽다.

게시글 1개만 있는 화면에서는 layout 재계산 비용이 작을 수 있다. 하지만 1,000개 행이 있는 table이나 복잡한 dashboard에서 반복적으로 크기와 위치를 바꾸면 비용이 커진다.

특히 나쁜 패턴은 layout을 읽고 쓰는 일을 반복하는 것이다.

items.forEach((item) => {
  const height = item.offsetHeight; // layout 정보 읽기
  item.style.height = `${height + 10}px`; // layout에 영향 주는 쓰기
});

브라우저는 style 변경을 모아서 처리하려고 하지만, layout 정보를 읽는 순간 최신 layout 값이 필요해질 수 있다. 읽기와 쓰기가 섞이면 브라우저가 layout 계산을 자주 강제로 수행하게 되고, 화면이 버벅일 수 있다.

그래서 성능을 볼 때는 "DOM을 바꿨다"에서 멈추지 말고, 어떤 변경이 style 계산, layout, paint, composite 중 어디까지 영향을 주는지 봐야 한다.

repaint와 composite까지 나눠 봐야 성능 판단이 선명해진다

reflow만 알면 모든 성능 문제가 layout 때문처럼 보인다. 실제로는 비용의 층위가 더 나뉜다.

대략 이렇게 볼 수 있다.

style recalculation:
어떤 CSS 규칙이 적용되는지 다시 계산

layout / reflow:
요소의 크기와 위치를 다시 계산

paint / repaint:
pixel을 다시 칠함

composite:
이미 그려진 layer들을 합성해 최종 화면을 만듦

예를 들어 width를 바꾸면 layout부터 다시 갈 가능성이 크다. background-color를 바꾸면 layout은 그대로지만 paint가 필요할 수 있다. transform이나 opacity animation은 많은 경우 layout과 paint를 건너뛰고 composite 중심으로 처리될 수 있다.

그래서 animation에서는 이런 차이가 중요하다.

/* layout을 계속 바꿀 수 있음 */
.box {
  left: 100px;
}

/* 많은 경우 composite에 유리함 */
.box {
  transform: translateX(100px);
}

물론 transformopacity가 언제나 공짜라는 뜻은 아니다. layer가 너무 많아지면 memory와 compositor 비용이 커질 수 있다. 하지만 "왜 어떤 animation은 transform을 선호하는가"를 이해하려면 layout, paint, composite의 차이를 알아야 한다.

프론트엔드 성능은 감각으로만 판단하기 어렵다. "느리다"는 느낌 뒤에는 JavaScript 실행, style 계산, layout, paint, composite 중 하나 또는 여러 개가 숨어 있다.

event loop는 JavaScript와 rendering 기회를 조율한다

JavaScript는 아무 때나 마음대로 실행되고, 브라우저도 아무 때나 화면을 그리는 것이 아니다. 브라우저는 event loop로 JavaScript 실행, 사용자 입력, timer, network callback, rendering 기회를 조율한다.

입문 단계에서는 아래 흐름으로 이해하면 충분하다.

task 실행
-> microtask queue 비우기
-> requestAnimationFrame callback
-> style 계산
-> layout
-> paint
-> composite
-> 화면 표시

Task는 큰 실행 단위다. 초기 script 실행, click event handler, setTimeout callback, network event callback 같은 것이 task로 들어간다.

Microtask는 현재 task가 끝난 직후, 브라우저가 다음 rendering 기회를 갖기 전에 처리되는 작은 후속 작업이다. Promise.then(), queueMicrotask(), MutationObserver callback이 대표적이다.

예를 들어 이런 코드를 보자.

console.log("sync");

setTimeout(() => console.log("task"), 0);

Promise.resolve().then(() => console.log("microtask"));

console.log("end");

대략 이런 순서로 찍힌다.

sync
end
microtask
task

왜 이게 중요할까.

Microtask는 rendering 전에 모두 비워진다. 그래서 microtask 안에서 다시 microtask를 계속 추가하면 브라우저가 화면을 갱신할 기회를 얻기 어렵다. 사용자는 버튼을 눌렀는데 화면이 멈춘 것처럼 느낄 수 있다.

반대로 시각적 업데이트를 다음 frame timing에 맞추고 싶다면 requestAnimationFrame이 더 자연스럽다.

requestAnimationFrame(() => {
  box.style.transform = "translateX(100px)";
});

requestAnimationFrame callback은 다음 화면 갱신 직전에 실행된다. animation이나 scroll-driven UI처럼 시각적 변화가 있는 코드는 이 타이밍에 맞추는 편이 브라우저의 frame pipeline과 잘 맞다.

여기까지 오면 DOM 변경을 더 정확히 말할 수 있다.

JavaScript가 DOM을 바꾼다
-> 그 변경은 event loop와 frame timing을 지난다
-> browser가 style/layout/paint/composite를 수행한다
-> 사용자는 화면 변화를 본다

innerHTML은 편하지만 HTML 해석 경계를 여는 API다

DOM API 중에서 초보자가 특히 조심해야 할 것이 innerHTML이다.

innerHTML은 요소 안의 내용을 HTML 문자열로 읽거나 쓴다. 즉 문자열을 HTML로 해석해 DOM node를 만든다.

message.innerHTML = "<strong>저장했습니다.</strong>";

이 자체가 항상 나쁜 것은 아니다. 신뢰할 수 있는 template을 넣는 상황에서는 쓸 수 있다. 문제는 사용자 입력이나 외부 데이터를 그대로 넣을 때 생긴다.

comment.innerHTML = userInput;

만약 userInput에 공격자가 만든 HTML이나 script 실행 가능성이 있는 payload가 들어오면, 브라우저는 그것을 단순 텍스트가 아니라 HTML로 해석하려고 한다. 이런 경계에서 XSS가 시작될 수 있다.

단순히 사용자가 입력한 문장을 보여주면 되는 상황이라면 textContent가 기본 선택지다.

comment.textContent = userInput;

textContent는 문자열을 HTML로 해석하지 않고 텍스트로 넣는다. <strong>이라는 글자가 들어오면 굵은 글자가 되는 것이 아니라 <strong>이라는 텍스트로 표시된다.

바이브코딩에서 이 차이는 아주 중요하다. AI에게 "사용자 댓글을 화면에 보여줘"라고만 하면 구현이 어떻게 나올지 모른다. 더 좋은 요청은 이렇게 한다.

사용자 입력은 HTML로 해석하지 말고 textContent로 표시해줘.
정말 HTML이 필요하다면 sanitizer가 필요한지 설명해줘.

보안은 백엔드만의 일이 아니다. 브라우저가 문자열을 HTML로 해석하는 순간, 프론트엔드도 보안 경계를 다루고 있다.

event bubbling은 DOM tree가 코드 패턴으로 드러나는 순간이다

DOM이 tree라는 사실은 event 처리에서도 드러난다.

버튼을 클릭하면 event는 그 버튼에서만 끝나지 않는다. 일반적으로 target에서 시작해 부모 요소 방향으로 올라간다. 이것을 event bubbling이라고 한다.

<ul id="todo-list">
  <li>
    <button data-id="1">완료</button>
  </li>
  <li>
    <button data-id="2">완료</button>
  </li>
</ul>

각 버튼에 listener를 붙일 수도 있다.

document.querySelectorAll("#todo-list button").forEach((button) => {
  button.addEventListener("click", handleDone);
});

하지만 항목이 많거나 동적으로 추가되는 리스트에서는 부모 하나에 listener를 붙이는 방식이 더 단순할 수 있다.

const list = document.querySelector("#todo-list");

list.addEventListener("click", (event) => {
  const button = event.target.closest("button[data-id]");
  if (!button) return;

  markDone(button.dataset.id);
});

이것이 event delegation이다.

버튼에서 발생한 click event가 부모 ul까지 bubble 되기 때문에 가능한 패턴이다. 새 libutton이 나중에 추가되어도 부모 listener는 그대로 동작한다.

event delegation은 "성능 최적화 기술"로만 외우면 약하다. 더 정확히는 DOM tree와 event propagation을 이용해 동적 UI를 단순하게 다루는 코드 패턴이다.

3편에서 jQuery와 React를 비교할 때도 이 지점이 이어진다. jQuery는 DOM 조작과 event 처리를 쉽게 해줬다. 하지만 UI 상태가 복잡해질수록 DOM을 직접 찾아 바꾸는 코드가 여러 event handler에 흩어지는 문제가 커졌다.

Shadow DOM은 숨김 장치가 아니라 캡슐화 장치다

Shadow DOM도 DOM 이야기에서 자주 오해되는 주제다.

Shadow DOM은 웹 컴포넌트 내부 구조와 스타일을 외부 문서와 어느 정도 분리하는 기술이다. 컴포넌트 내부의 markup과 style을 캡슐화해, 바깥 CSS와 충돌을 줄이고 내부 구현을 감추는 데 도움을 준다.

하지만 Shadow DOM은 보안 장벽이 아니다.

브라우저가 화면에 그릴 수 있는 데이터는 이미 클라이언트에 온 데이터다. Shadow DOM 안에 넣었다고 해서 서버의 비밀 데이터가 안전해지는 것은 아니다. mode: "closed" 같은 설정도 일반적인 DOM 접근을 어렵게 만들 수는 있지만, 민감한 정보를 보호하는 보안 모델로 보면 안 된다.

크롤링 방지 수단으로 이해하는 것도 위험하다. 검색엔진이나 자동화 도구의 처리 방식은 도구마다 다를 수 있지만, "Shadow DOM에 넣으면 절대 수집되지 않는다"는 식으로 기대해서는 안 된다.

기본 원칙은 간단하다.

보여주면 안 되는 데이터는 클라이언트에 보내지 않는다.
권한 검사는 서버에서 한다.
Shadow DOM은 캡슐화 도구로 이해한다.

이 원칙은 바이브코더에게도 중요하다. AI에게 "이 값을 화면에는 숨겨줘"라고 요청하는 것과 "이 값은 권한 없는 사용자에게 API 응답으로 보내지 마"라고 요청하는 것은 완전히 다른 말이다.

DevTools Performance panel은 느린 화면을 시간축으로 보여준다

성능 문제는 말로만 설명하면 감각적이다.

"버벅인다", "느리다", "클릭이 늦게 먹는다", "스크롤이 끊긴다" 같은 표현은 사용자의 경험을 잘 보여주지만, 원인을 바로 말해주지는 않는다.

Chrome DevTools Performance panel은 이 원인을 시간축으로 보여준다.

관찰할 수 있는 항목은 대략 이렇다.

Main thread
Long Task
Recalculate Style
Layout
Paint
Composite Layers
LCP marker
Layout Shift

예를 들어 button click 이후 긴 JavaScript task가 main thread를 오래 점유하면 사용자의 다음 입력 반응이 늦어질 수 있다. DOM을 반복해서 읽고 쓰는 코드가 있으면 Layout이 여러 번 발생할 수 있다. 큰 이미지나 복잡한 그림자 효과는 Paint 비용을 키울 수 있다. 광고나 이미지 크기 미지정으로 내용이 밀리면 Layout Shift가 보일 수 있다.

DevTools를 볼 때 처음부터 모든 것을 해석하려고 할 필요는 없다. 2편 단계에서는 이 정도 질문이면 충분하다.

긴 JavaScript task가 있는가?
Layout이 반복되는가?
Paint 영역이 큰가?
Composite 중심으로 처리되는 animation인가?
LCP와 Layout Shift marker가 어디에 찍히는가?

중요한 것은 "느낌"을 "trace"로 바꾸는 일이다. Trace를 보면 AI에게도 더 정확히 요청할 수 있다.

이 화면이 느립니다

보다

Performance panel에서 click 이후 긴 Long Task가 반복해서 나오고,
Layout이 반복됩니다.
DOM read/write가 섞인 부분을 찾아서 batch 처리하거나
layout 영향을 줄이는 방식으로 개선해 주세요.

가 훨씬 강한 요청이다.

Core Web Vitals는 내부 비용을 사용자 경험 언어로 바꾼다

브라우저 내부에서는 style, layout, paint, composite 같은 비용을 본다. 하지만 사용자는 이런 단어를 느끼지 않는다.

사용자는 이렇게 느낀다.

주요 콘텐츠가 빨리 보였는가?
클릭이나 입력에 빨리 반응했는가?
읽고 있는데 화면이 갑자기 밀리지 않았는가?

Core Web Vitals는 이 경험을 지표로 바꾼다. 2026-05-11 기준 공식 Web Vitals 문서에서 확인한 핵심 지표는 LCP, INP, CLS다.

LCP:
주요 콘텐츠가 언제 보였는가

INP:
사용자 interaction에 얼마나 빨리 반응했는가

CLS:
화면이 예기치 않게 얼마나 흔들렸는가

2편의 핵심은 이 지표를 외우는 것이 아니다. DOM 변경과 JavaScript 실행과 rendering pipeline이 결국 사용자가 느끼는 경험으로 이어진다는 감각을 잡는 것이다.

예를 들어 hero image가 늦게 로딩되면 LCP가 나빠질 수 있다. Click handler가 긴 계산을 main thread에서 돌리면 INP가 나빠질 수 있다. 이미지 크기를 지정하지 않아 로딩 후 본문이 아래로 밀리면 CLS가 나빠질 수 있다.

그래서 성능 최적화는 "코드를 빠르게"가 아니라 "사용자가 보는 흐름을 안정적으로" 만드는 일에 가깝다.

AI에게 맡길 때는 DOM, 보안, 성능 조건을 같이 말해야 한다

바이브코더 입장에서 2편의 실전 가치는 분명하다.

AI에게 웹 UI를 맡길 때 "버튼 누르면 목록 바꿔줘"라고만 말하면 DOM 조작, 보안, 접근성, 성능 조건이 빠질 수 있다. 작은 실습에서는 괜찮을 수 있지만, 실제 화면에서는 나중에 고치기 어려운 방식으로 코드가 만들어질 수 있다.

요청을 이렇게 바꾸면 더 낫다.

이 HTML 구조를 semantic하게 만들고,
JavaScript는 DOM API로 필요한 요소만 갱신해 주세요.

사용자 입력은 HTML로 해석하지 말고 textContent로 표시하고,
innerHTML이 필요하다면 XSS 위험과 sanitizer 필요성을 설명해 주세요.

동적으로 추가되는 list item은 부모 container에 event delegation을 적용하고,
클릭 target은 closest로 검증해 주세요.

크기와 위치를 반복해서 읽고 쓰는 코드를 피하고,
DOM read/write를 분리해 layout thrashing 가능성을 줄여 주세요.

DevTools Performance panel에서 확인할 항목도 함께 알려 주세요.

이런 요청은 단순히 "더 자세한 프롬프트"가 아니다. 브라우저가 실제로 일하는 방식에 맞춘 요구사항이다.

AI가 코드를 만들더라도 최종 책임은 사용자가 읽고 판단해야 한다. DOM이 무엇인지, innerHTML이 왜 위험한지, reflow가 무엇인지, event delegation이 왜 가능한지 알면 AI가 만든 코드를 훨씬 더 잘 검토할 수 있다.

DOM을 알면 3편의 jQuery와 React 차이가 보인다

2편의 결론은 이렇다.

DOM은 화면 자체가 아니다. HTML source도 아니다. 브라우저가 HTML을 해석해 만든 문서 객체 모델이고, JavaScript가 웹 문서를 읽고 수정하는 작업 표면이다.

이 모델을 알면 여러 문제가 한 줄로 연결된다.

DOM을 바꾸면
-> browser가 rendering pipeline을 다시 거친다
-> layout/reflow, paint, composite 비용이 생길 수 있다
-> event는 DOM tree를 따라 bubble 될 수 있다
-> 문자열을 HTML로 해석하면 XSS 경계가 열린다
-> semantic HTML과 ARIA는 accessibility tree에 영향을 준다

이제 다음 질문이 자연스럽게 나온다.

DOM을 직접 찾아 바꾸는 방식으로 UI를 만들 수 있다. jQuery는 이 일을 훨씬 쉽게 해줬다. 그런데 화면이 커지고 state가 많아지면, DOM을 직접 바꾸는 코드가 여러 event handler에 흩어진다.

그래서 3편에서는 jQuery가 왜 한때 혁명이었는지, 그리고 왜 React가 state 기반 UI라는 다른 모델을 들고 나왔는지로 넘어간다.

이어 읽기

시리즈는 순서대로, 편집 추천은 맥락대로, 비슷한 주제는 태그 기준으로 정리합니다.

시리즈 전체

AI에게 웹 개발을 더 잘 맡기기 위한 웹 기초2/5
  1. 1.AI 웹개발 기초: 프론트엔드 1-1 | 프론트엔드는 왜 이렇게 복잡해졌을까
  2. 2.AI 웹개발 기초: 프론트엔드 1-2 | DOM은 화면이 아니라 브라우저의 작업 모델이다
  3. 3.AI 웹개발 기초: 프론트엔드 1-3 | jQuery에서 React로 넘어간 진짜 이유
  4. 4.AI 웹개발 기초: 프론트엔드 1-4 | React를 쓰는데 왜 Node.js와 npm이 필요할까
  5. 5.AI 웹개발 기초: 프론트엔드 1-5 | SPA, SSR, Next.js는 어떤 기준으로 골라야 할까

비슷한 주제의 글

태그가 겹치는 글입니다. 시리즈와 편집 추천에 이미 나온 글은 제외합니다.