| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- Algorithm
- JPA
- OS
- Road to Web3
- 운영체제
- react
- Ethereum
- design pattern
- 백준
- Galera Cluster
- 디자인 패턴
- 컴퓨터구조
- redis
- C
- 자바
- 네트워크
- MySQL
- mongoDB
- JavaScript
- Data Structure
- Spring
- Java
- 자료구조
- spring webflux
- Blockchain
- 알고리즘
- Heap
- MSA
- 파이썬
- IT
- Today
- Total
시냅스
Road to Web3 (10) 스마트컨트랙트는 DB 트랜잭션 함수다 본문
이 글은 Ethereum 및 EVM 계열을 기준으로 설명합니다.
이번 편은 웹 백엔드 개발자가 가장 빨리 감을 잡는 비유를 사용합니다.
- 스마트컨트랙트 함수 호출 = DB 트랜잭션 함수 호출
- require = 사전 조건 검사
- revert = 롤백
이 비유가 완벽하진 않지만, 초반에 뇌를 붙잡는 데는 매우 유효합니다.
제가 처음 스마트컨트랙트를 접할 때 했던 오해는 이렇습니다.
- 컨트랙트는 마법 같은 자동화 서버다
- 실패하면 아무 일도 안 일어난다
- 트랜잭션은 값만 보내는 단순 송금이다
하지만 EVM에서 컨트랙트는 더 현실적입니다.
- 상태를 가진 프로그램
- 입력 calldata 를 받아 실행
- 실행 결과로 상태를 변경하거나, 실패하면 롤백
- 실행 비용은 가스로 청구
요약
| 웹 백엔드 | EVM |
|---|---|
| API 호출 | 트랜잭션 또는 call |
| DB 트랜잭션 begin commit rollback | 컨트랙트 실행 성공 또는 revert |
| 사전 검증 validation | require |
| 예외 throw | revert |
| 트랜잭션 로그 테이블 | 이벤트 로그 event |
| DB 락 | 전역 직렬화 nonce 와 블록 순서 |
| 외부 시스템 | 오라클 브리지 인덱서 |
1) 컨트랙트는 상태를 가진 프로그램이다
컨트랙트는 코드와 상태가 같이 붙어 있습니다.
- 코드: EVM 바이트코드
- 상태: storage 슬롯 값들
web2로 비유하면
- 코드: 배포된 서비스 바이너리
- 상태: DB 테이블
컨트랙트 주소는 서비스 엔드포인트이자, 그 상태를 품은 저장소 네임스페이스입니다.

2) 컨트랙트 호출은 DB 트랜잭션 함수 호출과 닮았다
EVM에서 상태를 바꾸는 호출은 결국 트랜잭션입니다.
- 트랜잭션이 블록에 포함되고
- 모든 노드가 그 트랜잭션을 실행하고
- 동일한 상태 변경을 재현해야 합니다
이 구조 때문에 컨트랙트 함수는 DB 트랜잭션 함수처럼 봐도 됩니다.
예를 들어 ERC20 transfer 는 이런 함수입니다.
- balances[from] 감소
- balances[to] 증가
- Transfer 로그 기록
web2로 번역하면
- update accounts set balance = balance - amount where id = from
- update accounts set balance = balance + amount where id = to
- insert into audit_log
단, EVM에는 트랜잭션 격리 수준을 선택하는 옵션이 없습니다.
체인이 정한 순서대로 전역 직렬로 실행됩니다.

3) require 는 사전 조건 검사다
Solidity에서 require 는 조건을 만족하지 않으면 즉시 실패합니다.
- 잔액이 충분한가
- 권한이 있는가
- 입력이 유효한가
- 상태가 기대한 값인가
web2에서라면 보통
- validation 실패면 400
- 권한 실패면 403
- 비즈니스 조건 실패면 409
같은 식으로 분기할 텐데, 컨트랙트에서는 그냥 require 로 통일됩니다.
하지만 중요한 차이가 하나 있습니다.
- require 실패는 롤백을 만든다
- 그리고 실패해도 가스를 일부 소비한다
4) revert 는 롤백이다
컨트랙트 실행 도중 revert 되면
- 지금까지의 상태 변경이 전부 무효
- 이벤트 로그도 남지 않음
- 다만 이미 소비한 실행 가스는 지불
web2 DB 트랜잭션으로 치면
- begin
- update update update
- throw
- rollback
과 거의 같습니다.

5) call 과 트랜잭션의 차이
여기서 혼동이 자주 생깁니다.
- call eth_call: 상태를 바꾸지 않고 실행만 시뮬레이션
- 트랜잭션: 상태를 실제로 바꾸는 커밋
web2 비유로는
- call: read only 쿼리 또는 dry run
- tx: 실제 commit 을 포함하는 write 트랜잭션
그래서 서비스는 보통
- 먼저 call 로 실패 여부를 시뮬레이션하고
- 그 다음 tx 를 보내는
패턴을 씁니다.
6) 동시성은 락이 아니라 전역 직렬화로 해결한다
web2에서는 여러 요청이 동시에 들어오면
- 낙관적 락 버전 체크
- 비관적 락 row lock
같은 걸 씁니다.
체인은 다르게 합니다.
- 하나의 블록에서 트랜잭션은 정해진 순서로 실행
- EOA 는 nonce 로 순서가 강제
- 컨트랙트 상태는 실행 순서에 의해 결정
즉, 락 대신 순서를 고정해 직렬 실행을 만든다고 보면 됩니다.
하지만 이게 만능은 아닙니다.
- 같은 블록 안에서 순서가 바뀌면 결과가 바뀐다
- 그래서 순서 경쟁이 생기고, MEV 같은 현상이 등장한다
7) 이벤트 로그는 감사 로그이자 인덱싱 원재료다
컨트랙트는 이벤트 로그를 남깁니다.
- Transfer
- Approval
- OrderFilled
이 로그는
- 사용자에게는 트랜잭션 히스토리
- 서비스에게는 인덱싱 원재료
- 운영자에게는 감사 로그
역할을 합니다.
web2에서는 트랜잭션 로그 테이블과 CDC 같은 것을 붙이는 감각과 닮았습니다.
8) 체크리스트
1) 상태 변경 호출은 전부 트랜잭션이고 비용이 든다
2) require 는 validation 이 아니라 롤백 트리거다
3) revert 는 공짜가 아니고 가스를 소비한다
4) out of gas 는 실패 비용이 커서 최우선으로 줄인다
5) call 로 사전 시뮬레이션하되, 레이스 컨디션은 남는다
6) 이벤트는 진실 원천이 아니라, 상태 변경의 흔적이다
7) 인덱서는 reorg 와 중복을 전제로 설계한다
8) 컨트랙트 함수는 외부 호출과 재진입 위험을 가진다
9) 업그레이드 가능 컨트랙트는 운영 리스크가 더 크다
10) web2 결제처럼 상태 머신과 멱등성을 반드시 구현한다
결론
- 스마트컨트랙트 호출은 DB 트랜잭션 함수 호출처럼 생각하면 이해가 빠르다
- require 는 사전 조건, revert 는 롤백이다
- call 은 시뮬레이션, 트랜잭션은 커밋이다
- 락 대신 전역 직렬화로 동시성을 다룬다
'Road To Web3 > Blockchain' 카테고리의 다른 글
| Road to Web3 (9) 토큰 vs 네이티브 코인: USDC는 있는데 왜 전송이 안 되죠 (0) | 2025.12.29 |
|---|---|
| Road to Web3 (8) 가스비의 실체: 가스 사용량 곱하기 가스 가격 (0) | 2025.12.29 |
| Road to Web3 (7) 서명 2종류: 메시지 서명 vs 트랜잭션 서명 (0) | 2025.12.28 |
| Road to Web3 (6) 지갑은 키 관리 + 서명기: 주소/개인키/공개키 (0) | 2025.12.28 |
| Road to Web3 (5) 온체인 vs 오프체인: 임의 처리가 아니라 합의 경계 (0) | 2025.12.28 |
