Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[refactor] 디스코드 웹훅 알림 비동기 이벤트로 리팩터링 #163

Merged
merged 15 commits into from
Apr 19, 2024

Conversation

SunwoongH
Copy link
Member

Related Issue 📌

Description ✔️

중복 회원가입 동시성 문제가 발생하게 된 주요한 원인

앱 내에서 회원가입 버튼 클릭 시 약 0.7초 정도의 딜레이 시간이 발생했고 해당 시간 동안 사용자가 버튼을 연속으로 클릭하면 동시에 여러 요청이 들어와 첫번째 요청이 처리되기 전 두번째 요청이 수행되어 중복 회원 검증 로직이 예상했던 결과와 다르게 동작하게 되고 결국 서비스에 동일한 회원이 2명 이상 존재하게 되는 문제였습니다. 이유는 race condition이 발생했기 때문이라고 판단했고 이를 해결하기 위해 회원가입 로직을 임계 영역으로 두고 setnx 락을 사용하여 해결하였습니다. 그러나 회원가입 버튼을 클릭한 이후 API 통신의 응답을 받기까지 약 0.5 ~ 0.7초 정도의 딜레이 시간은 사용자 입장에서 앱이 먹통되어 정상적으로 동작하고 있지 않다고 느껴질 것이고 이에 따라 자연스럽게 회원가입 버튼을 여러 번 클릭하게 끔 유도된다고 생각되었습니다. 따라서 락을 사용하여 race condition을 방지하되, API 통신의 딜레이 시간을 최소화할 수 있는 방법을 도입해야 한다고 판단되었습니다.

해결방안

현재 회원가입 비즈니스 로직에서 소요시간의 비중이 가장 큰 기능은 외부 API 통신이 수행되는 디스코드 웹훅 알림 기능이었습니다. 디스코드 웹훅 알림 기능은 회원가입 비즈니스 로직에서 동기적으로 동작하지 않아도 되는 기능이라고 판단되었고 이를 비동기 방식으로 리팩터링하여 회원가입 API 통신의 딜레이 시간을 단축시키고자 하였습니다.
ApplicationEventPublisher와 @eventlistener 그리고 @async 어노테이션을 적용하여 디스코드 웹훅 알림 기능을 비동기 이벤트 방식으로 리팩터링을 진행하였습니다.
스프링 이벤트 기능을 도입하면서 어떤 모듈 그리고 패키지에 해당 클래스들을 두어야 할지 고민하였습니다. 초기 설계는 회원가입 로직이 수행되는 doorip-api 모듈에는 EventPublisher, 디스코드 웹훅 알림 기능이 수행되는 doorip-external 모듈에는 EventSubscriber를 두어 구현을 하였습니다. 그러나 EventPublisher와 EventSubscriber는 각 모듈이 가진 관심사와 다른 관심사라고 판단되어 doorip-event-publisher, doorip-event-subscriber 모듈로 각각 분리하여 적용하였습니다. 모듈을 분리하는게 옳은 방향인지는 아직 고민 중이며 전체적인 모듈 간의 의존성을 파악하고 지속적으로 개선해나가려고 합니다.
스프링 이벤트 기반을 비동기 방식으로 구현하기 위해 @async 어노테이션을 적용하였습니다. 단, @async 어노테이션의 기본 설정은 SimpleAsyncTaskExecutor를 사용하여 요청마다 스레드가 생성되는 방식이기 때문에 무분별하게 스레드가 생성되어 관리되지 못하는 문제가 생길 수 있다고 판단되어 ThreadPoolTaskExecutor를 활용한 스레드 풀 방식으로 구현하였습니다.

@async 어노테이션 적용 X(동기 방식)

@async 어노테이션 적용 O(비동기 방식)

결론은 다음과 같습니다. 디스코드 알림 기능에 총 가입자 수를 카운팅하는 기능까지 추가하여 동기 방식으로 API 통신이 수행되었을 때 약 0.9초의 딜레이 시간이 발생했고 이를 비동기 이벤트 기반으로 리팩터링하여 약 0.18초까지 단축할 수 있었습니다.

Copy link
Member

@gardening-y gardening-y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트 알림 변경된 거 봤는데 넘 멋있네요.. 수고하셨습니다^_^

@SunwoongH SunwoongH merged commit 65fa1aa into develop Apr 19, 2024
1 check passed
@SunwoongH SunwoongH deleted the feature/160 branch July 11, 2024 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[refactor] 디스코드 웹훅 알림 비동기 이벤트로 리팩터링
2 participants