본문 바로가기
daily/project

동아리 회원 관리 페이지 (어드민 페이지 / Admin Page)

by 황보재윤 2024. 8. 14.

안녕하세요 😊

이번 여름방학 시작과 동시에 실시하게 된 작은 프로젝트 하나를 소개드리고자 합니다.

FE / BE 개발이 처음이라 많이 서툴지만 '재미있는거 만들었구만' 같은 관점으로 봐주시면 감사하겠습니다!

 

프로젝트 시작 계기

 

2024년 1학기 모 중앙동아리에서 임원직을 맡고 있던 저는 학기 말에 큰 위기를 맞습니다. 바로 동아리 내 부서에서 해야 할 일을 제때 하지 못해 회원들의 활동 인정 신청서가 제출되지 않았던 것입니다. 그래서  평소 활동 인정 신청서 제출할 때 필요한 서류가 수작업이고 사람이 하는 일이다 보니 오류가 많다고 생각해 "이 모든 것을 자동화하고 클릭 몇 번으로 쉽게 관리할 수 있도록 만들어보자!"라는 취지로 시작하게 되었습니다.

 

프로젝트 설계

 

처음 프로젝트를 시작할 때 가장 막막했던 것은 바로 프로그래밍 언어 선택이었습니다. 왜냐하면 저는 할 줄 아는 프로그래밍 언어가 파이썬 밖에 없었고, 웹과 서버를 설계하기 위해서는 무조건 JS를 할 줄 알아야 한다고 생각했기 때문입니다. 하지만 파이썬의 프레임워크 중 Flask라는 웹 프레임워크를 사용하여 웹사이를 구축할 수 있다는 것을 알게 되었고, 플라스크와 학과 데이터베이스에서 배운 MySQL을 사용하여 FE / BE 가 통합된 애플리케이션을 만들기로 계획했습니다.

프로젝트 아키텍처

Member Page는 현재 진행형이므로 추 후에 포스팅하겠습니다.

 

필수 기능 계획 및 배포

 

프로젝트를 시작하면서 생각한 기능은 크게 두 카테고리로, 회원 관리기능활동 관리기능입니다. 이 두 기능들을 세부적으로 나누게 된다면 

 

회원 관리 기능

  • 회원 등록: 새로운 회원 정보를 DB에 추가
  • 회원 조회: 등록된 모든 회원 또는 특정 회원의 정보 조회
  • 회원 정보 수정: 회원의 정보를 수정
  • 회원 삭제: 더 이상 활동하지 않거나 입회비를 내지 않은 회원 삭제
  • 블랙리스트 관리: 활동 신청 후 불참하는 회원을 조회하여 다음 활동 참여를 제한

활동 관리 기능

  • 활동 추가: 새로운 활동을 등록하고, 활동명, 날짜, 참여 인원 등의 정보 등록
  • 활동 조회: 등록된 모든 활동 또는 특정 활동의 정보 조회
  • 활동 수정: 활동 정보 수정
  • 활동 참여 현황 조회: 각 활동에 참여한 회원 목록 조회
  • 활동 참여 여부 수정: 회원의 활동 참여 여부 수정 (출석부 개념)
  • 활동 참여자 팀 분배: 활동 참여자를 팀으로 나눕니다. (성별 고려 가능)

그리고 이 모든 데이터를 담당하게 될 MySQL에 PyMySQL 모듈로 연결하여 각 기능을 수행하게끔 계획했습니다.

 

디자인

디자인은 Figma 를 사용하여 디자인하였고, Plugins 중에 완성된 디자인을 HTML과 CSS로 내보내 주는 것이 있어 이를 사용하여 HTML을 생성하였습니다. 하지만 이는 전체적인 디자인의 프레임을 추출해 줄 뿐, input 태그와 button 태그들은 추출해주지 못하고 모든 디자인된 항목들을 div 태그로 추출해 줄 뿐입니다. 그렇기에 이를 알맞은 태그로 변환하는 과정에서 CSS에 문제가 생기기도 하고 생각보다 간단하지만은 않은 작업이었습니다.

 

완성된 관리자 페이지 모습

 

초기에 계획했던 모든 기능을 구현하는 데에는 크게 문제없이 원활하게 수행했던 것 같습니다. 하지만 제가 간과했던 것이 있었으니 바로 웹애플리케이션의 배포였습니다. 무료 호스팅 서비스를 해주는 곳은 많지만 Flask를 호스팅 해주는 곳은 많지 않았고, Flask 배포로 유명한 Heroku는 전격 유료화 선언, Ngrok은 쉽게 터널링이 가능하지만 도메인 연결 시 유료, 이미 사용해 버린 AWS 1년 무료 서비스.. 결국 Vercel로 호스팅 하기로 선택했습니다. 하지만 이 또한 어려웠는데요, Vercel에서는 Flask를 공식 지원하지 않기 때문이었습니다. 하지만 구글링으로 찾아낸 결과 root dir에 Vercel.json 파일을 만들어 주면 Vercel 배포 시 이를 인식하여 app.py를 실행시켜 준다는 것을 알았습니다.

 

## Vercel.json

{
    "version": 2,
    "builds": [
      {
        "src": "app.py",
        "use": "@vercel/python"
      }
    ],
    "routes": [
      {
        "src": "/(.*)",
        "dest": "/app.py"
      }
    ]
  }

 

## Hearder 은 이제 못 넣더라고요.. ##

 

이와 관련해서 공식 문서도 살펴보았지만 얄팍한 저의 지식으로는 이해하기 어려웠습니다. 그래서 위와 같이 설정해 두고 배포가 되길래 그 이후로는 건들지 않고 있습니다. 

 

Vercel에서 웹애플리케이션을 배포 후 문제가 있었던 동아리 부서의 부원에게 부탁하여 테스트를 진행하였고, 데이터베이스에 회원의 성별을 0과 1로 해서 그대로 출력되던 것을 '남', '여'로 바인딩하여 출력해 달라는 것을 부탁받았고, 간단히 피드백을 수행 하였습니다. 

 

이후 웹애플리케이션 개발에 경험이 많은 친구에게 애플리케이션의 아키텍처에 대한 피드백을 받기 위해 비공개 레포지토리에 초대해 줬습니다. 돌아오는 말은 "우와 어떻게 이런 생각을...!". 물론 좋은 뜻이 아니었습니다. 

 

문제점

  • FE / BE 통합으로 인한 안정성 문제
  • 기능 수행마다 생성되는 DB 커서로 인한 성능저하

이 문제점들을 해결하고자 저는 Flask로 REST API를 구현하고자 했고, flask_restful 라이브러리를 사용하여 api를 배포하고자 했습니다. 생각보다 flask_restful을 사용하는 것은 어렵지 않았고, 원래 있던 코드들을 가져와서 api로 분리만 하면 되는 작업이다 보니 구축 시간은 많이 걸리지 않았습니다. 또한 DB의 커서문제도 커서를 재활용하는 방법으로 바꾸어 성능저하를 피해 갔습니다. 그렇게 FE와 BE가 나뉘게 되자 엄청난 속도차이가 났고, 제 마음을 설레게 하기엔 충분했습니다.

 

 

 

그렇게 필수기능 개발을 마치고 FE와 BE까지 분리하고 나서 이 관리자페이지를 사용할 임원들을 위해 '활동 참여자 팀 분배'와 같은 편의기능 개발을 하기로 마음먹었습니다.

 

편의기능 개발

 

추가한 편의기능

  • 회원별 활동 내역 보고서: 특정 회원의 모든 활동 내역을 Excel 파일로 다운로드
  • QR 코드 생성: 각 활동에 대한 QR 코드를 생성하여 참여 확인
  • 예약 시스템: 회원들이 활동에 미리 참여를 예약할 수 있는 기능 제공
  • 카카오톡 알림 기능(최종 관리자용): 새로운 활동 추가, 참여 마감 등 중요한 이벤트에 대한 카카오톡 알림을 제공

회원별 활동 내역 보고서는 회원들의 활동 시간 인정 서류를 작성할 때 꼭 필요한 것입니다. 원래는 활동자 명단을 종이로 뽑아서 본인의 이름에 서명을 하는 식으로 참여자를 구분하고, 참여자들의 성명과 개인정보를 하나씩 엑셀파일로 작성하였지만 DB를 사용하는 지금은 참여자들만 자동으로 추려 제출 형식에 맞게 Excel 파일을 작성하도록 하였고, 이는 Openpyxl 라이브러리로 구현하였습니다.

@app.route('/download-excel/<date>/<id>')
def download_excel(date, id):
    response_data = session.get('response_data')

    if response_data:
        file_path = './form.xlsx'

        # 기존 파일 열기
        workbook = openpyxl.load_workbook(file_path)

        # 특정 행(예: 5번째 행)부터 데이터 추가
        start_row = 4
        add_data_to_excel(workbook, start_row, response_data)

        # 엑셀 파일을 메모리 내의 바이너리 스트림에 저장
        output = io.BytesIO()
        workbook.save(output)
        output.seek(0)

        session.pop('response_data', None)

        # 파일을 응답으로 반환
        return send_file(
            output,
            as_attachment=True,
            download_name=f"{date}_활동명단.xlsx",
            mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        )
    
    return render_template('404.html')

참여자들은 관리자가 열어둔 예약 가능 활동을 직접 선택하여 예약을 할 수 있습니다. 또한 활동 시작 시 관리자가 해당 날자의 활동 번호를 통해 생성한 QR코드를 스캔하여 학번을 입력함으로써 본인이 활동에 참여했다는 것을 인증할 수 있습니다. 물론 QR코드를 스캔하고 학번을 입력할 때 부정행위를 방지하기 위한 가능한 모든 예외처리를 하였습니다. QR 코드 생성 시 URL 이 필요합니다. 하지만 관리자 페이지에서 생성하여 배포 시 관리자 페이지의 도메인 주소 노출의 우려가 있음으로 QR코드 생성을 위한 Vercel App을 하나 더 만들었습니다. QR코드 생성은 qrcode 모듈로 간단하게 생성할 수 있습니다.

관리자 페이지에서 활동을 생성하거나, 회원이 회원가입을 하거나, 활동 예약을 오픈할 때 등 관리자 페이지에서 일어나는 모든 행위는 그 데이터와 함께 최종 관리자(동아리장)의 카카오톡으로 전송되도록 구성하였습니다. 처음에는 카카오톡 채널을 생성하여 모든 임원들이 메시지를 받게 하도록 구성하려 했지만, 카카오톡 채널 메시지 전송 무료 횟수가 없어짐에 따라 KakaoTalk Develops에서 애플리케이션 생성 후 REST API를 발급받아 '나에게 보내기' 기능으로만 카카오톡 메시지를 전송받게 해 두었습니다.

 

+ 추가적으로 관리자 페이지의 URL이 노출되어도 무단으로 사용하지 못하게 로그인 기능을 구현하였습니다. 먼저 관리자 페이지에 접근하려면 임원이어야 합니다. 이를 위해 DB에서 회원들의 아이디와 비밀번호가 저장되어 있는 테이블에서 임원들만 빼서 뷰를 만들었고, 이를 참조하여 일반 회원들은 로그인 시도 시 본인의 아이디와 비밀번호를 알맞게 입력해도 로그인이 거부되도록 만들었습니다.

 

+ API의 버전관리를 위해 Flask의 Blueprint를 사용하여 관리자 페이지와 회원 페이지에서 쓰는 API를 분리시켜 놨습니다.  이렇게 분리시켜 놓으니 API의 형상관리 또한 쉬워지는 효과가 있었습니다.

 

+ BE를 지인의 AWS 아이디를 빌려 EC2에 구축하였습니다.

 

 

 

사진 출처

Flask : https://justkode.tistory.com/10
MySQL : https://velog.io/@leo3179/MySQL-%EB%A6%AC%EB%B7%B0
Vercel : https://www.hatimeria.com/services/vercel
Flask-RESTful API : https://ubeezy.netlify.app/flask-rest-api/
Openpyxl : https://hogelog.com/python/openpyxl-excel-chart-1.html
qrcode : https://www.geeksforgeeks.org/python-generate-qr-code-using-pyqrcode-module/
kakao developers : https://developers.kakao.com/tool/resource/developers

 

 

 

'daily > project' 카테고리의 다른 글

대구가톨릭대학교 학사공지 디스코드 봇  (0) 2024.03.15