Commit ed75132
develop -> main ( 강의, 수강신청 ) (#180)
* [fix] 대기열 인원 수 확인 로직 변경 테스트 반영 (#179)
* feat: Redis 기반 동시성 제어 및 큐 기반 수강신청·취소 비동기 처리 구현 (#176)
* test: 현재 동시성 문제가 발생하는지 확인하기 위한 테스트 추가
- 동시에 100명이 신청했을 경우 최대 수강 인원이 30명인 강좌에 몇명이 등록되는지 확인
- 수강신청 내역이 30개가 아닌 100개가 생성되고있음
- 강의 정보에 현재 수강인원이 제대로 갱신되고 있지 않음
- 30명이 채워져야하지만 11, 12명 등 이상한 값으로 채워지고 있음
# Conflicts:
# backend/src/main/java/com/WEB4_5_GPT_BE/unihub/domain/enrollment/repository/EnrollmentRepository.java
* feat: 수강신청 로그를 추가하여 수강인원이 제대로 증가하지 않는 문제점 파악
- 동시에 수강신청을 보내고 인원을 변경하기 때문에 해당 강좌의 현재수강신청 인원 수가 제대로 증가하지 않고 오히려 적게 나타나는 문제였음
```
수강 신청이 완료되었습니다. 학생: 25020004, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020010, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020002, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020005, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020006, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020003, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020001, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020009, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020008, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020007, 강좌: 0
현재 수강인원 변경이 완료되었습니다. 학생: 25020001, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020006, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020004, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020005, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020002, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020007, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020010, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020003, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020008, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020009, 강좌: 1
```
* refactor : 변경된 회원 도메인에 맞게 테스트 코드 수정
* feat: Redisson을 통한 수강신청 동시성 제어 구현
- 코드별 주석으로 상세 설명
* feat: 동시성 테스트는 프로젝트 테스트에서 진행하지 않도록 @Profile("!test") 수정
- 현재 동시성 로직은 별도의 트랜잭션을 생성하기 때문에 test 코드 상에 transational 을 붙여줄 수 없음
- test 코드에서 @transational 을 붙이지 않으면 테스트 과정에서 수정된 데이터가 롤백되지 못해 다른 테스트에 영향을 줄 수 있음
- 또한 동시성 관련 테스트는 생성해야 하는 회원 데이터 등이 많아 테스트에 부하가 많이 걸림
- 프로젝트 테스트에서 동시성을 검증하지 않고 별도의 툴 (jmeter) 을 통해 외부에서 테스트 할 예정
* feat: 동시성 테스트용 데이터 (4학년 학생 100명 및 신청용 강좌) 생성
# Conflicts:
# backend/src/main/java/com/WEB4_5_GPT_BE/unihub/global/init/InitDevData.java
* feat: 동시성 문제 해결을 위해 redis의 원자성이 보장되는 AtomicLong 적용 및 Queue를 통한 수강신청 비동기 처리 구현
- Redis RAtomicLong 을 이용해 capacity 및 enrolled 카운터를 원자적으로 관리하고, 수강신청 시 increment하여 동시성 보장
- 수강신청 요청 시 DB 트랜잭션 대신에 Redis 카운터만 업데이트하여 빠른 응답을 제공
- EnrollmentCommand DTO 를 통해 수강신청 정보를 큐(RBlockingQueue<EnrollmentCommand>)에 저장
- EnrollmentCommandConsumer 가 큐에서 명령을 순차적으로 꺼내 EnrollmentCommandHandler 에게 위임
* feat: Redisson을 활용하여 강의 생성 시 강의 수강 인원 및 수용 인원 정보를 Redis에 저장하는 기능 추가
* docs: k6를 활용한 수강신청 동시성 테스트 (100명 동시 신청 시 30명 정상 등록 완료) 파일 추가
- local 테스트
* test: 변경된 로직에 맞게 테스트 코드 수정
* refactor: 잘못 적용되어있는 ConcurrencyGuard 제거
* feat: EnrollmentDuplicateChecker를 구현하여 중복 queue 삽입 (동일 학생이 연속으로 신청하는 경우 (따닥)) 방지
- k6 테스트 스크립트 추가 (한 학생이 동일강좌에 5번 동시에 신청)
* docs : 주석 추가
* refactor: EnrollmentAlreadyQueuedException 예외처리를 공용으로 사용할 수 있도록 수정
* feat: 강의 취소의 경우에도 순차적으로 queue를 통해 처리될 수 있도록 수강 신청 로직과 동일하게 구현
* docs: 30명 동시 수강신청 및 동시 수강 취소 k6 테스트 스크립트 추가
* refactor : 수강신청 api 주석 수정 및 수강신청 queue 처리 후 flag를 제거하도록 추가
* refactor : 테스트용 대기열 설정 제거
* test : 테스트 코드 수정
* refactor: 패키지 이동
* feat: 강의 등록, 수정 시 redis에 저장된 Enrolled와 Capacity를 업데이트하도록 추가
* feat: 강의 삭제 시 redis에 저장된 Enrolled와 Capacity를 삭제하도록 구현
* feat: redis counter 관련 로직을 별도의 service로 분리
* feat: 프로젝트 재부팅 시 redis에 저장된 counter 값을 현재 강의 정보와 동기화 하도록 구현
* test: 변경된 로직에 맞게 테스트 코드 수정
* feat: initData 과정에서 강의 생성 시 counter를 redis에 저장하도록 추가
* refactor: 필요없는 주석 제거
* merge: [BUGFIX] 강의 생성시 대학 정보 획득 방식 변경 (#178)
* fix: 강의 생성 및 수정 시 인증된 유저 정보도 가져오도록 변경
* fix: 강의 생성 및 수정 시 요청 본문 대신 인증된 유저 정보로부터 대학 정보를 가져오도록 변경
* test: 변경 사항을 테스트에 반영
* fix: 강의 요청 DTO에서 대학 이름을 필수에서 선택으로 변경
* [fix] 대기열 인원 수 확인 로직 변경 테스트 반영 (#179)
* feat: Redis 기반 동시성 제어 및 큐 기반 수강신청·취소 비동기 처리 구현 (#176)
* test: 현재 동시성 문제가 발생하는지 확인하기 위한 테스트 추가
- 동시에 100명이 신청했을 경우 최대 수강 인원이 30명인 강좌에 몇명이 등록되는지 확인
- 수강신청 내역이 30개가 아닌 100개가 생성되고있음
- 강의 정보에 현재 수강인원이 제대로 갱신되고 있지 않음
- 30명이 채워져야하지만 11, 12명 등 이상한 값으로 채워지고 있음
# Conflicts:
# backend/src/main/java/com/WEB4_5_GPT_BE/unihub/domain/enrollment/repository/EnrollmentRepository.java
* feat: 수강신청 로그를 추가하여 수강인원이 제대로 증가하지 않는 문제점 파악
- 동시에 수강신청을 보내고 인원을 변경하기 때문에 해당 강좌의 현재수강신청 인원 수가 제대로 증가하지 않고 오히려 적게 나타나는 문제였음
```
수강 신청이 완료되었습니다. 학생: 25020004, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020010, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020002, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020005, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020006, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020003, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020001, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020009, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020008, 강좌: 0
수강 신청이 완료되었습니다. 학생: 25020007, 강좌: 0
현재 수강인원 변경이 완료되었습니다. 학생: 25020001, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020006, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020004, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020005, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020002, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020007, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020010, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020003, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020008, 강좌: 1
현재 수강인원 변경이 완료되었습니다. 학생: 25020009, 강좌: 1
```
* refactor : 변경된 회원 도메인에 맞게 테스트 코드 수정
* feat: Redisson을 통한 수강신청 동시성 제어 구현
- 코드별 주석으로 상세 설명
* feat: 동시성 테스트는 프로젝트 테스트에서 진행하지 않도록 @Profile("!test") 수정
- 현재 동시성 로직은 별도의 트랜잭션을 생성하기 때문에 test 코드 상에 transational 을 붙여줄 수 없음
- test 코드에서 @transational 을 붙이지 않으면 테스트 과정에서 수정된 데이터가 롤백되지 못해 다른 테스트에 영향을 줄 수 있음
- 또한 동시성 관련 테스트는 생성해야 하는 회원 데이터 등이 많아 테스트에 부하가 많이 걸림
- 프로젝트 테스트에서 동시성을 검증하지 않고 별도의 툴 (jmeter) 을 통해 외부에서 테스트 할 예정
* feat: 동시성 테스트용 데이터 (4학년 학생 100명 및 신청용 강좌) 생성
# Conflicts:
# backend/src/main/java/com/WEB4_5_GPT_BE/unihub/global/init/InitDevData.java
* feat: 동시성 문제 해결을 위해 redis의 원자성이 보장되는 AtomicLong 적용 및 Queue를 통한 수강신청 비동기 처리 구현
- Redis RAtomicLong 을 이용해 capacity 및 enrolled 카운터를 원자적으로 관리하고, 수강신청 시 increment하여 동시성 보장
- 수강신청 요청 시 DB 트랜잭션 대신에 Redis 카운터만 업데이트하여 빠른 응답을 제공
- EnrollmentCommand DTO 를 통해 수강신청 정보를 큐(RBlockingQueue<EnrollmentCommand>)에 저장
- EnrollmentCommandConsumer 가 큐에서 명령을 순차적으로 꺼내 EnrollmentCommandHandler 에게 위임
* feat: Redisson을 활용하여 강의 생성 시 강의 수강 인원 및 수용 인원 정보를 Redis에 저장하는 기능 추가
* docs: k6를 활용한 수강신청 동시성 테스트 (100명 동시 신청 시 30명 정상 등록 완료) 파일 추가
- local 테스트
* test: 변경된 로직에 맞게 테스트 코드 수정
* refactor: 잘못 적용되어있는 ConcurrencyGuard 제거
* feat: EnrollmentDuplicateChecker를 구현하여 중복 queue 삽입 (동일 학생이 연속으로 신청하는 경우 (따닥)) 방지
- k6 테스트 스크립트 추가 (한 학생이 동일강좌에 5번 동시에 신청)
* docs : 주석 추가
* refactor: EnrollmentAlreadyQueuedException 예외처리를 공용으로 사용할 수 있도록 수정
* feat: 강의 취소의 경우에도 순차적으로 queue를 통해 처리될 수 있도록 수강 신청 로직과 동일하게 구현
* docs: 30명 동시 수강신청 및 동시 수강 취소 k6 테스트 스크립트 추가
* refactor : 수강신청 api 주석 수정 및 수강신청 queue 처리 후 flag를 제거하도록 추가
* refactor : 테스트용 대기열 설정 제거
* test : 테스트 코드 수정
* refactor: 패키지 이동
* feat: 강의 등록, 수정 시 redis에 저장된 Enrolled와 Capacity를 업데이트하도록 추가
* feat: 강의 삭제 시 redis에 저장된 Enrolled와 Capacity를 삭제하도록 구현
* feat: redis counter 관련 로직을 별도의 service로 분리
* feat: 프로젝트 재부팅 시 redis에 저장된 counter 값을 현재 강의 정보와 동기화 하도록 구현
* test: 변경된 로직에 맞게 테스트 코드 수정
* feat: initData 과정에서 강의 생성 시 counter를 redis에 저장하도록 추가
* refactor: 필요없는 주석 제거
* fix: 강의 생성 및 수정 시 인증된 유저 정보도 가져오도록 변경
* fix: 강의 생성 및 수정 시 요청 본문 대신 인증된 유저 정보로부터 대학 정보를 가져오도록 변경
* merge: Rebase 박주원/fix-177 onto develop
* fix: 강의 요청 DTO에서 대학 이름을 필수에서 선택으로 변경
* test: 변경 사항을 테스트에 반영
---------
Co-authored-by: TheGreatKang <77500386+TheGreatKang@users.noreply.github.com>
Co-authored-by: OJH <ok6737@naver.com>
---------
Co-authored-by: TheGreatKang <77500386+TheGreatKang@users.noreply.github.com>
Co-authored-by: OJH <ok6737@naver.com>
Co-authored-by: SalinatedCoffee <74612242+SalinatedCoffee@users.noreply.github.com>1 parent 8c3eab1 commit ed75132
1 file changed
Lines changed: 6 additions & 6 deletions
File tree
- backend/src/main/java/com/WEB4_5_GPT_BE/unihub/domain/enrollment/service
Lines changed: 6 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
11 | | - | |
12 | | - | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
0 commit comments