완성본
사람들에게 무료로 배포할 수 있는 퀴즈 게임을 만들어보고 싶었어요. 가능하다면 공부하는 사람들에게 도움이 되면 좋겠다, 아니면 연인이나 친구들과 넌센스 퀴즈를 만들어 공유하면 좋겠다 싶어 만들었어요. 작은 미니 pc를 사서 도메인을 구입하고 DNS와 IP를 연결해 사이트를 열어두었습니다. 사람들 반응이 좋다면 광고도 같이 받으려 하고 있어요. 사이트는 simdev1234.site 여기로 들어가면 무료로 가입 후 퀴즈 게임을 사용할 수 있습니다!:)
[ 퀴즈 게임 ]
- Service : 퀴즈 게임을 만들어 친구들과 공유할 수 있는 프로그램
- Link : simdev1234.site
- Stack : Java/SpringBoot, Thymeleaf, html/css/javascript, Docker, Redis, Mysql 등
기획부터 시작해서 설계까지
기획하는 단계에서는 '어떤 걸 만들 것인가'를 잘 정해야 하는 것 같습니다. 제가 만들고자 했던 것은 편안하게 할 수 있는 퀴즈 게임이었고, 그걸 만들기 위해서는 기존의 퀴즈 서비스들이 뭐가 있는지를 알아야 했습니다.
- Quiz 관련 서비스들
- 기타 유사 서비스들
그리고 나서는 브레인 스토밍을 할 차례였습니다. MVP 버전으로 뭘 중점으로 만들 것인가. 그게 관건이었어요.
브레인스토밍
- 주제 : 5초 폭탄 스피드 퀴즈 (10문제 이하)
- 내용 : 주제별 (우선은 영어단어로)
- 유형 : 객관식 (3지선다)
- 기능 :
- 회원가입 및 로그인
- 제한 시간 내에 퀴즈 풀기
- 5초 안에 문제를 못 맞추면 폭탄이 터지고 틀리는 게임
- 중도 이탈 시, 이전 퀴즈에 이어서 문제 풀기
- 도전 횟수 : 하루에 5번까지 재도전 가능
- 결과 보기 : 결과 상세보기
- 실시간 랭킹 :
- 랭킹 기준 : 맞춘 최대 정답 갯수가 많을 수록, 도전 횟수 적을수록 / 10위까지만 출력
- 반영 시점 : 퀴즈 끝나마자마자 점수 반영 (유저수 별로 없음. 즉시 갱신)
그 다음에 도메인별 상세 기능 및 정책에 대해 대강 작성을 해보았습니다. 물론 최종으로는 이대로 되지는 않았지만요.
도메인별 상세 기능 및 정책
회원
- 회원가입
- 절차 : 이메일 인증 → 비밀번호 및 닉네임 입력 → 가입 완료
- 이메일 인증 코드 정책
- 코드유형 : 6자리의 십진수
- 유효기간 : 1분
- 로그인 유지 기능을 통해서 24시간 동안 로그인을 유지할 수 있다.
- 이메일 인증 코드 정책
- 회원(Users) 데이터는 아래와 같이 구성되어 있다.
- 이메일(email) : 동일 이메일로 가입 불가
- 비밀번호(password) : 8자 이상의 알파벳 대문자 + 소문자 + 특수문자 + 숫자
- 닉네임(nickname) : 중복 가능
- 절차 : 이메일 인증 → 비밀번호 및 닉네임 입력 → 가입 완료
- 로그인
- 로그인 성공시,
- JWT 인증 토큰 발급
- AT (만료 : 1시간)
- 로그인 히스토리(기기 정보 및 로그인 일시) 저장
- JWT 인증 토큰 발급
- 로그인 실패시,
- 알럿 : 아이디 및 비밀번호를 확인 후 재시도 해주세요~
- 로그아웃
- 로그인 성공시,
- 마이페이지
- (선택) 비밀번호 초기화
- (선택) 닉네임 수정
퀴즈
- 퀴즈가 시작되면 5초 안에 각 문항을 풀어야한다.
- 각각의 보기는 랜덤순으로 노출되도록 한다. (ex. 123 → 321 → 213…)
- 퀴즈는 최대 5번까지 풀 수 있으며, 다시 풀었을 때 랭킹 순위가 올라갈 수 있다.
- 중도에 이탈할 경우 풀던 문항부터 풀도록 한다.
(단, 이 경우 재진입시 문항 시간은 초기화된다.) - 랭킹 정산 방법
- 랭킹 기준 : 맞춘 최대 정답 갯수가 많을 수록, 도전 횟수 적을수록 / 10위까지만 출력
- 계산방법 : ROUND{(전체 맞춘 문항 갯수 / 도전 횟수) - (도전횟수 -1)}
- Redis의 SortedSet를 통해서 도전할 때마다 score 갱신
- 반영 시점 : 퀴즈 끝나마자마자 점수 반영 (유저수 별로 없음. 즉시 갱신)
- 랭킹 기준 : 맞춘 최대 정답 갯수가 많을 수록, 도전 횟수 적을수록 / 10위까지만 출력
- 문항(questions) 데이터는 아래와 같이 구성되어 있다.
- 주제(subjects) : 우선은 ‘영어’하나만 갖는다.
- 유형(question_type) : 객관식/주관식.. → 우선은 객관식만 갖는다
- 질문(question_text) : 문항 질문지(ex. reimburse 의 뜻을 고르시오.)
- 선지(choices) : 보기내용 및 정답 여부
- 노출여부
- 노출순서
- 생성일, 수정일, 노출일
- 퀴즈 풀이 이력(quizz_attempt_histories) 데이터는 아래와 같이 구성되어 있다.
- 사용자 ID
- 문항 ID / (선택한) 선지 ID / (입력한) 주관식 답변
- 정답 여부
- 시도 횟수? (-> 불필요할 것 같은데 우선 차후에 확인)
- 생성일
복잡한 시퀀스 다이어그램의 일부. 이렇게 작성을 해도 결국에는 복잡한 절차를 줄이게 되더라고요. 이러니 항상 개발을 시작할 때는 욕심은 금물! 최소한으로 기획을 하고 개발을 하는 게 최선이라는 생각을 했습니다.
그리고 드디어 대망의 코딩의 시작. 폴더 구조는 모놀로틱 구조에 계층형 구조를 섞어두고, 약간의 어뎁터/포트 방식도 사용해 보았습니다. 처음 구상은 아래와 같았어요.
com.xxx.xxx
├── application
│ ├── UserService.java # Port: Interface
│ ├── QuizService.java
│ └── impl
│ ├── UserServiceImpl.java # Adapter: 구현체
│ └── QuizServiceImpl.java
├── domain
│ ├── user
│ │ ├── User.java # Domain Entity
│ │ ├── UserRepository.java # Domain Port
│ │ └── UserCommand.java # 도메인 서비스 (필요 시)
│ └── quiz
│ ├── Quiz.java
│ ├── QuizRepository.java
│ └── QuizCommand.java
├── interfaces
│ ├── user
│ │ ├── UserController.java
│ │ ├── request
│ │ │ └── CreateUserRequest.java
│ │ └── response
│ │ └── UserResponse.java
│ └── quiz
│ ├── QuizController.java
│ ├── request
│ │ └── CreateQuizRequest.java
│ └── response
│ └── QuizResponse.java
├── infra
│ ├── auth
│ │ ├── JwtTokenProvider.java
│ │ └── SecurityConfig.java
│ ├── persistence # JPA 구현체 or MyBatis Mapper 위치
│ │ ├── user
│ │ │ ├── UserEntity.java
│ │ │ └── UserJpaRepository.java
│ │ └── quiz
│ │ ├── QuizEntity.java
│ │ └── QuizJpaRepository.java
│ └── redis
│ └── RedisConfig.java
├── global
│ ├── exception
│ │ ├── GlobalExceptionHandler.java
│ │ ├── CustomException.java
│ │ └── ErrorCode.java
│ └── common
│ └── Constants.java
└── XxxApplication.java
그리고 현실은 아래와 같았죠.
폴더 구조의 경우 초기 구상과 크게 달라지진 않았던 것 같긴 합니다.
다양한 재미 요소
퀴즈 게임을 만들고 테스트를 해보면서 애인과 친구들을 위해 퀴즈를 만들어 공유를 했었어요. 예를 들어 아래와 같이, 궁합 테스트를 하는 게임을 만들어서 애인에게 공유를 했었죠.
내가 만든 퀴즈는 다른 사람들과 링크를 공유할 수 있게 만들었기 때문에, 빠른 공유가 가능합니다. 정해진 시간 안에 문제를 풀도록 되어 있기 때문에 타입 압박을 받으며 솔직(?)한 답변을 할 수 있어요.:)
가능하면 쉽고 빠르게. 그러면서도 모두가 재밌게 즐길 수 있는 방향으로 만들어보려 노력했습니다. 무료로 배포하는 거니, 편하게 사용해주시면 좋겠어요. :) 이제 또다른 플젝을 시작해봐야겠군요. 이번에는 파이썬과 Django를 써봐야겠어요. 자바랑 스프링은 너무 물리니, 새로운 시도도 좋겠죠. 그 때까지 다들 행쇼하시고, 다시 보아요~