일반 결제는 송신자가 자신의 입력만 골라 거래를 완성하지만 PayJoin은 수신자가 자신의 입력과 필요하면 출력을 더한 PSBT 제안을 돌려줍니다. 송신자는 원래 지급액, 자신의 입력·거스름돈, 수수료와 거래 필드가 안전한지 검증한 뒤 자기 입력만 다시 서명해 방송합니다. 두 당사자의 입력이 섞여 공통 입력 소유 추정을 약화하지만, 지원 지갑과 통신 endpoint가 필요합니다.
일반 결제와 달리 거래를 두 당사자가 함께 만듭니다
일반 비트코인 지급에서는 송신자가 자신의 UTXO를 입력으로 선택하고 수신 주소 출력과 거스름돈 출력을 만든 뒤 서명·방송합니다. PayJoin은 수신자가 BIP 21 URI의 `pj` endpoint를 알리고, 송신자가 먼저 서명한 original PSBT를 그 endpoint에 보내는 상호작용을 추가합니다.
수신자는 자신의 서명된 입력과 필요한 출력을 더한 PayJoin proposal을 반환할 수 있습니다. 송신자는 이 제안이 원래 지급 의도를 훼손하지 않았는지 검사한 뒤 자신의 원래 입력을 다시 서명합니다. 최종 거래만 보면 여러 입력이 한 당사자 것이라는 전형적 모양이 더 이상 확실하지 않습니다.
PayJoin의 핵심은 코인을 섞는 이름이 아니라 수신자도 실제 결제 거래의 입력 구성에 참여한다는 점입니다.
JOBCOIN 해설

그림은 이 주제의 공통 개념을 단순화한 설명입니다. 아래 항목에서 이 글의 구체적인 조건과 예외를 함께 읽어보세요.
- 일반 결제와 달리 거래를 두 당사자가 함께 만듭니다
일반 비트코인 지급에서는 송신자가 자신의 UTXO 를 입력으로 선택하고 수신 주소 출력과 거스름돈 출력을 만든 뒤 서명·방송합니다.
- 제안 전후의 금액을 숫자로 대조합니다
가정으로 송신자의 original PSBT가 120,000 sat 입력, 80,000 sat 지급, 38,000 sat 거스름돈, 2,000 sat 수수료라고 하겠습니다.
- 송신자는 자신의 입력만 서명해야 합니다
제안에는 원본의 모든 송신자 입력과 수신자가 소유하지 않는 원본 출력이 유지돼야 합니다.
AI로 제작한 개념도 · 실제 가격·거래 내역·통계가 아닙니다.
제안 전후의 금액을 숫자로 대조합니다
가정으로 송신자의 original PSBT가 120,000 sat 입력, 80,000 sat 지급, 38,000 sat 거스름돈, 2,000 sat 수수료라고 하겠습니다. 수신자가 30,000 sat 입력을 추가하면 제안의 입력 합계는 150,000 sat가 됩니다. 추가 출력과 수수료 변화까지 합계가 맞아야 하며 원래 송신자 출력이 허용 범위 밖으로 줄어서는 안 됩니다.
BIP 78은 제안의 절대 수수료가 원본보다 낮지 않아야 하고, 송신자의 추가 수수료 기여가 수신자 추가 입력으로 생긴 비용을 넘지 않게 검사하도록 규정합니다. 단순히 총입력 값이 늘었다는 이유로 안전하다고 판단하면 안 됩니다. 원본과 제안의 각 입력·출력·수수료를 항목별로 비교해야 합니다.
| 단계 | 일반 결제 | PayJoin |
|---|---|---|
| 지급 요청 | 주소·금액 | BIP21과 pj endpoint |
| 입력 구성 | 주로 송신자 입력 | 송신자와 수신자 입력 가능 |
| 서명 전 확인 | 송신자가 만든 거래 확인 | 수신자 제안을 원본과 비교 |
| 실패 처리 | 방송 실패 처리 | 협상 실패와 fallback 정책 확인 |
송신자는 자신의 입력만 서명해야 합니다
제안에는 원본의 모든 송신자 입력과 수신자가 소유하지 않는 원본 출력이 유지돼야 합니다. 거래 version, nLockTime과 송신자 입력 sequence도 바뀌지 않았는지 확인합니다. 수신자가 추가한 입력은 이미 finalize되어야 하고 송신자 키 경로나 부분 서명이 그 입력에 섞여서는 안 됩니다.
지급 출력 대체가 허용된 경우 수신자는 자신의 출력 스크립트나 금액 구성을 바꿀 수 있지만 송신자 지갑은 BIP21의 `pjos=0` 신호와 사용자 정책을 따라야 합니다. 하드웨어 지갑 화면이 최종 지급액과 예상 거스름돈을 충분히 보여주지 못하면 복잡한 제안을 승인하지 않는 편이 안전합니다.
- BIP21 URI의 주소·금액·pj endpoint를 확인합니다.
- 원본과 제안의 입력·출력 목록을 나란히 비교합니다.
- 절대 수수료와 추가 수수료 기여 상한을 계산합니다.
- 송신자 입력의 sequence와 nLockTime 변경 여부를 확인합니다.
- 서명 후 최종 txid와 실제 방송 상태를 기록합니다.
프라이버시 효과는 휴리스틱 약화이지 익명성 보증이 아닙니다
수신자 입력이 들어가면 모든 입력이 송신자 소유라는 common-input 가정이 틀릴 수 있습니다. 수신자는 지급 출력 유형을 조정하거나 별도 지급을 배치해 거스름돈 스크립트 유형과 둥근 금액 휴리스틱도 약화할 수 있습니다. PayJoin 거래가 존재한다는 사실 자체가 일반 거래 분석의 확신도를 낮춥니다.
하지만 endpoint 접근 기록, 주문 정보, 지갑 로그 같은 체인 밖 자료는 별도로 남을 수 있습니다. 수신자가 반복적인 입력 형태를 쓰거나 송신 지갑이 독특한 수수료 패턴을 만들면 다른 단서도 생깁니다. PayJoin 하나로 상대에게서 신원과 금액을 모두 숨긴다고 홍보해서는 안 됩니다.
수신자는 UTXO probing과 재사용을 방어해야 합니다
자동 결제 서버가 요청마다 다른 수신자 UTXO를 제안하면 공격자가 original 거래를 여러 번 보내 제안을 받기만 하고 방송하지 않으면서 수신자 UTXO를 알아낼 수 있습니다. BIP 78은 원본 입력이 이전에 보이지 않았는지 검사하고, 노출된 UTXO를 우선 재사용하는 완화책을 설명합니다.
비대화식 서버는 original 거래가 실제 방송 가능한지도 확인해야 합니다. endpoint에 요청 제한, 주문별 일회성 상태, 타임아웃과 감사 로그를 두고 실패했다고 곧바로 새 수신자 UTXO를 계속 노출하지 마세요. 서버 운영 보안은 지갑의 제안 검증만큼 중요합니다.
지원 실패와 결제 실패를 별도 상태로 기록합니다
송신 지갑이 `pj`를 이해하지 못하면 일반 BIP21 결제로 진행할 수 있습니다. endpoint가 응답하지 않거나 버전이 맞지 않는 경우에도 지갑별 fallback 동작이 다를 수 있습니다. 사용자는 PayJoin 협상 실패인지 최종 온체인 거래 방송 실패인지 구분해야 중복 결제를 피할 수 있습니다.
결제 후에는 원본 PSBT를 실수로 추가 방송하지 않았는지, 최종 txid가 주문과 연결됐는지 확인하세요. 자동 시스템은 `제안 요청`, `제안 검증`, `최종 서명`, `방송 수락`, `확인`을 별도 상태로 저장해야 합니다. HTTP 성공 응답만으로 온체인 결제 완료를 표시하면 안 됩니다.
자주 묻는 질문
PayJoin이면 수신자가 제 코인을 가져갈 수 있나요?
송신자가 제안을 규격대로 검증하고 자신의 원래 입력만 서명한다면 임의 탈취를 막도록 설계돼 있습니다. 지갑 구현과 최종 화면 확인이 중요합니다.
수신자도 비트코인을 추가로 지불하나요?
수신자가 입력을 추가할 수 있지만 자신의 출력도 조정할 수 있습니다. 순지급 효과와 추가 수수료는 완성 거래 전체로 계산해야 합니다.
PayJoin endpoint가 실패하면 결제도 끝난 건가요?
아닙니다. 협상 실패와 일반 결제 fallback, 실제 거래 방송 여부를 지갑 상태와 txid로 따로 확인하세요.



