Baby Monitor Timmy는 집 안의 프라이버시를 존중하는 베이비 모니터라는 단순한 생각에서 시작했습니다. 클라우드 녹화도, 아기방 밖으로 나가는 불필요한 데이터 경로도 없습니다. 많은 분이 잘 모르시는 점은, 제가 취리히에서 Timmy를 혼자 개발하고 있으며 GitHub Copilot 은 아주 빠른 제 페어 프로그래머라는 것입니다.
사람과 AI의 작업 방식
역할은 분명합니다. 기능을 정의하고, 우선순위를 정하며, 아키텍처 결정을 내리는 것은 제 몫입니다. Copilot은 코드 작성, 테스트 추가, 버그 범위 좁히기, 출시 단계 준비처럼 구현을 돕습니다.
제가 진행하는 일반적인 스프린트는 대략 이렇습니다.
- 기능 설명: 예외 상황과 제약 조건을 포함해 기능이 무엇을 해야 하는지 설명합니다.
- 구현: Copilot이 코드를 제안하고 프로젝트의 기존 규칙을 따릅니다.
- 테스트: 자동화된 엔드투엔드 테스트가 두 에뮬레이터에서 실행되어 실제 아기 기기와 부모 기기 연결을 확인합니다.
- 배포: 테스트를 통과하면 Android와 iOS 빌드를 알맞은 스토어 및 테스트 트랙에 맞춰 준비합니다.
이 과정은 기능 개발과 버그 수정 때마다 반복됩니다. 모든 줄의 코드를 제가 직접 쓰지는 않지만, 무엇을 만들지, 왜 만드는지, 그리고 제안이 Timmy에 맞는지는 제가 결정합니다.
콘셉트에서 WebRTC까지
핵심 기술 과제는 처음부터 분명했습니다. 두 휴대폰 사이의 실시간 오디오와 영상입니다. WebRTC가 당연한 선택이었지만 Flutter에 통합하는 일은 간단하지 않습니다. ICE 후보, SDP 협상, TURN 폴백, DataChannel이 올바른 순서로 함께 작동해야 합니다.
Copilot은 이 요소들을 단계별로 연결하는 데 도움을 줬습니다. 피어 연결을 설정하고, 중요한 순서(DataChannel은 offer 전에, onTrack은 setRemoteDescription 전에)를 지키며, Firebase Firestore에 시그널링을 구현했습니다. 다음 단계로 넘어가기 전에는 모든 요소를 두 에뮬레이터에서 실행해야 했습니다.
ECDH를 이용한 안전한 페어링
가장 중요한 기능 중 하나는 안전한 페어링 시스템입니다. 두 기기는 중앙 서버가 서로의 신원을 보증하지 않아도 상호 신뢰를 형성해야 합니다. 해결책은 Firebase를 통한 ECDH P-256 키 교환과 중간자 공격을 감지하는 시각적 확인 번호(SAS)를 결합하는 것이었습니다.
Copilot은 키 생성, 공개 키 교환, 공유 비밀 도출, SAS 계산, 이후 모든 시그널링 데이터에 적용하는 AES-256-GCM 암호화로 이어지는 암호화 과정을 구현하는 데 도움을 줬습니다. 페어링 키 자체는 백엔드로 보내지 않으며, SHA-256 해시만 Firestore 문서 식별자로 사용합니다.
보안 감사: 취약점 찾기와 수정
AI 지원 개발은 제게 단지 타이핑을 빠르게 하는 일이 아닙니다. 체계적으로 버그를 찾는 데도 도움이 됩니다. 집중 보안 감사 스프린트에서 Copilot은 코드베이스를 분석해 제가 수정해야 할 6가지 문제 를 찾아냈습니다.
- 시그널링 데이터의 입력 검증 누락
- ICE 후보 처리 과정에서 발생할 수 있는 경쟁 상태
- 제대로 정리되지 않는 오래된 세션 데이터
- 너무 허용적인 Firestore 보안 규칙
- 인증서 피닝 고려 사항 누락
- TURN 자격 증명 흐름의 불충분한 오류 처리
6가지 모두 같은 스프린트에서 수정했습니다. Copilot이 강점을 보이는 부분이 바로 여기입니다. 많은 파일을 읽고, 패턴을 비교하며, 제가 더 자세히 살펴봐야 할 곳을 표시해 줍니다.
반복 스프린트: 앱이 발전한 과정
Timmy는 빠르면서도 범위가 명확한 스프린트를 거치며 성장했습니다. 주요 변경 사항은 다음과 같습니다.
- v1.8: 페어링 전면 개편 — Firebase를 통한 4자리 코드 + ECDH P-256 방식으로 기존 직접 키 방식이 대체되었습니다.
- v1.10: 보안 강화 스프린트 — 6개 취약점 감사 및 수정 과정입니다.
- v1.11: 모든 화면의 다크 모드와, 지금 읽고 계신 홈페이지 및 블로그를 추가했습니다.
- v1.12: 부모 기기 화면을 대폭 개선하고, 야간 모드와 카메라 프레임 분석 기반 움직임 감지 기능을 추가했습니다.
모든 스프린트는 같은 기본 흐름을 따릅니다. 목표를 설명하고, 제안을 검토하고, 자동 테스트를 거친 뒤 테스터에게 배포합니다.
기기 간 E2E 테스트
베이비 모니터는 한 기기만으로 제대로 테스트할 수 없습니다. 아기 기기 하나와 부모 기기 하나가 필요합니다. 프로젝트는 두 대의 Android 에뮬레이터를 동시에 실행하는 방식으로 시작했고, 이제는 로컬 iOS 시뮬레이터 및 실제 기기 점검도 이 과정에 더했습니다. 자동화된 Android 테스트 스크립트는 여전히 다음을 수행합니다.
- 두 에뮬레이터에 앱 설치
- 두 기기에서 페어링 과정 진행
- 오디오와 영상 연결이 설정되었는지 확인
- 푸시투토크, 카메라 제어 및 기타 기능 테스트
두 에뮬레이터가 같은 IP 주소를 공유하므로 (10.0.2.15), STUN을 통한 직접 피어 투 피어 연결은 불가능합니다. 모든 테스트 실행은 Cloudflare TURN 릴레이를 거쳐야 합니다. 번거롭지만 유용합니다. 가장 복잡한 연결 경로를 매번 테스트하기 때문입니다.
배운 점
AI 페어 프로그래머와 함께 앱 하나를 온전히 만들며 몇 가지를 배웠습니다.
- 아키텍처는 그 어느 때보다 중요합니다. 명확한 규칙과 잘 문서화된 코드베이스는 AI가 일관된 코드를 제안하도록 돕습니다. 모호함은 금세 큰 비용으로 돌아옵니다.
- 테스트는 타협할 수 없습니다. AI가 생성한 코드도 사람이 작성한 코드와 똑같이 엄격한 테스트가 필요합니다. 자동화된 E2E 테스트는 수동으로는 놓치기 쉬운 문제를 찾아냈습니다.
- 사람은 과정에 계속 참여해야 합니다. 모든 아키텍처 결정, 모든 보안상 절충, 모든 제품의 경계는 제 책임입니다. AI는 구현 속도를 높이지만 판단을 대신하지는 않습니다.
- 속도는 품질을 가능하게 합니다. 기능을 며칠이 아닌 몇 시간 만에 출시할 수 있기에, 완성도를 다듬고 버그를 수정할 반복 작업을 더 많이 할 수 있습니다. 빠르다고 해서 자동으로 좋은 것은 아닙니다.
앞으로
Baby Monitor Timmy는 계속 발전하고 있습니다. iOS 출시가 임박했으며, 그다음에는 추가 센서 기능과 지속적인 보안 강화가 이어집니다. 작업 방식은 비슷하게 유지됩니다. 저는 방향과 경계를 정하고, Copilot은 빠른 구현과 점검을 돕습니다.
보안과 관련된 핵심 구성 요소는 이제 명확한 경계 를 갖춘 공개 baby-monitor-timmy-core 저장소에 있습니다. 페어링, 시그널링, 백엔드 인터페이스에 관한 아키텍처 결정도 그곳에 문서화되어 있습니다.