- 프로젝트 개요: 오픈소스 실시간 커뮤니케이션 서버 구축
최근 자가 호스팅 기반의 실시간 메시징 시스템을 구축하고자 하면서, 데이터 소유권과 기능 확장성 사이에서 균형을 찾기 위해 오픈소스 생태계를 조사했다. 그 과정에서
eagurin/synapse라는 프로젝트에 주목하게 되었다. 이는 유명한matrix-org/synapse프로젝트의 활발한 커뮤니티 분지로, 원본의 기능 완전성은 유지하면서도 성능 및 운영 효율성을 높인 버전이다.
Matrix 프로토콜은 중앙 집중식 서비스(예: Slack, Discord)의 데이터 비공개성, 사용자 맞춤 설정 제약, 장기 운영 비용 문제를 해결할 수 있는 대안으로 부상하고 있다. 이를 통해 각자가 자체 서버를 운영하고, 서로 다른 서버 간에 자유롭게 소통하는 연합형 네트워크를 구성할 수 있다. eagurin/synapse는 이러한 연합 메시징 인프라를 쉽게 구축할 수 있도록 도와주는 핵심 도구이며, 최적화 덕분에 경량화된 환경에서도 안정적으로 동작한다.
이 문서에서는 개인 또는 소규모 팀이 내부 커뮤니케이션 플랫폼, 게임 커뮤니티 채팅 시스템, 혹은 탈중앙화 커뮤니케이션 기술을 체험하고 싶은 경우에 적합한 실전 배포 방법을 단계별로 설명한다. 전체 과정은 Python, PostgreSQL, Redis, Docker 등 현대 백엔드 서비스에서 필수적인 기술 스택을 포함하며, 실습 중심의 접근을 통해 개념을 명확히 이해할 수 있다.
- 아키텍처 및 주요 최적화 요소 분석
2.1 Matrix 프로토콜과 Synapse의 역할 Matrix는 실시간 통신을 위한 오픈 표준 프로토콜로, 가장 큰 특징은 "연합성"(Federated)과 "호환성"이다. 연합성은 중앙 서버 없이도 누구나 자신의 서버(홈서버)를 운영할 수 있으며, 이들이 표준 프로토콜로 연결되어 거대한 커뮤니케이션 네트워크를 형성한다는 점이다. 호환성은 다양한 서비스(슬랙, IRC, 텔레그램 등) 간의 메시지 변환을 가능하게 하는 목표를 지닌다.
synapse는 이 프로토콜의 공식 참조 구현체로, 파이썬 기반의 홈서버 역할을 수행한다. 사용자 계정 관리, 채널 생성, 메시지 전달, 에디터 암호화, 그리고 다른 서버와의 연합 통신 등을 담당한다.
eagurin/synapse는 원본 synapse의 기능은 그대로 유지하면서도, 특히 메모리 사용량, 시작 속도, 리소스 효율성 측면에서 개선된 버전이다. 커뮤니티에서 지속적으로 제기되던 리소스 과잉 문제를 해결하기 위해, 주로 아래와 같은 방향으로 최적화가 이루어졌다.
2.2 주요 개선 사항
- 지연 로딩 및 의존성 최소화: 초기 모듈 로딩을 줄이고, 비핵심 컴포넌트를 지연 로딩하여 시작 시간 단축.
- 데이터베이스 쿼리 및 연결 풀 최적화: 고빈도 쿼리 재설계, 인덱스 조정, SQLAlchemy 연결 풀 설정 조정으로 성능 저하 완화.
- 메모리 사용 및 가비지 컬렉션 개선: 효율적인 데이터 구조 사용, 파이썬 가비지 컬렉션 정책 조정으로 메모리 피크 감소.
- 로그 출력 최소화: 생산 환경에서 불필요한 디버그 로그 제거, 디스크 I/O 및 성능 저하 방지.
- 경량화된 Docker 이미지 제공: 알파인 리눅스 기반 이미지, 미리 설정된 최적화 옵션 포함,
docker run한 줄로 바로 실행 가능.
⚠️ 주의사항: 커뮤니티 분지는 상위 저장소(
matrix-org/synapse) 업데이트를 꾸준히 반영해야 한다. 최근 병합 여부를 확인해 보안 패치 및 새로운 기능을 누락하지 않도록 해야 한다.
- 실전 배포: 최적화된 Synapse 서버 구축 절차 Ubuntu 22.04 LTS 환경에서 최신 도커 기반 배포를 예제로 설명한다.
3.1 기본 환경 설치
# 시스템 업데이트 및 도구 설치
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git vim
# Docker 설치 (공식 스크립트 사용)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
# Docker Compose 설치 (GitHub Release 사용)
DOCKER_COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep -Po '"tag_name": "\K.*?(?=")')
sudo curl -L "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 설치 검증
docker --version
docker-compose --version
3.2 Docker Compose 설정 파일 작성
프로젝트 폴더를 생성하고 docker-compose.yml 파일을 작성한다:
version: '3.8'
services:
postgres:
image: postgres:15-alpine
container_name: matrix-postgres
restart: unless-stopped
environment:
POSTGRES_USER: matrix_user
POSTGRES_PASSWORD: secure_db_password_here
POSTGRES_DB: matrix
POSTGRES_INITDB_ARGS: "--encoding='UTF8' --lc-collate='C' --lc-ctype='C'"
volumes:
- ./data/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U matrix_user"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: matrix-redis
restart: unless-stopped
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- ./data/redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
synapse:
image: eagurin/synapse:latest
container_name: matrix-server
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
ports:
- "8008:8008"
- "8448:8448"
environment:
SYNAPSE_SERVER_NAME: "your-domain.com"
SYNAPSE_REPORT_STATS: "no"
SYNAPSE_NO_TLS: "1"
POSTGRES_HOST: postgres
POSTGRES_USER: matrix_user
POSTGRES_PASSWORD: secure_db_password_here
POSTGRES_DB: matrix
REDIS_HOST: redis
volumes:
- ./data/synapse:/data
command: >
sh -c "
if [ ! -f /data/homeserver.yaml ]; then
python -m synapse.app.homeserver \
--server-name=$${SYNAPSE_SERVER_NAME} \
--config-path=/data/homeserver.yaml \
--generate-config \
--report-stats=$${SYNAPSE_REPORT_STATS};
echo '설정 파일 생성 완료. /data/homeserver.yaml을 수정 후 다시 시작하세요.';
exit 0;
else
python -m synapse.app.homeserver --config-path=/data/homeserver.yaml;
fi"
eagurin/synapse:latest이미지를 사용하며,SYNAPSE_NO_TLS: "1"로 외부 프록시에서 HTTPS 처리를 위임함.- 처음 실행 시 자동으로
homeserver.yaml생성 → 이후에는 해당 파일을 읽어 실행. - Postgres와 Redis는 상태 체크를 통해 의존성 관리.
3.3 설정 파일 생성 및 수정
cd ~/matrix-docker
docker-compose up -d postgres redis
docker-compose up synapse # 첫 번째 실행
실행 후, ./data/synapse/homeserver.yaml 파일을 열어 다음과 같이 수정:
server_name: "your-domain.com"
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
bind_addresses: ['::']
resources:
- names: [client, federation]
compress: false
database:
name: psycopg2
args:
user: matrix_user
password: secure_db_password_here
database: matrix
host: postgres
cp_min: 5
cp_max: 10
redis:
enabled: true
host: redis
port: 6379
log_config: "/data/your-domain.com.log.config"
media_store_path: /data/media_store
enable_registration: false
# registration_shared_secret: "secret_key"
admin_contact: 'mailto:admin@your-domain.com'
설정 완료 후, 모든 서비스를 백그라운드로 시작:
docker-compose down
docker-compose up -d
docker-compose logs -f synapse
- 역방향 프록시 및 도메인 설정
4.1 Nginx를 통한 HTTPS 프록시 구성
Let’s Encrypt 인증서를 사용하는 경우, /etc/nginx/sites-available/matrix 파일 생성:
server {
listen 80;
server_name your-domain.com;
location / {
return 301 https://$server_name$request_uri;
}
location /.well-known/acme-challenge/ {
root /var/www/html;
}
}
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location / {
proxy_pass http://localhost:8008;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
client_max_body_size 50M;
proxy_read_timeout 300s;
}
}
sudo ln -s /etc/nginx/sites-available/matrix /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
4.2 연합 서비스 발견 설정
https://your-domain.com/.well-known/matrix/server 접근 시 다음 JSON 응답이 반환되어야 함:
{
"m.server": "your-domain.com:443"
}
이 설정은 다른 서버가 당신의 서버에 연결할 수 있도록 합니다.
- 운영 관리 및 성능 최적화
5.1 사용자 관리 및 작업 명령어
# 새 사용자 등록 (공개 등록 비활성화 시)
docker exec -it matrix-server register_new_matrix_user http://localhost:8008 -c /data/homeserver.yaml
# 비밀번호 해시 생성
docker exec -it matrix-server hash_password -c /data/homeserver.yaml
# 서버 상태 확인
docker exec matrix-server python -m synapse.app.admin.notifications -c /data/homeserver.yaml
5.2 백업 전략
간단한 백업 스크립트 (backup.sh):
#!/bin/bash
BACKUP_DIR="/backups/matrix"
DATE=$(date +%Y%m%d_%H%M%S)
# DB 백업
docker exec matrix-postgres pg_dump -U matrix_user matrix | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# 데이터 볼륨 백업
tar -czf $BACKUP_DIR/data_$DATE.tar.gz -C ~/matrix-docker/data .
# 7일 이상 된 백업 삭제
find $BACKUP_DIR -name "*.gz" -type f -mtime +7 -delete
실행 권한 부여 후 crontab에 등록.
5.3 모니터링 및 성능 조정
docker stats로 메모리, CPU 사용률 확인.cp_max값이 자주 포화되는지 확인 → 필요 시 증가.prometheus와grafana연동으로 메트릭 수집 및 시각화 권장.rc_message,rc_registration등의 제한 설정으로 서비스 과부하 방지.
- 일반적인 오류 및 진단 팁
6.1 연합 연결 실패
dig your-domain.com으로 DNS 확인.curl https://your-domain.com/.well-known/matrix/server결과 확인.ufw status로 443, 8448 포트 개방 여부 확인.- federationtester.matrix.org에서 진단.
6.2 클라이언트 연결 불가
- Element 클라이언트에서
https://your-domain.com입력. - Nginx
proxy_read_timeout,client_max_body_size조정 필요. - 메모리 부족 시,
eagurin/synapse최신 버전으로 업그레이드.
6.3 미디어 업로드 실패
- 디스크 공간 확인 (
df -h). media_store디렉터리 권한 조정 (chown -R 991:991).- S3와 연동을 고려하면 장기적으로 더 효율적.
6.4 이미지 업그레이드
docker-compose pull synapse
docker-compose up -d --no-deps synapse
업그레이드 전 반드시 백업 수행.