채굴 기능, 직접 구현해보니 이래서 복잡하구나 싶더라
채굴 기능, 직접 구현해보니 이래서 복잡하구나 싶더라
“그냥 버튼 하나 누르면 되는 거 아냐?”의 착각
처음에 저도 그랬어요. 채굴 기능 만들겠다고 마음먹고 제일 먼저 든 생각이 딱 이거였거든요.
“어차피 버튼 하나 누르면 시작하는 거잖아?”
근데 막상 구현을 시작하니까 그게 얼마나 순진한 생각이었는지 바로 알겠더라고요.
제일 먼저 마주한 벽은 **“사용자의 행동을 시스템이 어떻게 인식할까?”**였어요.
단순히 버튼 눌렀다는 사실만 알면 될 줄 알았는데, 막상 만들다 보니까
-
지갑 주소는 입력됐는지
-
현재 코인 수량은 뭔지
-
보상금은 어디에 표시할 건지
이런 요소들이 한데 엮이면서 시스템이 해야 할 판단이 많아지더라고요.
이걸 가능하게 해주는 게 결국 JavaScript, 그리고 DOM 제어였어요.
HTML이 뼈대라면, 자바스크립트는 그걸 움직이는 근육이자 신경 같은 느낌?
그 역할을 직접 다뤄보니까, '단순한 인터랙션'조차 얼마나 복잡한 준비를 필요로 하는지 새삼 느꼈어요.
“상태를 기억 못 하면, 시스템은 그냥 바보다”
이건 제가 피땀으로 배운 교훈 중 하나예요.
처음엔 사용자가 가진 코인 수량을 미리 기억해둬야 한다는 걸 까먹고 있었어요.
그래서 채굴 시작 버튼을 누르면 무조건 0에서 시작하는 거예요.
결과는? 당연히 보상 계산이 완전히 엉망이었죠. 😵
이후엔 사용자가 조회 버튼을 따로 안 눌러도, 자동으로 현재 코인 수량을 불러오게 바꿨어요.
이건 사용자가 실수할 수도 있다는 걸 미리 감안해서 시스템이 알아서 커버해주는 방식이에요.
겪어보니까 이런 세심함이 실제 구현에서는 훨씬 중요하더라고요.
실시간 데이터는, 진짜 실시간으로 관리해야 해서 어렵다
채굴을 시작하면 백엔드는 스레드를 돌리고, 프론트에서는 3초마다 상태를 서버에 요청해요.
setInterval()
하나로 구현은 했는데, 문제는 이게 단순한 타이머가 아니라는 거예요.
예를 들면 이런 상황들요:
-
서버는 잘 돌아가고 있는데 프론트는 멈춘 줄 알고 사용자에게 오류처럼 보이기도 하고
-
반대로 프론트는 살아 있는데, 서버 쪽 스레드가 죽어버리기도 하고
이런 꼬인 상황이 생길 때마다, 저는 결국 Ctrl + C
눌러서 서버 강제 종료했어요.
그때 느꼈죠. 실시간 시스템은 진짜 정교하게 설계하지 않으면 망가지는 속도도 실시간이라는 걸요.
Flask는 고집이 좀 세더라
한참 채굴 상태 저장 로직 짜던 중에, 갑자기
RuntimeError: Working outside of application context
이 에러가 떴어요.
그땐 진짜 뭔 소리인지 감도 안 왔어요.
결국 뒤져보니까 Flask는 “앱 컨텍스트” 안에서만 DB를 건드릴 수 있도록 제한을 걸어둔 거였고,
with app.app_context():
로 감싸야 해결되는 문제였어요.
이거 하나 몰라서 2시간 넘게 콘솔창 들여다보며 디버깅했던 기억이… 아직도 생생합니다.
웹 채굴의 본질은 ‘데이터 저장’
처음엔 채굴이라고 하니까 GPU 돌리고 해시 푸는 이미지부터 떠올랐어요.
근데 실제 웹 채굴은 그런 게 아니더라고요.
진짜 중요한 건 보상 데이터를 정확하게 DB에 저장하는 로직이에요.
저는 ORM으로 Transfer
객체 만들어서 DB에 커밋하는 방식으로 처리했어요.
블록이 만들어졌다는 건 결국
-
트랜잭션이 생겼고
-
그게 DB에 반영됐으며
-
실패/성공 여부에 따라 처리까지 돼야 한다는 뜻이니까요.
막상 구현해보면 은근히 섬세하게 짜야 할 부분이 많아요.
계산은 숫자처럼 생겼어도, 꼭 숫자로 바꿔줘야 해요
보상 계산은 이전 코인 수량과 현재 수량을 비교해서 차이만큼 지급하는 방식으로 짰어요.
당연히 숫자 계산이니까 parseFloat()
를 써야 했는데…
초반엔 그걸 몰라서 문자열 상태로 계산하다가 NaN
뜨는 걸 보고 멘붕했었죠.
콘솔창에 찍힌 그 에러 메시지, 진짜 잊기 힘들어요. 그날 이후로 숫자 계산은 무조건 형 변환부터 합니다.
연속 채굴, 잘 돌아가는 게 문제였다
진짜 웃긴 건, 채굴이 너무 잘 돌아가서 문제였어요.
한번 시작하면 서버 끌 때까지 스레드가 계속 돌더라고요.
노트북 팬 소리 점점 커지면서, “아… 이게 진짜 채굴기구나” 싶었어요.
그래서 중단 버튼 누르면 스레드를 정지시키는 플래그 변수를 넣는 구조로 바꿨어요.
이 부분은 다음 글에서 조금 더 자세히 풀어볼게요.
마무리 요약
-
채굴 시작 시, 초기 코인 수량 기준으로 보상 계산
-
프론트는 3초마다 서버에서 상태 받아오기
-
백엔드는 스레드로 채굴 상태 계속 유지
-
Flask는 앱 컨텍스트 안에서만 DB 접근 가능
-
숫자 계산 시엔 꼭
parseFloat()
같은 형 변환 필수 -
자동 채굴 구조라면 중단 로직 필수
-
실시간 반영을 위해선 DOM 조작 필요
-
오류는 미리 예측하고 대비해야 함
한 줄 요약
“버튼 하나 눌러도, 시스템은 그 이유부터 결과까지 다 이해해야만 움직인다.”
이걸 직접 구현해보면서 진짜 많이 느꼈어요.
기술이 어렵다기보단, 사용자의 행동 하나하나를 시스템이 얼마나 잘 이해하느냐가 핵심이더라고요.
웹은 특히 사용자 의도가 명확히 전달되지 않기 때문에,
“혹시 이걸 안 눌렀다면?”, “이 순서가 바뀌었다면?” 같은 가정들을 항상 염두에 두고 구조를 짜야 해요.
처음엔 이게 너무 귀찮고 번거로운 일처럼 느껴졌는데,
계속 다듬다 보니 그 안에 UX와 시스템 안정성의 진짜 핵심이 숨어 있더라고요.
특히 채굴처럼 연속 동작하는 기능일수록,
‘의도치 않은 실행’과 ‘예상 못 한 중단’을 막는 구조가 얼마나 중요한지 몸으로 배웠습니다.
이건… 진짜 직접 겪어보지 않으면 모르는 세계예요.
결국 웹에서의 시스템이란, 사용자와 대화를 이어가는 구조라는 걸 깨달았어요.
한 번의 클릭에도 "왜 눌렀을까", "그 전에 뭘 했을까", "이후엔 뭘 기대할까" 같은 맥락을 다 읽어야 하니까요.
처음엔 기술적으로 어떻게 연결할지만 고민했는데, 시간이 지날수록 사람을 이해하는 게 더 중요하구나 싶더라고요.
그리고 그런 이해가 쌓일수록 시스템도 점점 ‘똑똑해지는’ 게 느껴졌어요.
그냥 잘 돌아가는 코드보다, 실수에도 무너지지 않는 구조, 사용자의 행동을 기다려주는 흐름,
그런 걸 만들 때 가장 보람도 크고, 진짜 제품이 된다는 느낌이 들었습니다.
이제는 버그 하나 잡을 때도 단순히 ‘왜 에러가 났지?’보다
‘사용자가 어떤 상황에서 이걸 누를 수 있었을까?’부터 떠올리게 돼요.
아마 그게, 개발자로서 조금은 자라났다는 증거 아닐까요.
댓글
댓글 쓰기