학습 목표
이 포스트를 마치면 다음을 할 수 있습니다:
- Metabase 외관을 회사 브랜드에 맞게 커스터마이징
- 로고, 색상, 폰트 변경
- 커스텀 도메인 설정
- 환경 변수로 고급 설정
- 플러그인과 확장 기능 활용
브랜딩 커스터마이징
먼저 사용 중인 버전과 요금제에서 Appearance 설정을 제공하는지 확인하세요. 공식 문서에서 custom appearance는 Pro·Enterprise 기능으로 안내합니다. 아래 설정 화면·환경 변수·HTML 예시는 모두 같은 수준의 기본 제공 기능이 아니므로, 실제 관리 화면에서 가능한 항목부터 적용하세요. 공식 Appearance 설명을 기준으로 확인하면 됩니다.
Application Settings
1
2
3
4
5
6
7
8
9
10
11
| Admin > Settings > Appearance
Application name:
Metabase → "Your Company Analytics"
Application description:
"Business intelligence platform for Your Company"
Application color:
Default: #509EE3 (Metabase blue)
Custom: #007bff (Your brand color)
|
로고 변경
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| Admin > Settings > Appearance > Logo
Logo image:
- Format: PNG, SVG (recommended)
- Size: 60px height, max 200px width
- Background: Transparent
- Upload: [Choose file]
Favicon:
- Format: ICO, PNG
- Size: 32x32px or 16x16px
- Upload: [Choose file]
Powered by Metabase:
☐ Show "Powered by Metabase" (Paid feature)
☑ Hide branding (Enterprise plan)
|
색상 테마
Primary Colors:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| Admin > Settings > Appearance > Colors
Primary color: #007bff
- Buttons
- Links
- Active states
Accent color: #28a745
- Success messages
- Positive metrics
- Call-to-actions
Navigation bar color: #343a40
- Top navigation background
- Sidebar background
|
커스텀 CSS (고급):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| /* metabase-custom.css */
/* Navigation bar */
.Nav {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
/* Primary button */
.Button--primary {
background-color: #007bff;
border-color: #007bff;
}
.Button--primary:hover {
background-color: #0056b3;
border-color: #004085;
}
/* Cards */
.Card {
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* Question titles */
.Question-header {
font-family: 'Roboto', sans-serif;
font-weight: 700;
}
|
폰트 커스터마이징
1
2
3
4
5
6
7
8
9
10
11
12
| Admin > Settings > Appearance > Font
Font family (URL):
https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap
Font family name:
'Roboto', sans-serif
Apply to:
☑ Headings
☑ Body text
☑ UI elements
|
지원되는 Google Fonts:
1
2
3
4
5
6
7
8
9
10
11
12
13
| Sans-serif:
- Roboto
- Open Sans
- Lato
- Montserrat
Serif:
- Merriweather
- Playfair Display
Monospace:
- Roboto Mono
- Source Code Pro
|
커스텀 도메인
도메인 설정
Step 1: DNS 설정
1
2
3
4
5
| CNAME record:
analytics.yourcompany.com → metabase.yourcompany.com
또는 A record:
analytics.yourcompany.com → 203.0.113.1 (Metabase server IP)
|
Step 2: Metabase 설정
1
2
| # Environment variable
MB_SITE_URL=https://analytics.yourcompany.com
|
Step 3: SSL/TLS 인증서
1
2
3
4
5
6
| # Let's Encrypt (무료)
sudo certbot --nginx -d analytics.yourcompany.com
# 또는 상용 인증서
# SSL certificate: /etc/ssl/certs/yourcompany.crt
# SSL key: /etc/ssl/private/yourcompany.key
|
Step 4: Nginx 리버스 프록시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| # /etc/nginx/sites-available/metabase
server {
listen 80;
server_name analytics.yourcompany.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name analytics.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/analytics.yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.yourcompany.com/privkey.pem;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
|
환경 변수 설정
주요 환경 변수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| # Site URL
MB_SITE_URL=https://analytics.yourcompany.com
# Database (H2 → PostgreSQL 권장)
MB_DB_TYPE=postgres
MB_DB_DBNAME=metabase
MB_DB_PORT=5432
MB_DB_USER=metabase
MB_DB_PASS=secure_password
MB_DB_HOST=db.yourcompany.com
# Email
MB_EMAIL_SMTP_HOST=smtp.gmail.com
MB_EMAIL_SMTP_PORT=587
MB_EMAIL_SMTP_SECURITY=tls
MB_EMAIL_SMTP_USERNAME=metabase@yourcompany.com
MB_EMAIL_SMTP_PASSWORD=app_password
MB_EMAIL_FROM_ADDRESS=metabase@yourcompany.com
# Security
MB_PASSWORD_COMPLEXITY=strong
MB_PASSWORD_LENGTH=10
MB_SESSION_COOKIES=true
MB_EMBEDDING_SECRET_KEY=your-secret-key-min-64-chars
# Performance
MB_JETTY_MAX_THREADS=100
MB_ASYNC_QUERY_THREAD_POOL_SIZE=50
MB_QUERY_TIMEOUT=120
# Caching
MB_APPLICATION_DB_MAX_CONNECTION_POOL_SIZE=15
# Logging
MB_LOG_LEVEL=INFO
MB_PLUGINS_DIR=/plugins
|
Docker Compose 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| # docker-compose.yml
version: '3.8'
services:
metabase:
image: metabase/metabase:latest
container_name: metabase
hostname: metabase
ports:
- 3000:3000
environment:
MB_DB_TYPE: postgres
MB_DB_DBNAME: metabase
MB_DB_PORT: 5432
MB_DB_USER: metabase
MB_DB_PASS: ${MB_DB_PASS}
MB_DB_HOST: postgres
MB_SITE_URL: https://analytics.yourcompany.com
MB_EMBEDDING_SECRET_KEY: ${MB_EMBEDDING_SECRET_KEY}
volumes:
- ./metabase-data:/metabase-data
- ./plugins:/plugins
depends_on:
- postgres
restart: always
postgres:
image: postgres:15
container_name: metabase-postgres
environment:
POSTGRES_USER: metabase
POSTGRES_PASSWORD: ${MB_DB_PASS}
POSTGRES_DB: metabase
volumes:
- postgres-data:/var/lib/postgresql/data
restart: always
volumes:
postgres-data:
|
.env 파일:
1
2
3
| # .env
MB_DB_PASS=your-secure-database-password
MB_EMBEDDING_SECRET_KEY=your-very-long-secret-key-at-least-64-characters-long
|
고급 커스터마이징
커스텀 Drivers
MongoDB driver 추가:
1
2
3
4
5
6
7
8
9
10
11
12
13
| # 1. Driver 다운로드
wget https://github.com/metabase/metabase-mongodb-driver/releases/download/v1.0.0/mongodb.metabase-driver.jar
# 2. Plugins 디렉토리에 복사
mkdir -p /path/to/metabase/plugins
cp mongodb.metabase-driver.jar /path/to/metabase/plugins/
# 3. Metabase 재시작
docker-compose restart metabase
# 4. 확인
Admin > Databases > Add database
→ MongoDB should appear in the list
|
지원되는 커뮤니티 Drivers:
1
2
3
4
5
6
| - MongoDB
- Presto
- Druid
- Vertica
- Exasol
- Oracle (free driver)
|
Landing Page 커스터마이징
1
2
3
4
5
| # Environment variable
MB_SITE_HOMEPAGE=custom
# 또는
MB_SITE_HOMEPAGE=/dashboard/1 # Specific dashboard
|
Custom homepage HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| <!-- /path/to/metabase/resources/frontend_client/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Your Company Analytics</title>
<link rel="stylesheet" href="/app/dist/app.css">
<style>
body {
font-family: 'Roboto', sans-serif;
}
.homepage-banner {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 60px 20px;
color: white;
text-align: center;
}
</style>
</head>
<body>
<div class="homepage-banner">
<h1>Welcome to Your Company Analytics</h1>
<p>Empowering decisions with data</p>
</div>
<div id="root"></div>
<script src="/app/dist/app.js"></script>
</body>
</html>
|
Email 템플릿 커스터마이징
아래 HTML은 이메일의 구조와 스타일을 설계하는 샘플입니다. {{alert_title}}, {{metric_value}} 등의 값을 누가 채우고 어떤 발송 경로에서 렌더링하는지는 구현되어 있지 않습니다. HTML을 파일로 저장하는 것만으로 Metabase의 기본 알림 템플릿에 등록되는 절차로 읽지 마세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| <!-- Email alert template -->
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: 'Roboto', sans-serif;
background-color: #f4f4f4;
padding: 20px;
}
.container {
max-width: 600px;
margin: 0 auto;
background: white;
border-radius: 8px;
overflow: hidden;
}
.header {
background: #007bff;
color: white;
padding: 30px;
text-align: center;
}
.logo {
max-width: 150px;
}
.content {
padding: 30px;
}
.metric {
font-size: 36px;
font-weight: bold;
color: #007bff;
margin: 20px 0;
}
.footer {
background: #f8f9fa;
padding: 20px;
text-align: center;
font-size: 12px;
color: #6c757d;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<img src="https://yourcompany.com/logo.png" alt="Your Company" class="logo">
<h1>Analytics Alert</h1>
</div>
<div class="content">
<h2>{{alert_title}}</h2>
<p>{{alert_description}}</p>
<div class="metric">{{metric_value}}</div>
<p><a href="{{dashboard_url}}" style="background: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;">View Dashboard</a></p>
</div>
<div class="footer">
<p>© 2025 Your Company. All rights reserved.</p>
<p><a href="{{unsubscribe_url}}">Unsubscribe</a></p>
</div>
</div>
</body>
</html>
|
조직별 커스터마이징
Enterprise Use Cases
1. Multi-tenant SaaS
1
2
3
4
5
6
| # 각 테넌트별 브랜딩
MB_SITE_NAME={{tenant.name}} Analytics
MB_SITE_URL=https://{{tenant.subdomain}}.analytics.yourcompany.com
# 테넌트별 로고 (동적 로딩)
# Application에서 tenant_id로 로고 조회
|
2. 금융 기관
1
2
3
4
5
6
7
8
9
| # 보안 강화
MB_PASSWORD_COMPLEXITY=strong
MB_PASSWORD_LENGTH=12
MB_SESSION_TIMEOUT=30 # minutes
MB_ENABLE_AUDIT_APP=true
# 화이트라벨링
MB_HIDE_METABASE_BRANDING=true
MB_CUSTOM_LOGIN_MESSAGE="Secure Financial Analytics Portal"
|
3. 이커머스
1
2
3
4
5
6
7
| # 실시간 대시보드
MB_CACHE_TTL_SHORT=60 # 1 minute for real-time data
MB_CACHE_TTL_LONG=3600 # 1 hour for historical
# 고객 대면 임베딩
MB_EMBEDDING_ENABLED=true
MB_EMBEDDING_HOMEPAGE=/dashboard/customer-analytics
|
사용자 경험 개선
기본 대시보드 설정
1
2
3
4
5
6
7
8
9
10
| Admin > Settings > General
Default Dashboard:
☑ Set a default dashboard for new users
Dashboard: "Company Overview"
New user experience:
☑ Show onboarding
☑ Show tips
Tutorial collection: "Getting Started"
|
Question Templates
1
2
3
4
5
6
7
8
9
10
11
| -- Template: "Monthly Sales Report"
-- Saved as a template with placeholders
SELECT
DATE_TRUNC('month', created_at) as month,
{{metric}} as value, -- Placeholder
{{grouping}} as category -- Placeholder
FROM orders
WHERE created_at >= {{date_range}}
GROUP BY month, {{grouping}}
ORDER BY month DESC
|
Snippets Library
1
2
3
4
5
6
7
8
| -- Snippet: "current_quarter"
DATE_TRUNC('quarter', CURRENT_DATE)
-- Snippet: "revenue_query"
SUM(total) FILTER (WHERE status = 'completed')
-- Snippet: "active_users"
COUNT(DISTINCT user_id) FILTER (WHERE last_active >= CURRENT_DATE - INTERVAL '30 days')
|
모니터링 및 유지보수
Health Checks
1
2
3
4
5
6
7
8
9
| # API endpoint
GET /api/health
Response:
{
"status": "ok",
"database": "ok",
"cache": "ok"
}
|
모니터링 대시보드:
1
2
3
4
5
6
7
8
| -- System metrics
SELECT
metric_name,
metric_value,
recorded_at
FROM metabase_metrics
WHERE recorded_at >= NOW() - INTERVAL '24 hours'
ORDER BY recorded_at DESC
|
Backup & Restore
1
2
3
4
5
6
7
8
9
| # Backup Metabase database (PostgreSQL)
pg_dump -h localhost -U metabase metabase > metabase_backup_$(date +%Y%m%d).sql
# Backup uploaded files
tar -czf metabase_data_$(date +%Y%m%d).tar.gz /path/to/metabase-data/
# Restore
psql -h localhost -U metabase metabase < metabase_backup_20250101.sql
tar -xzf metabase_data_20250101.tar.gz -C /path/to/restore/
|
Upgrade 프로세스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 1. Backup (위 참조)
# 2. Docker image 업데이트
docker-compose pull metabase
# 3. 서비스 재시작
docker-compose up -d metabase
# 4. 확인
docker logs -f metabase
# 5. 테스트
# - 로그인 확인
# - 대시보드 로딩 확인
# - Query 실행 확인
|
실전 연습 문제
연습 1: 기본 브랜딩 (초급)
과제: 회사 브랜드 적용
- 로고 변경
- 색상 테마 적용
- 커스텀 도메인 설정
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| 1. 로고 준비:
- Company logo: 200x60px PNG (transparent)
- Favicon: 32x32px ICO
2. Metabase 설정:
Admin > Settings > Appearance
Application name: "Acme Analytics"
Logo:
- Upload: acme-logo.png
- Position: Left aligned
Favicon:
- Upload: acme-favicon.ico
Colors:
- Primary: #E91E63 (Acme brand pink)
- Accent: #FFC107 (Acme brand yellow)
- Navigation: #212121 (Dark gray)
Font:
- URL: https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700
- Family: 'Poppins', sans-serif
3. 커스텀 도메인:
DNS (Cloudflare):
CNAME analytics → metabase.acme.com
Environment:
MB_SITE_URL=https://analytics.acme.com
SSL:
certbot --nginx -d analytics.acme.com
Nginx:
server_name analytics.acme.com;
proxy_pass http://localhost:3000;
4. 테스트:
- https://analytics.acme.com 접속
- 로고 표시 확인
- 색상 테마 확인
- SSL 인증서 확인
|
연습 2: 이메일 템플릿 커스터마이징 (중급)
해답의 파일 경로는 예시이며 템플릿 로더나 발송 코드가 함께 제공되지는 않습니다. 먼저 샘플 값으로 제목·지표·대시보드 링크가 채워진 이메일을 만들어 실제 수신 화면에서 확인하세요. 브랜드 적용 결과와 Metabase 알림에 연결하는 작업을 각각 검증하는 것이 과제입니다.
과제: 브랜드 일치 이메일 템플릿
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
| <!-- /resources/email-templates/alert.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body {
font-family: 'Poppins', -apple-system, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.email-container {
max-width: 600px;
margin: 20px auto;
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.email-header {
background: linear-gradient(135deg, #E91E63, #C2185B);
padding: 40px 30px;
text-align: center;
}
.email-header img {
max-width: 180px;
height: auto;
}
.email-header h1 {
color: white;
margin: 20px 0 10px;
font-size: 28px;
}
.email-header p {
color: rgba(255,255,255,0.9);
margin: 0;
}
.email-body {
padding: 40px 30px;
}
.metric-card {
background: #FFF9C4;
border-left: 4px solid #FFC107;
padding: 20px;
margin: 20px 0;
border-radius: 4px;
}
.metric-value {
font-size: 48px;
font-weight: 700;
color: #E91E63;
margin: 10px 0;
}
.metric-label {
font-size: 14px;
color: #666;
text-transform: uppercase;
letter-spacing: 1px;
}
.cta-button {
display: inline-block;
background: #E91E63;
color: white;
padding: 12px 30px;
text-decoration: none;
border-radius: 4px;
font-weight: 600;
margin: 20px 0;
}
.email-footer {
background: #fafafa;
padding: 30px;
text-align: center;
font-size: 12px;
color: #999;
}
.email-footer a {
color: #E91E63;
text-decoration: none;
}
</style>
</head>
<body>
<div class="email-container">
<div class="email-header">
<img src="https://acme.com/assets/logo-white.png" alt="Acme">
<h1>Alert Triggered</h1>
<p>{{alert_condition}}</p>
</div>
<div class="email-body">
<h2>{{alert_title}}</h2>
<p>{{alert_message}}</p>
<div class="metric-card">
<div class="metric-label">Current Value</div>
<div class="metric-value">{{metric_value}}</div>
<p>{{metric_comparison}}</p>
</div>
<p><strong>What this means:</strong></p>
<p>{{explanation}}</p>
<p><strong>Recommended action:</strong></p>
<ul>
<li>{{action_1}}</li>
<li>{{action_2}}</li>
</ul>
<center>
<a href="{{dashboard_url}}" class="cta-button">
View Dashboard
</a>
</center>
</div>
<div class="email-footer">
<p>© 2025 Acme Corporation. All rights reserved.</p>
<p>
<a href="{{preferences_url}}">Notification Preferences</a> |
<a href="{{unsubscribe_url}}">Unsubscribe</a>
</p>
<p style="margin-top: 20px; font-size: 11px;">
This is an automated alert from Acme Analytics.
For support, contact analytics@acme.com
</p>
</div>
</div>
</body>
</html>
|
다음 단계
커스터마이징을 마스터했습니다. 다음 포스트에서는:
- 운영과 모니터링: 백업, 복구, 성능 모니터링
- 고가용성: Load balancing, Clustering
- 문제 해결: Common issues, Debugging
요약
커스터마이징 체크리스트
브랜딩:
- 로고 및 Favicon 변경
- 색상 테마 적용
- 폰트 커스터마이징
- Application 이름 변경
도메인:
- 커스텀 도메인 설정
- SSL 인증서 설치
- Nginx/Reverse proxy 설정
- DNS 설정 완료
고급:
- 환경 변수 최적화
- 이메일 템플릿 커스터마이징
- 커스텀 Drivers 설치
- Landing page 설정
유지보수:
- 정기 백업 스케줄
- 업그레이드 계획
- 모니터링 설정
- 문서화 완료
다음 포스트에서는 Metabase를 안정적으로 운영하는 방법을 배웁니다!
📚 시리즈 전체 목차
🚀 기초편 (1-5화)
- Metabase 소개와 핵심 개념
- 설치와 초기 설정
- 샘플 데이터 둘러보기
- 첫 차트 만들기 - 실습 완전정복
- 대시보드 만들기 - 한 화면에 모으기
💪 활용편 (6-10화)
- 필터와 파라미터
- SQL 네이티브 쿼리
- 데이터 모델링
- 자동화와 알림
- 권한과 보안
🎯 고급편 (11-16화)
- 임베딩과 공유
- 성능 최적화
- 멀티 데이터소스
- [커스터마이징] (현재 글)
- 운영과 모니터링
- 실전 프로젝트