⚠ 참고
- 이미 Notion에 정리한 내용이지만, 이 내용을 참고하여 시행착오를 겪지 않았으면 좋겠습니다.
- 혹은 좋았던 부분은 참고하여 더 쉽게 진행하길 바랍니다.
- 최대한 기술적인 부분은 제외하고 프로젝트가 진행되었던 과정과 느낀 점 위주로 작성하였습니다.
- Github Link
실제 개발 기간은 객관적으로 길지 않았다. 하지만 초기 개발환경 세팅과 개발 계획을 세우는 부분에서 생각보다 고려할 부분도 많았고, 프로젝트가 끝난 후 돌아봤을 때 전체 기간의 절반이나 차지하고 있다는 것을 알게 되고 이 부분 또한 정리해 보려고 한다.
이번 프로젝트를 하면서 특히 마음에 들었던 Tool은 바로 Docker app
이었다.
많이 쓰이는 기본적인 도커 명령어들을 클릭으로 대체할 수 있다는 점과 직관적으로 눈에 보이는 점이 초보자의 입장에서 너무 좋았다.
세부적인 내용은 아래를 참고.
Vscode, docker app , postman, mysqlworkbench
MacBook Pro (Retina, 13-inch, Early 2015), 작업 환경은 container 내에서 remote로 작업.
처음 서비스를 기획하게 된 계기는 수강신청할 때마다 들어가게 되는 '개설교과목 정보 사이트'의 UI가 불편했고, 느린 검색 속도 때문이었다.
프런트 파트에서는 필요한 정보만 담아서 가로 스크롤을 없애고 한 눈에 정보가 들어올 수 있도록, 백엔드 파트는 검색 속도를 빠르게 하고, 담아놓기한 정보가 업데이트 될 경우 알람을 보내는 기능을 추가로 구현하기로 했다.
이 중 내가 맡은 파트는 크롤러를 제외한 파트였다.
다른 팀원이 파이썬으로 크롤링을 한 경험이 있어서 선택하게 되었다.
그리고 진입 장벽이 낮고, 많은 자료가 있는 언어를 선택해야 했기에 자연스럽게 파이썬이 적합하다고 생각했다고 한다.
처음에는 node.js
와 Python
둘 중 하나를 선택해야 했는데, 크롤링 파트를 파이썬으로 진행하기도 하고, 파이썬을 공부 목적으로 한 번 사용해 보는 것도 좋을 것 같아서 파이썬을 백엔드 언어로 정하게 되었다.
파이썬 웹 개발 프레임워크는 크게 Django
와 Flask
가 있는데,
Django
는 좀 더 무겁고 러닝커브가 있다고 알고 있고, Flask
가 공부할 때 더 좋고 빠르게 구축할 수 있다고 한다.
그래서 바로 Flask
를 선택하게 되었다.
크롤링할 데이터가 테이블 형태로 이루어져 있어 똑같이 옮겼을 때 직관적으로 이해하기 쉽다고 생각했다. 또한 생성될 user 테이블과 과목 테이블에 관계를 부여해서 즐겨찾기 테이블을 쉽게 구현하는데 좋다고 생각했다. 그리고 무엇보다 무료이고, 그에 따라 참고할 수 있는 자료가 많다.
도커를 사용하려 했지만, 도커 컨테이너 형태로 Mysql Server를 구축하는 것은 위험한 방식일 수 있다는 글을 읽었다.
AWS RDS를 Freetier로 이용하면 비용 부담 없이 안정적이게 db 서버 운용이 가능하기에 RDS를 택했다.
사실 욕심이었다.
그러나 단순히 결과물보다 공부 목적도 있었기에 선택하게 되었다.
예전부터 도커에 대해 궁금증이 있었고, 로컬 개발 환경과 배포 환경을 일치시키는 데에서 매력을 느꼈다.
EC2 - 둘 다 사용 경험 있고, 가장 보편적이기 때문. 사실 더 좋은 다른 방안을 쓰려면 거기에 따른 러닝커브가 존재하기 때문에 급한 상황에서 시도해보지 못했다.
→ 학교 동아리 서버로 docker container를 구동하려 시도했지만, super user 권한이 있어야 했다. Super user 권한을 받기까지 시간이 지체되었다. 또한 관리적인 측면에서 AWS EC2 console 또는 Jupyter 환경을 사용하는게 더 간편했다. 비용적인 측면은 물론 학교 동아리 서버가 가성비가 좋겠지만, AWS Freetier 계정으로도 큰 부담없이 서버를 구축 할 수 있어서 AWS EC2를 선택했다.
먼저 도커파일을 만들어 가상환경에서 작업하기 전에 파일 디렉토리를 작성해야 했다.
How to structure a Flask-RESTPlus web service for production builds
이 링크를 참고해서 파일 디렉토리를 구성했다. 정말 좋은 글이라 따로 정리도 할 예정이다.
.
├── app
│ ├── __init__.py
│ ├── main
│ │ ├── config.py
│ │ ├── controller
│ │ │ └── __init__.py
│ │ ├── __init__.py
│ │ ├── model
│ │ │ └── __init__.py
│ │ └── service
│ │ └── __init__.py
│ └── test
│ └── __init__.py
├── manage.py
└── requirements.txt
위와 같이 디렉토리 구조를 작성하게 되었다.
개발환경을 위한 도커파일은 다음과 같이 작성하게 되었다.
FROM python
# Install requirements
RUN pip install --no-cache-dir --upgrade pip
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Add source code
ADD app /home/app
ADD migrations /home/migrations
ADD requirements.txt /home
ADD manage.py /home
WORKDIR /home
# Set environment variables
ENV FLASK_APP=manage.py
# ENTRYPOINT
ENTRYPOINT python manage.py run
사용자의 정보가 담겨 있는 user테이블과 과목 정보가 담겨 있는 subject테이블은 Many-to-many relationship이다. 위에서도 언급했듯이 즐겨찾기 테이블(user_subject 테이블)은 primary key를 foreign key로 참조하여 만들어야 한다.
그러나 새로운 학기가 시작될 경우 subject 테이블이 새로 생성이 되기 때문에 그 때마다 관계를 새로 정의해주어야 하는 문제가 발생했다. 동적으로 관계를 정의할 수 있다면 좋겠지만, 그 방법을 실패했다.
그리고 subject 테이블이 새로 만들어짐에 따라 join 테이블도 함께 늘어나게 되므로, 회원의 즐겨찾기 과목을 조회하기 위해서 탐색해야 하는 테이블의 개수도 늘어나게 되는 문제가 생긴다.
그래서 이러한 문제를 다음과 같이 해결했다.
정석적인 join의 방법이 아닌 '이메일', 'subject_id' 두가지 필드를 정의해 참조용 key로 사용했다. subject_id는 직접 만든 과목에 대한 식별자다.
학년도-학기-과목코드-분반
subject_id example
21-2-MAT1002-01
참조 과정은 다음과 같다
크롤러 파트는 내 파트가 아니어서 패스하도록 하겠다. 자세한 내용은 여기를 참고.
프론트와의 지속적인 회의를 통해 필요한 api에 대한 리스트업을 하고 개발을 진행했다.
마주쳤던 이슈들은 대략 다음과 같다.
Queue Pool 이슈
→ Flask-SQLAlchemy를 사용했는데,
코드 상에서 session.close()를 해주지 않아 커넥션 반납이 안 됐음
Sleep Connection 이슈
→ 일부 connection들이 Sleep 상태로 머물러 있어 누적시 rds가 터지는 이슈 (해결 방법)
이메일 발송 시도 시 Google에서 막는 이슈
→ 구글 측에서 막은 보안 이슈로, 발신 계정 로그인 시 해결
MysqlDb 패키지에는 Pool_recycle 셋팅이 불가능한 이슈
→ subject 조회시 사용된 패키지였는데 그냥 sqlAlchemy 패키지로 통일
→ 대신 교과목 조회시 속도가 살짝 저하되었다
교과목 불러오는 api 호출시 속도 이슈
시간 검색옵션 기능 api 구현 중 이슈
대부분은 요일이 달라도 수업시간은 같았으나, 수업시간이 다른 과목도 존재했다
→ 기존의 DB부터 문제가 있음(예외 고려 못했음)
→ 일단 db에 새로운 필드를 추가해서 예외 상황도 처리했다
시작시간, 종료시간 사이의 과목을 select한 방법
대부분은 프론트에서의 이슈가 많았지만, 백엔드에서도 추가하거나 수정한 사항들이 있다. 크게 서너 가지가 있지만 그 중 가장 큰 이슈는 토큰 인증 문제였다.
백엔드 api를 만들 때는 토큰을 넘겨받지 않을 경우를 고려하지 않았다. 유효한 토큰인지, 아닌지만 검증하고 아예 받지 않을 때는 고려하지 않고 작업을 했는데, 이게 프런트와 만날 때 문제가 되는 일이 있었다.
백엔드 파트는 무엇보다 분기처리와 가능한 모든 경우의 수를 생각하고 짜야 하는 것이 중요한 것 같다.
추가적으로 갑자기 필요한 api가 생겨서 급하게 만들기도 했는데, 이미 전체적인 틀이 있어서 그렇게 많은 시간이 들지는 않았다.
약 1달간의 프로젝트가 끝났다. 프로젝트를 시작하기 전과 지금을 비교하면 정말 많이 배우고 성장했다. (Docker, Flask, MySQL 전부 다 처음 써 봤으니까) Notion
에 정리한 내용들만 봐도 정말 양이 많다.
프로젝트는 프런트3, 백엔드2로 진행했는데 처음에는 내가 맡은 파트를 잘 모르는 부분도 많고 부족해서 1인분을 못하지는 않을까 하는 걱정도 있었지만, 별 탈 없이 잘 마무리되어서 기분이 좋다.
정말 별 거 아닌 오류 때문에 4~5시간을 보내기도 했고, 배포 전 3일동안은 새벽 3시까지 버그 수정을 하기도 했고, 함께 진행한 승우와 스터디룸에서 코딩하다 나와 순대국밥을 먹으며 오늘은 CORS
가 날 화나게 했다거나 분기 처리 하나를 잘못 해서 2시간을 다시 코딩했다거나 등등 시시콜콜한 이야기를 나누었던 것들이 벌써 추억으로 자리잡게 된 것 같다.
한 달간 압축적으로 빠르게 성장하신 것 같아 대단합니다😎