본문 바로가기
개발자도구

data-* 속성

by 로맨틱스터디 2025. 12. 24.
728x90
반응형

data-* 속성은 **HTML 표준에서 정식으로 제공하는 “사용자 정의 데이터 저장 공간”**이에요.
한 줄로 요약하면 👉 HTML 요소에 JS용 데이터를 몰래(?) 붙여두는 방법입니다.


✅ data-* 속성이란?

 
<div data-id="123" data-user-name="sukiyam" data-role="admin"></div>
  • data-로 시작하는 모든 속성은 유효한 HTML
  • 브라우저는 의미 해석 안 함
  • JavaScript가 읽어서 사용하는 용도

👉 HTML ↔ JavaScript 사이의 데이터 전달 통로


🧠 왜 필요할까?

❌ 나쁜 옛날 방식

<div
 class="admin active"
 id="user123">
</div>
  • 의미 없는 id/class 남발
  • 스타일용로직용이 섞임

✅ data-* 사용

<div
  class="user"                 // 스타일 데이터
  data-user-id="123"       // 로직용 데이터
  data-role="admin">
</div>
  • 스타일은 class
  • 로직 데이터는 data-*
  • 역할 분리 👍

📌 JavaScript에서 어떻게 쓰나?

1️⃣ dataset으로 접근 (가장 많이 씀)

<button
  data-user-id="10"
  data-is-admin="true">
    버튼
</button>
const btn = document.querySelector("button");

btn.dataset.userId // "10"
btn.dataset.isAdmin // "true"

 

📌 규칙

  • data-user-id → dataset.userId
  • data-is-admin → dataset.isAdmin
  • 항상 문자열로 들어옴
728x90

Q. data-user-id -> dataset.uesrId 로 접근

더보기

이건 HTML 규칙 + JavaScript 문법 + 브라우저 자동 변환 규칙이 겹쳐서 생기는 차이입니다.


❓ 왜 btn.dataset.userId만 되고, btn.dataset.user-id 는 안 될까?

🔴 btn.dataset.user-id ❌

JS 문법상 이렇게 해석됩니다:

btn.dataset.user - id

👉 - 는 하이픈이 아니라 뺄셈 연산자
그래서 문법 에러 또는 엉뚱한 계산이 됨


🔴 btn.dataset."user-id" ❌

btn.dataset."user-id"

👉 JS에서는 속성 이름에 문자열 직접 접근 불가

문자열로 접근하려면 대괄호 표기법을 써야 함

 

btn.dataset["user-id"] // ❌ 이것도 안 됨

왜냐하면 dataset 안에는 "user-id"라는 키가 존재하지 않기 때문


🔄 그럼 왜 userId로 접근되는데 같은 거야?

🔹 HTML

<button data-user-id="10">

HTML 속성 이름 규칙:

  • 케밥 케이스 (kebab-case) 사용
  • data-user-id ← 이게 표준

🔹 JavaScript (dataset)

브라우저가 자동 변환함:

data-user-id → dataset.userId

📌 변환 규칙 (중요)

  1. data- 제거
  2. - 뒤 문자를 대문자로 변환
  3. 하이픈(-) 제거
user-id → userId
user-name → userName
long-user-id-value → longUserIdValue

👉 그래서 camelCase가 됨


🧠 그럼 user-id 같은 표기법 이름은 뭐라고 불러?

정확한 용어는 👇

✅ kebab-case (케밥 케이스)

user-id
data-user-name
long-user-id-value
  • HTML 속성 이름 표준
  • CSS 클래스 이름
  • URL 경로

🔄 다른 케이스들 정리

표기법 예시
camelCase userId
PascalCase UserId
kebab-case user-id
snake_case user_id
SCREAMING_SNAKE USER_ID

❗ 그럼 접근할 수 있는 방법은 오직 하나?

✅ 표준 & 권장

btn.dataset.userId

⚠️ 예외적으로 가능한 방법

btn.getAttribute("data-user-id") // "10"

 

하지만

  • 자동 변환 ❌
  • 읽기 전용 느낌
  • dataset 조작과 섞어 쓰기 불편

🧩 왜 이런 귀찮은 규칙을 만들었을까?

이유 3가지

  1. HTML은 kebab-case가 읽기 쉬움
  2. JS 객체는 camelCase가 표준
  3. 하이픈은 JS 식별자에 ❌

👉 그래서 브라우저가 중간에서 번역기 역할을 함


한 줄 요약

  • data-user-id → kebab-case
  • dataset.userId → camelCase
  • 브라우저가 자동 매핑
  • dataset.user-id는 JS 문법상 불가능

이거 이해했으면
👉 data-user-id="true"가 왜 boolean이 아닌지
👉 dataset과 aria-* 차이
👉 React에서 data-*가 그대로 안 쓰이는 이유

이런 것도 바로 이어서 이해될 거예요 😄


2️⃣ getAttribute 방식

btn.getAttribute("data-user-id"); // "10"

 

Q. getAttribute("")

더보기

getAttribute()는 DOM 요소에 붙어 있는 “HTML 속성(attribute)” 값을 그대로 꺼내오는 함수예요.


🔹 getAttribute() 한 줄 정의

HTML에 실제로 적혀 있는 속성 값문자열로 가져오는 함수


📌 기본 형태

element.getAttribute("속성이름")

예시

<button data-user-id="10" disabled></button>
 
const btn = document.querySelector("button");

btn.getAttribute("data-user-id"); // "10"
btn.getAttribute("disabled"); // "" (있으면 빈 문자열)
btn.getAttribute("class"); // null (없으면 null)

🧠 attribute vs property (핵심 차이)

이게 제일 중요해요.

1️⃣ attribute (HTML에 적힌 것)

<input type="checkbox" checked>
checkbox.getAttribute("type"); // "checkbox"
checkbox.getAttribute("checked"); // "" (존재 여부만)

2️⃣ property (JS 객체 상태)

checkbox.checked; // true
 

📌 getAttribute는 항상 attribute만 봄
📌 .checked, .value, .id 이런 건 property


🔄 dataset이랑 비교하면?

<div data-count="5"></div>

getAttribute

div.getAttribute("data-count"); // "5"
 

dataset

div.dataset.count; // "5"

차이 요약

항목getAttributedataset
접근 대상 HTML 속성 JS 변환 객체
케이스 그대로 camelCase
타입 항상 문자열 항상 문자열
존재 안 하면 null undefined
값 변경 setAttribute dataset.xxx =

🔧 setAttribute도 같이 알아두자

btn.setAttribute("data-user-id", "20");
btn.removeAttribute("disabled");

📌 존재만 중요하면 값은 보통 ""로


⚠️ 언제 getAttribute를 쓰는 게 좋을까?

✅ 써야 하는 경우

  • 원본 HTML 값이 필요한 경우
  • 속성 이름이 JS 식별자로 부적합할 때
    el.getAttribute("aria-label")
  • 속성 존재 여부만 확인할 때
    el.hasAttribute("disabled")

❌ 피하는 게 좋은 경우

input.getAttribute("value") // ❌
input.value // ⭕

이유: value는 사용자 입력에 따라 property가 변함


🧩 왜 이렇게 헷갈리게 만들어졌냐면…

  • HTML: 문서 포맷
  • DOM: JS 객체
  • 둘이 1:1이 아님

👉 그래서
**“보여지는 상태” vs “HTML 원본”**이 분리됨


한 줄 요약

  • getAttribute() = HTML에 적힌 속성 그대로 읽기
  • DOM property랑 다름
  • dataset은 getAttribute의 JS 친화 버전

이해됐으면 다음 단계로
👉 getAttribute()와 .value 차이
👉 boolean attribute (checked, disabled) 왜 값이 없는지
👉 removeAttribute vs false 차이

이것들도 자연스럽게 이어져요 😄


🔄 값 변경도 가능

btn.dataset.userId = "20";

→ HTML에 즉시 반영됨

<button data-user-id="20"></button>

⚠️ 주의사항 (중요)

❗ 1. 보안용 ❌

<div data-password="1234"></div> ❌
  • 개발자도구에서 누구나 볼 수 있음
  • 인증, 권한, 토큰 저장용 ❌

❗ 2. 데이터 타입 없음

 
btn.dataset.count // "5"
  • 숫자 ❌ 문자열
  • 필요하면 변환
Number(btn.dataset.count)

❗ 3. 너무 큰 데이터 ❌

  • JSON 덩어리, 텍스트 ❌
  • DOM 비대해짐 → 성능 저하

💡 언제 쓰는 게 좋을까?

👍 적합한 경우

  • element에 연결된 ID
  • 상태값 (data-state="open")
  • 서버에서 내려준 초기 값
  • 클릭 시 필요한 파라미터
<li data-post-id="345" data-category="news"></li>

👎 안 좋은 경우

  • 민감 정보
  • 대용량 데이터
  • 자주 변경되는 상태 (→ JS 변수/상태관리)

🤔 class랑 뭐가 달라?

구분 class data-*
목적 스타일/선택자 데이터 저장
의미 CSS 중심 JS 중심
여러 개 가능 가능
접근 classList dataset

👉 class는 디자인, *data-는 데이터


한 줄 정리

  • data-* = HTML 요소에 붙이는 JS용 데이터
  • 브라우저는 무시, 개발자는 적극 활용
  • 보안·대용량·타입은 조심

원하면
👉 실무 예제 (이벤트 처리 / 서버 데이터 바인딩)
👉 React·Vue에서 data-* 쓰는 경우
👉 복사 방지 사이트에서 data-*로 숨겨둔 텍스트 분석

이런 것도 이어서 설명해줄게요.

728x90
반응형