11 KiB
작업 플랜
- UUID:
7aaa0cce-3da2-4ae4-8eda-c956e96c5af3 - 작업자:
Codex - 생성 시각:
2026-06-02 16:41 - 요청 요약:
README와 필수 문서를 읽고 server 작업을 이어받을 준비
할 일
- 현재 요청 확인
- README와 협업 규칙 확인
- 저장소 상태와 작업 범위 확인
- server 관련 문서와 이전 플랜 확인
- server 구현 상태와 로컬 빌드 준비 상태 확인
- 이어받을 작업 지점 정리
범위
- 이번 준비 작업은
server/,docs/,plans/맥락 확인에 집중합니다. client/작업영역은 수정하지 않습니다.- 사용자가 서버 구현 계획을 확정하고 실행을 지시하기 전까지 코드 변경은 하지 않습니다.
현재 확인 내용
- 현재 브랜치:
main - 작업 시작 시점의 Git 변경사항:
.DS_Storeuntracked - 이전 server 작업은
Homebrew + CMake + miniaudio기준의 C++ 서버 구현을 추가한 상태입니다. - 이전 기록상 빌드 검증은 도구 부재로 완료되지 않았습니다.
- 현재 환경에는
/usr/bin/c++가 있지만cmake명령은 PATH에서 확인되지 않았습니다. - Homebrew는
/opt/homebrew에 있으나cmake와miniaudio의 실제 설치 파일은/opt/homebrew/Cellar와/opt/homebrew/opt에서 확인되지 않았습니다. - 따라서 server 작업의 다음 지점은 Homebrew로
cmake miniaudio를 준비한 뒤server빌드 검증을 수행하는 것입니다.
완료 요약
- 필수 문서, server 방향 문서, server README, 이전 작업 플랜을 확인했습니다.
client/작업영역은 수정하지 않았습니다.- 이번 준비 과정에서 추가한 파일은 이 플랜 파일뿐입니다.
- 코드 수정 없이 server 이어받기 지점을 정리했습니다.
추가 진행 기록
- 사용자 요청에 따라 Homebrew로
cmake 4.3.3과miniaudio 0.11.25를 설치했습니다. - 설치 및 Homebrew 자동 cleanup 기록을
docs/99-mac.md에 추가했습니다. miniaudio.h가/opt/homebrew/opt/miniaudio/include/miniaudio/miniaudio.h에 있어MINIAUDIO_INCLUDE_DIR를 명시해 server CMake configure를 수행했습니다.cmake --build server/build로server/build/mic_server빌드 성공을 확인했습니다.- client 없이
server/build/mic_server server/server.conf.example를 실행해 오디오 장치 초기화와 UDP4860바인딩을 확인했습니다. - localhost에서 서버 지정 56바이트
MIC1헤더와 960바이트 무음 PCM payload를 가진 테스트 UDP 패킷 100개를 보내 수신 처리를 확인했습니다. - 서버 로그에서
sender_id=1,packets=100,dropped=0,out_of_order=0을 확인했습니다. SIGTERM후recvfrom대기를 깨우기 위해 빈 UDP 패킷 하나를 보내Server stopped정상 종료를 확인했습니다.- 사용자와 논의해 목표 송신기 규모를 최소 2대, 최대 16대로 조정했습니다.
docs/03-server-direction.md와server/README.md에 첫 bring-up은 1대, 이후 2대, 4대, 8대, 16대 순서로 검증하는 방향을 반영했습니다.- 사용자 요청에 따라 권장 네트워크 기준을 5 GHz 우선에서 2.4 GHz Wi-Fi 기준 검증으로 변경했습니다.
추가 요청 - 2026-06-02 17:13
- 요청 요약:
server 제어용 Web UI 도입 플랜 작성
할 일
- 현재 요청 확인
- 기존 server 방향과 목표 송신기 규모 확인
- Web UI 목표와 범위 정리
- 구현 단계 후보 정리
- 사용자 승인 전 코드 변경 없음 확인
Web UI 도입 목표
server는 C++ CLI 프로그램으로 유지하고, 브라우저에서 접속하는 Web UI를 통해 수신 상태와 기본 제어를 확인하는 방향을 우선합니다.
초기 Web UI의 목표는 예쁜 화면보다 2대에서 16대 송신기 상태를 빠르게 확인하고, 실전 중 문제가 생겼을 때 어떤 송신기에서 문제가 나는지 식별하는 것입니다.
대상 환경
- server 실행 환경: macOS, Ubuntu, Rocky Linux 9, Windows WSL2
- 권장 네트워크: 2.4 GHz Wi-Fi 기준 검증
- 송신기 목표 규모: 최소 2대, 최대 16대
- 서버 구현 언어: C++
- UI 접근 방식: 같은 장비 또는 같은 네트워크의 브라우저
권장 구조 후보
C++ mic_server
- UDP audio receive
- sender별 상태 관리
- jitter buffer
- mixer
- audio output
- stats collector
- HTTP/WebSocket control endpoint
Web UI
- 정적 HTML/CSS/JS 또는 가벼운 프론트엔드
- sender 상태 대시보드
- sender별 제어
- 실시간 통계 표시
초기에는 별도 Web 서버 프로세스를 두기보다 mic_server 안에 작은 HTTP 서버를 붙이는 후보를 우선 검토합니다. 이유는 실행 절차를 단순하게 유지하고, server 내부 상태를 별도 IPC 없이 직접 노출할 수 있기 때문입니다.
C++ HTTP/WebSocket 라이브러리 후보
아래는 후보이며 아직 확정하지 않습니다.
cpp-httplib: 단일 헤더 방식에 가까워 초기 HTTP API와 정적 파일 제공에 단순합니다. WebSocket은 별도 고려가 필요합니다.Boost.Beast: HTTP/WebSocket 모두 가능하지만 초기 구현 복잡도가 큽니다.uWebSockets: WebSocket 성능이 좋지만 빌드와 의존성 관리가 더 무거울 수 있습니다.CivetWeb또는Mongoose: embedded web server 용도에 맞지만 라이선스와 배포 조건을 확인해야 합니다.
초기 단계에서는 HTTP polling으로 시작하고, 실시간성이 부족할 때 WebSocket을 추가하는 방향이 가장 보수적입니다.
초기 Web UI 기능
1단계 Web UI는 관찰 중심으로 둡니다.
- server 실행 상태
- listen_port
- sample_rate / channels / frame_ms
- active sender count
- sender_id별 packets
- sender_id별 dropped
- sender_id별 out_of_order
- sender_id별 jitter buffer underflow / overflow
- sender_id별 last packet time
2단계에서 제어 기능을 추가합니다.
- sender별 mute
- sender별 gain
- sender별 display name
- 전체 output mute
- 통계 reset
- active sender 제거 또는 재선택
3단계에서 믹서 기능을 확장합니다.
- 2대 이상 sender 동시 믹싱 상태 표시
- sender별 간단한 level meter
- clipping indicator
- network health summary
- 2 / 4 / 8 / 16대 검증용 dashboard
API 초안 후보
구체적인 URL과 payload는 구현 전에 확정합니다. 초기 후보는 다음과 같습니다.
GET /api/status
GET /api/senders
POST /api/senders/{sender_id}/mute
POST /api/senders/{sender_id}/gain
POST /api/stats/reset
GET /api/events 또는 WebSocket /ws
초기에는 GET /api/status, GET /api/senders만 구현해도 충분합니다.
UI 화면 구성 후보
첫 화면은 dashboard 하나로 시작합니다.
상단:
server 상태, 포트, 오디오 포맷, 활성 sender 수
중앙:
sender 1-16 목록 테이블
sender_id, name, packets, dropped, out_of_order, underflow, overflow, last_seen
하단:
전체 로그 또는 최근 이벤트
16대 목표이므로 카드형 화면보다 조밀한 테이블형 화면을 우선합니다.
구현 단계
-
server 내부 상태 구조 정리
- sender별 stats를 UI/API에서 읽을 수 있게 정리합니다.
- 오디오 스레드와 HTTP 스레드가 동시에 접근하므로 mutex 또는 snapshot 구조를 정합니다.
-
HTTP status API 추가
GET /api/statusGET /api/senders- JSON 응답 후보를 정합니다.
-
정적 Web UI 제공
server/web/또는 embedded asset 방식을 검토합니다.- 초기 화면은 sender 상태 테이블 하나로 시작합니다.
-
실시간 갱신
- 처음에는 500 ms 또는 1 s polling을 사용합니다.
- 필요하면 WebSocket으로 전환합니다.
-
제어 기능 추가
- mute, gain, stats reset 같은 조작은 관찰 기능이 안정된 뒤 추가합니다.
-
16대 검증 화면 보강
- sender별 문제 상태를 색상이나 간단한 상태값으로 표시합니다.
- dropped/out_of_order/underflow 증가 추이를 확인합니다.
검증 방법
- server를 실행하고 브라우저에서 dashboard가 열리는지 확인합니다.
- client 없이 테스트 UDP 패킷으로 sender 1-16 상태가 표시되는지 확인합니다.
- sender별 sequence gap을 만든 테스트 패킷으로 dropped 증가가 표시되는지 확인합니다.
- out_of_order 패킷을 보내 UI 표시가 갱신되는지 확인합니다.
- server 오디오 수신/재생 루프가 Web UI 요청 때문에 끊기지 않는지 확인합니다.
아직 확정하지 않을 항목
- HTTP/WebSocket 라이브러리
- Web UI 파일 위치
- 정적 파일을 디스크에서 읽을지 바이너리에 embedded할지
- UDP 바인딩 실패 시 프로세스를 종료할지, Web UI만 살려 오류를 표시할지
사용자 확정 내용
- 접속 범위는
localhost전용으로 제한합니다. - 같은 Wi-Fi 안의 다른 장비에서 접속하는 기능은 현재 범위에 넣지 않습니다.
- 초기 Web UI는 상태 보기와 기본 제어를 함께 포함합니다.
- UI는 순수 HTML/CSS/JS로 구현합니다.
- Web 서버는
mic_server안에 내장합니다. - UDP 서버 또는 오디오 수신 경로에 문제가 생기면 Web UI에서도 알 수 있게 합니다.
- 별도 비밀번호나 인증은 두지 않습니다.
- 보안은 인증이 아니라
127.0.0.1바인딩으로 외부 노출을 막는 방식으로 처리합니다.
확정 후 Web UI 구현 기준
Web UI HTTP 서버는 기본적으로 127.0.0.1에만 바인딩합니다. 기본 후보 포트는 다음과 같습니다.
web_host = 127.0.0.1
web_port = 4861
0.0.0.0 또는 LAN IP 바인딩은 현재 범위에서 제외합니다. 나중에 원격 접속이 필요해지면 설정으로 명시적으로 켜는 방식만 후보로 둡니다.
초기 Web UI에는 다음 제어를 포함합니다.
- 전체 output mute
- sender별 mute
- sender별 gain
- sender별 display name
- 통계 reset
UDP 서버와 오디오 수신 경로 문제는 다음 상태로 표시합니다.
- udp_state: starting / listening / error / stopped
- udp_error: bind 실패, recvfrom 실패 등 마지막 오류 메시지
- audio_state: starting / running / error / stopped
- audio_error: 오디오 장치 초기화 또는 시작 실패 메시지
- last_packet_time
- sender별 packets/sec
- sender별 dropped / out_of_order / underflow / overflow
server가 UDP 바인딩에 실패하면 현재처럼 프로세스를 바로 종료할지, Web UI만 살려서 오류를 보여줄지는 구현 전에 결정해야 합니다. 사용자가 Web UI에서 UDP 서버 문제를 보길 원하므로, Web UI를 먼저 띄우고 UDP 수신을 별도 상태로 관리하는 구조를 우선 검토합니다.