유저의 입력에 반응하기 로딩 화면과 결과 없음 : Event loop, Class

nnm·2020년 3월 27일
16
post-thumbnail
post-custom-banner

프로그래머스 2020 Dev-Matching : 웹 프론트엔드 과제 복기
https://github.com/woohyeonjo/ilovecat

웹 서비스를 이용하는 중에 입력을 했는데 아무런 반응이 없으면 어떨까? 아마 다시 누르고 또 다시 누르다가 무언가 잘못되었다고 느낄 것이다. 그런데 문제가 생긴 것이 아니라 요청한 작업이 오래걸리는 작업이라서 눈에 보이는 반응이 없었을 뿐 사실은 열심히 작업을 하고 있었다면? 계속해서 새로운 입력이 들어와서 기존 작업이 취소되거나 딜레이 될 것이다. 따라서 쾌적한 UX를 위해서는 유저의 요청에 따른 즉각적인 반응을 보여야한다.

이번 프로젝트에서로딩 화면검색 결과 없음 화면 구현을 통해서 유저의 요청에 따른 즉각적인 반응을 생각해보았다.

로딩 화면

로딩 화면은 언제 보여야할까? 바로 검색 요청 직후 부터 결과 화면이 랜더링되기 직전까지다. 유저가 검색을 요청하면 로딩 화면이 즉각적으로 나타나면서 유저의 요청을 처리하고 있는 중이라는 것을 나타내고, 결과 화면이 나타나기 직전에 로딩 화면이 없어지면서 요청에 대한 작업을 완료했음을 보여줘야한다.

그렇다면 아주 간단하게도 검색 이벤트에 로딩 화면을 띄워주는 함수를 실행하고 결과화면이 나타나기 직전에 로딩 화면을 감추는 함수를 실행하면 되는 것이 아닌가?

  function searching() {
      showLoadingScreen();
      callSearchingAPI();
      hideLoadingScreen();
      showResultScreen();
  }

하지만 위와 같이 작성할 경우에는 로딩 화면이 보이지 않는다. 자바스크립트의 비동기 요청을 처리하는 방식 때문이다. 따라서 비동기 요청을 수행하는 함수를 신경써서 작성해야한다.

  onSearch: async keyword => {
      loading.toggleSpinner();

      const response = await api.fetchCats(keyword);
      if(!response.isError){
        setItem('data', response.data);
        resultsSection.setState(response.data);
        loading.toggleSpinner();
      } else {
        error.setState(response.data);
      }
  }

위의 코드는 이번 프로젝트에서 작성한 검색 요청에 대한 이벤트다. 비동기 처리를 위해 async, await을 사용하였다. onSearch 이벤트가 호출되는 즉시 첫 줄에 loading.toggleSpinner()을 통해서 로딩 화면을 띄워주게 된다. 그 후에 검색 결과가 화면에 랜더링된 후에 다시 loading.toggleSpinner()을 통해서 로딩화면을 숨겼다.

결과화면 랜더링 전에 로딩 화면을 숨기지 않고 랜더링 후에 숨긴 이유는 혹시 랜더링하는 과정이 오래걸려서 로딩 화면이 사라졌는대도 유저가 결과 화면을 바로 보지못할 경우가 생기지 않을까 싶어서다.

검색 결과 없음 화면

검색 결과 화면이 나타날 때는 두 가지 경우가 있다.

  • 이전 결과 화면이 있는 상태에서 다른 검색을 수행한 경우
  • 결과 화면이 없는 상태에서 검색을 수행한 경우

만약 검색 결과가 없음을 나타내는 화면이 없다면 어떨까?

  • 이전 결과 화면이 있는 상태
    검색이 안된건가? 아니면 결과가 같은 건가?
  • 결과 화면이 없는 상태
    검색 기능이 작동하지 않는다?

위와 같은 혼동을 없애기 위해서 검색 결과가 없을 때는 없다는 것을 표현해줄 화면이 필요하다. 로직은 아래와 같다.

API 호출에 따른 Response에 데이터가 있는가 없는가에 따라서 분기하여 다른 화면을 랜더링하면 되겠다. 그렇다면 결과 화면 컴포넌트를 만들고 API 호출의 결과만 넘겨주면 자동으로 랜더링 되도록 하면 좋을 것 같다. 여기서는 자바스크립트의 Class를 사용하였다.

export default class ResultsSection {
    constructor({...}) {
        ...
        this.render();
      	...
    }
    
    setState(data) {
      	// 상태가 변화할 때 마다 다시 랜더링한다.
        this.data = data;
        this.render();
        ...
    }
      
    render() {
      	// API 요청을 하지 않아 데이터가 전혀 존재하지 않음
        if(!this.data) return;
        this.section.innerHTML = '';
        
        if(this.data.length > 0){
          // 받아온 데이터가 있을 때
        	...           
        } else {
          // 받아온 데이터가 없을 때
        	...
        }
    }
}

작성하고 보니 위의 로직에는 문제가 있었다. 바로 페이지에 처음 접속 했을 때는 API 요청을 하지 않아서 데이터가 없기 때문에 검색 결과 없음 화면을 띄우게 되기 때문이다. 따라서 해당 부분은 따로 처리 해줘야했다.

따라서 위와 같은 로직이 되겠다.

profile
그냥 개발자
post-custom-banner

1개의 댓글

comment-user-thumbnail
2020년 6월 8일

글을 맛깔나게 잘쓰시네요 ㅋ 감사합니다.

답글 달기