A club can be created by entering its name, the reason for creating it, initial members, and an introduction.
The club leader can send membership invitations to students.
Teachers can review club creation requests and approve or reject them.
Students can view the status of their own creation requests.
Club Application Logic
Implemented logic that lets users apply to clubs in order of preference, from first to third choice.
Since clubs are divided into official (curriculum) clubs and self-organized clubs, a feature for applying to self-organized clubs was also required.
Application Accept, Pending, and Reject Features
When a club leader creates a club, they can select the club's members.
A student could not be added as a member without the student's own acceptance.
Accordingly, membership invitation requests were categorized as accepted, pending, or rejected, so that leaders could clearly see which students wanted to join their club.
Used in production for club applications by Daegu Software Meister High School's 10th-cohort freshmen and current students in March 2025.
Troubleshooting
☄️ Background
When the club feature was first developed, the plan was for students to apply to only a single official club of their choice. However, following a logic change requested by the client (the school), I had to build logic within a short time frame in which students each applied to first, second, and third choices, and members were then assigned randomly.
During refactoring, I discovered a potential JPA N+1 problem in ClubMemberRepository.
⭐️ Solution
I used a Priority-based Allocation Algorithm. This algorithm made it possible to optimally distribute limited resources (club capacity) according to students' application priorities.
The processAllPriorities method was implemented to process student applications by priority, so that when a club reached its capacity, lower-ranked applicants could be moved to their next-priority club.
Using an assignedStudents set, I completely prevented any student from being assigned more than once by adding a student to the set immediately upon assignment to block re-assignment.
I applied a fetch join via @EntityGraph(attributePaths = {"club"}) so that the club entity was fetched together through a JOIN query. This reduced unnecessary additional queries and improved response times.