๐Ÿ“„ Vue 2 โ†’ Vue 3 ์ •๋ฆฌ

๋ฐ•์ค€๊ทœยท2022๋…„ 3์›” 10์ผ
0

Vue

๋ชฉ๋ก ๋ณด๊ธฐ
1/1

โญ๏ธ Composition API(setup)

์ด Composition API๋Š” Vue2 ๊ตฌ์กฐ๋ฅผ ๋ถ•๊ดด์‹œํ‚ค๋Š” API๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ํ˜„์žฌ Vue 3๊ฐ€ ๋‚˜์˜จ์ง€ ์–ผ๋งˆ ์•ˆ ์ง€๋‚œ ์ƒํ™ฉ์—์„œ Compositiion API์™€ Vue 2๋ฅผ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๊ฒฝ์šฐ ๋งค์šฐ ํฐ ํ˜ผ๋ž€์„ ์•ผ๊ธฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•ด์š”.

์ฆ‰ Composition API๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์€ ๊ธฐ์กด์˜ Vue 2๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋˜ ๊ฐ์ฒด ๊ธฐ๋ฐ˜์˜ ์˜ต์…˜ ํ˜•ํƒœ๋ฅผ ์ „๋ถ€ ๋‹ค ๋ถ€์ธํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ์• ์ดˆ์— Vue 3๋ฅผ ๊นŠ๊ฒŒ ๊ณต๋ถ€ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค๋งŒ ์ง„์ง€ํ•˜๊ฒŒ ๊ณต๋ถ€ํ•˜๋Š”๊ฒŒ ๋‚ซ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. (์ „ ์ข€ ๊ณต๋ถ€์ข€ ํ•ด์•ผ๊ฒ ๋„ค์š”..ใ…‹ใ…‹)

๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๊ถ๊ธˆํ•ดํ•  ์ˆ˜ ์žˆ๋Š” data: { return { } }๊ตฌ์กฐ๋ฅผ ์™œ ๋ฒ„๋ฆฌ๊ณ  setup ( ) { }๊ตฌ์กฐ๋กœ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€์— ๋Œ€ํ•ด์„œ๋Š” Evan You(Vue์˜ ์ฐฝ์‹œ์ž)๊ฐ€ ๋‹ต๋ณ€ํ•œ ๊ฒƒ์ด ์žˆ์–ด์š”. ํ•ด๋‹น ๋งํฌ์ธ github issue์˜ ๋‹ต๋ณ€์— ๋”ฐ๋ฅด๋ฉด ๊ฐœ๋ฐœ์ž๋“ค์ด Vue 2 API๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ƒ๋‹นํžˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค๊ณ  ์ด์•ผ๊ธฐ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ํ•ด์š”. ๊ทธ๋ž˜์„œ ์ข€ ๋” ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์—†๋‚˜? ํ•ด์„œ ๋‚˜ ์ด์ œ ์ง„์งœ ๋ณ€ํ•ด๋ณผ๊นŒ? ํ–ˆ๋Š”๋ฐ, Vue 2 ๊ตฌ์กฐ์™€ ์™„์ „ํžˆ ๊ผฌ์—ฌ๋ฒ„๋ฆฐ ๊ดด๋ฌผ?๋กœ ํƒ„์ƒํ•œ๊ฒŒ Composition API์ด๊ณ  ์ด Composition API์™€ Vue 2์˜ ๊ฐ์ฒด ๊ธฐ๋ฐ˜ ์˜ต์…˜๋“ค์ด ํ•œ ๋ฒˆ์— ์„ž์—ฌ์žˆ๋Š” ์ƒํ™ฉ์ด๋‹ˆ ๊ฐœ๋ฐœ์ž๋“ค ์ž…์žฅ์—์„œ ๋”์šฑ ๋‚œ๊ฐํ•œ ๊ฒƒ ๊ฐ™์•„์š”. Vue 3๋ฅผ ์„ค๋ช…ํ•œ ์‚ฌ๋žŒ๋“ค ์ค‘์—๋Š” ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฐ€์ด๋“œ์— ์ด๋Ÿฌํ•œ ๊ฒฝ๊ณ ๋ผ๋„ ํ•ด์คฌ์œผ๋ฉด ์ข‹๊ฒ ๋‹ค๊ณ  ์ด์•ผ๊ธฐ ํ•˜๋˜๋ฐ, ์•„๋ฌด๋ž˜๋„ Vue 3๊ฐ€ Vue 2๋ž‘ ๋‹ฌ๋ผ์ง„๊ฒŒ ์ƒ๊ฐ๋ณด๋‹ค ๋งŽ์•„์„œ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ฒ˜์Œ์— ํ˜ผ๋ž€์„ ๊ฒช์—ˆ์ง€ ์•Š์•˜์„๊นŒ์š”?.

๊ทธ๋ž˜์„œ ๋‹ค๋ฅธ ์ด์•ผ๊ธฐ์ง€๋งŒ, ๋งŒ์•ฝ์— ํ˜„์žฌ ํ”„๋กœ์ ํŠธ๋ฅผ Vue 2๋กœ ์ง„ํ–‰ํ•ด์•ผ ํ•œ๋‹ค๋ฉด, Composition API๋ฅผ ์•Œ๊ณ ๊ฐ€์ง€ ์•Š๊ธธ ๋ฐ”๋ž€๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค...

๊ทธ๋ฆฌ๊ณ  ๋งŒ์•ฝ์— Vue 3๋กœ Composition API๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์ ˆ๋Œ€ Vue 2 ๊ธฐ๋ฐ˜์˜ ์„ค์ •์€ ์—†์—ˆ์œผ๋ฉด ํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค...

๋‹ค ๊ผฌ์—ฌ๋ฒ„๋ฆฐ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ง€์˜ฅ์„ ๋ง›๋ณผ๊ฑฐ๋ผ๋„ค์š”๐Ÿ˜ฑ๐Ÿ˜ฑ๐Ÿ˜ฑ๐Ÿ˜ฑ

๋ณธ๋ก ์œผ๋กœ ๋„˜์–ด๊ฐ€์„œ Composition API๋Š” ์ด๋ฒˆ Vue 3์— ์ฒ˜์Œ์œผ๋กœ ๋„์ž…๋˜๋Š” ํ˜•ํƒœ์ด๋ฉฐ ์ปดํฌ๋„ŒํŠธ ๋‚ด์— setup์œผ๋กœ ๊ตฌ์„ฑํ•˜๊ฒŒ ๋˜์š”. setup์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐ›์„ Props์™€ Context(์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” Attribute์™€ Slots๊ทธ๋ฆฌ๊ณ  Emit)๋ฅผ ์ „๋‹ฌ๋ฐ›์„ ์ˆ˜ ์žˆ๊ณ  ํ•ด๋‹น ๋ถ€๋ถ„์ด ๊ถ๊ธˆํ•˜์‹œ๋ฉด ํด๋ฆญํ•˜์„ธ์šฉ. ๊ณต์‹๋ฌธ์„œ์—์„œ Vue 2 โ†’ Vue 3์˜ ๋ณ€ํ™”๋œ ์ ์„ ๋”์šฑ ์ž์„ธํžˆ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋“œ๋””์–ด ์™œ setup ์•ˆ์—์„œ Reactivity API์ด ํฌํ•จ๋˜์–ด ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์‹ ๊ธฐํ•œ๊ฒŒ Vue 3 ๊ตฌ์กฐ์—์„œ Composition API๋ฅผ ๋‹ด๋‹นํ•˜๋Š” setup์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๊ธฐ ์ „์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋จผ์ € ์ƒ์„ฑ๋˜์—ˆ์œผ๋‹ˆ๊นŒ. this์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ ์ฐธ์กฐ๋ฅผ ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์• ์ดˆ์— setup ์ƒ์„ฑ ์ดํ›„์— ์ฒ˜๋ฆฌ๋  ์ปดํฌ๋„ŒํŠธ์˜ data, methods, computed, watch์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†๋‹ค๊ณ  ํ•ด์š”. ์™œ๋ƒ๋ฉด setup์ƒ์„ฑํ•  ๋•Œ๋Š” component๊ฐ€ ์ƒ์„ฑ๋˜์ง€๊ฐ€ ์•Š์•„์„œ ์ €๊ฒƒ๋“ค์ด ์—†๊ฑฐ๋“ ์š”..ใ…‹ใ…‹

์ƒ๊ฐํ•ด๋ณด๋ฉด ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์› ๋˜ Vue 2๋Š” export default{ ... }์•ˆ์— data, computed, methods, watch๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์ƒ์„ฑํ–ˆ๋˜ ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹ค๊ฒ๋‹ˆ๋‹ค. ์ด ๊ตฌ์กฐ๋Š” component๊ฐ€ ์ƒ์„ฑ๋œ ์ดํ›„์— ์ฒ˜๋ฆฌ๋˜๋Š” ๊ตฌ์กฐ๋‹ˆ๊นŒ this๋กœ ์ ‘๊ทผ(์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋‚ฎ๊ธฐ ๋•Œ๋ฌธ์—)ํ•ด์„œ ํ•˜๋‚˜ํ•˜๋‚˜ ์ฒ˜๋ฆฌํ•ด์ค„ ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ, ์ด๊ฒŒ Vue 3์˜ setup์œผ๋กœ ๋ฐ”๋€Œ๋ฉด์„œ ์ปดํฌ๋„ŒํŠธ๋ณด๋‹ค ๋จผ์ € setup์ด ์ƒ์„ฑ๋˜๋Š”๊ฑฐ์ฃ . ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ์šฐ๋ฆฌ์—๊ฒŒ ์ต์ˆ™ํ•œ data, computed, methods, created, watch ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, Vue 3๊ฐ€ ์ธ์‹์„ ๋ชปํ•œ๋‹ค๋Š” ์ด์•ผ๊ธฐ์ธ๊ฑฐ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค Vue 3 ๊ณต์‹๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด์„œ ์ „ ๊ณ„์† ๐Ÿ˜ก โ† ์ด ํ‘œ์ •์–ด์—ˆ๊ฑฐ๋“ ์š”. ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๋Š” Vue 2, ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๋Š” Vue 3๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋” ํ—ท๊ฐˆ๋ฆฌ๊ณ  ์ดํ•ด๊ฐ€ ์•ˆ๊ฐ€๋”๊ตฐ์š”.

์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฒ„์ „์„ ๋‹ค๋ฅด๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์„ ๋•Œ๋„ ํž˜๋“ค์–ด ํ–ˆ๋Š”๋ฐ, ํ•œ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์šฐ๋ฆฌ์—๊ฒŒ ์ต์ˆ™ํ•œ Vue 2 ๊ตฌ์กฐ์™€ Vue 3์˜ Composition API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ง„์งœ ์ง€์˜ฅ์ด๊ตฌ๋‚˜ ๋ผ๊ณ  ๋ณด์‹œ๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Vue 2์™€ ์™„์ „ํžˆ ๊ผฌ์—ฌ๋ฒ„๋ฆฐ ๊ดด๋ฌผ = Composition API

๊ทธ๋ž˜์„œ Composition API๋ฅผ ์ด์šฉํ•  ๊ฒฝ์šฐ Vue 2 ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ๋‹ค์Œ ํ•ญ๋ชฉ๋“ค์€ setup ํ•จ์ˆ˜ ์•ˆ์— ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.

  • methods
  • data
  • lifecycle hooks(onCreate, created ๋“ฑ)
  • watch

Vue 2 ์—์„œ๋Š” ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ์ค‘๊ด„ํ˜ธ๋กœ ํ•˜๋‚˜ํ•˜๋‚˜ ์ž‘์„ฑํ•˜๋ฉด์„œ ๋ญ‰ํƒฑ์ด๋กœ ๊ตฌ๋ถ„ํ–ˆ๋Š”๋ฐ, Vue 3์—์„œ๋Š” ์ด๊ฑธ ์•„์— ๋ฒ„๋ฆฌ๊ณ  setup์•ˆ์—์„œ๋งŒ ์ž‘์„ฑํ•ด์„œ ์œ ์ง€๋ณด์ˆ˜์™€ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ธ๊ฑฐ ๊ฐ™์•„์š”(๊ฐœ์ธ์ ์œผ๋กœ ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•ด์š” ใ…Žใ…Ž). ๊ทธ๋ฆฌ๊ณ  setup์•ˆ์— return์„ ์‚ฌ์šฉํ•ด์„œ ๋ฐ˜ํ™˜ ๊ฐ์ฒด๋ฅผ ๋‚ด๋ณด๋‚ด๋Š” ๊ฒƒ๋งŒ์œผ๋กœ Vue 3์˜ ์ง„ํ™”๋œ ์ ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์ฃ . ๊ทธ๋ฆฌ๊ณ  ๋”์šฑ ์ค‘์š”ํ•œ๊ฑด setup ์•ˆ์—์„œ ์ƒ์„ฑํ•œ data๋Š” ์ด์ œ this๋กœ ์ ‘๊ทผํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒ์„ฑํ•˜๊ธฐ ์ „์— setup์ด ์ƒ์„ฑ๋˜์–ด์„œ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๊ธฐ ๋•Œ๋ฌธ์— this์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด์ œ ์ด๋Ÿฌํ•œ API ๋˜๋Š” hook์€ ๋ฌด์กฐ๊ฑด importํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Vue 2์—์„œ๋Š” ๊ทธ๋Ÿฐ์ ์ด ์—†์–ด์„œ ์ €๋Š” ์ฒ˜์Œ์— ๋งŽ์ด ํ˜ผ๋ž€์Šค๋Ÿฌ์› ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์ œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

<template>
	<div>
    <h1>์ถœ์ž…๋ฌธ</h1>
    <p>{{ welcomeMessage }}</p>
    <button @click="leave">๋– ๋‚˜๊ธฐ</button>
  </div>
</template>

<script>
import {
  reactive, ref,
  computed, watch,
  onMounted
} from 'vue' // ์“ธ ํ•ญ๋ชฉ์„ ๋ฏธ๋ฆฌ importํ•ฉ๋‹ˆ๋‹ค.
export default {
  // setup ์—์„œ { attribute, slots, emit }์™€ ๊ฐ™์ด ์ž‘์„ฑํ•œ ์ด์œ ๋Š” context๋ฅผ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์ธ๊ฑฐ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  // ์ €๋„ ์ด๊ฑด ์ฐพ์•„๋ณด์ง„ ๋ชปํ–ˆ์–ด์š”.
  setup (prop, { attribute, slots, emit }) {
    const state = reactive({
      name: 'Dooly',
      visitCount: 0
    }) // vue 3 ์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต์ œํ•  ๋•Œ ์ด์ œ data๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  setup๋‚ด์—์„œ vanilla js ์ฒ˜๋Ÿผ ๊ทธ๋ƒฅ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    
    const leave = () => { // methods๋„ ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
      state.visitCount = 0 // ๋ญ”๊ฐ€ Vue 2 ๋ณด๋‹ค ๋” js ์Šค๋Ÿฌ์šด ๋Š๋‚Œ์ด ๋“ค์ง€ ์•Š๋‚˜์š”?
    }
  
    
    // hook์— ํ•ด๋‹นํ•˜๋Š” ํ•ญ๋ชฉ๋“ค์„ ์œ„์—์„œ ์‚ฌ์ „์— importํ•˜๊ณ 
    // setup ์•ˆ์— ์‹คํ–‰ํ•จ์ˆ˜๋ฅผ ๋„ฃ์œผ๋ฉด ํ•ด๋‹น ํ›… ์กฐ๊ฑด์— ๋งž๊ฒŒ ์‹คํ–‰๋˜์š”!
    // ์ฐธ๊ณ ๋กœ Vue 2 โ†’ Vue 3 ๋กœ ๋ณ€๊ฒฝ๋˜๋ฉด์„œ ๋ฐ”๋€ ๋ผ์ดํ”„ ์‚ฌ์ดํด์€ ๊ณต์‹๋ฌธ์„œ์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์–ด์š”!
    // ๋ช…์นญ๊ณผ ์ฃผ๊ธฐ๊ฐ€ ์ข€ ๋ฐ”๋€๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค. Composition API ๋•Œ๋ฌธ์—..
    onMounted(() => {  
      console.log('component mounted!')
    })
    
    const welcomeMessage = computed(() => `${state.name}๋‹˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค`)

    watch( 
      () => state.visitCount,
      (value, prev) => {
        console.log(`${state.name}๋‹˜ ${value}ํšŒ ๋ฐฉ๋ฌธ`)
      }
    )

    // ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋Š” ๊ทธ๋ƒฅ ํ•œ ๋ฒˆ์— return ํ•ฉ๋‹ˆ๋‹ค.
    // ์ด๊ฑด ์ •๋ง ํŽธํ•ด์ง„๋“ฏ
    return { 
      state,
      leave,
      welcomeMessage
    }
  }
}
</script>

์ด๋ ‡๊ฒŒ ๋ณด๋‹ˆ Vue 2 ์™€ Vue 3์˜ ์ฐจ์ด์ ์ด ๋Š๊ปด์ง€์‹œ์ง€ ์•Š๋‚˜์š”??!! ์•ˆ ๋Š๊ปด์ง€๋ฉด ์–ด์ฉ” ์ˆ˜ ์—†์ฃ ..ใ… 

โญ๏ธ Reactivity API (reactive, ref, toRefs, readonly)

๊ธฐ์กด Vue 2์˜ ๋ฌธ์ œ์ ์€ object ์•ˆ์— ์ƒˆ๋กœ์šด key๊ฐ’์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฐ˜์‘ํ˜•์œผ๋กœ ์ธ์‹ํ•˜์ง€ ์•Š์•˜๊ณ , array์•ˆ์— push, slice, shift๋“ฑ์„ ์ด์šฉํ•ด์•ผ๋งŒ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด๋กœ ์ธ์‹ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฌํ•œ ๋ฐ์ดํ„ฐ์˜ ๋ฐ˜์‘์„ฑ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ Proxy API์™€ ๋น„์Šทํ•œ ํ˜•ํƒœ์˜ API๋ฅผ ์ œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด Reactivity API์ธ๋ฐ, ์ด๋•Œ Javascript์—์„œ ์ง€์›ํ•˜๋Š” Proxy API์˜ ์™„์ „ํžˆ ๊ฐ™์€ ํ˜•ํƒœ๋Š” ์•„๋‹ˆ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ถ€๋ถ„๋ถ€ํ„ฐ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ๋‚œ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ „ ๊ทธ๋žฌ์–ด์š”. ๊ทธ๋ž˜์„œ ๊ทธ๋ƒฅ ๋ฐ˜์‘ํ˜• ๋ณ€์ˆ˜ ์‚ฌ์šฉ๋ฒ•์ด ๋ฐ”๋€Œ์—ˆ๊ตฌ๋‚˜ ๊ทธ๊ฒŒ Reactivity API๊ตฌ๋‚˜ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์–ตํ•ด์•ผ ํ•  ๊ฒƒ์€ reactive, ref, toRefs, readonly์ž…๋‹ˆ๋‹ค.

reactive: ๊ฐ์ฒด์™€ ๋ฐฐ์—ด, set๊ณผ ๊ฐ™์€ ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋“ค์„ ๋‹ด๋‹น.

ref : ๋‹จ์ˆœ๊ฐ’(์ˆซ์ž, ๋ฌธ์ž์—ด, ๋ณผ๋ฆฐ๊ณผ ๊ฐ™์€)์„ ๋‹ด๋‹น.

toRefs: Reactivity API๋กœ ๊ฐ์‹ธ์ง„ ๊ฐ’๋“ค์„ ์ผ๋ฐ˜ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜.

readonly: ๋ช…์นญ ๊ทธ๋Œ€๋กœ ๊ฐ’์„ ์˜ค๋กœ์ง€ ์ฝ์–ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์— ์ง€์ •, Reactivity API๋กœ ๊ฐ์‹ธ์ง„ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด์„œ๋งŒ ์ž‘๋™.

์•„๋ž˜์˜ ์˜ˆ์ œ๋กœ ์ดํ•ดํ•ด ๋ณผ๊ฒŒ์šฉ

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="count++">count update</button>
    
    <p>list: {{ list }}</p>
    <button @click="updateList(list)">list push</button>
    <p>readOnlyCount: {{ readOnlyCount }}</p>
    <button @click="readOnlyCount++">readOnlyCount update</button>
    <hr />
    <p>failedCount: {{ failedCount }}</p>
    <button @click="failedCount++">count update</button>
    <p>failedList: {{ failedList }}</p>
    <button @click="updateList(failedList)">list push</button>
  </div>
</template>

<script>
import {ref, reactive, readonly} from 'vue'
export default {
  setup () {
    // ### ๋ฐ์ดํ„ฐ ์ƒ์„ฑ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค ###
    const count = ref(0) // ๋‹จ์ˆœ ๊ฐ’์€ ref
    const list = reactive([]) // ๋ฐฐ์—ด์ด๋ฏ€๋กœ reactive

    const readOnlyCount = readonly(count) 
    // ref๋ฅผ ์ด์šฉํ•œ ๊ฐ’์— readonly ์†์„ฑ์„ ์ง€์ •ํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋กœ ์ง€์ •.
    // ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋ ค๊ณ  ํ•ด๋„ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋˜์ง€ ์•Š์œผ๋ฉฐ count๊ฐ€ ์˜ฌ๋ผ๊ฐˆ๋•Œ
    // ์ž๋™์œผ๋กœ ์ฐธ์กฐ๋˜์–ด ์—…๋ฐ์ดํŠธ.

    const failedCount = reactive(0)
    // 0์€ ๋‹จ์ˆœ๊ฐ’์œผ๋กœ ์ง€์ •ํ•ด์•ผ ํ•˜์ง€๋งŒ, reactive๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. ๊ฐ’์ด ๋ฐ˜์˜๋˜์ง€ ์•Š์„ ๊ฒƒ.
    // ์ด๊ฑด ๋ฐ˜์˜๋˜๋”๊ตฐ์š”...? ์™œ ๊ทธ๋Ÿด๊นŒ์š”??

    const failedList = ref([])
    // ref์— ๋ฐฐ์—ด []์„ ์‚ฌ์šฉํ–ˆ๋‹ค. ๋ฐ˜์˜๋˜์ง€ ์•Š์„ ๊ฒƒ. ์ด๊ฑด ๋ฐ˜์˜ ์•ˆ ๋˜๋”๊ตฐ์š”

    // ์‚ฌ์‹ค์ƒ methods ์ƒ์„ฑ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.
    const updateList = (base) => {
      base.push(Math.random())
    }

    // template์—์„œ ์ฐธ์กฐํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ผญ!!!!! return ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
    return {
      count,
      list,
      readOnlyCount,
      failedCount,
      failedList,
      updateList
    }
  }
}
</script>

์ƒ๊ฐ๋ณด๋‹ค ํŽธํ•˜๊ฒŒ ๋ฐ˜์‘ํ˜• ๋ณ€์ˆ˜๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ํฐ ์žฅ์ ์œผ๋กœ ๋ฐ”๋€๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

โญ๏ธ ์ œ๊ณต(Provide)์™€ ํˆฌ์ž…(Inject)

Provide์™€ Inject์ž…๋‹ˆ๋‹ค. ์ด๊ฑด ์ง€๊ธˆ๊ป ์šฐ๋ฆฌ๊ฐ€ Vue 2์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— Props๋ฅผ ํ–ˆ๋˜ ๋ถ€๋ถ„์ด ์ง„ํ™” ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹น~ ์‚ฌ์‹ค provide์™€ inject๋Š” Vue 2์—๋„ ์žˆ์—ˆ๋˜ ๋‚ด์šฉ์œผ๋กœ ๊ธฐ์–ตํ•ฉ๋‹ˆ๋‹ค. ๊ณต์‹๋ฌธ์„œ์—์„œ ํ™•์ธํ•œ ๊ธฐ์–ต์ด...

Vue 2๋ฅผ ๋ฐฐ์šธ ๋•Œ, ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์ค„ ๋•Œ ์šฐ๋ฆฌ๋Š” ํ•ญ์ƒ template์™€ import, component๋ฅผ ์ง€์ •ํ•ด์ฃผ์—ˆ์ฃ . main.vue๊ฐ€ ๋ถ€๋ชจ๊ณ  childComponent.vue๊ฐ€ ์ž์‹์ด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์คฌ์ฃ . ๊ทผ๋ฐ ์ด๊ฑฐ ๊ผฌ์ด๋ฉด ์ฝ”๋“œ ์ˆ˜์ •ํ•˜๊ธฐ๊ฐ€ ์ฐธ ๊ป„๋„๋Ÿฌ์› ์ง€์š”...

// main.vue ๋ถ€๋ชจ
<template>
  <ChildComponent :propkey="data"> <!-- ์ด๊ฑธ ์จ์•ผ propkey๋ผ๋Š” ๋ช…์นญ์œผ๋กœ data๊ฐ€ ๋„˜์–ด๊ฐ”์–ด์š” -->
  </ChildComponent> 
</template>
<script>
import ChildComponent from './child-component.vue' // ๊ผญ import ํ•ด์ค˜์•ผํ–ˆ๊ณ 

export default {
  components: {
    ChildComponent // ์ปดํฌ๋„ŒํŠธ ์ž…๋ ฅ!
  }
}
</script>
// childComponent.vue ์ž์‹
<template>
  <AnotherChild :values="this.propkey">
  </AnotherChild>
</template>

<script>
import AnotherChild from './another-child.vue'

export default {
  props: {
    propkey: Object
  },
  components: {
    AnotherChild
  }
}
</script>

๋ถ€๋ชจ โ†’ ์ž์‹์œผ๋กœ ๊ฐ€๋ฉด ์šฐ๋ฆฌ๋Š” ์ž์—ฐ์Šค๋ ˆ props: { ... }๋ฅผ ์ผ์Šต๋‹ˆ๋‹ค. ๊ทผ๋ฐ ์ด๋Ÿฐ ๊ด€๊ณ„๊ฐ€ ๋งŒ์•ฝ์— ์—„์ฒญ ๋งŽ์•„์ ธ์„œ ๋ณต์žกํ•ด์ง„๋‹ค๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•ด๋ด์š”. ๋ถ€๋ชจ โ†’ ์ž์‹ โ†’ ์ž์‹ โ†’ ์ž์‹ โ†’ ์ž์‹ โ†’ ์ž์‹ โ†’ ... ๋„ˆ๋ฌด ๋งŽ์•„์ง€๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

๊ทธ๋•Œ provide์™€ Inject๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋˜์š”. (์‚ฌ์‹ค ์ด๋•Œ๋Š” vuex๊ฐ€ ๋‹ต์ธ๋ฐ..ใ…Žใ…Ž)

๋งŒ์•ฝ์— ๋ถ€๋ชจ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ ๊ด€๊ณ„๊ฐ€ main.vue โ†’ childComponent.vue โ†’ another-child.vue๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•ด๋ณผ๊ฒŒ์š”.

์ผ๋‹จ main.vue๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด provide๋ฅผ ๊ฐ์ฒดํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•ด์„œ ์ž์‹ ์˜ ์ž์‹๋“ค์—๊ฒŒ ๋ณด๋‚ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// main.vue
<template>
  <ChildComponent :propkey="data">
  </ChildComponent>
</template>
<script>
import ChildComponent from './child-component.vue'

export default {
  provide: {
    providedValue: 'hello' // provide ๋“ฑํŒ! ๊ฐ์ฒด๋กœ ์ „๋‹ฌ!
  },
  components: {
    ChildComponent // main์˜ ์ž์‹!
  }
}
</script>

์ด์ œ ์œ„์˜ providedValue์€ main์˜ ์–ด๋–ค ์ž์‹์ด๋ผ๋„ inject์„ ํ†ตํ•ด ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. another-child.vue๋Š” ์•„๋ž˜ ์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋˜๊ฒ ๋„ค์š”!

// childComponent.vue
<template>
  <div>
    {{ providedValue }}
  </div>
</template>

<script>
export default {
  inject: [
    'providedValue' // inject๋“ฑํŒ! inject๋กœ ๋ถˆ๋Ÿฌ์˜ฌ๋• array ํ˜•ํƒœ๋กœ provide๋กœ ์ œ๊ณต๋œ ํ‚ค๋ฅผ ์ง€์ •ํ•œ๋‹ค.
  ],
}
</script>

๊ทผ๋ฐ ์–ด๋œป ๋ณด๋ฉด ๋˜๊ฒŒ ์ข‹์€ ๊ฑฐ ๊ฐ™์€๋ฐ, ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ์ด๋Ÿฐ ๋ง์„ ํ–ˆ๋„ค์š”. prop์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ๊ธฐํ•ด์˜จ ์ง€๋‚œ๋‚ ๋“ค๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ, provide๋Š” ์–ด๋Š ์ปดํฌ๋„ŒํŠธ์—์„œ ์–ด๋– ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ inject๋กœ ์ œ๊ณตํ–ˆ๋Š”์ง€ ์ƒ๋‹นํžˆ ๋ถˆ๋ช…ํ™•ํ•œ ํ‘œ๊ธฐ๋ฒ•์ด๋ผ๋Š” ์˜๊ฒฌ์ด ์žˆ๋„ค์š”. ๊ทผ๋ฐ ์ƒ๊ฐํ•ด๋ณด๋ฉด ๊ทธ๋ ‡์ฃ . ๊ฐœ๋ฐœ ํ›„ ํ•œ์ฐธ ๋’ค์— inject๋ฅผ ๋ณด์•˜์„ ๋•Œ ์ด๊ฒŒ ์–ด๋””์„œ ์™”๋”๋ผ? ํ•˜๊ณ  ์ฐพ์•„์•ผํ•˜๋‹ˆ๊นŒ์š”... ๊ทธ๋ž˜์„œ ํ”„๋กœ์ ํŠธ์—์„œ ๋‚˜๋ฆ„์˜ ๊ทœ์น™์„ ๊ฐ–์ง€ ์•Š๋Š” ํ•œ ํ›„์— ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์— ์ง๋ฉดํ–ˆ์„ ๋•Œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํž˜๋“ค ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ์—๋„ ์žฅ์ ์€ ๋ถ„๋ช…ํ•˜๋‹ˆ๊นŒ. ๋ฏธ๋ฆฌ Component ๊ตฌ์กฐ๋ฅผ ์ž˜ ์„ค๊ณ„ํ•œ๋‹ค๋ฉด ์ถฉ๋ถ„ํžˆ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค! ํŠนํžˆ vuex๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ์—๋Š” ์• ๋งคํ•œ ๋ฐ์ดํ„ฐ๋“ค์„ provide/inject๋กœ ํ•˜๋ฉด ์ข‹์„๊ฑฐ ๊ฐ™๋‹ค๋Š” ์˜๊ฒฌ๋“ค๋„ ์žˆ์—ˆ๋„ค์š”.

์ƒ๊ฐ๋ณด๋‹ค ์ˆ˜๋งŽ์€ ๋ถ€๋ถ„์ด ๋ฐ”๋€Œ์—ˆ์ง€๋งŒ, ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ฒŒ ๋ฐ”๋€ ๋ถ€๋ถ„์ด ๋ฐ”๋กœ Reactivity API์™€ Composition API์ด๊ธฐ ๋•Œ๋ฌธ์—, ํ•ด๋‹น ๋ถ€๋ถ„๋งŒ ์ˆ™์ง€ํ•˜๊ณ  ๊ณ„์‹œ๋ฉด, FrontEnd๋ฅผ Vue 3๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋˜๋ฆฌ๋ผ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

profile
'๊ฐœ๋ฐœ'์€ '์˜ˆ์ˆ '์ด๊ณ  '์„œ๋น„์Šค'๋Š” '์ž‘ํ’ˆ'์ด๋‹ค

0๊ฐœ์˜ ๋Œ“๊ธ€