콜아웃(Callouts)
콜아웃은 사용자에게 알림을 표시하는 메커니즘입니다. 전역 컨텍스트: 콜아웃은 애플리케이션 어디에서나 사용자에게 표시될 수 있습니다. 그룹 및 프로젝트 컨텍스트: 콜아웃은 특정 사용자에게 표시되며 그룹이나 프로젝트 컨텍스트와 같은 특정 컨텍스트 바인딩을 가질 수 있습니다.
콜아웃은 사용자에게 알림을 표시하는 메커니즘입니다. 사용자는 알림을 해제할 수 있으며, 알림은 미리 정의된 기간 동안 해제된 상태로 유지될 수 있습니다. 알림 해제는 페이지 로드와 다른 사용자 디바이스에서도 지속됩니다.
콜아웃 컨텍스트#
전역 컨텍스트: 콜아웃은 애플리케이션 어디에서나 사용자에게 표시될 수 있습니다. 예를 들어, 2단계 인증 복구 코드를 안전한 곳에 보관하도록 사용자에게 알림을 표시할 수 있습니다. 이 유형의 콜아웃을 해제하면 해당 사용자 전체 GitLab 인스턴스에서 효력이 발생하며, 콜아웃을 어디서 접했든 상관없습니다.
그룹 및 프로젝트 컨텍스트: 콜아웃은 특정 사용자에게 표시되며 그룹이나 프로젝트 컨텍스트와 같은 특정 컨텍스트 바인딩을 가질 수 있습니다. 예를 들어, 그룹 소유자에게 그룹의 사용 가능한 시트가 부족하다는 알림을 표시할 수 있습니다. 해당 콜아웃을 해제하면 특정 그룹에서만 해당 사용자에게만 효력이 발생하며, 해당하는 경우 다른 그룹에서는 동일한 콜아웃이 여전히 표시됩니다.
컨텍스트에 관계없이, 콜아웃 해제는 해당 사용자에게만 효력이 발생합니다. 다른 사용자는 여전히 관련 콜아웃을 볼 수 있습니다.
콜아웃 ID#
콜아웃은 고유 이름을 사용하여 식별하고, 고유 값을 사용하여 해제 데이터를 저장합니다. 예를 들어:
amazing_alert: 42,
여기서 amazing_alert은 콜아웃 ID이고, 42는 데이터베이스에 해제를 등록하는 데 사용되는
고유 번호입니다. 그룹 콜아웃이 저장되는 방식은 다음과 같습니다:
id | user_id | group_id | feature_name | dismissed_at
----+---------+----------+--------------+-------------------------------
0 | 1 | 4 | 42 | 2025-05-21 00:00:00.000000+00
새 콜아웃 ID를 생성하려면, 관련 컨텍스트 유형 레지스트리 파일의 feature_name enum에
고유 이름과 순차 값을 사용하여 새 키를 추가합니다:
- 전역 컨텍스트:
app/models/users/callout.rb. 콜아웃은 사용자가 전역으로 해제합니다. 관련 알림은 해당 사용자에 대해 GitLab 인스턴스 어디에서도 표시되지 않습니다. - 그룹 컨텍스트:
app/models/users/group_callout.rb. 콜아웃은 사용자가 특정 그룹에서 해제합니다. 관련 알림은 다른 그룹에서 사용자에게 여전히 표시됩니다. - 프로젝트 컨텍스트:
app/models/users/project_callout.rb. 사용자가 특정 프로젝트에서 해제한 콜아웃입니다. 관련 알림은 다른 프로젝트에서 사용자에게 여전히 표시됩니다.
위의 enum 파일 중 하나에 새 콜아웃 ID를 추가한 후 다음 명령을 실행하여 GraphQL 문서를 업데이트해야 합니다:
bundle exec rake gitlab:graphql:compile_docs
이전 enum 값을 재사용하지 마세요. 그러면 잘못된 양성 해제가 발생할 수 있습니다. 대신 새로운 순차 번호를 생성하세요.
콜아웃 deprecated 처리#
콜아웃이 더 이상 필요하지 않을 때, 콜아웃 ID enum에서 제거할 수 있습니다. 하지만 DB의 해제 레코드는 enum의 숫자 값을 사용하기 때문에, 이전 해제가 새 콜아웃에 영향을 미치지 않도록 deprecated된 ID의 재사용을 명시적으로 방지해야 합니다. 따라서 콜아웃 ID를 제거하려면:
- enum 해시에서 키/값 쌍을 제거합니다
- deprecated된 ID와 콜아웃을 제거하는 MR을 언급하는 인라인 주석을 남깁니다
예를 들어:
- amazing_alert: 42,
+ # 42 removed in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121920
해제 가능한 알림 컴포넌트#
Haml#
HAML 뷰에서 해제 가능한 알림을 구현할 때는 해제 가능한 알림 컴포넌트를 사용합니다. 이 컴포넌트들은
Pajamas::AlertComponent를 확장하고 강력한 유효성 검사, 간소화된 설정, 해제 로직의 자동 처리를 제공합니다.
사용 가능한 컴포넌트#
Users::DismissibleAlertComponent- 사용자(전역) 컨텍스트 콜아웃용Users::GroupDismissibleAlertComponent- 그룹 컨텍스트 콜아웃용Users::ProjectDismissibleAlertComponent- 프로젝트 컨텍스트 콜아웃용
모든 컴포넌트는 Pajamas::AlertComponent를 상속하며 동일한 인터페이스를 지원하고,
dismiss_options 및 선택적 wrapper_options 매개변수가 추가됩니다.
기본 사용법#
사용자(전역) 콜아웃#
= render Users::DismissibleAlertComponent.new(
title: _('Alert title'),
variant: :warning,
dismiss_options: { user: current_user, feature_id: 'my_user_callout' }
) do |c|
- c.with_body do
= _('Alert message content goes here.')
그룹 콜아웃#
= render Users::GroupDismissibleAlertComponent.new(
title: _('Group-specific alert'),
dismiss_options: { user: current_user, group: @group, feature_id: 'my_group_callout' },
variant: :info
) do |c|
- c.with_body do
= _('This alert is specific to the current group.')
프로젝트 콜아웃#
= render Users::ProjectDismissibleAlertComponent.new(
title: _('Project notification'),
dismiss_options: { user: current_user, project: @project, feature_id: 'my_project_callout' },
variant: :success
) do |c|
- c.with_body do
= _('This alert is specific to the current project.')
추가 매개변수#
dismiss_options (필수)#
모든 해제 가능한 알림 컴포넌트는 dismiss_options 해시를 필요로 합니다:
- 사용자 콜아웃:
{ user: current_user, feature_id: 'callout_name' } - 그룹 콜아웃:
{ user: current_user, group: @group, feature_id: 'callout_name' } - 프로젝트 콜아웃:
{ user: current_user, project: @project, feature_id: 'callout_name' }
ignore_dismissal_earlier_than (선택 사항)#
ignore_dismissal_earlier_than을 추가하여 특정 기간이 지나면 콜아웃이 다시 나타나도록 합니다:
= render Users::DismissibleAlertComponent.new(
title: _('Recurring alert'),
dismiss_options: {
user: current_user,
feature_id: 'recurring_callout',
ignore_dismissal_earlier_than: 30.days.ago
}
) do |c|
- c.with_body do
= _('This alert will reappear every 30 days.')
Time, Date, DateTime 객체 또는 유효한 날짜/시간 문자열을 사용할 수 있습니다:
# Time 객체 사용 (권장)
ignore_dismissal_earlier_than: 30.days.ago
ignore_dismissal_earlier_than: 1.week.ago
# 날짜 문자열 사용
ignore_dismissal_earlier_than: '2023-01-01'
ignore_dismissal_earlier_than: '2023-01-01 12:00:00'
이 매개변수 없이는 해제가 영구적으로 유지됩니다. 매개변수가 있으면, 지정된 시간 이전에 해제된 경우 알림이 다시 나타납니다.
wrapper_options (선택 사항)#
wrapper_options를 사용하여 알림을 사용자 정의 컨테이너로 감쌉니다:
= render Users::GroupDismissibleAlertComponent.new(
title: _('Alert with wrapper'),
dismiss_options: { user: current_user, group: @group, feature_id: 'wrapped_callout' },
wrapper_options: { tag: :section, class: 'custom-wrapper' }
) do |c|
- c.with_body do
= _('This alert is wrapped in a custom container.')
해제 가능한 알림 컴포넌트의 이점#
- 강력한 유효성 검사: 컴포넌트는 feature ID가 적절한 콜아웃 모델에 존재하고 필수 매개변수가 제공되는지 확인합니다
- 간소화된 설정: CSS 클래스, 데이터 속성, 해제 엔드포인트를 수동으로 구성할 필요가 없습니다
- 자동 처리: 해제 로직, 렌더링 조건 및 JavaScript 통합이 자동으로 처리됩니다
- 타입 안전성: 컴포넌트는 올바른 매개변수 유형을 강제하고 구성 오류를 조기에 발견합니다
- 일관된 동작: 모든 해제 가능한 알림은 동일한 패턴과 관례를 따릅니다
- 완전한 AlertComponent 호환성: 기존
AlertComponent매개변수와 기능을 모두 지원합니다
수동 구현에서 마이그레이션#
수동 Pajamas::AlertComponent 사용에서 마이그레이션할 때:
이전:
= render Pajamas::AlertComponent.new(
title: _('Alert title'),
variant: :warning,
alert_options: {
class: 'js-persistent-callout',
data: {
feature_id: 'my_callout',
dismiss_endpoint: callouts_path
}
},
dismissible: true
) do |c|
- c.with_body do
= _('Alert content')
이후:
= render Users::DismissibleAlertComponent.new(
title: _('Alert title'),
variant: :warning,
dismiss_options: { user: current_user, feature_id: 'my_callout' }
) do |c|
- c.with_body do
= _('Alert content')
해제 가능한 배너 컴포넌트#
Haml#
HAML 뷰에서 해제 가능한 배너를 구현할 때는 해제 가능한 배너 컴포넌트를 사용합니다. 이 컴포넌트들은
Pajamas::BannerComponent를 확장하고 강력한 유효성 검사, 간소화된 설정, 해제 로직의 자동 처리를 제공합니다.
사용 가능한 컴포넌트#
Users::DismissibleBannerComponent- 사용자(전역) 컨텍스트 콜아웃용Users::GroupDismissibleBannerComponent- 그룹 컨텍스트 콜아웃용Users::ProjectDismissibleBannerComponent- 프로젝트 컨텍스트 콜아웃용
모든 컴포넌트는 Pajamas::BannerComponent를 상속하며 동일한 인터페이스를 지원하고,
dismiss_options 및 선택적 wrapper_options 매개변수가 추가됩니다.
기본 사용법#
사용자(전역) 콜아웃#
= render Users::DismissibleBannerComponent.new(
button_text: _('Learn more'),
button_link: 'https://about.gitlab.com/',
svg_path: 'illustrations/devops-sm.svg',
variant: :promotion,
dismiss_options: { user: current_user, feature_id: 'my_user_callout' }
) do |c|
- c.with_title do
= _('Banner title')
%p
= _('Banner message content goes here.')
그룹 콜아웃#
= render Users::GroupDismissibleBannerComponent.new(
button_text: _('Learn more'),
button_link: 'https://about.gitlab.com/',
svg_path: 'illustrations/devops-sm.svg',
variant: :promotion,
dismiss_options: { user: current_user, group: @group, feature_id: 'my_group_callout' }
) do |c|
- c.with_title do
= _('Group-specific banner')
%p
= _('This banner is specific to the current group.')
프로젝트 콜아웃#
= render Users::ProjectDismissibleBannerComponent.new(
button_text: _('Learn more'),
button_link: 'https://about.gitlab.com/',
svg_path: 'illustrations/devops-sm.svg',
variant: :promotion,
dismiss_options: { user: current_user, project: @project, feature_id: 'my_project_callout' }
) do |c|
- c.with_title do
= _('Project notification')
%p
= _('This banner is specific to the current project.')
추가 매개변수#
dismiss_options (필수)#
모든 해제 가능한 배너 컴포넌트는 dismiss_options 해시를 필요로 합니다:
- 사용자 콜아웃:
{ user: current_user, feature_id: 'callout_name' } - 그룹 콜아웃:
{ user: current_user, group: @group, feature_id: 'callout_name' } - 프로젝트 콜아웃:
{ user: current_user, project: @project, feature_id: 'callout_name' }
ignore_dismissal_earlier_than (선택 사항)#
ignore_dismissal_earlier_than을 추가하여 특정 기간이 지나면 콜아웃이 다시 나타나도록 합니다:
= render Users::DismissibleBannerComponent.new(
button_text: _('Learn more'),
svg_path: 'illustrations/devops-sm.svg',
variant: :promotion,
dismiss_options: {
user: current_user,
feature_id: 'recurring_callout',
ignore_dismissal_earlier_than: 30.days.ago
}
) do |c|
- c.with_title do
= _('Recurring banner')
%p
= _('This banner will reappear every 30 days.')
Time, Date, DateTime 객체 또는 유효한 날짜/시간 문자열을 사용할 수 있습니다:
# Time 객체 사용 (권장)
ignore_dismissal_earlier_than: 30.days.ago
ignore_dismissal_earlier_than: 1.week.ago
# 날짜 문자열 사용
ignore_dismissal_earlier_than: '2023-01-01'
ignore_dismissal_earlier_than: '2023-01-01 12:00:00'
이 매개변수 없이는 해제가 영구적으로 유지됩니다. 매개변수가 있으면, 지정된 시간 이전에 해제된 경우 배너가 다시 나타납니다.
wrapper_options (선택 사항)#
wrapper_options를 사용하여 배너를 사용자 정의 컨테이너로 감쌉니다:
= render Users::GroupDismissibleBannerComponent.new(
button_text: _('Learn more'),
svg_path: 'illustrations/devops-sm.svg',
variant: :promotion,
dismiss_options: { user: current_user, group: @group, feature_id: 'wrapped_callout' },
wrapper_options: { tag: :section, class: 'custom-wrapper' }
) do |c|
- c.with_title do
= _('Banner with wrapper')
%p
= _('This banner is wrapped in a custom container.')
해제 가능한 배너 컴포넌트의 이점#
- 강력한 유효성 검사: 컴포넌트는 feature ID가 적절한 콜아웃 모델에 존재하고 필수 매개변수가 제공되는지 확인합니다
- 간소화된 설정: CSS 클래스, 데이터 속성, 해제 엔드포인트를 수동으로 구성할 필요가 없습니다
- 자동 처리: 해제 로직, 렌더링 조건 및 JavaScript 통합이 자동으로 처리됩니다
- 타입 안전성: 컴포넌트는 올바른 매개변수 유형을 강제하고 구성 오류를 조기에 발견합니다
- 일관된 동작: 모든 해제 가능한 배너는 동일한 패턴과 관례를 따릅니다
- 완전한 BannerComponent 호환성: 기존
BannerComponent매개변수와 기능을 모두 지원합니다
수동 구현에서 마이그레이션#
수동 Pajamas::BannerComponent 사용에서 마이그레이션할 때:
이전:
= render Pajamas::BannerComponent.new(
button_text: _('Learn more'),
svg_path: 'illustrations/devops-sm.svg',
variant: :promotion,
banner_options: {
class: 'js-persistent-callout',
data: { feature_id: 'my_callout', dismiss_endpoint: callouts_path }
}
) do |c|
- c.with_body do
= _('Banner content')
이후:
= render Users::DismissibleBannerComponent.new(
button_text: _('Learn more'),
svg_path: 'illustrations/devops-sm.svg',
variant: :promotion,
dismiss_options: { user: current_user, feature_id: 'my_callout' }
) do |c|
- c.with_title do
= _('Banner title')
= _('Banner content')
Vue#
이 섹션은 .vue 컴포넌트에서 클라이언트에 렌더링될 때 콜아웃 사용에 대해 설명합니다.
클라이언트 측에서 콜아웃 해제#
Vue 컴포넌트의 경우, GraphQL API와 통합하여 콜아웃의 해제 및 해제 상태 확인을 간소화하는 dismisser 래퍼 컴포넌트를 제공합니다.
사용자(전역) 콜아웃#
모든 그룹 및 프로젝트에서 전체 GitLab 인스턴스에 걸쳐 해제되어야 하는 전역 사용자 콜아웃의 경우
<user-callout-dismisser>를 사용합니다. 콜아웃이 모든 그룹 및 프로젝트에서 사용자에게 전역으로
해제되어야 하는 경우(예: 기능 공지, 계정 보안 알림)에 이 컴포넌트를 사용합니다.
<user-callout-dismisser feature-name="my_user_callout">
<template #default="{ dismiss, shouldShowCallout }">
<my-callout-component
v-if="shouldShowCallout"
@close="dismiss"
/>
</template>
</user-callout-dismisser>
자세한 내용은 app/assets/javascripts/vue_shared/components/user_callout_dismisser.vue를 참조하세요.
그룹 콜아웃#
특정 그룹 컨텍스트 내에서만 해제되어야 하는 그룹별 콜아웃의 경우
<user-group-callout-dismisser>를 사용합니다. 콜아웃이 그룹 컨텍스트에 특화되어
해당 그룹 내에서만 해제되어야 하는 경우(예: 그룹 청구 알림, 그룹별 기능 프로모션)에
이 컴포넌트를 사용합니다.
<user-group-callout-dismisser
feature-name="my_group_callout"
:group-id="groupId"
>
<template #default="{ dismiss, shouldShowCallout }">
<my-group-callout-component
v-if="shouldShowCallout"
@close="dismiss"
/>
</template>
</user-group-callout-dismisser>
group-id prop은 숫자 ID(예: 123)와 GraphQL ID(예: 'gid://gitlab/Group/123') 모두 허용합니다.
컴포넌트는 내부적으로 GraphQL 형식으로의 변환을 처리하므로 어느 형식이든 전달할 수 있습니다.
자세한 내용은 app/assets/javascripts/vue_shared/components/user_group_callout_dismisser.vue를 참조하세요.
사용 가능한 슬롯 props#
두 컴포넌트 모두 동일한 슬롯 props를 제공합니다:
dismiss: 콜아웃을 해제하는 함수shouldShowCallout: 콜아웃을 표시할지 여부를 나타내는 Boolean
