Va.Link — 하이퍼링크 컴포넌트
브라우저 표준 <a> 태그를 감싸는 얇은 래퍼입니다. 프레임워크의 이벤트 시스템·CSS 테마·상태 관리에 편입시킨 것 외에는 표준 HTML 링크와 거의 동일하게 동작합니다.
- 클래스: Va.Link — va_component.js:11446
- short name: link
- 상속: Va.Component
- DOM 태그: <a> (앵커)
- isContainer: false
- 베이스 CSS: va-link

1. 기본 사용
{
tagName: 'link',
innerHTML: 'Microsoft',
href: 'http://www.microsoft.co.kr',
target: '_new'
}
렌더 결과:
Microsoft
href 없이 단순 라벨로 쓸 수도 있고(그럴 땐 onClick으로 프로그램적 이동), 표준 링크처럼 쓸 수도 있습니다.
2. 다른 버튼/텍스트 컴포넌트와의 차이
항목Va.ButtonVa.LinkVa.Span
| DOM 태그 | <button> | <a> | <span> |
| 시맨틱 | 액션 트리거 | 네비게이션 | 텍스트 |
| href / target | ✕ | ✓ | ✕ |
| 브라우저 히스토리 진입 | ✕ | ✓ (표준) | ✕ |
| 우클릭 "새 탭에서 열기" | ✕ | ✓ | ✕ |
| SEO 크롤러 인식 | ✕ | ✓ | ✕ |
| 시각 스타일 | 버튼 look | 밑줄 텍스트 look | 인라인 텍스트 |
| 상태 (pressed/selected) | ✓ | 없음 (disabled만) | 없음 |
한 줄 요약: "액션 트리거가 아니라 이동을 뜻할 때" 쓰는 컴포넌트. HTML 시맨틱 규칙과 접근성을 지키기 위해 Button 대신 Link를 선택하는 상황에 맞습니다.
3. 속성
속성타입설명
| text | string | 순수 텍스트 (선언은 안 되어 있지만 update()가 처리함) |
| innerHTML | string | HTML 포함 라벨. Va._sanitize 적용 |
| href | string | 링크 URL |
| target | string | _blank, _self, _new, 프레임 이름 등 |
| size | string | small / medium / large (CSS 클래스로 반영) |
| disabled | boolean | 비활성화 (클래스로 반영, 실제 <a>의 href 무효화는 CSS pointer-events 등으로 처리 필요) |
⚠️ text는 properties 배열에 선언이 빠져 있지만 update() 로직에는 있습니다. innerHTML을 우선 쓰는 게 정석. Demo도 전부 innerHTML을 사용.
⚠️ 흔히 기대하는 download, rel(nofollow/noopener) 같은 앵커 속성은 옵션으로 노출되어 있지 않습니다. 필요하면 생성 후 component.element.setAttribute('rel', 'noopener')로 직접 세팅.
4. 이벤트
이벤트시그니처발생 시점
| click | (component, element, evt) | 클릭 |
| contextmenu | (component, element, evt) | 우클릭 (기본 컨텍스트 메뉴 유지) |
| focus | (component, element, evt) | 포커스 진입 + selected 클래스 자동 부여 |
| blur | (component, element, evt) | 포커스 이탈 + selected 클래스 자동 제거 |
주목: focus/blur 시 selected 클래스를 자동 토글해 시각 상태를 표현합니다 (va_component.js:11469-11476).
⚠️ click 이벤트에서 evt.preventDefault()가 자동 호출되지 않습니다 — 즉, href가 있으면 콜백 실행 후 브라우저 기본 이동이 그대로 일어남. SPA 라우팅 등으로 이동을 가로채고 싶다면 콜백에서 명시적으로 evt.preventDefault() 호출:
onLinkClick(component, element, evt) {
evt.preventDefault();
Va.setRouterUrl('main', '/some/route');
}
5. 메서드
메서드설명
| setInnerHTML(html) | HTML 라벨 변경 (내부에서 Va._sanitize 적용) |
| setDisabled(bool) | 비활성화 토글 |
주의: 다른 버튼 컴포넌트에 흔한 setText, setHref, setTarget, setSize, focus, blur 같은 setter/헬퍼가 정의되어 있지 않습니다. 필요하면:
- 값 변경: component.href = 'new-url'; component.update()
- 포커스: component.element.focus()
Demo의 setReadOnly 호출은 실제로 정의된 메서드가 없어 오류가 날 수 있습니다 (Demo의 onReadOnly/onUnReadOnly 참조 → 실제 메서드 부재).
6. 내부 구조
방금 수정한 버그 반영 후 정상 구조:
<a elname="element" class="va-link [size] [selected] [disabled]"
href="..." target="..." tabindex="0">
텍스트 또는 sanitized HTML
</a>
지극히 단순합니다. Button처럼 inner span이나 icon element를 두지 않고, <a> 태그 자체에 텍스트를 직접 넣는 구조.
7. 스타일
base CSS: va-link 클래스 하나만 부여됩니다. 색상·밑줄·hover 효과는 테마 CSS(va-light.css, va-dark.css 등)에서 정의된 .va-link 규칙이 담당합니다.
size 3단계: small / medium / large — 폰트 사이즈만 조정, 다른 버튼들처럼 xsmall/xlarge까지 5단계는 아닙니다.
appearance / shape 없음: 버튼 계열의 appearance(primary/secondary 등), shape(circular/square 등)는 존재하지 않습니다. Link는 시각 배리언트가 훨씬 단순한 컴포넌트.
8. 접근성 (a11y)
- tabIndex="0" 자동 세팅 → 키보드 탭 순회 대상
- 표준 <a> 태그 → 스크린리더가 "link"로 인식, 우클릭 컨텍스트 메뉴 정상 동작
- focus 시 selected 클래스 자동 → CSS로 focus indicator 커스터마이즈 가능
- disabled 클래스만 부여 → 실제 링크 이동을 막으려면 CSS pointer-events: none을 함께 적용하거나, onClick에서 preventDefault 필요
9. 언제 쓰나
Link가 맞을 때
- 다른 페이지·URL·문서로 이동 ("자세히 보기", "이용약관", "회사 홈페이지")
- 페이지 내 앵커 이동 (href: '#section-2')
- 새 탭에서 열기 (target: '_new' 또는 '_blank')
- 이메일/전화 링크 (href: 'mailto:...', href: 'tel:...')
- SEO에 유리한 링크로 노출되어야 하는 경우
Button을 쓸 때
- 액션 실행 (저장/삭제/제출) — 이동이 아니라 상태 변경
- 팝업 열기, 폼 전송 등 페이지에 머무는 동작
- 시각적으로 버튼처럼 강조되어야 하는 CTA (Call-to-Action)
혼용 위험: "링크처럼 보이지만 실제로는 액션"인 UI를 자주 보게 되는데, 시맨틱상 이는 잘못된 사용입니다. 액션이면 Button, 이동이면 Link.
'컴포넌트 > 버튼' 카테고리의 다른 글
| FileButton (파일버튼) (0) | 2026.09.09 |
|---|---|
| TabButton (탭버튼) (0) | 2026.09.09 |
| ToggleButton (토글버튼) (0) | 2026.09.09 |
| SplitButton (분할버튼) (0) | 2026.09.09 |
| ResponsiveMenuButton (응답형메뉴버튼) (0) | 2026.09.09 |