내일배움캠프 프로젝트

BuySell - 선착순 쿠폰발급

공부처음하는사람 2024. 3. 20. 01:01

 

동시성 제어 기능을 구현하기 위해 우리 프로젝트에서 어떤 내용으로 동시성 제어를 해볼까 고민하다가

선착순 쿠폰발급 기능을 추가하게 되었다.

 

쿠폰의 혜택이 좋을수록 트래픽이 몰리게 될 것이고 순차적인 발급을 위해 좋은 주제인 것 같다.

 

일단 현재 임시적으로 요구사항을 정해보았다.

  1. 쿠폰번호 제약 사항
    • 16자리 영문 + 숫자
    • 영문은 대문자만 입력 가능
  2. 사용가능 여부
    • available = Boolean 설정
  3. 쿠폰에 사용자 정보 입력 (사용한 id 확인)
  4. 쿠폰 지급받은 계정만 사용 가능
  5. 쿠폰 사용기한 추가
  6. 쿠폰생성은 어드민만 가능
  7. 쿠폰 n개 선착순 발급
  8. n개 이상의 쿠폰이 발급되면 안됨
  9. 트래픽이 몰렸을 때 다른 웹페이지의 속도가 저하되어선 안됨

일단 쿠폰을 생성하는 코드를 작성해보았다.

@Service
class CouponServiceImpl(
    private val couponRepository: CouponRepository,
    private val memberRepository: MemberRepository,
    private val couponUtility: CouponUtility
) : CouponService {
    @Transactional
    override fun createCoupon(request: CreateCouponRequest, principal: UserPrincipal): MessageResponse {
        val memberId = request.memberId
        val member = memberRepository.findByIdOrNull(memberId)
            ?: throw IllegalArgumentException("유효하지 않은 계정입니다.")

        val createdCoupons = mutableListOf<Coupon>()

        for (i in 1..request.couponCount) {

            val coupon = Coupon(
                content = request.content,
                couponNumber = couponUtility.createCouponNumber(),
                couponCount = request.couponCount,
                member = member,
                available = true
            )
            couponRepository.save(coupon)
            createdCoupons.add(coupon)
        }
        return MessageResponse("쿠폰 ${createdCoupons.size}개를 생성했습니다.")
    }
}

 

일단 쿠폰은 요구하는 개수만큼 생성이 되는것을 확인했는데, request의 memberId가 있을 이유가 없다.. 

항상 생각을 하고 코드를 짜야하는데 이상한 습관이 든 것 같다.

당연히 findByOrNull로 예외처리 하는 코드는 지금 하는 역할이 없다..

 

쿠폰을 생성 -> 생성되어 있는 쿠폰을 순차적 발급 -> 그 과정에서 동시성 제어

이렇게 생각하는게 맞을까? 아니면 쿠폰을 발급받는 과정에서, 쿠폰이 생성됨과 동시에 발급을 하는게 맞을까?

 

프론트에서 선착순 쿠폰 받기 버튼을 누르게 되면, 그때 설정되어 있는 개수만큼 하나씩 발급 되는 방식도 맞는 것 같고..

아직도 이런 플로우를 생각하는게 익숙하지 않다. 한번 두가지 방법을 고민해보고 다른 사람과 의견을 들어봐야겠다.