Link#
내부 라우팅 또는 외부 URL로 이동하는 링크 텍스트 컴포넌트입니다. 다양한 시각적 변형과 외부 링크 아이콘을 지원합니다.
Live Preview#
Link(
href: '#',
child: Text('Click here'),
)
Link(
href: '#',
child: Text('Click here'),
)
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 본문 텍스트 중간에 인라인 링크가 필요할 때
- 외부 사이트로 이동하는 링크를 명시적으로 표시할 때 (새 창 아이콘)
- 이용약관, 개인정보처리방침 같은 보조 링크가 필요할 때
대신 다른 컴포넌트를 사용하세요:
Button: 사용자 액션을 유발하는 클릭 가능한 요소에 (탐색이 아닌 경우)Breadcrumb: 계층적 페이지 탐색 경로를 표시할 때
기본 사용법 (Basic Usage)#
// 기본 링크 (내부 이동)
Link(
onTap: handleNavigateToProfile,
child: Text('프로필 보기'),
)
// 외부 URL 링크
Link(
href: 'https://coui.cocode.im',
isExternal: true,
child: Text('CoUI 문서'),
)
// Underline 변형
Link(
onTap: handleNavigateToSettings,
variant: LinkVariant.underline,
child: Text('설정'),
)
// Muted 변형
Link(
href: 'https://example.com/terms',
isExternal: false,
variant: LinkVariant.muted,
child: Text('이용약관'),
)
// 기본 내부 링크
Link(
href: '/profile',
child: text('프로필 보기'),
)
// 외부 링크 (새 탭, external 파라미터 사용)
Link(
href: 'https://coui.cocode.im',
external: true,
child: text('CoUI 문서'),
)
// Underline 항상 표시 (underline: true가 기본값)
Link(
href: '/settings',
underline: true,
child: text('설정'),
)
// Underline 숨김 (Muted 스타일)
Link(
href: '/terms',
underline: false,
child: text('이용약관'),
)
Props / Parameters#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
child | Widget | 필수 | 링크로 표시할 위젯 |
href |
String? |
null |
이동할 URL (외부/내부) |
onTap |
VoidCallback? |
null |
탭 핸들러 (href 대신 사용) |
variant |
LinkVariant |
default |
스타일 변형 |
isExternal |
bool |
false |
외부 링크 여부. true이면 새 창으로 열기 및 아이콘 표시 |
변형 (Variants)#
Default#
기본 링크 색상을 사용합니다. 호버 시 언더라인이 나타납니다.
Link(
onTap: handleNavigate,
variant: LinkVariant.defaultVariant,
child: Text('기본 링크'),
)
Underline#
항상 언더라인이 표시됩니다. 본문 내 링크에 적합합니다.
Link(
onTap: handleNavigate,
variant: LinkVariant.underline,
child: Text('밑줄 링크'),
)
Muted#
더 낮은 대비의 색상으로 표시됩니다. 부가 정보 링크에 적합합니다.
Link(
href: 'https://example.com/privacy',
isExternal: false,
variant: LinkVariant.muted,
child: Text('개인정보처리방침'),
)
외부 링크 (isExternal)#
외부 링크 아이콘을 자동으로 표시하고 새 창에서 열립니다.
Link(
href: 'https://flutter.dev',
isExternal: true,
child: Text('Flutter 공식 사이트'),
)
동작 스펙 (Behavior)#
인터랙션#
- 클릭/탭:
onTap호출 또는hrefURL로 이동 - 호버: default 변형에서 언더라인 표시; 커서 포인터로 변경
- 외부 링크:
isExternal: true시 새 탭/창에서 열림, 우측에 외부 링크 아이콘 자동 추가
상태 전환#
default→hover: 언더라인 표시 (200ms)default→visited: 방문 후 색상 변경 (Web 전용)
애니메이션#
- 호버 언더라인: 200ms ease-in-out
사용 가이드라인 (Usage Guidelines)#
✅ Do#
본문 내 링크에는 underline variant로 가시성 확보
Text.rich(
TextSpan(
text: '자세한 내용은 ',
children: [
WidgetSpan(
child: CouiLink(
onTap: handleNavigateToHelp,
variant: LinkVariant.underline,
child: const Text('도움말'),
),
),
const TextSpan(text: '를 참조하세요.'),
],
),
)
본문 텍스트 중 링크를 언더라인으로 구분해야 사용자가 클릭 가능한 텍스트를 인식한다.
❌ Don't#
링크처럼 보이는 일반 텍스트를 클릭 불가로 표시하지 않기
// ❌ 파란색인데 클릭 안 됨
Text('프로필 보기', style: TextStyle(color: Colors.blue))
링크처럼 보이는 텍스트가 클릭되지 않으면 사용자 신뢰를 잃는다. 파란색 텍스트는 반드시 클릭 가능해야 한다.
✅ Do#
외부 링크에는 isExternal: true로 명시적 안내
CouiLink(
href: 'https://external-site.com',
isExternal: true, // 새 창 아이콘 자동 표시
child: const Text('외부 리소스'),
)
외부 링크 아이콘이 사용자에게 새 탭이 열릴 것임을 미리 알려 혼란을 방지한다.
❌ Don't#
링크 텍스트로 "여기", "클릭" 같은 모호한 표현 사용
// ❌ 맥락 없는 링크 텍스트
CouiLink(
onTap: handleNavigate,
child: const Text('여기를 클릭하세요'),
)
스크린 리더 사용자는 링크 텍스트만 읽어 탐색하므로 "여기"는 의미가 없다. 목적지를 명확히 서술한다.
✅ Do#
링크 텍스트는 목적지를 설명하는 내용으로 작성하세요.
// ✅ 명확한 링크 텍스트
CouiLink(
href: '/docs/getting-started',
child: Text('시작 가이드 보기'),
)
링크 텍스트가 목적지를 설명하면 사용자와 스크린 리더가 클릭 전에 무엇으로 이동하는지 파악할 수 있습니다.
❌ Don't#
'여기', '클릭' 같은 모호한 링크 텍스트를 사용하지 마세요.
// ❌ 모호한 링크 텍스트
CouiLink(href: '/docs', child: Text('여기'))
CouiLink(href: '/contact', child: Text('클릭하세요'))
스크린 리더는 링크 텍스트만 읽어줍니다. '여기', '클릭'은 어디로 이동하는지 알 수 없어 접근성을 심각하게 해칩니다.
접근성 (Accessibility)#
키보드 인터랙션#
| 키 | 동작 |
|---|---|
Tab | 링크로 포커스 이동 |
Enter | 링크 활성화 |
스크린 리더#
- Flutter:
Semantics(link: true, label: linkText)자동 적용 -
Web:
<a>태그로 렌더링;href있으면 자동 링크 역할;isExternal이면rel="noopener noreferrer"+target="_blank"자동
터치 타겟#
- 인라인 링크의 경우 부모 컨테이너 크기에 따름
- 독립 링크는 최소 44x44dp 터치 영역 확보 권장
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | CouiLink | Link |
| 내부 라우팅 | onTap + Navigator | href 속성 (SPA 라우터 처리) |
| 외부 링크 | url_launcher 패키지 | target="_blank" |
| 방문 색상 | 지원 안 함 | CSS :visited |
관련 컴포넌트 (Related Components)#
- Button: 탐색이 아닌 액션 실행에 사용
- Text: 링크가 없는 일반 텍스트에 사용
- Breadcrumb: 계층적 페이지 탐색 경로 표시에 사용
조합 예제#
// 로그인 폼 하단 링크들
Column(
children: [
// ... 폼 필드들
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CouiLink(
onTap: handleForgotPassword,
variant: LinkVariant.muted,
child: const Text('비밀번호를 잊으셨나요?'),
),
CouiLink(
onTap: handleSignUp,
variant: LinkVariant.underline,
child: const Text('회원가입'),
),
],
),
const Gap.md(),
CouiButton(
onPressed: handleLogin,
child: const Text('로그인'),
),
const Gap.sm(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('계속 진행하면 '),
CouiLink(
href: '/terms',
variant: LinkVariant.muted,
child: const Text('이용약관'),
),
const Text('에 동의하는 것입니다.'),
],
),
],
)