From bca9f041f524fb3d5d8e9a590d144cc2b71d2bbc Mon Sep 17 00:00:00 2001 From: daehyeong2 Date: Thu, 23 Jul 2026 14:52:44 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20TURN=20=EC=84=9C=EB=B2=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 +- README.md | 2 +- SERVER_STRUCTURE.md | 2 +- app/core/config.py | 6 +- software_engineering_portfolio.md | 170 ++++++++++++++++++++++++++++++ tests/test_webrtc_ice_config.py | 21 ++++ 6 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 software_engineering_portfolio.md diff --git a/.env.example b/.env.example index a8ada78..a06739a 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,7 @@ APP_NAME=inno-live-server APP_ENV=local DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/inno_live_server WEBRTC_STUN_URLS=stun:stun.l.google.com:19302 -WEBRTC_TURN_URLS= +WEBRTC_TURN_URLS=turn:innolive.duckdns.org:3478?transport=udp,turn:innolive.duckdns.org:3478?transport=tcp,turns:innolive.duckdns.org:5349?transport=tcp WEBRTC_TURN_USERNAME= WEBRTC_TURN_CREDENTIAL= WEBRTC_ANNOUNCED_IP= diff --git a/README.md b/README.md index 8bff028..bf5fb68 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,7 @@ Configure the server with environment variables: ```bash WEBRTC_STUN_URLS=stun:stun.l.google.com:19302 -WEBRTC_TURN_URLS=turn:turn.example.com:3478?transport=udp +WEBRTC_TURN_URLS=turn:innolive.duckdns.org:3478?transport=udp,turn:innolive.duckdns.org:3478?transport=tcp,turns:innolive.duckdns.org:5349?transport=tcp WEBRTC_TURN_USERNAME= WEBRTC_TURN_CREDENTIAL= WEBRTC_ANNOUNCED_IP= diff --git a/SERVER_STRUCTURE.md b/SERVER_STRUCTURE.md index c80f73a..4b5e2f4 100644 --- a/SERVER_STRUCTURE.md +++ b/SERVER_STRUCTURE.md @@ -160,7 +160,7 @@ Status: active → closing → closed | 설정 | 기본값 | 설명 | |------|--------|------| | `webrtc_stun_urls` | `stun:stun.l.google.com:19302` | STUN 서버 URL | -| `webrtc_turn_urls` | (비어있음) | TURN 서버 URL (선택사항) | +| `webrtc_turn_urls` | `turn:innolive.duckdns.org:3478?transport=udp`, `turn:innolive.duckdns.org:3478?transport=tcp`, `turns:innolive.duckdns.org:5349?transport=tcp` | TURN UDP/TCP/TLS 서버 URL | | `webrtc_turn_username` | null | TURN 인증 사용자명 | | `webrtc_turn_credential` | null | TURN 인증 자격증명 | | `webrtc_announced_ip` | null | 호스트 candidate IP 교체용 공개 IP | diff --git a/app/core/config.py b/app/core/config.py index 083b692..35b71f6 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -10,7 +10,11 @@ class Settings(BaseSettings): app_env: str = "local" log_level: str = "INFO" webrtc_stun_urls: str = "stun:stun.l.google.com:19302" - webrtc_turn_urls: str = "" + webrtc_turn_urls: str = ( + "turn:innolive.duckdns.org:3478?transport=udp," + "turn:innolive.duckdns.org:3478?transport=tcp," + "turns:innolive.duckdns.org:5349?transport=tcp" + ) webrtc_turn_username: str | None = None webrtc_turn_credential: str | None = None webrtc_announced_ip: str | None = None diff --git a/software_engineering_portfolio.md b/software_engineering_portfolio.md new file mode 100644 index 0000000..081abe9 --- /dev/null +++ b/software_engineering_portfolio.md @@ -0,0 +1,170 @@ +# 소프트웨어공학실무 포트폴리오 + +## 1. 요구 분석 프로젝트 + +### 제목 + +요구 분석 프로젝트 + +### 프로젝트 개요 + +이번 요구 분석 프로젝트에서는 주문 및 배달 서비스 문제를 선택하고, 가상의 서비스인 **배달의정석**을 대상으로 요구사항을 분석했다. 서비스의 기본 목표는 소비자가 주변 음식점을 쉽게 찾고 주문할 수 있게 하며, 점주는 주문과 홍보 기회를 얻고, 배달 수행원은 배달 위치와 경로를 효율적으로 확인할 수 있게 하는 것이다. + +이 프로젝트를 진행하면서 단순히 "음식 주문 앱을 만든다"는 수준에서 멈추지 않고, 실제 시스템에 영향을 주는 사용자와 이해관계자를 나누어 보았다. 이를 통해 같은 서비스라도 소비자, 점주, 배달 수행원, 운영사 담당자가 서로 다른 관점과 요구를 가진다는 점을 확인할 수 있었다. + +### 이해관계자 분석 + +| 구분 | 분석 내용 | +|---|---| +| 소비자 분쟁 담당자 | 음식 품질, 오배송, 주문 누락 같은 문제가 발생했을 때 소비자와 음식점 사이의 분쟁을 처리하는 역할이다. 이 담당자에게는 주문 기록, 음식점 정보, 소비자 요청 내역이 정확히 연결되는 것이 중요하다. | +| 마케팅 담당자 | 신규 고객 유입과 이벤트 기획을 담당한다. 서비스의 음식점 노출 방식, 할인 정책, 사용자 유입 경로는 마케팅 성과와 직접 연결된다. | +| 배달 수행원 | 음식점에서 소비자에게 음식을 전달하는 과정에 참여한다. 주소 확인, 경로 확인, 주문 취소 알림 같은 기능이 부족하면 배달 시간이 늘어나고 서비스 만족도도 낮아질 수 있다. | + +### 관련 개념과 보완점 + +이해관계자는 시스템의 개발과 운영 결과에 영향을 받거나 영향을 주는 사람 또는 조직이다. 반면 사용자는 시스템을 직접 조작하는 사람이고, 유스케이스 다이어그램의 액터는 시스템과 상호작용하는 외부 역할을 의미한다. + +보고서에서는 배달 수행원을 이해관계자로도 다루고 유스케이스 다이어그램의 액터로도 표현했다. 이 부분은 논리적으로 가능하지만, 포트폴리오에서는 **배달 수행원은 서비스 품질에 영향을 받는 이해관계자이면서 동시에 배달 관련 기능을 사용하는 액터**라고 구분해 설명하는 것이 더 정확하다. + +### 기능 요구사항 정리 + +| 요구사항 | 포트폴리오용 정리 | +|---|---| +| 근처 음식점 조회 | 시스템은 소비자의 현재 위치나 입력 주소를 기준으로 주문 가능한 주변 음식점 목록을 제공해야 한다. | +| 주문 현황 확인 | 점주는 접수된 주문의 상태를 실시간으로 확인하고, 조리 가능 여부에 따라 주문을 처리할 수 있어야 한다. | +| 배달 위치 확인 | 배달 수행원은 음식점 위치, 소비자 위치, 배달 경로를 지도에서 확인할 수 있어야 한다. | + +기능 요구사항은 시스템이 반드시 제공해야 하는 동작을 문장으로 정리한 것이다. 좋은 기능 요구사항은 주체, 기능, 결과가 분명하고 나중에 테스트할 수 있어야 한다. 예를 들어 "주문 현황을 확인한다"보다 "점주는 접수, 조리 중, 완료, 거절 상태로 구분된 주문 현황을 확인할 수 있어야 한다"라고 쓰면 구현 범위와 검증 기준이 더 명확해진다. + +### 유스케이스 모델링 정리 + +유스케이스 다이어그램에서는 소비자, 점주, 배달 수행원을 주요 액터로 설정했다. 소비자는 근처 음식점 조회, 주문하기, 주문 취소 기능과 연결되고, 점주는 주문 현황 확인과 주문 거절 기능을 사용한다. 배달 수행원은 배달하기와 배달 경로 확인 기능을 사용한다. + +| 액터 | 주요 유스케이스 | +|---|---| +| 소비자 | 근처 음식점 조회, 주문하기, 주문 취소 | +| 점주 | 주문 현황 확인, 주문 거절 | +| 배달 수행원 | 배달하기, 배달 경로 확인 | + +유스케이스 관계에서는 `<>`와 `<>`의 의미를 구분하는 것이 중요했다. `<>`는 기본 유스케이스가 항상 포함하는 공통 기능에 사용하고, `<>`는 특정 조건에서만 추가되는 기능에 사용한다. 따라서 멤버십 할인이 주문 과정에서 조건부로 적용된다면 `주문하기`를 확장하는 관계로 보는 것이 적절하다. 반면 위약금 결제는 모든 주문 취소에서 항상 발생하는 것이 아니라 취소 시점이나 정책에 따라 달라질 수 있으므로, 실제 서비스라면 `주문 취소`의 필수 포함 기능으로 단정하기보다 조건부 확장 흐름으로 다루는 것이 더 자연스럽다. + +### 유스케이스 명세 보완 + +보고서에서는 `주문하기` 유스케이스를 선택해 기본 흐름과 대안 흐름을 작성했다. 포트폴리오 관점에서 보면 이 명세는 소비자가 음식점을 선택하고 메뉴를 고른 뒤 주문 요청을 저장하는 흐름을 잘 보여준다. 다만 실제 주문 서비스에서는 주문 요청이 단순히 소비자의 목록에 저장되는 것에서 끝나지 않고, 점주에게 전달되어 주문 상태가 변경되어야 한다. + +따라서 종료 조건은 다음과 같이 보완할 수 있다. + +> 소비자의 주문 요청이 저장되고, 해당 주문이 점주에게 전달되어 `접수 대기` 상태로 등록된다. + +이렇게 수정하면 유스케이스의 결과가 소비자 화면뿐 아니라 점주 업무 흐름까지 연결되므로, 시스템의 실제 동작을 더 정확하게 설명할 수 있다. + +## 2. 소프트웨어 개발 프로세스 반복적 모델 분석 + +### 제목 + +소프트웨어 개발 프로세스 반복적 모델 분석 + +### 보고서 요약 + +반복적 모델은 소프트웨어를 한 번의 순차적인 과정으로 완성하는 방식이 아니라, 분석, 설계, 구현, 테스트, 피드백 과정을 여러 차례 반복하면서 완성도를 높이는 개발 프로세스이다. 이 모델은 사용자의 요구가 개발 중에 더 구체화될 수 있다는 점을 전제로 하며, 초기 결과물을 바탕으로 문제를 발견하고 다음 반복에서 개선하는 데 강점이 있다. + +반복적 모델은 대표적으로 **증분형 모델**과 **진화형 모델**로 나누어 볼 수 있다. + +| 모델 | 핵심 내용 | 적합한 상황 | +|---|---|---| +| 증분형 모델 | 전체 기능을 여러 부분으로 나누고, 각 부분을 분석, 설계, 구현, 테스트하여 단계적으로 완성한다. | 최종 목표와 주요 요구사항이 어느 정도 정해져 있지만, 기능을 나누어 순차적으로 제공하고 싶을 때 적합하다. | +| 진화형 모델 | 초기 프로토타입을 만들고 사용자 피드백을 반영하면서 요구사항과 제품을 함께 발전시킨다. | 요구사항이 명확하지 않거나 개발 중 변경 가능성이 큰 경우에 적합하다. | + +증분형 모델과 진화형 모델은 모두 반복을 활용하지만 초점이 다르다. 증분형 모델은 정해진 목표를 여러 기능 단위로 나누어 완성하는 데 초점이 있고, 진화형 모델은 불명확한 요구사항을 실제 사용자의 반응을 통해 구체화하는 데 초점이 있다. + +### 특징과 장단점 + +| 구분 | 정리 | +|---|---| +| 특징 | 전체 시스템을 한 번에 완성하지 않고, 일부 기능 또는 일부 범위를 반복적으로 개발한다. 각 반복에서는 분석, 설계, 구현, 테스트가 다시 수행된다. | +| 장점 | 중간 결과물을 빠르게 확인할 수 있고, 사용자 피드백이나 요구사항 변경을 다음 반복에 반영할 수 있다. 따라서 문제를 비교적 이른 시점에 발견하고 수정할 수 있다. | +| 단점 | 반복이 많아질수록 버전과 산출물 관리가 어려워질 수 있다. 또한 변경을 계속 반영하면서 구조 관리가 부족하면 시스템이 복잡해지고 유지보수가 어려워질 수 있다. | + +### 문항 1 + +다음 중 반복적 모델에 대한 설명으로 가장 적절한 것은? + +1. 증분형 모델은 요구사항이 거의 정해지지 않은 상황에서 가장 적합하다. +2. 반복적 모델은 여러 산출물을 만든 뒤 가장 좋은 하나만 선택하는 방식이다. +3. 진화형 모델은 전체 진화 방향에 대한 개요를 가지고 피드백을 반영하며 발전시킨다. +4. 증분형 모델은 항상 프로토타입을 먼저 만들고 요구사항을 새로 정의하는 방식이다. + +정답: 3 + +풀이: 진화형 모델은 초기 요구사항이 불명확할 때 프로토타입과 피드백을 통해 제품을 발전시키는 방식이지만, 아무 방향 없이 개발하는 것은 아니다. 전체적인 목표나 진화 방향에 대한 개요는 필요하다. 1번은 진화형 모델에 더 가까운 설명이고, 2번은 반복적 모델의 목적을 잘못 이해한 것이다. 4번은 증분형 모델보다 진화형 모델의 특징에 가깝다. + +### 문항 2 + +다음 상황에 가장 알맞은 개발 프로세스 모델은? + +> 개발팀은 "직장인 대상 건강관리 서비스"라는 큰 주제만 전달받았고, 세부 기능과 화면 요구사항은 아직 정리되지 않았다. 우선 핵심 기능을 담은 프로토타입을 만든 뒤, 고객 미팅과 시범 운영을 거치며 요구사항을 계속 추가하고 수정할 계획이다. + +1. 증분형 모델 +2. 진화형 모델 +3. 폭포수 모델 +4. V 모델 + +정답: 2 + +풀이: 이 상황은 요구사항이 명확하지 않고, 프로토타입을 통해 사용자의 반응을 확인하면서 제품을 발전시키는 구조이다. 따라서 진화형 모델이 가장 적합하다. 폭포수 모델과 V 모델은 요구사항이 초기에 비교적 안정적으로 정리되어 있을 때 더 적합하며, 증분형 모델은 목표 기능이 어느 정도 정해진 상태에서 기능을 나누어 개발하는 방식에 가깝다. + +## 3. 소프트웨어공학 용어와 개발 프로젝트 연결하기 + +### 연결한 개발 프로젝트 + +| 항목 | 내용 | +|---|---| +| 프로젝트명 | inno-live-server | +| 프로젝트 성격 | FastAPI 기반 실시간 라이브 스트리밍 서버 | +| 주요 기능 | WebRTC 세션 생성, WebSocket 시그널링, AI 얼굴 블러 처리, 기준 얼굴 등록, RTMP 송출, 상태 확인 API | +| 참고한 코드 구조 | `app/api/routes/`, `app/services/`, `app/core/config.py`, `privacy_blur/`, `tests/` | + +`inno-live-server`는 브라우저에서 들어온 실시간 영상 트랙을 서버가 받아 AI 프라이버시 필터를 적용하고, 처리된 영상을 다시 송출하는 서버 프로젝트이다. 이 프로젝트는 단순한 CRUD 애플리케이션보다 실시간성, 개인정보 보호, 장애 대응이 중요하기 때문에 소프트웨어공학 개념을 실제 코드 구조와 연결해 보기 좋다. + +### 용어 1: 결합도(Coupling) + +| 항목 | 내용 | +|---|---| +| 의미 | 결합도는 모듈이나 클래스가 서로 얼마나 의존하고 있는지를 나타내는 개념이다. 결합도가 낮으면 한 부분을 수정해도 다른 부분에 미치는 영향이 작아지고, 테스트와 유지보수가 쉬워진다. | +| 프로젝트 적용 | 이 프로젝트는 API 라우터, 세션 관리, WebRTC 처리, AI 필터 처리를 별도 계층으로 나누어 결합도를 낮추려는 구조를 가지고 있다. 예를 들어 `app/api/routes/webrtc.py`는 WebSocket 메시지를 받고 요청을 검증한 뒤, 실제 offer 처리와 ICE candidate 처리는 `OfferService`, `IceCandidateService`에 위임한다. `app/api/routes/sessions.py`도 직접 세션 저장 구조를 조작하지 않고 `SessionManager`를 통해 세션을 생성하고 조회한다. | +| 코드 근거 | `app/services/webrtc/offer.py`는 WebRTC answer 생성에 집중하고, `app/services/sessions/manager.py`는 세션 상태와 트랙 수명주기를 관리한다. AI 필터 생성과 런타임 관리는 `app/services/ai/filter.py`, 실제 영상 프레임 보호 처리는 `app/services/ai/track.py`에 분리되어 있다. | +| 논리적 평가 | 라우터가 AI 모델 내부 구조나 WebRTC 세부 구현을 직접 알지 않아도 되므로 전체적으로 결합도를 낮추는 방향의 설계라고 볼 수 있다. 다만 `ProtectedVideoTrack.stop()`에서 `app.services.ai.filter`의 내부 전역 목록에 접근하는 부분처럼 일부 구현은 내부 상태에 직접 의존한다. 이 부분은 장기적으로 명시적인 필터 등록/해제 인터페이스로 바꾸면 결합도를 더 낮출 수 있다. | + +### 용어 2: 응집도(Cohesion) + +| 항목 | 내용 | +|---|---| +| 의미 | 응집도는 하나의 모듈 안에 있는 기능들이 하나의 목적을 위해 얼마나 밀접하게 모여 있는지를 의미한다. 응집도가 높으면 모듈의 책임이 분명해지고 코드를 이해하기 쉬워진다. | +| 프로젝트 적용 | 프로젝트의 디렉터리 구조를 보면 `app/api/routes/`는 외부 요청 처리, `app/services/webrtc/`는 WebRTC 연결과 SDP/ICE 처리, `app/services/ai/`는 AI 프라이버시 필터, `app/core/`는 설정과 예외 처리처럼 역할이 나뉘어 있다. | +| 코드 근거 | `ProtectedVideoTrack`은 원본 영상 프레임을 받아 AI 필터를 적용하고, 실패하면 검은 프레임을 반환하는 "보호된 영상 트랙" 책임에 집중한다. `app/core/config.py`는 환경 변수 기반 설정을 모아 WebRTC, AI, RTMP 설정을 한곳에서 관리한다. | +| 논리적 평가 | 기능별 파일과 패키지가 비교적 명확해 응집도가 높은 편이다. 특히 AI 필터 실패 시 원본 영상을 노출하지 않는 정책은 `ProtectedVideoTrack` 안에서 일관되게 처리된다. 다만 `SessionManager`는 세션 생성, 트랙 교체, 연결 종료 처리, RTMP 송출 시작/중지까지 담당하므로 프로젝트가 더 커지면 스트리밍 송출 책임을 별도 서비스로 분리하는 것이 응집도 측면에서 더 좋다. | + +### 용어 3: CMMI 모델의 조직 성숙도 + +| 항목 | 내용 | +|---|---| +| 의미 | CMMI는 조직의 소프트웨어 개발 프로세스가 얼마나 체계적으로 관리되고 개선되는지를 평가하는 성숙도 모델이다. 일반적으로 초기 단계인 1단계부터 관리, 정의, 정량적 관리, 지속적 개선 단계로 성숙도가 높아진다. | +| 프로젝트 적용 | `inno-live-server`는 개인 또는 소규모 프로젝트이므로 CMMI 성숙도 등급을 공식적으로 부여할 수는 없다. 다만 프로젝트 산출물을 기준으로 보면 요구사항과 실행 방법을 `README.md`에 정리하고, 서버 구조를 `SERVER_STRUCTURE.md`에 문서화했으며, 기능별 테스트를 `tests/`에 작성했다. 이는 즉흥적으로만 개발하는 1단계보다, 프로젝트 단위로 작업을 관리하고 검증하려는 2단계적 특징에 가깝다. | +| 코드와 산출물 근거 | `.env.example`, `Dockerfile`, `docker-compose.prod.yml`은 실행 환경을 표준화하려는 산출물이고, `tests/test_track.py`, `tests/test_api_webrtc.py`, `tests/test_session_manager.py` 등은 기능 변경 시 회귀를 확인하기 위한 검증 장치이다. 또한 `SERVER_STRUCTURE.md`와 `AI_ARCHITECTURE.md`는 구조와 설계 의도를 문서화한다. | +| 논리적 평가 | 이 프로젝트는 프로젝트 수준의 관리와 검증 체계는 갖추고 있지만, 조직 전체에 공통 적용되는 표준 프로세스나 정량적 품질 관리 지표가 충분히 정의되어 있다고 보기는 어렵다. 따라서 "CMMI 3단계 이상"이라고 단정하는 것은 과장이다. 포트폴리오에서는 **CMMI 관점에서 보면 프로젝트 단위 관리 수준은 갖추었지만, 조직 차원의 표준화와 정량적 개선 체계는 앞으로 보완할 부분**이라고 설명하는 것이 가장 정확하다. | +| 개선 방향 | 이슈 관리 규칙, 코드 리뷰 기준, 배포 전 체크리스트, 장애 기록 방식, 성능 지표 추적 기준을 문서화하면 조직 성숙도 관점에서 더 높은 단계로 발전할 수 있다. | + +### 용어 4: 비기능 요구사항(Non-Functional Requirement) + +| 항목 | 내용 | +|---|---| +| 의미 | 비기능 요구사항은 시스템이 어떤 기능을 제공하는지를 넘어서, 그 기능을 어떤 품질 수준으로 제공해야 하는지를 설명한다. 성능, 보안, 신뢰성, 가용성, 개인정보 보호 등이 포함된다. | +| 프로젝트 적용 | 이 프로젝트의 핵심 비기능 요구사항은 실시간성, 개인정보 보호, 신뢰성이다. 영상 처리 지연이 너무 길면 라이브 스트리밍으로 사용하기 어렵고, AI 필터 실패 시 원본 얼굴이 그대로 노출되면 개인정보 보호 목적을 달성할 수 없다. | +| 코드 근거 | `app/services/ai/track.py`의 `ProtectedVideoTrack`은 AI 필터가 실패하거나 시간 초과될 때 원본 프레임을 그대로 보내지 않고 검은 프레임을 반환한다. 이는 기능을 계속 제공하는 것보다 개인정보 노출을 막는 것을 우선한 설계이다. 또한 `app/core/config.py`에는 AI 배치 크기, 프레임 타임아웃, WebRTC UDP 포트 범위, RTMP 재시도 설정이 환경 변수로 분리되어 있어 운영 환경에 맞게 품질 속성을 조정할 수 있다. | +| 논리적 평가 | 이 설계는 "영상은 계속 나가야 한다"는 기능 요구사항과 "개인정보를 보호해야 한다"는 비기능 요구사항이 충돌할 때, 개인정보 보호를 우선하도록 만든 사례이다. 따라서 단순 기능 구현이 아니라 품질 요구사항을 코드 정책으로 반영한 사례라고 볼 수 있다. | + +### 종합 정리 + +`inno-live-server` 프로젝트를 소프트웨어공학 개념으로 분석해 보면, 기능을 단순히 구현하는 것보다 구조와 품질을 함께 고려한 프로젝트라는 점을 확인할 수 있다. API 라우터와 서비스 계층을 나누어 결합도를 낮추려 했고, WebRTC, AI 필터, 설정, 테스트를 역할별로 나누어 응집도를 높였다. 또한 AI 필터 실패 시 원본 영상을 차단하는 방식은 개인정보 보호라는 비기능 요구사항을 코드에 직접 반영한 사례이다. + +CMMI 모델의 조직 성숙도 관점에서는 이 프로젝트가 공식적인 조직 프로세스를 갖춘 것은 아니지만, 문서화, 테스트, 실행 환경 표준화가 존재한다는 점에서 프로젝트 단위의 관리 체계는 확인할 수 있다. 앞으로 코드 리뷰 기준, 배포 체크리스트, 성능 지표 관리까지 체계화한다면 더 성숙한 개발 프로세스로 발전할 수 있다. diff --git a/tests/test_webrtc_ice_config.py b/tests/test_webrtc_ice_config.py index 8f386e3..5eeb48b 100644 --- a/tests/test_webrtc_ice_config.py +++ b/tests/test_webrtc_ice_config.py @@ -4,6 +4,27 @@ from app.services.webrtc.sdp import extract_ice_candidates, rewrite_host_candidates +def test_webrtc_config_exposes_default_stun_and_turn_servers(): + from app.main import app + + with TestClient(app) as client: + response = client.get("/webrtc/config") + + assert response.status_code == 200 + assert response.json() == { + "iceServers": [ + {"urls": ["stun:stun.l.google.com:19302"]}, + { + "urls": [ + "turn:innolive.duckdns.org:3478?transport=udp", + "turn:innolive.duckdns.org:3478?transport=tcp", + "turns:innolive.duckdns.org:5349?transport=tcp", + ], + }, + ], + } + + def test_webrtc_config_exposes_stun_and_turn_from_environment(monkeypatch): monkeypatch.setenv("WEBRTC_STUN_URLS", "stun:stun1.example.com:3478") monkeypatch.setenv(