벤티의 개발 로그

[React] 새로고침 '더' 잘 하기 본문

카테고리 없음

[React] 새로고침 '더' 잘 하기

sonsh75 2025. 12. 20. 21:28

지난 글

지난 글에서는 단순히 기술적으로, 새로고침을 처리할 수 있는 여러 가지 방법들을 나열해서 정리했다.

 

[React] 새로고침 '잘' 하기

에피소드 1현재 진행하고 있는 프로젝트는 Web View로 되어 있기 때문에, 프론트엔드와 모바일 간 통신과 호환성이 굉장히 중요하다. 다행히 현재까지 개발하고 있던 코드에는 큰 문제가 없었다.

ventilog.tistory.com

 

그리고 당시에는 location.reload(), window.location.href, history.go(0) 사용하면 구현할 수 있는 수준의 업무를 맡았다.

 

하지만 이번에는 그렇지 않았다.

 

더 나은 UX를 고려한 새로고침

최근 업무를 진행할수록 UX를 고려하는 개발이 얼마나 중요한지를 알게 되었다. 특히나 '타이밍'이 중요한 도메인과 서비스를 맡고 있는 만큼 사소한 UX 차이가 서비스 이용률의 차이를 만들 수 있었다.

 

내가 개발을 맡은 이벤트 페이지의 구성은 아래와 같았다.

정확한 이미지를 캡쳐할 수 없기에 다이어그램으로 대체했다.

 

좌측 이미지는 사용자가 최초로 이벤트 페이지에 진입했을 때 이미지로, 배너 이미지가 페이지 상단을 가득 채웠다. 그리고 가운데 이미지처럼, 그 아래로 체크인 미션 현황을 나타내는 스탬프 북과 체크인을 할 수 있는 버튼이 나란히 배치되어 있다.

 

즉, 화면 크기가 어마어마하게 크지 않은 이상 체크인을 하려면 반드시 스크롤을 내린 후 버튼을 눌러야 했다.

 

잠시 내가 사용자라면 체크인 버튼을 누르고 우측 이미지에 뜨는 팝업을 닫는다면, '화면이 어떻게 바뀌어야 할까?'라는 고민을 해봤다. 제일 자연스러운 것은 곧바로 미션 현황이 업데이트 된 후, 버튼이 비활성화 되는 것이라고 생각했다.

 

그렇게 긴 여정이 시작되었다.

 

Step 1: location.reload()를 대체하자

이벤트 오픈 기한이 얼마 남지 않아 가장 빠른 방법을 채택해야했고, 따라서 처음에는 이전 업무에서 사용했던 location.reload()를 사용했다.

 

그랬더니 아래와 같은 문제가 발생했다.

 

만약 내가 사용자라면 체크인 버튼을 누르고 뜨는 팝업을 닫았을 때, 곧바로 Check-In Stamp 영역에서 업데이트된 현황을 확인하고 싶을 것이라고 생각했다. 하지만 location.reload()를 사용했더니, 체크인 버튼을 누른 후에 화면이 페이지 상단으로 이동하여 현황을 곧바로 확인할 수가 없었다.

 

게다가 체크인 버튼 밑에 또 다른 미션이 있었기 때문에, 기존처럼 location.reload()를 사용해서 사용자의 화면을 페이지 상단으로 이동시키면 다른 미션의 참여율이 떨어질 우려가 있었다.

 

Step 2: fetch API 전후로 state를 적절하게 사용하자

그래서 계획을 수정했다. 우선 코드에 아래처럼 서버에 전체 이벤트 현황을 불러오는 fetch API가 있었다.

useEffect(() => {
    fetchInfo();
}, []);

 

이 API를 Check-In Button을 누른 직후 실행해서, 사용자가 Check-In 후 뜨는 팝업을 닫으면 곧바로 업데이트된 현황을 확인하게 하고 싶었다.

 

따라서 Check-In Button에 '해당 날짜에 Check-In을 했는 지 확인하는' state를 추가했고, 서버로 POST 요청을 보낸 후 fetch API를 재실행하면 자연스럽게 현황이 업데이트 될 것이라고 생각했다.

 

그런데 그러지 않았다. 제대로 DB에 데이터는 저장되었으나, fetch API의 응답이 곧바로 반영되지 않아 Check-In버튼이 계속 활성화되고 있었다.

 

Step 3: Check-In 팝업 전후로 state를 적절하게 사용하자

처음에는 이 문제의 해결 방향을 제대로 잡지 못해서 navigate 함수와 window.location.href를 조합하였으나, 시행착오 끝에 결국 state를 몇 개 더 추가해야 한다는 것을 깨달았다.

 

우선 아래처럼 Check-In 버튼을 비활성화(setCurDayEnable(false))하는 위치를, 팝업을 닫은 직후로 옮겼다.

function PopupCheckin() {
    const [isOpen, setIsOpen] = useState(true);

    const handleClose = (e) => {
        setIsOpen(false); // 팝업 닫기
        setCurDayEnable(false);  // 팝업 닫을 때 Check-In 버튼 비활성화
        e.preventDefault();
        DimmedOut(e.target);
    };

    const handleSaveCheckin = () => {
        startAdInterstital();
        setIsOpen(false);
    };
    
    /// 생략
 }

 

기존에는 Check-In 버튼을 비활성화하는 타이밍이 fetch API의 응답을 받은 후로 설정되었기 때문에, 별도의 페이지 새로고침 없이는 곧바로 반영되지 않는 문제가 있었다. 그래서 위처럼 state가 바뀌는 위치를 조정하여 문제를 해결할 수 있었다.

 

Step 4: POST 요청 전후로 state를 적절하게 사용하자

const checkinReward = (param) => {
    try {
        axios.get(
            '/post/end-point',
            { headers: { Authorization: `Bearer ${token}` } }
        )
        .then(async (accessData) => {
            if (accessData && accessData.data && accessData.data.result === 'success') {
                if (accessData.data.result_code === 1) { // result_code가 1일 때 - 정상 처리
                    // window.location.reload();
                    // 데이터 업데이트 후 curDayEnable을 false로 설정
                    await fetchInfo();
                    setCurDayEnable(false);
                } else if (accessData.data.result_code === 0) {
                    ToastTopText(accessData.data.result_text);
                }
            }
        });
    } catch (errorData) {
        console.error('Error during checkInReward:', errorData);
    }
};

 

그리고 location.reload()로 처리 중이던 기존 새로고침 코드도 수정했다.

 

우선 팝업이 화면에 나타난 직후 닫기 버튼을 누를 경우도 고려하여, POST 요청 전후에도 Check-In 버튼을 비활성화(setCurDayEnable(false))하는 로직을 추가했다.

 

그리고 사용자의 전체 이벤트 현황을 불러오는 fetch API를 async/await로 처리하도록 수정했다. (일반적으로 checkInReward 함수에도 async/await 패턴을 추가하는 것이 맞으나, 이 함수는 Android와도 연관되어 있어 그러지 않았다.)

 

완성! (+ 고찰)

다행히 이벤트 오픈 기한 전에 아래처럼 계획했던 것을 모두 구현할 수 있었다!

 

 

시간이 다소 촉박하기는 했지만, 좀 더 나은 UX를 고려해서 새로고침 로직을 수정했다는 뿌듯함이 남았다. 그리고 프론트엔드 개발이 익숙하지 않아서 기본적인 구현에 급급했던 지난 업무와 달리, 주도적으로 뭔가를 해낸 것 같아서 재밌었다!

 

 

[React] Class Component 내부 순차 실행 (in React 18) 1편

약 3달 만의 글, 그리고 짧은 근황정말 오랜만에 블로그에 글을 남기게 되었다. 글또에서 그랬던 것처럼, 취업 후 첫 1달까지는 격주로 글을 업로드했다. 하지만 그 후로는 점점 늘어나는 업무에

ventilog.tistory.com

 

다만 이번에는 지난 글에 작성했던 async/await를 사용하여 문제를 해결하기는 했지만, 더 나은 방법이 분명히 있을 것이라는 의문은 존재한다. 이에 대해서는 나중에 더 깊게 알아봐야겠다!