전화번호 없는 Signal — 영지식 증명이 대신하는 것과 대신하지 못하는 것

전화번호를 걷어 낸 자리에 들어오는 것은 프라이버시인가, 아니면 다른 이름의 신원 확인인가?

도입

2026년 9월 13일(UTC), 해커뉴스 1면에 「Signal에서 전화번호 없는 가입은 영지식 증명을 사용할 것이다」라는 제목의 글이 올라와 397점을 받았다. 링크는 Signal 공식 블로그가 아니라 Signal 커뮤니티 포럼의 오래된 스레드 「Registration without a phone number」의 10페이지였다. 이 스레드의 글 번호는 이미 200을 넘는다. 전화번호 없이 가입하게 해 달라는 요구는 그만큼 오래되었다.

이번에 달라진 것은 요구가 아니라 증거다. 8월 중순부터 Signal-Android 공개 저장소에 「numberless」라는 단어가 들어간 커밋이 줄지어 올라왔고, 포럼 이용자들은 베타 릴리스마다 그것을 퍼 날랐다. 8월 17일 「전화번호 없는 가입을 위한 네트워크 자리표시자 추가」, 9월 2일 「전화번호 없는 계정을 등록하는 기본 기능 추가」와 「전화번호 없는 계정에 새 zkgroup 자격증명 사용」, 9월 9일 「Signal 로그인 결제 기능 추가」가 그 흐름이다.

해커뉴스 제목은 영지식 증명(ZKP)을 앞세웠지만, 커밋을 직접 열어 보면 이야기의 중심은 결제다. 전화번호 대신 일회성 구매가 들어오고, 영지식 증명은 그 구매가 계정과 연결되지 않도록 하는 장치로 쓰인다. 그렇다면 질문은 이렇게 바뀐다. 전화번호가 Signal에서 하던 일은 무엇이었고, 결제와 영지식 증명의 조합은 그중 어디까지를 대신하는가.

이 글은 커밋과 포럼, 해커뉴스 토론에서 확인되는 사실을 먼저 정리하고, 그 위에서 분석을 따로 덧붙인다. 출시일과 가격 등 아직 공개되지 않은 부분은 그렇다고 적는다.

커밋이 말해 주는 것

먼저 9월 9일 커밋 「Add ability to pay for a signal login」의 구조부터 보자. 이 커밋은 Google Play의 일회성 상품 구매를 다루는 billing 모듈과, 가입 화면의 결제 단계를 추가한다. 서버 API 쪽에는 GET /v1/subscription/configuration 에서 「login」 항목을 읽어 오는 함수가 생겼다. 응답에는 판매할 Play 상품 ID와 함께, 그 구매가 갖는 「영수증 레벨(receipt level)」이 들어 있다. 클라이언트 코드는 이 값을 300으로 두고, App Store 상품 ID 필드도 정의해 두되 Android에서는 쓰지 않는다고 주석에 적었다. iOS 경로도 설계에 들어가 있다는 뜻으로 읽히지만, iOS 쪽 구현은 이 글에서 확인하지 못했다.

핵심은 결제 이후의 흐름이다. 코드가 import하는 클래스 이름이 이를 그대로 보여 준다. 클라이언트는 무작위 ReceiptSerial 을 만들고, 그것으로 ReceiptCredentialRequestContext 를 생성한다. 서버가 Play 구매를 확인한 뒤 ReceiptCredentialResponse 를 돌려주면, 클라이언트는 이를 검증해 ReceiptCredential 을 받는다. 그리고 가입할 때는 그 자격증명 자체가 아니라 그것으로부터 만든 ReceiptCredentialPresentation 을 제출한다. 9월 2일 커밋의 주석은 이렇게 정리한다. 가입 요청에는 SMS 세션 ID, 복구 비밀번호, 영수증 자격증명 프레젠테이션 중 정확히 하나를 제공해야 하며, 프레젠테이션을 내면 전화번호가 없는 계정이 만들어진다. 이때 전화번호 필드와 PNI용 사전 키는 반드시 비어 있어야 하고, 「전화번호로 검색 가능」 속성도 null이어야 한다.

이 zkgroup.receipts 계열은 새로 만든 것이 아니다. Signal은 2025년 9월 보안 백업을 소개하면서 월 1.99달러의 유료 플랜을 내놓았고, 「그룹을 메타데이터 노출 없이 작동시키는 것과 같은 영지식 기술」을 써서 백업 아카이브를 특정 결제나 계정과 직접 연결하지 않고 저장한다고 밝혔다. 포럼에서 한 이용자는 기부 배지와 백업이 비슷하게 작동한다고 설명했다. Signal은 결제한 사람의 목록은 갖지만, 클라이언트가 「그중 하나」임을 증명할 뿐 「누구」인지는 드러내지 않는다는 것이다. 정확한 암호학적 구성은 포럼 글이 설명하는 것보다 복잡하겠지만, 이번 가입 경로가 기존의 결제-비연결 인프라를 재사용한다는 점은 import 목록에서 확인된다.

결제 흐름의 세부도 흥미롭다. 저장소 코드 주석에 따르면 구매는 상환되기 전에 먼저 디스크에 저장되고, 결제 후 어디서 실패하든 다시 시작하면 같은 구매를 이어서 쓴다. 서버는 같은 구매를 다른 요청으로 다시 상환하려 하면 거부하며, 그래서 이미 상환된 구매에 새 요청 컨텍스트를 만들면 영구적인 「AlreadyRedeemed」 오류가 난다고 적혀 있다. 구매는 상환 후에야 Play에서 「소비(consume)」 처리되고, 그래야 두 번째 계정을 위해 다시 살 수 있다. 즉 한 번의 결제는 정확히 하나의 계정이 된다.

또 하나의 커밋이 눈에 띈다. 「Use new zkgroup credential for numberless accounts」는 그룹 인증 코드를 고친다. 기존에는 그룹 서버에 자신을 증명하는 자격증명이 ACI(계정 식별자)와 PNI(전화번호 식별자)를 함께 묶었다. 전화번호 없는 계정에는 PNI가 없으므로, 새 코드는 PNI가 없을 때 서버가 가입 시점에 내려준 솔트를 대신 넣는 receiveAuthCredentialWithoutPni 경로를 탄다. 전화번호는 가입 관문만이 아니라 그룹 프로토콜의 자격증명 구조에까지 스며들어 있었다는 이야기다.

마지막으로 가입 이후의 계정 모습이다. 다른 커밋들은 전화번호 검색 가능 설정을 숨기고 기본값을 false로 고정하며, PIN 알림을 끄고, 백업 온보딩을 손본다. 8월 말 커밋들은 사용자명을 가입 과정에서 바로 정하게 하고, 이용자 제보에 따르면 TOTP나 물리 보안 키를 이용한 2단계 인증도 선택지로 보인다. 전화번호 없는 계정은 「사용자명 + 별도의 로그인 자격」이라는, 우리가 웹 서비스에서 익숙한 형태에 가까워진다.

전화번호가 하던 일, 영지식 증명이 대신하는 일

여기서부터는 분석이다. 전화번호는 Signal에서 적어도 두 가지 역할을 동시에 맡아 왔다. 하나는 연락처 발견, 즉 주소록에 있는 사람이 Signal을 쓰는지 알아내는 식별자 역할이다. 다른 하나는 가입 비용, 곧 한 사람이 계정을 무한히 찍어 낼 수 없게 하는 시빌(sybil) 방어 역할이다.

첫 번째 역할은 이미 2024년에 상당 부분 분리되었다. Signal은 2024년 2월 사용자명을 도입하면서 전화번호를 대화 상대에게 기본적으로 보이지 않게 했고, 「전화번호로 나를 찾을 수 있는 사람」을 「아무도」로 설정하는 옵션을 추가했다. 다만 당시 공지는 괄호 안에 분명히 적었다. 가입하려면 여전히 전화번호가 필요하다고. 즉 식별자로서의 노출은 줄였지만, 서버와 통신사가 「이 번호가 Signal 계정을 갖고 있다」는 사실을 아는 구조는 남았다.

두 번째 역할이 이번 변화의 본체다. 해커뉴스에서 karel-3d는 「문지기 없음」, 「누구나 누구에게나 메시지를 보낼 수 있음」, 「낮은 스팸」의 세 가지를 동시에 가질 수는 없다고 요약했다(직접 인용은 아니고, 코멘트의 요지를 요약). EGreg와 iamsyr도 같은 질문을 던졌다. 전화번호를 빼면 시빌 공격은 무엇으로 막는가, 공격자가 싸게 찍어 낼 수 없는 것이 무엇인가(직접 인용은 아니고, 코멘트의 요지를 요약).

커밋이 내놓은 답은 단순하다. 돈이다. 9월 16일에 공개된 8.28 베타 공지는 이를 명시했다(아래 추기 참조). 그런데 전화번호와 돈은 비용으로서 성격이 다르다. Cider9986은 Signal 가입용 전화번호를 10센트 남짓에 살 수 있고, 스패머는 더 싸게 구할 것이라고 지적하면서, 그래도 번호를 잃어버릴 걱정이 없으니 자신은 돈을 낼 것이라고 했다(직접 인용은 아니고, 코멘트의 요지를 요약). 이 지적이 맞다면 전화번호는 스패머에게는 이미 싼 비용이었고, 오히려 정상 이용자에게 비싼 비용이었다. 번호를 바꾸면 계정이 흔들리고, 해외로 이주하면 SMS가 오지 않고, 검열 국가에서는 인증 코드 자체가 도착하지 않는다. 포럼의 러시아 이용자는 SMS 코드가 오지 않거나, 결제하면 처벌받을 위험이 있어 두 선택지 모두 맞지 않는다고 썼다.

결제 기반 비용의 장점은 가격을 서비스가 직접 정할 수 있다는 것이다. 전화번호의 가격은 통신 시장과 가상 번호 업자가 정하지만, 「Signal 로그인」의 가격은 Signal이 서버 설정으로 정한다. 코드가 상품 ID와 레벨을 서버에서 받아 오도록 설계된 것은 이 다이얼을 손에 쥐겠다는 뜻으로 읽힌다. 다만 9월 14일 시점에 가격은 공개되지 않았다. 포럼에서는 가격대를 묻는 투표가 열렸을 뿐이다.

ynniv는 「영지식」이라고 손을 흔든다고 프라이버시가 생기지는 않으며, 이 정보만으로는 판단할 수 없다고 썼다(직접 인용은 아니고, 코멘트의 요지를 요약). 이 회의는 정당하다. 그러니 무엇이 증명되고 무엇이 증명되지 않는지를 구분해 보자.

영지식 영수증 자격증명이 대신하는 것은 「서버 데이터베이스 안의 연결고리」다. 서버는 Play 구매 토큰을 검증하고 자격증명을 발급한다. 나중에 가입 요청에 프레젠테이션이 도착하면, 서버는 그것이 유효한 미사용 자격증명이라는 것은 알지만 어느 발급 건에서 나왔는지는 수학적으로 연결할 수 없도록 설계되어 있다. teravor는 이런 「쿠폰을 사서 귀속 없이 쓰는」 구조라면 블라인드 서명으로도 충분하다고 짚었다(직접 인용은 아니고, 코멘트의 요지를 요약). PinkiesBrain은 결제 참조가 서버 DB에 있으면 결국 식별 가능하지 않느냐고 물었는데(직접 인용은 아니고, 코멘트의 요지를 요약), 바로 그 연결을 끊는 것이 이 자격증명의 역할이다. 서버가 갖는 것은 「결제가 있었다」와 「계정이 생겼다」라는 두 개의 분리된 사실이고, 그 사이의 화살표는 저장되지 않는다.

그러나 영지식 증명이 대신하지 못하는 것이 최소 세 가지 있다.

첫째, 결제 대행자가 아는 것이다. Google Play는 어느 Google 계정이 「Signal 로그인」 상품을 샀는지 안다. opengrass는 커밋상 Google Play Billing 구매가 필요하다고 정리했고, wolvoleo는 Android에서 Google 계정을 요구한다면 받아들일 수 없다고 반발했다(둘 다 직접 인용은 아니고, 코멘트의 요지를 요약). mr_big_bowls는 이를 한 식별자를 다른 식별자로 바꾼 것 아니냐고 표현했다(직접 인용은 아니고, 코멘트의 요지를 요약). 영지식 증명은 Signal 서버 쪽의 연결을 끊을 뿐, 「이 사람이 Signal 계정을 하나 샀다」는 사실이 결제 쪽에 남는 것은 막지 못한다. 전화번호 가입에서 통신사가 알던 사실이 결제 회사로 옮겨 갈 뿐이다. 그나마 차이가 있다면, 통신사는 번호와 실명을 묶고 있는 경우가 많고, Play 계정은 선불 기프트 카드 등으로 비교적 느슨하게 만들 수 있다는 점이다. 포럼에서도 현금으로 스토어 크레딧을 사는 방법이 언급되었다.

둘째, 타이밍과 네트워크 상관이다. 이 흐름에서는 구매, 자격증명 발급, 가입이 한 화면에서 몇 초 간격으로 일어난다. 영지식 증명은 데이터베이스 레코드 사이의 수학적 연결을 끊지만, 같은 IP에서 몇 초 차이로 도착한 두 요청을 서버가 로그로 보관한다면 통계적으로 다시 묶을 수 있다. 기부나 백업처럼 결제와 상환 사이에 시간이 벌어질 수 있는 경우와 달리, 가입은 결제 직후에 상환하는 것이 자연스러운 흐름이다. 이는 코드에서 확인된 취약점이 아니라 구조에서 나오는 추론이며, Signal이 이런 로그를 남기는지는 확인되지 않았다. 다만 「영지식」이라는 말이 보장하는 범위가 어디까지인지 생각할 때 빼놓을 수 없는 지점이다.

셋째, 스팸 그 자체다. 영지식 증명은 비용을 지불했다는 사실을 익명으로 증명할 뿐이다. 비용이 얼마인지는 증명의 문제가 아니라 가격 정책의 문제다. 가격이 10센트짜리 가상 번호보다 낮다면 스패머에게는 오히려 더 좋은 경로가 된다. 높다면 정상 이용자, 특히 Signal이 가장 필요한 지역의 이용자에게 장벽이 된다. 포럼의 한 이용자가 지적했듯, 이미 가입한 전화번호 계정의 번호를 「연결 해제」하는 기능을 무료로 주면 번호 하나로 가입과 해제를 반복해 계정을 무한히 만들 수 있다. 커밋은 지금까지 신규 가입 경로만 다루고 있으며, 기존 계정의 번호 분리는 근거가 보이지 않는다.

정리하면, 영지식 증명은 「Signal이 누가 돈을 냈는지 모르게 하는 것」을 대신한다. 「누가 돈을 냈는지 아무도 모르게 하는 것」과 「돈이 스팸을 막을 만큼 충분한 것」은 대신하지 못한다. 전자는 결제 수단의 문제이고, 후자는 경제학의 문제다.

전망과 시사점

몇 가지 신호를 정리해 두자. 첫째, 결제 수단의 다양화가 다음 쟁점이 될 것이다. 해커뉴스와 포럼 모두에서 Monero나 Bitcoin, 혹은 Signal 앱에 이미 있는 암호화폐 결제를 쓰자는 요구가 나왔다. 코드가 상품 정의를 서버 설정으로 빼 두고 App Store 필드까지 마련한 것을 보면, 결제 경로를 추가하는 구조적 여지는 있다. 다만 어떤 결제 수단이 추가될지는 근거가 없다.

둘째, 이 설계는 「번호 없는 메신저」 진영과의 차별점을 분명히 한다. user10235는 SimpleX와 Delta Chat이 이미 수년 전부터 결제 없이 번호 없는 가입을 제공한다고 지적했다(직접 인용은 아니고, 코멘트의 요지를 요약). 그 프로젝트들은 전역 식별자 자체를 없애는 방향을 택했다. Signal은 중앙 서버와 전역 계정을 유지하면서, 서버가 알 수 있는 것을 수학적으로 줄이는 방향을 택했다. 같은 「번호 없음」이지만 위협 모델이 다르다.

셋째, sarjann이 언급했듯 AI 에이전트용 계정처럼 사람 아닌 주체가 메신저 계정을 필요로 하는 경우가 늘고 있다(직접 인용은 아니고, 코멘트의 요지를 요약). 결제 기반 가입은 그런 수요에 길을 열어 주는 동시에, 「한 사람 한 번호」라는 묵시적 상한이 사라진다는 뜻이기도 하다. 계정 하나의 가격이 곧 자동화된 계정 하나의 가격이 된다.

넷째, 가장 실무적인 시사점은 설계 방법론이다. 하나의 식별자가 여러 역할을 겸하고 있을 때, 그것을 제거하려면 역할을 하나씩 떼어 내야 한다. Signal은 2024년에 발견 기능을, 2026년에 가입 비용을 분리하고 있으며, 그 과정에서 그룹 자격증명처럼 숨어 있던 의존성까지 고쳐야 했다. 자신이 운영하는 서비스에서 이메일이나 전화번호가 몇 가지 역할을 동시에 맡고 있는지 세어 보는 것은 의미 있는 연습이다.

(9월 16일 추기: 포럼 스레드에 따르면 Android 8.28 베타 공지는 전화번호 없이 선택적으로 가입할 수 있게 되었으며, 스팸 방지를 위해 소액의 일회성 요금이 필요하지만 이 인앱 구매는 새 Signal 계정과 직접 연관되지 않는다고 밝혔다. 9월 17일에는 당분간 Google Play로만 결제할 수 있다는 점이 포럼에서 지적되었고, 9월 23일에는 「Enable phoneless registration」 커밋이 공유되었다. 가격은 이 글이 확인한 자료에서는 찾지 못했다.)

결론

해커뉴스 제목은 영지식 증명을 앞에 세웠지만, 커밋을 따라가 보면 이번 변화의 실체는 「전화번호라는 비용을 돈이라는 비용으로 바꾸는 것」이고, 영지식 증명은 그 교환이 Signal 서버에 새로운 연결고리를 남기지 않도록 하는 보조 장치다. 그 장치는 이미 기부와 백업에서 쓰이던 것이다.

이 교환은 정상 이용자에게 분명한 이득이 있다. 번호를 잃어도 계정이 흔들리지 않고, 통신사가 「이 번호는 Signal을 쓴다」는 사실을 알 필요가 없다. 그러나 결제 회사가 아는 것, 몇 초 간격으로 도착하는 요청의 상관관계, 그리고 가격이 스팸을 막기에 충분한지라는 문제는 수학이 풀어 주지 않는다.

그러니 「영지식」이라는 말을 들었을 때 물어야 할 것은 하나다. 누구에 대해 무엇을 모르게 하는가. Signal의 답은 「Signal 서버가, 결제와 계정의 연결을」이다. 그 답이 당신의 위협 모델에 충분한지는, 당신이 걱정하는 상대가 Signal인지 Google인지 통신사인지에 달려 있다.


출처: