본문 바로가기

트러블슈팅

React Coupon Selector에서 발생한 isToggle과 maxPriceCoupon 동기화 문제 해결하기

들어가며

개발을 하다 보면 간단해 보이는 기능도 실제 구현 과정에서 예상치 못한 복잡성을 마주치게 됩니다. 최근 제가 경험한 쿠폰 선택 기능 구현 과정이 바로 그랬습니다. 자동/수동 쿠폰 선택이라는 겉보기에 단순한 기능이, 여러 상태값들이 얽히면서 꽤나 까다로운 문제로 발전했던 경험을 공유하고자 합니다.

 

구현하고자 했던 기능

우리 프로젝트에서는 사용자에게 두 가지 쿠폰 선택 방식을 제공하고자 했습니다:

  1. 자동 선택: 시스템이 자동으로 최대 할인 쿠폰을 선택
  2. 수동 선택: 사용자가 직접 원하는 쿠폰을 선택

이를 위해 isToggle이라는 상태값으로 자동/수동 모드를 전환하고, maxPriceCoupon으로 최대 할인 쿠폰을 관리하는 방식을 선택했습니다.

 

발생한 문제

처음에는 단순하게 접근했습니다. isToggle이 false면 무조건 maxPriceCoupon을 적용하고, true면 사용자 선택을 유지하는 방식으로요. 하지만 실제 테스트 과정에서 예상치 못한 문제가 발생했습니다.

// 초기 구현 코드 (문제가 있는 버전)
useEffect(() => {
  if (!isToggle && maxPriceCoupon) {
    setUserInputs(prev => ({
      ...prev,
      coupon_code: maxPriceCoupon.code
    }));
  }
}, [isToggle, maxPriceCoupon]);

가장 큰 문제는 사용자가 수동으로 선택한 쿠폰이 maxPriceCoupon과 동일한 금액일 때 발생했습니다. isToggle이 false로 변경되면서 이미 선택된 쿠폰이 강제로 maxPriceCoupon으로 덮어써지는 현상이 있었죠. 사용자 입장에서는 "내가 선택한 쿠폰이 왜 갑자기 다른 쿠폰으로 바뀌지?"라는 혼란스러운 경험을 하게 되었습니다.

 

문제 해결 과정

이 문제를 해결하기 위해 먼저 개발자 도구의 콘솔을 활용해 상태 변화를 관찰했습니다. 그 결과, 다음과 같은 인사이트를 얻을 수 있었습니다:

  1. 쿠폰 선택의 우선순위를 명확히 해야 한다
  2. 동일 금액 쿠폰에 대한 처리 로직이 필요하다
  3. 상태 변경의 타이밍을 적절히 조절해야 한다

이러한 인사이트를 바탕으로 다음과 같이 코드를 개선했습니다:

// 개선된 코드
useEffect(() => {
  if (!isToggle && maxPriceCoupon) {
    // 현재 선택된 쿠폰과 최대 할인 쿠폰의 금액 비교
    const currentCoupon = coupons.find(
      coupon => coupon.code === userInputs.coupon_code
    );
    
    if (!currentCoupon || currentCoupon.discount !== maxPriceCoupon.discount) {
      setUserInputs(prev => ({
        ...prev,
        coupon_code: maxPriceCoupon.code
      }));
    }
  }
}, [isToggle, maxPriceCoupon, coupons, userInputs.coupon_code]);

이렇게 수정한 코드는 다음과 같은 장점이 있습니다:

  1. 사용자의 선택을 우선적으로 존중합니다
  2. 불필요한 상태 업데이트를 방지합니다
  3. 동일 금액 쿠폰에 대한 처리가 자연스럽게 이루어집니다

 

개선 전

개선 후

얻은 교훈과 향후 개선 방향

이번 트러블 슈팅을 통해 몇 가지 중요한 교훈을 얻을 수 있었습니다:

1. 상태 관리의 복잡성

여러 상태가 서로 연관되어 있을 때는, 상태 업데이트의 우선순위와 타이밍을 신중하게 고려해야 합니다. 저는 이번 경험을 통해 다음 프로젝트에서는 처음부터 상태 관리 라이브러리 도입을 적극적으로 고려해볼 생각입니다.

2. 사용자 경험 중심의 사고

기능이 정상적으로 동작하는 것과 사용자에게 좋은 경험을 제공하는 것은 다른 문제라는 것을 다시 한번 깨달았습니다. 특히 자동화 기능을 구현할 때는 사용자의 의도를 존중하는 것이 매우 중요합니다.

3. 테스트의 중요성

다양한 시나리오에 대한 테스트의 중요성을 다시 한번 실감했습니다. 현재는 수동으로 테스트를 진행했지만, 앞으로는 다음과 같은 테스트 케이스를 자동화된 테스트로 구현할 계획입니다:

  • 동일 금액의 다른 쿠폰 선택 시나리오
  • Toggle 상태 변경에 따른 쿠폰 선택 유지 여부
  • 최대 할인 쿠폰 변경 시 동작 검증

마치며

이번 경험을 통해 프론트엔드 개발에서 상태 관리의 중요성을 다시 한번 깨달았습니다. 특히 여러 상태가 얽혀 있는 기능을 구현할 때는 처음부터 상태 간의 관계를 명확히 정의하고, 사용자 경험을 중심으로 설계하는 것이 중요하다는 것을 배웠습니다.

 

앞으로는 이러한 경험을 바탕으로, 복잡한 상태 관리가 필요한 기능을 구현할 때 더 체계적인 접근 방식을 취할 수 있을 것 같습니다. 또한, 사용자 경험을 더욱 개선하기 위해 상태 변화를 시각적으로 더 명확하게 표현하는 UI 개선도 진행할 예정입니다.

 

여러분들도 비슷한 경험이 있으시다면, 어떻게 해결하셨는지 댓글로 공유해 주시면 감사하겠습니다. 😊