결론부터 말하면, 비트코인 난이도 조정 주기는 2주가 아니라 블록 2,016개예요. 2주는 규칙이 아니라 블록이 예정대로 나왔을 때 나오는 결과일 뿐이에요. 그래서 실제 간격은 매번 달라져요.
완결된 최근 10에폭, 그러니까 블록 20,160개를 경계 타임스탬프로 직접 재 봤어요. 평균은 에폭당 14.09일이었고, 짧은 에폭은 13.07일, 긴 에폭은 15.58일이었어요. 그 둘은 서로 이어진 에폭이라, 같은 규칙 아래서 한 달이 채 안 되는 사이에 2.5일이 벌어진 거예요.
그리고 한 자리가 더 있어요. 조정이 시간을 재는 창은 블록 2,016개인데, 그 안에 든 간격은 2,015개예요. 이 하나 차이 때문에 조정이 실제로 겨냥하는 값은 600초가 아니라 600.2978초예요. 이 글은 그 자리를 비트코인 코어 원문과 블록 타임스탬프로 재현해서 확인해요.
이 글이 다루는 것은 시계 쪽 하나예요. 해시레이트 지표를 읽는 법이나 장비·전력 쪽 이야기는 다루지 않아요. 에폭이 실제로 며칠 걸렸는지, 계산 창이 몇 개인지, 다음 조정이 언제로 추정되는지까지만 봐요.
![]()
난이도 조정은 2016블록마다예요 — 2주는 규칙이 아니라 결과예요
프로토콜이 세는 것은 시간이 아니라 블록이에요. 블록 높이가 2,016의 배수가 되는 자리에서만 난이도가 바뀌고, 그 사이에는 무슨 일이 있어도 그대로예요.
이 성질은 블록 데이터에서 눈으로 확인돼요. 난이도는 블록 헤더의 bits 필드에 압축된 형태로 실려 있는데, 조정 지점 앞뒤를 나란히 놓으면 이렇게 갈려요.
| 높이 | bits | 난이도 |
|---|---|---|
| 959615 | 386021021 | 127,170,500,429,035.19 |
| 959616 | 386022100 | 126,231,507,121,868.19 |
| 961631 | 386022100 | 126,231,507,121,868.19 |
| 961632 | 386020669 | 127,479,855,693,691.4 |
959615와 959616 사이에서 값이 바뀌고, 그 뒤로 961631까지 2,016블록 내내 같은 값이 유지돼요. 그리고 961632에서 다시 바뀌어요. 조정 지점이 아닌 높이에서 bits 가 달라지면 그 블록 자체가 규칙 위반이에요.
그러면 왜 다들 2주라고 말할까요. 블록 2,016개가 정확히 10분씩 나오면 20,160분, 그러니까 14일이 되거든요. 비트코인 코어 소스의 해당 줄에도 주석이 그렇게 달려 있어요. 문제는 블록이 10분씩 나오지 않는다는 거예요. 채굴에 투입된 연산력이 늘면 빨라지고 줄면 느려지는데, 난이도는 그 변화를 뒤늦게 따라가요.
즉 순서가 이래요. 먼저 블록 2,016개가 나오고, 그게 며칠 걸렸는지를 보고, 그다음에 난이도를 고쳐요. 2주는 목표값이지 관측값이 아니에요. 해시레이트와 난이도가 서로를 따라다니는 구조 자체는 해시레이트와 채굴 난이도 읽는 법에 정리해 두었어요. 이 글은 그 뒤에 남는 시간 문제만 파고들어요.
참고로 블록 개수로 일정을 정하는 방식은 비트코인에서 한 군데가 더 있어요. 발행량이 절반으로 줄어드는 지점도 시간이 아니라 블록 210,000개마다예요. 그쪽은 반감기와 블록 보상 구조에서 따로 다뤘어요. 두 일정이 다 블록 세기라서, "4년마다"와 "2주마다"라는 표현이 같은 이유로 어긋나요.
비트코인 코어 원문에서 확인한 두 상수 — 1,209,600초와 600초
값의 출처를 3자 설명이 아니라 소스에서 직접 받아 왔어요. 2026년 8월 19일 오전에 내려받은 파일이에요.
https://raw.githubusercontent.com/bitcoin/bitcoin/master/src/kernel/chainparams.cpp
34,649바이트짜리 이 파일의 메인넷 설정 블록에 두 줄이 나란히 있어요.
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
앞 줄이 1,209,600초이고 뒷 줄이 600초예요. 그런데 여기서 조심할 자리가 하나 있어요. 이 이름의 줄은 같은 파일에 다섯 곳 있어요. 클래스 선언 줄 번호로 소속을 확인했어요.
| 줄 | 소속 | 값 |
|---|---|---|
| 127 | CMainParams (메인넷) | 14 * 24 * 60 * 60 |
| 251 | CTestNetParams | 14 * 24 * 60 * 60 |
| 351 | CTestNet4Params | 14 * 24 * 60 * 60 |
| 495 | SigNetParams | 14 * 24 * 60 * 60 |
| 580 | CRegTestParams | 24 * 60 * 60 (하루) |
네 곳이 14일이고 로컬 시험망인 regtest 만 하루예요. 이 글에서 인용하는 값은 전부 127번째 줄, 그러니까 메인넷 값이에요.
이제 2,016이라는 숫자가 어디서 나오는지 볼 차례예요. 흔히 소스에 박힌 상수라고 생각하기 쉬운데 그렇지 않아요. 다른 파일에 계산식으로 들어 있어요.
https://raw.githubusercontent.com/bitcoin/bitcoin/master/src/consensus/params.h
6,262바이트짜리 이 파일의 130번째 줄이에요.
int64_t DifficultyAdjustmentInterval() const
이 함수의 본문은 딱 한 줄이에요. return nPowTargetTimespan / nPowTargetSpacing; 이 전부예요. 1,209,600을 600으로 나누면 2,016이에요. 그러니까 2,016은 독립된 규칙이 아니라 두 상수의 몫이에요. 목표 기간을 바꾸든 목표 간격을 바꾸든 이 값이 따라 움직여요.
같은 메인넷 블록에서 함께 읽어 둘 값이 세 개 더 있어요. 뒤에서 계산할 때 어느 분기를 타는지가 여기서 갈려요.
| 항목 | 메인넷 값 | 뜻 |
|---|---|---|
fPowAllowMinDifficultyBlocks | false | 최소 난이도 예외 없음 |
enforce_BIP94 | false | testnet4 전용 분기를 타지 않음 |
fPowNoRetargeting | false | 재조정을 실제로 수행 |
같은 파일의 testnet4 블록(351번째 줄 아래)에서는 앞의 두 값이 전부 true 예요. 그래서 시험망 기준으로 설명된 글을 메인넷에 그대로 옮기면 어긋나요. 이 글의 계산은 전부 메인넷 분기예요.
투자 정보 안내
본 글은 암호화폐 시장에 대한 객관 데이터·정보 제공 목적이며, 특정 코인 매수·매도 권유가 아닙니다. 암호화폐는 변동성이 매우 크고 원금 전액 손실이 가능하므로 본인 판단과 책임 하에 결정하세요.
계산 창은 블록 2016개인데 시간 간격은 2015개예요
여기가 이 글의 중심이에요. 조정이 "직전 2주가 얼마나 걸렸는지"를 잴 때, 정확히 어디서 어디까지를 재는지 원문으로 보면 이래요.
https://raw.githubusercontent.com/bitcoin/bitcoin/master/src/pow.cpp
6,549바이트짜리 이 파일의 GetNextWorkRequired 안에 이 세 줄이 있어요.
// Go back by what we want to be 14 days worth of blocks
int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
pindexLast 는 새 에폭이 시작되기 직전 블록이에요. 다음 블록 높이가 2,016의 배수일 때만 이 지점에 들어오니까, 새 에폭 시작 높이를 H라고 하면 pindexLast 는 H 빼기 1이에요. 여기서 2,016 빼기 1, 그러니까 2,015를 더 빼면 시작점은 H 빼기 2,016이에요.
정리하면 이래요.
| 항목 | 값 |
|---|---|
| 창의 첫 블록 | H 빼기 2,016 (직전 에폭의 첫 블록) |
| 창의 마지막 블록 | H 빼기 1 (직전 에폭의 마지막 블록) |
| 창에 든 블록 수 | 2,016개 |
| 창에 든 시간 간격 수 | 2,015개 |
블록이 2,016개면 그 사이 간격은 2,015개예요. 울타리 기둥 2,016개 사이에 널빤지가 2,015장 들어가는 것과 같아요. 그런데 이 2,015개 간격의 합을 1,209,600초와 비교해요. 그래서 조정이 실제로 겨냥하는 블록 간격은 이렇게 나와요.
| 계산 | 결과 |
|---|---|
| 1,209,600 나누기 2,016 | 600.0000초 |
| 1,209,600 나누기 2,015 | 600.2978초 |
흔히 말하는 10분은 앞쪽 값이고, 조정이 실제로 목표로 삼는 값은 뒤쪽이에요. 차이는 블록당 0.2978초예요. 작아 보이지만 블록이 쌓이면 이렇게 돼요.
| 항목 | 계산 | 결과 |
|---|---|---|
| 에폭 하나(간격 2,016개)를 600.2978초 페이스로 | 2,016 곱하기 600.2978 | 1,210,200.30초 |
| 14일과의 차이 | 1,210,200.30 빼기 1,209,600 | 600.30초 = 약 10.0분 |
| 1년에 도는 에폭 수 | 365.25일 나누기 14.006948일 | 약 26.08개 |
| 1년 누적 | 26.08 곱하기 600.30초 | 약 4.35시간 |
에폭마다 딱 블록 하나치, 그러니까 약 10분씩 늦어져요. 1년이면 4시간이 조금 넘어요. 이 어긋남은 버그로 알려져 있지만 고치면 체인이 갈라지기 때문에 그대로 두고 있어요.
창을 2,016간격으로 잡으면 계산이 전부 틀려요
말로만 하면 믿기 어려우니 반증으로 확인했어요. 같은 계산을 두 번 돌렸어요. 한 번은 원문대로 간격 2,015개, 한 번은 흔한 오해대로 간격 2,016개로요. 결과는 다음 절에서 표로 나오는데, 미리 요약하면 이래요.
| 창 잡는 법 | 예측한 다음 bits 가 실제와 맞은 횟수 |
|---|---|
| 간격 2,015개 (H 빼기 1에서 H 빼기 2,016까지) | 10에폭 중 10회 |
| 간격 2,016개 (H에서 H 빼기 2,016까지) | 10에폭 중 0회 |
한 블록 차이가 열 번 다 결과를 바꿨어요. 이 자리는 반올림 오차 수준이 아니라 값 자체가 갈리는 자리예요.
블록 20,160개 실측 — 10에폭 평균 14.09일과 에폭별 편차
이제 실제로 며칠 걸렸는지 재 볼게요. 표본은 완결된 에폭 10개, 블록 941472부터 961631까지 20,160개예요. 진행 중인 에폭은 아직 결과가 안 나왔으니 표본에서 뺐어요.
경계 블록 11개의 타임스탬프를 개별 조회해서 받았어요. 조회는 공개 API 두 단계로 했어요. 높이로 해시를 받고, 해시로 블록을 받는 방식이에요.
| 높이 | 유닉스 시각 | 한국 시각 |
|---|---|---|
| 941472 | 1774043659 | 2026-03-21 06:54:19 |
| 943488 | 1775208520 | 2026-04-03 18:28:40 |
| 945504 | 1776448537 | 2026-04-18 02:55:37 |
| 947520 | 1777687605 | 2026-05-02 11:06:45 |
| 949536 | 1778860884 | 2026-05-16 01:01:24 |
| 951552 | 1780050586 | 2026-05-29 19:29:46 |
| 953568 | 1781396637 | 2026-06-14 09:23:57 |
| 955584 | 1782525607 | 2026-06-27 11:00:07 |
| 957600 | 1783800551 | 2026-07-12 05:09:11 |
| 959616 | 1785019866 | 2026-07-26 07:51:06 |
| 961632 | 1786217755 | 2026-08-09 04:35:55 |
전체 벽시계는 1786217755 빼기 1774043659, 그러니까 12,174,096초예요. 그 사이 간격은 20,160개예요.
| 항목 | 계산 | 결과 |
|---|---|---|
| 총 경과 | 1786217755 빼기 1774043659 | 12,174,096초 |
| 간격 수 | 961632 빼기 941472 | 20,160개 |
| 블록당 평균 | 12,174,096 나누기 20,160 | 603.8738초 |
| 에폭당 평균 | 12,174,096 나누기 10 | 1,217,409.6초 |
| 일로 환산 | 1,217,409.6 나누기 86,400 | 14.0904일 |
평균은 14.09일이에요. 그런데 평균만 보면 놓치는 게 있어요. 에폭별로 갈라 보면 이래요.
| 에폭 | 구간 | 경과(초) | 일 | 블록당(초) |
|---|---|---|---|---|
| 1 | 941472에서 943488 | 1,164,861 | 13.4822 | 577.81 |
| 2 | 943488에서 945504 | 1,240,017 | 14.3521 | 615.09 |
| 3 | 945504에서 947520 | 1,239,068 | 14.3411 | 614.62 |
| 4 | 947520에서 949536 | 1,173,279 | 13.5796 | 581.98 |
| 5 | 949536에서 951552 | 1,189,702 | 13.7697 | 590.13 |
| 6 | 951552에서 953568 | 1,346,051 | 15.5793 | 667.68 |
| 7 | 953568에서 955584 | 1,128,970 | 13.0668 | 560.01 |
| 8 | 955584에서 957600 | 1,274,944 | 14.7563 | 632.41 |
| 9 | 957600에서 959616 | 1,219,315 | 14.1124 | 604.82 |
| 10 | 959616에서 961632 | 1,197,889 | 13.8645 | 594.19 |
가장 짧은 에폭은 13.07일, 가장 긴 에폭은 15.58일이에요. 차이가 2.51일이에요. 그리고 재미있는 자리가 6번과 7번이에요. 15.58일짜리 바로 다음이 13.07일짜리예요. 긴 에폭이 끝나면 난이도가 내려가고, 그러면 다음 에폭이 짧아져요. 이 되먹임이 눈에 보이는 자리예요.
10에폭 평균 14.09일은 조정이 겨냥하는 14.007일보다 조금 길어요. 차이는 에폭당 7,209초, 그러니까 약 2시간이에요. 이건 앞 절의 오프바이원 때문이 아니라 이 구간에 실제로 블록이 목표보다 느리게 나왔기 때문이에요.
표본을 더 넓히면 값이 조금 달라져요. 같은 방식으로 완결 에폭 25개, 블록 50,400개를 재면 이래요.
| 표본 | 블록 수 | 총 경과(초) | 블록당(초) | 에폭당(일) |
|---|---|---|---|---|
| 최근 10에폭 (941472에서 961632) | 20,160 | 12,174,096 | 603.8738 | 14.0904 |
| 최근 25에폭 (911232에서 961632) | 50,400 | 30,322,077 | 601.6285 | 14.0380 |
표본이 길어질수록 목표값 쪽으로 수렴해요. 그러니 "비트코인 난이도 조정 주기는 며칠인가"라는 질문의 답은 어느 구간을 재느냐에 따라 13일대에서 15일대까지 갈린다가 정확해요. 하나의 숫자를 외우는 것보다 이 폭을 아는 편이 나아요.
이 폭이 일정에 얼마나 쌓이나
에폭 하나만 보면 며칠 차이가 별것 아닌 것처럼 보여요. 그런데 조정을 달력에 미리 찍어 두는 사람 입장에서는 이 차이가 어디까지 벌어지는지가 문제예요. 2주씩 세는 달력과 실제 사이가 얼마나 벌어졌는지 계산해 봤어요.
| 표본 | 달력 기준(2주씩) | 실제 경과 | 밀린 시간 |
|---|---|---|---|
| 10에폭 | 12,096,000초 | 12,174,096초 | 78,096초 = 약 21.7시간 |
| 25에폭 | 30,240,000초 | 30,322,077초 | 82,077초 = 약 22.8시간 |
10에폭은 달력으로 140일인데 실제로는 140.90일 걸렸어요. 25에폭은 350일 예정에 350.95일이었고요. 그런데 재는 기간이 두 배 반으로 늘어나는 동안 밀린 양은 21.7시간에서 22.8시간으로 1시간쯤만 늘었어요. 달력과의 이 차이는 시간에 비례해 쌓이는 게 아니라 에폭마다 더해지고 상쇄돼요. 그래서 "다음 조정은 8월 23일쯤"이라고 적어 둔 메모가 어긋나는 이유는 총량이 커져서가 아니라, 에폭 하나가 하루 넘게 흔들리기 때문이에요.
앞 절의 오프바이원과는 크기가 다르다는 점도 짚어 둘게요. 오프바이원 때문에 밀리는 양은 10에폭이면 6,003초, 그러니까 약 1.7시간이에요. 실제로 밀린 21.7시간 중 대부분은 그게 아니라 이 구간에 블록이 목표보다 느리게 나왔기 때문이에요. 조정이 겨냥하는 값(에폭당 1,210,200초)을 기준으로 다시 재면 10에폭에서 72,093초, 약 20.0시간이 밀렸어요.

실측 난이도 변화율이 코어 산식과 맞았어요 — 10에폭 전부 정수까지
앞의 표들이 맞는지 확인하는 가장 확실한 방법은, 그 타임스탬프만 가지고 다음 난이도를 직접 계산해서 실제 값과 대조하는 것이에요. 그래서 그렇게 했어요.
먼저 산식이에요. 같은 pow.cpp 의 CalculateNextWorkRequired 안에 있어요.
int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
bnNew.SetCompact(pindexLast->nBits);
bnNew *= nActualTimespan;
bnNew /= params.nPowTargetTimespan;
return bnNew.GetCompact();
말로 옮기면 이래요. 직전 난이도의 목표값에 실제 걸린 시간을 곱하고 1,209,600으로 나눠요. 실제가 오래 걸렸으면 목표값이 커지고, 목표값이 커진다는 건 난이도가 내려간다는 뜻이에요.
여기서 SetCompact 와 GetCompact 는 256비트 숫자를 4바이트로 줄여 담는 압축 표기예요. 이 압축 과정에서 아래 자리가 버려지기 때문에, 소수점 계산으로 어림하면 값이 안 맞아요. 그래서 이 두 함수를 원문 그대로 옮겨 구현하고 정수 연산으로 돌렸어요.
결과예요. 경계 블록 타임스탬프만 넣어서 나온 예측값과, 체인에 실제로 실린 값이에요.
| 조정 높이 | nActualTimespan | 예측 bits | 실제 bits | 일치 |
|---|---|---|---|---|
| 943488 | 1,164,574 | 386008708 | 386008708 | 일치 |
| 945504 | 1,239,689 | 386012009 | 386012009 | 일치 |
| 947520 | 1,238,117 | 386015216 | 386015216 | 일치 |
| 949536 | 1,172,986 | 386011001 | 386011001 | 일치 |
| 951552 | 1,189,160 | 386008719 | 386008719 | 일치 |
| 953568 | 1,345,374 | 386023619 | 386023619 | 일치 |
| 955584 | 1,128,849 | 386013762 | 386013762 | 일치 |
| 957600 | 1,273,330 | 386021021 | 386021021 | 일치 |
| 959616 | 1,218,603 | 386022100 | 386022100 | 일치 |
| 961632 | 1,197,762 | 386020669 | 386020669 | 일치 |
10에폭 전부 정수까지 똑같이 나왔어요. 그리고 위 nActualTimespan 은 전부 간격 2,015개짜리 값이에요. 앞 절에서 말한 반증도 여기서 나와요. 같은 코드에서 창만 간격 2,016개로 바꾸면 예측값이 386008741, 386012045처럼 조금씩 어긋나서 열 번 다 틀려요.
난이도 변화율로 옮기면 이래요. 위 예측 bits 에서 계산한 배수와, 조회한 조정 이력에 적힌 배수를 나란히 놓았어요.
| 조정 높이 | 계산한 배수 | 기록된 배수 |
|---|---|---|
| 943488 | 1.03866958 | 1.03867 |
| 945504 | 0.97573526 | 0.975735 |
| 947520 | 0.97696915 | 0.976969 |
| 949536 | 1.03121459 | 1.03121 |
| 951552 | 1.01719008 | 1.01719 |
| 953568 | 0.89908636 | 0.899086 |
| 955584 | 1.07153432 | 1.07153 |
| 957600 | 0.94995622 | 0.949956 |
| 959616 | 0.99261626 | 0.992616 |
| 961632 | 1.00988936 | 1.00989 |
기록 쪽은 유효숫자 여섯 자리로 반올림돼 있어서, 두 값의 차이는 전부 그 반올림 폭 안이에요. 가장 큰 차이가 0.0000046이었어요.
여기서 단위 문제 하나도 같이 풀렸어요. 조정 이력 배열의 값은 1.00989처럼 배수로 적혀 있는데, 현재 상태를 알려주는 응답의 previousRetarget 필드는 0.9889358055576736 이에요. 제가 계산한 배수 1.00988936에서 1을 빼고 100을 곱하면 0.988936이에요. 소수점 아래까지 그대로 맞아요. 그러니까 배열 쪽은 배수, 상태 응답 쪽은 퍼센트예요. 같은 조정을 두 단위로 적어 둔 거라, 섞어 읽으면 100배가 어긋나요.
한 가지 밝혀 둘 게 있어요. 이 대조는 비트코인 코어의 로그를 읽어서 한 것이 아니에요. 경계 블록의 타임스탬프와 bits 만 받아서 산식을 재현한 거예요. 재현이 실제 값과 열 번 다 맞았다는 것이 여기서 확인한 전부예요.
4배 한도는 언제 걸리나 — 1년치 조정 26건에서 한 번도 안 걸렸어요
같은 함수 안에 안전장치가 있어요. nActualTimespan 을 쓰기 전에 위아래로 자르는 부분이에요. 원문에서는 조건과 대입이 각각 다른 줄이고, 대입 줄은 조건 아래로 들여쓰기돼 있어요.
if (nActualTimespan < params.nPowTargetTimespan/4)
nActualTimespan = params.nPowTargetTimespan/4;
if (nActualTimespan > params.nPowTargetTimespan*4)
nActualTimespan = params.nPowTargetTimespan*4;
숫자를 넣으면 이렇게 돼요.
| 경계 | 초 | 일 | 그때 블록 2,015간격 평균 |
|---|---|---|---|
| 하한 (1,209,600 나누기 4) | 302,400 | 3.5일 | 150.07초 |
| 상한 (1,209,600 곱하기 4) | 4,838,400 | 56일 | 2,401.19초 = 약 40분 |
즉 난이도가 한 번에 4배 오르려면 직전 에폭이 3.5일 만에 끝나야 하고, 4분의 1로 떨어지려면 56일이 걸려야 해요. 블록 간격으로는 2.5분 또는 40분이에요.
이 한도는 계산 편의가 아니라 규칙이에요. 같은 파일의 PermittedDifficultyTransition 함수가 조정 지점마다 새 값이 이 범위 안인지 따로 검사해요. 주석도 그렇게 적혀 있어요.
// Check that on difficulty adjustments, the new difficulty does not increase
// or decrease beyond the permitted limits.
그럼 실제로 걸린 적이 있을까요. 최근 1년치 조정 이력 26건을 받아서 배수를 전부 확인했어요.
| 항목 | 값 |
|---|---|
| 조정 기록 수 | 26건 |
| 배수 최댓값 | 1.14725 (높이 937440, 2026-02-20) |
| 배수 최솟값 | 0.888447 (높이 935424, 2026-02-07) |
| 한도 도달 | 0건 |
클램프가 걸리면 배수가 정확히 4.0 또는 0.25로 찍혀요. 26건 어디에도 그런 값이 없어요. 배수로 역산한 실제 소요 시간도 1,054,347초에서 1,361,477초 사이라, 경계인 302,400초와 4,838,400초와는 자릿수가 달라요.
정리하면 4배 한도는 실무에서 만날 일이 거의 없는 장치예요. 다만 이 문장의 범위는 제가 조회한 최근 1년 26건 안에서라는 뜻이에요. 그 이전 기록까지 확인한 것은 아니에요.
투자 정보 안내
본 글은 암호화폐 시장에 대한 객관 데이터·정보 제공 목적이며, 특정 코인 매수·매도 권유가 아닙니다. 암호화폐는 변동성이 매우 크고 원금 전액 손실이 가능하므로 본인 판단과 책임 하에 결정하세요.
다음 조정 시각을 직접 확인하는 순서와 추정치가 흔들리는 폭
여기서부터는 진행 중인 값이라 시효가 있어요. 아래 숫자는 전부 2026년 8월 19일 오전 11시 34분(한국 시각) 에 조회한 것이고, 지금 다시 열면 다르게 나와요.
| 항목 | 값 |
|---|---|
| 현재 에폭 시작 높이 | 961632 (타임스탬프 1786217755, 2026-08-09 04:35:55) |
| 조회 시점 팁 높이 | 963117 (타임스탬프 1787106153, 2026-08-19 11:22:33) |
| 다음 조정 높이 | 963648 |
| 지나온 간격 | 1,485개 |
| 경과 시간 | 888,398초 |
| 지금까지 블록당 평균 | 598.2478초 |
| 진행률 | 1,485 나누기 2,016 = 73.66% |
| 남은 블록 | 531개 |
지금까지는 598.25초 페이스라 목표보다 조금 빨라요. 그래서 다음 조정에서 난이도는 소폭 오르는 쪽으로 추정돼요. 다만 여기서 "언제"를 정하려면 남은 531블록이 어떤 페이스로 나올지를 가정해야 하는데, 그 가정에 따라 답이 이만큼 벌어져요.
| 가정한 페이스 | 예상 시각(한국) |
|---|---|
| 이번 에폭 실측 598.2478초 | 2026-08-23 03:37 |
| 600초 | 2026-08-23 03:52 |
| 600.2978초(조정이 겨냥하는 값) | 2026-08-23 03:55 |
| 최근 10에폭 평균 603.874초 | 2026-08-23 04:26 |
가정 하나 바꿨을 뿐인데 약 50분이 벌어져요. 그러니 어느 사이트에서 본 "다음 조정까지 몇 시간" 표시는 그 사이트가 어떤 페이스를 가정했는지에 따라 달라지는 값이에요.
추정치는 블록이 안 나와도 계속 움직여요
같은 공개 API에 8분 사이 세 번 물어봤어요. 그 사이 새 블록은 하나도 나오지 않았고 팁 높이는 963117 그대로였어요. 그런데도 값이 이렇게 흘렀어요.
| 조회 시각(한국) | 다음 조정 폭 추정 | 예상 조정 시각 |
|---|---|---|
| 11:26:49 | 0.3316% | 2026-08-23 03:42 |
| 11:30:50 | 0.3044% | 2026-08-23 03:48 |
| 11:34:16 | 0.2812% | 2026-08-23 03:52 |
왜 그런지는 같은 응답의 다른 필드를 검산해 보면 드러나요. expectedBlocks 라는 필드가 있는데, 이 값을 제가 적어 둔 조회 시각으로 역산하면 이렇게 나와요.
| 회차 | 검산식 | 계산값 | 응답값 |
|---|---|---|---|
| 1회 | (1787106409 빼기 1786217755) 나누기 600 | 1481.0900 | 1481.0883 |
| 3회 | (1787106856 빼기 1786217755) 나누기 600 | 1481.8350 | 1481.8333 |
두 회차 다 계산값이 응답값보다 0.0017 큰데, 이건 1초를 600으로 나눈 값이에요. 제가 호출한 시각과 서버가 응답을 만든 시각이 1초 어긋난 것이지 산식이 다른 게 아니에요. 서버 쪽 경과 초로 되돌리면 1회차가 888,653초, 3회차가 889,100초예요.
즉 이 필드는 블록을 세는 게 아니라 벽시계를 600으로 나눈 값이에요. 시간이 흐르면 "지금쯤 나왔어야 할 블록 수"가 계속 늘어나니, 실제 블록이 안 나오는 동안에는 예상 상승폭이 계속 깎여요. 블록 하나가 나오는 순간 다시 튀어 올라요.
추정 상승폭 자체도 같은 응답 안에서 재구성돼요. 에폭 시작 블록의 시각부터 조회 시각까지 흐른 초를 에폭 시작 블록부터 팁 블록까지의 블록 개수로 나눠 지금까지 평균을 내고, 600을 그 평균으로 나눈 뒤 1을 빼서 100을 곱하면 돼요. 이번 에폭이라면 그 블록 개수가 1,486개예요.
| 조회 시각(한국) | 경과(초) | 나눈 블록 개수 | 계산한 상승폭 | 응답값 |
|---|---|---|---|---|
| 11:26:49 | 888,653 | 1,486 | 0.3316255% | 0.3316255% |
| 11:30:50 | 888,894 | 1,486 | 0.3044232% | 0.3044232% |
| 11:34:16 | 889,100 | 1,486 | 0.2811832% | 0.2811832% |
세 번 다 응답이 돌려준 자릿수 끝까지 같았어요(표에는 일곱 자리까지만 옮겼어요). 그런데 같은 응답의 timeAvg 는 같은 경과 초를 1,485, 그러니까 간격 수로 나눠요. 1회차로 확인하면 888,653 나누기 1,485 = 598.4195초이고 응답값은 598,419밀리초예요. 한 응답 안에서 분모가 1,485와 1,486으로 갈리는 거예요. 이 글이 내내 다룬 블록 2,016개 대 간격 2,015개와 같은 자리의 오프바이원이에요.
그래서 이런 추정치는 조회 시각을 같이 적어 두지 않으면 의미가 없어요. 이 글이 모든 진행 중 수치에 시각을 붙인 이유예요.
직접 확인하는 순서
가정을 남에게 맡기지 않고 직접 재려면 순서는 이래요. 공개 블록 조회 서비스 하나면 돼요.
| 순서 | 무엇을 | 어떻게 |
|---|---|---|
| 1 | 현재 블록 높이 | 블록 탐색기 첫 화면의 최신 블록 번호 |
| 2 | 다음 조정 높이 | 현재 높이를 2,016으로 나눠 내림한 뒤 1을 더하고 다시 2,016을 곱함 |
| 3 | 남은 블록 | 2번에서 1번을 뺌 |
| 4 | 이번 에폭 시작 블록의 시각 | 2번에서 2,016을 뺀 높이의 블록을 열어 타임스탬프 확인 |
| 5 | 지금까지 평균 | (현재 블록 시각 빼기 4번 시각) 나누기 (현재 높이 빼기 시작 높이) |
| 6 | 예상 시각 | 현재 블록 시각에 (남은 블록 곱하기 5번 평균)을 더함 |
2번에서 올림으로 계산하면 현재 높이가 마침 2,016의 배수인 순간에 답이 그 높이 자신이 되고, 3번의 남은 블록이 0으로 나와요. 그 높이에서는 조정이 이미 일어난 뒤라 다음 조정 높이는 2,016만큼 더 위예요. 내림한 뒤 1을 더하면 그 자리에서도 맞아요.
5번 나눗셈에서 분모를 틀리기 쉬워요. 블록 수가 아니라 간격 수를 써야 해요. 시작 블록과 현재 블록 사이에 블록이 1,486개 있으면 간격은 1,485개예요. 이 글의 계산도 전부 간격 기준이에요.
스스로 점검할 것
- 내가 본 "다음 조정까지 남은 시간"이 어떤 페이스 가정에서 나온 값인지 확인했다
- 그 수치에 조회 시각이 붙어 있는지 확인했다
- 평균을 낼 때 블록 수가 아니라 간격 수로 나눴다
- 난이도 배수(1.01719 같은 값)와 퍼센트(1.719 같은 값)를 섞어 읽지 않았다
- "2주"를 규칙이 아니라 목표값으로 이해했다
- 에폭 하나의 결과를 추세로 읽지 않았다(10에폭 안에서도 13.07일과 15.58일이 있었다)
블록이 예정된 시각에 안 나오는 문제는 송금할 때도 그대로 체감돼요. 그쪽 이야기, 그러니까 수수료를 얼마로 잡아야 다음 블록에 실리는지는 송금 수수료가 붙는 단위에 따로 정리해 두었어요.

이더리움과 비교하면 차이가 선명해져요
같은 "몇 초마다 블록"이라도 체인마다 구조가 달라요. 비트코인은 목표 간격만 정해 두고 실제 시각은 블록이 나오는 대로 흘러가요. 그래서 앞의 표처럼 에폭이 13일이 되기도 하고 15일이 되기도 해요.
반면 이더리움은 시각 자체를 12초 단위로 미리 끊어 두고, 그 칸 위에 블록이 실리는 구조예요. 그쪽은 블록 간격이 12초의 배수로만 찍혀요. 실제로 재 본 값과 그 구조는 이더리움 12초는 블록 간격이 아니라 슬롯 길이에 정리해 두었어요.
정리하면 이래요.
| 항목 | 비트코인 |
|---|---|
| 정해 둔 것 | 블록 2,016개마다 조정, 목표 1,209,600초 |
| 흘러가는 것 | 에폭이 실제로 며칠 걸리는지 |
| 실측 폭(10에폭) | 13.07일에서 15.58일 |
| 조정이 겨냥하는 블록 간격 | 600.2978초 |
오해와 원문을 한 표로
| 흔히 도는 말 | 원문과 실측 | 확인한 자리 |
|---|---|---|
| 난이도는 2주마다 바뀐다 | 규칙은 블록 2,016개. 10에폭 실측 평균 14.09일, 폭은 13.07일에서 15.58일 | chainparams.cpp 127번째 줄 · 경계 블록 11개 |
| 조정은 블록 2,016개의 시간을 잰다 | 재는 것은 간격 2,015개. 창을 2,016으로 잡으면 10에폭 전부 예측이 틀린다 | pow.cpp 의 GetNextWorkRequired |
| 목표는 블록당 10분(600초)이다 | 조정이 실제로 겨냥하는 값은 1,209,600 나누기 2,015 = 600.2978초 | pow.cpp · params.h |
| 2,016은 소스에 박힌 상수다 | params.h 가 목표 기간을 목표 간격으로 나눠 만든다 | params.h 130번째 줄 |
| 14일 설정은 하나뿐이다 | 같은 파일에 다섯 곳. 넷이 14일, regtest 만 하루 | chainparams.cpp 다섯 곳 |
| 난이도는 최대 4배까지 뛴다 | 규칙은 맞다. 다만 1년치 26건의 배수는 0.888447에서 1.14725 사이 | pow.cpp 클램프 · 조정 이력 26건 |
| 다음 조정 시각은 정해져 있다 | (2026-08-19 11시 34분 조회 기준) 남은 531블록의 페이스 가정에 따라 8월 23일 03:37에서 04:26으로 갈렸다 | 팁 블록 · 에폭 시작 블록 |
| 난이도 변화율은 어디서 봐도 같은 단위다 | 이력 배열은 배수, 상태 응답은 퍼센트 | 1.00988936과 0.988936의 대조 |
이 글에서 확인하지 못한 것
범위를 밝혀 둘게요.
- 추정 상승폭 산식의 출처. 위에서 그 값을 같은 응답의 다른 필드로 재구성해 세 번 다 끝자리까지 맞췄지만, 그건 응답값끼리 맞아떨어졌다는 뜻이에요. 그 서비스의 소스 코드를 열어 산식을 대조한 것은 아니에요.
- 현재 에폭의 최종 결과. 963648번 블록이 아직 안 나왔으니 다음 조정 폭도 시각도 확정값이 아니에요. 본문의 진행 중 수치는 전부 추정이고 조회 시각이 붙어 있어요.
- 4배 한도가 실제로 걸린 역사적 사례. 제가 확인한 것은 최근 1년 26건에서 0건이라는 사실까지예요. 그 이전 전체 기록은 이번에 열지 않았어요.
- 블록 타임스탬프의 정확성. 블록 타임스탬프는 채굴자가 일정 범위 안에서 정할 수 있어요. 이 글은 조회한 값을 그대로 썼고, 개별 블록의 타임스탬프가 실제 채굴 시각과 얼마나 어긋나는지는 재지 않았어요.
- 조회처 한 곳만 썼다는 점. 블록 타임스탬프와 조정 이력은 공개 API 한 곳에서 받았어요. 다만 그 값으로 계산한
bits가 체인에 실린 값과 10에폭 전부 일치했으니, 최소한 자기모순은 없다는 것까지는 확인됐어요. - 다른 클라이언트 구현. 비트코인 코어 master 소스만 열었어요. 다른 구현이 같은 값을 쓰는지는 이번에 확인하지 않았어요.
- 진행 중 에폭의 결측 블록 여부. 이 글은 간격 수와 경과 시간만 봤고, 개별 블록의 크기나 채굴 주체는 보지 않았어요.
자주 묻는 질문 (FAQ)
Q. 난이도 조정이 정확히 2주가 아닌 이유가 뭔가요?
프로토콜이 세는 단위가 시간이 아니라 블록이기 때문이에요. 블록 2,016개가 다 나와야 조정이 걸리는데, 그 2,016개가 며칠에 걸쳐 나올지는 그때그때 투입된 연산력에 달려 있어요. 연산력이 늘어난 구간이면 예정보다 빨리 끝나고, 줄어든 구간이면 늦어져요. 최근 10에폭에서는 13.07일부터 15.58일까지 벌어졌어요.
Q. 다음 조정이 언제인지 지금 확인하려면 어디를 봐야 하나요?
블록 탐색기에서 현재 높이만 알면 나머지는 계산이에요. 현재 높이를 2,016으로 나눠 내림한 뒤 1을 더하고 다시 2,016을 곱하면 다음 조정 높이가 나와요. 거기서 현재 높이를 빼면 남은 블록 수예요. 다만 시각으로 옮기려면 남은 블록의 페이스를 가정해야 하는데, 이 글에서 잰 경우에는 가정에 따라 약 50분이 벌어졌어요. 그러니 시각보다 남은 블록 수 쪽이 더 단단한 정보예요.
Q. 조정 폭이 4배까지 벌어지는 경우도 있나요?
규칙상으로는 있어요. 다만 그러려면 직전 에폭이 3.5일 만에 끝나거나 56일이 걸려야 해요. 블록 간격으로는 평균 2.5분 또는 40분이라는 뜻이에요. 제가 확인한 최근 1년 26건에서는 배수가 0.888447에서 1.14725 사이였고 한도에 닿은 건이 없었어요. 그 이전 기록까지는 이번에 확인하지 않았어요.
Q. 조정 폭 추정치가 볼 때마다 다르게 나오는 건 왜 그런가요?
블록이 새로 안 나와도 값이 움직이기 때문이에요. 그 추정은 진행 블록 수가 아니라 벽시계로 흐른 시간을 분자에 쓰거든요. 블록이 안 나오는 동안에도 경과 시간만 늘어나니 지금까지 평균이 길어지고, 그만큼 예상 상승폭이 깎여요. 실제로 8분 사이 세 번 조회했더니 팁 높이는 그대로인데 추정 상승폭이 0.3316%에서 0.2812%로 깎였어요. 블록이 하나 나오는 순간 다시 올라가요. 그래서 이런 수치를 옮겨 적을 때는 조회 시각을 반드시 같이 적어야 해요.
Q. 블록 2,016개와 간격 2,015개 차이가 실제로 얼마나 큰가요?
계산 결과 자체를 바꿔요. 같은 코드에서 창만 바꿔 돌려 보니 간격 2,015개로는 10에폭 전부 실제 값과 맞았고, 간격 2,016개로는 10에폭 전부 틀렸어요. 시간으로 옮기면 조정이 겨냥하는 블록 간격이 600초가 아니라 600.2978초가 되고, 에폭마다 약 10분씩, 1년이면 약 4.35시간이 밀려요.
Q. 난이도가 내려가면 블록이 빨리 나오나요?
연산력이 그대로라면 그렇게 되는 방향이에요. 실제로 표에서 6번 에폭이 15.58일로 길어진 뒤 난이도가 0.899배로 내려갔고, 이어진 7번 에폭이 13.07일로 짧아졌어요. 이 표본에서는 이어지는 구간 아홉 번이 전부 이 방향이었어요. 난이도가 오른 다음 에폭은 직전보다 길어졌고, 내린 다음 에폭은 직전보다 짧아졌어요. 다만 이건 에폭 10개에서 그랬다는 뜻이지 항상 그렇다는 뜻은 아니에요. 연산력이 같은 기간에 크게 움직이면 방향이 뒤집힐 수 있어요.
Q. 이 글의 숫자를 그대로 인용해도 되나요?
완결된 10에폭 표본(블록 941472에서 961631까지)은 이미 확정된 과거라 바뀌지 않아요. 반면 진행 중 에폭 관련 수치, 그러니까 팁 높이·남은 블록·예상 시각은 2026년 8월 19일 오전 11시 34분 기준이고 지금은 이미 달라졌어요. 인용하실 때는 앞쪽만 쓰시거나, 뒤쪽은 위의 순서대로 직접 다시 재 보시는 편이 정확해요.
정리
- 비트코인 난이도 조정 주기는 블록 2,016개예요. 2주는 규칙이 아니라 블록이 목표대로 나왔을 때의 결과값이에요.
- 2,016은 소스에 박힌 상수가 아니라 1,209,600초를 600초로 나눈 몫이에요. 두 상수는
chainparams.cpp의 메인넷 블록에 있고, 같은 이름의 줄이 파일 안에 다섯 곳 있어요. - 조정이 시간을 재는 창은 블록 2,016개지만 그 안의 간격은 2,015개예요. 그래서 겨냥하는 블록 간격은 600초가 아니라 600.2978초이고, 에폭마다 약 10분, 1년이면 약 4.35시간이 밀려요.
- 완결 10에폭(블록 20,160개) 실측 결과는 총 12,174,096초, 블록당 603.8738초, 에폭당 14.0904일이었어요. 폭은 13.07일에서 15.58일이에요.
- 경계 블록 타임스탬프만으로 코어 산식을 재현하니 다음
bits가 10에폭 전부 정수까지 일치했어요. 창을 간격 2,016개로 바꾸면 열 번 다 틀렸어요. - 4배 한도는 직전 에폭이 3.5일 이하이거나 56일 이상일 때만 걸려요. 최근 1년 조정 26건에서는 배수가 0.888447에서 1.14725 사이라 한도에 닿은 건이 없었어요.
- 진행 중 에폭은 2026년 8월 19일 오전 11시 34분(한국 시각) 기준 팁 963117, 남은 531블록, 진행률 73.66%였어요. 예상 조정 시각은 페이스 가정에 따라 8월 23일 03시 37분에서 04시 26분 사이로 갈렸어요.
숫자 하나를 외우는 것보다 남길 만한 건 절차예요. 현재 높이를 2,016으로 나눠 내림한 뒤 1을 더하고 2,016을 곱해 다음 조정 높이를 구하고, 이번 에폭 시작 블록의 타임스탬프를 열어 지금까지 평균을 내고, 남은 블록에 그 평균을 곱해 보세요. 그러면 어느 사이트의 숫자를 그대로 믿지 않고도 지금 값이 나와요. 그리고 그 값을 적을 땐 조회 시각을 꼭 같이 적어 두세요.
이 글은 비트코인 코어 소스 원문과 공개 블록 조회 API 응답을 직접 내려받아 정리한 정보 제공 글이며 매매를 권유하는 글이 아니에요. 특정 자산을 사거나 팔라는 뜻으로 읽지 말아 주세요. 가상자산은 변동성이 크고 원금 손실 위험이 있으며, 거래와 보유의 판단과 책임은 본인에게 있어요.
확인한 자료: Bitcoin Core master 저장소의 src/kernel/chainparams.cpp(34,649바이트), src/pow.cpp(6,549바이트), src/consensus/params.h(6,262바이트). mempool.space 공개 API 의 1년 난이도 조정 이력(원소 26개), 현재 조정 상태 응답 3회, 블록 22건 조회(경계 블록 11개, 경계 직전 블록 10개, 팁 블록 1개). 모두 2026년 8월 19일 오전 11시 25분부터 11시 34분(한국 시각) 사이에 직접 내려받아 확인했어요.