아키텍처
SCOPE Connect는 브라우저의 dApp, SCOPE Connect 서버, 사용자의 지갑 세 영역에서 동작합니다. 각 영역은 다룰 수 있는 값과 책임이 다릅니다. 이 문서는 구성 요소와 역할, 어떤 값을 어디에 두어야 하는지 정리합니다.
구성 요소와 역할
| 구성 요소 | 담당 | 누가 만드나 |
|---|---|---|
| dApp 화면 | AppKit 호출로 지갑 연결·서명·전송 기능 구현, 서비스 화면과 UI 구성 | dApp 개발자 |
| AppKit | 지갑 연결과 서명 요청, 릴레이 페어링 QR 생성, 잔액 조회 등 부가 기능 제공 | SCOPE Connect |
| Connect 백엔드 | 프로젝트 설정과 앱 식별, 릴레이 토큰·모바일 세션, 선택적 텔레메트리, Nodit 기반 잔액 조회 제공 | SCOPE Connect |
| Relay | dApp과 WalletKit을 암호화된 채널로 연결 | SCOPE Connect |
| WalletKit | AppKit과 연동해 지갑 연결·서명 결과를 AppKit으로 전달 | 지갑 제공사 |
두 SDK는 연결과 전송을 맡습니다. AppKit 코어는 모달·QR·딥링크에 필요한 데이터만 반환하므로 서비스 화면은 dApp이 만들고, React 바인딩을 사용하면 지갑 목록과 릴레이 QR 같은 기본 UI를 바로 쓸 수 있습니다. WalletKit은 사용자 동의를 대신하지 않습니다. 사용자에게 무엇을 보여주고 무엇을 승인받을지는 dApp과 지갑 앱이 정합니다.
데스크톱 주입형 연결은 AppKit과 브라우저 확장 지갑이 직접 통신합니다. 프로젝트 설정(활성 지갑·네트워크) 조회, 릴레이 토큰 발급, 모바일 지갑 세션, 잔액 조회와 활성화된 텔레메트리는 Connect 백엔드를 사용합니다.
값의 노출 범위
브라우저에 노출해도 되는 값과 서버에만 두어야 하는 값을 먼저 구분합니다. dApp 가이드와 지갑 가이드의 보안 항목은 이 구분을 전제로 합니다.
| 값 | 위치 | 브라우저 노출 | 비고 |
|---|---|---|---|
clientId (X-App-Key) | 브라우저 dApp + 백엔드 | 가능 | 공개 식별자 |
| Client Secret | 서버 비밀 저장소 | 불가 | 서버 전용 |
relayToken | 브라우저의 단기 세션 | 가능 | 세션 한정 토큰 |
페어링 URI의 symKey | dApp과 지갑 사이 | 제한적 | 릴레이에 전달되지 않는 종단 간 암호화 키 |
| 서명 키 | 지갑 제공사가 통제하는 보안 환경 | 해당 없음 | SCOPE Connect 서버는 수집·저장하지 않음 |
브라우저 번들에 지속적으로 포함할 수 있는 값은 공개 식별자뿐입니다. 수명이 짧은 세션 토큰과 페어링 URI는 연결 중 메모리에서만 다룹니다. 장기 비밀은 서버 비밀 저장소에 두고, 서명 키의 보관·사용 방식은 지갑 제공사의 보안 구조에 따릅니다.
SCOPE Connect 서버와 AppKit은 개인키를 수집하거나 저장하지 않습니다. WalletKit의 세션 API는 지갑 앱이 제공한 Signer에 서명을 요청하며, 키 생성·보관·인증·백업·복구 방식은 지갑 제공사가 결정합니다. 키는 HSM·MPC·플랫폼 키 저장소처럼 지갑 제공사가 통제하는 보안 환경에 둘 수 있습니다. 단, 지갑 앱이 InMemorySigner 또는 개인키 바이트를 직접 받는 서명 함수를 사용하면 키 바이트가 해당 앱의 프로세스 메모리에서 처리됩니다.
릴레이도 내용을 볼 수 없습니다. 세션 메시지는 채널 대칭키로 암호화된 ChaCha20-Poly1305 AEAD 데이터(IV ‖ 암호문 ‖ 태그)로 전송되며, 복호화는 세션 키를 가진 dApp과 지갑만 수행합니다. 페어링 채널은 URI로 공유한 symKey_P를, 세션 채널은 X25519 ECDH 공유 비밀에서 HKDF-SHA256으로 파생한 symKey_S를 씁니다. 그래서 대칭키가 담긴 페어링 URI는 QR·딥링크로만 전달하고 릴레이에는 싣지 않습니다.
페어링 URI에는 세션을 복원할 수 있는 대칭키가 들어 있습니다. 이 URI와 relayToken, 관련 쿼리 파라미터를 로그, 오류 리포트, URL 기록, 분석 도구에 남기지 마세요. 개인키와 서명 요청 원문도 마찬가지입니다.
온체인 제출
dApp은 트랜잭션 데이터를 만들어 AppKit Operations의 request()에 eth_sendTransaction으로 전달합니다. AppKit은 이 요청을 활성 연결로 라우팅하고, 지갑이 서명과 브로드캐스트를 수행한 뒤 트랜잭션 해시를 돌려줍니다. 해시는 제출 결과일 뿐이므로 블록 포함과 확정 여부는 dApp이 이어서 확인합니다. 구현 예시는 결제 요청에서 다룹니다.
EIP-3009 가스리스 전송은 경로가 다릅니다. AppKit Operations의 signTransferAuthorization()은 서명만 받고, 구조화 데이터 생성과 가스 대납·온체인 제출은 dApp의 서버가 맡습니다. 가스 대납은 SCOPE Connect가 제공하는 기능이 아니며, 문서의 관련 예제는 외부 로직을 호출하는 방법을 보여 주는 예시입니다.
다음 단계
- AppKit 개요 — dApp의 연결 방식과 통합 순서
- WalletKit 개요 — 지갑의 릴레이 세션 처리 범위
- AppKit 오류 처리 — dApp에 반환되는 오류 코드
- WalletKit 오류 처리 — 지갑 응답과 dApp 오류의 대응 관계