Post

디스코드 뮤직 봇 개발 (3)

디스코드 뮤직 봇 개발 (3)

출석체크 기능을 사용하다 보니 자정인데도 출석했다고 인식하는 것을 보고 직감적으로 한국 표준 시간대가 설정되지 않았다고 생각했다. 이를 적용하고자 코드를 변경하려고 했고, 그 전에 CI/CD 및 임시배포방법인 tmux 대신 systemd 로 바꾸고자 생각했다.

이에 먼저 다시 기존 설정을 확인해봤는데 이상한 점을 하나 찾았다.

가상환경 디렉토리 구조 확인

ls -la meloD_venv/bin/

현재 실행 중인 프로세스에서 python 경로 확인

ps aux | grep python

를 한 결과 2가지 특징을 발견했다.

  1. 가상환경 구조 : meloD_venv/bin/ 디렉토리가 존재하지만, python3가 시스템의 /usr/bin/python3로 심볼릭 링크되어 있는 특이한 구조였다.
  2. 현재 실행 프로세스: 프로세스 목록을 보면 python3 main.py로 실행 중이며, 가상환경 경로를 명시적으로 사용하지 않았다.

그래서 다시 제대로 틀을 잡고자 했다.

  1. 현재 필요한 패키지 목록 저장
    • pip freeze > requirements.txt
  2. 기존 가상환경 제거
    • rm -rf meloD_venv
  3. 새 가상환경 생성
    • python3 -m venv meloD_venv --system-site-packages
  4. 가상환경 활성화
    • source meloD_venv/bin/activate
  5. 필요한 패키지 설치
    • pip install -r requirements.txt

잘 설정해주었다.

다시 본론으로 돌아와서, systemd 서비스 설정을 해보자.

Systemd 서비스 설정

  1. GCP 인스턴스에 SSH로 접속
  2. 봇 코드 디렉토리로 이동 cd /path/to/your/discord/MeloD

  3. systemd 서비스 파일 생성 sudo nano /etc/systemd/system/meloD.service

  4. 내용을 입력 (실제 경로와 사용자명으로 수정) ```cmd [Unit] Description=Discord Bot Service After=network.target

[Service] User=YOUR_USERNAME WorkingDirectory=/path/to/your/bot ExecStart=/usr/bin/python3 /path/to/your/bot/main.py Restart=always RestartSec=10 Environment=”PATH=/path/to/your/venv/bin:$PATH”

[Install] WantedBy=multi-user.target

1
2
3
4
5
6
7
8
![](/assets/posts/9523fd3c0ff9b7b2537cd5e88e8a57146994305c5b1a9d5bc1b4658e40ca51c1.png)


5. 서비스 활성화 및 시작
```cmd
sudo systemctl daemon-reload       # systemd 설정 파일을 새로 읽어들인다. 서비스 파일을 새로 만들거나 수정한 후에 필요한 명령어
sudo systemctl enable meloD  # meloD 서비스를 시스템 부팅 시 자동으로 시작되도록 설정
sudo systemctl start meloD   # meloD 서비스를 즉시 시작
  1. 상태 확인 sudo systemctl status discord-bot 잘 작동된다!

서비스가 자동으로 시작되는지 확인까지 해주었다.

GitHub Actions CI/CD 설정

  1. GCP 인스턴스에 SSH 키 설정
    1
    2
    3
    
    # 로컬 컴퓨터에서 실행
    ssh-keygen -t rsa -b 4096 -C "github-actions"
    # (키 저장 위치와 비밀번호 입력)
    
  2. 공개 키를 GCP 인스턴스의 authorized_keys에 추가 ```

    로컬에서 공개 키 확인

    cat ~/.ssh/id_rsa.pub

GCP 인스턴스에서 실행

echo “복사한_공개키” » ~/.ssh/authorized_keys

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
3. GitHub 저장소에 비밀 키 추가:

- GitHub 저장소 → Settings → Secrets and variables→ New repository secret
- 이름: `SSH_PRIVATE_KEY`, 값: 비밀 키 내용(~/.ssh/id_rsa 파일의 내용) ; 주석과 줄바꿈까지 그대로 복사
- 이름: `HOST`, 값: GCP 인스턴스 IP
  - `curl -s ifconfig.me` 로 확인
- 이름: `USERNAME`, 값: GCP 사용자 이름
- 이름: `TARGET_DIR`, 값: 봇 코드 디렉토리 경로
  - ex) /home/nowalex322/MeloD
  
![](/assets/posts/18c01515b6ec58bc93591759875ccb01e4040bdb08f5fdd3f1f3dfd599b85d1b.png)


4. `.github/workflows/deploy.yml` 파일 생성:
GitHub Actions Workflow (deploy.yml)
```yml
name: Deploy to GCP

on:
  push:
    branches: [ develop ]  # 푸시될 브랜치를 지정, 필자는 develop 브랜치에 푸시될 때 실행

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
      
    - name: Setup SSH
      uses: webfactory/ssh-agent@v0.5.4
      with:
        ssh-private-key: $
        
    - name: Add to known hosts
      run: |
        mkdir -p ~/.ssh
        ssh-keyscan -H $ >> ~/.ssh/known_hosts
        
    - name: Deploy to GCP
      run: |
        rsync -avz --delete ./ $@$:$
        
    - name: Restart meloD Service
      run: |
        ssh $@$ 'sudo systemctl restart meloD'

워크플로우가 잘 작동중이다!


한국 시간대 수정 적용

  1. 로컬에서 코드 수정
    • pip install pytz 먼저 실행
    • Discord 봇 코드에 시간대 관련 수정 적용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 필요한 import 추가
import pytz

# AttendanceCommands 클래스의 check_attendance 메소드 수정
@app_commands.command(name='출첵', description="출석체크")
async def check_attendance(self, interaction: discord.Interaction):
    user_id = str(interaction.user.id)
    
    # 한국 시간대 적용
    korea_tz = pytz.timezone('Asia/Seoul')
    today = datetime.now(korea_tz).strftime('%Y-%m-%d')

    conn = sqlite3.connect('attendance.db')
    c = conn.cursor()

    # 오늘 출석했는지 확인
    c.execute('SELECT * FROM attendance WHERE user_id = ? AND attendance_date = ?', (user_id, today))
    if c.fetchone():
        await interaction.response.send_message(f'{interaction.user.mention} 이미 오늘은 출석체크를 하셨어요!')
        conn.close()
        return

    # 연속 출석 확인 - 여기도 수정
    yesterday = (datetime.now(korea_tz) - timedelta(days=1)).strftime('%Y-%m-%d')
    c.execute('SELECT streak, total_days FROM attendance WHERE user_id = ? ORDER BY attendance_date DESC LIMIT 1', (user_id,))
    result = c.fetchone()
    
    # 나머지 코드는 동일...
  1. 수정한 코드를 GitHub에 push

  2. GitHub Actions가 자동으로 코드를 GCP에 배포하고 서비스를 재시작

This post is licensed under CC BY 4.0 by the author.