변경된 결제수단 반영되는 로직

427ed1a0-27e6-406d-824b-8cc582bbe982.MOV

paymentMethodService에서 setPaymentMethodInfo메서드를 통해 PUT의 페이로드 데이터를 적절히 변환하여 세션스토리지에 저장합니다.

setPaymentMethodInfo(registerData: PaymentMethodRequest) {
    const cardList = this.getCardResult()
    const accountList = this.getAccountResult()
    const paymentMethodList = [...cardList, ...accountList]

    const {usePointAll, firstPayMethod, secondPayMethod, cashReceiptApply, cashReceipt} = registerData

    // 1순위 결제수단을 포맷팅
    const formattedFirstPayment = this.findAndFormatPayment(firstPayMethod, paymentMethodList)
    if (!formattedFirstPayment) {
        return 'unknownError'
    }
    // 2순위 결제수단을 포맷팅
    const formattedSecondPayment = this.findAndFormatPayment(secondPayMethod, paymentMethodList)
    // 세션스토리지에 저장할 형태
    const paymentUIState = {
        cashReceipt,
        cashReceiptApply,
        usePointAll,
        orderPayMethodNo: ORDER_PAY_METHOD_NO,
        firstPaymentMethod: formattedFirstPayment,
        secondPaymentMethod: formattedSecondPayment,
    }

    sessionStorage.setItem(PAYMENT_STATE_KEY, JSON.stringify(paymentUIState))
},

그리고 해당 데이터를 orderService에서 결제수단 정보를 가져올 때 확인합니다. KEY값이 존재하면 해당 정보를 그대로 이용합니다.

// 구독 결제 방법 정보를 가져옵니다.
getOrderPayMethod() {
    const storeData = loadStateFromSessionStorage(PAYMENT_STATE_KEY)
    if (storeData) {
        return storeData
    }
    // ...

세션스토리지 사용 이유

세션스토리지를 활용한 이유는, 우선 페이지를 새로고침 해도 바뀐 값이 유지되게 하고 싶었습니다. 그렇기 위해선 스토리지를 이용해야 했는데, 한번 생성되면 임의로 제거할 때 까지 영구적인 로컬스토리지와는 다르게 세션스토리지는 현재 열려있는 탭, 세션 동안만 유지된다는 특성이 있습니다. 사용자 측면에서 현재 탭을 닫았음에도 다른 탭에 해당 정보를 갖고 있을 필요가 없다고 생각했기에 세션스토리지를 택하였습니다.

보안적인 측면에 대한 생각

하지만 세션스토리지 특성 상, 사용자에 의해 데이터 변조 가능성이 있습니다. 그렇게 되면 저희가 맞춘 데이터 형식에 어긋나는 데이터가 될 수 있으며 이로 인해 애플리케이션 전체가 터질 수 있습니다. 이를 방지하고자 storage이벤트를 활용하였습니다. storage이벤트는 스토리지에 변화가 발생할 때 트리거됩니다. 이를 이용하여 스토리지 값을 설정하고, 사용자에 의해 의도치 않게 그 값이 변경된 경우, 해당 값이 오염되었다 판단하여 스토리지 값을 모두 없애버립니다. 해당 구현은 오직 현재 프로젝트에 한해서 작성되었으며, 실제였다면, 새로고침 마다 API 요청을 보내 데이터를 갱신하기 때문에 이런 조치를 취할 필요가 없습니다.

왜 결제수단 slice를 공유하지 않았는지?

가장 큰 이유는 기능의 역할과 책임이 다르다고 생각했기 때문입니다. 두 페이지 모두 '결제수단 데이터'를 다루지만, 그 역할은 근본적으로 다릅니다.

하나의 Slice로 이 두 역할을 모두 처리하게 되면, 단순히 데이터를 보여주기만 하는 주문서 페이지가 불필요하게 복잡한 상태 변경 로직까지 알게 되어 Slice의 역할이 모호해지고 비대해집니다.

만약, 동일한 결제수단을 활용하는 또다른 주문서 화면이 추가되어야 한다면?