ECMAScript | TypeScript

Vue.js 2.x SSR시 computed 객체와 template 렌더링 문제

partner_jun 2022. 7. 30. 21:47

정확한 이유는 알 수 없지만 Vue.js 2.x (3버전대로는 경험하지 못했으니)에서 v-디렉티브 사용시 SSR도중 DOM이 렌더링 되지 않는 현상이 때때로 발생한다. 내가 경험했던 케이스는 모두 vuex 데이터를 가공하는 computed 구문 내의 객체를 v-for 혹은 v-if에 사용했을 때 발생했다. 대략 2.3 ~ 2.4부터 경험했던 문제인데 2.7이 되도록 해결되지 않은 것으로 봐선 해결이 쉽지 않은 문제로 보인다.

 

이 문제는 정말 골치아픈 것이, computed로 처리하는 객체를 템플릿에 {{ object }} 구문 등으로 직접 노출시에는 데이터가 담겨있지 않지만, 라이프사이클에서 객체를 stdout으로 출력시에는 의도한대로 데이터가 담겨 출력된다. 심지어 data에 computed된 데이터를 삽입할 때에도 의도한대로 작동한다. 아래에도 적겠지만 watch쪽 문제로 템플릿 렌더링 이후 computed 객체가 갱신되어 발생하는 문제로 보이지만 근본적인 원인과 해결 방법을 찾기는 귀찮기도 하고 현실적으로 Vue.js 3로 넘어가야 할 시기이기에 의욕이 생기질 않는다...

 

아무튼 직면한 문제만을 해결하기 위해 내가 사용했던 방법은 아래 세가지다.

  • DOM의 위치, key를 변경한다.
    • 화면에 노출될 DOM의 렌더링 순서를 변경한다. 물론 CSS를 이용하여 의도한대로 노출되도록 하는 추가 작업이 필요하다.
  • Vuex에 데이터를 넣기 위한 action / mutation 구문의 호출 순서를 변경한다.
    • mutation간 호출 순서나 api 호출 이후 함수 실행 등, 순서를 변경하는 것으로대부분의 문제가 해결된다.
      • A.SET_1(...)와  B.SET_2(...) 두개 mutation의 순서 변경만으로도 해결될 수 있다.
        (이렇게 해결되는 것을 보면 computed를 호출하는 watch쪽 문제로 보인다)
  • 비어있는 serverPrefetch 메소드를 작성한다.
    • routeEnter 등 Vue Router 라이프사이클에서 실행된 로직과 관련된 문제는 비어있는 async serverPrefetch 메소드를 선언하는 것만으로도 해결된다.
      (보는 순간 지워버리고 싶은 함수가 되므로 주석 처리가 필요할 것이다)

이게 말이 되나 싶은 내용들이지만 실제로 해결된다는게 적는 나로서도 어처구니가 없다.