ERC-5219 컨트랙트 리소스 요청 (Contract Resource Requests)
Final · 기타 · 2022-07-10 작성
스마트 컨트랙트에 웹 페이지를 요청하듯 리소스를 요청하고 상태 코드와 본문, 헤더가 있는 HTTP 비슷한 응답을 받는 인터페이스를 정합니다. 탈중앙 앱의 화면을 중앙 서버 없이 체인 위에서 제공할 수 있게 합니다.
왜 필요한가
이더리움은 탈중앙 앱(DApp)을 만드는 데 가장 널리 쓰이는 블록체인이지만 정작 그 앱을 쓰려면 먼저 중앙 서버에 올라간 웹사이트에 접속해 화면 코드를 받아야 합니다. 뒷단의 컨트랙트는 체인 위에 있어도 앞단의 화면은 한 회사의 서버에 의존하는 셈입니다. 원문은 여기서 네 가지 위험을 짚습니다. 믿어야 하는 주체가 불필요하게 많아지고 중앙 웹사이트는 검열을 막지 못합니다. 화면 코드를 영구히 보존할 장치가 없고 스마트 컨트랙트가 다른 앱의 화면과 직접 상호작용할 수 없습니다. 이 표준은 컨트랙트 자체가 화면에 필요한 리소스를 돌려줄 수 있게 요청과 응답의 모양을 정해 앱의 앞단까지 체인 위에서 제공할 길을 엽니다.
심층 설명
무엇을 표준화하나
이 표준은 스마트 컨트랙트에 리소스를 요청하고 HTTP 비슷한 응답을 받는 인터페이스를 정합니다. DApp 컨트랙트는 원문에 첨부된 IDecentralizedApp.sol 파일의 인터페이스를 반드시(MUST) 구현해야 합니다. 원문 본문에는 함수 선언이 직접 실려 있지 않고 첨부 파일을 가리키므로, 구현할 때는 그 파일을 기준으로 삼아야 합니다. 응답의 모양은 Note to Implementers의 예시로 알 수 있습니다. statusCode, body, 그리고 key와 value 쌍으로 된 headers 목록으로 이루어집니다. RFC 2119의 MUST, SHOULD, MAY 같은 낱말이 원문 요구 수준을 나타냅니다.
이름 해석과 하위 호환
이름 해석(어떤 이름이 어느 컨트랙트를 가리키는지 찾는 방법) 자체는 이 표준이 정하지 않습니다. 이름 해석 메커니즘을 제안하는 EIP가 이 표준을 참조할 수 있고(MAY), 클라이언트가 자기 메커니즘을 지원하도록 권할 수 있습니다(MAY). 클라이언트는 RFC 1034와 RFC 1035에 정의된 일반 DNS도 지원할 수 있습니다(MAY). 하위 호환성 절은 이 표준이 Name Resolution 절에 열거된 표준들과 하위 호환된다고 밝힙니다. 즉 어떤 이름 체계를 쓰든 그 뒤의 요청과 응답 형식은 이 표준으로 통일할 수 있습니다.
관심사 분리: 앞단 컨트랙트와 뒷단 컨트랙트
애플리케이션 로직과 프론트엔드 로직을 분리하는 것이 권장됩니다(RECOMMENDED). 여기서 프론트엔드 로직은 위 인터페이스를 구현한 컨트랙트를 뜻합니다. Rationale은 그 이유를 이렇게 설명합니다. 복잡한 프론트엔드 로직을 컨트랙트에 저장하면 배포 비용이 크고 그런 로직은 최종 사용자의 기기에서 실행하는 쪽이 낫습니다. 또 프론트엔드 컨트랙트가 백엔드 컨트랙트와의 상호작용까지 신경 쓰지 않아도 되도록 역할을 나눕니다.
request는 읽기 전용
request 메서드는 읽기 전용으로 정해졌습니다. 모든 데이터는 해석된 DApp 쪽에서 컨트랙트로 보내야 한다는 생각에서입니다. 요청을 보내기 위해 트랜잭션을 제출하면 비용이 들고 트랜잭션이 채굴될 때까지 기다려야 하므로 사용자 경험이 나빠집니다. 상태를 바꾸는 동작이 필요하면 307 Temporary Redirect 상태 코드와 함께 다른 EIP를 사용해 요청할 수 있습니다. 즉 화면을 받아 오는 길과 상태를 바꾸는 길을 분리합니다.
HTTP를 그대로 흉내 내지 않는 이유
완전한 HTTP 요청을 흉내 내는 대신 크게 줄인 형태를 택했습니다. 원문은 세 가지 이유를 듭니다. 실제로 의미 있는 HTTP 메서드는 GET 하나뿐입니다. 쿼리 파라미터는 리소스 안에 인코딩할 수 있습니다. GET 요청에서는 요청 헤더가 대체로 필요하지 않습니다. 그래서 요청은 리소스 지정 위주로 단순하고 응답은 statusCode와 body, headers만으로 HTTP의 핵심을 전달합니다. 클라이언트는 이 응답을 일반 웹 응답처럼 해석하면 됩니다.
가스 절약: message/external-body
구현자 참고 절은 가스 비용을 줄이기 위해 message/external-body MIME 타입을 쓰라고 권합니다. 이 타입을 쓰면 컨트랙트가 직접 접근하지 못할 수도 있는 데이터를 가리킬 수 있습니다. 원문 예시는 statusCode 200에 body로 THIS IS NOT REALLY THE BODY! 라는 자리표시 문자열을 두고 Content-type 헤더 값을 message/external-body; access-type=URL; URL="ipfs://11148a173fd3e32c0fa78b90fe42d305f202244e2739" 로 지정합니다. 클라이언트는 이 헤더를 보고 본문 대신 IPFS에서 실제 데이터를 가져옵니다. 큰 화면 코드를 체인에 저장하지 않아도 되는 방법입니다.
쓸 때 주의할 점
- 리다이렉트를 따라갈 때 개인 정보 유출: 일반 URL에 접근할 때의 보안 고려사항이 그대로 적용됩니다. 특히 3XX 리다이렉트를 따라갈 때 개인 정보가 새어 나갈 가능성이 있습니다. 클라이언트는 리다이렉트 처리에 주의해야 합니다.