카카오톡처럼 편리하지만, 모든 데이터는 내 집 NAS에 안전하게 보관되는 크로스플랫폼 메신저 만들기 프로젝트
모바일(Android, iOS)부터 데스크톱(Windows, macOS)까지 코드 하나로 개발하고, 집에 있는 Ugreen NAS(Docker)를 백엔드 서버로 구축하는 전체적인 아키텍처와 로드맵을 공유합니다.
1. 프로젝트를 시작하게 된 계기
가족들과 친구들이 매일 사용하는 메신저 앱. 카카오톡이나 라인처럼 친숙하고 편리하지만, 아래와 같은 아쉬움이나 고민이 있었습니다:
- 데이터 주권과 프라이버시: 가족들의 사진, 일상 대화, 소중한 파일들을 외부 클라우드가 아닌 우리 집 NAS에 안전하게 보관하고 싶다.
- 크로스플랫폼 지원: 부모님 스마트폰(Android/iOS)은 물론, 일할 때 쓰는 컴퓨터(Windows, Mac)에서도 매끄럽게 돌아가야 한다.
- 가족 친화적인 쉬운 사용성: QR 코드 같은 번거로운 인증 대신, 카톡 링크 전송이나 휴대전화 연락처로 쉽게 초대할 수 있어야 한다.
그래서 집에서 24시간 가동 중인 유그린(Ugreen) NAS를 개인 서버로 활용하고, Flutter로 4개 OS를 모두 지원하는 프라이빗 메신저 ‘딩동(DingDong)’ 프로젝트를 시작하게 되었습니다.
2. 우리가 만들 핵심 기능 (Feature Scope)
- 💬 실시간 1:1 및 가족 그룹 채팅: 카카오톡처럼 안 읽은 인원 수(노란 숫자 1) 표시 및 실시간 읽음 처리
- 📞 1:1 보이스톡(음성 통화): WebRTC 기반 고음질 음성 통화 (잠금화면에서도 일반 전화처럼 수신)
- 📷 사진 및 대용량 파일 전송: 네트워크가 끊겨도 이어서 올릴 수 있는 안정적인 업로드, 내 NAS 하드디스크에 원본 영구 저장
- 🔗 초간단 친구/가족 초대: 카카오톡이나 문자로 원클릭 링크 공유, 내 폰 주소록(연락처) 기반 친구 매칭
- 🖥️ PC 멀티 디바이스 로그인: 모바일 앱에서 한 번의 승인으로 데스크톱 앱 간편 로그인
3. 전체 시스템 아키텍처
클라우드 비용을 매달 내지 않고, 안정적이면서도 유지보수가 쉬운 구성을 목표로 설계했습니다.
flowchart TB
subgraph Clients["클라이언트 (Flutter 단일 코드베이스)"]
A[Android 스마트폰]
I[iPhone / iPad]
M[Mac 데스크톱]
W[Windows PC]
end
subgraph Internet["외부 서비스 (푸시 전용)"]
FCM["Google FCM (안드로이드 푸시)"]
APNS["Apple APNs (아이폰 VoIP/푸시)"]
end
subgraph HomeNAS["우리 집 유그린 NAS (Docker Compose)"]
CADDY["Caddy 웹서버 (HTTPS / WSS 자동 SSL)"]
API["NestJS API 서버 (REST + WebSocket)"]
PG[(PostgreSQL DB - 대화/회원 정보)]
RD[(Redis - 접속상태 / 작업 큐)]
FILES[("NAS HDD 볼륨 - 사진/파일 원본")]
LK["LiveKit 서버 (WebRTC 음성 통화 중계)"]
end
Clients -->|HTTPS / WSS 실시간 접속| CADDY
CADDY --> API
API --> PG & RD & FILES
Clients <-->|WebRTC 음성 스트림| LK
API -.->|백그라운드 알림 전송| FCM & APNS
FCM & APNS -.->|앱 깨우기| Clients
linkStyle default stroke-width:3px,stroke:#333333왜 이 기술들을 선택했을까요?
| 계층 | 선택한 기술 | 선택 이유 (초보 개발자 팁) |
|---|---|---|
| 앱 클라이언트 | Flutter (Dart) | 코드 1개로 Android, iOS, Windows, macOS 4개 플랫폼 앱이 모두 나옵니다. UI 컴포넌트가 OS에 구애받지 않고 카톡과 똑같이 그려집니다. |
| 로컬 캐시 DB | Drift (SQLite) | “오프라인 우선” 구조를 위해 필수입니다. 집 인터넷이나 NAS가 잠시 끊겨도 앱에서 이전 대화를 즉시 볼 수 있고, 오프라인 작성 후 재연결 시 자동 전송됩니다. |
| 백엔드 서버 | NestJS (TypeScript) | Node.js 생태계에서 가장 구조화가 잘 되어 있고, 실시간 WebSocket 게이트웨이 및 LiveKit 연동이 매우 쉽습니다. |
| 데이터베이스 | PostgreSQL 16 | 안정성과 트랜잭션 보장이 뛰어납니다. 대화 순번(seq)을 매겨 메시지 유실 없는 동기화를 구현하기에 최적입니다. |
| 캐시 / 큐 | Redis + BullMQ | 사용자의 현재 접속 여부(Presence) 체크와 백그라운드 푸시 알림 발송 큐를 가볍게 처리합니다. |
| 음성 통화 | LiveKit (Self-hosted) | WebRTC 기반 오픈소스 통화 서버입니다. 복잡한 P2P 통신이나 TURN 서버 설정 없이, Docker 컨테이너 하나로 깔끔하게 음성 통화 인프라가 해결됩니다. |
| 리버스 프록시 | Caddy | Nginx보다 설정이 10배 간단하며, 도메인만 적어두면 무료 Let’s Encrypt SSL 인증서(HTTPS)를 알아서 발급/갱신해 줍니다. |
4. 핵심 기술 포인트 & 구현 꿀팁
① 실시간 채팅과 “안 읽은 숫자 1” 처리
- 방별 순번(Seq) 방식: 기기 시계 차이로 인한 메시지 순서 꼬임을 방지하기 위해, 서버에서 방마다 1, 2, 3… 형태로
seq번호를 부여합니다. - 가벼운 읽음 계산: 메시지마다 “누가 읽었는지” 리스트를 저장하면 서버에 부하가 큽니다. 대신 **”각 멤버가 마지막으로 읽은 순번(Last Read Seq)”**만 기록하여,
현재 순번 - 내가 읽은 순번으로 안 읽은 개수를 가볍게 계산합니다.
② 가족과 친구를 편하게 초대하는 방법
- 카톡/문자 원클릭 링크: 앱 내 [초대하기]를 누르면 카톡 공유창이 떠서 바로 초대 링크가 전송됩니다. 링크 클릭 시 설치 안내 및 딥링크를 통해 가입 즉시 친구로 연결됩니다.
- 연락처(주소록) 매칭: 내 폰 주소록의 전화번호를 안전하게 단방향 암호화(SHA-256 해시)하여 서버와 대조합니다. 이미 가입된 가족은 바로 추가하고, 미가입된 가족은 문자 초대장을 보낼 수 있습니다.
③ 유그린 NAS(집 서버) 환경에 맞춘 최적화
- HDD 수면 모드 방지: NAS의 하드디스크가 절전 모드에 들어가면 첫 메시지 반응이 몇 초 느려질 수 있습니다. 따라서 DB와 Docker 컨테이너는 NVMe SSD 볼륨에 두고, 용량이 큰 사진/파일 원본만 대용량 HDD 볼륨에 저장하도록 분리했습니다.
- Docker Compose 배포: 모든 서버 환경이
docker-compose.yml파일 하나로 관리되므로, NAS를 교체하거나 다른 PC로 이전할 때도 명령어 한 줄로 복구할 수 있습니다.
5. 앞으로의 개발 로드맵
앞으로 실제 코드를 작성하고 기능을 완성해 나갈 단계별 계획입니다:
- [1단계] NAS 환경 셋업 & 기술 검증: Caddy + NestJS + PostgreSQL + LiveKit을 NAS Docker에 올리고, 외부(LTE) 접속 및 통화 테스트
- [2단계] 기본 로그인 & 친구 추가: 초대 링크 공유 및 주소록 매칭 기능 구현
- [3단계] 실시간 문자 채팅 완성: 오프라인 로컬 저장, WebSocket 실시간 전송, 안 읽은 숫자 카운팅
- [4단계] 사진/대용량 파일 전송 & 푸시 알림: 이어올리기(Tus) 프로토콜 및 모바일 푸시 알림 연동
- [5단계] 보이스톡(음성 통화): LiveKit 연동 및 스마트폰 잠금화면 수신 UI(CallKit) 연동
- [6단계] 데스크톱(Windows/Mac) 최적화 & 가족 실사용 테스트
6. 다음 편 예고
다음 글에서는 Mac에서 Flutter & VS Code 개발 환경 구축하기를 다루겠습니다.
메신저 개발이나 개인 NAS를 활용한 셀프 호스팅에 관심 있으신 분들은 다음 편도 기대해 주세요! 궁금한 점이 있으시다면 언제든 댓글로 남겨주세요.
📂 Part 1. 기획 & 아키텍처 설계
- ✅ [개발일지 #01 | 기획] 유그린 NAS와 Flutter로 만드는 나만의 프라이빗 메신저 ‘딩동’ (기획 & 아키텍처 편)
📂 Part 2. 홈서버 & 인프라 구축 (UGREEN + Synology)
- ✅ [개발일지 #02 | 인프라] Mac에서 Flutter & VS Code 개발 환경 구축하기 (초보자 완벽 가이드)
- ✅ [개발일지 #03 | 인프라] 유그린 NAS에 Caddy & PostgreSQL 구축하기 (홈서버 443 포트 충돌 해결 꿀팁 포함)
📂 Part 3. 백엔드(API) & 실시간 통화 서버
- ✅ [개발일지 #04 | 백엔드] 유그린 NAS에 Go(Golang) 초경량 메신저 백엔드 서버 구축하기
- ⏳ [#05 | 백엔드] JWT 기반 가족 인증 및 실시간 WebSocket 채팅 구현 (예정)
- ⏳ [#06 | 통화] LiveKit 연동으로 무료 음성/영상 통화 서버 구축하기 (예정)
📂 Part 4. 모바일 앱 개발 (iOS / Android)
- ⏳ [#07 | 앱-공통] 모바일 앱 프로젝트 생성 및 로그인/채팅방 UI 구현 (예정)
- ⏳ [#08 | 앱-공통] 300MB 대용량 원본 사진/영상 전송 및 미디어 처리 (예정)
- ⏳ [#09 | 앱-푸시] 앱이 꺼져 있어도 울리는 푸시 알림(FCM/APNs) 연동 (예정)
📂 Part 5. 정식 배포 & 운영
- ⏳ [#10 | 배포] 백엔드 서버 도커 이미지 빌드 및 유그린 NAS 정식 배포 (예정)
- ⏳ [#11 | 운영] DB 자동 백업 스크립트 구성 및 가족 실사용 후기 (예정)