이더리움 테스트넷 환경을 Hardhat과 Foundry로 구성하는 방법
Sepolia와 Holesky를 중심으로 이더리움 테스트넷을 구성하고 Hardhat·Foundry 배포, 키 관리, RPC와 모니터링 운영 기준을 정리한다.
2026-08-14 · 최초 발행 2025-10-31
메인넷에 올리기 전에 검증할 환경
테스트넷은 실제 가치가 없는 테스트 토큰으로 스마트 컨트랙트와 배포 절차를 검증하는 공개 네트워크다. 메인넷과 분리되어 있지만 트랜잭션 수수료, 가스 정책, 체인 파라미터처럼 배포 결과에 영향을 주는 조건을 유사하게 재현하는 데 목적이 있다.
Ropsten은 PoW 기반 이더리움 테스트넷으로 메인넷과의 유사성은 높았지만 스팸과 난이도 불안정 문제가 있었고, 2022년에 종료됐다. PoA 기반이던 Rinkeby 역시 안정성과 예측 가능성은 높았으나 메인넷 유사성에 한계가 있었으며 2022년에 종료됐다. Goerli는 합의 전환(머지) 이후 주류 테스트넷 역할을 맡았지만, 2024~2025년에는 Sepolia와 Holesky로의 전환이 가속되는 흐름이다(최신 정보 확인 필요).
신규 DApp 개발과 검증에는 경량·안정 특성을 가진 Sepolia가 표준으로 권장된다. 대규모 검증자나 인프라·스테이킹 시나리오를 검증해야 한다면 Holesky가 더 맞다.
네트워크 선택은 재현성과 운영 조건을 함께 본다
합의 방식의 차이는 단순한 네트워크 특성 차이에 그치지 않는다. 블록 간격, 최종성, 재조직(reorg) 빈도가 달라지고, 이는 테스트 결과를 다시 재현할 수 있는지에 직접 영향을 준다. PoS 전환 이후의 Sepolia와 Holesky는 메인넷 유사성 측면에서 우세하다.
| 네트워크 | 성능(확정속도) | 확장성(네트워크 용량) | 일관성(메인넷 유사성) | 안정성(운영/가용) | 운영 편의(도구/문서) | 상태 |
|---|---|---|---|---|---|---|
| Ropsten | 중 | 중 | 높음(과거 PoW) | 낮음(스팸/종료) | 낮음 | 종료 |
| Rinkeby | 중 | 중 | 중(PoA) | 낮음(종료) | 낮음 | 종료 |
| Goerli | 중 | 중 | 중~높음(머지 이후) | 중(자원 부족 이슈) | 중 | 단계적 폐기(최신 정보 확인 필요) |
| Sepolia | 중~높음 | 중 | 높음(PoS) | 높음 | 높음 | 권장 |
| Holesky | 중 | 높음(대규모) | 높음(PoS) | 높음 | 중 | 권장(인프라 검증) |
공인 상태와 지원 정책은 지속 변동 가능하므로 최신 정보 확인이 필요하다.
RPC·키·테스트 토큰을 배포 경로에 맞춰 준비한다
RPC는 Alchemy, Infura, Ankr, QuickNode 같은 공용 서비스를 쓰거나 Geth·Nethermind를 직접 운영하는 방식으로 구성할 수 있다. 공용 RPC는 편의성과 가용성이 좋고, 자가 호스팅은 데이터 주권과 요율 제한 회피에 강점이 있다. 어느 쪽이든 운영 복잡도와 비용을 함께 고려해야 한다.
테스트 토큰은 faucet을 통해 확보한다. 무료 지급에는 레이트 리밋과 지급량 제한이 있으므로, 조직 단위로 사용할 때는 자체 faucet 서버나 사내 토큰 재분배 큐를 운영하는 편이 낫다.
키는 반드시 테스트넷 전용으로 분리한다. 비밀키는 .env에 암호화해 보관하고 하드코딩하지 않는다. CI에서는 임시 키와 임시 지갑을 사용하며, 접근권한 스코프를 최소화한다. EIP-1559 환경에서는 maxFeePerGas, maxPriorityFeePerGas, chainId 설정이 필요하고, nonce 관리와 재전송(Replace-By-Fee), 실패 시 롤백·리트라이 전략도 배포 설계에 포함해야 한다.
개발 환경으로는 Node.js 18+와 npm 또는 pnpm, Hardhat 2.22+ 또는 Foundry(Forge/Cast, 최신 릴리스), OpenSSL, Git, dotenv를 준비한다. 신규 프로젝트는 Sepolia를 우선 선택하고, 인프라 검증에는 Holesky를 병행한다. 레거시 호환성을 재현해야 할 경우에는 Goerli 사용 가능 여부를 먼저 확인한다.
공용 RPC 제공업체에서 프로젝트를 만든 뒤 Sepolia 또는 Goerli 엔드포인트를 확보하고, 다음 환경변수를 구성한다.
PRIVATE_KEYRPC_URL_SEPOLIARPC_URL_GOERLIETHERSCAN_API_KEY
테스트넷 전용 지갑을 사용하고 출금 제한을 설정한다.
Hardhat으로 배포 경로를 구성한다
전제조건은 Node.js 18+와 Hardhat 2.22+다.
# 초기화
mkdir eth-testnet-demo && cd $_
npm init -y
npm i -D hardhat @nomicfoundation/hardhat-toolbox dotenv
npx hardhat init --typescript
hardhat.config.ts에는 Sepolia와 레거시 Goerli 설정을 함께 둘 수 있다.
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import * as dotenv from "dotenv";
dotenv.config();
const PRIVATE_KEY = process.env.PRIVATE_KEY || "";
const RPC_URL_SEPOLIA = process.env.RPC_URL_SEPOLIA || "";
const RPC_URL_GOERLI = process.env.RPC_URL_GOERLI || ""; // 레거시
const config: HardhatUserConfig = {
solidity: {
version: "0.8.24",
settings: { optimizer: { enabled: true, runs: 200 } },
},
networks: {
sepolia: {
url: RPC_URL_SEPOLIA,
chainId: 11155111,
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
},
goerli: {
url: RPC_URL_GOERLI,
chainId: 5,
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
},
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY || "",
},
};
export default config;
배포 스크립트는 컨트랙트 생성과 배포 완료 대기를 분리해 상태를 확인한다.
import { ethers } from "hardhat";
async function main() {
const Factory = await ethers.getContractFactory("Greeter");
const contract = await Factory.deploy("hello");
await contract.waitForDeployment();
console.log("Deployed:", await contract.getAddress());
}
main().catch((e) => {
console.error(e);
process.exit(1);
});
컴파일, 배포, 검증은 다음 순서로 실행한다.
npx hardhat compile
npx hardhat run scripts/deploy.ts --network sepolia
# 검증(지원 네트워크 여부 확인)
npx hardhat verify --network sepolia <DEPLOYED_ADDRESS> "hello"
가스와 수수료는 기본적으로 EIP-1559 자동 추정을 사용한다. 실패하면 --max-fee-per-gas, --max-priority-fee-per-gas를 스크립트에서 지정하거나 Hardhat 설정값을 오버라이드한다.
Foundry 설정과 온체인 검증
Foundryup 설치와 forge 0.2+, Cast가 필요하다.
curl -L https://foundry.paradigm.xyz | bash
foundryup
forge init foundry-testnet-demo
cd foundry-testnet-demo
foundry.toml에서 RPC 엔드포인트와 Etherscan 키를 분리해 관리한다.
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']
optimizer = true
optimizer_runs = 200
evm_version = 'shanghai'
[rpc_endpoints]
sepolia = "${RPC_URL_SEPOLIA}"
goerli = "${RPC_URL_GOERLI}"
[etherscan]
sepolia = { key = "${ETHERSCAN_API_KEY}" }
배포와 컨트랙트 검증은 환경변수를 통해 수행한다.
# .env에 PRIVATE_KEY, RPC_URL_SEPOLIA 설정
forge create --rpc-url $RPC_URL_SEPOLIA --private-key $PRIVATE_KEY src/Greeter.sol:Greeter --constructor-args "hello"
forge verify-contract --chain sepolia <ADDRESS> src/Greeter.sol:Greeter --compiler-version v0.8.24+commit.e11b9ed9
배포 실패를 관측 가능한 흐름으로 만든다
Sepolia faucet은 공용 제공업체 또는 Etherscan Faucet을 사용할 수 있으며, 깃허브 Oauth와 지연 제한이 존재한다(최신 정보 확인 필요). 조직 내부에서는 토큰 풀을 주기적으로 보충하는 자동화 워커를 운영할 수 있다.
배포 후에는 sepolia.etherscan.io, goerli.etherscan.io 같은 블록 탐색기에서 결과를 확인한다. Tx 실패 이벤트, nonce 드리프트, RPC 에러율을 CloudWatch나 Grafana 등으로 관측하고 알림과 연결한다.
CI/CD에서는 PR마다 Anvil 또는 Hardhat Network의 로컬 테스트를 수행한 뒤 Sepolia 샌드박스에 배포하고, 메인넷 변경은 승인 이후에 진행한다. 시드 계정의 잔액을 점검해 부족하면 자동 faucet 요청과 재시도 백오프를 연결한다.
릴리스 리허설과 연동 검증에 쓰는 방법
컨트랙트 릴리스 전에 스키마 마이그레이션, 프록시 업그레이드, 권한 롤 설정을 반복 검증할 수 있다. 멀티서그 서명과 타임락 절차 역시 실제 변경 전에 연습 대상이 된다.
가스 최적화에서는 메트릭 기반 가스 프로파일링, 바이트코드 크기 제한(24KB) 대응, EIP-1559 수수료 정책 튜닝과 재전송 전략 검증이 주요 대상이다.
Webhook, Keeper, Oracle feed 같은 서드파티 서비스를 통합하고, 브릿지 테스트넷 간 자산 이동 시나리오를 단위 테스트할 수도 있다. 다만 이 경로는 실거래 경로와 차이가 존재한다는 점을 고려해야 한다.
품질과 운영 비용 사이의 선택
테스트넷 기반 릴리스 검증은 배포 실패율을 50% 이상 줄이고 롤백 소요시간을 분→초 단위로 단축하는 효과를 기대할 수 있다. CI 자동화는 릴리스 리드타임을 30~60% 단축하고 재현 버그 발견률을 높인다. 메인넷 리스크를 낮추는 동시에 릴리스 신뢰성, 팀 온보딩, 문서화와 절차 표준화에도 도움이 된다.
운영 기준은 다음 트레이드오프를 전제로 잡아야 한다.
- 테스트넷 전용 키와 최소 권한을 기본으로 하고, 필요에 따라 HSM 또는 Key Vault를 적용한다.
- 공용 RPC는 이중화하고 지연·오류율 SLO를 정의한다.
- 배포 트랜잭션에는 중복 배포 방지 가드를 포함해 idempotency를 고려한다.
- 공용 RPC는 저비용·신속이라는 장점이 있지만 레이트 리밋과 가용성 리스크가 있다.
- 자가 호스팅은 안정성과 제어에 강점이 있지만 운영 복잡도와 비용이 증가한다.
- Goerli 유지는 호환성 이점이 있으나 단계적 폐기로 장기 지원이 부재하다.