탈중앙화 시대, 이제는 앱도 중앙 서버 없이 작동하는 시대가 왔습니다. 이더리움과 같은 블록체인 플랫폼 위에 스마트컨트랙트를 얹고, 그걸 기반으로 만든 DApp(디앱)은 기존 앱의 구조를 송두리째 바꾸고 있죠. 이 포스팅에서는 코딩을 잘 모르는 사람도 이해할 수 있도록 Solidity 언어로 간단한 스마트컨트랙트를 작성하고, 그것을 웹 애플리케이션(DApp)으로 연결해 실제로 작동시켜보는 전 과정을 하나하나 짚어보겠습니다.
📌 요약 목차
- 스마트컨트랙트가 뭐길래, 앱이 서버 없이도 돌아가는지 알려드릴게요
- 솔리디티로 카운터 만드는 초간단 예제, 생각보다 재밌어요
- Ganache, Truffle, Hardhat? 배포 도구들 뭐가 다른지도 비교해봤어요
- 프론트엔드에서 버튼 클릭하면 블록체인에 기록되는 마법같은 과정
- 진짜 중요한 보안 문제, 그리고 가스비 아끼는 팁까지 알려드릴게요
- 처음 만드는 DApp, 이걸 알면 다음은 어렵지 않아요
💡 DApp이 뭔가요? 중앙 서버 없이도 작동하는 앱?
DApp(디앱)은 Decentralized Application, 즉 탈중앙화 애플리케이션의 줄임말이에요. 쉽게 말해, 기존에는 앱이 데이터를 중앙 서버(DB)에 저장했다면, DApp은 블록체인에 저장해요. 이게 왜 중요하냐면, 누구나 열람할 수 있고, 조작이 불가능한 블록체인 특성 덕분에 투명하고 신뢰할 수 있는 시스템을 만들 수 있죠.
중앙 서버가 없어도 돌아가는 앱? 말은 어렵지만 실제로는 간단해요. 백엔드 대신 스마트컨트랙트가 로직을 처리하고, 그 로직은 블록체인 위에 고정된 코드로 배포되어 있어요. 그럼 클라이언트는 그 컨트랙트에 직접 요청해서 앱이 작동하게 되는 구조죠.
🔧 Solidity로 스마트컨트랙트 작성해보기
📋 예제: 카운터 만들기 (Counter.sol)
자, 이제 코드를 조금 들여다볼까요? 아래는 가장 단순한 형태의 스마트컨트랙트 예제입니다.
pragma solidity ^0.8.15;
contract Counter {
uint256 private _count;
function current() public view returns (uint256) {
return _count;
}
function increment() public {
_count += 1;
}
function decrement() public {
require(_count > 0, "Counter: underflow");
_count -= 1;
}
}
위 코드는 말 그대로 숫자 카운터예요. 증가, 감소, 현재 값 조회 — 딱 이 세 가지 기능만 들어있죠. 그런데 이게 블록체인에 올라간다고 생각해보세요. 누가 값을 바꿨는지, 언제 바뀌었는지가 전부 기록되고 조작할 수 없다는 점이 엄청난 차이를 만듭니다.
그리고 require 함수는 일종의 방어막이에요. 예외 처리를 통해 오류를 방지하고, 오버플로우나 언더플로우 같은 문제가 생기지 않도록 안전장치를 두는 거죠.
🚀 로컬에서 배포하기: Ganache + Truffle or Hardhat
🔍 Ganache는 뭐고, Truffle은 또 뭐야?
현실에서 메인넷에 바로 배포하긴 부담되니, 먼저 로컬 테스트넷을 씁니다. Ganache는 그런 테스트 네트워크를 만들 수 있는 프로그램이에요. GUI도 있고 CLI도 있어서 편하게 쓸 수 있죠.
그다음은 Truffle 또는 Hardhat 같은 배포 도구로 실제 배포를 해봐야겠죠. Truffle은 전통적이고 안정적이라 초보자에게 익숙하고, Hardhat은 좀 더 유연한 설정이 가능해서 최근엔 개발자들 사이에서 인기예요.
📄 Truffle 배포 스크립트 예시
const Counter = artifacts.require("Counter");
module.exports = function (deployer) {
deployer.deploy(Counter);
};
truffle migrate를 실행하면 컨트랙트가 로컬 이더리움에 올라가고, 그 주소를 사용할 수 있어요.
🧩 DApp 프론트엔드에 컨트랙트 연결하기
🧪 Ethers.js로 간단하게 연결해보기
웹 브라우저에서 MetaMask가 설치되어 있다면, 사용자의 지갑과 연결한 후 다음처럼 스마트컨트랙트를 부를 수 있어요.
const provider = new ethers.providers.Web3Provider(window.ethereum); const signer = provider.getSigner(); const counterContract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer); const currentValue = await counterContract.current(); const tx = await counterContract.increment(); await tx.wait();
여기서 중요한 건, 단순히 숫자를 올리고 내리는 일이 블록체인에서는 트랜잭션이라는 이름으로 기록된다는 점이죠. 그리고 이걸 하기 위해 MetaMask가 등장해 사용자가 직접 서명해야 합니다.
🔒 보안과 가스비, 진짜 실전에서는 이게 중요해요
💣 흔한 보안 실수들, 여기서 많이 터집니다
솔리디티 초보들이 흔히 저지르는 실수 중 하나는 접근 제어를 안 하는 것이에요. 누구나 중요한 함수를 호출할 수 있도록 열어두면, 진짜 큰일 납니다. 그래서 보통 onlyOwner 같은 제한 조건을 꼭 붙이죠.
💸 가스비 아끼는 팁
변수 접근을 줄이고, 연산을 최소화하는 게 포인트예요. 예를 들어 배열보다 mapping을 사용하는 게 효율적일 수 있고, 동일한 변수를 여러 번 읽지 않도록 메모리 캐시를 사용하는 것도 방법이에요.
📚 마무리: 나만의 DApp, 어디까지 만들어봤니?
Counter DApp은 초보자용이지만, 그 안에서 배울 수 있는 건 굉장히 많아요. 메인넷 배포까지 가지 않더라도, 로컬 환경에서 직접 만든 DApp을 띄워보고 버튼을 클릭해서 스마트컨트랙트가 실제로 작동하는 모습을 본다면, 블록체인이란 게 더 이상 먼 세상의 얘기가 아니라는 걸 느낄 수 있을 거예요.
이후에는 토큰을 발행하는 ERC20 DApp, 투표 시스템, 간단한 탈중앙 금융(DeFi) DApp까지도 가능하죠. 단계별로 하나씩 확장해가며 연습해보세요. 실전에서 가장 중요한 건 “작은 성공 경험”이거든요 😊
