Discord.js + Node.js 디스코드 모의주식 이코봇 개발기
이 글은 TISTORY에서 발행되어 이전된 글 입니다.
어쩌피 솔로라 할 것도 없어 뒹굴거리던 12월 19일 저녁에 깃허브에 들어갔더니 갑자기 제가 팔로우하는 분중 한분이 해커톤 참여 레포를 생성하셨길래 저번부터 해커톤에 나가고 싶은 생각이 있어서, 급하게 아는 친구 한명 불러서 팀으로 하고 아이디어 30분만에 짜고 마감 1시간 남기고 기획서를 작성 후 신청서를 제출했습니다. 그 이후에 크리스마스가 아주 재미있어질꺼 같더라구요..ㅎㅎ 그래서 크리스마스동안 밖엔 눈이 오지만, 쓸쓸히 집에서 누워서 코딩을 했고 발표까지 끝났습니다. 그래서 한번 개발기를 적어보겠습니다!
개발 환경 세팅
일단 제가 필요한 것은 1. 서로간의 협업이 가능한 툴이어야하고 2. 여러 플러그인들이 쉽게 깔려야 하고 3. 어디서든지 접근이 가능하고 4. 사용이 쉬워야한다는 조건을 만족할 협업 툴을 찾다가 구름IDE를 사용해 개발하게 되었습니다. 구름IDE를 써보니까 서로간 작업할때 편하더라구요. 코드를 입력하면 상대방에게도 바로 보이고, 내가 어디에 입력하고있는지도 보여서 만족스럽게 썼으나…! 후술하겠습니다.. (기다려주세요)
그리고, 혹시나 팁을 드리자면.. 만약 구름IDE로 Discord.js를 사용하신다면 꼭 컨테이너를 생성하실때 “Node.js 버전 16.x로 업그레이드” 옵션을 체크해주셔야 Discord.js 13버전이 사용 가능합니다! 만약 이 부분을 체크 안하면 event 오류가 나며 사용 불가합니다. 이 부분때문에 1시간동안 삽질했습니다ㅠㅠ
이제 가장 중요한 DB를 세팅하는 문단이 등장할 타이밍인데.. 저희는 DB를 사용하지 않았습니다..! 그 사유는 mongoose를 설치하며 자꾸 오류가 날뿐더러 아이디/비밀번호를 세팅해야하는데 세팅하려 해도 오류나고 (아까 후술하겠다고 한 부분입니다.), 방법은 모르겠고.. 해서 MySQL로도 시도하다가 결국 DB가 없는 노DB로 개발했습니다. 여기서 어떻게 구현했는지가 많이들 궁금해하실거 같은데 이것도 후술…
기본 코딩
저는 Discord.js의 기본 문서를 보고 일단 ping를 입력하면 pong가 답변하는 코드부터 했는데요, 여기서도 많이 삽질했습니다. 이유가 뭐나면…
client.on('messageCreate', async (message) => {
여기서 client.on(‘messageCreate ~~ 에서 제가 본 강좌는 구버전이라 그런지 Create를 적어야한다는 것을 몰라서 안적었는데, 그래서 당연히 메세지 전송이 안되어 고민을 많이했었습니다. 결론적으로는 Create를 적어야 한다는 것을 깨닫고 적으니까 바로 되더라구요…ㅋㅋㅋ 그래서 아래 부분이 전송하는 부분의 전체 코드입니다.
client.on('messageCreate', async (message) => {
if (message.content === 'ping') {
message.channel.send('pong');
}
}
주가 변경 알고리즘 구현
이제 주가는 계속 변동해야하기 때문에 주가 변동 알고리즘을 구현해줘야 해서 어떻게 해줄까 고민을 해주고, 만들 주식을 생각했습니다. 카카ㅇ..가 아닌 캐캐오이고 어떻게 주가가 오르락 내리락 하나면, 캐캐오의 기본값은 800이코(단위는 이코입니다.) 이고, 여기서 얼만큼 오르고 내릴지를 랜덤으로 정한 뒤에 50% 확률로 오르고 내리게 해두었습니다. 그래서 이렇게 주가 변경을 구현했습니다.

setTimeout(function () {
//캐캐오 랜덤값 설정
kakaoMove = Math.floor(Math.random() * 20) + 8;
console.log('kakaoMove : ' + kakaoMove);
//오를까 내릴까 설정
kakaoIfDownOrUp = Math.floor(Math.random() * 2 + 1);
console.log(kakaoIfDownOrUp);
}, UpdateTime);
setTimeout(function () {
if (kakaoIfDownOrUp == 1) {
//주식값 오름
kakaoJusik = kakao + kakaoMove;
console.log('kakaoJusik : ' + kakaoJusik);
UpOrDownMessage = '▲ ';
} else if (kakaoIfDownOrUp == 2) {
//주식값 내림
kakaoJusik = kakao - kakaoMove;
console.log('kakaoJusik : ' + kakaoJusik);
UpOrDownMessage = '▼ ';
}
}, UpdateTime);
주식 구매/판매하기
일단 사용자가 주가 구매 [주가명]을 입력하게 했습니다. 여기에서 구매를 어떻게 구현할지가 중점인데, 뭐.. DB를 안쓰기로 했으니, Arrary와 변수를 사용해 구현을 해줘야합니다. 그래서 일단 구매를 정말로 하겠다고 사용자가 디스코드에 커맨드를 입력하면 Arrary에 [주식명]을 넣어주고(.push), 구매를 감지하는 변수에 true를 넣어주었습니다. 그리고 지갑의 돈을 wallet 변수로 설정해줘서, wallet 변수에서 캐캐오의 현재 주가 값을 빼서 wallet 변수에 다시 저장하는 방법으로 돈이 차감되는 것도 구현했습니다. 판매도 작동 방식은 이와 동일합니다. true가 false로 바뀌고 Arrary에서 [주식명]을 삭제했습니다. (.slice) 물론 자바스크립트는 코드를 위에서 아래로 읽어내려가므로 적절한 위치에 코드를 배치하고 코드가 섞인 만큼 주석처리도 빡세개 해줬습니다.
if (message.content === '이코야 구매 확인 캐캐오') {
console.log('정상 입력');
if (myjusik_1 == '캐캐오') {
const exampleEmbed = new MessageEmbed()
.setColor('#FE9A2E')
.setTitle('이미 캐캐오를 보유하고 있습니다.')
.setFooter('Make by SEONG Park(Dev) & Nayun(Plan)');
message.channel.send({ embeds: [exampleEmbed] });
} else {
//구매의사 저장
buy = '구매완료';
console.log(sell);
MyHave.splice('보유한 주식이 없습니다.');
//지갑에서 돈 차감
if (buy == '구매완료') {
if (wallet >= kakaoJusik) {
wallet = wallet - kakaoJusik;
const exampleEmbed = new MessageEmbed()
.setColor('#FE9A2E')
.setTitle('구매가 완료되었습니다.')
.setDescription(
kakaoJusik +
'이코가 지갑에서 차감되어 현재 보유 금액은 ' +
wallet +
'이코입니다.'
)
.setFooter('Make by SEONG Park(Dev) & Nayun(Plan)');
message.channel.send({ embeds: [exampleEmbed] });
//보유 주식 어레이 저장
MyHave[MyHave.length] = '캐캐오';
myjusik_1 = '캐캐오';
console.log(MyHave);
} else {
//구매 실패
const exampleEmbed = new MessageEmbed()
.setColor('#FE9A2E')
.setTitle('지갑에 돈이 부족하여 구매가 불가합니다.')
.setFooter('Make by SEONG Park(Dev) & Nayun(Plan)');
message.channel.send({ embeds: [exampleEmbed] });
}
}
}
}

지갑 구현하기
지갑 부분은 구현할때.. 되게 잔머리를 많이 썼습니다. 일단 지갑 코드는 맨 아래에 위치해있어야 위에서 변경사항을 다 반영하기 때문에 맨 아래에 두고, 보유중인 이코 부분은 그냥 변수를 출력하면 되는 부분이라 간단했는데 저 아래 보유 주식 부분이 깔끔하게 표시하기 위해서 되게.. 머리를 많이 굴려서 구현해줬습니다.
let MyHave = ['보유한 주식이 없습니다.'];
일단 저는 주식값들을 MyHave라는 어레이에 넣어놨습니다. 그리고 그 어레이의 초기값으로 보유한 주식이 없습니다를 넣어줘서 보유한 주식이 없는 채로 이코야 지갑을 입력하게 된다면 보유한 주식이 없습니다를 표시하게 했습니다. 그럼 여기서 만약 주식을 보유하면 ‘보유한 주식이 없습니다’부분을 어떻게 했나면,
if (message.content === '이코야 구매 확인 캐캐오') {
MyHave.splice('보유한 주식이 없습니다.');
}
splice 함수를 사용하여 구매를 한다면 주식을 저장하는 MyHave 어레이에서 초기값인 ‘보유한 주식이 없습니다’ 부분을 삭제해주었습니다.
그래서 이렇게 잔머리를 굴린 끝에 보유 주식 부분을 깔끔하고 예쁘게 구현했습니다 ㅎㅎ
난생 첫 해커톤 참여 후기
이번 2021 한디리 해커톤을 처음 참여해봤는데, 일단 첫 소감으론 되게 재미있었습니다. 말이 좀 이상한데.. 시간에 쫓기며 개발하는 맛이 있더라구요 (??) 앞으로 이런 해커톤이나 코딩 대회에 자주 참여할 생각입니다.