- 개발자를 위한 사이드 프로젝트 공유 플랫폼 서비스 (with. 커피챗을 곁들인)
- 주제 : 사이드 프로젝트 공유 플랫폼 (with. 커피챗)
- 기간 : 2022.07.07 (목) ~ 2022.08.04 (목)
- Team : 김선민 (Github), 김민기 (Github), 박재현 (Github), 황신혜 (Github)
- FE Repo : Sidepro-FE
- 시연 영상 : 링크
- main : LocalHost 실행 branch
- publish : EC2 Hosting 실행 Branch
┌─SIDEPRO
├── sidepro // project
│ ├── urls.py // base url
│ ├── asgi.py // chat route setting
│ ├── settings.py // setting
│ └── ...
├── project // app
│ ├── models.py // DB Model - project, comment
│ ├── views.py // View Functions
│ ├── serializers.py // Serializers
│ ├── tests.py // Test Code
│ ├── pagination.py // pagination
│ └── ...
├── chat // app
│ ├── models.py // DB Model - status, room, chat
│ ├── views.py // View Functions
│ ├── serializers.py // Serializers
│ ├── tests.py // Test Code
│ ├── constants.py // Constants
│ ├── consumers.py // Consumer
│ ├── routung.py // Routing
│ └── ...
├── ai // app
│ ├── views.py // View Functions
│ ├── serializers.py // Serializers
│ ├── tests.py // Test Code
│ ├── cron.py // Crontab
│ └── ...
├── user // app
│ ├── models.py // DB Model - user, userprofile, ...
│ ├── views.py // View Functions
│ ├── serializers.py // Serializers
│ ├── tests.py // Test Code
│ ├── constants.py // Constants
│ └── ...
├── _utils
│ ├── auto_clean_pyc_migrate.py // Migrations
│ ├── auto_cleancode.py // Run black, isort
│ ├── auto.runserver.py // Run Server
│ ├── query_utils.py // Query Debuger
│ └── set_basedb.sql // Base DB Data
│
├── .github\workflow
│ └── be_cicd.yml // CI/CD PIPE LINE
│
├── log
│ └── a.txt // Save crontab log
│
├── nginx
│ ├── nginx.conf // nginx
│ └── Dokerfile // nginx Dokerfile
│
├── Dockerfile // Dokerfile
├── docker-compose.yaml // Doker-Compose
├── **manage.py**
└── requirements.txt
- 기본 vaildation & 로그인 JWT Token 사용
- 프로젝트 목록 조회 (Django-Pagination)
- 프로젝트 등록 (Toast UI Editor / Image Preview)
- 프로젝트 검색, 정렬 (기술 스택 기반 검색 / 조회순, 최신순, 인기순 정렬)
- 프로젝트 상세 조회 / 수정 / 삭제 (댓글 CRUD, 북마크 ON/OFF)
- 채팅 Room 목록 (조회, 생성, 삭제)
- 채팅 소켓 연결에 따른 Room Status 관리 (Running, Pending, Stop)
- 채팅 유저 프로필 조회
- 실시간 채팅
- Websocket & Django Channels 이용
- Daphne ASGI 서버 => WS 프로토콜 요청 처리
- Redis를 이용한 실시간 메시지 전송
- User-Based 추천 시스템 ("나와 비슷한 기술 스택을 보유한 유저의 프로젝트" 추천)
- Django-CronTab을 이용한 유사도 계산 부하 방지 (1분마다 Query & 유사도 계산)
- 스토리
-
- CronTab이 1분마다 나와 유사한 기술 스택 보유한 유저간의 유사도 계산
-
- 유사도 계산 파일 csv 저장
-
- 사용자 요청시 해당 파일 읽어서 추천 프로젝트 결과 출력
-
- 마이(유저) 프로젝트 모아보기
- 북마크한 프로젝트 모아보기
- 유저 프로필 정보 조회
- 내 프로필 정보 조회 수정, 삭제
- AWS EC2 내 container 기반 Publish 배포
- AWS S3 FE 버켓 2개 이용하여 각각 정적 웹 호스팅, 업로드 파일 저장소
- AWS IAM 부여하여 Infra Team 공동 관리
- AWS RDS 이용하여 DataBase 속도와 안정성 확보
- AWS ROUTER 53 도메인 등록하여 가독성, 접근성 증가
- GitActions 이용한 CI-CD 자동화 구축
- Nginx : Proxy 역할
- Gunicorn : Django 배포용 WSGI서버 http protocol 요청 처리 (worker : 2)
- Daphne : Django 배포용 ASGI서버 WebSocket portocol 요청 처리
🛠 서비스 비대응시간 최소화 브랜치 전략
- EC2 단일 서버에서 서비스 대응 중 Bug가 발견되어 수정 소요가 발생
- 재빌드 및 재배포 과정에서 서비스 중단 시간이 생기게 됨
- Bug 수정 후 재배포 간 추가 Bug 발생으로 빌드 실패 => "Bug 발생 + 오류 DEBUGGING 시간 + 재빌드 시간" 등 서비스 중단 시간이 계속 늘어나게 됨
- 단일 EC2에서 서비스를 대응 및 수정 사항을 직접 반영하다보니, 개발(수정)시 서비스가 중단되야 되는 상황 발생
- CD(Continuous Deployment)과정에서 Git Main Branch => Publish Branch로 배포하는 Branch 전략에 문제가 있다고 판단
- Dev Branch 배포 서버 추가 (개발자용 배포 서버)
- 기존 배포 전략 : Main(개발, local)⇒ Publish (서비스, 배포O)
- 수정 후 배포 전략 : Main(개발, local) ⇒ Development (개발, 배포O) ⇒ Publish (서비스, 배포O)
- Dev Branch에서 최종 완료 확인 후 Publish 로 배포
🛠 동시성 문제 (Concurrency) 발생
게시물 상세 조회시 여러명(N)이 동시에 접근하였더니, 조회수가 N이 오르지 않고, N 미만의 숫자가 오름 (조회수, 북마크 수, 댓글 수 등에 동시성 이슈 확인)
PostgreSQL은 기본적으로 READ COMMITTED의 Transaction 격리 환경을 가지고 있어, 한 유저의 Transaction이 값을 수정 중이더라도, 다른 유저의 Transaction이 접근 가능하고, commit 되기 전, 순차적으로 commit에 더하는 것이 아닌, 이전 commit 값을 같이 바라보고 같은 값으로 수정하게 되는 현상 발생
Django에서 제공해주는 F Method 활용하여 Python 메모리 로드 없이 DB단에서 즉석 반영하게 함. 총 3건 (조회수, 북마크 수, 댓글 수) 에 적용하였고, Curl 메소드로 테스트시 정상적으로 실행되는 것 확인.
🛠 Query 최적화
- 지연로딩을 사용할 경우 연관관계가 있는 엔티티가 필요한 경우라면, Select 쿼리를 여러번 수행해서 엔티티를 조회하게 되므로 따라서 성능에 문제가 생길 수 있다. select_related, prefetch_related를 사용하여 즉시로딩 (Eager Loading)하여 쿼리를 최적화하였습니다.
- 통신 도중 연결이 끊긴다거나 오류 발생 시 여러개의 insert, update 쿼리가 발생될 때 중간 과정에 끊길 경우 DB데이터에 대한 신뢰성이 깨질 수 있기 때문에 @transaction.atomic을 이용해서 SAVEPOINT를 이용하여 모든 쿼리가 성공했을 때 DB에 반영되도록 하게 만들었습니다.
블로그 정리내용(https://psb6604.tistory.com/69)