240206 TIL - 1차 프로젝트(예약 페이지에서 생성된 임시 데이터 불필요하게 생성되는 문제)

jkeum·2024년 2월 6일
0

TECHIT-BackendSchool

목록 보기
40/50
post-thumbnail

예약하기 페이지에서 뒤로가기 후 다시 예약할 때의 문제

챗지피티한테 적절한 해결방법이 있을지 물어봤다.

A.
기술한 시나리오를 해결하는 한 가지 방법은, 사용자가 '예약하기' 페이지로 돌아왔을 때 기존 예약 데이터의 존재 여부를 확인하고, 이미 예약이 진행 중인 경우 해당 데이터를 수정하는 로직을 구현하는 것입니다. 이를 위해서는 몇 가지 단계를 거쳐야 합니다.

  1. 예약 데이터의 유니크 식별자 보존
    사용자가 예약 프로세스를 시작할 때 생성된 예약 데이터의 ID(예: reserveId)를 클라이언트 측에서 보존해야 합니다. 이 ID는 사용자가 예약을 수정하거나 결제를 진행할 때 참조될 수 있습니다.
  • 방법 1: URL 파라미터 사용
    결제 페이지로 이동할 때 URL에 reserveId를 포함시키고, 사용자가 뒤로 가기를 했을 때 이 파라미터를 읽어 기존 예약 데이터를 조회하고 수정할 수 있습니다.
// 뒤로 가기 시 URL에서 reserveId 가져오기
const { reserveId } = router.query;
  • 방법 2: 상태 관리 라이브러리 사용
    React의 상태 관리 라이브러리(예: Redux, Recoil)를 사용하여 애플리케이션의 전역 상태로 reserveId를 관리할 수 있습니다. 이 방법을 사용하면 사용자가 다른 페이지로 이동해도 reserveId를 유지할 수 있습니다.
  1. 예약 데이터 수정 로직 구현
    사용자가 예약하기 페이지로 돌아온 경우, URL 파라미터나 전역 상태에서 reserveId를 조회하여 해당 ID의 예약 데이터가 존재하는지 확인합니다. 이미 존재하는 경우, 해당 예약 데이터를 사용자가 입력한 새 정보로 업데이트합니다.
  1. 사용자 인터페이스 및 사용자 경험 고려
    사용자가 예약 데이터를 수정할 수 있음을 명확히 하고, 예약 수정이 가능한 상태임을 UI에 표시합니다. 예를 들어, 예약하기 버튼을 "예약 수정하기"로 변경할 수 있습니다.
  • 결론
    사용자가 결제 페이지에서 뒤로 가기를 통해 예약 페이지로 돌아왔을 때 기존 예약을 수정하는 방식은 사용자 경험을 개선하고 데이터의 중복 생성을 방지할 수 있는 좋은 방법입니다. 이를 위해 적절한 예약 데이터 관리 및 UI/UX 디자인이 필요합니다.

해결방법 고민

여기서 1번의 방법 1과 방법 2를 각각 어떻게 구현할 수 있을지 상황을 생각해봤다.

방법 1

A.
방법 1을 사용할 경우, 결제 페이지로 이동할 때 URL에 reserveId를 포함시키는 방식은 특정 사용 사례에만 적합할 수 있습니다. 사용자가 결제 페이지에서 예약하기 페이지로 직접 뒤로 가기를 할 때는 URL의 reserveId를 통해 기존 예약 데이터에 접근하여 수정하는 것이 가능하지만, 사용자가 예약하기 페이지를 벗어나 다른 페이지로 이동한 후 다시 예약하기 페이지로 돌아오는 경우에는 reserveId가 유지되지 않습니다.

⇒ 이렇게 하면, 결제페이지에서 예약페이지로 뒤로가기 할 때는 reserveId를 사용해서 예약데이터에 접근이 가능하다.
뒤로가기가 아니라 아예 다른 페이지로 이동할 때는 reserveId를 가지고 있지 않으니까 예약데이터에 접근이 안 된다.
사용자가 다시 동일한 숙소의 예약페이지로 오면 새로 예약데이터가 생성된다.

근데 그러면 어찌되었든 간에 결제까지 완료되지 않은 예약데이터가 생길 수밖에 없다. 우리 흐름에서 이걸 아예 막을 수는 없다.
→ 이건 시간이 지나면 isPaidfalse인 데이터를 삭제하든가 따로 처리해야 할 것 같다.(생각나는 방법이 이것뿐..)

그런데 만약 여기에 임시예약 방법을 사용한다면, 예약페이지에서 숙소 상세페이지로 뒤로가기(혹은 아예 다른 페이지로 이동)를 할 때 임시예약 데이터가 결국에는 쌓이게 된다.
그러면 결제페이지에서 예약페이지로 뒤로가기를 할 때 쓸데없이 쌓이는 데이터를 줄이기 위해 이걸 하는 건데 다른 쪽에서 결국엔 같은 문제가 발생하는 것이니까 의미가 없어지는 것 같다.

임시예약 말고 현재 하던 방법대로 한다면 예약페이지에서 다른 페이지로 이동하는 것은 상관하지 않아도 된다.
이 방법은 결제페이지에서 예약페이지로 뒤로가기를 하는 것만 해결하고 다른 페이지로 이동해버리면 isPaidfalse인 그 데이터는 그대로 남아있게 된다.
아니면 결제페이지에서 라우팅을 할 때 뭔가 처리할 수 있나?

✅ 방법 2

A.
결제가 완료되면 전역 상태에서 reserveId를 삭제하거나 초기화하는 것이 좋습니다. 이렇게 하면 사용자가 다른 예약을 시작할 때 이전 예약의 reserveId가 영향을 주지 않도록 할 수 있습니다.
Recoil을 예로 들면, 전역 상태를 관리하는 Atom을 사용하여 reserveId를 저장하고 관리할 수 있습니다. 결제가 성공적으로 완료된 후에는 해당 Atom의 값을 초기화하거나 삭제하여 다음 예약 프로세스에 영향을 미치지 않도록 할 수 있습니다.
예를 들어, reserveId를 관리하는 Atom이 다음과 같이 정의되어 있다고 가정해 보겠습니다.

// atoms.js
import { atom } from 'recoil';
.    
export const reserveIdState = atom({
	key: 'reserveIdState', // 고유한 키
    default: '', // 기본값
});

결제 완료 후 reserveId 상태를 초기화하는 방법은 다음과 같습니다.

import { useRecoilState } from 'recoil';
import { reserveIdState } from './atoms';
  
function PaymentSuccess() {
	const [reserveId, setReserveId] = useRecoilState(reserveIdState);
   
	// 결제 성공 처리 함수
    const handlePaymentSuccess = () => {
        // 로직 처리 ...

        // reserveId 상태 초기화
        setReserveId('');
	};
   
	return (
        <div>
        	{/* 결제 성공 UI 및 로직 */}
			<button onClick={handlePaymentSuccess}>결제 완료 처리</button>
        </div>
    );
}

이러한 방식을 통해, 애플리케이션의 다른 부분에서 reserveId를 참조할 때, 결제가 완료되지 않았거나 다른 예약으로 인해 영향을 받지 않도록 할 수 있습니다. 결제 프로세스가 완료되면 상태를 깨끗이 정리하여 다음 동작에 대비하는 것이 좋습니다.

A.
예약하기 페이지에서 '예약' 버튼을 눌러 예약 데이터를 서버에 저장한 후, 서버로부터 받은 reserveId를 Recoil의 Atom을 이용해 전역 상태로 저장할 수 있습니다. 이렇게 하면 이후 결제 페이지에서 이 reserveId를 사용하여 사용자의 결제를 처리하거나, 예약 상태를 업데이트하는 등의 작업을 수행할 수 있습니다.
다음은 reserveId를 전역 상태로 저장하는 과정의 간단한 예시입니다:

  1. reserveId를 저장할 Atom 생성:
// atoms/reserveIdAtom.js
import { atom } from 'recoil';
       
export const reserveIdAtom = atom({
	key: 'reserveId', // 고유한 ID
    default: null, // 초기값은 null 혹은 빈 문자열 등으로 설정 가능
});
  1. 예약하기 페이지에서 예약을 생성하고 reserveId 저장:
import React, { useState } from 'react';
import { useSetRecoilState } from 'recoil';
import { reserveIdAtom } from '../atoms/reserveIdAtom';
import axios from 'axios';
       
export default function ReservationForm() {
	const [formData, setFormData] = useState(/* 초기 폼 데이터 상태 */);
    const setReserveId = useSetRecoilState(reserveIdAtom); // Recoil 상태 설정 함수
       
	const handleSubmit = async (event) => {
    	event.preventDefault();
        try {
        	const response = await axios.post('/api/reservations', formData);
            const { data } = response;
            // 서버로부터 받은 reserveId를 Recoil Atom에 저장
            setReserveId(data.reserveId);
            // 결제 페이지로 이동 또는 다른 로직 처리
		} catch (error) {
        	console.error('Reservation creation failed:', error); // 에러 처리 로직
        }
	};

    return (
		<form onSubmit={handleSubmit}>
        	{/* 폼 필드 및 '예약' 버튼 */}
		</form>
	);
}

이 방식을 사용하면 사용자가 '예약' 버튼을 클릭할 때 생성된 예약 데이터의 ID를 전역 상태로 관리할 수 있으며, 애플리케이션의 어느 부분에서든 쉽게 접근할 수 있습니다. 이후 사용자가 결제 페이지로 이동했다가 다시 예약 페이지로 돌아오더라도, 이미 생성된 예약 ID를 참조하여 예약 정보를 업데이트하거나 확인할 수 있습니다.

⇒ 방법 1보다 복잡하지만, 전역으로 저장해서 상태 관리를 할 수 있다.
→ 결제페이지에서 결제하지 않고 다른 페이지로 이동을 해도 reserveId를 가지고 예약데이터를 처리할 수 있다.

예약데이터를 생성(디비에 저장)한 후에, reserveId를 전역 상태로 저장한다.
뒤로가기를 한 경우에는 reserveId를 가져와서 그 예약데이터를 수정하는 방법으로 예약데이터 새로 생성하지 않고 재사용이 가능하다.
다른 페이지로 이동해버린 경우에는 저장된 reserveId의 예약데이터를 삭제한 후에 전역 상태로 저장해뒀던 reserveId를 삭제하면 된다.
→ 대신 여기서 문제는, 다른 페이지로 이동하는 경우에 뒤로가기가 포함된다. 뒤로가기를 제외하는 로직이 필요할 것 같다.
(이후에 방법을 조금 바꿔서 보다 간단하게 해결함)


방법도 정했고 어떻게 사용하면 좋을지 머릿속에서 정리가 되었다.
이런 저런 상황을 고려해서 고민해봤는데 구현했을 때 깔끔하게 처리가 되었으면 좋겠다.

profile
It's me, jkeum!

0개의 댓글