FrontEnd/Vue.js

[Vue/nuxt] mounted에서 $ref undefined 해결하기(<client-only> 이슈)

김평범님 2022. 5. 2. 22:00
반응형

vue.js client-only $ref 해결하기

📌최근 발생한 문제점 $ref undefined

mounted()에서 $ref에 접근을 해서 무언가를 적용을 하려고 해 봤는데,

$ref에 접근이 안되고 undefined가 뜨는 오류가 발생했다.

 

무엇이 문제인지 찾아본 결과 

<client-only>안에 있는 $ref에 접근을 할 때,

초반에 undefined가 발생할 수 있다는 점을 찾아냈다.

 

이러한 상황은 왜 발생하는걸까?

먼저 이 문제를 알기 위해서는 <client-only>를 왜 사용하는지를 알아야 했고,

SSRCSR의 차이를 먼저 이해해야 되어서 

오늘은 이 부분을 정리해보기로 했다!

 

 

⚙️SSR이란?

Server Side Rendering이라고 해서

Server에서 렌더링이 된 HTML 화면을 만들어서 보내주는 방식을 말한다.

 

SSR 실행 과정

SSR로 처리가 된다고 하면 모든 리소스를 서버에서 랜더링 한 다음에

클라이언트 쪽에 Return을 해주기 때문에 페이지를 모두 구성하는데 서버 측에 부담이 있으나

받기만 한다면 바로 완성된 화면을 띄울 수 있어 초기 로딩 속도가 빠르다.

 

 

🧾CSR이란?

SSR과 반대되는 경우가 CSR(Client Side Rendering)이 있다.

Client Side Rendering이라고 해서

서버에서 HTML과 Javascipt를 함께 보내서

클라이언트에서 두 파일을 받아 같이 랜더링을 하는 것을 말한다.

CSR 랜더링 과정

 

CSR의 경우 일단 페이지가 뜨나, 처음 빈 페이지가 뜨고,

그다음에 화면을 그릴 자바스크립트와 HTML 읽어 Rendering 실행하기 때문에

SSR보다 초기 로딩 시간은 더 오래 걸린다.

 

 

🎁vue + Nuxt.js

Vue에서 SSR처리를 위한 프레임워크는 바로 nuxt.js이다.

나의 경우도 Nuxt를 이용해서 프로젝트를 구성을 많이 하고 있다.

 

하지만, SSR를 구현을 했지만 필요에 따라서 CSR이 필요한 부분들이 있었다.

이럴 때 이용하는 것이 바로 <client-only> 컴포넌트였다.

 

<client-only>

<client-only> 컴포넌트 안에 들어있는 자식 요소들은 클라이언트 사이드 랜더링을 진행하게 된다.

<template>
  <div>
    <sidebar />
    <client-only placeholder="Loading...">
      <!-- this component will only be rendered on client-side -->
      <comments />
    </client-only>
  </div>
</template>

위의 예시를 보면 client-only안에 있는 comments는 CSR로 호출을 할 수 있고

Client Side에서 그려지는 동안 Placeholder에 작성된 텍스트가 표시되게 됩니다.

 

 

<no-ssr>

Nuxt.js v2.9.0 버전 전에는 <no-ssr>를 사용했으나,

위 버전 이상부터는 <client-only>로 변경되었으니,

최신 버전에서는 <client-only>를 사용하면 된다. 

 

 

 

 

🥲<client-only> 안의 $ref 문제

<client-only> 안에서 $ref가 있어서 해당 요소에 접근을 하려다 보면은

바로 접근이 되지 않은 채  undefined가 뜨는 경우가 있다.

 

이런 경우는 Client에서 Rendering을 해주기 때문에 mounted가 되더라도 

아직 그려지지 않았다면 해당 컴포넌트를 아직 읽을 수 없는 상황인 것이다.

 

Nuxt에서는 $netTick을 이용해서 준비가 될 때를 체크해서 접근을 하는 아래 코드를 제시하고 있다.

mounted(){
  this.initClientOnlyComp()
},
methods: {
  initClientOnlyComp(count = 10) {
    this.$nextTick(() => {
      if (this.$refs.myComp) {
        //...
      } else if (count > 0) {
        this.initClientOnlyComp(count - 1);
      }
    });
  },
}

mounted 시 initClientOnlyComp를 호출해서 

this.$ref가 있는지 없는지를 체크한 뒤 만약 없다면 다시 해당 function을 재호출 한다.

초기 count횟수만큼 해당 function을 재 호출한다.

 

 


관련 포스팅

https://ordinary-code.tistory.com/147

 

[Vue.js] ref undefined일 경우 해결 방법 (this.$nextTick)

🏷️Vue ref란? Vue에서 특정 컴포넌트나 HTML에 접근을 하고 싶을 때는 ref속성을 이용해서 접근이 가능하다. 먼저 아래의 코드로 예시를 보자. /page/ref.vue 상위컴포넌트 입니다. 하위 컴포넌트 클릭

ordinary-code.tistory.com

 

 

 

Reference

https://nuxtjs.org/docs/features/nuxt-components/

 

Built-in Components

Nuxt comes with a few important components included out of the box, which will be helpful when building your application.

nuxtjs.org

https://www.toptal.com/vue-js/server-side-rendered-vue-js-using-nuxt-js

 

Creating Server-side Rendered Vue.js Apps Using Nuxt.js

When initially loading your website, your browser doesn't receive a complete page to display. Instead, it gets a bunch of pieces and instructions of how to put them all together. It takes a substantial amount of time to put all this information together be

www.toptal.com

 

반응형