data-active는 컴포넌트 상태를 DOM 속성으로 노출하여 스타일과 로직을 의미 있게 분리하는 React 패턴이다.
HTML 요소
-
HTML 요소는 브라우저가 HTML 문서를 파싱할 때 DOM 트리 안의 노드 객체로 변환된다.
-
이 노드는 JavaScript의 객체이며,
Element나HTMLElement클래스의 인스턴스이다. -
즉, 화면에 보이는
<button>태그는 사실 메모리상에 존재하는 객체와 1:1로 연결되어 있다. -
객체이기 때문에 프로퍼티를 가질 수 있고, HTML의 속성(
attribute)은 이 객체의 정보로 저장된다. -
data-*속성도 마찬가지로 객체에 정보로 저장되며,element.dataset을 통해 JS에서 접근할 수 있다.const btn = document.querySelector("button"); btn.dataset.active; // "true" btn.dataset.active = "false"; // DOM에도 즉시 반영됨 -
따라서 마크업에 적은
data-active="true"는 단순한 텍스트가 아니라, 실제 DOM 객체의 살아있는 상태 정보이다. -
이 구조 덕분에 HTML, JS, CSS가 같은 정보를 공유하면서도 각자의 방식으로 읽고 활용할 수 있다.
배경
-
HTML에는 요소에 커스텀 정보를 저장할 수 있는
data-*속성이 존재한다. -
이 속성은 JavaScript나 CSS가 특정 상태를 추적하거나 스타일에 반응해야 할 때 활용된다.
-
UI 컴포넌트에서는 탭, 버튼, 메뉴 아이템 같은 요소가 "활성 상태"인지를 표현해야 하는 경우가 많다.
-
이때 상태를
className문자열로만 관리하면 의미가 흐려지고 스타일과 로직이 뒤섞이는 문제가 있다.
개념
-
data-active는 요소가 활성 상태인지를 마크업 수준에서 표현하는 커스텀 데이터 속성이다. -
React에서는 컴포넌트의
state값을 DOM 속성에 그대로 반영하는 패턴으로 자주 사용된다. -
예를 들어 탭에서 선택된 항목을 구분할 때 다음과 같이 작성한다.
<button data-active={isActive}>탭 1</button> -
이렇게 하면
isActive가true일 때 DOM에data-active="true"가 실제로 붙는다.
CSS 연결
-
CSS에서는 속성 선택자를 사용해 해당 상태에 스타일을 적용한다.
[data-active="true"] { background-color: blue; color: white; } -
상태가 마크업에 그대로 노출되어 있기 때문에 별도의 클래스 토글 없이도 CSS가 상태에 반응할 수 있다.
className 방식과의 비교
-
기존 방식은 조건부로
className을 바꾸어 스타일을 적용했다.// className 방식 <button className={isActive ? "active" : ""}>탭</button> // data-active 방식 <button data-active={isActive}>탭</button> -
className방식은 문자열을 조작해야 해서 상태와 스타일의 관계가 한눈에 드러나지 않는다. -
반면
data-active방식은 상태값이 그대로 속성에 반영되므로 의미가 명확하다. -
또한 상태는 컴포넌트가, 스타일링은 CSS가 담당하므로 역할 분리가 깔끔해진다.
aria-* 속성과의 차이
-
aria-*속성은 스크린 리더 같은 보조 기술에 의미를 전달하는 접근성 속성이다. -
반면
data-active는 접근성 의미를 부여하지 않고, 순수하게 시각적·논리적 상태 표현 용도로만 쓰인다. -
따라서 접근성까지 고려해야 한다면
aria-selected같은 속성을 함께 사용해야 한다.
마크업 수준 표현의 의미
-
"마크업 수준에서 표현한다"는 것은 상태가 JavaScript 변수 안에만 머무르지 않고 실제 DOM 속성으로 노출됨을 의미한다.
-
즉, 브라우저 개발자 도구에서 요소를 클릭하면 현재 상태가 그대로 보이는 상태가 된다.
-
상태가 마크업에 드러나 있기 때문에 CSS, 디버깅 도구, 테스트 코드가 모두 같은 정보원을 공유할 수 있다.
마크업 수준 표현의 장점
-
상태가 DOM에 드러나므로 DevTools에서 즉시 확인할 수 있어 디버깅이 쉽다.
-
CSS 속성 선택자만으로 상태별 스타일을 적용할 수 있어, JS에서 클래스 문자열을 조립할 필요가 없다.
-
테스트 코드에서도 속성 기반으로 요소를 찾을 수 있어, 시각 상태와 검증 로직이 일치한다.
-
상태와 마크업이 같은 위치에 표현되어 선언적이며, 컴포넌트의 의도가 한눈에 드러난다.
마크업 수준 표현의 단점
-
DOM 속성값은 항상 문자열로 변환되므로
boolean이나 숫자 같은 타입 정보가 손실된다.<button data-active={false} /> // 실제 DOM: <button data-active="false"> (속성이 제거되지 않음) -
따라서 CSS에서
[data-active]만 쓰면"false"상태에도 매칭되므로,[data-active="true"]처럼 값까지 명시해야 한다. -
잦은 상태 변경이 있는 경우 DOM 속성 업데이트가 발생하므로, 메모리 변수만 갱신하는 것보다 미세하게 비용이 더 든다.
-
무분별하게 사용하면 DOM이 의미 없는 데이터 속성으로 지저분해지고, 마크업의 가독성이 떨어질 수 있다.