[PonsLink] 다시 P2P로 돌아오며 PonsLink의 중심이 선명해졌다
중계 서버에 맡기던 것들을 클라이언트와 signaling 경계로 옮기자 실패가 "방이 안 열림" 하나로만 보이기 시작했다. 이상한 일이었다. 서버를 걷어내고 P2P로 돌아왔는데, 오히려 문제의 종류가 늘어난 것 같았다. 이 편은 PonsLink의 큰 피벗 — 서버 중심에서 P2P 중심으로 돌아온 것 — 이 왜 필요했고, 피벗이 무엇을 줄이고 무엇을 늘렸는지, 그리고 그 과정에서 제품의 중심이 무엇으로 선명해졌는지에 대한 기록이다.
"돌아온다"고 쓴 이유가 있다. PonsLink의 초기는 원래 P2P였다. 방 하나, 링크 하나, 두 브라우저가 직접 연결되는 모습에서 시작했다. 서버 중심으로 간 것은 규모를 꿈꾼 시기의 선택이었다. 그 시도가 돌아오는 길이었으니, 이 피벗은 신기술 도입이 아니라 원점 복귀에 가깝다. 다른 점이 하나 있다면, 원점으로 돌아왔을 때 원점이 같지 않았다는 것이다. 요청 운영에 대한 이해, 실패 설명의 필요, 제품의 존재 이유 — 이전에 없던 짐을 들고 돌아왔다.

서버 중심 구조가 무거워진 이유
먼저 왜 서버 중심에서 벗어나려 했는지부터 보자. 서버 중계 구조는 설계가 단순하다. 모든 미디어가 서버를 거치니 상태가 한곳에 모이고, 디버깅이 쉽고, 권한 제어도 서버에서 끝난다. 그런데 이 단순함의 청구서가 1인 운영 제품에 고스란히 들어왔다. 중계 서버는 대역폭 비용을 의미하고, 대역폭 비용은 사용자가 늘기도 전에 나가는 돈이다. 서버의 안정성 책임도 나의 것이었다. 서버가 죽으면 모든 방이 죽는다 — 밤에 문자 알림이 오는 구조다.
비용의 무게는 달러 단위보다 심리 단위가 더 컸다. 사용자가 늘지 않아도 고정비는 매달 나가는데, 이 고정비는 "더 정교한 중계 로직"을 만들 여유를 주지 않는다. 서버 중심 구조는 유지하는 데만 돈이 들고, 그 돈을 줄이려면 서버 규모를 줄여야 하고, 줄이면 중계 품질이 떨어진다. 이 사이클에서 나올 길은 구조의 변경뿐이었다.
여기에 운영의 심리 비용이 겹친다. 서버가 있는 제품은 서버를 돌보는 일이 항상 남는다. 업그레이드, 용량 감시, 장애 대응 — 이런 일들은 제품 개선이 아니라 생존 유지다. 1인 운영자의 시간은 유한한데, 생존 유지가 먹는 시간만큼 제품으로 갈 시간이 줄어든다. 서버 중심 구조의 진짜 가격표에는 달러와 함께 시간이 적혀 있었다.
Pion과 mesh 조합을 다시 검토했을 때 계산은 단순했다. 같은 서버 비용으로 소규모 방을 더 잘 서빙하는 것보다, 서버는 signaling과 최소 BFF만 남기고 실제 미디어는 피어 사이로 흐르게 하는 것이 1인 운영자에게 맞는 구조였다. Polar로 결제를 붙이려던 시기와 겹쳐서, "돈이 나가는 구조를 줄이고 돈이 들어오는 구조를 만든다"는 방향이 맞아 떨어졌다. 가격 정책을 설계하면서 확인한 것도 같은 사실이었다 — 고정비가 크면 가격을 올릴 수밖에 없고, 올린 가격은 초기 사용자를 밀어낸다. 구조와 가격은 따로 놀지 않는다.
P2P 뒤에 남은 설명 책임
P2P 데모는 두 브라우저에서 예쁘게 붙는데 실제는 권한 지연, 재입장, 네트워크 전환이 섞인다. 데모 성공률만 보면 제품이 완성된 것처럼 보이지만 사용자는 매번 다른 실패를 만난다.
데모와 실사용의 이 간극은 P2P 제품에서 특히 넓다. 데모는 같은 사무실의 두 기기, 같은 네트워크, 방금 설치된 브라우저다. 실사용은 카페 Wi-Fi, 오래된 폰, 화면 뒤집기, 백그라운드 전환이다. "두 브라우저에서 붙었다"는 성공 문장에 담긴 조건들을 하나씩 깨 보면 실패의 지도가 된다. 이 지도를 그리지 않은 P2P 제품은 데모의 성공률을 제품의 성공률로 착각하고 출시한다.

"방이 안 열림"으로만 보였던 실패를 뜯어보면 전부 달랐다. 권한 지연 때문에 늦게 열리는 것, 재입장에서 상태가 어긋나는 것, Wi-Fi에서 셀룰러로 넘어가며 연결이 끊기는 것. 서버 중계 구조에서는 이 세 가지가 서버 로그에 각각 남았다. P2P로 넘어오니 로그가 사라지고, 실패는 사용자 화면의 한 문장으로 압축됐다. 문제의 개수가 준 게 아니라 문제의 가시성이 사라진 것이다.
가시성의 상실은 운영자에게 특히 불편했다. 이전에는 "오늘 몇 건의 재접속이 있었다"를 로그에서 세울 수 있었다면 이제는 사용자가 말해주기 전까지 모른다. 그래서 P2P 피벗 뒤에 상태 문장의 정교화 작업이 반드시 따라와야 했고, 실제로 입장 전 조건 확인이나 연결 상태 안내 같은 화면들이 이 시기 이후에 하나씩 늘어났다. 제품이 로그를 버리는 대신 문장으로 복구한 것이다.
비용을 구체적인 장면으로 그려보면 이렇다. 사용자가 방에 들어왔는데 상대 화면이 안 뜬다. 서버 중계 구조였다면 내가 로그를 보고 "relay 연결 실패, 재시도됨"을 확인해 답할 수 있었다. P2P 구조에서는 그 로그가 없다. 대신 화면은 "연결 경로를 확인하는 중이에요" 또는 "네트워크가 바뀌었어요. 다시 입장해 주세요" 같은 문장으로 상태를 말해야 한다. 이 문장들이 정확하지 않으면 사용자는 실패 원인을 자기 잘못으로 돌린다. 정확한 상태 문장이 P2P 제품의 실질적 품질이 된다.
피벗 뒤에 고정한 기준
P2P를 택하면 서버가 줄어드는 대신 연결 상태를 사용자에게 설명할 문장을 제품이 더 가져야 했다. 서버 중심 구조에서는 서버 로그가 설명을 대신했는데 P2P에서는 그 설명을 화면으로 옮겨야 했다.
| 축 | 피벗 전 | 피벗 후 |
|---|---|---|
| 중계 | 서버 중심 | 최소 BFF + P2P |
| 실패 설명 | 서버 로그 | 사용자 상태 문장 |
| 기능 추가 | 늘리는 방향 | 줄이는 방향 |
| 설명 책임 | 숨김 | 노출 |
이 표를 만들 때 하나하나가 각각 따로 결정된 게 아니라, 첫 행이 나머지를 결정했다는 점을 남겨둔다. 중계가 서버에서 피어로 가자, 실패의 증거가 로그에서 화면으로 가야 했고(둘째 행), 화면으로 실패를 노출하려면 실패를 만들 기능이 줄어야 했고(셋째 행), 노출 자체가 설명 책임의 노출이었다(넷째 행). 표의 행들은 하나의 결정의 네 얼굴이다. 그래서 피벗은 결정 목록이 아니라 문장 하나로 기억된다 — 중계를 피어에게 맡기자.
표에서 가장 중요한 행은 마지막이다. 설명 책임이 숨김에서 노출로 바뀐 것은, 제품의 실패를 사용자와 함께 본다는 뜻이었다. "연결이 불안정합니다"를 보여주는 것은 실패를 인정하는 설계다. 실패를 숨기면 사용자는 자기 탓을 하고, 노출하면 사용자는 상황을 이해한다. 이 선택이 이후 PonsLink의 모든 상태 화면 — 입장 전 조건, 권한 지연 안내, 재입장 흐름 — 의 뿌리가 됐다.
기능 추가가 "늘리는 방향"에서 "줄이는 방향"으로 바뀐 것도 같은 맥락이다. 서버가 할 일을 줄이는 피벗은 자연스럽게 제품이 하는 일을 줄이는 방향으로 이어졌다. 방 안의 풍성한 기능보다, 연결의 각 단계가 명확히 설명되는 제품이 P2P 구조에서 살아남는다.
무엇을 잃고 무엇을 얻었나
피벗의 수지타산을 정산하면 이렇다.
잃은 것. 서버가 주던 안정감 — 중계 품질이 회선에 의존하게 됐다. 로그 — 실패가 화면 문장으로만 남는다. 서버 사이드의 즉시 개선 능력 — 서버만 고치면 되던 일이 클라이언트 배포를 요구한다.
얻은 것. 고정비의 소멸 — 방이 늘어도 나가는 돈은 signaling과 BFF 수준이다. 장애 반경의 축소 — 서버가 죽어도 진행 중인 방은 피어 사이에서 산다. 그리고 가장 중요한 것, 제품 정체성의 문장화. "연결은 피어가 하고, 제품은 상태를 설명한다."
정산표를 두 줄로 요약하면 이렇다. 규모를 꿈꾸는 시기에는 서버 중심이 이기고, 견디는 제품을 만드는 시기에는 P2P가 이긴다. PonsLink가 겨냥한 것은 대규모 웨비나가 아니라 1:1 상담과 소수 세션이었다. 필드가 다르면 최적해도 다르다. 피벗은 옳은 구조를 찾은 게 아니라, 내 필드에서 옳은 구조를 찾은 기록이다.
한 가지 단서를 남긴다. 이 피벗이 "서버는 나쁘다"는 원칙이 된 것은 아니다. signaling과 BFF는 남았고, 나중에 요청·결제·운영이 제품 안으로 들어올 때도 서버가 필요한 기능은 서버가 맡았다. 기각된 것은 "모든 미디어의 중계"였지 서버 자체가 아니었다. 피벗의 정확한 기록은 이렇게 좁혀져야 나중에 다시 판단할 때 도움이 된다 — 서버를 없앴다가 아니라, 서버의 몫을 제품의 정체에 맞게 재분배했다가.
피벗이 선명하게 한 것
돌아보면 이 피벗의 가장 큰 수확은 기술적이지 않았다. PonsLink의 중심이 선명해졌다는 것. 피벗 전의 PonsLink는 "서버가 있는 회의 도구"였다 — 모호한 정체다. 피벗 후에는 "연결은 피어가 하고, 제품은 상태를 설명한다"는 문장이 생겼다. 이 문장이 이후의 모든 결정 — 요청 선별, 세션 접근, 파일 전송의 분리 — 을 판단하는 축이 됐다.
정체성의 문장이 생기면 결정이 빨라지는 이유는, 문장이 기각의 근거가 되기 때문이다. "이 기능을 넣을까"에 대해 서버가 필요한가를 물으면 된다. 필요하면 피벗 방향과 어긋나니 다시 생각하고, 필요 없으면 피어 경로로 푼다. 서버 의존을 줄인다는 방향이 명확한 동안, 기능 후보들은 자연스럽게 걸러졌다. 방향 전환의 실질적 효용은 무엇을 만들었는가보다 무엇을 만들지 않게 됐는가에서 나온다.
이 편이 시리즈에서 하는 역할도 짚어두자. 앞 편(07)에서 운영이 제품 안으로 들어왔다면 이 편에서 연결 구조가 재정의됐다. 운영과 연결, 두 축이 모두 정리된 뒤에야 다음 편의 출시 판단(No-Go)이 가능했다. 구조가 흔들리는 동안에는 출시 판단의 기준도 흔들린다. 기준을 세울 수 있을 만큼 제품이 안정된 지점 — 그것이 이 피벗이 남겨 준 것이다.
기술을 줄이는 게 아니라 그 기술이 만드는 설명 책임을 정직하게 드러내는 게 제품의 중심이다. 이 문장이 이 편의 결론이고, PonsLink가 지금까지 유지하는 자기 정의다. 다음 편은 이 정의가 처음으로 출시 판단에 적용된 사례 — 파일 전송의 No-Go — 를 다룬다.