[P2P 설계] edge와 serverless를 P2P와 섞으면 무엇이 달라질까
순수 P2P 그림은 매력적이다. 서버는 연결만 돕고 payload는 피어끼리 직접 보낸다. 다이어그램도 깔끔하고 비용 설명도 쉽다. 그런데 제품 화면으로 내려오면 금방 예외가 생긴다. 사용자는 동시에 접속하지 않을 수 있고, 모바일은 중간에 잠들 수 있고, 회사망에서는 TURN이 필요하고, 권한과 결제는 어딘가에서 확인해야 한다. 같은 입력인데 어떤 환경에서만 P2P가 도드라졌다.

edge와 serverless가 붙은 지점
이 실험은 큰 플랫폼 흉내를 내기 위한 준비가 아니다. 작은 제품에서도 사용자에게 어떤 약속을 하고 있는지 숨기지 않기 위한 안전장치다. 혼합 구조는 P2P를 포기한다는 고백이 아니다. 오히려 직접 경로가 실패했을 때 무엇을 숨기고 무엇을 공개할지 정하는 방식이다. direct, relay, cloud drop, metadata-only 서버를 모드로 분리하고 각 모드의 비용과 개인정보 경계를 화면 문구까지 연결해야 한다.
- signaling과 권한 검사를 edge 가까이에 둘 때 어떤 지연을 줄이는지 알고 있는가. - payload를 서버에 올릴지 여부를 파일 민감도와 동시 접속 가능성으로 판단하는가. - serverless가 긴 전송을 붙잡지 않고 짧은 handoff와 정책 판단을 맡는가. - Cloud Drop을 실패가 아니라 시간차를 다루는 별도 모드로 설명하는가. - direct, relay, cloud drop, metadata-only 서버의 비용과 개인정보 경계를 구분했는가. - 사용자가 현재 어떤 경로로 전송 중인지 이해할 수 있는가. | 모드 | payload 위치 | metadata 위치 | 맞는 장면 | 사용자 문구 | |---|---|---|---|---| | direct P2P | 피어 사이 | signaling 서버에 최소 기록 | 양쪽이 동시에 접속하고 파일 민감도가 높다 | “브라우저끼리 직접 전송 중” | | TURN relay | relay를 통과하지만 보관하지 않음 | 연결 상태와 비용 지표 | 회사망, NAT, 직접 연결 실패 | “직접 연결이 어려워 중계 경로 사용 중” | | Cloud Drop | 제한된 시간 동안 서버/스토리지에 보관 | 만료, 권한, 수신 상태 | 상대가 나중에 받을 수 있어야 함 | “상대가 돌아오면 받을 수 있게 임시 보관” | | metadata-only edge | payload는 피어 또는 별도 경로 | 가까운 edge에서 정책 판단 | 권한, 결제, 만료 확인이 중요함 | “전송 조건 확인 중” |

현재 구성의 가정
Cloud Drop은 직접 전송 실패의 부끄러운 우회가 아니라 시간차를 다루는 별도 모드다. 상대가 지금 없을 때 사용자는 파일을 다시 보낼지, 임시 보관할지, 나중에 알림을 받을지 선택해야 한다. 이 선택을 “P2P 실패”로만 보이면 제품은 방어적으로 변한다. 모드 전환으로 보이면 payload가 어디에 얼마나 머무는지 공개할 수 있다. edge 위치가 가까워질수록 빠르게 결정할 수 있는 값과 중앙에서만 판단해야 하는 값도 갈라진다.
지역 가까운 edge에서 만료 시간과 임시 토큰을 확인할 수는 있지만, 결제 상태나 abuse 정책처럼 전역 일관성이 필요한 값은 다른 경로가 필요할 수 있다. 모든 정책을 edge로 밀어 넣으면 지연은 줄어도 일관성 문제가 생긴다. 반대로 모든 판단을 중앙에 두면 direct 전송 시작 전에 체감 지연이 커진다. PonsLink와 PonsWarp를 같은 구조로 보면 역할이 조금 갈라진다. PonsLink는 상담, 링크, 권한, 문맥을 다루는 제품 쪽에 가깝고, PonsWarp는 파일 전송과 경로 선택이 더 앞에 온다.
둘 다 P2P라는 단어를 쓸 수 있지만 payload와 metadata의 민감도는 다르다. 그래서 edge 설계에는 “가까워도 되는 판단”과 “중앙에 남아야 하는 판단” 표가 필요하다. 이 표가 없으면 edge는 성능 개선 도구처럼 보이지만 실제로는 책임 위치를 흐리는 새 서버가 된다.

가정을 깨는 사례
이 값이 없으면 “P2P가 느리다”는 문의를 다시 풀 수 없다. direct가 실패한 것인지, relay가 비싼 것인지, policy가 늦은 것인지, cloud drop 만료가 짧은 것인지 따로 봐야 한다. 1. 양쪽이 동시에 접속한 direct P2P 기준을 잡는다. 2. 직접 연결 실패를 만들어 relay 전환 시간을 잰다. 3. 수신자가 사라진 상태에서 Cloud Drop handoff를 제안한다. 4. edge에서 권한과 만료 정책만 판단하는 경로를 분리한다. 5. payload 위치와 metadata 보존 범위를 운영 로그에 남긴다.
순수 P2P는 두 피어가 살아 있고 서로 연결될 수 있으며 전송 중 권한 판단이 끝났다는 전제에서 아름답다. 실제 제품은 이 전제를 자주 잃는다. 상대가 나중에 받을 수 있어야 하고, 모바일 탭이 background로 내려가도 상태가 남아야 하며, 조직 네트워크에서 직접 연결이 막히면 relay가 필요하다. 여기에 파일 민감도, 보관 시간, 결제 상태, 악용 방지 같은 정책이 붙는다.
예를 들어 PonsWarp에서 두 사용자가 동시에 파일을 주고받고 있고 파일이 민감하다면 direct P2P를 먼저 시도하는 편이 맞다. 반대로 수신자가 자주 사라지고 파일이 일정 시간 보관되어도 되는 흐름이라면 Cloud Drop이 더 솔직한 UX가 될 수 있다. 권한 확인은 edge에서 빠르게 하고, payload는 계속 피어 사이로 보내는 선택도 가능하다. 만료 정책은 사용자 문구와 같은 화면에 있어야 한다.
“임시 보관”이라고만 쓰고 시간이 빠지면 임시의 의미가 없다. 1시간인지, 24시간인지, 수신자가 받으면 바로 지우는지, 보낸 사람이 취소할 수 있는지 정해야 Cloud Drop이 실패 우회가 아니라 별도 모드가 된다. 순수 P2P만 약속하면 비동기 수신, 모바일 이탈, TURN 비용, 권한 확인 같은 제품 현실을 전부 예외로 밀어내게 된다. P2P를 설명할 때 서버/클라이언트/사용자 중 누구 문장으로 말하는지 먼저 고르면 논쟁이 줄었다.
분리·중계·직접연결 선택
개인정보 경계는 payload 기준으로 먼저 그린다. 파일 본문을 보관하지 않는 모드, 제한된 시간만 보관하는 모드, metadata만 남기는 모드를 사용자에게 같은 색으로 보여 주면 안 된다. 작은 제품일수록 이 구분을 일찍 고정해야 한다. 나중에 정책 페이지와 support 문구를 맞추려면 처음부터 모드 이름이 선명해야 한다. 측정값은 direct 유지 비율, relay 체류 시간, edge 정책 판단 지연, cloud drop 보관 시간, payload가 서버에 머문 총 시간으로 시작한다.
여기에 사용자 문구를 붙인다. “직접 전송 중”, “중계 경로 사용 중”, “임시 보관 중”, “전송 조건 확인 중”이 내부 상태와 맞지 않으면 혼합 구조는 곧 불신으로 바뀐다. PonsWarp에서는 “파일 본문이 어디에 머무는가”가 가장 먼저 보인다. direct와 relay, cloud drop을 명확히 구분해야 한다. PonsLink에서는 “누가 이 링크와 세션에 접근할 수 있는가”가 먼저 올 수 있다. edge policy와 metadata-only 처리가 더 중요해지는 순간이다.
두 제품을 하나의 순수 P2P 원칙으로 밀어붙이면 필요한 책임이 서로 덮인다. 여기서 남는 기준은 순수 P2P냐 서버 중심이냐의 이분법이 아니다. 책임을 어디에, 얼마나 오래, 어떤 문구로 맡기는가다. edge와 serverless를 섞는 순간에도 payload와 metadata의 위치를 바로 설명할 수 있다면, 그 구조는 P2P를 흐리는 예외가 아니라 제품이 실패를 감당하는 방식이 된다.
다시 짜 본 구조
edge를 쓰면 중앙 서버가 사라지는 것은 아니다. 정책 판단 위치가 사용자 가까이로 이동한다. signaling과 권한 검사는 edge 가까이에 둘수록 체감 지연이 줄어든다. 그렇다고 모든 payload를 edge에 올려야 한다는 뜻은 아니다. payload를 서버에 올릴지 여부는 파일 민감도와 동시 접속 가능성에 따라 달라진다. P2P와 edge/serverless 혼합 구조: 발견, 검증, 운영 경계를 한 장에 겹쳐 둔 흐름 노트. 동의 흐름도 모드마다 달라진다.
direct에서 relay로 넘어가는 것은 중계 비용과 연결 안정성의 문제지만, direct에서 Cloud Drop으로 넘어가는 것은 payload 보관의 문제다. 사용자가 별도 동의 없이 서버 보관 모드로 넘어갔다고 느끼면 기능이 편해도 신뢰가 흔들린다. 자동 전환이 가능한 범위와 명시적 확인이 필요한 범위를 나눠야 한다. 이 표의 목적은 기술 이름을 늘리는 데 있지 않다. 사용자가 “내 파일이 어디에 있나요?”라고 물었을 때 direct, relay, cloud drop을 같은 말로 답하지 않기 위한 최소한의 구분이다.
혼합 구조에서는 사용자가 어떤 경로로 전송 중인지 이해할 수 있어야 한다. 내부 상태가 많아도 화면 문구는 단순할 수 있다. 다만 단순한 문구가 payload 위치를 숨기면 안 된다. '[P2P 설계 edge와 serverless를 P2P와 섞으면 무엇이 달라질까'을 관통하는 질문은 이 섹션에서도 같았고, 답만 더 구체적이 됐다.
실패 모드
- signaling: SDP, candidate, 세션 상태를 교환한다.
- metadata: 파일 크기, 만료 시간, 권한, 모드 전환 기록을 남긴다.
- policy: 보관 가능 여부, 다운로드 권한, 비용 제한을 판단한다.
- relay: 직접 연결이 어려운 순간 byte를 중계한다.
- handoff: 상대가 나중에 받을 수 있도록 비동기 흐름을 연결한다. 혼합 구조 실험은 순수성을 포기했는지 따지는 일이 아니다. 책임 이동을 재는 일이다. 같은 파일을 direct, relay, cloud drop 세 모드로 보내 보고, payload가 서버에 머문 총 시간과 metadata가 남은 범위를 함께 기록한다. “서버를 썼다”보다 “무엇을 얼마 동안 맡겼다”가 더 중요하다. 이 목록을 채우지 않고 “edge 적용”이라고만 적으면 장애가 났을 때 원인이 사라진다. edge 정책이 늦었는지, metadata가 틀렸는지, relay 비용이 늘었는지, cloud drop 만료가 짧았는지 알 수 없다.
direct-active: 직접 경로가 살아 있다.relay-active: 직접 연결이 어려워 relay를 쓰고 있다.handoff-requested: 비동기 수신을 위해 전환을 제안했다.cloud-drop-stored: 제한된 시간 동안 payload를 보관한다.metadata-only: payload는 보관하지 않고 정책과 경로 상태만 남긴다.expired-or-revoked: 만료 또는 권한 철회로 새 전송이 필요하다. 이때 서버를 쓰는지 아닌지만 물으면 판단이 거칠어진다. 더 좋은 질문은 payload와 metadata를 따로 보는 것이다. payload는 사용자의 파일 본문이다. metadata는 파일 크기, 만료 시간, 권한, 경로 상태, retry 기준 같은 운영 단서다. 두 값을 같은 수준으로 다루면 개인정보 경계도 흐려지고 비용 설명도 어려워진다. *P2P와 edge/serverless 혼합 구조: 구현 전에 다시 볼 질문을 현장 노트처럼 정리한다.
마치며
그래서 edge와 serverless를 다시 보게 됐다. 질문은 서버를 다시 늘리자는 쪽이 아니다. 어떤 byte는 피어끼리 보내고, 어떤 책임은 가까운 실행 위치에 잠깐 맡겨야 할까? payload를 항상 서버에 올리는 것과 signaling, metadata, async handoff, 짧은 relay, 정책 판단을 나눠 맡기는 것은 다른 결정이다. 두 제품에 공통으로 필요한 값도 있다. 사용자가 본 문구, 실제 payload 위치, metadata 보존 범위, 모드 전환 시각이다. 이 넷이 같은 trace에 있어야 운영자가 화면과 시스템을 함께 읽는다.
개발자 이벤트만 남기면 support는 사용자의 질문에 답하지 못하고, 화면 문구만 남기면 엔지니어는 원인을 재현하지 못한다. 비용도 같은 방식으로 나눠야 한다. direct는 서버 비용이 작지만 실패 복구를 사용자의 시간에 맡긴다. relay는 보관하지 않아도 대역폭 비용이 생긴다. Cloud Drop은 비동기 수신을 가능하게 하지만 저장 비용과 만료 정책을 요구한다.
metadata-only edge는 payload 비용을 줄이지만 권한 판단과 감사 로그 책임을 남긴다. 비용을 월 청구서 숫자로만 보면 사용자가 기다린 시간과 개인정보 설명 비용이 빠진다. serverless는 긴 전송을 직접 붙잡기보다 짧은 handoff와 정책 판단에 맞다. 이 사실을 놓치면 serverless 함수 안에 긴 연결을 억지로 넣고, timeout과 비용 문제를 뒤늦게 만난다. 혼합 구조에서 serverless가 잘하는 일은 전송 본문을 계속 들고 있는 것이 아니라 상태 전환을 안전하게 기록하는 쪽이다.