Ethereum-Solidity 퀴즈 Q14: 왜 constructors를 upgradeable contracts에서 사용할 수 없나요?

발행: (2026년 1월 6일 오전 04:42 GMT+9)
3 min read
원문: Dev.to

Source: Dev.to

업그레이드 가능한 계약에서의 생성자 동작

Solidity에서는 생성자 내부에 있거나 전역 변수 선언에 포함된 코드는 배포된 계약의 런타임 바이트코드에 포함되지 않습니다. 이 코드는 계약 인스턴스가 배포되는 순간 한 번만 실행됩니다.

프록시 뒤에서 로직 계약을 사용할 경우, 로직 계약의 생성자는 프록시의 스토리지 컨텍스트에서 절대 실행되지 않습니다. 프록시는 생성자에 의해 수행된 스토리지 변경 사항을 전혀 인식하지 못합니다.

해결책: 초기화 함수 사용

계약을 업그레이드 호환으로 만들기 위해, 생성자 로직을 일반 initializer 함수로 옮기고 프록시가 로직 계약에 연결된 뒤 이 함수를 호출합니다. 초기화 함수는 한 번만 호출될 수 있도록 보호되어야 하며, 이는 생성자가 제공하는 일회성 실행 보장을 그대로 반영합니다.

OpenZeppelin Upgrades를 사용하면 프록시를 배포할 때 초기화 함수의 이름(및 매개변수)을 지정할 수 있습니다.

OpenZeppelin Initializable 사용 예시

// contracts/MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

contract MyContract is Initializable {
    function initialize(
        address arg1,
        uint256 arg2,
        bytes memory arg3
    ) public payable initializer {
        // "constructor" code...
    }
}

이 계약은 Initializable을 상속받으며, 이는 initialize 함수를 한 번만 실행할 수 있도록 보장하는 initializer 수정자를 제공합니다.

OpenZeppelin Docs 발췌

Back to Blog

관련 글

더 보기 »