블록체인 채굴, 중단은 어떻게 구현될까? 실전 시스템 설계 관점에서 보는 핵심 로직

블록체인 채굴, 중단은 어떻게 구현될까? 실전 시스템 설계 관점에서 보는 핵심 로직

채굴 중단 기능, 단순한 버튼 하나의 문제가 아니다

블록체인 시스템에서 채굴(Mining)은 복잡한 연산의 연속입니다. 하지만 더 복잡한 건 그 채굴을 **"중간에 안전하게 멈춘다"**는 거죠. 단순히 Stop 버튼 하나 추가한다고 끝나는 문제가 아닙니다. 실제 시스템에서는 다양한 고려사항들이 얽혀 있고, 무턱대고 중단하면 블록 생성 무결성, 리소스 누수, 상태관리 오류 등이 발생합니다.

제가 이 주제를 다루게 된 계기는 주변 개발자 지인이 만든 테스트넷에서 무한 채굴 루프가 돌다가 서버 다운됐던 사례였어요. 그래서 직접 플라스크(Flask) 백엔드 환경에서 테스트하며 이 채굴 중단 로직을 완성해봤고, 그 경험을 공유해보려 합니다.

데이터 흐름의 시작, 프론트엔드에서 오는 신호

채굴 중단 기능은 프론트엔드(예: React, Vue 등)에서 시작됩니다. 보통 사용자는 웹 UI에서 "채굴 중단" 버튼을 클릭하고, 이때 자바스크립트는 fetch() 혹은 axios 같은 비동기 통신을 통해 JSON 데이터를 백엔드에 전달하죠.

이 JSON 안에는 stopFlag: true 같은 명확한 신호가 포함되어 있고, 이 신호를 Flask 서버가 받아야 합니다. 여기서 중요한 포인트는 Content-Type: application/json을 명시해야 서버에서 request.get_json() 같은 함수로 해당 데이터를 올바르게 해석할 수 있다는 점입니다.

실제로 테스트해본 결과, Content-Type이 application/x-www-form-urlencoded일 경우에는 None이 반환되기 때문에, 이건 꼭 체크해야 해요. 한 번쯤 실수로 POST는 했는데 값이 안 들어와서 디버깅하다가 반나절 날린 적도 있습니다.

상태 플래그: 전역 변수의 힘과 위험

채굴 중단을 제어하는 건 stopMining 같은 전역 변수입니다. 이걸 True로 바꾸는 순간, 백엔드 로직은 "지금 채굴 멈춰야 한다"는 신호를 받는 거죠. 단순해 보이지만 여기엔 함정도 있습니다.

멀티스레드 환경에서는 전역 변수 하나가 여러 스레드에서 동시에 접근되기 때문에, race condition이 발생할 수 있어요. 그래서 저는 파이썬의 threading.Lock()을 사용해서 동기화 처리했는데, 이거 안 하면 예외 상황에서 stop 신호가 무시되거나, 중단되었다고 착각하고 블록이 계속 생성되는 문제가 생깁니다.

스레드를 써야 하는 이유, 그리고 왜 백그라운드에서 돌아가야 하나

채굴 프로세스는 기본적으로 계속 반복되는 작업입니다. 즉, 무한 루프 형태죠. 그런데 이걸 메인 스레드에서 돌려버리면, 웹서버 자체가 먹통됩니다. 그래서 채굴은 **스레드(Thread)**로 돌려야 합니다.

스레드를 이용해 백그라운드에서 while not stopMining: 이런 식의 반복문을 돌리고, 플래그가 True로 바뀌면 루프를 빠져나오게 만드는 거죠. 이걸 실제 구현해보면서 느낀 건, "한 번 멈췄다가 다시 시작"하는 걸 가능하게 하려면 스레드를 완전히 종료했다가 새로 생성하는 구조로 짜는 게 좋습니다.

재사용하면 간편해 보이지만, 예기치 않은 내부 상태가 남아서 예외 발생률이 높아지거든요. 특히 비동기 환경에서는 이전 루프가 완전히 종료되지 않아서 이중 채굴이 일어날 수도 있고요.

중단 로직의 핵심, 와일문 탈출의 조건 설계

채굴 로직의 중심은 while True: 형태의 무한 루프입니다. 여기에 if stopMining: break 구조를 삽입하는 게 핵심이에요. 이 조건문이 없다면 사용자가 중단 버튼을 눌러도 시스템은 멈추지 않겠죠.

중요한 건 stopMining이라는 조건이 변할 타이밍을 적절히 잡아야 한다는 거예요. 예를 들어, 하나의 블록을 채굴 중이라면, 그 작업이 끝날 때까지 기다린 후 루프를 종료하는 게 더 자연스럽고, 무결성 유지에도 도움이 됩니다. 그래서 저는 보통 아래 같은 순서를 따릅니다:

  1. 블록 연산 수행

  2. 결과 저장

  3. 중단 상태 확인

  4. 루프 유지 or 종료 결정

이렇게 되면 사용자는 "버튼 누르고 0.5초 뒤에 멈췄네?"라고 생각하겠지만, 내부적으로는 하나의 사이클을 마무리한 뒤 종료되는 거라 더 안전한 거죠.

중단 상태 확인은 단순 출력이 아니라 진짜 상태 리턴까지

사용자가 중단 버튼을 눌렀을 때, 단순히 서버에서 "OK"를 반환하는 건 충분하지 않습니다. 정확히 중단되었는지 여부를 프론트엔드에 리턴해줘야 합니다.

그래서 /mining/stop 같은 라우트에서는 중단 신호 수신 후, 실제로 stopFlag가 작동했는지 확인하고 그 결과를 JSON 형태로 반환해요. 예: {status: "stopped", blocksMined: 12} 이런 식으로요.

이런 리턴 구조가 있어야 프론트엔드에서도 "완전 중단됨" 같은 메시지를 명확히 보여줄 수 있고, 사용자가 시스템을 믿고 다시 시작 버튼을 누를 수 있게 됩니다.

다양한 중단 로직 구현 방법, 무엇이 정답일까?

이론적으로는 여러 방식이 가능합니다. 제가 실험해본 방식만 해도 아래와 같아요.

  • 전역 변수 방식: 가장 쉽고 빠름, 단점은 스레드 간 공유 위험

  • 세마포어(Semaphore) 사용: 제어가 명확하지만 코드 복잡도 증가

  • 플라스크의 g 객체: 요청 간 상태 저장에는 부적절함

  • 세션(Session): 로그인 기반이라면 유용하지만 스레드 제어와는 별개

  • 설정 파일 활용: 동적 제어엔 불리, 서버 재시작 필요 가능성

결국 저는 전역 변수 + Lock 조합으로 갔어요. 이유는 단순성과 효율성 때문이죠. 실제 시스템에서는 장애가 나면 대응 속도가 중요하니까요.

중단 반응 속도는 어떻게 확보할까?

이건 채굴 로직이 얼마나 자주 stopFlag를 체크하느냐에 달려 있어요. 예를 들어, 연산 루프 중간마다 10번에 한 번씩만 체크하게 해두면, 반응 속도가 늦어질 수밖에 없죠.

그래서 저는 블록 하나 채굴 완료할 때마다 한 번씩 체크하는 구조로 만들었어요. 이러면 평균 0.2~0.5초 정도 안에 중단 처리가 되더라고요. 물론 서버 사양, 채굴 난이도에 따라 달라질 수 있습니다.

채굴 횟수, 생성 블록 수 기록은 반드시 남겨야 한다

중단되더라도 지금까지 몇 개 블록을 생성했는지, 채굴 시도는 몇 번 있었는지 로그로 남겨야 합니다. 이건 단순 기록의 문제가 아니라, 시스템 회복 및 추후 분석을 위해 필요합니다.

제가 구현한 시스템에서는 minedCount, successfulBlocks 같은 전역 카운터를 따로 만들어서 로그 파일에 남겨두었어요. 이건 나중에 대시보드 만들 때도 유용하게 쓰이더라고요.

다음 스텝은 '합의 알고리즘'

이번 포스팅에서는 채굴 중단 로직 자체에만 집중했지만, 실제 블록체인에서는 **합의 알고리즘(Consensus Algorithm)**이 병행되어야 합니다. 즉, 내가 멈췄다고 해서 블록이 무효화되거나, 다른 노드와 충돌이 생기면 안 되겠죠.

그래서 PoW나 PoS 방식에 따라 중단 시점에서의 상태 동기화가 필요한데, 이건 다음 글에서 자세히 다루겠습니다.


마무리하며

채굴 중단 로직은 단순한 UI 버튼에서 끝나는 게 아닙니다.
시스템의 안정성, 무결성, 사용자 경험을 모두 고려해야 하는 설계 문제입니다.

개발 실무나 사이드 프로젝트에서 이 기능이 필요하다면, 반드시 상태 플래그 관리, 스레드 동기화, 반응 속도 최적화, 상태 기록 유지를 염두에 두고 설계하시길 바랍니다.

여의도에서 시스템 설계 컨설팅할 때, 제가 가장 많이 받는 질문 중 하나가 "블록체인 시스템에서 안전하게 멈추는 방법 없어요?"였어요. 그만큼 중요한 기능이고, 잘 구현하면 신뢰도 있는 시스템으로 평가받을 수 있습니다.

다음 포스팅에서는 합의 알고리즘과 중단 이후 블록 검증의 절차를 중심으로 다뤄보겠습니다.

댓글

이 블로그의 인기 게시물

미국 비트코인 채굴 75.4% 점유율 확대

비트코인 해시레이트 감소와 채굴자 반전

비트코인 채굴과 부동산의 에너지 혁신