๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
ํ™ˆ > ๋ ˆ๋ฒจ์—…์˜ ํ…Œํฌ๋…ธํŠธ

[ํ”„๋ก ํŠธ์—”๋“œ] ClientOnly ์ปดํฌ๋„Œ๋“œ ๊ฐœ๋ฐœ ์—ฌํ–‰

by ์•Œ ์ˆ˜ ์—†๋Š” ์‚ฌ์šฉ์ž 2022. 1. 12.

๐Ÿ“Œ ๋ชฉ์ฐจ

  • ์„œ๋ก 
  • Vue SSR์˜ ๊ธฐ๋ณธ์ ์ธ ์„ค๋ช…
  • ์ฝ”๋“œ ์„ค๋ช…
  • ๊ฒฐ๋ก 
  • ์ฐธ๊ณ ์ž๋ฃŒ

๐Ÿ“Œ ์„œ๋ก 

์•ˆ๋…•ํ•˜์„ธ์š”. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋กœ ์ผํ•˜๋Š” ์ตœ์ข…์„ ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ €ํฌ ํšŒ์‚ฌ๋Š” Nuxt๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  Vue๋ฅผ ์ž์ฒด ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜์—ฌ SSR์„ ๊ตฌํ˜„ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ํ•„์š”์— ๋”ฐ๋ผ ์ปดํฌ๋„ŒํŠธ ์ „์ฒด์˜ ๋žœ๋”๋ง ์‹œ์ ์„ ๊ฒฐ์ •ํ•˜๋Š” Nuxt์—์„œ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋”ฐ๋กœ ์ œ์ž‘ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ์— ๋”ฐ๋ผ ์ด ๊ธ€์—์„œ๋Š” ์‚ฌ์šฉ๋ฐฉ๋ฒ• ๋ฐ ๊ตฌํ˜„ ๋ฐฉ์‹์„ ์„ค๋ช…ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์žฌ๋ฐŒ๊ฒŒ ์ฝ์–ด์ฃผ์„ธ์š”~! ๐Ÿ™‡๐Ÿป‍โ™‚๏ธ

๐Ÿ’ก Nuxt์—์„œ client-only ์ปดํฌ๋„ŒํŠธ๋ž€?
ClientOnly ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์‹์š”์†Œ๋“ค์„ client-side์—์„œ ๋žœ๋”๋ง ์‹œํ‚ต๋‹ˆ๋‹ค.

๐Ÿ“Œ Vue SSR์˜ ๊ธฐ๋ณธ์ ์ธ ์„ค๋ช…

์ผ๋‹จ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•ด์„œ ์กฐ๊ธˆ ๋” ๊นŠ๊ฒŒ ์ดํ•ด๋ฅผ ํ•˜์ž๋ฉด ๋จผ์ € customized vue ssr ๋ถ€๋ถ„์„ ๋จผ์ € ์ดํ•ด๋ฅผ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ณดํ†ต SSR์ผ ๋•Œ๋Š” server์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ๋งŒ๋“  static ํ•œ HTML ํŒŒ์ผ์ด ํ•˜๋‚˜๊ฐ€ ๋–จ์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Client side์— ์™”์„ ๋• Client Bundle๋กœ ์ด์ œ javscript code ์‚ฝ์ž… (hydrate)์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Server Side → Static HTML → Client Side → HTML์— script ์ฝ”๋“œ ์‚ฝ์ž… (hydrate) → ์ดํ›„ ๋ชจ๋“  ๋™์ž‘์€ CSR(SPA)๋กœ ๋™์ž‘

๊ทธ๋ž˜์„œ ์–ด๋–ค side์ด๋ƒ์— ๋”ฐ๋ผ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋Š” ์ด๋ ‡๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  Server Side Client Side
beforeCreate V  
create V  
beforeMount   V
mount   V

๐Ÿ“Œ ์ฝ”๋“œ ์„ค๋ช…

์ด์ œ ํ•œ๋ฒˆ ์ „์ฒด ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณผ๊นŒ์š”? ์ผ๋‹จ ์ „์ฒด ์ฝ”๋“œ๋Š” ์ด๋ ‡๊ฒŒ ์งœ์—ฌ์žˆ์Šต๋‹ˆ๋‹ค.

export default {
  name: 'ClientOnly',
  functional: true,
  render(h, { parent, slots }) {
    const { default: defaultSlots = [] } = slots();

    if (parent._isMounted) {
      return defaultSlots;
    }

    parent.$once('hook:mounted', () => {
      parent.$forceUpdate();
    });
    return defaultSlots.length > 0 ? defaultSlots.map(() => h(false)) : h(false);
  },
};

๊ทธ๋Ÿผ ํ•œ ์ค„ ํ•œ ์ค„์”ฉ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

render(h, { parent, slots }) {
    // โญ๏ธ ๋จผ์ € slots์— ํ•ด๋‹นํ•˜๋Š” ๊ฒƒ๋“ค์„ ๋ฐฐ์—ด๋กœ ์„ ์–ธํ•ด ์ค๋‹ˆ๋‹ค.
    // ex>
    // <client-only>
    //   <Comp1/>
    //   <Comp2/>   
    // </client-only>
    // defaultSlots = [Comp1, Comp2]
    const { default: defaultSlots = [] } = slots();
  },
};

 

 

render(h, { parent, slots }) {
    // โญ๏ธ ์œ„์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ mounted๊ฐ€ ํ˜ธ์ถœ์ด ๋œ๋‹ค๋ฉด,
    // ์ด๋ฏธ client side์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ƒฅ children์„ render ํ•ฉ๋‹ˆ๋‹ค.
    if (parent._isMounted) {
      return defaultSlots;
    }
  },
};

 

 

render(h, { parent, slots }) {
    // โญ๏ธ ๋งŒ์•ฝ ์œ„ if (parent._isMounted)์—์„œ ๊ฑธ๋Ÿฌ์ง€์ง€ ์•Š์•˜๋‹ค๋ฉด ์ง€๊ธˆ์€ server side์ž…๋‹ˆ๋‹ค.
    // ๊ทธ๋ž˜์„œ parent๊ฐ€ mounted๋œ ์‹œ์ (client-side)์— re-render์„ ํ•ด์ค๋‹ˆ๋‹ค.
    parent.$once('hook:mounted', () => {
      parent.$forceUpdate();
    });
  },

 

 

render(h, { parent, slots }) {
    // โญ๏ธ ์œ„ if (parent._isMounted)์—์„œ ๊ฑธ๋Ÿฌ์ง€์ง€ ์•Š์•˜์œผ๋‹ˆ 
    // slot์œผ๋กœ ๋“ค์–ด์˜จ ์•„์ด๋“ค์˜ render๋ฅผ ๋ง‰์•„์ค๋‹ˆ๋‹ค.
    return defaultSlots.length > 0 ? defaultSlots.map(() => h(false)) : h(false);
  },
};

์ด๋ ‡๊ฒŒ ํ•ด์ฃผ์–ด์„œ server-side์˜ rendering์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.(Nuxt์™€ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๋™์ผ)

<!-- Comp1์€ csr -->
<client-only>
  <Comp1 />
</client-only>
<!-- Comp2๋Š” ssr -->
<Comp2 />

๊ทธ๋Ÿผ ์ €ํฌ ํ”„๋กœ์ ํŠธ์— Header์— ClientOnly๋ฅผ ํ•œ๋ฒˆ ๊ฑธ์–ด๋ณผ๊นŒ์š”?

๐Ÿ“Œ ๊ฒฐ๋ก 

์ด๋ ‡๊ฒŒ ํ•œ๋ฒˆ nuxt์—์„œ์˜ client-only ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  nuxt์—์„œ๋Š” placeholder์˜ ๊ธฐ๋Šฅ๊นŒ์ง€ ์žˆ์ง€๋งŒ ๋ ˆ๋ฒจ ์—… ํ”„๋กœ๋•ํŠธ ๋‚ด์—์„œ๋Š” ํ•ด๋‹น ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์•„ ๋”ฐ๋กœ ๊ตฌํ˜„์„ ํ•ด๋†“์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์žฌ๋ฐŒ๊ณ  ์ฆ๊ฒ๊ฒŒ client-only๋ฅผ ์‚ฌ์šฉํ•ด ์ฃผ์‹œ๊ธฐ๋ฅผ ๋ฐ”๋ผ๋ฉด์„œ ๊ธ€์„ ๋งˆ์นฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ๊ธด๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ! ๐Ÿ™‡๐Ÿป‍โ™‚๏ธ

๐Ÿ“Œ ์ฐธ๊ณ ์ž๋ฃŒ

๋Œ“๊ธ€