๐Ÿ” ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค FE ๋ฐ๋ธŒ์ฝ”์Šค 5๊ธฐ TIL = Computed | Watch | ํด๋ž˜์Šค ์Šคํƒ€์ผ ๋ฐ”์ธ๋”ฉ

Jun 2k (Jun2)ยท2023๋…„ 11์›” 21์ผ
1
post-thumbnail

2023.11.21 ๊ฐ•์˜

๐Ÿ’ป Intro & TMI

์–ด์ œ๋Š” Vue๋Š” ์š”๋Ÿฐ๊ฑฐ์—์š”๋ผ๊ณ  ์†Œ๊ฐœํ•œ ์ •๋„๋ผ๋ฉด ์˜ค๋Š˜๋ถ€ํ„ฐ๋Š” ์„ธ์„ธํ•˜๊ฒŒ ํ•˜๋‚˜์”ฉ ๊ฐœ๋…๋“ค์„ ์งš์–ด๋‚˜๊ฐ”๋‹ค.
HTML ์š”์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋Š” Computed์™€ Watch ์†์„ฑ, ํด๋ž˜์Šค๋กœ ์Šคํƒ€์ผ์„ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๋ฒ•์„ ๋ฐฐ์› ๋‹ค.

2์ฐจํŒ€ ์„ธํฌํŒ€์›๋“ค๊ณผ ์•„์ง๊นŒ์ง€ ์–ด์ƒ‰์–ด์ƒ‰ํ•˜๋‹ค ใ…‹ใ…‹ใ…‹ใ…‹ 1์ฐจํŒ€ ๋•Œ๋„ ๊ทธ๋žฌ์—ˆ์œผ๋‹ˆ ํ•˜๋ฃจํ•˜๋ฃจ ์กฐ๊ธˆ์”ฉ ํŒ€์›๋“ค์„ ์•Œ์•„๊ฐ€์•ผ๊ฒ ๋‹ค. ๋„ˆ๋ฌด ๊ฐ‘์ž‘์Šค๋Ÿฝ๊ฒŒ ์นœํ•ด์ง€๋ ค๊ณ  ๋‹ค๊ฐ€๊ฐ€๋ฉด ๋ถ€๋‹ด์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ์œผ๋‹ˆ... ์„ธํฌํŒ€์›๋ถ„๋“ค ๋ณด๊ณ  ๊ณ„์‹œ์ฃ ?



๐Ÿง ์˜ค๋Š˜ ์ƒˆ๋กญ๊ฒŒ ๋ฐฐ์šด ๊ฒƒ

computed ์†์„ฑ์„ ํ†ตํ•œ ์บ์‹ฑ

Vue์—์„œ๋Š” computed ์†์„ฑ์œผ๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ๋ฐ”๋กœ HTML์— ๋ฐ”์ธ๋”ฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

<div id="app">
  <h1>{{count}}</h1>
  <h2>{{double}}</h2>
  <h2>{{double}}</h2>
  <h2>{{double}}</h2>
  <h2>{{double}}</h2>
</div>

<script>
      const App = {
        data() {
          return {
            count: 3,
          };
        },
        computed: {
          double() {
            return this.count * 2;
          },
        },
      };
  ...
</script>
    

methods ์†์„ฑ์„ ํ†ตํ•ด double์ด๋ž€ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด HTML์— ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ๊ณ„์‚ฐ ๋กœ์ง์„ ๋Œ๋ ค์•ผ ํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ์„ฑ๋Šฅ ์ธก๋ฉด์—์„œ ๋‚ญ๋น„ํ•˜๊ฒŒ ๋œ๋‹ค.

๋”ฐ๋ผ์„œ ๋˜‘๊ฐ™์€ ๊ณ„์‚ฐ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์ผ ๋•Œ๋Š” methods๊ฐ€ ์•„๋‹Œ computed ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์ž!



computed ์†์„ฑ ๋‚ด getter, setter

computed ์†์„ฑ์„ ํ†ตํ•ด ๊ณ„์‚ฐ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊นŒ์ง„ ์•Œ๊ฒ ๋‹ค.
ํ•˜์ง€๋งŒ ๋‹จ์ˆœํžˆ ๋ฉ”์„œ๋“œ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ computed๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

<div id="app">
      <h1>{{ fullName }}</h1>
      <h2>{{ firstName }}</h2>
      <h2>{{ lastName }}</h2>
</div>
<script>
      const App = {
        data() {
          return {
            firstName: 'Cho',
            lastName: 'ikjun',
          };
        },

        computed: {
          fullName() {
          	return `${this.firstName} ${this.lastName}`
          },
        },
      };

      const vm = Vue.createApp(App).mount('#app');
</script>

๊ธฐ์กด ๋ฐฉ์‹๋Œ€๋กœ fullName์ด๋ž€ ๊ณ„์‚ฐ๊ฐ’์„ ์ผ๋ฐ˜ ํ•จ์ˆ˜ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ๋„˜๊ฒจ์ฃผ๊ฒŒ๋˜๋ฉด ์–ผํ• ๋ณด๋ฉด ์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

ํ•˜์ง€๋งŒ fullName์ด๋ž€ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•ด๋„ ๋ฐ˜์‘์„ฑ์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. 'Pro Grammers'๋กœ ๋ณ€๊ฒฝํ–ˆ์ง€๋งŒ ์ด๋ฆ„์ด ๊ทธ๋Œ€๋กœ์ด๋‹ค.

์™œ ๊ทธ๋Ÿฐ๊ฑธ๊นŒ?

๊ทธ ์ด์œ ๋Š” Proxy ๊ตฌ์กฐ์—์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ getter์™€ setter ํ•จ์ˆ˜ ์ค‘ ํ•จ์ˆ˜ ๋ฐ˜ํ™˜๊ฐ’ ํ˜•ํƒœ๋กœ computed๋ฅผ ์ž‘์„ฑํ•˜๊ฒŒ๋˜๋ฉด getter๋งŒ ๊ตฌํ˜„๋œ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ƒˆ๋กญ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ๋™ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” computed ์†์„ฑ ๋‚ด์—์„œ๋„ get, set ํ•จ์ˆ˜๋ฅผ ๊ตฌ๋ถ„ํ•ด์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

computed: {
	fullName: {
      	// fullName ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” get ํ•จ์ˆ˜
		get() {
      		return `${this.firstName} ${this.lastName}`;
   		},
        // fullName ๋ฐ์ดํ„ฐ๋ฅผ ์„ค์ •ํ•˜๋Š” set ํ•จ์ˆ˜
    	set(newValue) {
      		const names = newValue.split(' ');
      		this.firstName = names[0];
      		this.lastName = names[names.length - 1];
    	},
 	},
},

์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜๋ฉด fullName์„ ์ฝ˜์†”์—์„œ ๋ณ€๊ฒฝํ•˜์ž ๋ฐ”๋กœ ์—ฐ๋™๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.



๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด์ผ ๋•Œ watch ์†์„ฑ ์‚ฌ์šฉ ์ฃผ์˜์ 

๋ฐ์ดํ„ฐ๊ฐ€ ์›์‹œ ํƒ€์ž…์ผ ๊ฒฝ์šฐ์—๋Š” watch ์†์„ฑ์„ ๋ฐ์ดํ„ฐ ์ด๋ฆ„ ๋™์ผํ•˜๊ฒŒ ๋ฉ”์„œ๋“œ ํ˜•ํƒœ๋กœ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๋กœ์ง์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด์ผ ๊ฒฝ์šฐ์—๋Š” ๋‚ด๋ถ€ ์†์„ฑ์ด๋‚˜ ์š”์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๊ฒฝ์šฐ์—๋Š” ๋ฉ”์„œ๋“œ ํ˜•ํƒœ๋กœ watch ์†์„ฑ์„ ์ง€์ •ํ•˜๋ฉด ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด watch ์†์„ฑ์„ ํ†ตํ•ด ์‹คํ–‰ํ•  ๋กœ์ง์€ handler๋กœ ๊ฐ์‹ธ๊ณ  deep: true์ด๋ž€ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๊นŠ๊ฒŒ ๋ฐ์ดํ„ฐ์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

<script>
  const App = {
    data() {
      return {
        user: {
          name: 'Ikjun',
          age: 28,
        },
        fruits: [
          { id: 1, name: 'Apple' },
          { id: 2, name: 'Banana' },
          { id: 3, name: 'Cherry' },
        ],
      };
    },

    watch: {
      user: {
        handler(newValue, oldValue) {
          console.log(newValue, oldValue);
        },
        deep: true, // ๊นŠ๊ฒŒ ๊ฐ์ง€
      },
      fruits: {
        handler() {
          console.log(this.fruits);
        },
        deep: true,
        immediate: true, // DOM์ด ๋ Œ๋”๋ง๋˜์ž๋งˆ์ž ๊ฐ์ง€ ์‹œ์ž‘
      },
    },
  }
</script>

immediate: true ์†์„ฑ์€ DOM์ด ๋ Œ๋”๋ง๋˜์ž๋งˆ์ž ํ•ด๋‹น ๋ฐ์ดํ„ฐ์˜ ์ƒํƒœ๋ฅผ ๊ฐ์ง€ํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋„๋ก ํ•˜๋Š” ์˜ต์…˜์ธ๋ฐ deep๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ์œ ์šฉํ•˜๋‹ค.

์•„๋ž˜ ์‚ฌ์ง„์—์„œ์ฒ˜๋Ÿผ ์ดˆ๊ธฐ fruits ๋ฐฐ์—ด์˜ ํ”„๋ก์‹œ์™€ capitalize ๋ฒ„ํŠผ์— ์˜ํ•ด ๋‚ด๋ถ€ ์š”์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋œ fruits ๋ฐฐ์—ด ํ”„๋ก์‹œ๊ฐ€ ์ฝ˜์†”์— ์ถœ๋ ฅ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.



๋ฐ˜์‘์„ฑ์„ ๊ณ ๋ คํ•œ computed ํด๋ž˜์Šค

v-bind๋ฅผ ํ†ตํ•ด classObject ๊ฐ์ฒด ํ˜•ํƒœ์˜ ํด๋ž˜์Šค๋กœ ์—ฌ๋Ÿฌ ํด๋ž˜์Šค๋ฅผ ํ•œ๊บผ๋ฒˆ์— HTML ์š”์†Œ์— ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

<div id="app">
  <!-- ... -->
  <h1 :class="classObject" class="title">{{ msg }}</h1>
</div>
<script>
  const App = {
    data() {
      return {
        // ...
        active: false,
        small: true,
      };
    },
    computed: {
      classObject() {
        return {
          active: this.active,
          'title--small color--orange': this.small,
        };
      },
    },
  };
</script>


์œ„ ์‚ฌ์ง„๊ณผ ์ฒ˜๋Ÿผ acitve์™€ title--small, color--orange ํด๋ž˜์Šค์— ๋Œ€ํ•œ acitve, small ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋ฐ”์ธ๋”ฉ๋˜์–ด ์ถ”๊ฐ€๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์•„๋ž˜์™€ ๊ฐ™์ด computed ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐ”์ธ๋”ฉํ•˜๊ฒŒ ๋˜๋ฉด data()์— ์žˆ๋Š” acitve์™€ small ์†์„ฑ์„ ์—ฐ๋™ํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.

<script>
  const App = {
    data() {
      return {
        // ...
        active: false,
        small: true,
        classObject: {
          active: false,
          'title--small color--orange': true
        }
      };
    },
  };
</script>

๋”ฐ๋ผ์„œ Vue ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด ๋ฐ˜์‘ํ˜• ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฐ์ฒด๋Š” ๋‹จ์ˆœํžˆ data ๋‚ด์— ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ
computed ์†์„ฑ์—์„œ this๋กœ ์—ฐ๋™ํ•ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.



์—ฌ๋Ÿฌ style ๊ฐ์ฒด๋ฅผ v-bindํ•  ๋•Œ ์ฃผ์˜์ 

์•„๋ž˜ ์ฝ”๋“œ์—์„œ h1 ํƒœ๊ทธ์— styleObject, titleStyleObject ๋‘ ๊ฐœ์˜ style ๊ด€๋ จ ๊ฐ์ฒด๋ฅผ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ์ˆœ์„œ๋ฅผ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.

<div id="app">
  <h1 :style="[titleStyleObject, styleObject]">Hello Vue!</h1>
</div>

<script>
  const App = {
  	data() {
  		return {
  			styleObject: {
 	 			color: 'royalblue',
  				backgroundColor: 'orange',
  			},
  			titleStyleObject: {
              fontSize: '40px',
              fontWeight: 'bold',
              color: 'brown',
  			},
 	 	};
  	},
  };

  // ...
</script>

๋ฐฐ์—ด ๋ฆฌํ„ฐ๋Ÿด์—์„œ ๋‚˜์ค‘์— ๋ฐ”์ธ๋”ฉ๋˜๋Š” CSS ๊ฐ’์œผ๋กœ ๋ฎ์–ด์จ์ง€๊ฒŒ ๋˜๋ฏ€๋กœ ํ˜„์žฌ ์ฝ”๋“œ์—์„œ ์ค‘๋ณต๋˜๋Š” color ์†์„ฑ์—์„œ ๋‚˜์ค‘์— ๋ฐ”์ธ๋”ฉ๋œstyleObject์˜ royalblue ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.



๐Ÿ‘€ ๋А๋‚€์ 

๐Ÿ‘ Keep

๊ฐ•์˜๋ฅผ ๋“ค์œผ๋ฉด์„œ ๋ชจ๋“  ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๊ทธ ์ค‘ ์ •๋ง ์ค‘์š”ํ•œ ๊ฒƒ์„ ๊ฐ•์˜๋ณ„๋กœ ํ•˜๋‚˜์”ฉ ๊ผฝ์•„์„œ ์š”์•ฝํ•˜๋‹ˆ ๋ญ”๊ฐ€ ๋” ์ง‘์ค‘๋„ ์ž˜๋˜๊ณ  ์ดํ•ด๊ฐ€ ๋น ๋ฅธ ๊ฒƒ ๊ฐ™๋‹ค. ์š”์•ฝํ•˜์—ฌ ์„ค๋ช…ํ•˜๊ธฐ ๊ณ„์† ์ง„ํ–‰ํ•ด์•ผ๊ฒ ๋‹ค.

๐Ÿ˜ฑ Problem

Vue๋งŒ์˜ ํ…œํ”Œ๋ฆฟ ๋ฌธ๋ฒ•์ด ์•„์ง ์ต์ˆ™์น˜๊ฐ€ ์•Š์•„์„œ ๊ณ„์† ๊ณต์‹๋ฌธ์„œ๋ฅผ ์ฐพ์•„๋ณด๊ฒŒ๋œ๋‹ค. ์•„์ง 2์ผ์ฐจ๋ผ ๋ฐ”๋กœ ์•„๋Š”๊ฒŒ ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ์€ ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ ๋ฌธ๋ฒ•์— ๋Œ€ํ•ด์„œ ๋” ์ˆ™์ง€๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๐Ÿ˜œ Try

Vue ๊ฐ•์˜ ๋ง๊ณ ๋„ CSS ๊ณผ์ œ ํ”ผ๋“œ๋ฐฑ ๋ฐ ํ•œ๋‹ฌํšŒ๊ณ  ๋ฐ ํฌํŠธํด๋ฆฌ์˜ค ๋ณด์™„ ๋“ฑ ํ• ๊ฒŒ ํƒœ์‚ฐ์ด๋‹ค. ์–ผ๋ฅธ ํ•˜๋‚˜์”ฉ ๋๋‚ด๋„๋ก ํ•˜์ž.



๐Ÿ˜… ํ•ด๋‹น ๋‚ด์šฉ์€ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ํ‹€๋ฆฐ ๋ถ€๋ถ„์ด๋‚˜ ์˜คํ•ดํ•˜๊ณ  ์žˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ํ”ผ๋“œ๋ฐฑ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

profile
ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ค€๋น„์ค‘...

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

comment-user-thumbnail
2023๋…„ 11์›” 21์ผ

ํ• ๊ฒŒ ํƒœ์‚ฐ์ด์‹œ๋ผ๋‹ˆ,, ์˜ค๋Š˜๋„ ๋“ฑ๋Œ€ํ•˜์‹œ๊ฒ ๋„ค์š”

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ