🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

스마트 컨트랙트 배포 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 2. · 20 Views

스마트 컨트랙트 배포 완벽 가이드

Hardhat을 활용하여 스마트 컨트랙트를 작성하고 Private 네트워크에 배포하는 전 과정을 다룹니다. 프로젝트 설정부터 컨트랙트 함수 호출까지, 실무에서 바로 적용할 수 있는 내용을 담았습니다.


목차

  1. Hardhat 프로젝트 설정
  2. hardhat.config.js 네트워크 설정
  3. 간단한 컨트랙트 작성
  4. Private 네트워크에 배포
  5. 배포된 컨트랙트 주소 확인
  6. 컨트랙트 함수 호출 테스트

1. Hardhat 프로젝트 설정

블록체인 개발에 관심을 갖게 된 김개발 씨는 드디어 첫 스마트 컨트랙트를 작성해보기로 결심했습니다. 하지만 어디서부터 시작해야 할지 막막했습니다.

선배 박시니어 씨에게 조언을 구하자 돌아온 대답은 간단했습니다. "Hardhat부터 설치해봐요."

Hardhat은 이더리움 스마트 컨트랙트 개발을 위한 전문 도구입니다. 마치 목수에게 연장통이 필요하듯, 블록체인 개발자에게는 Hardhat이 필요합니다.

컴파일, 테스트, 배포까지 모든 과정을 한 곳에서 처리할 수 있어 개발 생산성이 크게 향상됩니다.

다음 코드를 살펴봅시다.

# 프로젝트 디렉토리 생성
mkdir my-first-contract
cd my-first-contract

# npm 프로젝트 초기화
npm init -y

# Hardhat 및 필수 패키지 설치
npm install --save-dev hardhat
npm install --save-dev @nomicfoundation/hardhat-toolbox

# Hardhat 프로젝트 생성
npx hardhat init
# "Create a JavaScript project" 선택

김개발 씨는 입사 6개월 차 주니어 개발자입니다. 회사에서 블록체인 프로젝트를 시작한다는 소식을 듣고 가슴이 두근거렸습니다.

하지만 막상 시작하려니 막막했습니다. 이더리움?

솔리디티? 들어본 적은 있지만 어디서부터 손을 대야 할지 감이 오지 않았습니다.

점심시간에 박시니어 씨를 붙잡고 물었습니다. "선배, 스마트 컨트랙트 개발하려면 뭐부터 해야 해요?" 박시니어 씨는 커피를 한 모금 마시며 답했습니다.

"일단 Hardhat부터 설치해봐. 그게 제일 첫 단계야." 그렇다면 Hardhat이란 정확히 무엇일까요?

쉽게 비유하자면, Hardhat은 마치 주방의 만능 조리도구 세트와 같습니다. 요리를 하려면 칼, 도마, 냄비, 프라이팬이 각각 필요하듯이, 스마트 컨트랙트 개발에도 컴파일러, 테스트 도구, 배포 도구가 필요합니다.

Hardhat은 이 모든 것을 하나의 패키지로 제공합니다. Hardhat이 없던 시절에는 어땠을까요?

개발자들은 각각의 도구를 따로 설치하고 설정해야 했습니다. 컴파일러 버전이 맞지 않아 에러가 나기도 하고, 테스트 환경 구축에만 하루를 꼬박 써야 할 때도 있었습니다.

더 큰 문제는 팀원마다 개발 환경이 달라서 "내 컴퓨터에서는 되는데요"라는 악명 높은 문제가 자주 발생했다는 점입니다. 바로 이런 문제를 해결하기 위해 Hardhat이 등장했습니다.

Hardhat을 사용하면 몇 가지 명령어만으로 완벽한 개발 환경을 구축할 수 있습니다. 또한 팀 전체가 동일한 환경에서 작업할 수 있어 협업이 수월해집니다.

무엇보다 로컬에서 가상의 이더리움 네트워크를 실행할 수 있어, 실제 이더를 소비하지 않고도 마음껏 테스트할 수 있습니다. 위의 코드를 단계별로 살펴보겠습니다.

먼저 mkdir 명령으로 프로젝트 폴더를 생성합니다. 깔끔한 시작을 위해 새 폴더에서 작업하는 것이 좋습니다.

npm init -y는 package.json 파일을 생성하는데, 이는 프로젝트의 신분증과 같습니다. 다음으로 hardhat과 hardhat-toolbox를 설치합니다.

toolbox에는 테스트, 배포에 필요한 거의 모든 도구가 포함되어 있습니다. 마지막으로 npx hardhat init을 실행하면 대화형 설정이 시작됩니다.

실제 현업에서는 어떻게 활용할까요? 대부분의 블록체인 스타트업과 대기업에서 Hardhat을 표준 도구로 사용합니다.

NFT 마켓플레이스, DeFi 프로토콜, DAO 거버넌스 등 다양한 프로젝트에서 Hardhat으로 개발을 시작합니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수는 Node.js 버전을 확인하지 않는 것입니다. Hardhat은 Node.js 18 이상을 권장합니다.

버전이 맞지 않으면 설치 과정에서 예상치 못한 에러가 발생할 수 있습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 조언대로 터미널을 열고 명령어를 입력했습니다. 몇 분 후, 화면에 "Project created" 메시지가 떴을 때 김개발 씨는 작은 성취감을 느꼈습니다.

이제 본격적인 여정이 시작됩니다.

실전 팁

💡 - Node.js 버전은 18 이상을 사용하세요. node -v로 확인할 수 있습니다.

  • hardhat-toolbox는 ethers.js, chai 등 필수 라이브러리를 한 번에 설치해줍니다.
  • 프로젝트 생성 시 "Create a JavaScript project"를 선택하면 샘플 컨트랙트가 함께 생성됩니다.

2. hardhat.config.js 네트워크 설정

Hardhat 프로젝트가 생성되자 김개발 씨는 뿌듯한 마음으로 폴더 구조를 살펴봤습니다. 그런데 hardhat.config.js 파일이 눈에 들어왔습니다.

이 파일은 무엇을 하는 걸까요? 박시니어 씨가 다가와 말했습니다.

"그 파일이 네 컨트랙트가 어디로 배포될지를 결정해."

hardhat.config.js는 Hardhat 프로젝트의 중추 신경계와 같습니다. 솔리디티 컴파일러 버전, 배포할 네트워크 정보, 플러그인 설정 등 모든 핵심 설정이 이 파일에 담깁니다.

마치 네비게이션에 목적지를 입력하는 것처럼, 이 파일에서 컨트랙트의 목적지를 지정합니다.

다음 코드를 살펴봅시다.

require("@nomicfoundation/hardhat-toolbox");

module.exports = {
  // 솔리디티 컴파일러 버전 설정
  solidity: "0.8.19",

  // 네트워크 설정
  networks: {
    // 로컬 개발용 네트워크
    localhost: {
      url: "http://127.0.0.1:8545"
    },
    // Private 네트워크 (예: 사내 블록체인)
    private: {
      url: "http://192.168.1.100:8545",
      accounts: ["0xac0974bec...개인키..."],
      chainId: 1337
    }
  }
};

김개발 씨는 생성된 프로젝트 폴더를 VS Code로 열어봤습니다. contracts, scripts, test 폴더가 보이고, 루트에는 hardhat.config.js 파일이 있었습니다.

"이 config 파일이 왜 중요한 거예요?" 김개발 씨가 물었습니다. 박시니어 씨가 의자를 끌어와 앉으며 설명을 시작했습니다.

"생각해봐. 네가 택배를 보낼 때 주소를 적잖아?

이 파일이 바로 그 주소록이야. 컨트랙트를 어느 네트워크로 보낼지 여기서 정하는 거지." 그렇다면 네트워크 설정이란 정확히 무엇일까요?

쉽게 비유하자면, 이더리움 세계에는 여러 개의 평행우주가 존재합니다. 메인넷이라는 실제 돈이 오가는 세계가 있고, 테스트넷이라는 연습용 세계도 있습니다.

그리고 회사 내부에서만 운영하는 Private 네트워크도 있습니다. hardhat.config.js는 이 평행우주들의 좌표를 저장하는 지도책입니다.

네트워크 설정이 없다면 어떤 일이 벌어질까요? Hardhat은 기본적으로 임시 네트워크에서 실행됩니다.

스크립트가 끝나면 모든 것이 사라집니다. 마치 꿈에서 깨어나면 아무것도 남지 않는 것처럼요.

지속적인 테스트나 실제 배포를 위해서는 반드시 네트워크 설정이 필요합니다. 위의 코드를 자세히 살펴보겠습니다.

먼저 solidity 필드에서 컴파일러 버전을 지정합니다. 0.8.19는 현재 안정적인 버전 중 하나입니다.

버전이 맞지 않으면 컴파일 에러가 발생하니 주의해야 합니다. networks 객체 안에는 여러 네트워크를 정의할 수 있습니다.

localhost는 내 컴퓨터에서 실행되는 로컬 노드입니다. npx hardhat node 명령으로 로컬 노드를 실행하면 8545 포트에서 접속할 수 있습니다.

private 네트워크는 사내 블록체인이나 테스트용 Private 네트워크를 의미합니다. url에는 노드의 RPC 주소를, accounts에는 배포에 사용할 계정의 개인키를 입력합니다.

chainId는 네트워크를 구분하는 고유 번호입니다. 실제 현업에서는 어떻게 활용할까요?

대부분의 기업은 개발, 스테이징, 프로덕션 환경을 분리합니다. config 파일에 development, staging, mainnet 등 여러 네트워크를 정의해두고 상황에 맞게 선택합니다.

하지만 주의할 점이 있습니다. 절대로 개인키를 코드에 직접 작성하면 안 됩니다.

위 예시는 학습용일 뿐입니다. 실무에서는 반드시 환경 변수나 .env 파일을 사용해야 합니다.

개인키가 노출되면 자산을 모두 잃을 수 있습니다. 김개발 씨는 고개를 끄덕였습니다.

"그러니까 이 파일만 잘 설정하면 원하는 네트워크에 배포할 수 있는 거군요!" 박시니어 씨가 미소를 지었습니다. "맞아.

이제 다음 단계로 넘어가볼까?"

실전 팁

💡 - 개인키는 절대 코드에 직접 작성하지 마세요. dotenv 패키지로 .env 파일에서 불러오세요.

  • chainId가 맞지 않으면 트랜잭션이 거부됩니다. 네트워크 관리자에게 정확한 값을 확인하세요.
  • 여러 솔리디티 버전을 사용해야 한다면 solidity 필드에 배열로 지정할 수 있습니다.

3. 간단한 컨트랙트 작성

개발 환경이 준비되자 김개발 씨는 드디어 첫 스마트 컨트랙트를 작성할 차례가 되었습니다. 긴장되는 마음으로 contracts 폴더를 열었습니다.

"뭘 만들어볼까요?" 박시니어 씨가 말했습니다. "일단 간단한 저장소 컨트랙트를 만들어보자.

숫자를 저장하고 읽어오는 거야."

스마트 컨트랙트는 블록체인에서 실행되는 프로그램입니다. 한 번 배포되면 누구도 수정할 수 없고, 정해진 규칙대로만 동작합니다.

마치 자판기처럼, 정해진 입력을 넣으면 정해진 결과가 나옵니다. Solidity라는 언어로 작성하며, 문법은 JavaScript와 비슷합니다.

다음 코드를 살펴봅시다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

// 간단한 숫자 저장소 컨트랙트
contract SimpleStorage {
    // 저장할 숫자 (상태 변수)
    uint256 private storedNumber;

    // 숫자 저장 함수 (트랜잭션 발생)
    function store(uint256 _number) public {
        storedNumber = _number;
    }

    // 숫자 조회 함수 (가스 무료)
    function retrieve() public view returns (uint256) {
        return storedNumber;
    }
}

김개발 씨는 contracts 폴더에 새 파일을 만들었습니다. SimpleStorage.sol이라고 이름을 지었습니다.

.sol 확장자는 Solidity 파일을 의미합니다. "솔리디티 문법이 처음이라 좀 낯설어요." 김개발 씨가 말했습니다.

박시니어 씨가 화면을 가리키며 설명했습니다. "괜찮아.

JavaScript 해봤으면 금방 적응해. 하나씩 살펴보자." 스마트 컨트랙트란 정확히 무엇일까요?

쉽게 비유하자면, 스마트 컨트랙트는 블록체인 위에 설치된 자판기와 같습니다. 일반 자판기에 동전을 넣으면 음료가 나오듯, 스마트 컨트랙트에 트랜잭션을 보내면 정해진 로직이 실행됩니다.

한 번 설치된 자판기의 내부 구조를 바꿀 수 없듯이, 배포된 컨트랙트도 수정할 수 없습니다. 위의 코드를 한 줄씩 살펴보겠습니다.

첫 줄의 SPDX-License-Identifier는 라이선스를 명시합니다. MIT는 가장 자유로운 오픈소스 라이선스입니다.

pragma solidity는 컴파일러 버전을 지정합니다. ^0.8.19는 0.8.19 이상, 0.9.0 미만 버전에서 컴파일하라는 의미입니다.

contract SimpleStorage는 클래스 선언과 비슷합니다. 중괄호 안에 변수와 함수를 정의합니다.

uint256 private storedNumber는 상태 변수입니다. 블록체인에 영구적으로 저장되는 데이터입니다.

uint256은 부호 없는 256비트 정수를 의미하고, private은 외부에서 직접 접근할 수 없다는 뜻입니다. store 함수는 숫자를 저장합니다.

public 키워드는 누구나 이 함수를 호출할 수 있다는 의미입니다. 이 함수를 호출하면 블록체인에 트랜잭션이 기록되고, 가스 비용이 발생합니다.

retrieve 함수는 저장된 숫자를 읽어옵니다. view 키워드가 있으면 블록체인의 상태를 변경하지 않는다는 의미입니다.

따라서 가스 비용이 들지 않습니다. 실제 현업에서는 어떻게 활용할까요?

이 패턴은 설정값 저장, 상태 관리 등 다양한 곳에서 사용됩니다. 예를 들어 NFT 컨트랙트에서 민팅 가격을 저장하거나, DeFi 프로토콜에서 수수료율을 관리할 때 이와 유사한 구조를 사용합니다.

하지만 주의할 점이 있습니다. private 변수라고 해서 완전히 비밀이 되는 것은 아닙니다.

블록체인의 모든 데이터는 공개되어 있습니다. private은 단지 다른 컨트랙트에서 직접 읽을 수 없다는 의미일 뿐, 블록체인 익스플로러에서는 누구나 값을 확인할 수 있습니다.

김개발 씨가 파일을 저장하고 물었습니다. "이제 이걸 컴파일하면 되나요?" 박시니어 씨가 터미널을 열며 말했습니다.

"npx hardhat compile을 실행해봐. 에러 없이 되면 성공이야." 잠시 후 "Compiled 1 Solidity file successfully" 메시지가 떴습니다.

김개발 씨의 첫 컨트랙트가 성공적으로 컴파일되었습니다.

실전 팁

💡 - 솔리디티 파일은 반드시 contracts 폴더에 저장하세요.

  • 함수에 view나 pure가 없으면 트랜잭션이 발생하고 가스 비용이 듭니다.
  • 상태 변수를 변경하는 함수는 반드시 트랜잭션으로 호출해야 합니다.

4. Private 네트워크에 배포

컨트랙트가 컴파일되었습니다. 이제 실제로 배포할 차례입니다.

김개발 씨는 두근거리는 마음으로 박시니어 씨에게 물었습니다. "배포는 어떻게 하나요?" 박시니어 씨가 scripts 폴더를 가리켰습니다.

"배포 스크립트를 작성하고 실행하면 돼."

**배포(Deploy)**란 컴파일된 컨트랙트 코드를 블록체인에 올리는 과정입니다. 마치 앱스토어에 앱을 업로드하는 것과 비슷합니다.

배포가 완료되면 고유한 주소가 부여되고, 이 주소를 통해 컨트랙트와 상호작용할 수 있습니다. Hardhat의 ethers.js 라이브러리를 사용하면 몇 줄의 코드로 배포할 수 있습니다.

다음 코드를 살펴봅시다.

// scripts/deploy.js
const hre = require("hardhat");

async function main() {
  console.log("배포를 시작합니다...");

  // 컨트랙트 팩토리 가져오기
  const SimpleStorage = await hre.ethers.getContractFactory("SimpleStorage");

  // 컨트랙트 배포
  const simpleStorage = await SimpleStorage.deploy();

  // 배포 완료 대기
  await simpleStorage.waitForDeployment();

  // 배포된 주소 출력
  const address = await simpleStorage.getAddress();
  console.log("SimpleStorage 배포 완료:", address);
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

김개발 씨는 scripts 폴더에 deploy.js 파일을 만들었습니다. 이 파일이 컨트랙트를 블록체인으로 보내는 역할을 합니다.

"배포가 뭔지 정확히 이해가 안 돼요." 김개발 씨가 솔직하게 말했습니다. 박시니어 씨가 비유를 들어 설명했습니다.

"웹 개발할 때 서버에 코드 올리잖아? 그거랑 비슷해.

다만 블록체인에 올리면 영원히 거기 남아있는 거지. 삭제도 수정도 안 돼." 배포 과정을 자세히 살펴보겠습니다.

먼저 hre(Hardhat Runtime Environment)를 불러옵니다. 이 객체를 통해 Hardhat의 모든 기능에 접근할 수 있습니다.

ethers는 이더리움과 상호작용하는 라이브러리입니다. getContractFactory 함수는 컴파일된 컨트랙트의 설계도를 가져옵니다.

인자로 컨트랙트 이름을 전달합니다. 이 이름은 .sol 파일 안의 contract 키워드 다음에 오는 이름과 일치해야 합니다.

deploy 함수가 실제 배포를 수행합니다. 이 함수를 호출하면 트랜잭션이 생성되어 네트워크로 전송됩니다.

생성자에 인자가 필요하면 deploy(arg1, arg2)처럼 전달합니다. waitForDeployment는 배포 트랜잭션이 블록에 포함될 때까지 기다립니다.

블록체인은 즉시 처리되지 않으므로 이 대기가 필요합니다. 마지막으로 getAddress로 배포된 컨트랙트의 주소를 얻습니다.

이 주소는 컨트랙트의 고유 식별자입니다. 이제 실제로 배포해보겠습니다.

터미널에서 먼저 로컬 노드를 실행해야 합니다. 새 터미널을 열고 npx hardhat node를 실행합니다.

그러면 테스트용 계정 20개와 함께 로컬 블록체인이 시작됩니다. 다른 터미널에서 배포 명령을 실행합니다.

npx hardhat run scripts/deploy.js --network localhost라고 입력합니다. --network 옵션으로 어느 네트워크에 배포할지 지정합니다.

Private 네트워크에 배포하려면 --network private으로 변경하면 됩니다. 물론 config 파일에 해당 네트워크가 설정되어 있어야 합니다.

실무에서 흔히 하는 실수가 있습니다. 배포 후 주소를 기록해두지 않는 것입니다.

주소를 잃어버리면 컨트랙트를 찾기 어렵습니다. 배포 스크립트에서 주소를 파일로 저장하거나, 배포 로그를 꼼꼼히 관리해야 합니다.

김개발 씨가 명령어를 실행하자 화면에 주소가 출력되었습니다. "0x5FbDB231...로 시작하는 긴 문자열이네요!" 박시니어 씨가 고개를 끄덕였습니다.

"그게 네 컨트랙트 주소야. 잘 저장해둬."

실전 팁

💡 - 배포 전에 반드시 npx hardhat compile을 실행하여 최신 코드를 컴파일하세요.

  • 배포된 주소는 반드시 어딘가에 기록해두세요. 잃어버리면 찾기 어렵습니다.
  • 로컬 노드는 종료하면 모든 데이터가 사라집니다. 지속적인 테스트에는 별도의 네트워크를 사용하세요.

5. 배포된 컨트랙트 주소 확인

배포가 완료되었습니다. 하지만 김개발 씨는 정말 배포가 잘 된 건지 확신이 없었습니다.

"이게 진짜 블록체인에 올라간 건가요?" 박시니어 씨가 미소 지었습니다. "확인하는 방법이 있지.

직접 조회해보자."

배포된 컨트랙트는 고유한 **주소(Address)**를 갖습니다. 이 주소는 이더리움 주소와 같은 형식으로, 0x로 시작하는 40자리 16진수입니다.

주소만 알면 누구나 해당 컨트랙트에 접근할 수 있습니다. Hardhat console이나 별도 스크립트로 배포 상태를 확인할 수 있습니다.

다음 코드를 살펴봅시다.

// scripts/verify.js
const hre = require("hardhat");

async function main() {
  // 배포된 컨트랙트 주소 (배포 시 출력된 주소로 교체)
  const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";

  // 해당 주소의 코드 확인
  const code = await hre.ethers.provider.getCode(contractAddress);

  if (code !== "0x") {
    console.log("컨트랙트가 정상적으로 배포되어 있습니다!");
    console.log("바이트코드 길이:", code.length, "자");
  } else {
    console.log("해당 주소에 컨트랙트가 없습니다.");
  }
}

main().catch(console.error);

김개발 씨는 배포 스크립트가 출력한 주소를 복사해두었습니다. 하지만 마음 한구석에 의문이 남았습니다.

정말 이 주소에 컨트랙트가 있는 걸까? "의심이 많은 건 좋은 거야." 박시니어 씨가 말했습니다.

"개발자는 항상 검증해야 해. 확인하는 스크립트를 만들어보자." 블록체인에서 주소란 무엇일까요?

쉽게 비유하자면, 주소는 인터넷의 URL과 비슷합니다. 웹사이트에 접속하려면 URL이 필요하듯, 컨트랙트에 접근하려면 주소가 필요합니다.

다만 블록체인 주소는 한 번 정해지면 절대 바뀌지 않습니다. 이더리움에는 두 종류의 주소가 있습니다.

**EOA(Externally Owned Account)**는 개인 지갑 주소입니다. 개인키로 제어합니다.

**CA(Contract Account)**는 컨트랙트 주소입니다. 코드로 제어됩니다.

두 주소를 구분하는 방법은 간단합니다. 해당 주소에 코드가 있는지 확인하면 됩니다.

getCode 함수가 0x를 반환하면 일반 지갑이고, 다른 값을 반환하면 컨트랙트입니다. 위의 코드를 살펴보겠습니다.

먼저 확인하고 싶은 주소를 변수에 저장합니다. 이 주소는 배포 스크립트에서 출력된 값입니다.

hre.ethers.provider는 블록체인 노드와 통신하는 객체입니다. getCode 함수는 해당 주소에 저장된 바이트코드를 반환합니다.

바이트코드는 컴파일된 컨트랙트의 실행 코드입니다. 일반 지갑 주소에는 코드가 없으므로 0x만 반환됩니다.

실무에서는 이 방법 외에도 여러 확인 방법을 사용합니다. 첫째, 블록체인 익스플로러를 이용합니다.

이더스캔(Etherscan)이나 사내 익스플로러에 주소를 검색하면 컨트랙트 정보를 시각적으로 확인할 수 있습니다. 둘째, Hardhat의 console 기능을 사용합니다.

npx hardhat console --network localhost를 실행하면 대화형 환경에서 직접 조회할 수 있습니다. 셋째, 배포 시 반환된 트랜잭션 해시를 조회합니다.

트랜잭션이 성공했다면 컨트랙트도 제대로 배포된 것입니다. 주의할 점도 있습니다.

Private 네트워크에는 공개 익스플로러가 없습니다. 따라서 스크립트나 console을 통한 확인이 더 중요합니다.

또한 주소를 잘못 복사하면 엉뚱한 결과가 나올 수 있으니 주의하세요. 김개발 씨가 verify 스크립트를 실행했습니다.

"컨트랙트가 정상적으로 배포되어 있습니다!" 메시지를 보고 안도의 한숨을 내쉬었습니다. 진짜 배포가 된 겁니다.

실전 팁

💡 - 배포 주소는 반드시 별도 파일이나 환경 변수로 관리하세요.

  • Private 네트워크에서는 자체 블록 익스플로러를 구축하면 관리가 편합니다.
  • 같은 코드라도 배포할 때마다 다른 주소가 생성됩니다.

6. 컨트랙트 함수 호출 테스트

컨트랙트가 배포되었고, 주소도 확인했습니다. 이제 마지막 단계입니다.

실제로 함수를 호출해서 데이터를 저장하고 읽어와야 합니다. 김개발 씨의 눈이 반짝였습니다.

"드디어 진짜 사용해보는 거군요!"

배포된 컨트랙트와 상호작용하려면 컨트랙트 인스턴스를 생성해야 합니다. 주소와 ABI(Application Binary Interface)를 조합하여 인스턴스를 만들면, 일반 JavaScript 객체처럼 함수를 호출할 수 있습니다.

상태를 변경하는 함수는 트랜잭션을 발생시키고, view 함수는 즉시 결과를 반환합니다.

다음 코드를 살펴봅시다.

// scripts/interact.js
const hre = require("hardhat");

async function main() {
  const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";

  // 컨트랙트 인스턴스 생성
  const SimpleStorage = await hre.ethers.getContractFactory("SimpleStorage");
  const contract = SimpleStorage.attach(contractAddress);

  // 현재 저장된 값 조회 (가스 무료)
  let value = await contract.retrieve();
  console.log("현재 저장된 값:", value.toString());

  // 새로운 값 저장 (트랜잭션 발생)
  console.log("42를 저장합니다...");
  const tx = await contract.store(42);
  await tx.wait(); // 트랜잭션 확정 대기

  // 변경된 값 확인
  value = await contract.retrieve();
  console.log("변경 후 값:", value.toString());
}

main().catch(console.error);

김개발 씨는 마지막 스크립트를 작성하기 시작했습니다. 지금까지 배운 모든 것이 이 순간을 위한 것이었습니다.

실제로 블록체인에 데이터를 저장하고 읽어오는 것입니다. "여기서 중요한 개념이 하나 있어." 박시니어 씨가 말했습니다.

"ABI라는 거야." ABI란 무엇일까요? 쉽게 비유하자면, ABI는 컨트랙트의 사용 설명서입니다.

리모컨에 어떤 버튼이 있고 각 버튼이 무슨 기능을 하는지 적혀 있는 설명서처럼, ABI에는 컨트랙트에 어떤 함수가 있고 어떤 인자를 받는지 정의되어 있습니다. Hardhat은 컴파일 시 ABI를 자동으로 생성합니다.

getContractFactory를 사용하면 ABI가 자동으로 로드됩니다. attach 함수는 이미 배포된 컨트랙트에 이 ABI를 연결합니다.

위의 코드를 단계별로 살펴보겠습니다. 먼저 getContractFactory로 컨트랙트 정보를 가져옵니다.

그리고 attach 함수에 주소를 전달하여 배포된 컨트랙트에 연결합니다. 이렇게 하면 새로 배포하지 않고 기존 컨트랙트를 사용할 수 있습니다.

retrieve 함수는 view 함수이므로 즉시 결과를 반환합니다. 블록체인에 트랜잭션을 보내지 않아 가스 비용이 들지 않습니다.

반환값은 BigInt 타입이므로 toString으로 변환하여 출력합니다. store 함수는 상태를 변경하므로 트랜잭션이 발생합니다.

함수 호출 결과로 트랜잭션 객체가 반환됩니다. tx.wait() 은 트랜잭션이 블록에 포함될 때까지 기다립니다.

이 과정 없이 바로 조회하면 변경이 반영되지 않을 수 있습니다. 마지막으로 다시 retrieve를 호출하여 값이 제대로 변경되었는지 확인합니다.

실무에서 주의해야 할 점이 있습니다. 트랜잭션은 실패할 수 있습니다.

가스가 부족하거나, 컨트랙트 로직에서 require 조건을 만족하지 못하면 에러가 발생합니다. try-catch로 에러를 처리하는 것이 좋습니다.

또한 Private 네트워크에서는 가스 가격이나 제한이 메인넷과 다를 수 있습니다. 네트워크 설정을 확인하고 필요하면 가스 옵션을 조정하세요.

김개발 씨가 스크립트를 실행했습니다. "현재 저장된 값: 0" "42를 저장합니다..." "변경 후 값: 42" 화면에 출력된 결과를 보며 김개발 씨는 환호성을 질렀습니다.

"됐어요! 진짜로 블록체인에 데이터가 저장됐어요!" 박시니어 씨가 어깨를 토닥였습니다.

"축하해. 이제 넌 스마트 컨트랙트 개발자야." 김개발 씨의 블록체인 개발 여정이 이제 막 시작되었습니다.

오늘 배운 기초 위에 더 복잡한 컨트랙트, 토큰 발행, DeFi 프로토콜까지 무한한 가능성이 펼쳐져 있습니다.

실전 팁

💡 - 트랜잭션 함수 호출 후에는 반드시 wait을 호출하여 확정을 기다리세요.

  • BigInt 값을 다룰 때는 toString이나 Number 변환에 주의하세요. 큰 숫자는 정밀도를 잃을 수 있습니다.
  • 실무에서는 트랜잭션 실패에 대비한 에러 처리 로직을 반드시 추가하세요.

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Solidity#Hardhat#SmartContract#Ethereum#BlockchainDevelopment#Blockchain,Ethereum,Solidity

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.