블록체인 스마트컨트랙트 솔리디티로 구현해보는 간단 DApp

탈중앙화 시대, 이제는 앱도 중앙 서버 없이 작동하는 시대가 왔습니다. 이더리움과 같은 블록체인 플랫폼 위에 스마트컨트랙트를 얹고, 그걸 기반으로 만든 DApp(디앱)은 기존 앱의 구조를 송두리째 바꾸고 있죠. 이 포스팅에서는 코딩을 잘 모르는 사람도 이해할 수 있도록 Solidity 언어로 간단한 스마트컨트랙트를 작성하고, 그것을 웹 애플리케이션(DApp)으로 연결해 실제로 작동시켜보는 전 과정을 하나하나 짚어보겠습니다.





📌 요약 목차

  1. 스마트컨트랙트가 뭐길래, 앱이 서버 없이도 돌아가는지 알려드릴게요
  2. 솔리디티로 카운터 만드는 초간단 예제, 생각보다 재밌어요
  3. Ganache, Truffle, Hardhat? 배포 도구들 뭐가 다른지도 비교해봤어요
  4. 프론트엔드에서 버튼 클릭하면 블록체인에 기록되는 마법같은 과정
  5. 진짜 중요한 보안 문제, 그리고 가스비 아끼는 팁까지 알려드릴게요
  6. 처음 만드는 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까지도 가능하죠. 단계별로 하나씩 확장해가며 연습해보세요. 실전에서 가장 중요한 건 “작은 성공 경험”이거든요 😊

댓글 남기기