스마트홈 IoT

프로젝트 소개


본 프로젝트는 스마트홈 대시보드와 라즈베리파이 기반 AI 스피커를 결합하여, 사용자가 직관적이고 통합된 환경에서 IoT 기기를 관리할 수 있는 솔루션을 제공합니다. 웹 기반 대시보드를 통해 실시간 상태 모니터링 및 제어가 가능하며, 라즈베리파이에 구현된 AI 스피커를 통해 음성 명령으로 간단한 기능을 수행할 수 있습니다. 이를 통해 사용자는 집 안의 다양한 스마트 기기를 일원화된 인터페이스로 관리하고, 음성 제어를 통한 편리성을 더해 보다 직관적이고 효율적인 스마트홈 경험을 누릴 수 있습니다.

프로젝트 기획


  1. 개발 환경 및 도구 선정: Raspberry Pi, 오픈소스 음성 인식 엔진, 웹 프레임워크(React, Vue, 또는 단순 HTML/CSS/JS)와 IoT 디바이스 SDK를 활용하여 구현 범위를 확정했습니다.
  1. 시스템 아키텍처 설계: IoT 기기 상태를 수집하고 제어하는 백엔드 서버, 사용자 친화적인 프런트엔드 대시보드, 음성 명령 처리 모듈(음성 인식, 명령 해석, 기기 제어)로 구성된 구조를 수립했습니다.
  1. 프로토타입 개발 및 테스트: 기본적인 조명 온/오프, 온도 조회 등 핵심 기능을 우선 구현한 뒤, 테스트를 통해 성능과 안정성을 검증하였습니다.
  1. 사용자 피드백 반영 및 개선: 실 사용자 테스트를 거쳐 UI 개선, 음성 명령 정확도 향상 등을 진행하였습니다.

프로젝트 결과


인프라


이번 프로젝트의 인프라는 높은 처리 성능을 요구하는 AI 연산을 담당하고, IoT 대시보드를 호스팅 하는 메인 서버와 메시지 브로커 기능을 수행하는 Raspberry Pi로 구성합니다. 먼저 메인 서버는 Intel Xeon Scalable CPU와 Nvidia Titan Xp GPU 3대를 탑재해, 대규모 병렬 연산에 적합한 환경을 갖추었습니다. 이 서버에는 가상화 플랫폼 Proxmox를 설치하여 VM과 LXC를 동시에 운영할 수 있도록 하였으며, Proxmox 상에서 Ubuntu 24.04 LTS 기반 가상 머신(VM)을 생성한 뒤, Passthrough 방식으로 GPU 자원을 직접 연결해 Nvidia Docker 컨테이너가 GPU 연산을 직접 활용할 수 있게 했습니다. 이를 통해 음성 인식이나 딥러닝 추론 등 고부하 AI 처리를 효율적으로 수행합니다.

서버 환경과 함께, 현장에서 실제 음성 데이터를 수집하고 브로커 역할을 수행할 Raspberry Pi 3에는 Raspberry Pi OS를 설치하였습니다. 라즈베리 파이는 프로세싱 성능이 제한적이므로, 초기에는 On-Device AI 방식을 시도하려 했으나 실사용 시 성능이 부족하다고 판단하여, AI 연산은 서버로 모두 위임하고 라즈베리 파이는 메시지 브로커(MQTT) 및 간단한 호출어만 처리하도록 구조를 바꾸었습니다. 이로써 서버와 라즈베리 파이가 각각 고유한 역할에 집중하면서, 확장성과 안정성을 동시에 확보할 수 있었습니다. 특히 라즈베리 파이의 역할이 명확해짐으로써, 필요 시 추가 디바이스 연동이 쉽도록 설계했습니다. 또한 이러한 서버-엣지 분산 구조 덕분에 네트워크가 안정적이라면 대규모 확장도 가능하며, 파이가 여러 대인 경우에도 서로 겹치지 않는 고유 역할을 분담해 운영할 수 있습니다.

AI스피커


AI 스피커 부문은 실제 사용자가 가장 가까이서 체감하는 부분으로, 정확하고 빠른 음성 인식 및 자연스러운 피드백이 핵심 목표였습니다. 이를 위해 “nefus”라는 호출어를 Kitt-AI의 Snowboy로 학습하여, 라즈베리 파이의 마이크가 해당 호출어를 인식하면 즉시 이벤트를 발생시키도록 구성합니다. Snowboy 라이브러리는 비교적 가벼우면서 맞춤형 트리거 단어를 손쉽게 등록할 수 있어, 커스텀 호출어를 사용하기에 적합합니다. 호출어가 검출되면, Hermes MQTT 프로토콜을 통해 음성 데이터를 서버 측으로 전송하고, 서버는 Rhasspy에서 받아 명령어를 이해한 뒤 결과를 MQTT 메시지로 되돌려줍니다.

이후 라즈베리 파이는 해당 결과에 따라 다양한 후속 동작을 수행합니다. 예를 들어, 사용자가 “nefus, 불 꺼줘”라고 명령하면, 서버가 이를 해석하여 조명 기기에 MQTT 혹은 Zigbee 명령을 보내고, 실제로 불이 꺼지면 완료 신호를 다시 파이에 보내게 됩니다. 파이는 aplay를 통해 완료 알림음을 재생함으로써 사용자가 요청이 정상 처리되었음을 즉각 확인할 수 있도록 합니다. 이렇게 분업화된 구조 덕분에 라즈베리 파이는 최대한 가벼운 작업(호출어 감지, 음성 송신, 알림음 출력)만 담당하고, 무거운 AI 연산이나 STT/TTS 처리는 서버에서 수행하여 인식의 정확도와 속도를 모두 높였습니다. 추후 Snowboy 대신 다른 키워드 스폿팅(Hotword Detection) 모델을 적용하거나, Rhasspy를 다른 STT 엔진과 연동하는 등 커스터마이징이 가능하므로, 유연한 유지보수가 가능합니다.

IoT 대시보드


스마트 홈 환경에서 음성 명령 외에도 직관적인 시각화와 제어 및 모니터링이 가능하도록 IoT 대시보드를 마련하였습니다. AI 스피커용 서버를 그대로 활용하여, 동일한 Proxmox 환경 내에 Ubuntu 22.04 LTS 기반 LXC 컨테이너를 하나 더 생성하고, 이 컨테이너 안에 Node.js나 Flask 등으로 작성된 웹 대시보드를 호스팅합니다. 이 대시보드는 Zigbee, MQTT, 그리고 각종 API 연동을 통해 온도 센서, 조명, 스위치, 에어컨 같은 다양한 IoT 기기의 상태를 실시간으로 수집하고 표시합니다. 또 사용자 인터페이스를 통해 기기를 직접 켜고 끄거나, 특정 시나리오(예: 귀가 모드, 취침 모드 등)를 실행할 수 있도록 구현합니다.

호스팅을 위해, 라우터에서 80, 443 TCP 인바운드 규칙을 생성하여, 외부에서 들어오는 연결이 HAProxy로 전달되도록 설정했습니다.

외부 접속을 안전하게 지원하기 위해, Cloudflare DNS와 HAProxy를 연동하여 도메인 접근과 SSL 인증서를 관리합니다. HAProxy를 이용해 443 포트(HTTPS)로 들어오는 트래픽을 LXC 컨테이너의 웹 서버로 라우팅하고, Let’s Encrypt 인증서를 적용하여 암호화 통신을 보장합니다. /etc/letsencrypt/renewal/leeyoonho.com.conf 파일을 통해 인증서 자동 갱신을 설정했으며, crontab에 스크립트를 등록하여 주기적으로 인증서 만료를 점검하고 필요한 경우 자동으로 갱신을 수행합니다. 이렇게 구축된 https://ha.leeyoonho.com 에 접속하면, 로그인 후 대시보드에 진입할 수 있고, 실시간 기기 상태 모니터링 및 제어가 가능합니다. 특히 이 대시보드는 고정 PC뿐 아니라 모바일 환경에서도 접근 가능하도록 반응형 웹 디자인을 적용하여 사용 편의성을 높였습니다.

ha.leeyoonho.com에 로그인 한 모습

아래는 haproxy에 사용된 haproxy.cfg와 ssl 인증서를 관리하는 leeyoonho.com.conf 파일입니다.

#/etc/haproxy/haproxy.cfg
global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

		# Default SSL material locations
    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\
ECDHE-ECDSA-CHACHA20_POLY1305:ECDHE-RSA-CHACHA20_POLY1305:\
DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:\
TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    log global
    mode http
    option httplog
    option dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

# stats 페이지 (HAProxy 모니터링)
frontend stats
    bind *:8404
    stats enable
    stats uri /
    stats realm Haproxy\ Statistics
    stats refresh 10s

# 대시보드 HTTPS 프론트엔드
frontend Dashboard
    bind *:443 ssl crt /etc/letsencrypt/live/leeyoonho.com/haproxy.pem crt /etc/letsencrypt/live/nexsyslab.com/haproxy.pem
    default_backend default

acl valid_domains hdr(host) -i ha.leeyoonho.com
use_backend dashboard if { hdr(host) -i ha.leeyoonho.com }

# 기본 백엔드 (기타 백엔드들은 모두 제거)
backend default
    server main 192.168.0.100:497 check ssl verify none

backend ha
	redirect scheme https unless { ssl_fc }
	server ha 192.168.0.103:8123 check
#/etc/letsencrypt/renewal/leeyoonho.com.conf

# renew_before_expiry = 30 days
version = 2.9.0
archive_dir = /etc/letsencrypt/archive/leeyoonho.com
cert = /etc/letsencrypt/live/leeyoonho.com/cert.pem
privkey = /etc/letsencrypt/live/leeyoonho.com/privkey.pem
chain = /etc/letsencrypt/live/leeyoonho.com/chain.pem
fullchain = /etc/letsencrypt/live/leeyoonho.com/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = 1bf58625ec2de34efb1a588326578ea7
authenticator = dns-cloudflare
dns_cloudflare_credentials = /etc/letsencrypt/cloudflare.ini
server = https://acme-v02.api.letsencrypt.org/directory
key_type = ecdsa

시스템 모니터링 대시보드


서비스를 효율적이고 안정적으로 모니터링하기 위해, Proxmox의 매트릭 정보를 수집하는 PVE Exporter와 Prometheus, Grafana를 활용하여 리소스 모니터링 대시보드를 제작했습니다. Public Dashboard는 https://ls.leeyoonho.com/grafana 에서 확인 가능합니다.

시연


이미지 1

이미지 2
이미지 3
이미지 4
이미지 5
이미지 6