2023년 7월 31일 월요일부터 8월 2일 수요일까지 2박 3일 동안 서울 웹3.0 페이스벌 해커톤에 참가해 경험을 나누고자 후기를 작성했습니다. 동국대학교 블록체인 학회 2plusONE 소속으로 팀원 6명과 함께 2PO 팀명으로 참가했습니다. 대회 준비과정부터 대회 마무리까지 시간 순서대로 작성하려 합니다.
서울시와 서울디자인재단, 바오밥파트너즈가 개최한 서울시 최초의 웹3.0 페스티벌입니다.
-일정: 7월 31일 (월) ~ 8월 2일 (수) 2박 3일
-장소: 동대문 디자인 플라자 (DDP)
Hackathon 상금 1억 2천만원
-대상(1팀) 서울특별시장상 3000만원
*주제별 1등 3개팀 중 1개팀 대상 수상
-1등 (3팀) 1500 만원
-2등 (3팀) 900만원
-3등 (3팀) 600만원
해커톤 정보에 대해 더 알아보시고 싶으시면 아래 링크를 참고해주세요.
https://seoulweb3festival.com/
해커톤 구글 폼을 제출하기 위해 6월 말부터 아이디어를 선정하고자 약 3주간 많은 회의를 거쳤습니다. 총 3번의 아이디어가 교체되었고 이로 인해 해커톤 시작일(7월 31일) 2주 전부터 디자인과 개발을 시작했습니다. 그러다 보니 구글폼에 제출한 주제와 다른 주제인 약자와의 동행 키워드에 맞춘 '기부런'으로 해커톤에 참가했습니다.
웹3를 사용해야하기 때문에 아이디어엔 항상 'Why Blockchain?'이라는 물음이 함께하다 보니 난관에 봉착할 때가 있었습니다. 기존 중앙화 서비스를 이용할 수 있는데, 왜 블록체인을 사용하려고 하냐? 라고 하면 말문이 탁 막힐 때가 있었습니다. 나부터 나의 주제를 설명하지 못하는데, 다른 사람을 설득시킬 수 없다고 생각하여 제가 낸 아이디어를 더 진행시킬 수 없었습니다. 아이디어 선별과정에서 보완점을 찾아냈습니다. 오? 할 수 있는 아이디어는 잘 내지만, 이를 깎아내고 구체화 하는 능력을 키우면 좋겠다는 배움을 얻었습니다. 아이디어 발전과정에서 학회장님의 도움으로 넥슨 블록체인 팀장님, 라인 프론트엔드 개발자님, 해커톤 멘토님의 피드백을 받을 수 있었습니다.
기부런은 무엇이냐?
기부런은 블록체인을 활용하여 혁신적인 기부 시스템을 제시하고 투명성을 제공하는 플랫
폼입니다. 기부자들과 수혜자들을 직접 연결하여 신뢰성을 높이고, 기부 수혜자들이 블
록체인 생태계의 구성원으로 성장하여 미래 사회에 발맞출 수 있도록 도울 수 있습니다.
Figma라는 디자인 협업툴을 이용해 처음으로 만들고자 하는 웹페이지를 꾸몄습니다. 거래 내역 페이지, 토큰 사용법 페이지, 기부 진행과정(홈페이지 구현x)을 담당했습니다. 웹페이지를 시각화하니 아직 디자인 단계인데도, 실제 서비스가 존재하는 느낌이 들었습니다. 다른 팀원의 디자인을 보고 디자인을 배워야겠다는 생각도 들었습니다.
위의 피그마로 디자인한 페이지를 토대로 HTML문서를 작성하고, 리액트로 웹페이지를 제작하기 시작했습니다. 이때 Git을 이용해 협업을 처음 진행해 다른 팀원들에게 레포지토리 폭파와 같은 사태를 일으키고 싶지 않아 밤에 6시간동안 <do it! 깃&깃허브 입문>책을 보고 실습했던 기억이 납니다. 리액트도 처음하다보니 1주일 동안 이론과 적용을 집중해서 몰아쳤습니다. 이때 잘모르는 코드를 계속 관찰하여 어떤 구조로 이뤄졌는지 파악하니 리액트를 좀 더 이해할 수 있었습니다. 관찰의 힘이란..! 홈페이지를 작성한 코드를 토대로 동일한 폴더구조와 파일을 생성해서 리액트로 맡은 페이지를 구현할 수 있었습니다. 리액트를 쓰면서 제가 생각했던 동작은 간단하게 느껴지는데 이를 구현하는게 생각보다 어려웠습니다.
오전 8시에 팀원들과 아트홀 2관 앞에서 모여 들어갔습니다. 일찍 도착해서 아직 준비를 하고 계셨습니다. 서울시에서 제공해준 에코백, 반팔2개, 명찰입니다. 에코백안에 상품들이 꽤 많았습니다. 아침, 점심, 저녁을 3일동안 챙겨주셨습니다. 라면, 과자, 물, 핫식스, 탄산수 등 먹거리도 무한리필로 챙겨주셔서 너무 행복했습니다.
개막식동안 각 기관, 회사 대표님들이 오셔서 연사해주셨는데, 오세훈 서울시장께서 오신걸 보고 진짜 큰 대회임을 느꼈습니다. 중간에 교육세션이 있었고 나머지는 개발을 진행했습니다. 각 페이지별로 구현하지 못한 부분을 분담하여 개발해나갔습니다. 저는 기존 페이지에서 적용할 내용을 개선하고 있었습니다. 평소 늦게 자는 편이라 밤 11시쯤에 예인님과 같이 라면도 먹으면서 담소를 나눴습니다. 재밌었어요 😁
2일차 때도 프론트 쪽에서 구현하고자 하는 기능을 모두 구현하지 못해 컨트랙트 개발을 시작하지 못했습니다. 모든지 기간을 정하고 완료하지 못했을 경우 계획을 조정해서 다음 스텝을 밟아갈 수 있는 결단이 필요하겠다는 걸 배웠습니다.
기부하기 페이지에서 원하는 사업의 기부하기 버튼을 클릭하고, 기부하고자 하는 코인의 양을 입력하면 자동으로 기부 대상자의 월렛으로 코인이 전송하게끔 기능을 구현하고자 했습니다. 해당 페이지와 스마트 컨트랙트의 연동을 담당했습니다.
스마트 컨트랙트의 주기능은 다음과 같습니다.
컨트랙트 배포 시 토큰 발행 transfer 함수 호출 시 to 주소로 토큰 전송
리액트에서 스마트 컨트랙트와 연동한 부분입니다. <ProgressDetail.jsx>
인퓨라를 통해 web3 객체를 가져와야합니다. 스마트 컨트랙트를 배포한 후 ABI와 컨트랙트 주소를 가져와 연동해야합니다. 리액트에서 작성한 컴포넌트에서 원하는 동작시 컨트랙트의 함수를 호출하도록 구현합니다.
TypeError: contract.methods.transfer is not a function
컨트랙트 함수를 호출하는 부분이 호출되지 않아 이날 잠을 자지 않고 계속 방법을 찾고 있었습니다. 주원인은 크게 3가지임을 찾았습니다.
ABI와 컨트랙트 주소는 이상이 없었고, 배포된 컨트랙트를 Remix 상에서 transfer함수를 호출하여 다른 팀원의 월렛으로 토큰 전송까지 확인해 컨트랙트에 이상이 없다고 판단했습니다. 하지만 연동부분이 개발자도구에서 확인했을 때, 오류가 계속 발생했습니다. 컨트랙트 연동부분에서 개발멘토인 정윤님이 많이 도와주셨습니다. 감사합니다!
컨트랙트와 리액트 연동부분입니다.
// 컨트랙트 관련
// Infura Goerli
const infuraUrl = `인퓨라 url`;
const web3 = new Web3(infuraUrl);
// 컨트랙스 주소와 ABI 정의
const contractAddress = "0xd9973163F044268417c7b50C0A571d293B6da5B4"; // 컨트랙트 주소
const contractABI = [
[
..내용이 길어서 생략..
];
// 컨트랙트 인스턴스를 생성합니다.
const contract = new web3.eth.Contract(contractABI, contractAddress);
//기부 수량 =================================
const [donationAmount, setDonationAmount] = useState("");
const [receiverAddress, setReceiverAddress] = useState("");
const handleReceiverAddressChange = (e) => setReceiverAddress(e.target.value);
// 댓글 입력 값이 변경될 때 호출되는 함수
const handleDonationAmountChange = (e) => {
// 댓글 입력 값을 상태(state)에 저장
setDonationAmount(e.target.value);
};
// (병합) [댓글 등록 버튼을 클릭했을 때 호출되는 함수
const handleDonationSubmit = () => {
// 댓글 등록 처리 로직 추가
console.log("컨트랙트 주소: ", contract);
console.log("수량 입력: ", donationAmount);
//console.log("기부 대상자 지갑주소: ", selectedContent.address);
// 댓글 입력 값을 초기화
//setDonationAmount("");
};
const totalButton = () => {
handleDonationSubmit();
handleCloseAndOpen();
handleDonation();
};
// 이더리움 기부 처리 함수 (미정)
const handleDonation = async () => {
try {
const accounts = await web3.eth.getAccounts(); // 사용자 계정 가져오기
const sender = "0x2401bC67706121CCa309d6cd01a05E2fdF9Cff4a";
//const sender = accounts[0]; // 보내는 사람의 주소
const receiver = selectedContent.address; //{selectedContent.address}; // 기부 대상자 지갑 주소
console.log("보내는 사람 주소 ", sender);
console.log("기부 대상자 지갑주소 진짜: ", receiver);
const amount = web3.utils.toWei(
/*이더리움의 양*/ donationAmount,
"ether"
); // 이더리움의 양을 Wei 단위로 변환
// 이더리움 전송하기
const receipt = await contract.methods
.sendEther(receiver)
.send({ from: sender, value: amount });
console.log(receipt);
} catch (err) {
console.error(err);
}
};
//-- 컨트랙트 관련
2일차의 밤
최종 코드 제출은 마지막날 오전 7시 30분이기 때문에 대부분의 팀이 대회장에서 밤을 새웠습니다. 밤 12시쯤 팀원들과 라면을 먹었습니다! 먹는 동안 구현하지 못한 부분에 대한 걱정은 살짝 덜어 놓았습니다. 식사는 오른쪽과 같이 나왔습니다!
![]() | ![]() |
---|
라면 말고도 빈츠, 스니커즈 등도 많았습니다.
예선 발표을 위해 나머지 팀원들이 PPT, 사업계획서(한글, 영문), 사용 영상을 준비하고 있었습니다. 저는 컨트랙트와 리액트 연결을 위해 방법을 오전 5시까지 계속 찾아보고 있었는데요. 결국에는 방법을 찾지 못해 프론트에서 오류가 나지 않을 정도까지만 구현을 했습니다. 지금도 그 문제를 해결하고 싶어 자바스크립트 문법과 리액트를 이용한 웹3 프로젝트를 공부하고 있습니다.
오전 7시 30분에 최종 제출이 완료되고, 팀원들과 아침을 마지막으로 먹고 DDP에서 낮잠을 잤습니다. 다들 잠을 못자서 그런지 약 30분동안 DDP의 하늘을 보며 푹 자다가 8시 53분에 잠이 깨 예선 발표에 늦지 않도록 대회장으로 들어갔습니다. DDP에서 왜 그렇게 누워있는지 알 것 같습니다. 오전 9시에 랜덤으로 예선 발표가 정해졌는데, 저희 팀이 첫번째로 배정됐습니다.
첫번째 호명이라 긴장되었을텐데, 도윤님이 본선 통과라는 멋진 결과를 가져오셨습니다 👍 본선 발표 대상자는 본선 발표 시간 대 호명하면 통과하는 걸로 바로 알려주진 않았습니다. 그래서 더 떨렸습니다. 그때 너무 놀라서 손이 떨리는 상태로 앞쪽으로 가 본선 발표 영상을 찍은 기억이 납니다.
2PO 학회는 올해 3월 말에 만들어진 신생 학회입니다. 첫 해커톤에서 본선 진출이라는 쾌거를 이뤄 너무 행복했습니다. 또한 2PO 학회에서 멘토님 포함 총 3팀이 모두 본선 진출을 하고 해커톤 멘토님 팀에서는 2등을 수상했습니다!!
모든 수상이 끝나고 해커톤 참가 확인서를 받았는데, 드디어 끝이 났구나 라는 생각이 들었습니다. 대회장 내부에서는 외부와 차단되어 해가 뜨는지 지는지도 모르고 3일동안 개발을 했습니다. 시간이 느리게 가는 듯 하면서도 빨리 갔습니다.
![]() | ![]() |
---|
밤 8시가 되어서야 DDP를 나올 수 있었는데, 하늘이 너무 예뻐서 사진을 찍었습니다. 첫 해커톤 동안 부족한 점을 느꼈고 앞으로 나아갈 수 있는 에너지와 방향성을 얻을 수 있었습니다. 팀원분들, 학회장님, 멘토님들, 피드백 주셨던 넥슨, 라인 개발자님들 모두 감사합니다. 앞으로 더 나아가겠습니다. 2PO 파이팅