컴포넌트/버튼

Link (링크)

VanillaFront 2026. 9. 9. 17:11

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.