곰투 크립토
guide전체 41편 중 26편

이더리움 프록시 컨트랙트 완전 정리: delegatecall·UUPS·업그레이드 리스크

이더리움 프록시 컨트랙트의 delegatecall 구조, 투명·UUPS·비콘 방식의 차이와 실제 업그레이드 권한을 안전하게 확인하는 법을 설명해요.

GOMTU
GOMTU
크립토 리서치 · 2026년 8월 26일 · 약 8분
공유𝕏in

최종 업데이트

블록 익스플로러에서 검증된 소스 코드를 읽었는데도, 내 거래를 실제로 처리하는 코드는 다른 주소에 있을 수 있어요. 많은 이더리움 앱은 하나의 공개 주소를 유지하면서 교체 가능한 로직으로 호출을 넘깁니다. 이 구조는 블록체인 기초에서 꼭 알아둘 부분이에요. 사용자가 토큰을 새 주소로 옮기지 않아도 업그레이드 뒤 동작이 달라질 수 있기 때문입니다.

업그레이드는 버그 수정과 기능 추가에 유용합니다. 반대로 업그레이드 권한이 탈취되거나 잘못 행사되면 규칙 자체가 바뀔 수 있어요. 이 글에서는 프록시(Proxy), 위임 호출(Delegatecall), 주요 프록시 방식과 실전 검증 순서를 설명합니다. 업그레이드 가능하다고 무조건 위험한 것도, 소스가 검증됐다고 무조건 안전한 것도 아니에요.

이더리움 프록시 컨트랙트란 무엇인가요?

광고

프록시는 주소가 고정된 식당과 비슷해요. 손님은 늘 같은 문으로 들어오지만 주방 팀은 교체할 수 있습니다. 예약 장부, 재고와 금고는 식당 주소에 그대로 남아 있죠.

이더리움에서 **프록시 컨트랙트(Proxy Contract)**는 고정 주소와 스토리지(Storage), 흔히 자산까지 보유합니다. 구현 컨트랙트(Implementation Contract) 또는 로직 컨트랙트는 실행할 코드를 담아요. 호출이 프록시에 도착하면 폴백(Fallback) 경로가 EVM의 DELEGATECALL 명령으로 입력값을 구현 컨트랙트에 전달합니다.

핵심은 실행 맥락이에요. 일반 외부 호출은 호출받은 컨트랙트의 스토리지에서 실행됩니다. 위임 호출은 구현 코드를 빌리되 프록시의 스토리지와 잔액을 읽고 써요. 원래 호출자와 전송된 값도 실행 맥락에 유지됩니다. 구현 컨트랙트는 별도 계좌라기보다 프록시가 빌려 보는 작업 설명서에 가깝습니다.

그래서 업그레이드 뒤에도 토큰 잔액, 승인(Allowance), 사용자 기록과 연동 주소를 유지할 수 있어요. 바뀌는 것은 로직을 빌려 오는 대상입니다.

위임 호출은 어떻게 흐르나요?

단순화하면 다음 순서로 동작해요.

  1. 지갑이 프록시 주소로 호출 데이터(Calldata)를 보냅니다.
  2. 프록시는 지정된 스토리지 슬롯에서 구현 주소를 읽거나 비콘(Beacon)에 묻습니다.
  3. 원래 호출 데이터를 구현 컨트랙트로 위임합니다.
  4. 구현 바이트코드는 프록시의 잔액과 스토리지를 대상으로 실행돼요.
  5. 반환 데이터나 실패(Revert)가 지갑으로 그대로 전달됩니다.

함수 선택자(Function Selector)와 인자는 이더리움 호출 데이터에 실려 있어요. 프록시는 애플리케이션 함수마다 직접 해석하기보다 바이트를 넘기는 경우가 많습니다. 블록 익스플로러가 프록시 주소에 구현 컨트랙트의 ABI를 결합해 사용 가능한 화면을 보여주는 이유도 여기에 있어요.

ERC-1967 스토리지 슬롯이 필요한 이유

프록시가 구현 주소를 평범한 초기 슬롯에 저장하면 구현 컨트랙트의 변수가 그 값을 덮어쓸 수 있습니다. ERC-1967은 구현, 비콘, 선택적 관리자(Admin) 정보를 위한 특정 슬롯을 정의해요. 구현 슬롯은 keccak256("eip1967.proxy.implementation") - 1에서 계산되며, Solidity 컴파일러가 보통 상태 변수에 배정하는 위치와 충돌하지 않도록 설계됐습니다.

표준은 값이 바뀔 때 Upgraded, BeaconUpgraded, AdminChanged 이벤트를 남기도록 권고해요. 이벤트는 모니터링에 유용하지만 현재 값의 기준은 스토리지입니다. 사람이 읽기 좋은 활동 라벨만 믿지 말고 이벤트와 변경 후 슬롯을 함께 확인해야 해요.

투명·UUPS·비콘 프록시는 무엇이 다른가요?

세 방식 모두 프록시 주소를 유지할 수 있지만, 업그레이드 로직과 권한의 위치가 달라요.

방식업그레이드 장치의 위치영향 범위꼭 확인할 질문
투명(Transparent)프록시와 전용 관리자 경로프록시 하나ProxyAdmin 또는 관리자 소유자는 누구인가?
UUPS구현 컨트랙트프록시 하나_authorizeUpgrade가 의도한 권한을 제한하는가?
비콘(Beacon)여러 프록시가 따르는 비콘비콘을 따르는 여러 프록시비콘 소유자는 누구이며 어떤 프록시가 함께 바뀌는가?

투명 프록시

투명 프록시는 관리자 호출과 사용자 호출을 분리합니다. 널리 쓰이는 OpenZeppelin 구조에서는 관리자가 업그레이드를 담당하고, 일반 사용자의 호출은 구현 컨트랙트로 위임돼요. 이 분리는 4바이트 함수 선택자가 우연히 충돌할 때 생기는 혼동을 줄이지만, 안전하게 관리해야 할 관리자 구성요소가 추가됩니다.

프록시 주소만 보고 실제 통제자를 판단하면 안 돼요. ProxyAdmin 컨트랙트가 또 다른 계정, 다중서명(Multisig), 거버넌스 시스템의 소유일 수 있습니다. 실제로 업그레이드를 승인할 수 있는 계정과 규칙까지 추적하세요.

UUPS 프록시

UUPS는 업그레이드 함수를 프록시가 아니라 구현 컨트랙트에 둡니다. 프록시는 작게 유지하고, 구현의 권한 확인 훅(Hook)이 누가 업그레이드할 수 있는지 결정해요. ERC-1822는 호환성 장치를 설명하며, 널리 쓰이는 UUPS 구현은 ERC-1967 구현 슬롯을 함께 사용합니다.

따라서 업그레이드 권한 검토가 매우 중요해요. 접근 제어가 빠지거나 잘못되면 업그레이드 경로가 노출됩니다. 호환되지 않는 구현으로 교체하면 향후 업그레이드가 막히거나 앱이 깨질 수도 있어요. 현재 OpenZeppelin UUPS 구현에는 호환성 검사가 있지만, 커스텀 로직과 이를 둘러싼 거버넌스는 별도로 확인해야 합니다.

비콘 프록시

비콘 프록시는 ERC-1967 구현 슬롯에 구현 주소를 직접 저장하지 않습니다. 비콘 주소를 저장하고, 비콘의 implementation() 응답에서 로직 주소를 얻어요. 비콘 하나를 바꾸면 이를 따르는 여러 프록시의 구현을 한 번에 전환할 수 있습니다.

비슷한 인스턴스가 많은 서비스에는 편리해요. 하지만 영향도 집중됩니다. 한 번의 승인된 비콘 업그레이드가 모든 추종 프록시에 영향을 줄 수 있죠. 프록시, 비콘, 현재 구현, 비콘 소유자와 공유 범위를 모두 확인해야 합니다.

생성자·초기화 함수·스토리지 레이아웃

구현 컨트랙트의 생성자(Constructor)는 위임 실행에서 쓰는 프록시 스토리지가 아니라 구현 컨트랙트 자체의 스토리지를 초기화합니다. 업그레이드 시스템은 보통 배포 중 프록시를 통해 초기화 함수(Initializer)를 호출해요. 초기화 함수는 다시 호출되지 않도록 보호해야 합니다.

초기화는 사소한 배포 절차가 아니에요. 초기화되지 않은 프록시나 구현에는 의도하지 않은 사용자가 소유권 또는 특권 설정을 가져갈 위험이 있습니다. 검증된 라이브러리는 재호출 방지 장치를 제공하지만, 배포 시 초기화 호출을 정확히 인코딩하고 실행해야 해요.

스토리지 레이아웃도 이전 버전과 호환돼야 합니다. 버전 1이 슬롯 0에 owner, 슬롯 1에 balance를 저장했다고 해볼게요. 버전 2에서 순서를 함부로 바꾸면 새 코드는 기존 바이트를 전혀 다른 의미로 읽습니다. 변수 이름이 자연스러워 보여도 데이터가 자동 이전되지는 않아요. 변수 추가 위치, 상속 순서, 패킹된 변수, 구조체와 매핑을 이전 레이아웃과 도구로 비교해야 합니다.

프록시와 상호작용하기 전 확인 순서

1. 체인과 프록시 주소를 확인하세요

프로젝트의 공식 채널에서 시작하고 네트워크를 확인합니다. 같은 화면처럼 보여도 이더리움과 롤업의 컨트랙트는 달라요. 검색할 때마다 주소를 찾기보다 검증한 익스플로러 페이지를 저장하되, 마이그레이션 공지가 있으면 다시 확인하세요.

2. 프록시 방식을 식별하세요

익스플로러의 프록시 표시는 편의 기능이지 유일한 증거가 아닙니다. 해당한다면 신뢰할 수 있는 RPC를 통해 ERC-1967 구현·비콘·관리자 슬롯을 읽으세요. 비콘 방식은 비콘에 implementation()을 호출합니다. 커스텀 프록시나 미니멀 프록시는 다른 배치를 쓸 수 있으므로 ERC-1967 슬롯이 비었다고 위임이 없다고 단정하면 안 돼요.

3. 현재 구현을 검증하세요

구현 소스가 검증됐는지, 컴파일된 바이트코드와 일치하는지 확인합니다. 실행할 함수의 구현 ABI도 살펴보세요. 프록시 껍데기의 검증은 교체 가능한 앱 로직을 검증하지 않으며, 과거 구현의 감사 보고서는 새 구현을 설명하지 않습니다.

4. 실질적인 업그레이드 권한을 추적하세요

구현을 바꿀 수 있는 계정, 다중서명, 타임락(Timelock), 거버넌스 실행자를 찾습니다. 서명 임계값, 서명자, 지연 시간, 취소 권한과 정상 절차를 우회할 수 있는 비상 역할까지 확인하세요. 온체인 통제 경로가 뒷받침하지 않으면 “DAO가 관리한다”는 문구만으로는 부족합니다.

5. 업그레이드 이력과 모니터링을 살펴보세요

ERC-1967 업그레이드 이벤트를 찾고 스토리지 변경과 대조합니다. 배포된 버전의 릴리스 노트, 감사 보고서, 거버넌스 제안을 확인하세요. 이더리움 이벤트 로그는 좋은 알림 수단이지만, 체인 재구성(Reorg)과 커스텀 경로를 고려해 정규 상태와 맞춰 봐야 합니다.

6. 정확한 거래를 시뮬레이션하세요

목적지가 사용자가 호출해야 할 프록시인지 확인하고, 호출 데이터를 해석하며 승인과 자산 이동을 살펴보세요. 이전 검토와 실제 실행 사이에도 프록시는 업그레이드될 수 있습니다. 영향이 큰 행동은 현재 상태에서 다시 시뮬레이션해야 해요.

리스크와 한계

업그레이드 키 탈취

공격자가 실질적인 업그레이드 권한을 얻으면 자산 이동, 회계 변경 또는 권한 부여 로직을 설치할 수 있습니다. 다중서명과 타임락은 단일 키와 기습 업그레이드 위험을 줄이지만, 임계값·서명자·지연·우회 역할이 적절하고 실제로 모니터링될 때만 효과가 있어요.

악성 또는 버그가 있는 구현

정상적으로 승인된 업그레이드도 안전하다는 보장은 없습니다. 새 로직에 재진입(Reentrancy), 잘못된 접근 제어, 오라클 가정 또는 이전 감사에 없던 경제적 동작이 들어갈 수 있어요. 감사 범위와 실제 배포 바이트코드 버전이 중요합니다.

스토리지 충돌과 잘못된 초기화

호환되지 않는 레이아웃은 영구 상태를 훼손할 수 있습니다. 초기화 처리가 잘못되면 특권 역할이 탈취되거나 핵심 설정이 초기화될 수 있어요. 자동 업그레이드 검증은 도움이 되지만 비즈니스 로직과 거버넌스 안전까지 증명하지는 않습니다.

함수 선택자와 인터페이스 혼동

EVM은 함수 시그니처 해시의 첫 4바이트로 호출을 분기합니다. 프록시 관리 함수와 구현 함수가 예상치 못한 동작을 만들지 않도록 라우팅을 설계해야 해요. 표시된 ABI가 오래됐거나 잘못된 구현에 연결됐을 수도 있습니다.

업그레이드 가능성도 바뀔 수 있어요

업그레이드 권한을 포기하거나 제거해 영구히 잠글 수 있는 시스템이 있는 반면, 불변성을 주장하면서 간접 통제 경로를 남긴 시스템도 있습니다. 홍보 문구가 아니라 현재 코드와 권한을 확인하세요. 반대로 꼭 필요한 업그레이드 권한을 잃으면 버그를 고치지 못할 수도 있어요.

Warning

프록시 주소의 소스 검증만으로는 부족합니다. 현재 구현, 스토리지 레이아웃 가정, 초기화 상태와 코드를 교체할 수 있는 전체 권한 경로를 확인하세요.

실전 체크리스트

  • 체인 ID와 의도한 프록시 주소 확인
  • 투명·UUPS·비콘·미니멀·커스텀 방식 식별
  • 관련 구현·비콘·관리자 상태 직접 읽기
  • 현재 구현 소스와 배포 바이트코드 검증
  • 업그레이드 권한을 실질 소유자와 우회 역할까지 추적
  • 타임락 지연, 다중서명 임계값과 비상 권한 확인
  • 업그레이드 이벤트·제안·감사·버전 릴리스 노트 검토
  • 스토리지 레이아웃 호환성과 초기화 상태 확인
  • 현재 상태에서 정확한 거래 해석 및 시뮬레이션
  • 큰 승인·예치·거버넌스 행동 직전 다시 확인

자주 묻는 질문

프록시가 사용자 자산을 보유하나요?

그런 경우가 많습니다. delegatecall에서는 앱 상태와 잔액이 프록시 주소에 남아요. 구현은 코드를 제공하고, 사용자는 보통 프록시 주소를 승인하거나 여기에 자산을 보냅니다.

모든 프록시는 업그레이드할 수 있나요?

아니요. 위임은 실행 방식이지 살아 있는 업그레이드 경로의 증거가 아닙니다. 미니멀 클론은 고정 구현에 위임할 수 있고, 업그레이드 시스템도 나중에 권한을 제거하거나 잠글 수 있어요. 배포 코드와 상태를 확인해야 합니다.

UUPS가 투명 프록시보다 안전한가요?

어느 이름도 안전을 보장하지 않습니다. 업그레이드 로직의 위치와 검토 지점이 달라요. 구현 정확성, 권한, 스토리지 호환성, 거버넌스, 모니터링과 운영 규율이 안전성을 좌우합니다.

블록 익스플로러는 구현 주소를 항상 찾을 수 있나요?

ERC-1967은 일반적인 방식을 찾기 쉽게 하지만 커스텀 프록시는 다른 장치를 쓸 수 있습니다. 익스플로러 라벨이 상태 변경을 늦게 반영할 수도 있어요. 중요한 판단은 직접 슬롯을 읽고 검증된 코드를 대조하세요.

감사 보고서는 미래 업그레이드도 포함하나요?

감사 범위가 해당 버전과 업그레이드 경로를 명시적으로 포함할 때만 그렇습니다. 구현 코드를 교체하면 검토 대상 시스템도 바뀌어요. 프로토콜의 “감사 완료” 배지보다 배포 바이트코드와 감사 커밋 또는 릴리스를 확인하세요.

1차 자료

하나의 주소가 아니라 변하는 시스템으로 보세요

프록시는 단순한 전달 껍데기가 아닙니다. 영구 상태를 담는 프록시, 현재 실행할 구현, 그 구현을 교체할 수 있는 권한 경로가 연결된 시스템이에요. 검증할 때도 세 요소를 모두 따라가야 합니다.

이 글은 교육 목적이며 투자 조언이 아닙니다. 스마트 컨트랙트와 관련 자산은 실패하거나 가치를 잃을 수 있어요. 최신 1차 문서와 배포 상태를 직접 확인하고, 잃어도 되는 범위로 노출을 제한하며 스스로 조사하세요(DYOR).

광고

함께 읽으면 좋은 글

관련 주제 살펴보기

GOMTU의 다른 글