[SFU 딥다이브] Simulcast와 SVC는 왜 SFU 옆에 따라붙을까
Simulcast와 SVC를 처음 봤을 때는 코덱 쪽의 어려운 옵션처럼 느껴졌다. 그런데 SFU를 공부하고 나니 둘은 품질을 누가, 어떤 단위로 고를 수 있느냐의 문제였다. SFU가 수신자마다 다른 품질을 전달하려면 고를 재료가 있어야 한다. 송신자가 한 가지 품질만 보내면 SFU는 그것을 전달하거나 끊는 정도밖에 못 한다. 그래서 SFU 옆에는 자연스럽게 simulcast와 SVC가 따라붙는다. 같은 단어를 쓰더라도 제품 문맥이 다르면 답이 갈렸다. 그 갈림길을 숨기지 않는 쪽으로 썼다.

Simulcast가 붙은 이유
수신자별 선택을 하려면 수신자 상태를 알아야 한다. 단순히 서버가 레이어를 갖고 있다고 끝나는 것이 아니다. 각 수신자의 packet loss, RTT, 디코딩 상태, 화면 크기, 현재 visible 여부를 봐야 한다. 탭이 백그라운드로 가 있거나 썸네일이 보이지 않는 상태라면 높은 품질을 계속 보낼 이유가 없다. 반대로 발표자 화면이 크게 열려 있는데 낮은 레이어가 오래 유지되면 사용자는 품질 저하를 바로 느낀다.
화면 공유에서는 판단이 조금 달라진다. 카메라 영상은 움직임이 부드러운지가 중요하지만, 화면 공유는 글자가 읽히는지가 중요하다. 네트워크가 나쁘다고 해상도를 낮춰 버리면 문서나 코드가 뭉개진다. 반대로 프레임은 조금 낮아져도 괜찮을 때가 많다. 그래서 카메라와 화면 공유를 같은 레이어 정책으로 묶으면 실제 사용성이 나빠질 수 있다.
이 부분은 SFU 설정 문제가 아니라 제품 정책 문제에 가깝다. 오디오와 비디오의 우선순위도 따로 둬야 한다. 네트워크가 나빠졌을 때 영상 품질은 낮춰도 음성이 끊기면 회의는 바로 어려워진다. SFU가 영상 레이어를 낮추는 동안 오디오는 최대한 안정적으로 유지해야 한다. 사용자는 흐린 얼굴은 참아도 끊기는 말은 참기 어렵다. 그래서 미디어 품질 조절을 이야기할 때 비디오 해상도만 보면 절반만 본 셈이다.
품질 레이어의 실패는 대부분 “선택지가 없음” 또는 “선택지가 너무 비쌈”에서 시작한다. 특히 SFU에서는 재현 조건을 같이 적어야 의미가 있었다.

처음에는 하나의 스트림이면 충분할 줄 알았다
녹화와 실시간 수신을 분리하는 것도 여기서 다시 중요해진다. 실시간 참여자에게는 낮은 레이어를 보내도 되지만, 나중에 저장할 강의나 상담 기록은 더 나은 원본이 필요할 수 있다. 이때 송신자가 녹화용 고품질 레이어를 계속 올릴 수 있는지, 서버가 별도로 저장할지, 녹화가 필수 기능인지 옵션인지에 따라 설계가 달라진다. 품질 레이어는 화면에 보이는 순간만이 아니라, 나중에 남는 결과물까지 생각해야 한다.
PonsLink가 실시간 세션이나 PonsCast 같은 기능을 확장한다면 이 문제가 그대로 나온다. 상담자 화면, 참여자 썸네일, 화면 공유, 녹화용 원본은 서로 다른 품질 요구를 가진다. PonsWarp의 파일 전송과 직접 같지는 않지만, chunk 크기와 backpressure를 조절하듯 미디어에서는 레이어와 bitrate를 조절한다는 점에서 닮았다. 중요한 것은 자동이라는 말에 기대지 않고, 어떤 상황에서 무엇을 낮추고 무엇을 지킬지 미리 정하는 것이다.
Simulcast를 실제 설정으로 옮길 때는 레이어 이름을 먼저 정하는 것보다 사용 장면을 먼저 적는 편이 좋다. 큰 화면 발표자, 작은 썸네일, 모바일 청중, 화면 공유, 녹화 원본은 서로 원하는 것이 다르다. 썸네일은 낮은 해상도와 낮은 bitrate로 충분하지만 발표자 화면은 조금 더 높은 품질이 필요하다. 화면 공유는 프레임을 낮춰도 글자가 살아야 한다. 녹화 원본은 실시간 수신보다 나중의 품질이 중요할 수 있다.
같은 비디오라고 한 정책으로 묶으면 어딘가가 불편해진다. 품질 조절은 SFU 혼자 해결하지 못한다. 송신자가 어떤 선택지를 만들어 주는지가 먼저다. 현실적인 구현에서는 기본 레이어 수를 적게 시작하는 편이 낫다. 낮음, 중간, 높음 정도만 있어도 많은 상황을 커버한다. 그보다 촘촘한 단계가 필요해 보인다면 먼저 실제 전환 로그를 봐야 한다.
사용자가 체감하지 못하는 레이어를 늘리는 일은 품질 개선이 아니라 송신 부담 증가일 수 있다.

다른 화질이 필요해진 순간
내가 제품에 넣는다면 네 가지를 먼저 정하겠다. 수신자 화면 크기별 품질 기준, 발표자와 썸네일의 우선순위, 화면 공유 전용 정책, 레이어별 CPU와 bitrate 한계다. 이 기준 없이 SFU 설정만 만지면 데모에서는 좋아 보여도 운영에서 흔들린다. 특히 작은 썸네일을 보는 사람에게 높은 품질을 계속 보내거나, 발표자 화면을 낮은 레이어로만 유지하는 실수는 사용자가 바로 알아차린다.
화면 공유에는 또 다른 예외가 있다. 발표자가 코드나 문서를 공유하는 경우에는 낮은 해상도보다 낮은 프레임이 낫다. 슬라이드 발표도 마찬가지다. 움직임이 적은 화면은 프레임을 줄여도 내용 전달이 된다. 반면 디자인 시안이나 영상 편집 화면처럼 움직임과 색이 중요한 공유는 다른 기준이 필요하다. 한 가지 화면 공유 정책으로 모든 업무를 처리하려고 하면 어떤 팀은 계속 불편해진다.
브라우저별 차이도 실제 작업에서는 크게 느껴진다. 같은 simulcast 설정이라도 브라우저가 인코딩을 다르게 다루거나, 모바일에서 특정 codec 조합이 안정적이지 않을 수 있다. 데스크톱 크롬 하나로만 성공을 확인하면 출시 뒤에 이상한 문의가 들어온다. 그래서 레이어 전략은 지원 브라우저 목록과 같이 관리해야 한다. “우리 서비스가 공식적으로 보장하는 조합”을 정하지 않으면 테스트 범위가 끝없이 늘어난다.
*Simulcast와 SVC는 우열보다 비용 배치가 다르다. 송신 부담, 서버 선택, 수신 적응을 나눠서 봐야 한다. 이런 이유로 나는 품질 레이어를 설계할 때 “사용자가 무엇을 읽거나 들어야 하는가”를 먼저 적는다. 얼굴 표정이 중요한 상담, 텍스트가 중요한 화면 공유, 흐름이 중요한 강의는 서로 다른 품질 손실을 싫어한다. 네트워크가 부족할 때 무엇을 줄일지 정하려면 무엇을 지킬지부터 정해야 한다.
그 순서를 바꾸면 레이어 설정은 많아지는데 실제 경험은 좋아지지 않는다. 운영자 도구에는 현재 레이어뿐 아니라 “왜 그 레이어가 선택됐는가”가 보여야 한다. low가 선택된 이유가 수신자 화면이 작아서인지, 네트워크 손실 때문인지, 송신자 CPU 제한 때문인지에 따라 대응이 다르다. 수신자 화면이 작아서 낮춘 것이라면 정상이다. 네트워크 손실 때문이라면 우회나 region 문제가 있을 수 있다.
송신자 CPU 제한이라면 발표자의 기기 상태가 원인이다. 이유 없는 자동화는 나중에 디버깅을 어렵게 만든다. SFU를 설명할 때 서버/클라이언트/사용자 중 누구 문장으로 말하는지 먼저 고르면 논쟁이 줄었다.
SFU 옆에 두는 경계 나누기
릴리스 뒤에는 기본값을 고정하지 말고 로그를 보고 조정해야 한다. 레이어 전환이 너무 적으면 약한 네트워크 사용자가 오래 버퍼링하고, 너무 많으면 화면이 불안정해진다. 발표자 기기에서 CPU 제한이 자주 나오면 레이어 수나 해상도를 낮춰야 한다. 특정 브라우저에서 high 레이어가 거의 선택되지 않는다면 지원 조합을 다시 봐야 한다.
품질 정책은 한 번 정하고 끝나는 설정이 아니라, 실제 세션 기록을 보며 다듬는 운영 규칙이다. 품질 정책을 문서로 남길 때는 “자동”이라는 단어를 조심해야 한다. 자동 조절은 사용자가 신경 쓰지 않아도 된다는 뜻이지, 제품팀이 기준을 정하지 않아도 된다는 뜻이 아니다. 어떤 packet loss에서 낮은 레이어로 내릴지, 얼마나 안정되면 다시 올릴지, 발표자와 일반 참여자 중 누구를 우선할지 정해야 한다.
기준이 없으면 SFU는 그때그때 그럴듯한 선택을 하지만, 사용자는 세션마다 다른 품질을 경험한다. 녹화가 끼어들면 판단이 또 바뀐다. 실시간 수신자는 낮은 품질을 받아도 되지만, 나중에 저장할 원본은 높은 품질이 필요할 수 있다. 이 요구를 같은 스트림 정책으로 묶으면 둘 중 하나가 손해를 본다. 그래서 품질 레이어를 설계할 때는 화면에 지금 보이는 경로와 나중에 결과물로 남을 경로를 따로 적어 두는 것이 좋다.
특히 SFU에서는 재현 조건을 같이 적어야 의미가 있었다. 확인 항목은 품질 이름보다 정책을 묻는다. 누구에게 어떤 품질을 줄지 결정해야 SFU가 제대로 일한다. 특히 SFU에서는 재현 조건을 같이 적어야 의미가 있었다.
책임 흐름이 바뀐 지점
요지를 줄이면 simulcast와 SVC는 같은 기술이 아니다. Simulcast는 여러 스트림을 보내고, SVC는 계층형 스트림을 쓴다. 둘은 SFU가 수신자별로 다른 품질을 전달할 수 있게 해 주는 재료다. 항상 고화질이 좋은 것도 아니다. 모바일 수신자, 작은 썸네일, 화면 공유, 녹화 요구가 섞이면 좋은 품질의 의미가 달라진다. Simulcast는 송신자가 여러 품질의 스트림을 동시에 보내는 방식이다.
예를 들어 180p, 360p, 720p를 따로 올리고 SFU가 수신자 상태에 맞춰 하나를 골라 준다. SVC는 하나의 스트림 안에 계층을 넣는 방식이다. 기본 계층만 받으면 낮은 품질로 재생하고, 추가 계층을 더 받으면 해상도나 프레임이 좋아진다. 둘 다 목표는 비슷하다. 발표자는 가능한 범위에서 품질 후보를 만들고, SFU는 수신자의 화면 크기와 네트워크 상태를 보고 적당한 것을 전달한다.
측정할 값은 명확하다. 레이어별 bitrate, 송신 CPU, 인코딩 시간, 수신 packet loss, 레이어 전환 횟수, 전환 뒤 안정화 시간이다. p95 연결 시간처럼 네트워크 지표도 같이 봐야 하지만, 이 주제에서는 품질 전환이 사용자에게 어떻게 보이는지도 중요하다. 자주 오르내리는 화질은 낮은 화질보다 더 거슬릴 때가 있다. 제품에서는 “자동으로 조절 중”이라는 문구보다, 실제로 안정적인 기준을 잡는 일이 먼저다.
이 개념이 필요한 이유는 방 안의 사용자가 같은 조건에 있지 않기 때문이다. 발표자는 유선망에 있고, 한 청중은 모바일 데이터로 듣고, 다른 사람은 노트북에서 작은 썸네일만 보고 있을 수 있다. 모두에게 1080p를 보내면 약한 수신자가 버퍼링하고, 모두에게 낮은 품질을 보내면 큰 화면 사용자가 손해를 본다. 실시간 미디어에서는 공평함이 같은 품질을 뜻하지 않는다.
각자가 버틸 수 있는 품질을 받는 것이 더 중요하다. 품질 전환의 리듬도 중요하다. 네트워크가 순간적으로 나빠졌다고 바로 낮은 레이어로 내리고, 조금 좋아졌다고 바로 올리면 화면이 계속 출렁인다. 사용자는 평균 화질보다 불안정한 변화를 더 크게 느낀다. 일정 시간 상태가 유지될 때만 올리거나, 내려갈 때는 빠르게 내려가되 올라갈 때는 천천히 올리는 식의 hysteresis가 필요하다.
이런 정책은 SFU 설정 파일 몇 줄보다 사용자 경험에 더 직접적으로 닿는다. '[SFU 딥다이브 Simulcast와 SVC는 왜 SFU 옆에 따라붙을까'을 관통하는 질문은 이 섹션에서도 같았고, 답만 더 구체적이 됐다.
마치며
이 글에서 확인한 경계는 다음 변경의 기준으로 남겼다.