- 게임의 구조를 알아보는 프로젝트입니다.
- JWT토큰을 사용하여 회원가입, 로그인, 로그아웃 기능을 제공합니다.
- redis queue를 이용해 특정 게임을 여러명의 유저들이 함께 사용할때 충돌이 일어나지 않게 설계하였습니다.
- 레이드의 시작, 종료, 레이드 상태조회, 랭킹조회등을 제공합니다.
- 랭킹조회시 redis 캐싱기능을 이용해 데이터베이스로의 직접적인 호출을 최소화 하였습니다.
과제소개
-
유저 생성
-
유저 조회
-
보스레이드 상태 조회
-
보스레이드 시작
-
보스레이드 종료
-
랭킹 조회
요구사항
-
유저 생성
- 중복되지 않는 userId를 생성
- 생성된 userId를 응답
-
유저 조회
- 해당 유저의 보스레이드 총 점수와 참여기록 응답
-
보스레이드 상태 조회
- 보스레이드 현재 상태 응답
- canEnter : 입장 가능한지
- enteredUserId : 현재 진행중인 유저가 있다면, 해당 유저의 id
- 입장 가능 조건 : 한번에 한 명의 유저만 보스레이드를 진행할 수 있습니다.
- 아무도 보스레이드를 시작한 기록이 없다면 시작 가능합니다.
- 시작한 기록이 있다면 마지막으로 시작한 유저가 보스레이드를 종료했거나, 시작한 시간으로부터 레이드 제한시간만큼 경과되었어야 합니다.
- 보스레이드 현재 상태 응답
-
보스레이드 시작
- 레이드 시작 가능하다면 중복되지 않는 raidRecordId를 생성하여 isEntered:true와 함께 응답
- 레이드 시작이 불가하다면 isEntered : false
-
보스레이드 종료
- raidRecordId 종료 처리
- 레이드 level에 따른 score 반영
- 유효성 검사
- 저장된 userId와 raidRecoridId 일치하지 않다면 예외 처리
- 시작한 시간으로부터 레이드 제한시간이 지났다면 예외 처리
- raidRecordId 종료 처리
-
보스레이드 랭킹 조회
- 보스레이드 totalScore 내림차순으로 랭킹을 조회합니다.
보스레이드 관련 api는 고려해야 할 예외상황이 많기 때문에, 아래와 같이 api 별로 예외처리를 했습니다.
보스레이드 상태조회 api 예외처리
-
레이드 기록들 중, end_time 필드의 값이 없는 기록을 플레이 중이라고 볼 수 있습니다.
-
비정상적으로 종료된 기록(유저의 컴퓨터가 다운되거나, 꺼지는 등)은 end_time 필드의 값이 없을 수 있습니다.
-
end_time 필드의 값이 없는 기록들 중, enter_time이 현재시각과 비교했을 때 게임 제한 시간보다 이전이라면 비정상 종료된 기록입니다.
결론: 예외 처리 후에도 남은 기록이 있다면, 누군가가 플레이 중이므로, 입장 불가능 응답을 보냅니다.
보스레이드 시작 api 예외처리
-
보스레이드 상태조회 api와 동일하게, 플레이 중인 유저가 있는지 확인합니다.
-
플레이 중인 유저가 없다면 게임을 시작하고, 플레이 중인 유저가 있다면 게임 시작 불가능으로 응답합니다.
-
동시에 시작을 하려는 유저들이 있는 경우, Redis로 구현한 queue로 문제를 핸들링 합니다.
- 여러 유저가 동시에 게임을 시작하려 해도, queue에 가장 먼저 자신의 정보를 넣은 유저만 게임을 시작할 수 있습니다.
보스레이드 종료 api 예외처리
-
존재하지 않는 레이드를 종료하려는 경우 400/bad request로 예외 처리 합니다.
-
관리자와 레이드를 시작한 본인만 보스레이드를 종료 할 수 있습니다.
깃허브 이슈와 간단차트를 통해 태스크 및 일정관리를 했습니다.
Formatter
- isort
- black
Lint
- flake8
로컬에선 pre-commit 라이브러리 사용으로 커밋 전 세가지 라이브러리를 한번에 실행하고 통과되지않을시 커밋이 불가능합니다. 레포지토리에는 github action으로 다시 한번 체크 후, 통과되지 않으면 merge가 block됩니다.
- 회원 생성은 두개의 키값인 nickname과 password를 받아서 수행합니다. 예외처리로는 각각의 키값이 6자리를 넘지 못하면 동작되지 않습니다.
- 회원 로그인은 기본적인 로그인 기능과 로그인이 되는 상황에서 jwt토큰을 함께 요청하고 해당 토큰 값을 response에 같이 반환 합니다.
- 회원 로그아웃은 두가지로 구현하였습니다. 기본적인 장고의 logout()을 사용하되 한가지 경우는 토큰을 반납하면서 blacklist에 등록하고 다른 방법은 토큰 반납이 없이 로그아웃 됩니다.
- 회원조회는 전체조회와 단건조회로 나뉘어집니다. 그냥 문자상으로는 전체 회원의 내용과 특정 회원의 데이터를 보여주는 방식으로 다를 것이라고 생각되지만 전체 조회는 회원 전체의 리스트가 맞지만 단건조회는 회원 개인의 레이드레코드를 같이 서빙해준다는 점이 다릅니다.
- 보스레이드 상태조회는 보스레이드 상태를 조회합니다. 레이드 레코드의 endtime이 현재 시점에서 입력이 안되어있는 필드가 있는지 또 그 필드의 진행시간을 얼마나 지났는지를 판별하여 입장 가능 여부를 판별하게 됩니다.
- 보스레이드 시작은 API호출시 레이드 레코드의 starttime에 지금 시간을 등록하면서 시작하게 됩니다.
- 보스레이드 종료는 PATCH 메소드를 이용해서 보스레이드 시작에서 만든 레이드 레코드의 필드의 내용에서 endtime부분을 변경하게 됩니다.
- 랭킹 확인은 Redis에서 업데이트한 플레이어의 스코어 기록을 재가공하여 플레이어들의 스코어 배열을 정렬하여 받아서 이것을 원하는 랭킹 순위만큼 슬라이싱하여 유저에게 서빙합니다. 동일한 데이터에서 사용자의 닉네임을 이용하여 랭킹을 확인하여 같이 서빙합니다.
🚀 API 호출 테스트 결과
최종 모델링입니다. 초기 모델에서는 테이블을 3개로 구성하는 것으로 진행하였으나 redis를 사용하면서 정적파일을 변경사항이 있을때 가져오는 방식으로 동작 방식을 수정하면서 간소화 되었습니다.
Docker, NginX, uWSGI를 사용하여 AWS EC2 서버에 배포하였습니다.
➡️ 서비스 주소
유저 생성 및 로그인, 로그아웃, 유저 조회 API와 보스레이드 상태 조회, 시작, 종료 API TESTCASE 수행
Name | Task | Github |
---|---|---|
고희석 | 배포, 서버관리 | https://github.com/GoHeeSeok00 |
김민지 | 보스레이드 관련 API | https://github.com/my970524 |
김상백 | 테스트 케이스 | https://github.com/tkdqor |
김훈희 | 유저관련, 랭킹조회 API | https://github.com/nmdkims |
이정석 | Redis 캐싱 | https://github.com/sxxk2 |