컴포넌트/아바타, 페르소나
Persona (페르소나)
VanillaFront
2026. 9. 20. 16:25
Va.Persona — 아바타 + 이름·역할 조합 컴포넌트
Va.Avatar를 감싸 이름(title)과 부가 설명(detail)을 함께 표시하는 조합 컴포넌트입니다. "사용자 사진 + 이름 + 직책" 처럼 사람 정보를 한 단위로 표현하는 데 최적화되어 있으며, 텍스트 위치를 자유롭게 배치할 수 있습니다.

클래스 정보
Va.Persona extends Va.Component
tagName: 'persona' (실제 렌더링은 <div>)
isContainer: true
파일: va_avatar.js
기본 사용법
{
tagName: 'persona',
title: '홍길동',
detail: '개발팀장',
textPosition: 'right',
avatar: {
image: user.photoUrl,
size: 'medium'
}
}
또는 코드로:
let persona = new Va.Persona({
title: '홍길동',
detail: 'hong@example.com',
avatar: { initial: 'HG', backgroundColor: '#4A90E2', color: 'white' }
});
parent.append(persona);
왜 별도 컴포넌트인가
Avatar + Title + SubTitle을 매번 조합해 만들 수도 있지만, Va.Persona는:
- 표준 사람 표현 단위 — "누구" 를 한 컴포넌트로 명확히 표현
- 위치 배치 자동 — textPosition 하나로 top/bottom/left/right 자유 전환
- Avatar 이벤트 프록시 — 아바타·뱃지 클릭 이벤트를 상위에서 통일 처리
- 활성 상태 연동 — Persona의 actived가 내부 Avatar에 자동 반영
속성
속성타입기본값설명
| title | String | '' | 주 텍스트 (이름/직책) |
| detail | String | '' | 부가 텍스트 (설명/역할) |
| textPosition | String | 'right' | 텍스트 위치: 'top', 'bottom', 'left', 'right' |
| avatar | Object | — | 내부 Va.Avatar에 전달할 옵션 |
| size | String | 'medium' | 크기 (아바타에 자동 전파) |
| actived | Boolean | false | 활성 상태 (아바타에 반영) |
| disabled | Boolean | false | 비활성 상태 |
| stopPropagation | Boolean | true | 이벤트 전파 차단 |
textPosition별 레이아웃
값배치
| 'right' (기본) | [👤] 홍길동 개발팀장 — 아바타 왼쪽 |
| 'left' | 홍길동 개발팀장 [👤] — 아바타 오른쪽 |
| 'top' | 홍길동<br>개발팀장<br>[👤] — 아바타 아래 |
| 'bottom' | [👤]<br>홍길동<br>개발팀장 — 아바타 위 (프로필 카드 스타일) |
이벤트
이벤트발생 시점콜백 인자
| click | Persona 전체 클릭 | (sender, element, evt) |
| contextmenu | 우클릭 | (sender, element, evt) |
| avatarClick | 내부 아바타만 클릭 | (sender, element, evt) |
| avatarContextmenu | 내부 아바타 우클릭 | (sender, element, evt) |
| badgeClick | 아바타 뱃지 클릭 | (sender, element, evt) |
| badgeContextmenu | 뱃지 우클릭 | (sender, element, evt) |
주목: click(전체)과 avatarClick(아바타만)이 별도로 dispatch되므로, "아바타 클릭 = 프로필 이동, 전체 클릭 = 상세 열기" 같은 분기 가능.
메서드
- setTitle(title) — 주 텍스트 변경
- setDetail(detail) — 부가 텍스트 변경
- setAvatar(avatar) — 아바타 컴포넌트 교체
- hideAvatar() / showAvatar() — 아바타 표시/숨김
- active() / inactive() — 활성 상태 제어
- focus() / blur() — 포커스 (내부 아바타에 위임)
내부 구조
<div class="va-persona medium right">
<div class="persona-inner" elname="inner">
<span class="va-avatar circular">...</span> <!-- 내부 Avatar -->
<div class="content" elname="content">
<div class="title">홍길동</div>
<div class="detail">개발팀장</div>
</div>
</div>
</div>
textPosition에 따라 avatar와 content의 순서가 재배열됩니다.
사용 시점 — 언제 쓰나
- 사용자 리스트 — 팀원 목록, 회원 목록
- 댓글/메시지 헤더 — 작성자 정보
- 드롭다운 메뉴 헤더 — 로그인 사용자 표시
- 협업 툴 참여자 — 프로젝트 멤버 카드
- 프로필 카드 — 명함 스타일 UI
사용하지 말아야 할 때
- 아바타만 필요 → Va.Avatar 단독
- 여러 명 콤팩트 표시 → Va.AvatarGroup
- 정형 사용자 테이블 → Va.Grid
- 텍스트 없는 순수 이미지 → Va.Image
자주 쓰는 조합 예시
사용자 리스트 (오른쪽 텍스트)
{
tagName: 'section',
layout: 'ds-flex fd-column gap-s',
tags: users.map(user => ({
tagName: 'persona',
title: user.name,
detail: user.email,
textPosition: 'right',
size: 'medium',
avatar: {
image: user.photo,
initial: user.initial
},
onClick: 'onClickUser'
}))
}
프로필 카드 (아바타 위, 텍스트 아래)
{
tagName: 'div',
layout: 'ds-flex fd-row fw-wrap gap-m',
tags: team.map(member => ({
tagName: 'persona',
title: member.name,
detail: member.role,
textPosition: 'bottom',
size: 'large',
avatar: {
image: member.photo,
shape: 'circular'
},
style: {
padding: '15px',
border: '1px solid var(--colorNeutralStroke)',
borderRadius: 'var(--sizeRadiusM)',
width: '180px',
textAlign: 'center'
}
}))
}
드롭다운 메뉴 헤더 (로그인 사용자)
{
tagName: 'menu',
tags: [{
tagName: 'persona',
title: currentUser.name,
detail: currentUser.email,
textPosition: 'right',
avatar: { image: currentUser.photo },
style: { padding: '10px', borderBottom: '1px solid var(--colorNeutralStroke)' }
},{
tagName: 'menuItem', text: '내 프로필'
},{
tagName: 'menuItem', text: '설정'
},{
tagName: 'menuItem', text: '로그아웃'
}]
}
Avatar와 전체 각각 다른 액션
{
tagName: 'persona',
title: '홍길동',
detail: '개발팀',
avatar: { image: user.photo },
onClick: 'onClickPersona', // 전체 클릭 = 상세 열기
onAvatarClick: 'onClickAvatar' // 아바타만 클릭 = 프로필로 이동
}
// View 안:
onClickPersona(sender){
this.openUserDetail(sender.title);
}
onClickAvatar(sender){
this.navigateToProfile(sender.title);
}
활성 상태 표시 (온라인 등)
{
tagName: 'persona',
title: user.name,
detail: user.isOnline ? '온라인' : '오프라인',
actived: user.isOnline,
avatar: { image: user.photo }
}
뱃지 알림 카운트
{
tagName: 'persona',
title: user.name,
detail: '메시지 3건',
avatar: {
image: user.photo,
badgeVisible: true,
badge: { text: '3', appearance: 'danger' }
},
onBadgeClick: 'onClickMessages'
}
실전 예시 — 팀 대시보드
config(){
return {
tagName: 'page',
tags: [{
tagName: 'panel',
tags: [{
tagName: 'title',
innerHTML: '개발팀 (전체 12명)'
},{
tagName: 'div',
layout: 'ds-flex fd-row fw-wrap gap-m',
style: { marginTop: '20px' },
tags: this.team.map(member => ({
tagName: 'persona',
title: member.name,
detail: `${member.role} · ${member.status}`,
textPosition: 'bottom',
size: 'large',
actived: member.isOnline,
avatar: {
image: member.photo,
initial: member.initial,
backgroundColor: member.color,
color: 'white'
},
style: {
padding: '20px',
width: '180px',
textAlign: 'center',
border: '1px solid var(--colorNeutralStroke)',
borderRadius: 'var(--sizeRadiusM)',
cursor: 'pointer'
},
onClick: 'onClickMember',
onAvatarClick: 'onClickMemberAvatar'
}))
}]
}]
};
}
주의사항
- avatar 옵션은 객체로 전달 — 내부에서 Va.Avatar를 생성. 이미 만든 Avatar 인스턴스를 넣는 게 아님
- setAvatar() 메서드 두 개 정의됨 — 소스에 오버라이드된 두 버전이 있음 (va_avatar.js:647, va_avatar.js:657). 뒤의 것이 실제 실행됨. 새 Avatar 인스턴스 세팅용
- size 자동 전파 — Persona의 size가 내부 아바타에 자동 반영. 아바타 개별 size 지정 시엔 그 값 우선
- 텍스트만 필요하면 Persona 부적합 — 아바타 없이는 의미가 없으므로 Va.Div + Va.Title/Va.SubTitle 조합 사용
- stopPropagation 기본 true — 리스트 아이템으로 사용 시 부모 클릭도 필요하면 stopPropagation: false
- 이벤트 분리 활용 — click(전체)과 avatarClick(아바타만) 분리 가능. UX 상 유용
- actived는 아바타에만 반영 — Persona 자체의 시각적 활성 표시는 별도로 style에서 처리 필요
- detail 여러 줄 — 자동 줄바꿈 안 됨. 필요 시 \n 대신 style로 whiteSpace: 'pre-line' 등 처리
대안 비교
상황추천
| 아바타 + 이름·역할 표시 | Va.Persona |
| 아바타 단독 | Va.Avatar |
| 여러 사용자 콤팩트 | Va.AvatarGroup |
| 정형 사용자 테이블 | Va.Grid |
| 이름만 필요 | Va.Label |
| 카드 스타일 자유 구성 | Va.Div + Avatar + Title 조합 |
참고
- API 문서 페이지: https://vanillafront.com/docs.html?theme=light#main#apipersona
- 연관: Va.Avatar(내부 조합), Va.AvatarGroup(다수 사용자 대안)