솔라나 팁 통을 만들었습니다
Source: Dev.to
솔직히 말하자면, 이것을 시작했을 때 나는 내가 뭘 하고 있는지 전혀 몰랐어요.
Solana 기본은 좀 알았어요. 문서를 읽고, 유튜브 영상을 몇 개 보고, 모든 걸 이해한 듯 고개를 끄덕였죠. 하지만 실제로 무언가를 만든다는 건? 완전히 다른 이야기였어요.
그래서 스스로에게 도전을 걸었어요: 실제 dApp을 만들고, 배포하고, 작동하게 만들기—전체 과정을 튜토리얼이 손잡아 주지 않게.
나는 tip jar를 선택했어요. 간단한 개념: 지갑을 연결하고, 금액을 입력하고, 누군가에게 SOL을 보내는 것. 얼마나 어려울 수 있겠어요?
결과는 매우 어려웠어요. 하지만 결국 해냈습니다.
팁 자는 이유는?
왜냐하면 나는 실제적인 것을 만들고 싶었지만 너무 벅차지는 않게 하고 싶었기 때문입니다.
많은 초보자용 Solana 튜토리얼은 너무 단순해서 인상적이지 않거나, 너무 복잡해서 실제로 끝내기 어렵게 만듭니다. 팁 자는 그 중간에 정확히 자리합니다. 그것은 다음을 포함합니다:
- 실제 지갑 연결
- 실제 트랜잭션
- 실제 블록체인에서 실제 돈 이동
…하지만 로직이 충분히 단순해서 작성하는 모든 코드 라인을 이해할 수 있습니다.
규칙: 코드를 설명할 수 없다면, 실제로 그 코드를 알지 못하는 것입니다.
내가 사용한 스택
- Solana + Anchor – 스마트 계약용
- React + Vite – 프론트엔드용
- Phantom wallet – 연결 및 서명용
- Vercel – 배포용
나는 현재 시점에서 CRA가 오래된 느낌이라 Vite를 Create React App보다 선택했다. Vite는 빠르고 현대적이며 개발자 경험이 훨씬 좋다.
앱이 실제로 작동하는 방식
- 앱을 열면 Connect Wallet 버튼이 보입니다.
- 클릭하면 Phantom이 팝업되고, 연결을 승인합니다.
- 이제 앱은 당신의 공개키, 잔액 등을 알게 됩니다.
- 보내고 싶은 SOL 양을 입력하고 Send를 누릅니다.
백그라운드에서 (≈2 초):
- 프론트엔드가 트랜잭션을 생성합니다 – 이것을 서명된 수표라고 생각하면, 누가 보내는지, 누가 받는지, 얼마나 보내는지, 그리고 당신의 서명이 포함됩니다.
- 트랜잭션은 Solana devnet에 전송됩니다. 검증자들이 이를 확인하고, 정당함을 검증한 뒤 실행합니다.
- SOL이 이동하고, 블록체인은 이를 영구적으로 기록합니다.
완료. 아무도 이를 되돌리거나 거짓말할 수 없습니다. 이러한 영구성이 블록체인을 흥미롭게 만드는 이유입니다—과대광고도, 가격도 아니라, 코드가 중개인 없이 규칙을 강제할 수 있다는 사실 때문입니다.
거의 나를 무너뜨린 부분
Vite와 Solana는 기본 설정만으로는 서로를 좋아하지 않는다. Solana의 @solana/web3.js 라이브러리는 Webpack이 모든 것을 장악하던 시절에 만들어졌으며, 브라우저 번들에서 Vite가 의도적으로 제외하는 buffer와 같은 Node.js 내장 모듈에 의존한다.
나는 계속해서 다음 오류가 발생했다:
Module "buffer" has been externalized for browser compatibility
해결 방법은 두 줄이었다:
npm install buffer
// main.tsx
import { Buffer } from "buffer";
window.Buffer = Buffer;
두 줄. 그게 전부다. 때때로 가장 고통스러운 버그는 가장 평범한 해결책을 가지고 있다.
Anchor가 실제로 하는 일
이 프로젝트를 시작하기 전까지 나는 Anchor가 선택 사항—즉, 있으면 좋은 정도라고 생각했다. 선택 사항이 아니다.
순수 Rust만으로 Solana 프로그램을 작성하는 것은 도구 없이 가구를 만드는 것과 같다: 기술적으로는 가능하지만, 스스로에게 왜 그런 일을 하겠는가?
Anchor는 계정 검증, 오류 처리, 직렬화 등, 여러분이 포기하고 싶어 할 만한 모든 보일러플레이트를 처리한다. 덕분에 프로그램이 실제로 하는 일에 집중할 수 있다.
핵심 프로그램 로직
pub fn send_tip(ctx: Context, amount: u64) -> Result {
anchor_lang::system_program::transfer(
CpiContext::new(
ctx.accounts.system_program.to_account_info(),
anchor_lang::system_program::Transfer {
from: ctx.accounts.sender.to_account_info(),
to: ctx.accounts.receiver.to_account_info(),
},
),
amount,
)?;
msg!("Tip sent! 💰");
Ok(())
}
마지막에 있는 CPI(크로스‑프로그램 호출) 호출은 기본적으로 내 프로그램이 “Hey Solana의 System Program, 이 SOL을 옮겨줘.”라고 말하는 것이다. Solana의 프로그램은 SOL을 직접 이동시키지 않는다; 대신 System Program에 요청한다. 그 점이 이해되면서 모든 것이 더 명확해졌다.
Devnet vs. Mainnet
제가 만든 모든 것은 devnet – Solana의 테스트 환경에서 실행됩니다. 동일한 기술, 동일한 속도이지만 SOL은 가짜이고 무료입니다.
왜 중요한가요? 메인넷에서 실수를 하면 실제 돈이 듭니다. Devnet에서는 뭘 부숴도 되고, 고쳐도 되고, 다시 부숴도 되며 비용이 전혀 들지 않습니다.
테스트를 할 준비가 되었을 때 저는 devnet SOL을 에어드롭했습니다:
solana airdrop 2
무료 돈. 오직 devnet에서만 가능합니다. 가능한 한 즐기세요.
Deploying It
I used Vercel and it took about 3 minutes.
- Connect GitHub, import the repo.
- Set the root directory to
app. - Click Deploy.
That’s genuinely it. Vercel detected the Vite project and handled the rest.
- Live app: (link omitted in original)
- Source code: (link omitted in original)
배포하기
Vercel을 사용했으며 약 3분 정도 걸렸습니다.
- GitHub을 연결하고 저장소를 가져옵니다.
- 루트 디렉터리를
app으로 설정합니다. - Deploy를 클릭합니다.
그게 전부입니다. Vercel이 Vite 프로젝트를 감지하고 나머지를 처리했습니다.
- Live app: (원본에서 링크 생략)
- Source code: (원본에서 링크 생략)
내가 다르게 할 일
다시 시작한다면 바꾸고 싶은 몇 가지 사항:
- 버퍼 폴리필을 먼저 설정한다. 중간에 오류를 발견하지 않도록.
- 첫날부터 devnet을 사용한다 그리고 연결하기 전에 Phantom이 devnet으로 설정되어 있는지 확인한다. 네트워크가 맞지 않으면 혼란스러운 오류가 발생한다.
- 테스트를 더 일찍 작성한다. Anchor의 TypeScript 테스트 설정은 훌륭하다. 나는 빠르게 진행하려고 이를 건너뛰었고, 디버깅 시간으로 대가를 치렀다.
다음에 할 일
이것은 버전 1이었습니다. 제가 추가하고 싶은 내용은 다음과 같습니다:
- A transa… (the post cuts off here)
거래 내역
- 모든 팁을 확인할 수 있는 히스토리 뷰.
- 전송자가 팁과 함께 메모를 남길 수 있는 메시지 필드.
- 실제 SOL을 사용할 만큼 자신감이 생기면 메인넷 배포 예정.
이제 시작한다면
뭔가를 만들어 보세요. 무엇이든지.
문서는 좋고, 튜토리얼도 도움이 됩니다. 하지만 한밤중에 오류 메시지를 바라보며 스스로 해결해 보는 것만큼 가르쳐 주는 것은 없습니다.
- 작게 시작하세요.
- 끝내세요.
- 배포하세요.
그 다음에 또 다른 것을 만들어 보세요.
이게 전부 전략입니다.