June 25, 2025
텍스트만 있는 `div`를 버튼으로 사용하기 🚫
HTML
UX
JavaScript
SEO/접근성
Summary
div
를 버튼처럼 사용하면 키보드 접근성, 스크린 리더 지원 등 웹 접근성을 심각하게 저해하며 불필요한 개발 공수를 야기합니다. 대신 시맨틱 button
또는 a
요소를 사용하여 내장된 접근성 이점을 활용하고 코드의 견고함을 높여야 합니다.
Why Wrong?
div
는 왜 버튼이 될 수 없는가?
div
요소는 아무런 시맨틱(의미)도, 내장된 동작(behavior)도 없는 일반적인 컨테이너 요소입니다. 개발자가 div
에 onclick
이벤트 핸들러를 추가하여 시각적으로 버튼처럼 보이게 할 수는 있지만, 이는 여러 심각한 문제를 야기합니다:
- 키보드 접근성 부족:
div
는 기본적으로 탭(Tab) 키로 포커스를 받을 수 없습니다. 스크린 리더 사용자나 마우스 사용이 어려운 사용자는 키보드로 해당 요소를 활성화할 수 없습니다. 비록tabindex="0"
속성을 추가하여 포커스를 가능하게 하더라도, 엔터(Enter) 키나 스페이스(Space) 키로 클릭 이벤트를 발생시키는 동작은 수동으로onKeyDown
이벤트를 통해 구현해야 합니다. 이는 네이티브button
요소가 자동으로 제공하는 기능을 번거롭게 재구현하는 것입니다. - 스크린 리더 의미론 부족: 스크린 리더는
div
를 단순히 일반 텍스트 블록으로 인식하며, '버튼'이라는 역할을 전달하지 않습니다.role="button"
ARIA 속성을 추가하여 의미를 부여할 수 있지만, 이 역시 네이티브button
이 제공하는 견고함과 모든 브라우저/스크린 리더 조합에서의 일관성을 보장하기 어렵습니다. 예를 들어, 네이티브button
은 '눌려짐' 상태(aria-pressed
)나 '비활성화' 상태(disabled
)를 자동으로 관리하지만,div
기반 버튼은 이 모든 것을 수동으로 구현해야 합니다. - 예상치 못한 UX 문제:
div
는button
의:active
나:focus
와 같은 내장된 의사 클래스(pseudo-classes) 동작을 제공하지 않아, 사용자가 요소와 상호작용할 때 시각적인 피드백이 부족할 수 있습니다. 이는 사용자의 혼란을 가중시키고 전반적인 사용자 경험을 저해합니다. - 개발 및 유지보수 비용 증가: 위에서 언급된 모든 접근성 및 기능적 문제를 해결하기 위해
div
에tabindex
,role
, 다양한 키보드 이벤트 핸들러를 수동으로 추가하고 테스트하는 것은 불필요한 개발 시간을 소모하고 코드의 복잡성을 증가시켜 유지보수성을 떨어뜨립니다.
How to Fix?
시맨틱 HTML 요소를 사용하여 웹 접근성 및 견고성 확보
상호작용이 필요한 모든 요소에는 그 목적에 맞는 시맨틱 HTML 요소를 사용해야 합니다. 이는 웹 표준을 준수하고, 브라우저가 제공하는 내장된 접근성 기능을 자동으로 활용하여 모든 사용자가 웹사이트를 동등하게 이용할 수 있도록 합니다.
- 클릭 가능한 동작을 수행하는 경우:
button
요소를 사용하세요.button
은 키보드 내비게이션(탭, 엔터, 스페이스)과 스크린 리더 의미론을 자동으로 제공합니다. 또한disabled
속성을 통해 비활성화 상태를 쉽게 관리할 수 있습니다. - 다른 페이지로 이동하거나 페이지 내 특정 섹션으로 이동하는 경우:
a
(앵커) 요소를 사용하세요.a
태그는href
속성을 통해 링크의 목적지를 명확히 하고, 브라우저의 내비게이션 히스토리와 상호작용하는 기능을 제공합니다.
스타일링 팁: button
이나 a
태그의 기본 스타일이 만족스럽지 않다면, CSS를 사용하여 완전히 새로운 디자인을 적용할 수 있습니다. border: none;
, background: none;
, font: inherit;
, text-decoration: none;
등을 사용하여 기본 스타일을 초기화한 후, 원하는 대로 padding
, background-color
, border-radius
등을 적용하면 됩니다. 중요한 것은 시맨틱 구조를 유지하면서 시각적 표현만 변경하는 것입니다.
Before Code (Bad)
<style>
.my-button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border-radius: 5px;
cursor: pointer;
display: inline-block;
}
</style>
<div class="my-button" onclick="alert('클릭!')">
클릭하세요!
</div>
After Code (Good)
<style>
/* 버튼의 기본 스타일을 초기화하고 .my-button 스타일을 적용 */
.my-button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none; /* button 기본 border 제거 */
border-radius: 5px;
cursor: pointer;
font-family: inherit; /* 폰트 상속 */
font-size: inherit; /* 폰트 사이즈 상속 */
text-align: center;
text-decoration: none; /* a 태그 underline 제거 */
display: inline-block; /* 너비 조절 */
/* 필요에 따라 line-height, text-transform 등 추가 */
}
/* 포커스 시 시각적 표시 제공 (접근성 필수) */
.my-button:focus {
outline: 2px solid #0056b3; /* 기본 outline 대신 명확한 outline */
outline-offset: 2px;
}
/* Hover 및 Active 상태 */
.my-button:hover {
background-color: #0056b3;
}
.my-button:active {
background-color: #003f8e;
}
</style>
<button class="my-button" onclick="alert('클릭!')">
클릭하세요!
</button>
<!-- 또는 링크처럼 동작해야 한다면 -->
<!-- <a href="/dashboard" class="my-button">
대시보드로 이동
</a> -->