Skip to content

Xibo 디지털 사이니지 시스템 ​

시스템 소개 ​

Xibo는 오픈소스 디지털 사이니지 플랫폼으로, 무인 공간에서 효과적인 정보 전달과 광고 표시를 위한 강력한 솔루션입니다. 완전 무료로 사용 가능하며, 엔터프라이즈급 기능을 제공합니다.

주요 특징 ​

특징설명
오픈소스완전 무료, 소스코드 공개
웹 기반 관리어디서나 브라우저로 관리
다중 디스플레이무제한 디스플레이 지원
스케줄링시간대별 콘텐츠 예약
실시간 업데이트즉시 콘텐츠 변경 가능
통계 및 리포트재생 기록 및 성능 분석

시스템 구성요소 ​

1. Xibo CMS (Content Management System) ​

yaml
xibo_cms:
  description: "중앙 관리 서버"
  functions:
    - 콘텐츠 업로드 및 관리
    - 레이아웃 디자인
    - 스케줄 설정
    - 디스플레이 관리
    - 사용자 권한 관리
    
  requirements:
    - PHP 7.4 이상
    - MySQL 5.6 이상
    - Apache/Nginx 웹서버
    - 최소 2GB RAM

2. Xibo Player (디스플레이 클라이언트) ​

yaml
xibo_player:
  platforms:
    windows: "Windows 8.1 이상"
    android: "Android 4.4 이상"
    linux: "Ubuntu 18.04 이상"
    webos: "LG webOS 3.0 이상"
    tizen: "Samsung Tizen 3.0 이상"
    
  hardware_requirements:
    min_ram: "2GB"
    min_storage: "8GB"
    network: "안정적인 인터넷 연결"

설치 가이드 ​

Docker를 이용한 CMS 설치 (권장) ​

1. Docker 및 Docker Compose 설치 ​

bash
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install docker.io docker-compose

# CentOS/RHEL
sudo yum install docker docker-compose

# Docker 서비스 시작
sudo systemctl start docker
sudo systemctl enable docker

2. Xibo CMS 다운로드 및 설치 ​

bash
# Xibo CMS 다운로드
wget https://github.com/xibosignage/xibo-cms/releases/download/3.3.0/xibo-docker.tar.gz

# 압축 해제
tar -xvf xibo-docker.tar.gz
cd xibo-docker

# 설정 파일 복사
cp config.env.template config.env

# CMS 시작
sudo docker-compose up -d

3. 초기 설정 ​

yaml
# config.env 파일 수정
MYSQL_PASSWORD: "secure_password_here"
CMS_KEY: "generate_random_key_here"
MYSQL_ROOT_PASSWORD: "root_password_here"

# 시간대 설정
CMS_TIMEZONE: "Asia/Seoul"

# 파일 업로드 크기
CMS_PHP_POST_MAX_SIZE: "2000M"
CMS_PHP_UPLOAD_MAX_FILESIZE: "2000M"

웹 설치 마법사 ​

  1. 브라우저에서 http://서버IP 접속
  2. 설치 마법사 시작
  3. 데이터베이스 정보 입력
  4. 관리자 계정 생성
  5. 라이브러리 경로 설정
  6. 설치 완료

CMS 기본 사용법 ​

대시보드 인터페이스 ​

javascript
// 대시보드 주요 메뉴
const dashboard = {
  status: {
    displays: "연결된 디스플레이 상태",
    content: "콘텐츠 사용량",
    bandwidth: "네트워크 사용량",
    alerts: "시스템 알림"
  },
  
  quickActions: [
    "새 레이아웃 만들기",
    "미디어 업로드",
    "스케줄 설정",
    "디스플레이 추가"
  ]
};

미디어 라이브러리 관리 ​

미디어 업로드 ​

javascript
// 지원 미디어 형식
const supportedMedia = {
  images: ["jpg", "jpeg", "png", "gif", "bmp", "svg"],
  videos: ["mp4", "avi", "webm", "mkv", "mov"],
  audio: ["mp3", "wav", "ogg"],
  documents: ["pdf", "ppt", "pptx"],
  web: ["html", "url"]
};

// 미디어 업로드 설정
const uploadSettings = {
  maxFileSize: "2GB",
  batchUpload: true,
  autoTag: true,
  thumbnail: "auto-generate"
};

미디어 구성 및 태그 ​

yaml
media_organization:
  folders:
    - /광고
    - /공지사항
    - /이벤트
    - /날씨정보
    - /뉴스피드
    
  tags:
    - seasonal: "계절별 콘텐츠"
    - promotional: "프로모션"
    - emergency: "긴급 공지"
    - informational: "정보성 콘텐츠"

레이아웃 디자인 ​

레이아웃 구조 ​

javascript
// 레이아웃 템플릿
const layoutTemplate = {
  name: "무인매장 기본 레이아웃",
  resolution: {
    width: 1920,
    height: 1080
  },
  
  regions: [
    {
      name: "메인 콘텐츠",
      position: { x: 0, y: 0 },
      size: { width: 1920, height: 900 },
      widgets: ["이미지 슬라이드", "비디오"]
    },
    {
      name: "하단 정보바",
      position: { x: 0, y: 900 },
      size: { width: 1920, height: 180 },
      widgets: ["시계", "날씨", "텍스트 스크롤"]
    }
  ]
};

위젯 활용 ​

1. 텍스트 위젯 ​

html
<!-- HTML 텍스트 위젯 예제 -->
<div style="font-family: 'Noto Sans KR'; padding: 20px;">
  <h1 style="color: #2196F3;">오늘의 공지사항</h1>
  <marquee behavior="scroll" direction="left">
    무인 공간 이용 시간: 24시간 연중무휴 | 
    고객센터: 1588-0000 | 
    긴급 시 비상벨을 눌러주세요
  </marquee>
</div>

2. 시계 위젯 ​

javascript
// 디지털 시계 설정
const clockWidget = {
  format: "HH:mm:ss",
  timezone: "Asia/Seoul",
  font: {
    family: "Digital",
    size: "72px",
    color: "#FFFFFF"
  },
  showDate: true,
  dateFormat: "YYYY년 MM월 DD일 dddd"
};

3. 날씨 위젯 ​

yaml
weather_widget:
  provider: "OpenWeatherMap"
  api_key: "your_api_key_here"
  location: "Seoul,KR"
  
  display:
    - current_temp: true
    - weather_icon: true
    - humidity: true
    - forecast_3days: true
    
  update_interval: "30min"

4. RSS/뉴스 피드 ​

javascript
// RSS 피드 설정
const rssFeed = {
  url: "https://news.example.com/rss",
  items: 5,
  updateInterval: 600, // 10분
  
  template: `
    <div class="news-item">
      <h3>[Title]</h3>
      <p>[Description]</p>
      <span class="date">[Date]</span>
    </div>
  `,
  
  animation: {
    type: "fade",
    duration: 5000
  }
};

플레이어 설정 및 관리 ​

Android 플레이어 설정 ​

1. APK 설치 ​

bash
# ADB를 통한 설치
adb install xibo-player.apk

# 또는 Google Play Store에서 설치
# "Xibo for Android" 검색

2. 플레이어 구성 ​

javascript
// 플레이어 설정
const playerConfig = {
  cmsAddress: "http://192.168.1.100",
  cmsKey: "your_cms_key",
  displayName: "1층 로비 디스플레이",
  
  settings: {
    orientation: "landscape",
    preventSleep: true,
    startOnBoot: true,
    collectInterval: 300, // 5분
    screenshotInterval: 0, // 비활성화
  },
  
  hardware: {
    displayId: 1,
    blacklistVideo: false,
    useSurfaceVideoView: true,
    videoDecoderHardwareAccelerated: true
  }
};

Windows 플레이어 설정 ​

1. 설치 및 구성 ​

powershell
# Windows Player 설치
# 다운로드: https://xibosignage.com/downloads

# 설정 파일 위치
C:\Users\[Username]\Documents\Xibo Library\

# 자동 시작 설정
shell:startup # 시작 프로그램 폴더에 바로가기 추가

2. 플레이어 옵션 ​

xml
<!-- XiboClient.config.xml -->
<configuration>
  <cmsAddress>http://192.168.1.100</cmsAddress>
  <key>display_secret_key</key>
  <localLibrary>C:\XiboLibrary</localLibrary>
  <splashOverride>false</splashOverride>
  <preventSleep>true</preventSleep>
  <logLevel>error</logLevel>
</configuration>

스케줄링 및 캠페인 ​

스케줄 생성 ​

javascript
// 시간대별 스케줄 설정
const schedule = {
  name: "평일 운영 스케줄",
  
  campaigns: [
    {
      name: "아침 인사",
      time: "07:00-09:00",
      days: ["mon", "tue", "wed", "thu", "fri"],
      layouts: ["morning_welcome.xml"],
      priority: 1
    },
    {
      name: "점심 프로모션",
      time: "11:30-13:30",
      days: ["mon", "tue", "wed", "thu", "fri"],
      layouts: ["lunch_promotion.xml"],
      priority: 2
    },
    {
      name: "저녁 안내",
      time: "17:00-19:00",
      days: ["mon", "tue", "wed", "thu", "fri"],
      layouts: ["evening_info.xml"],
      priority: 1
    }
  ],
  
  defaultLayout: "default_content.xml"
};

캠페인 관리 ​

yaml
campaign_structure:
  seasonal_campaigns:
    spring:
      start: "2024-03-01"
      end: "2024-05-31"
      layouts:
        - spring_promotion.xml
        - flower_festival.xml
        
    summer:
      start: "2024-06-01"
      end: "2024-08-31"
      layouts:
        - summer_sale.xml
        - vacation_info.xml
        
  event_campaigns:
    black_friday:
      date: "2024-11-29"
      priority: 10
      override_all: true
      
    christmas:
      start: "2024-12-20"
      end: "2024-12-25"
      priority: 5

우선순위 및 충돌 해결 ​

javascript
// 스케줄 우선순위 규칙
const priorityRules = {
  levels: {
    emergency: 100,  // 최우선
    event: 50,       // 이벤트
    promotional: 30, // 프로모션
    regular: 10,     // 일반
    default: 0       // 기본
  },
  
  conflictResolution: {
    method: "priority", // priority, round-robin, percentage
    tieBreaker: "newest" // newest, oldest, random
  }
};

무인 공간 통합 활용 ​

시나리오 1: 무인 카페 ​

javascript
// 무인 카페 디지털 메뉴보드
const cafeSignage = {
  displays: [
    {
      location: "입구",
      content: "환영 메시지, 프로모션",
      schedule: "항시"
    },
    {
      location: "주문 키오스크 상단",
      content: "메뉴, 가격, 추천 음료",
      schedule: "운영시간"
    },
    {
      location: "픽업 대기 구역",
      content: "주문 번호, 대기 시간",
      integration: "POS 시스템 연동"
    }
  ],
  
  dynamicContent: {
    weatherBased: {
      hot: ["아이스 음료 프로모션"],
      cold: ["따뜻한 음료 추천"],
      rainy: ["테이크아웃 할인"]
    },
    
    timeBased: {
      morning: ["모닝 세트 메뉴"],
      afternoon: ["디저트 콤보"],
      evening: ["테이크아웃 특가"]
    }
  }
};

시나리오 2: 무인 편의점 ​

yaml
convenience_store_signage:
  entrance_display:
    content:
      - welcome_message
      - store_hours
      - today_promotion
      - payment_methods
      
  product_displays:
    fresh_food:
      update: "every_4_hours"
      content:
        - expiry_alerts
        - discount_items
        
    seasonal:
      update: "weekly"
      content:
        - new_arrivals
        - seasonal_products
        
  checkout_display:
    content:
      - payment_guide
      - membership_benefits
      - customer_service

시나리오 3: 공유 오피스 ​

javascript
// 공유 오피스 정보 시스템
const sharedOfficeSignage = {
  lobby: {
    widgets: [
      "회사 로고 롤링",
      "회의실 예약 현황",
      "오늘의 이벤트",
      "교통 정보"
    ]
  },
  
  meetingRooms: {
    doorDisplay: {
      size: "10.1 inch",
      content: [
        "현재 예약 상태",
        "다음 예약 정보",
        "QR 체크인"
      ]
    }
  },
  
  commonArea: {
    content: [
      "공지사항",
      "날씨 정보",
      "뉴스 피드",
      "시설 이용 안내"
    ]
  }
};

API 연동 ​

REST API 활용 ​

javascript
// Xibo API 인증
const xiboAPI = {
  baseURL: "http://your-cms-url/api",
  
  auth: async function() {
    const response = await fetch(`${this.baseURL}/authorize`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: 'grant_type=client_credentials&client_id=YOUR_ID&client_secret=YOUR_SECRET'
    });
    
    return response.json();
  },
  
  // 디스플레이 상태 조회
  getDisplayStatus: async function(displayId, token) {
    const response = await fetch(`${this.baseURL}/display/${displayId}`, {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });
    
    return response.json();
  },
  
  // 레이아웃 변경
  changeLayout: async function(displayId, layoutId, token) {
    const response = await fetch(`${this.baseURL}/displaygroup/${displayId}/action/changeLayout`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: `layoutId=${layoutId}&duration=0`
    });
    
    return response.json();
  }
};

외부 시스템 연동 ​

javascript
// POS 시스템 연동
const posIntegration = {
  // 실시간 매출 데이터 표시
  salesData: async function() {
    const sales = await fetchPOSData();
    
    return {
      widget: "dataSet",
      data: {
        todaySales: sales.today,
        bestSeller: sales.topProduct,
        customerCount: sales.customers
      },
      updateInterval: 300 // 5분
    };
  },
  
  // 재고 알림
  inventoryAlert: async function() {
    const inventory = await fetchInventory();
    const lowStock = inventory.filter(item => item.quantity < 10);
    
    return {
      widget: "ticker",
      text: lowStock.map(item => `${item.name} 재고 부족`).join(' | '),
      speed: "medium",
      backgroundColor: "#FF5722"
    };
  }
};

// IoT 센서 연동
const iotIntegration = {
  // 실내 환경 정보
  environmentData: {
    temperature: "23°C",
    humidity: "45%",
    airQuality: "좋음",
    co2Level: "450ppm"
  },
  
  // 혼잡도 표시
  crowdLevel: {
    current: 15,
    capacity: 50,
    status: "여유",
    color: "#4CAF50"
  }
};

모니터링 및 관리 ​

시스템 모니터링 ​

yaml
monitoring:
  display_health:
    check_interval: "5min"
    alerts:
      - offline: "디스플레이 연결 끊김"
      - storage_full: "저장 공간 부족"
      - content_error: "콘텐츠 재생 오류"
      
  performance_metrics:
    - cpu_usage
    - memory_usage
    - network_bandwidth
    - content_download_speed
    
  reporting:
    daily_report:
      - total_playtime
      - content_statistics
      - error_logs
      
    monthly_report:
      - display_uptime
      - content_performance
      - maintenance_schedule

원격 관리 ​

javascript
// 원격 명령 실행
const remoteCommands = {
  // 스크린샷 캡처
  screenshot: {
    command: "screenShot",
    params: {
      displayId: 1
    }
  },
  
  // 재부팅
  reboot: {
    command: "reboot",
    params: {
      displayId: 1,
      delay: 60 // 60초 후 재부팅
    }
  },
  
  // 캐시 삭제
  clearCache: {
    command: "clearCache",
    params: {
      displayId: 1
    }
  },
  
  // 콘텐츠 강제 업데이트
  forceRefresh: {
    command: "collectNow",
    params: {
      displayId: 1
    }
  }
};

문제 해결 가이드 ​

일반적인 문제와 해결방법 ​

문제원인해결방법
디스플레이 오프라인네트워크 연결 문제네트워크 설정 확인, 방화벽 규칙 검토
콘텐츠 미표시스케줄 설정 오류스케줄 시간대 및 우선순위 확인
동영상 재생 안됨코덱 미지원H.264 코덱으로 인코딩, 하드웨어 가속 활성화
레이아웃 깨짐해상도 불일치디스플레이 해상도와 레이아웃 해상도 맞춤
업데이트 지연수집 주기 설정Collection Interval 단축 (최소 60초)

성능 최적화 ​

javascript
// 성능 최적화 설정
const optimization = {
  media: {
    imageFormat: "webp", // 용량 절감
    videoCodec: "h264",
    videoBitrate: "5000k",
    resolution: "1920x1080"
  },
  
  player: {
    memoryLimit: "1024MB",
    downloadThreads: 2,
    renderingMode: "hardware",
    cacheSize: "500MB"
  },
  
  network: {
    downloadDuringPlayback: false,
    bandwidthLimit: "10mbps",
    retryCount: 3,
    timeout: 30
  }
};

보안 설정 ​

CMS 보안 ​

yaml
security_settings:
  authentication:
    two_factor: enabled
    password_policy:
      min_length: 12
      require_special: true
      expiry_days: 90
      
  access_control:
    ip_whitelist:
      - "192.168.1.0/24"
      - "10.0.0.0/8"
      
    user_roles:
      - super_admin: "모든 권한"
      - content_manager: "콘텐츠 관리"
      - viewer: "읽기 전용"
      
  encryption:
    api_ssl: required
    database: encrypted
    media_files: optional

플레이어 보안 ​

javascript
// 플레이어 보안 설정
const playerSecurity = {
  // 화면 보호
  screenLock: {
    enabled: true,
    pin: "1234",
    autoLockMinutes: 30
  },
  
  // 콘텐츠 보호
  contentProtection: {
    preventScreenshot: true,
    watermark: false,
    encryptedStorage: true
  },
  
  // 네트워크 보안
  network: {
    useHttps: true,
    certificateValidation: true,
    vpnOnly: false
  }
};

백업 및 복구 ​

백업 전략 ​

bash
#!/bin/bash
# Xibo CMS 백업 스크립트

# 데이터베이스 백업
mysqldump -u xibo -p xibo_db > /backup/xibo_db_$(date +%Y%m%d).sql

# 미디어 파일 백업
tar -czf /backup/xibo_media_$(date +%Y%m%d).tar.gz /var/www/xibo/library/

# 설정 파일 백업
cp -r /var/www/xibo/settings.php /backup/
cp -r /var/www/xibo/web/settings.php /backup/

# 오래된 백업 삭제 (30일 이상)
find /backup -mtime +30 -delete

복구 절차 ​

bash
# 데이터베이스 복구
mysql -u xibo -p xibo_db < /backup/xibo_db_20240101.sql

# 미디어 파일 복구
tar -xzf /backup/xibo_media_20240101.tar.gz -C /

# 권한 설정
chown -R www-data:www-data /var/www/xibo/
chmod -R 755 /var/www/xibo/

# 캐시 클리어
php /var/www/xibo/bin/xtr.php cache:clear

고급 기능 ​

대화형 콘텐츠 ​

html
<!-- 터치스크린 대화형 메뉴 -->
<div id="interactive-menu">
  <script>
    function showCategory(category) {
      // 카테고리별 콘텐츠 표시
      document.querySelectorAll('.category').forEach(el => {
        el.style.display = 'none';
      });
      document.getElementById(category).style.display = 'block';
      
      // Xibo에 이벤트 전송
      xiboIC.trigger('categorySelected', category);
    }
  </script>
  
  <button onclick="showCategory('food')">음식</button>
  <button onclick="showCategory('drinks')">음료</button>
  <button onclick="showCategory('desserts')">디저트</button>
  
  <div id="food" class="category">
    <!-- 음식 메뉴 -->
  </div>
</div>

데이터셋 활용 ​

sql
-- 동적 콘텐츠를 위한 데이터셋
CREATE TABLE product_info (
  id INT PRIMARY KEY,
  name VARCHAR(100),
  price DECIMAL(10,2),
  description TEXT,
  image_url VARCHAR(255),
  stock_quantity INT,
  promotion BOOLEAN
);

-- 실시간 업데이트 트리거
CREATE TRIGGER update_signage
AFTER UPDATE ON product_info
FOR EACH ROW
BEGIN
  -- Xibo API 호출하여 디스플레이 업데이트
  CALL xibo_update_dataset('product_display', NEW.id);
END;

맞춤형 위젯 개발 ​

javascript
// 커스텀 위젯 예제: 대기 번호 표시
class QueueDisplay extends XiboWidget {
  constructor(options) {
    super(options);
    this.queueAPI = options.queueAPI;
    this.updateInterval = options.updateInterval || 5000;
  }
  
  async render() {
    const queueData = await this.fetchQueueData();
    
    return `
      <div class="queue-display">
        <h1>현재 대기 번호</h1>
        <div class="current-number">${queueData.current}</div>
        <div class="waiting-count">대기: ${queueData.waiting}명</div>
        <div class="estimated-time">예상 대기 시간: ${queueData.estimatedTime}분</div>
      </div>
    `;
  }
  
  async fetchQueueData() {
    const response = await fetch(this.queueAPI);
    return response.json();
  }
  
  start() {
    this.interval = setInterval(() => {
      this.update();
    }, this.updateInterval);
  }
  
  stop() {
    clearInterval(this.interval);
  }
}

모범 사례 ​

콘텐츠 제작 가이드라인 ​

yaml
content_guidelines:
  visual:
    resolution: "1920x1080 (Full HD)"
    aspect_ratio: "16:9"
    file_format: "PNG, JPG (이미지), MP4 (비디오)"
    color_profile: "sRGB"
    
  text:
    font_size: "최소 24pt (원거리 시청)"
    contrast: "WCAG AA 기준 (4.5:1)"
    line_height: "1.5배"
    reading_time: "7초/화면"
    
  animation:
    duration: "5-10초"
    transition: "0.5초 이내"
    loop: "자연스러운 연결"
    
  audio:
    format: "MP3, AAC"
    bitrate: "128kbps 이상"
    volume: "정규화 (-16 LUFS)"

운영 체크리스트 ​

markdown
## 일일 점검
- [ ] 모든 디스플레이 온라인 상태 확인
- [ ] 콘텐츠 정상 재생 확인
- [ ] 오류 로그 확인
- [ ] 저장 공간 확인 (80% 미만)

## 주간 점검
- [ ] 콘텐츠 업데이트
- [ ] 스케줄 검토 및 수정
- [ ] 플레이어 소프트웨어 업데이트 확인
- [ ] 백업 실행

## 월간 점검
- [ ] 사용 통계 분석
- [ ] 하드웨어 점검 (먼지 제거 등)
- [ ] 보안 패치 적용
- [ ] 라이선스 갱신 확인 (클라우드 서비스 사용 시)

추가 리소스 ​

공식 문서 및 커뮤니티 ​

유용한 도구 ​

  • Xibo Layout Designer: 웹 기반 레이아웃 디자이너
  • Xibo API Postman Collection: API 테스트 도구
  • Xibo Android Management: MDM 솔루션
  • Content Creation Tools: Canva, Adobe Creative Suite

💡 Pro Tip

Xibo는 강력한 오픈소스 솔루션이지만, 초기 설정과 최적화가 중요합니다. 작은 규모로 시작하여 점진적으로 확장하는 것을 권장합니다.

⚠️ 주의사항

  • 정기적인 백업은 필수입니다
  • 네트워크 대역폭을 고려한 콘텐츠 크기 최적화
  • 디스플레이 하드웨어 사양에 맞는 콘텐츠 제작
  • 저작권이 있는 콘텐츠 사용 시 라이선스 확인

Released under the MIT License.