Vanilla JS로 구현한 클래스 컴포넌트의 렌더링 이슈

💛 nalsae·2023년 5월 9일
1

🔥 트러블 슈팅

목록 보기
1/7
post-thumbnail

 이번 글에서는 캘린더 웹 애플리케이션 "피플(Piece-Plan)" 프로젝트를 진행하면서 마주쳤던 가장 큰 이슈 중 하나를 소개하고자 한다.

📂 컴포넌트 구조

 먼저 해결 과정을 소개하기 전에 프로젝트의 컴포넌트 상속 구조를 간략하게 표현하면 위와 같다. 부모 클래스인 common/Component로부터 상속 받는 Main, Login, Signup 등 다양한 자식 클래스를 기반으로 컴포넌트(이자 페이지)를 구현했었다. 코어 컴포넌트인 Component의 구조를 코드로 보면 다음과 같다.

class Component {
 constructor(props) {
   this.props = props;
   this.setEvent && addEventHandlers(this.setEvent());
 }

 setState(newState) {
   this.state = { ...this.state, ...newState };

   render();
 }

 async patchState(callback, param) {
   try {
     await callback(param);
     render();
   } catch (e) {
     console.error(e);
   }
 }

 changePage(path) {
   window.history.pushState(null, null, path);

   render();
 }
}

 이처럼 부모 클래스인 Component를 상속 받는 자식 컴포넌트들을 생성하는 것까지는 문제가 없었다. 그런데 각자 작업한 크고 작은 컴포넌트를 결합하는 과정에서 자잘한 렌더링 이슈들이 빈번히 발생하는 것이었다.


🔨 해결 과정

🐛 마주한 이슈들

 렌더링과 관련하여 크게 3가지 이슈를 마주했는데, 소개하자면 다음과 같다.

  • 로고(상단 사진의 빨간 부분)를 클릭하면 메인 페이지가 아니라 모달 컴포넌트가 렌더링되는 이슈
  • 다른 날짜를 클릭해도 맨 처음 클릭한 날짜의 상세 정보 모달 컴포넌트 상태가 유지되는 이슈
  • 모달 컴포넌트의 피스(상단 사진의 파란 부분) 클릭 시 렌더링이 정상적으로 되지 않는 이슈

❓ 이슈의 원인

 처음에는 Routing 구현을 잘못했나 싶었는데 Routing에는 문제가 없었다. 원인이 무엇인고 하니 상위 컴포넌트에서 하위 컴포넌트를 렌더링할 때 props를 전달하는데, 그 중에 전체 캘린더에서 날짜를 선택했을 때 저장되는 selectedDate 상태 값이 초기화되지 않아서 발생하는 오류였다.

⭐ 해결 과정

 selectedDate 값이 초기화되지 않은 이유는 각자 작업한 컴포넌트를 부모 자식 관계로 결합하면서 this 바인딩이 일치하지 않는 데 있었다. 즉 최상위 컴포넌트에서 this를 바인딩시켜서 하위 컴포넌트의 props로 전달해야 하는데, 중간에 위치한 Modal 컴포넌트에서 this를 바인딩시켰기 때문에 정상적으로 값의 초기화가 이루어지지 않은 것이었다. 이는 this를 제대로 바인딩함으로써 문제를 해결할 수 있었다. 구체적인 과정과 코드는 다음과 같다.

이슈가 발생했던 컴포넌트 관계

: Calendar > Modal(여기서 this 바인딩) > DailyDetail

이슈가 해결된 컴포넌트 관계

: Calendar(여기서 this 바인딩) > Modal > DailyDetail

class Calendar extends Component {
  async render() {
    return `
    // bind를 사용하여 최상위 컴포넌트인 Calendar의 this를 바인딩 //
     ${new Modal({ ...this.state, filteredPlan, pieces, 
                  filterPieces: this.filterPieces.bind(this), 
                  resetModalData: this.resetModalData.bind(this), 
                  changeDatePage: this.changeDatePage.bind(this) }).render()}`;
   } catch (e) {
     console.error(e);
   }
 }

🤔 느낀 점

 사실 논리적으로만 생각했을 때는 seledtedDate라는 상태 값을 어차피 DailyDetail 컴포넌트에서만 사용하기 때문에 Modal 컴포넌트에서 값을 초기화하여 props로 전달해줘도 무방하다고 판단했다. 그래서 최상위 컴포넌트의 this를 바인딩하기 전에 하위 컴포넌트에서 상위 컴포넌트로 props를 전달할 수 있는 방법이 있는지 몇 시간씩 고민하고 구글링도 했던 기억이 난다. 그러나 React 환경이 아닌 Vanilla JS에서는 하위 컴포넌트에서 상위 컴포넌트로 props를 전달하는 방법을 찾기 어려웠다. 그리고 애초에 하위 컴포넌트에서 상위 컴포넌트로 props를 전달하는 것은 위에서 아래로 흐르는 컴포넌트 구조를 역행하는 것이기 때문에 React를 적용한 프로젝트 환경이었다고 하더라도 좋지 않은 해결 방법일 것이다. 여튼 이처럼 불필요한 Props Drilling 현상을 Vanilla JS 환경에서는 해결하기 어려웠기 때문에 React와 상태 관련 라이브러리의 필요성을 절실히 느꼈다. 또한 this 사용의 까다로움 역시 여실히 체감하는 계기가 되었다.

profile
𝙸'𝚖 𝚊 𝚍𝚎𝚟𝚎𝚕𝚘𝚙𝚎𝚛 𝚝𝚛𝚢𝚒𝚗𝚐 𝚝𝚘 𝚜𝚝𝚞𝚍𝚢 𝚊𝚕𝚠𝚊𝚢𝚜. 🤔

0개의 댓글