
안녕하세요! 오늘은 <input> 태그와 <label> 태그를 함께 써야 하는 이유를 알리는 글을 작성해 보겠습니다!
with. React.useId Hook
✅ <input>과 <label>
<input> 태그는 < label >을 필수로 제공하는 것이 좋습니다!
물론 제공하지 않아도 오류가 발생하거나 하지는 않지만 권장한다는 말 이죠!
그 이유는 이제부터 살펴보도록 하겠습니다.
🔸<input> 태그
<input> 태그는 라디오, 체크박스, 버튼 등 다양합니다. (참고)
<input>: The HTML Input element - HTML: HyperText Markup Language | MDN
The <input> HTML element is used to create interactive controls for web-based forms in order to accept data from the user; a wide variety of types of input data and control widgets are available, depending on the device and user agent. The <input> element
developer.mozilla.org
'input'이라는 단어 뜻 그대로 사용자가 값을 입력하는 UI에 쓰이는 태그이죠.
🔸<label> 태그
< label > 태그는 UI의 설명을 제공해 주는 태그입니다.
이런 식으로 말이죠!
위 예시와 같이 해당 체크박스가 어떤 체크박스인지를 설명해 주는 이러한 용도로 사용하곤 합니다.
(물론 체크박스에만 사용하는 것은 아닙니다!)
그럼 이 두 개의 태그는 어떤 상관관계를 갖길래 함께 써주라고 하는 걸까요?
이유 1. 사용성
첫 번째 이유는 < label >의 텍스트 영역을 클릭하면 <input> 요소가 선택되기 때문에 사용성이 증가하기 때문인데요!
말 보다 아래 예시를 보시면 이해가 쉬우실 것입니다!
See the Pen Untitled by Simo (@vfinsjgz-the-scripter) on CodePen.
label이 없는 체크박스는 '체크박스' 칸 그 자체를 정확히 눌러야 선택이 됩니다.
하지만 label이 있는 체크박스는 해당 label의 텍스트 영역을 눌러도 체크박스가 잘 선택되기 때문에 사용자의 사용성이 좋아진다고 할 수 있는 것 이죠!
이유 2. 접근성
스크린 리더가 연관된 <input>에 초점이 이동하면 label을 읽어주기 때문에 접근성이 준수됩니다!
화면 리더기는 체크박스와 label을 연결하여 "이용약관에 동의합니다, 체크박스"이런 식으로 읽어주기 때문에 어떤 사항에 대한 체크박스인지 좀 더 명확하게 알 수 있겠죠?
✅ <lable> 설정법
label을 설정하는 방법은 암시적 방법, 명시적 방법 두 가지가 있습니다.
아래에서 함께 살펴보죠ㅎㅎ
<암시적 방법>
<label>
이름
<input type="text" id="name"/>
</label>
암시적 방법은 JUST! 이런 식으로 <label>의 하위에 <input>이 위치하면 됩니다.
<명시적 방법>
<label htmlFor="email-input">이메일</label>
<input type="email" id="email-input" name="email" placeholder="user@dev.io" />
명시적 방법은 label과 input을 같은 값의 id와 htmlFor로 연결시켜줘야 하는데요!
html기준, input에 label을 연결하려면 id속성과 for속성이 필요한데 jsx 즉, 리액트에서는 id 속성과 htmlFor을 사용합니다.
위 코드와 같이 label과 input의 id와 htmlFor이 일치해야 두 태그가 연결되어 동작할 수 있는 것 이죠!
<label 설정 시 주의점>
고유한 ID 설정
input에 설정된 id 속성은 문서 내에서 고유해야 합니다!!
근데 id가 많아지면 고유하게 id를 관리하기 어려워지게 되는데? -> 이땐 충돌을 피하기 위해서 React.useId() 훅을 사용할 수도 있습니다.
‘내가 작성하는 컴포넌트에 얼마나 많은 id가 있길래 그걸 관리하기 어렵겠어?’라고 생각할 수 있지만 그게 아니라 이 관점은 컴포넌트를 재 사용할 때를 고려한 것입니다.
아래 코드를 보며 더 설명드리겠습니다.
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
return (
<>
<label>
Password:
<input
type="password"
aria-describedby={passwordHintId}
/>
</label>
<p id={passwordHintId}>
The password should contain at least 18 characters
</p>
</>
);
}
예를 들어 이렇게 id 속성이 있는 컴포넌트를 제작하였는데
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
return (
<>
<label>
Password:
<input
type="password"
aria-describedby={passwordHintId}
/>
</label>
<p id={passwordHintId}>
The password should contain at least 18 characters
</p>
</>
);
}
export default function App() {
return (
<>
<h2>Choose password</h2>
<PasswordField />
<h2>Confirm password</h2>
<PasswordField />
</>
);
}
위 코드와 같이 해당 컴포넌트를 여러 번 실행한다면???
id를 하드 하게 개발자가 정해두었으면 해당 문서에서 id가 중복 되게 되고??? 이건 있을 수 없는 일이죠!!!
당연히 에러도 납니다!
그렇기 때문에 이 id를 고유할 수 있게 관리해 주는 훅 함수인 React.useId()를 이용하여 id를 지정해 주면 컴포넌트가 재사용이 되어도 알아서 id를 고유하게 관리해 준다는 것입니다!
<React.useId() Hook>
React.useId()는 React 18에서 도입된 고유한 ID 생성을 위한 훅입니다. 이 훅은 컴포넌트가 여러 번 렌더링 되거나 재사용되더라도 고유한 ID 값을 보장해 줍니다. 주로 접근성 속성(예: aria-describedby, aria-labelledby)이나 label과 input을 연결할 때 유용하게 사용됩니다!
사용 방법
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
return (
<>
<label htmlFor={`password-${passwordHintId}`}>Password:</label>
<input id={`password-${passwordHintId}`} type="password" />
<p id={passwordHintId}>The password must be at least 18 characters long.</p>
</>
);
}
사용법은 위 코드와 같이 사용하게 되면 passwordHintId는 리액트가 고유한 ID로 설정해주게 됩니다.
✅ 마무리
React에서 <input>과 <label>을 함께 사용하는 것은 사용성과 접근성 모두를 향상시키는 중요한 개발 습관입니다!
그리고 React와 같은 라이브러리에서는 컴포넌트 재사용과 고유 ID 관리가 중요한데, 이때 React.useId() 훅을 사용하면 간편하면서도 확실하게 고유성을 유지할 수 있습니다.
작은 디테일 하나하나가 사용자 경험을 완성합니다. <label>과 useId() 같은 기본기를 잘 활용하는 습관은 누구나 사용할 수 있는 더 나은 웹을 만드는 첫걸음이 될 것입니다.
작지만 중요한 접근성을 고려하며, 함께 더 좋은 코드를 작성해 나갑시다!!
'🖥️개발 > 🐋React' 카테고리의 다른 글
[Zustand] Zustand란? 리액트에서 Zustand를 사용하는 이유 (0) | 2025.02.23 |
---|---|
[React] ref란? (0) | 2025.02.16 |
[React] 리액트의 단방향 데이터 흐름 (One-way Data Flow) (0) | 2025.02.02 |
[React] 엄격 모드(StrictMode)를 사용하는 이유 with 순수 함수 (0) | 2025.01.19 |
React.createElement의 매개변수 (0) | 2025.01.12 |