블록체인 학습
0 XP

Chapter 5: 함수 기초

로컬 노드에 컨트랙트 배포하기

로컬 노드에 컨트랙트 배포하기

컴파일은 코드를 EVM 바이트코드로 번역하는 일까지입니다. 그 바이트코드가 실제로 체인 위에 자리를 잡고 주소를 갖는 것이 배포입니다. 배포되기 전의 컨트랙트는 호출할 수 없습니다. 주소가 없기 때문입니다.

이번 랩에서는 내 컴퓨터에 가짜 이더리움 네트워크를 띄우고, 거기에 컨트랙트를 배포해 주소를 받아 봅니다.

1단계 — 로컬 노드 실행

터미널을 열고 프로젝트 폴더에서 실행합니다.

npx hardhat node

이 명령은 내 컴퓨터 안에서만 도는 이더리움 노드를 띄웁니다. 실행하면 이런 내용이 출력됩니다.

Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
 
Accounts
========
Account #0: 0xf39F...2266 (10000 ETH)
Private Key: 0xac09...ff80
...
Account #19: 0x8626...4199 (10000 ETH)

각각 10000 ETH 를 가진 테스트 계정 20개와 그 개인키가 그대로 화면에 찍힙니다. 실제 네트워크라면 상상할 수 없는 일이지만, 이 노드는 내 컴퓨터에만 존재하고 여기의 ETH 는 아무 가치가 없으므로 안전합니다.

화면에 출력된 개인키를 실제 지갑이나 메인넷에서 절대 사용하지 마세요. 전 세계에 공개된 값이라 누구나 그 계정을 통제할 수 있습니다.

이 터미널 창은 닫지 말고 계속 켜 두세요. 노드가 꺼지면 배포한 컨트랙트와 모든 데이터가 사라집니다. 이어지는 작업은 새 터미널 창을 하나 더 열어서 진행합니다.

2단계 — 배포할 컨트랙트 작성

앞 랩에서 만든 프로젝트에는 Hardhat 이 예제로 넣어 둔 contracts/Counter.sol 과 그것을 검사하는 테스트 두 개(contracts/Counter.t.sol, test/Counter.ts)가 이미 들어 있습니다. 여기서는 Counter 를 다른 모양(생성자 인자·increase·get)으로 새로 쓸 것이라, 예제 테스트를 그대로 두면 옛 Counter 의 함수를 찾지 못해 컴파일이 실패합니다. 먼저 두 테스트 파일을 지웁니다.

rm contracts/Counter.t.sol test/Counter.ts

이 단계를 건너뛰면 npx hardhat compile 이 Counter.t.sol 에서 inc 를 찾을 수 없다는 오류로 실패합니다. 오류 메시지에 Counter.t.sol 이 보이면 이 단계로 돌아오세요.

이제 contracts/Counter.sol 을 아래 내용으로 덮어씁니다. Chapter 5 에서 배운 생성자와 view 함수가 모두 들어 있습니다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract Counter {
    uint256 public count;
 
    // 배포할 때 시작값을 인자로 받는다
    constructor(uint256 _start) {
        count = _start;
    }
 
    // 상태를 바꾸는 함수 — 트랜잭션이 필요하다
    function increase(uint256 _amount) public {
        count += _amount;
    }
 
    // 상태를 읽기만 하는 함수 — 트랜잭션이 필요 없다
    function get() public view returns (uint256) {
        return count;
    }
}

새 터미널에서 컴파일합니다.

npx hardhat compile

3단계 — 배포 스크립트 작성

scripts/deploy.js 파일을 만듭니다. 배포는 결국 "생성자 인자를 담아 트랜잭션을 보내고, 채굴된 뒤 주소를 받아오는" 절차입니다.

// scripts/deploy.js
import { network } from 'hardhat'
 
// 실행할 때 지정한 네트워크에 연결한다
const { ethers } = await network.getOrCreate()
 
// 생성자 인자 배열을 두 번째 인자로 넘긴다 (시작값 10)
const counter = await ethers.deployContract('Counter', [10n])
 
// 배포 트랜잭션이 블록에 담길 때까지 기다린다
await counter.waitForDeployment()
 
console.log('Counter 배포 완료')
console.log('주소:', await counter.getAddress())

10n 처럼 숫자 뒤에 n 을 붙인 것은 자바스크립트의 bigint 리터럴입니다. uint256 은 자바스크립트의 일반 number 로는 안전하게 표현할 수 없는 큰 값을 담을 수 있어서, ethers.js v6 는 모든 정수를 bigint 로 주고받습니다.

4단계 — 로컬 노드에 배포

노드가 켜져 있는 상태에서, 다른 터미널에서 실행합니다.

npx hardhat run scripts/deploy.js --network localhost

--network localhost 가 핵심입니다. 이 옵션이 없으면 Hardhat 은 임시 인메모리 네트워크를 잠깐 띄웠다가 스크립트가 끝나는 순간 통째로 버립니다. 그러면 배포된 컨트랙트도 함께 사라져서 다음 랩에서 호출할 수 없습니다.

성공하면 0x 로 시작하는 40자리 컨트랙트 주소가 출력됩니다. 이 주소를 메모해 두세요. 다음 랩에서 그대로 사용합니다.

5단계 — 노드 쪽 로그 확인

노드를 켜 둔 터미널로 돌아가 보면, 방금 벌어진 일이 기록되어 있습니다.

eth_sendTransaction
  Contract deployment: Counter
  Contract address:    0x5fbd...0aa3
  Transaction:         0x8d7e...41c2
  From:                0xf39f...2266
  Gas used:            142351 of 30000000
  Block #1:            0x1f2a...9b04

배포도 결국 하나의 트랜잭션이며, 가스를 소모하고, 블록에 담긴다는 사실이 여기서 그대로 보입니다. 사용한 계정은 노드가 출력했던 Account #0 입니다.

시작 전 준비물

  • 앞 랩에서 만든 Hardhat 3 프로젝트 폴더
  • `npx hardhat compile` 이 성공하는 상태
  • 터미널 창을 두 개 동시에 열 수 있는 환경

진행 확인

0 / 5

각 단계를 직접 수행하고, 아래 ‘확인 기준’이 실제로 보이면 체크하세요. 모두 체크하면 완료할 수 있습니다.