항해 플러스 2주차 과제 - 클린 아키텍처
특강 신청 서비스
를 구현해 봅니다.- 항해 플러스 토요일 특강을 신청할 수 있는 서비스를 개발합니다.
- 특강 신청 및 신청자 목록 관리를 RDBMS를 이용해 관리할 방법을 고민합니다.
- 아래 2가지 API 를 구현합니다.
- 특강 신청 API
- 특강 신청 여부 조회 API
- 각 기능 및 제약 사항에 대해 단위 테스트를 반드시 하나 이상 작성하도록 합니다.
- 다수의 인스턴스로 어플리케이션이 동작하더라도 기능에 문제가 없도록 작성하도록 합니다.
- 동시성 이슈를 고려하여 구현합니다.
1️⃣ (핵심) 특강 신청 API
- 특정 userId 로 선착순으로 제공되는 특강을 신청하는 API 를 작성합니다.
- 동일한 신청자는 한 번의 수강 신청만 성공할 수 있습니다.
- 특강은
4월 20일 토요일 1시
에 열리며, 선착순 30명만 신청 가능합니다. - 이미 신청자가 30명이 초과되면 이후 신청자는 요청을 실패합니다.
2️⃣ (기본) 특강 신청 완료 여부 조회 API
- 특정 userId 로 특강 신청 완료 여부를 조회하는 API 를 작성합니다.
- 특강 신청에 성공한 사용자는 성공했음을, 특강 등록자 명단에 없는 사용자는 실패했음을 반환합니다.
3️⃣ (선택) 특강 선택 API
- 단 한번의 특강을 위한 것이 아닌 날짜별로 특강이 존재할 수 있는 범용적인 서비스로 변화시켜 봅니다.
- 이를 수용하기 위해, 특강 엔티티의 경우 기존의 설계에서 변경되어야 합니다.
- 특강의 정원은 30명으로 고정이며, 사용자는 각 특강에 신청하기전 목록을 조회해볼 수 있어야 합니다.
- 정확하게 30 명의 사용자에게만 특강을 제공할 방법을 고민해 봅니다.
- 같은 사용자에게 여러 번의 특강 슬롯이 제공되지 않도록 제한할 방법을 고민해 봅니다.
![image](https://private-user-images.githubusercontent.com/29749722/317723027-7bc0f5ad-437f-40f9-96cb-5112a3289ce9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ4ODQxNzAsIm5iZiI6MTcyNDg4Mzg3MCwicGF0aCI6Ii8yOTc0OTcyMi8zMTc3MjMwMjctN2JjMGY1YWQtNDM3Zi00MGY5LTk2Y2ItNTExMmEzMjg5Y2U5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MjglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODI4VDIyMjQzMFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWJiYjVlZjdjYjZiMzMxYzY1ZTM1YWQ4M2IwZDhlYTg1MDE1YjJmZGU0YmI4NWE2Zjk4OWQ4OWY4ZTYxNjUwOWUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.IyFgVdXkvGAolalAxfdTZXKwDIJ2mf8GshaChCayoFY)
![image](https://private-user-images.githubusercontent.com/29749722/317723176-32ed6616-e1e1-432b-8d4e-6f1f41ddc119.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ4ODQxNzAsIm5iZiI6MTcyNDg4Mzg3MCwicGF0aCI6Ii8yOTc0OTcyMi8zMTc3MjMxNzYtMzJlZDY2MTYtZTFlMS00MzJiLThkNGUtNmYxZjQxZGRjMTE5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MjglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODI4VDIyMjQzMFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWQ2Yzg5YzZiMjE3YjM0ZjBmMzNkMjQ3YzYxYmU3ZTUxZjYyYjdjNWUwMmE1ZTJhMDdlMzhiMmQzYzgyZjE3NDcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.ie5KDbrQlbCXHKuzCo46ha4B7IOXXmMHYYOdqgb3XsU)
![image](https://private-user-images.githubusercontent.com/29749722/317723284-b720f94f-7ab5-4b96-87b7-3d07c40f298c.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ4ODQxNzAsIm5iZiI6MTcyNDg4Mzg3MCwicGF0aCI6Ii8yOTc0OTcyMi8zMTc3MjMyODQtYjcyMGY5NGYtN2FiNS00Yjk2LTg3YjctM2QwN2M0MGYyOThjLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MjglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODI4VDIyMjQzMFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTNmYzEyYTVmYTQ0YmY4MGJiMGFlMGI4ZmUyYjFiNjNlM2NlNmM3OTc5ODBhYjMwMjQzZmMyZjhmMzY2YzY0YzkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Q_vxM96RAOxAAEUNxqd6X1iYnROSy4gjYCl0EjBkaUA)
![image](https://private-user-images.githubusercontent.com/29749722/317723447-a60b5eba-ed20-46fd-8f85-d2c362668633.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQ4ODQxNzAsIm5iZiI6MTcyNDg4Mzg3MCwicGF0aCI6Ii8yOTc0OTcyMi8zMTc3MjM0NDctYTYwYjVlYmEtZWQyMC00NmZkLThmODUtZDJjMzYyNjY4NjMzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MjglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODI4VDIyMjQzMFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFkMDQwNzcyYzYwNDExODI5MzU2ZmY1NTM0ZjFjNTAyZDIzYmFkYjk1NjMwMmQyYWQ5YjQzMjkzY2Q1MTNlNDMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.n9DfO94BoGNB9e1eMA2TYCFkKEDLP9DgZJWg3k3xjkU)