비트코인 트랜잭션의 내부 구조를 분해하여 읽는 방법을 배운다. version, inputs, outputs, locktime 필드를 하나씩 해석하고, 수수료 계산법과 컨펌의 의미를 이해한 뒤, txid.uk에서 실제 트랜잭션을 직접 조회하며 실습한다.
import Mermaid from '@components/shortcodes/Mermaid.astro'; import InfoBox from '@components/shortcodes/InfoBox.astro'; import CompareTable from '@components/shortcodes/CompareTable.astro'; import ChartBar from '@components/shortcodes/ChartBar.astro'; import ChartLine from '@components/shortcodes/ChartLine.astro'; import KidsQuiz from '@components/shortcodes/KidsQuiz.astro'; import KidsStory from '@components/shortcodes/KidsStory.astro'; import KidsCert from '@components/shortcodes/KidsCert.astro';
비트코인 블록체인은 트랜잭션의 연속이다. 블록은 트랜잭션을 담는 그릇이고, 주소는 트랜잭션의 입출력에 등장하는 식별자일 뿐이다. 트랜잭션 하나를 읽을 줄 알면 비트코인의 작동 원리 대부분을 이해한 셈이다. 이 글에서는 트랜잭션의 내부 구조를 분해하고, 각 필드의 의미를 하나씩 짚어본다.
0.5 BTC<br/>(서명 포함)"] I2["UTXO #2<br/>0.3 BTC<br/>(서명 포함)"] end subgraph 트랜잭션 TX["비트코인<br/>트랜잭션"] end subgraph 출력 O1["수신 주소<br/>0.7 BTC"] O2["잔돈 주소<br/>0.0999 BTC"] end I1 --> TX I2 --> TX TX --> O1 TX --> O2 FEE["수수료: 0.0001 BTC<br/>(입력 합 - 출력 합)"] TX -.-> FEE style TX fill:#f7931a,stroke:#f7931a,color:#000 style FEE fill:none,stroke:none,color:#8b949e`} />
비트코인 트랜잭션은 네 가지 핵심 필드로 구성된다.
| 필드 | 설명 |
|---|---|
| version | 트랜잭션 형식 버전. 현재 대부분 1 또는 2 |
| inputs | 소비할 이전 출력(UTXO)의 목록 |
| outputs | 새로 생성할 출력(잠금 스크립트 + 금액)의 목록 |
| locktime | 트랜잭션이 유효해지는 최소 블록 높이 또는 시간 |
Raw 트랜잭션 데이터를 간략히 표현하면 다음과 같다.
{
"version": 2,
"inputs": [ ... ],
"outputs": [ ... ],
"locktime": 0
}
version은 트랜잭션이 따르는 규칙 집합을 나타낸다. version 2는 BIP 68(상대적 시간 잠금)을 지원한다. locktime이 0이면 즉시 유효하며, 특정 블록 높이를 지정하면 그 블록 이후에만 포함될 수 있다. 핵심은 inputs와 outputs다. 이 두 필드가 "누가 누구에게 얼마를 보냈는가"를 담고 있다.
입력은 "어디서 비트코인을 가져오는가"를 명시한다. 각 입력은 이전 트랜잭션의 특정 출력을 참조하여 소비한다.
입력 하나의 구조는 다음과 같다.
{
"txid": "a1b2c3d4...이전 트랜잭션 ID",
"vout": 0,
"scriptSig": "서명 데이터(레거시)",
"witness": ["서명 데이터(SegWit)"],
"sequence": 4294967295
}
각 필드의 의미를 정리한다.
| 필드 | 설명 |
|---|---|
| txid | 소비할 UTXO가 생성된 이전 트랜잭션의 ID(해시) |
| vout | 이전 트랜잭션에서 몇 번째 출력인지 나타내는 인덱스. 0부터 시작 |
| scriptSig | 레거시 트랜잭션에서 서명과 공개키를 담는 해제 스크립트 |
| witness | SegWit 트랜잭션에서 서명 데이터를 담는 영역. scriptSig 대신 사용 |
| sequence | 기본값 0xFFFFFFFF. RBF(Replace-By-Fee) 또는 상대적 시간 잠금에 활용 |
핵심 원리는 간단하다. "이전 트랜잭션 txid의 vout번째 출력을 소비하겠다"는 선언이다. 그리고 scriptSig 또는 witness로 "내가 이 출력을 소비할 권한이 있다"는 것을 증명한다.
sequence 값이 0xFFFFFFFE 이하이면 RBF가 활성화된 상태로, 더 높은 수수료를 제시하여 미확인 트랜잭션을 대체할 수 있다.
출력은 "비트코인을 어디로 보내는가"를 정의한다. 각 출력은 금액과 잠금 스크립트로 구성된다.
{
"value": 0.01500000,
"scriptPubKey": {
"type": "witness_v0_keyhash",
"address": "bc1q..."
}
}
| 필드 | 설명 |
|---|---|
| value | 비트코인 금액 (BTC 단위, 내부적으로는 satoshi 정수) |
| scriptPubKey | 잠금 스크립트. 특정 조건을 충족해야만 이 출력을 소비할 수 있다 |
scriptPubKey의 유형은 주소 형식에 따라 달라진다.
| 주소 유형 | 접두사 | 스크립트 유형 | 설명 |
|---|---|---|---|
| P2PKH | 1... | pubkeyhash | 레거시. 공개키 해시에 잠금 |
| P2SH | 3... | scripthash | 스크립트 해시에 잠금. 멀티시그 등에 사용 |
| P2WPKH | bc1q... | witness_v0_keyhash | SegWit. 크기 효율적 |
| P2TR | bc1p... | witness_v1_taproot | Taproot. 프라이버시와 효율 개선 |
일반적인 송금 트랜잭션에서는 출력이 두 개 이상이다. 하나는 수신자 주소, 나머지는 발신자의 잔돈(change) 주소다. 입력 UTXO는 부분적으로 소비할 수 없으므로, 남는 금액을 자신에게 돌려보내야 한다.
비트코인 트랜잭션에는 수수료를 명시하는 필드가 없다. 수수료는 암묵적으로 계산된다.
수수료 = 입력 합계 - 출력 합계
예를 들어 입력이 0.05 BTC이고, 출력 합계가 0.0499 BTC라면 수수료는 0.0001 BTC(10,000 sat)다. 차이가 0이 아닌 이상 그 차이는 전부 채굴자의 수입이 된다.
이 구조는 실수에 취약하다. 잔돈 출력을 빼먹으면 차액 전부가 수수료로 지불된다. 2016년에는 한 사용자가 291 BTC(당시 약 1억 원 이상)를 수수료로 실수 지불한 사례가 있다. 현대의 지갑 소프트웨어는 이런 실수를 방지하는 경고 기능을 갖추고 있다.
수수료율(sat/vbyte)과 트랜잭션 크기의 관계는 수수료 계산 실전 가이드에서 상세히 다룬다.
트랜잭션이 네트워크에 전파되면 멤풀(mempool)에 들어간다. 채굴자가 해당 트랜잭션을 블록에 포함시키면 1컨펌이다. 이후 새 블록이 추가될 때마다 컨펌 수가 1씩 늘어난다.
| 컨펌 수 | 상태 | 소요 시간(평균) |
|---|---|---|
| 0 | 미확인(mempool 대기) | - |
| 1 | 블록에 포함됨 | 약 10분 |
| 3 | 소액 거래에 일반적으로 충분 | 약 30분 |
| 6 | 관행적으로 "최종 확정"으로 간주 | 약 1시간 |
6컨펌 관행은 사토시 나카모토의 백서에서 유래한다. 공격자가 블록을 되돌릴 확률은 컨펌 수가 늘어날수록 기하급수적으로 감소하며, 6컨펌 시점에서 사실상 0에 수렴한다. 대부분의 거래소가 입금 시 6컨펌을 요구하는 이유다. 고액 거래에서는 더 많은 컨펌을 기다리기도 한다.
실제 트랜잭션을 직접 조회하며 위에서 배운 내용을 적용해본다. 비트코인 역사상 유명한 "피자 트랜잭션"의 TXID를 사용한다.
a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d
이 트랜잭션은 2010년 5월 22일, 프로그래머 Laszlo Hanyecz가 피자 두 판 대가로 10,000 BTC를 보낸 것으로, 비트코인이 실물과 교환된 최초의 사례다.
조회 순서:
모든 트랜잭션이 일반적인 송금은 아니다. 몇 가지 특수한 유형을 알아둔다.
각 블록의 첫 번째 트랜잭션은 코인베이스 트랜잭션(coinbase transaction)이다. 이전 UTXO를 참조하지 않고, 블록 보상(신규 발행 + 수수료)을 채굴자 주소로 생성한다.
코인베이스 트랜잭션의 특징:
0000...0000)여러 개의 개인키 중 일정 수 이상의 서명이 있어야 소비 가능한 출력이다. "2-of-3 멀티시그"라면 3개 키 중 2개의 서명이 필요하다. 기업 자금 관리나 공동 계좌에 사용된다. P2SH(3으로 시작하는 주소)로 구현되는 경우가 많다.
출력의 스크립트에 OP_RETURN이 포함되면, 해당 출력은 소비 불가능하다. 대신 최대 80바이트의 임의 데이터를 블록체인에 영구히 기록할 수 있다.
OP_RETURN 48656c6c6f20426974636f696e
위 예시는 "Hello Bitcoin"이라는 문자열을 16진수로 인코딩한 것이다. 타임스탬프 증명, 디지털 자산 발행 프로토콜(Omni Layer 등) 등에 활용된다. OP_RETURN 출력의 value는 항상 0이다.
비트코인 트랜잭션은 version, inputs, outputs, locktime 네 가지 핵심 필드로 구성된다. 입력은 이전 UTXO를 참조하여 소비하고, 출력은 새로운 UTXO를 생성한다. 수수료는 입력 합계에서 출력 합계를 뺀 차이이며, 별도 필드가 없다. 컨펌은 트랜잭션이 포함된 블록 이후 추가된 블록 수로, 6컨펌이면 사실상 최종 확정으로 간주된다. 이 구조를 이해하면 블록체인 탐색기에서 어떤 트랜잭션이든 읽고 해석할 수 있다.
관련 글: