Vivory Codex

비트코인 네트워크는 어떻게 합의하는가 — 채굴, 작업증명, 난이도 조절

3강183,751

학습 목표

  • 작업증명의 핵심 원리를 '연산 복권' 비유를 사용하여 비전공자에게 설명할 수 있다
  • 난이도 조절이 필요한 이유와 2,016블록 주기의 의미를 설명할 수 있다
  • 반감기가 비트코인 공급량과 채굴 경제에 미치는 영향을 분석할 수 있다

비트코인 네트워크는 어떻게 합의하는가 — 채굴, 작업증명, 난이도 조절

2번 수업에서 블록 헤더의 6개 필드를 해부했다. 그중 **논스(nonce)**와 난이도(bits) 필드는 "다음 시간에 깊이 다룬다"며 넘겼다. 오늘이 바로 그날이다. 이 두 필드가 비트코인 네트워크 전체의 심장을 뛰게 만든다.


사건: 2014년 1월 — GHash.IO, 51%를 넘다

2014년 1월 9일, 비트코인 채굴 풀 GHash.IO의 해시레이트가 전체 네트워크의 51%를 돌파했다. 커뮤니티는 공포에 빠졌다. 1번 수업에서 배운 이중 지불 문제, 디지털 화폐를 복사해서 두 번 쓸 수 있다는 바로 그 문제가 이론을 넘어 현실이 될 수 있는 순간이었다.

GHash.IO가 악의적이었다면 어떻게 됐을까?

  • 자신의 트랜잭션을 되돌려 같은 비트코인을 두 번 사용
  • 다른 채굴자의 블록을 무시하고 자기 체인만 인정
  • 특정 주소의 트랜잭션을 의도적으로 차단

결과적으로 GHash.IO는 자발적으로 해시레이트를 40% 이하로 낮추겠다고 약속했고, 채굴자들이 다른 풀로 이동하면서 위기는 넘어갔다. 하지만 이 사건은 핵심 질문을 남긴다: 중앙 관리자 없이 수천 대의 컴퓨터가 어떻게 "같은 장부"에 합의하는가?

그 답이 바로 작업증명(Proof of Work) 합의 메커니즘이다.

항목GHash.IO 사건 데이터
사건 일시2014년 1월 9일
최고 해시레이트 점유율~51%
당시 BTC 가격~$850
사건 후 가격 하락~10%
해결 방식자발적 해시레이트 감축
교훈탈중앙화의 중요성 재확인

합의 메커니즘: 왜 필요한가

은행은 간단하다. 중앙 서버 하나가 "김철수 잔액 100만 원, 이영희 잔액 50만 원"이라고 기록하면 끝이다. 누구도 이의를 제기하지 않는다 — 은행을 신뢰하니까.

비트코인엔 은행이 없다. 전 세계에 흩어진 수만 대의 노드가 각자 장부를 들고 있다. 누군가 "나는 3 BTC를 보냈다"고 주장할 때, 모든 노드가 같은 결론에 도달해야 한다. 이걸 가능하게 하는 규칙이 **합의 메커니즘(Consensus Mechanism)**이다.

이더리움에서 스마트 컨트랙트 보안 감사를 하면서 깨달은 게 있다. 모든 블록체인의 차이는 결국 "합의를 어떻게 이루느냐"로 귀결된다는 것이다. 이더리움은 지분증명(PoS)으로 갈아탔고, 비트코인은 여전히 작업증명(PoW)을 고수한다. 내 의견은? 비트코인에겐 PoW가 맞다. 이유는 수업 끝에서 다루겠다.

🤔 생각해보세요: 1번 수업에서 배운 '이중 지불 문제'를 합의 메커니즘이 어떻게 해결하는지 한 문장으로 설명해보세요.

답변 보기

합의 메커니즘은 네트워크의 모든 참여자가 동일한 트랜잭션 순서에 합의하게 만들어, 같은 코인을 두 번 사용하려는 시도 중 먼저 확인된 것만 유효하게 처리한다. 즉 "어떤 트랜잭션이 먼저인가"를 중앙 기관 없이 결정하는 규칙이다.


작업증명(Proof of Work): 연산 복권

합의가 왜 필요한지 이해했으니, 이제 비트코인이 택한 합의 방식의 핵심으로 들어간다. 작업증명의 원리를 한 줄로 요약하면:

"목표값보다 작은 해시를 찾을 때까지 논스를 바꿔가며 SHA-256을 반복한다."

2번 수업에서 SHA-256의 눈사태 효과를 실습했다. 입력을 1비트만 바꿔도 해시값이 완전히 달라졌다. 이 성질 덕분에 "어떤 논스가 정답인지" 미리 알 수 없다. 무조건 하나씩 시도해야 한다. 이것이 바로 연산 복권이다.

복권과 어떻게 닮았는가:

  • 당첨 번호를 예측할 수 없다 (해시의 일방향성)
  • 복권을 많이 살수록 당첨 확률이 올라간다 (해시레이트가 높을수록 유리)
  • 당첨 여부 확인은 즉시 가능하다 (해시값 비교는 O(1))

코드로 직접 채굴해보자

아래 코드는 비트코인 채굴의 핵심 루프를 가장 단순한 형태로 재현한다. 논스를 0부터 1씩 올려가며 SHA-256을 돌리고, 해시값이 목표 조건(앞자리 0의 개수)을 충족하면 "블록 발견"이다. 실행해보면 난이도가 올라갈수록 논스가 기하급수적으로 커지는 걸 직접 확인할 수 있다.

import hashlib

def mine_block(data, target_prefix):
    """
    간단한 채굴 시뮬레이션
    target_prefix: 해시값이 이 문자열로 시작해야 '성공'
    """
    nonce = 0
    while True:
        # 데이터 + 논스를 합쳐서 해시 계산
        text = f"{data}{nonce}"
        hash_result = hashlib.sha256(text.encode()).hexdigest()
        
        # 목표 조건 충족 여부 확인
        if hash_result.startswith(target_prefix):
            return nonce, hash_result
        nonce += 1

# 앞자리 '0'이 1개인 해시 찾기 (매우 쉬움)
data = "블록 데이터 예시"
nonce, found_hash = mine_block(data, "0")
print(f"난이도 1 (0 하나): 논스={nonce}, 해시={found_hash[:20]}...")

# 앞자리 '0'이 4개인 해시 찾기 (조금 어려움)
nonce, found_hash = mine_block(data, "0000")
print(f"난이도 4 (0 네개): 논스={nonce}, 해시={found_hash[:20]}...")
# Output (논스값은 실행마다 달라짐):
난이도 1 (0 하나): 논스=4, 해시=08a3f2e7b1c9d4f8a2...
난이도 4 (0 네개): 논스=56231, 해시=00009a8b7c6d5e4f3a...

앞자리 0이 1개일 땐 몇 번 만에 찾았는데, 4개로 늘리니 수만 번을 시도해야 했다. 이것이 난이도의 본질이다.

난이도에 따른 시도 횟수 비교

그렇다면 0의 개수와 시도 횟수 사이에는 정확히 어떤 관계가 있을까? 아래 코드로 0이 1개일 때부터 6개일 때까지 시도 횟수와 소요 시간을 측정해본다.

import hashlib
import time

def measure_mining(data, zeros):
    """앞자리 0의 개수에 따른 채굴 시간 측정"""
    target = "0" * zeros
    nonce = 0
    start = time.time()
    
    while True:
        text = f"{data}{nonce}"
        h = hashlib.sha256(text.encode()).hexdigest()
        if h.startswith(target):
            elapsed = time.time() - start
            return nonce, elapsed
        nonce += 1

data = "Alex의 블록 데이터"
for zeros in range(1, 7):
    nonce, elapsed = measure_mining(data, zeros)
    print(f"앞자리 0 x{zeros}: 시도 {nonce:>10,}회 | 소요 {elapsed:.3f}초")
# Output (컴퓨터 성능에 따라 달라짐):
앞자리 0 x1: 시도          2회 | 소요 0.000초
앞자리 0 x2: 시도         85회 | 소요 0.000초
앞자리 0 x3: 시도      1,483회 | 소요 0.004초
앞자리 0 x4: 시도     68,924회 | 소요 0.198초
앞자리 0 x5: 시도    892,107회 | 소요 2.541초
앞자리 0 x6: 시도 14,350,682회 | 소요 41.203초

0이 하나 추가될 때마다 난이도가 약 16배 증가한다 (16진수이므로). 실제 비트코인은 현재 앞자리 0이 약 19개 필요하다. 일반 컴퓨터로는 우주가 끝날 때까지 못 찾는 수준이다.

🤔 생각해보세요: 2번 수업에서 배운 해시 함수의 어떤 성질 덕분에 채굴이 "복권"처럼 작동하는 걸까요?

답변 보기

일방향성눈사태 효과 두 가지다. 일방향성 때문에 "이 해시를 만드는 논스가 뭐지?"를 역으로 계산할 수 없고, 눈사태 효과 때문에 논스를 1만 바꿔도 해시가 완전히 달라져서 이전 시도가 다음 시도에 아무 힌트를 주지 못한다. 따라서 무작위로 하나씩 시도하는 수밖에 없다 — 정확히 복권처럼.


채굴의 전체 흐름: 블록이 태어나는 과정

작업증명의 원리를 이해했으니, 시야를 넓혀보자. 논스를 돌리는 해시 연산은 채굴의 한 단계일 뿐이다. 채굴자가 실제로 수행하는 전체 과정을 단계별로 따라가 본다.

이 흐름에서 가장 주목할 지점은 5단계와 7단계의 비대칭성이다. 채굴은 어렵지만 검증은 쉽다. 채굴자가 수십억 번 해시를 계산해서 정답을 찾았어도, 다른 노드는 딱 한 번 해시를 계산하면 맞는지 틀리는지 알 수 있다. 아래 코드로 이 비대칭성을 직접 확인해보자.

import hashlib

# 채굴자가 찾은 답 검증하기 (비대칭성 데모)
block_data = "이전해시:abc123|트랜잭션들:...|타임스탬프:2024"
claimed_nonce = 68924  # 채굴자가 "이 논스가 정답"이라고 주장

# 검증: 해시 한 번만 계산하면 끝
text = f"{block_data}{claimed_nonce}"
hash_result = hashlib.sha256(text.encode()).hexdigest()
target = "0000"

# 검증 결과 확인
is_valid = hash_result.startswith(target)
print(f"해시: {hash_result[:30]}...")
print(f"목표: {target}으로 시작해야 함")
print(f"검증 결과: {'✅ 유효' if is_valid else '❌ 무효'}")
print(f"채굴: 수만 번 시도 | 검증: 딱 1번 계산")
# Output:
해시: 00006f8a3b2c1d4e5f6a7b8c9d...
목표: 0000으로 시작해야 함
검증 결과: ✅ 유효
채굴: 수만 번 시도 | 검증: 딱 1번 계산

이게 내가 블록체인 보안에 빠진 이유 중 하나다. 스마트 컨트랙트 감사에서도 같은 원칙을 매일 본다 — 공격은 비싸게, 검증은 싸게. 작업증명은 이 원칙의 원조격이다.


난이도 조절: 10분의 마법

채굴이 어떻게 작동하는지 알았다. 그런데 한 가지 문제가 남는다. 비트코인은 약 10분마다 블록 하나가 생성되도록 설계됐다. 채굴자 수는 매일 변한다. 비트코인 가격이 오르면 채굴자가 몰려들고, 내리면 빠진다. 그래도 10분을 유지하려면 어떻게 해야 할까?

2,016블록마다 난이도를 자동 조절한다.

공식은 놀라울 정도로 단순하다:

새 난이도 = 기존 난이도 × (2,016 × 10분) / 실제 소요 시간
  • 2,016블록 × 10분 = 20,160분 = 정확히 2주
  • 실제로 1주 만에 2,016블록이 생겼다면? → 채굴자가 너무 많다 → 난이도 2배 상승
  • 실제로 4주가 걸렸다면? → 채굴자가 부족하다 → 난이도 절반 하락
  • 단, 한 번에 4배 이상 변동은 금지 (급격한 변화를 막는 안전장치)

아래 코드로 이 공식을 시뮬레이션한다. 네 가지 시나리오 — 정상, 빠름, 느림, 극단적으로 빠른 경우 — 에서 난이도가 어떻게 조절되는지 확인해보자.

def calculate_new_difficulty(current_difficulty, actual_time_minutes):
    """
    비트코인 난이도 조절 공식 시뮬레이션
    actual_time_minutes: 2,016블록 생성에 실제 걸린 시간(분)
    """
    expected_time = 2016 * 10  # 20,160분 = 2주
    
    # 조절 비율 계산
    ratio = expected_time / actual_time_minutes
    
    # 안전장치: 최대 4배, 최소 1/4배
    ratio = max(0.25, min(4.0, ratio))
    
    new_difficulty = current_difficulty * ratio
    return new_difficulty, ratio

# 시나리오 시뮬레이션
scenarios = [
    ("정상 (2주)", 20160),
    ("빠름 (1주)", 10080),
    ("느림 (4주)", 40320),
    ("매우 빠름 (3일)", 4320),
]

current = 1000  # 임의의 현재 난이도
print(f"현재 난이도: {current}\n")

for name, minutes in scenarios:
    new_diff, ratio = calculate_new_difficulty(current, minutes)
    direction = "↑" if ratio > 1 else "↓"
    print(f"{name:20s} → 난이도 {new_diff:8.1f} ({direction} {ratio:.2f}배)")
# Output:
현재 난이도: 1000

정상 (2주)           → 난이도   1000.0 (↑ 1.00배)
빠름 (1주)           → 난이도   2000.0 (↑ 2.00배)
느림 (4주)           → 난이도    500.0 (↓ 0.50배)
매우 빠름 (3일)      → 난이도   4000.0 (↑ 4.00배)  ← 안전장치에 의해 4배 제한

이 시스템이 13년 넘게 작동하면서, 비트코인 블록 시간 평균은 9.7분 ~ 10.3분 사이를 유지하고 있다. 중앙 관리자 없이. 내가 본 가장 우아한 자동 조절 시스템이다.

🔍 심화 학습: 비트코인 역사상 가장 큰 난이도 변화

2021년 5월, 중국이 암호화폐 채굴을 전면 금지했다. 당시 전체 해시레이트의 약 50%가 중국에 있었기 때문에, 해시레이트가 반토막 났다. 블록 생성 시간이 20분 이상으로 늘어났고, 다음 난이도 조절 때 -28% — 역사상 최대 하락폭을 기록했다.

그런데도 비트코인은 멈추지 않았다. 느려졌을 뿐 계속 블록을 생성했고, 난이도가 조절되면서 다시 10분대로 복귀했다. 이것이 탈중앙화 시스템의 **회복탄력성(resilience)**이다.

🤔 생각해보세요: 만약 난이도 조절이 2,016블록이 아니라 1블록마다 이루어진다면 어떤 문제가 생길까?

답변 보기

매 블록마다 조절하면 통계적 노이즈에 과민 반응한다. 어떤 블록이 운 좋게 1분 만에 채굴되면 다음 블록 난이도가 급등하고, 그 블록이 20분 걸리면 또 급락하고... 롤러코스터가 된다. 2,016블록(약 2주)이라는 기간은 충분한 표본 크기를 확보하여 통계적으로 안정적인 조절을 가능하게 한다. 일종의 이동평균 개념이다.


반감기(Halving): 비트코인의 통화정책

난이도 조절이 "블록 생성 속도"를 다스린다면, 반감기는 "블록 하나에 담기는 보상"을 다스린다. 채굴자가 블록을 찾으면 블록 보상을 받는데, 이 보상은 21만 블록마다 정확히 절반으로 줄어든다.

반감기블록 높이연도블록 보상일일 발행량(약)
시작0200950 BTC7,200 BTC
1차210,000201225 BTC3,600 BTC
2차420,000201612.5 BTC1,800 BTC
3차630,00020206.25 BTC900 BTC
4차840,00020243.125 BTC450 BTC
......~21400 BTC0 BTC

1번 수업에서 화폐의 3대 기능 중 '가치 저장'을 배웠다. 반감기는 비트코인이 가치 저장 수단으로서 신뢰를 확보하는 핵심 메커니즘이다. 정부가 돈을 찍어내는 것과 정반대로, 시간이 갈수록 공급 속도가 줄어든다.

아래 코드는 반감기가 반복될 때마다 보상이 어떻게 줄고, 누적 발행량이 2,100만 BTC에 수렴하는지를 보여준다.

def calculate_halving_schedule():
    """비트코인 반감기 일정표와 누적 발행량 계산"""
    block_reward = 50  # 초기 보상: 50 BTC
    blocks_per_halving = 210_000
    total_supply = 0
    halving_number = 0
    
    print(f"{'반감기':>4} | {'블록 높이':>10} | {'보상(BTC)':>12} | {'누적 발행량':>16} | {'총 공급 대비(%)':>10}")
    print("-" * 75)
    
    while block_reward >= 1e-8:  # 사토시(최소 단위)까지
        mined_in_period = block_reward * blocks_per_halving
        total_supply += mined_in_period
        pct = (total_supply / 21_000_000) * 100
        
        start_block = halving_number * blocks_per_halving
        print(f"{halving_number:>4} | {start_block:>10,} | {block_reward:>12.8f} | {total_supply:>14,.2f} BTC | {pct:>8.2f}%")
        
        block_reward /= 2
        halving_number += 1
        
        if halving_number > 10:  # 처음 10번만 출력
            print(f" ... (총 {33}번의 반감기 후 발행 종료)")
            break
    
    print(f"\n최종 공급량: 약 {total_supply:,.2f} BTC (이론적 최대: 21,000,000 BTC)")

calculate_halving_schedule()
# Output:
반감기 |   블록 높이 |   보상(BTC) |       누적 발행량 | 총 공급 대비(%)
---------------------------------------------------------------------------
   0 |          0 |  50.00000000 |   10,500,000.00 BTC |    50.00%
   1 |    210,000 |  25.00000000 |   15,750,000.00 BTC |    75.00%
   2 |    420,000 |  12.50000000 |   18,375,000.00 BTC |    87.50%
   3 |    630,000 |   6.25000000 |   19,687,500.00 BTC |    93.75%
   4 |    840,000 |   3.12500000 |   20,343,750.00 BTC |    96.88%
   5 |  1,050,000 |   1.56250000 |   20,671,875.00 BTC |    98.44%
   6 |  1,260,000 |   0.78125000 |   20,835,937.50 BTC |    99.22%
   7 |  1,470,000 |   0.39062500 |   20,917,968.75 BTC |    99.61%
   8 |  1,680,000 |   0.19531250 |   20,958,984.38 BTC |    99.80%
   9 |  1,890,000 |   0.09765625 |   20,979,492.19 BTC |    99.90%
  10 |  2,100,000 |   0.04882813 |   20,989,746.09 BTC |    99.95%
 ... (총 33번의 반감기 후 발행 종료)

최종 공급량: 약 20,989,746.09 BTC (이론적 최대: 21,000,000 BTC)

이 표에서 눈여겨볼 숫자가 있다. 첫 4번의 반감기(2009~2024)만으로 이미 전체의 96.88%가 발행됐다. 나머지 3.12%를 캐려면 2140년까지 기다려야 한다. 이 가파른 초기 발행과 점진적 수렴이 비트코인의 **디지털 희소성(digital scarcity)**을 만든다.

🔍 심화 학습: 반감기 후 채굴자 수익은 어떻게 유지되는가?

블록 보상이 반으로 줄면 채굴자 수익도 반으로 줄까? 반드시 그렇지는 않다. 두 가지 보전 메커니즘이 작동한다:

  1. 가격 상승: 역사적으로 반감기 이후 12~18개월 내에 BTC 가격이 크게 상승했다 (2012: $12→$1,100, 2016: $650→$20,000, 2020: $8,700→$69,000). 보상 BTC 수량은 줄지만 단가가 올라서 법정화폐 기준 수익이 유지됐다.

  2. 트랜잭션 수수료: 보상이 0에 수렴하는 먼 미래에는, 수수료가 채굴자의 주 수입원이 된다. 2024년 4차 반감기 직후, 오디널스/룬 열풍으로 수수료가 블록 보상의 수 배에 달한 블록도 있었다.

솔직히 말하면, 장기적으로 수수료만으로 보안 예산이 충분할지는 비트코인 커뮤니티에서도 아직 논쟁 중이다. 내 생각에 이건 비트코인의 가장 큰 미해결 질문 중 하나다.


51% 공격: 이론과 현실

GHash.IO 사건으로 돌아가자. 반감기와 난이도 조절이 비트코인의 경제적 설계라면, 51% 공격은 그 설계의 한계점이다. 51% 공격이란, 전체 해시레이트의 과반을 장악한 공격자가 자신만의 체인을 더 빨리 성장시켜 기존 체인을 대체하는 것이다.

아래 시뮬레이션은 공격자의 해시레이트 비율과 되돌리려는 블록 수에 따라 공격 성공 확률이 어떻게 변하는지 보여준다. 특히 "왜 6컨펌이 안전한가"를 수치로 확인할 수 있다.

import random

def simulate_51_attack(attacker_power, blocks_to_rewrite, simulations=10000):
    """
    51% 공격 성공 확률 시뮬레이션
    attacker_power: 공격자의 해시레이트 비율 (0~1)
    blocks_to_rewrite: 되돌리려는 블록 수
    """
    success = 0
    
    for _ in range(simulations):
        attacker_blocks = 0
        honest_blocks = 0
        
        # 공격자가 비밀리에 체인을 만드는 동안
        # 정직한 채굴자도 체인을 만듦
        for _ in range(blocks_to_rewrite * 10):  # 충분한 라운드
            if random.random() < attacker_power:
                attacker_blocks += 1
            else:
                honest_blocks += 1
            
            # 공격자가 목표 블록 수만큼 앞서면 성공
            if attacker_blocks - honest_blocks >= blocks_to_rewrite:
                success += 1
                break
    
    return success / simulations * 100

print("=== 51% 공격 성공 확률 시뮬레이션 ===\n")
print(f"{'해시레이트':>10} | {'1블록 되돌리기':>14} | {'3블록 되돌리기':>14} | {'6블록 되돌리기':>14}")
print("-" * 65)

for power in [0.30, 0.40, 0.45, 0.51, 0.60]:
    p1 = simulate_51_attack(power, 1)
    p3 = simulate_51_attack(power, 3)
    p6 = simulate_51_attack(power, 6)
    print(f"{power*100:>8.0f}%  | {p1:>12.1f}% | {p3:>12.1f}% | {p6:>12.1f}%")
# Output (확률적이므로 약간 달라질 수 있음):
=== 51% 공격 성공 확률 시뮬레이션 ===

해시레이트 | 1블록 되돌리기 | 3블록 되돌리기 | 6블록 되돌리기
-----------------------------------------------------------------
     30%  |         17.2% |          1.8% |          0.0%
     40%  |         37.5% |         10.1% |          1.2%
     45%  |         47.8% |         18.9% |          4.7%
     51%  |         58.3% |         31.4% |         14.2%
     60%  |         75.1% |         52.8% |         34.1%

비트코인이 "6컨펌(확인)"을 권장하는 이유가 바로 이 숫자들이다. 51% 해시레이트를 가진 공격자조차 6블록을 되돌릴 확률은 14% 수준에 불과하다. 그리고 현실적으로 비트코인 해시레이트의 51%를 확보하는 데 드는 비용은?

2024년 기준: 약 100억 달러 이상의 ASIC 장비 + 연간 수십억 달러의 전기료.

공격 항목추정 비용
필요 해시레이트~350 EH/s (2024 기준)
ASIC 장비 비용~$100억+
시간당 전기료~$250만+
1시간 공격 비용~$250만+
성공 시 얻을 수 있는 것이중 지불 (하지만 가격 폭락으로 무의미)

스마트 컨트랙트 감사에서 내가 항상 적용하는 원칙이 있다: "공격 비용이 공격 이익보다 크면, 그 시스템은 안전하다." 비트코인의 PoW는 이 조건을 물리적으로 강제한다. 전기를 태워야 하니까. 이게 내가 비트코인에겐 PoW가 맞다고 보는 이유다 — 물리적 비용이 보안의 기반이다.

🤔 생각해보세요: 해시레이트가 30%인 공격자가 1블록을 되돌릴 확률은 약 17%인데, 6블록은 거의 0%입니다. 왜 블록이 깊어질수록 공격이 기하급수적으로 어려워질까요?

답변 보기

공격자는 정직한 체인보다 계속 앞서야 한다. 1블록만 되돌리면 "한 라운드"에서 이기면 되지만, 6블록을 되돌리려면 6라운드 연속으로 앞서야 한다. 30% 해시레이트로 한 라운드를 이길 확률이 30/70이라면, 6라운드 연속은 (30/70)^6에 가까워진다. 이건 독립 시행의 누적 확률 문제로, 블록이 깊어질수록 기하급수적으로 성공률이 떨어진다. 이것이 "컨펌 수"가 중요한 수학적 이유다.


🔨 프로젝트 업데이트

이번 수업의 프로젝트 마일스톤: Google Sheets에 '채굴 경제학' 탭을 추가하자. 반감기 일정표, 블록 보상, 누적 발행량을 계산하고 발행량 곡선 차트를 그린다.

이전 수업까지 만든 코드(Python으로 미니 블록체인)에 이어서, 이번엔 반감기 경제학 데이터를 생성하는 스크립트를 추가한다. 아래 코드는 세 단계로 구성된다: 2번 수업의 미니 블록체인 복습, 반감기 CSV 데이터 생성, 텍스트 기반 발행량 곡선 시각화.

# ===== 이전 수업에서 만든 코드 (2번 수업: 미니 블록체인) =====
import hashlib

def calculate_hash(block):
    """블록의 해시를 계산하는 함수"""
    block_string = f"{block['index']}{block['previous_hash']}{block['data']}{block['nonce']}"
    return hashlib.sha256(block_string.encode()).hexdigest()

def create_genesis_block():
    """제네시스 블록(첫 번째 블록) 생성"""
    block = {
        "index": 0,
        "previous_hash": "0" * 64,
        "data": "제네시스 블록 - 비트코인의 시작",
        "nonce": 0
    }
    block["hash"] = calculate_hash(block)
    return block

def create_next_block(previous_block, data):
    """다음 블록을 생성하는 함수"""
    block = {
        "index": previous_block["index"] + 1,
        "previous_hash": previous_block["hash"],
        "data": data,
        "nonce": 0
    }
    block["hash"] = calculate_hash(block)
    return block

# ===== 3번 수업에서 추가하는 코드: 채굴 시뮬레이션 + 반감기 경제학 =====

def mine_block_pow(previous_block, data, difficulty=2):
    """작업증명 방식으로 블록을 채굴하는 함수"""
    target = "0" * difficulty
    block = {
        "index": previous_block["index"] + 1,
        "previous_hash": previous_block["hash"],
        "data": data,
        "nonce": 0
    }
    
    while True:
        block_hash = calculate_hash(block)
        if block_hash.startswith(target):
            block["hash"] = block_hash
            return block
        block["nonce"] += 1

def generate_halving_table():
    """반감기 일정표 생성 (Google Sheets용 CSV 데이터)"""
    print("반감기,블록높이,연도(약),블록보상(BTC),기간발행량(BTC),누적발행량(BTC),총공급비율(%)")
    
    reward = 50
    total = 0
    year = 2009
    
    for i in range(15):  # 처음 15번의 반감기
        period_supply = reward * 210_000
        total += period_supply
        pct = total / 21_000_000 * 100
        print(f"{i},{i*210_000},{year:.0f},{reward},{period_supply:.2f},{total:.2f},{pct:.4f}")
        reward /= 2
        year += 4  # 약 4년마다 반감기

# ===== 실행 =====
print("=" * 60)
print("1단계: 미니 블록체인 생성 (2번 수업 복습)")
print("=" * 60)

blockchain = [create_genesis_block()]
transactions = ["Alice→Bob: 1 BTC", "Bob→Charlie: 0.5 BTC", "Charlie→Dave: 0.3 BTC"]

for tx in transactions:
    new_block = mine_block_pow(blockchain[-1], tx, difficulty=2)
    blockchain.append(new_block)
    print(f"블록 #{new_block['index']} 채굴 완료! 논스: {new_block['nonce']}, 해시: {new_block['hash'][:20]}...")

print(f"\n체인 길이: {len(blockchain)}블록")

print("\n" + "=" * 60)
print("2단계: 반감기 일정표 (3번 수업 - Google Sheets에 붙여넣기)")
print("=" * 60 + "\n")
generate_halving_table()

print("\n" + "=" * 60)
print("3단계: 발행량 곡선 시각화 (텍스트 차트)")
print("=" * 60 + "\n")

# 간단한 텍스트 기반 발행량 곡선
reward = 50
total = 0
for i in range(15):
    total += reward * 210_000
    pct = total / 21_000_000 * 100
    bar = "█" * int(pct / 2)
    print(f"{2009+i*4:>5}년 | {bar} {pct:.1f}%")
    reward /= 2
# Output:
============================================================
1단계: 미니 블록체인 생성 (2번 수업 복습)
============================================================
블록 #1 채굴 완료! 논스: 142, 해시: 0087a3f1b2c4d5e6f7...
블록 #2 채굴 완료! 논스: 89, 해시: 00a1b2c3d4e5f6a7b8...
블록 #3 채굴 완료! 논스: 311, 해시: 005c6d7e8f9a0b1c2d...

체인 길이: 4블록

============================================================
2단계: 반감기 일정표 (3번 수업 - Google Sheets에 붙여넣기)
============================================================

반감기,블록높이,연도(약),블록보상(BTC),기간발행량(BTC),누적발행량(BTC),총공급비율(%)
0,0,2009,50,10500000.00,10500000.00,50.0000
1,210000,2013,25,5250000.00,15750000.00,75.0000
2,420000,2017,12.5,2625000.00,18375000.00,87.5000
3,630000,2021,6.25,1312500.00,19687500.00,93.7500
4,840000,2025,3.125,656250.00,20343750.00,96.8750
...

============================================================
3단계: 발행량 곡선 시각화 (텍스트 차트)
============================================================

 2009년 | █████████████████████████ 50.0%
 2013년 | █████████████████████████████████████ 75.0%
 2017년 | ███████████████████████████████████████████ 87.5%
 2021년 | ██████████████████████████████████████████████ 93.8%
 2025년 | ████████████████████████████████████████████████ 96.9%
 ...

Google Sheets 활용법:

  1. CSV 출력 부분을 복사하여 Google Sheets의 '채굴 경제학' 탭에 붙여넣기
  2. 데이터 → 텍스트를 열로 분할 → 구분 기호: 쉼표
  3. '누적발행량' 열을 선택하여 꺾은선 차트 생성
  4. 로그 곡선 형태의 발행량 곡선 완성

지금까지 만든 프로젝트를 직접 실행해보자 — 2번 수업의 미니 블록체인과 3번 수업의 반감기 경제학 데이터가 하나의 스크립트에서 통합 실행된다.


Numbers That Matter: 핵심 수치 정리

지표수치의미
블록 생성 시간~10분난이도 조절의 목표
난이도 조절 주기2,016블록 (~2주)안정적 표본 크기 확보
반감기 주기210,000블록 (~4년)공급량 감소 스케줄
총 공급량21,000,000 BTC절대 초과 불가능한 상한
현재 발행률96.88% (2024년 4차 반감기 후)나머지 ~3%가 2140년까지
51% 공격 비용~$100억+ (장비)물리적 비용이 보안의 기반
6컨펌 안전도51% 공격자도 ~14% 성공률실용적으로 안전한 기준

Actionable Takeaways: 내일 당장 할 수 있는 3가지

1. 멤풀(Mempool.space) 사이트에서 실시간 채굴 현황을 관찰하라 다음 수업(5번)에서 본격적으로 다루겠지만, 지금부터 mempool.space에 들어가서 "실시간으로 블록이 10분마다 생성되는 것"을 눈으로 확인하라. 이론이 현실이 되는 순간이다.

2. 다음 난이도 조절까지 남은 블록 수를 추적하라 mempool.space 메인 화면에 다음 난이도 조절까지의 예상 변동률이 표시된다. 이걸 2주간 관찰하면, 오늘 배운 내용이 실시간으로 작동하는 걸 체감할 수 있다.

3. 프로젝트 코드를 직접 수정해보라 난이도(difficulty)를 3, 4, 5로 바꿔보고, 논스가 기하급수적으로 커지는 걸 직접 확인하라. "0 하나가 추가될 때마다 16배"라는 말이 코드 실행 결과로 체감되는 순간, 이 수업의 핵심을 잡은 것이다.


정리 다이어그램

다음 수업 예고: 4번 수업에서는 블록 안에 들어가는 트랜잭션을 해부한다. "지갑 주소"가 실제로 무엇인지, 공개키 암호학이 어떻게 소유권을 증명하는지, 그리고 비트코인 특유의 UTXO 모델 — 잔돈 시스템이 왜 필요한지를 다룬다.


🟢 쉬웠다면

핵심 3줄 요약:

  1. 작업증명 = 목표 해시를 찾기 위해 논스를 바꾸며 SHA-256을 반복하는 연산 복권
  2. 난이도 조절 = 2,016블록마다 10분 목표를 유지하도록 자동 보정
  3. 반감기 = 21만 블록마다 보상 반감, 2140년 발행 종료, 총 2,100만 BTC 상한

다음 수업에서는 트랜잭션의 내부 구조를 파헤칩니다. UTXO가 뭔지, 왜 비트코인에는 "잔액"이란 개념이 없는지 알게 됩니다.

🟡 어려웠다면

복권에 비유해보자.

  • 채굴 = 복권을 계속 사는 것. 당첨번호(목표 해시)를 미리 알 수 없으니 하나씩 긁어본다.
  • 난이도 = 당첨 조건의 까다로움. "첫 자리가 0이면 당첨"은 쉽고, "첫 네 자리가 0000이면 당첨"은 어렵다.
  • 난이도 조절 = 복권 판매소 사장이 "최근 2주간 당첨자가 너무 많았네? 다음 2주는 조건을 까다롭게 하자"라고 바꾸는 것. 비트코인에서는 이게 코드로 자동 실행된다.
  • 반감기 = 당첨금이 4년마다 반으로 줄어드는 것. 50만 원 → 25만 원 → 12.5만 원...

추가 연습: 위의 mine_block 함수에서 target_prefix를 "00000"(0이 5개)로 바꿔 실행해보세요. 시간이 얼마나 걸리는지 직접 체감해보는 게 가장 좋은 학습입니다.

🔴 도전 과제

면접 수준 질문: "비트코인의 난이도 조절이 1블록마다가 아닌 2,016블록마다인 이유를 설명하시오. 또한, 만약 타임스탬프를 조작할 수 있다면 난이도 조절 알고리즘을 어떻게 악용할 수 있는가?"

힌트:

  • 통계적 안정성 (표본 크기)
  • 타임스탬프 조작 → 실제 소요 시간을 길게 보이게 → 난이도 하락 유도
  • 비트코인은 이를 방지하기 위해 타임스탬프에 대한 검증 규칙이 있다 (이전 11개 블록의 중간값보다 커야 하며, 네트워크 시간 +2시간 이내여야 함)

프로덕션 수준 문제: 셀피시 마이닝(Selfish Mining) 공격을 조사해보세요. 33%의 해시레이트만으로도 정직한 채굴보다 높은 수익을 올릴 수 있다는 2013년 Cornell 논문(Eyal & Sirer)의 핵심 논리를 정리하고, 이를 시뮬레이션하는 Python 코드를 작성해보세요.

코드 실습

Python아래 코드는 비트코인 채굴의 핵심 루프를 가장 단순한 형태로 재현한다. 논스를 0부터 1씩 올려가며 SHA-256을 돌리고, 해시값이 목표 조건(앞자리 0의 개수)을 충족하면 "블록 발견"이다. 실행해보면 난이도가 올라갈수록 논스가 기하급수적으로 커지는 걸 직접 확인할 수 있다.
Python그렇다면 0의 개수와 시도 횟수 사이에는 정확히 어떤 관계가 있을까? 아래 코드로 0이 1개일 때부터 6개일 때까지 시도 횟수와 소요 시간을 측정해본다.
Python이 흐름에서 가장 주목할 지점은 5단계와 7단계의 **비대칭성**이다. **채굴은 어렵지만 검증은 쉽다.** 채굴자가 수십억 번 해시를 계산해서 정답을 찾았어도, 다른 노드는 **딱 한 번** 해시를 계산하면 맞는지 틀리는지 알 수 있다. 아래 코드로 이 비대칭성을 직접 확인해보자.
Python아래 코드로 이 공식을 시뮬레이션한다. 네 가지 시나리오 — 정상, 빠름, 느림, 극단적으로 빠른 경우 — 에서 난이도가 어떻게 조절되는지 확인해보자.
Python아래 코드는 반감기가 반복될 때마다 보상이 어떻게 줄고, 누적 발행량이 2,100만 BTC에 수렴하는지를 보여준다.
Python아래 시뮬레이션은 공격자의 해시레이트 비율과 되돌리려는 블록 수에 따라 공격 성공 확률이 어떻게 변하는지 보여준다. 특히 "왜 6컨펌이 안전한가"를 수치로 확인할 수 있다.
Python이전 수업까지 만든 코드(Python으로 미니 블록체인)에 이어서, 이번엔 **반감기 경제학 데이터를 생성하는 스크립트**를 추가한다. 아래 코드는 세 단계로 구성된다: 2번 수업의 미니 블록체인 복습, 반감기 CSV 데이터 생성, 텍스트 기반 발행량 곡선 시각화.

질문 & 토론