먼저 보는 용어와 코드 읽기 지도
이 책은 프로그래밍 경험은 있다고 가정하지만, Rust와 블록체인은 처음이라고 가정합니다. 앞으로 나올 코드는 바로 실행 가능한 예제를 목표로 하지만, 처음 보는 문법과 용어가 한꺼번에 나오면 구조를 이해하기 어렵습니다.
이 장은 본문을 읽기 위한 지도입니다. 세부 구현은 뒤에서 다시 배우므로, 여기서는 단어의 뜻과 코드의 모양만 먼저 잡으세요.
1. 블록체인 핵심 용어
트랜잭션(Transaction)
트랜잭션은 블록체인에 기록해 달라고 네트워크에 제출하는 요청입니다.
백엔드 개발자의 관점으로 보면 트랜잭션은 다음에 가깝습니다.
HTTP POST /transfers
Body: {
"from": "Alice",
"to": "Bob",
"amount": "1 ETH"
}
다만 일반 API 요청과 다른 점이 있습니다.
| 일반 API 요청 | 블록체인 트랜잭션 |
|---|---|
| 서버가 인증 세션이나 JWT를 확인 | 개인 키 서명을 확인 |
| DB에 바로 반영될 수 있음 | 블록에 포함되어야 반영 |
| 관리자가 롤백할 수 있음 | 확정 후 되돌리기 어려움 |
| 서버 시간이 기준 | 네트워크 합의가 기준 |
예를 들어 “Alice가 Bob에게 1 ETH를 보낸다”는 말은 실제로는 “Alice가 개인 키로 서명한 트랜잭션을 네트워크에 제출했고, 검증자가 그 트랜잭션을 블록에 넣었다”는 뜻입니다.
블록(Block)
블록은 여러 트랜잭션을 묶은 기록 묶음입니다.
블록 #1024
├─ 이전 블록 해시: 0xabc...
├─ 생성 시각: 2026-04-14 10:00:00
├─ 트랜잭션 목록
│ ├─ Alice -> Bob: 1 ETH
│ ├─ Carol -> Dave: 0.2 ETH
│ └─ Token.transfer(...)
└─ 이 블록의 해시: 0xdef...
일반 데이터베이스에 비유하면 블록은 transactions 테이블의 여러 row를 일정 시간마다 묶어 만든 변경 로그 배치에 가깝습니다. 차이는 이 배치가 이전 배치의 해시를 들고 있어서, 중간 기록을 바꾸면 뒤쪽 기록이 모두 어긋난다는 점입니다.
체인(Chain)
체인은 블록들이 이전 블록의 해시로 연결된 구조입니다.
블록 #0(제네시스) -> 블록 #1 -> 블록 #2 -> 블록 #3
각 블록은 previous_hash라는 필드에 바로 앞 블록의 해시를 저장합니다. 그래서 블록 #1의 내용을 바꾸면 블록 #1의 해시가 바뀌고, 블록 #2가 들고 있던 previous_hash와 맞지 않게 됩니다. 이 연결 구조 때문에 과거 데이터 변조가 어렵습니다.
제네시스 블록(Genesis Block)
제네시스 블록은 체인의 첫 번째 블록입니다. 앞 블록이 없으므로 previous_hash를 0000... 같은 특수 값으로 둡니다.
제네시스 블록 = 체인의 시작점
해시(Hash)
해시는 데이터를 고정 길이 지문으로 바꾸는 함수의 결과입니다.
SHA256("hello") = 2cf24dba5fb0a30e...
SHA256("hellO") = 185f8db32921bd46...
입력이 한 글자만 달라도 출력이 완전히 달라집니다. 블록체인은 이 성질을 이용해 “기록이 바뀌었는가?”를 빠르게 확인합니다.
노드(Node)
노드는 블록체인 네트워크에 참여하는 컴퓨터 프로그램입니다.
노드는 보통 다음 일을 합니다.
- 다른 노드와 연결한다
- 트랜잭션을 전달받고 검증한다
- 블록을 전달받고 검증한다
- 자기 로컬 디스크에 체인 데이터를 저장한다
- 경우에 따라 새 블록 생성에 참여한다
Node.js 서버 하나가 HTTP 요청을 처리하듯, 블록체인 노드는 P2P 네트워크 요청을 처리합니다.
합의(Consensus)
합의는 여러 노드가 어떤 블록을 정식 기록으로 인정할지 결정하는 규칙입니다.
중앙 DB에서는 주 서버가 쓰기를 결정합니다. 블록체인에서는 중앙 주인이 없기 때문에, 네트워크 참여자들이 같은 규칙으로 블록을 검증하고 같은 체인을 선택해야 합니다.
대표적인 합의 방식은 다음과 같습니다.
| 방식 | 직관적 설명 | 예시 |
|---|---|---|
| Proof of Work | 계산 문제를 먼저 푼 노드가 블록 제안 | Bitcoin |
| Proof of Stake | 예치한 지분을 기반으로 검증자 선정 | Ethereum |
| Proof of Authority | 허가된 검증자들이 순번/투표로 블록 확정 | Besu private chain |
멤풀(Mempool)
멤풀은 아직 블록에 포함되지 않은 트랜잭션 대기열입니다.
백엔드의 작업 큐와 비슷합니다.
사용자 트랜잭션 제출
↓
멤풀에서 대기
↓
검증자/채굴자가 선택
↓
블록에 포함
이더리움에서는 가스비를 더 많이 내는 트랜잭션이 더 빨리 선택될 가능성이 큽니다.
지갑(Wallet), 주소(Address), 개인 키(Private Key)
지갑은 코인을 “보관하는 앱”처럼 보이지만, 정확히는 개인 키를 관리하고 트랜잭션에 서명하는 도구입니다.
| 용어 | 뜻 |
|---|---|
| 개인 키 | 트랜잭션에 서명할 수 있는 비밀값 |
| 공개 키 | 개인 키에서 계산되는 공개 가능한 값 |
| 주소 | 공개 키에서 파생된 짧은 식별자 |
| 지갑 | 개인 키를 보관하고 서명하는 앱 또는 라이브러리 |
중요한 점은 코인이 지갑 앱 안에 들어 있는 것이 아니라, 체인 상태에 “이 주소가 얼마를 가진다”라고 기록되어 있다는 것입니다.
스마트 컨트랙트(Smart Contract)
스마트 컨트랙트는 블록체인 위에 배포된 프로그램입니다.
일반 백엔드 코드와 비교하면 다음과 같습니다.
| 백엔드 서비스 | 스마트 컨트랙트 |
|---|---|
| 서버에 배포 | 블록체인에 배포 |
| DB 상태를 변경 | 온체인 상태를 변경 |
| 관리자가 핫픽스 가능 | 배포 후 수정 어려움 |
| 서버 비용 지불 | 사용자 또는 호출자가 가스비 지불 |
ERC-20 토큰, NFT, DEX, DAO 같은 애플리케이션은 스마트 컨트랙트로 구현됩니다.
가스(Gas)
가스는 블록체인에서 계산과 저장에 매기는 실행 비용 단위입니다.
이더리움에서는 컨트랙트 함수 호출, ETH 전송, 스토리지 변경 모두 가스를 소비합니다. 가스는 무한 루프와 네트워크 남용을 막고, 검증자에게 처리 보상을 줍니다.
2. Rust 코드 읽기 지도
처음에는 Rust 코드를 모두 이해하려고 하지 않아도 됩니다. 아래 기호만 먼저 알아두면 본문 예제를 훨씬 덜 낯설게 읽을 수 있습니다.
fn main()
fn main() {
println!("Hello, world!");
}
fn은 함수를 정의한다는 뜻입니다. main은 실행 파일의 시작점입니다. TypeScript의 main() 함수나 Node.js 파일의 최상위 실행 코드와 비슷합니다.
println!
println!("Block height: {}", 100);
println!은 콘솔에 출력하는 매크로입니다. !가 붙으면 일반 함수가 아니라 **매크로(macro)**입니다. 처음에는 console.log와 비슷하다고 생각해도 됩니다.
let과 mut
#![allow(unused)]
fn main() {
let height = 100;
let mut nonce = 0;
nonce = nonce + 1;
}
let은 변수를 만듭니다. Rust 변수는 기본적으로 불변입니다. 값을 바꾸려면 mut를 붙입니다.
| TypeScript | Rust |
|---|---|
const height = 100 | let height = 100 |
let nonce = 0; nonce += 1 | let mut nonce = 0; nonce += 1 |
타입 표기 : u64
#![allow(unused)]
fn main() {
let block_height: u64 = 1024;
}
콜론 뒤는 타입입니다. u64는 “부호 없는 64비트 정수”입니다. 블록 높이, 잔액, nonce처럼 음수가 될 수 없는 큰 숫자에 자주 씁니다.
String과 &str
#![allow(unused)]
fn main() {
let owned: String = String::from("Alice");
let borrowed: &str = "Bob";
}
둘 다 문자열처럼 보이지만 역할이 다릅니다.
| 타입 | 의미 | 비유 |
|---|---|---|
String | 내가 소유한 가변 문자열 | 직접 들고 있는 데이터 |
&str | 어딘가에 있는 문자열을 빌려 읽는 참조 | 읽기 전용 view |
자세한 규칙은 소유권 장에서 배웁니다. 처음에는 String은 소유, &str은 빌림이라고 기억하세요.
struct
#![allow(unused)]
fn main() {
struct Block {
index: u64,
hash: String,
}
}
struct는 데이터를 묶는 타입입니다. TypeScript의 interface나 DTO와 비슷하지만, Rust에서는 메서드를 struct 안에 직접 넣지 않고 impl 블록에 따로 둡니다.
impl과 Self
impl Block {
fn new(index: u64, hash: String) -> Self {
Self { index, hash }
}
}
impl Block은 Block 타입에 함수를 붙이는 영역입니다. Self는 현재 타입, 여기서는 Block을 뜻합니다.
Vec<T>
let blocks: Vec<Block> = Vec::new();
Vec<T>는 Rust의 가변 길이 배열입니다. TypeScript의 T[]와 가장 비슷합니다.
| TypeScript | Rust |
|---|---|
Block[] | Vec<Block> |
blocks.push(block) | blocks.push(block) |
참조 &
#![allow(unused)]
fn main() {
fn print_hash(hash: &String) {
println!("{}", hash);
}
}
&String은 String을 소유하지 않고 빌려 읽겠다는 뜻입니다. TypeScript에서는 객체 참조 전달이 자연스럽지만, Rust는 소유권 이동과 빌림을 문법으로 구분합니다.
Result<T, E>와 ?
#![allow(unused)]
fn main() {
fn parse_height(input: &str) -> Result<u64, std::num::ParseIntError> {
let height = input.parse::<u64>()?;
Ok(height)
}
}
Result<T, E>는 성공하면 Ok(T), 실패하면 Err(E)를 담는 타입입니다. ?는 실패(Err)가 나오면 즉시 바깥 함수로 돌려보냅니다.
TypeScript의 throw/try-catch와 목적은 비슷하지만, Rust에서는 에러가 반환 타입에 드러납니다.
#[derive(...)]
#![allow(unused)]
fn main() {
#[derive(Debug, Clone)]
struct Transaction {
from: String,
to: String,
}
}
#[derive(...)]는 컴파일러에게 반복 코드를 자동 생성해 달라고 요청하는 속성입니다. 예를 들어 Debug는 println!("{:?}", value)로 출력할 수 있게 해주고, Clone은 명시적 복사를 가능하게 합니다.
3. 이 책의 코드 읽기 순서
처음 보는 긴 예제가 나오면 아래 순서로 읽으세요.
struct부터 찾습니다. 어떤 데이터를 다루는지 먼저 봅니다.impl을 봅니다. 그 데이터에 어떤 동작이 붙는지 봅니다.main을 봅니다. 실제 실행 흐름을 봅니다.Result,?,unwrap은 에러 처리 장에서 자세히 배울 문법이라고 표시만 해둡니다.&,clone,String,Vec은 소유권/컬렉션 장에서 다시 배울 문법이라고 표시만 해둡니다.
블록체인 예제도 마찬가지입니다.
데이터 구조 확인: Block, Transaction, Blockchain
↓
동작 확인: new, calculate_hash, mine, validate
↓
실행 흐름 확인: main에서 블록 생성, 추가, 검증
코드를 처음부터 한 줄씩 완벽히 이해하려고 하면 어렵습니다. 이 책에서는 먼저 “이 코드가 어떤 역할을 하는가”를 잡고, 문법은 각 장에서 반복해서 풀어갑니다.
4. 앞으로 자주 만날 단어 한 줄 요약
| 단어 | 한 줄 뜻 |
|---|---|
| 트랜잭션 | 체인 상태를 바꾸기 위해 서명해서 제출하는 요청 |
| 블록 | 트랜잭션 여러 개와 메타데이터를 묶은 기록 단위 |
| 체인 | 이전 블록 해시로 연결된 블록 목록 |
| 해시 | 데이터의 고정 길이 지문 |
| 노드 | 블록체인 네트워크에 참여하는 컴퓨터 프로그램 |
| 합의 | 여러 노드가 같은 기록을 정식으로 인정하는 규칙 |
| 멤풀 | 아직 블록에 들어가지 않은 트랜잭션 대기열 |
| 지갑 | 개인 키를 관리하고 트랜잭션에 서명하는 도구 |
| 주소 | 체인에서 계정이나 컨트랙트를 식별하는 값 |
| 스마트 컨트랙트 | 블록체인 위에서 실행되는 프로그램 |
| 가스 | 온체인 실행 비용 단위 |
| nonce | 한 번만 쓰는 숫자. 순서 보장이나 채굴 탐색에 사용 |
다음 장부터는 이 단어들이 반복해서 나옵니다. 헷갈리면 이 장으로 돌아와 먼저 뜻을 확인하세요.