Vue Study

Vue์—์„œ modal ๊ด€๋ฆฌ ์‰ฝ๊ฒŒํ•˜๊ธฐ

2022. 7. 8. 13:50
๋ชฉ์ฐจ
  1. ๐Ÿ“Œ ๋ชฉ์ฐจ
  2. ๐Ÿ“Œ ์„œ๋ก 
  3. ๐Ÿ“Œ ๊ธฐ์กด ๋ชจ๋‹ฌ ๊ด€๋ฆฌ
  4. ๐Ÿ“Œ ๊ธฐ์กด ๋ชจ๋‹ฌ ๊ด€๋ฆฌ์˜ ๋ฌธ์ œ์ 
  5. 1. ๋งŒ์•ฝ์— ๊ด€๋ฆฌ๋ฅผ ํ•ด์•ผํ•  ๋ชจ๋‹ฌ์ด ๋งŽ์•„ ์ง„๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
  6. 2. vuex์˜ mutations๋งŒ ๋ณด๊ณ  ์‹ค์ œ๋กœ ์–ด๋–ค ๋ชจ๋‹ฌ์ด ๋›ฐ์–ด์ง€๋Š”์ง€ ํ•œ๋ฒˆ์— ํŒŒ์•…์ด ๊ฐ€๋Šฅํ•œ๊ฐ€?
  7. 3. ๋งŒ์•ฝ์— ๋™์‹œ์— ๊ฐ™์€ ๋ชจ๋‹ฌ์„ ๋„์›Œ์•ผ ํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
  8. 4. ๋งŒ์•ฝ์— ๋ชจ๋‹ฌ์—์„œ ์–ด๋–ค ๊ฐ’์„ ๋ฐ›์•„์„œ ํŽ˜์ด์ง€์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผํ•œ๋‹ค๋ฉด?
  9. ๐Ÿšง ๋ฌธ์ œ์  ๋ชจ์•„๋ณด๊ธฐ
  10. ๐Ÿ“Œ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ ํ•ด์•ผํ• ๊นŒ? interface ์žก์•„๋ณด๊ธฐ
  11. vue3 setup
  12. vue3 ์ผ๋ฐ˜ ๋ฌธ๋ฒ•
  13. ๐Ÿ“Œ ์™œ promise๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๊ฐ€?
  14. ๐Ÿ“Œ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„์„ ํ•ด์•ผํ• ๊นŒ?
  15. ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ
  16. ๐Ÿ“Œ ๊ทธ๋Ÿผ ํ›…์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ์ด ๋˜์–ด์งˆ๊นŒ?
  17. ๐Ÿ“Œ ๊ฒฐ๋ก 
๋ฐ˜์‘ํ˜•

๐Ÿ“Œ ๋ชฉ์ฐจ

  • ์„œ๋ก 
  • ๊ธฐ์กด ๋ชจ๋‹ฌ ๊ด€๋ฆฌ
  • ๊ธฐ์กด ๋ชจ๋‹ฌ ๊ด€๋ฆฌ์˜ ๋ฌธ์ œ์ 
  • ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•ด์•ผํ• ๊นŒ? interface ์žก์•„๋ณด๊ธฐ
  • ์™œ promise๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๊ฐ€?
  • ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„์„ ํ•ด์•ผํ• ๊นŒ?
  • ๊ทธ๋Ÿผ composition์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ์ด ๋˜์–ด์งˆ๊นŒ?
  • ๊ฒฐ๋ก 

๐Ÿ“Œ ์„œ๋ก 

์•ˆ๋…•ํ•˜์„ธ์š”. ์—๋”” ์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ๊ฐ€์žฅ ๋งŽ์€ ๋ถ„๋“ค์ด ๊ณ ๋ฏผํ•˜์‹œ๋Š” ๋ชจ๋‹ฌ ํ˜น์€ ๋‹ค์ด์–ผ๋กœ๊ทธ ๊ด€๋ฆฌ์— ๋Œ€ํ•ด์„œ ํ•œ๋ฒˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์˜ค๋žœ ๊ณ ๋ฏผ ๋์— ๋‚˜์˜จ ์ •์˜๋‹ˆ ํ˜น์‹œ ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ๋‹ฌ์•„์ฃผ์„ธ์š”. ๊ทธ๋Ÿผ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ“Œ ๊ธฐ์กด ๋ชจ๋‹ฌ ๊ด€๋ฆฌ

์šฐ๋ฆฌ ํ•œ๋ฒˆ ๋ชจ๋‹ฌ์„ ๋„์›Œ์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐ์„ ํ•ด๋ณผ๊นŒ์š”?

๊ทธ๋Ÿผ ์šฐ๋ฆฌ ๋จธ๋ฆฌ์†์— ๊ฐ€์žฅ ๋จผ์ € ๋“œ๋Š” ์ƒ๊ฐ์€ vuex๋ฅผ ํ†ตํ•œ ์Šค์œ„์นญ ๊ด€๋ฆฌ ์ผ๊ฑฐ์˜ˆ์š”. ๋Œ€๋žต์ ์œผ๋กœ ์ด๋ ‡๊ฒŒ ๋ณดํ†ต ๊ตฌํ˜„์„ ํ–ˆ์—ˆ์„๊ฑฐ ๊ฐ™์•„์š”.

// store.js
export default createStore({
  state: {
    modalOn: false
  },
  mutations: {
    setModalOn(state) {
      state.modalOn = true;
    },
    setModalOff(state) {
      state.modalOn = false;
    },
  }
});
// App.vue
<template>
  <div>
    <h1>APP</h1>
    <SimpleModal v-if="modalOn" />
    <button @click="setModalOn">ModalOn</button>
  </div>
</template>

<script>
import SimpleModal from './components/SimpleModal';
import { mapState, mapMutations } from 'vuex';

export default {
  name: 'App',
  components: {
    SimpleModal
  },
  computed: {
    ...mapState(['modalOn'])
  },
  methods: {
    ...mapMutations(['setModalOn', 'setModalOff'])
  }
};
</script>

๋Œ€๋žต ์ด๋Ÿฐ ํ˜•ํƒœ๋ฅผ ์ƒ๊ฐํ•˜๊ณ  ๊ณ„์…จ๋‚˜์š”? ์ € ๋˜ํ•œ ์ด๋Ÿฐ on, off(boolean) ํ˜•ํƒœ๋กœ modal์„ ๊ด€๋ฆฌ๋ฅผ ํ•˜์˜€์—ˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ๊ด€๋ฆฌ๋ฅผ ํ•˜์˜€์„๋•Œ ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ์ ์„ ํ•œ๋ฒˆ ์งš์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ“Œ ๊ธฐ์กด ๋ชจ๋‹ฌ ๊ด€๋ฆฌ์˜ ๋ฌธ์ œ์ 

1. ๋งŒ์•ฝ์— ๊ด€๋ฆฌ๋ฅผ ํ•ด์•ผํ•  ๋ชจ๋‹ฌ์ด ๋งŽ์•„ ์ง„๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

๋งŒ์•ฝ์— vuex๊ฐ€ ๋งŽ์•„ ์ง„๋‹ค๊ณ  ๊ฐ€์ •์„ ํ•ด๋ณผ๊ฒŒ์š”. ๊ทธ๋Ÿผ ์•„๋งˆ ์—ฌ๋Ÿฌ๋ถ„์˜ store๋Š” ์ด๋Ÿฐ ํ˜•ํƒœ๊ฐ€ ๋  ๊ฑฐ ๊ฐ™์•„์š”.

export default createStore({
  state: {
    modalOn1: false,
    modalOn2: false,
    modalOn3: false,
    modalOn4: false,
    modalOn5: false,
    modalOn6: false,
    //... ๐Ÿ”ฅ ๋ฌด์ˆ˜ํžˆ ๋งŽ์€ ๋ชจ๋‹ฌ๋“ค์„ ๊ด€๋ฆฌํ•˜๋Š” ์ƒํƒœ๊ฐ€ ํ•„์š”ํ•จ
  },
  mutations: {
    setModalOn1(state, payload) {
      state.modalOn = payload;
    },
    setModalOn2(state, payload) {
      state.modalOn = payload;
    },
    // ... ๐Ÿ”ฅ ๋ฌด์ˆ˜ํžˆ ๋งŽ์€ ๋ชจ๋‹ฌ๋“ค์„ ๊ด€๋ฆฌํ•˜๋Š” ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ๋“ค์ด ์ž‘์„ฑ๋˜์–ด์•ผ ํ•จ.
  }
});

๊ณผ์—ฐ ์ •๋ง ์ด๋ ‡๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•œ ๋ฐฉ๋ฒ•์ผ๊นŒ์š”?
ํ˜น์‹œ ์ง€๋‚˜์น˜๊ฒŒ vuex๋ฅผ ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“œ์‹œ๋‚˜์š”?
์ƒˆ๋กœ์šด ๋ชจ๋‹ฌ์„ ์ถ”๊ฐ€ํ•  ๋•Œ ๋งˆ๋‹ค vuex๋ฅผ ๊ฑด๋“ค์—ฌ์•ผํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ• ๊ฑฐ๊ณ  ๊ทธ๋กœ ์ธํ•ด vuex๋Š” ์ ์  ๋น„๋Œ€ํ•ด์ ธ๊ฐˆ ๊ฒ๋‹ˆ๋‹ค.
๊ทธ๋Ÿผ ํ•ด๋‹น vuex๋Š” ๊ณผ์—ฐ ๊ด€๋ฆฌ๊ฐ€ ๋ ๊นŒ์š”?
๋งˆ์ฐฌ๊ฐ€์ง€๋กœ App.vue๋„ ๊ฐ™์ด ๋Š˜์–ด๋‚˜๊ฒŒ ๋ ํ…๋ฐ ๊ด€๋ฆฌ ํฌ์ธํŠธ๊ฐ€ ๋А๋Š”๊ฑด ์•„๋‹๊นŒ์š”?

2. vuex์˜ mutations๋งŒ ๋ณด๊ณ  ์‹ค์ œ๋กœ ์–ด๋–ค ๋ชจ๋‹ฌ์ด ๋›ฐ์–ด์ง€๋Š”์ง€ ํ•œ๋ฒˆ์— ํŒŒ์•…์ด ๊ฐ€๋Šฅํ•œ๊ฐ€?

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// App.vue
<template>
  <div>
    <h1>APP</h1>
    <SimpleModal v-if="modalOn" />
    <button @click="setModalOn">ModalOn</button>
  </div>
</template>

<script>
import SimpleModal from './components/SimpleModal';
import { mapState, mapMutations } from 'vuex';

export default {
  name: 'App',
  components: {
    SimpleModal
  },
  computed: {
    ...mapState(['modalOn'])
  },
  methods: {
    ...mapMutations(['setModalOn', 'setModalOff'])
  }
};
</script>

ํ•ด๋‹น ์ฝ”๋“œ์—์„œ๋Š” depth๊ฐ€ ํ•œ ๋‹จ๊ณ„์ด๊ธฐ ๋•Œ๋ฌธ์— setModalOn์„ ํ•œ๋‹ค๋ฉด ๋Œ€๋žต์ ์œผ๋กœ ์–ด๋–ค ๋ชจ๋‹ฌ์ด ์—ด๋ฆฌ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์„๊ฑฐ ๊ฐ™์•„์š”.
๊ทผ๋ฐ ๋ณดํ†ต ์šฐ๋ฆฌ๊ฐ€ ์“ฐ๋Š” ์ฝ”๋“œ๋Š” ์—„์ฒญ ๋‚˜๊ฒŒ ๋งŽ์€ component์˜ depth๋ฅผ ๋“ค์–ด๊ฐ€์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ์— ๊ทธ๋Ÿผ depth๊ฐ€ ๊นŠ์„ ๋• ์–ด๋–ป๊ฒŒ ์–ด๋–ค ๋ชจ๋‹ฌ์ด ์—ด๋ฆฌ๋Š”์ง€ ํŒŒ์•…์„ ํ• ๊นŒ์š”?

  1. ChildComponent์—์„œ ์–ด๋–ค Mutation์„ ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
  2. Vuex์— ๋“ค์–ด๊ฐ€์„œ ์ฐพ์€ Mutation์ด ์–ด๋–ค ์ƒํƒœ๋ฅผ ๋ฐ”๊ฟ”์ฃผ๋Š”์ง€ ํŒŒ์•…ํ•œ๋‹ค.
  3. App.vue๋ฅผ ํ™•์ธํ•œ๋‹ค.(ํ˜น์€ ModalContainer๋กœ ๋ชจ์•„๋’€๋‹ค๋ฉด ํ•ด๋‹น Container๋ฅผ ํ™•์ธํ•œ๋‹ค.)
  4. ๊ทธ์ œ์„œ์•ผ ์–ด๋–ค ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—ด๋ฆฌ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ชจ๋‹ฌ์„ ์—ฌ๋Š” method ํ•œ์ค„์„ ์ฝ์—ˆ์„ ๋•Œ ์–ด๋–ค ๊ธฐ๋Šฅ ๋™์ž‘์„ ํ•˜๋Š”์ง€ ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—ด๋ฆฌ๋Š”์ง€ ์•Œ ์ˆ˜๋งŒ ์žˆ๋‹ค๋ฉด ์ •๋ง ์ข‹์ง€ ์•Š์„๊นŒ์š”?

3. ๋งŒ์•ฝ์— ๋™์‹œ์— ๊ฐ™์€ ๋ชจ๋‹ฌ์„ ๋„์›Œ์•ผ ํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

์œ„์™€ ๊ฐ™์ด ๊ด€๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๊ฐ™์€ ๋ชจ๋‹ฌ์ด์ง€๋งŒ ์ƒˆ๋กœ์šด ๋ชจ๋‹ฌ์„ ๋“ฑ๋ก์„ ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋“ฑ๋ก์„ ํ•ด์•ผ ํ• ๊ฑฐ ๊ฐ™์•„์š”. ๊ทธ๋Ÿผ ๋˜‘๊ฐ™์ด vuex์™€ App.vue๊ฐ€ ๋งŽ์ด ๋Š˜์–ด๋‚˜๊ฒŒ ๋  ๊ฑฐ ์˜ˆ์š”. ์ •๋ง ์ด๊ฒŒ ์ข‹์€ ๋ฐฉ๋ฒ•์ผ๊นŒ์š”?

4. ๋งŒ์•ฝ์— ๋ชจ๋‹ฌ์—์„œ ์–ด๋–ค ๊ฐ’์„ ๋ฐ›์•„์„œ ํŽ˜์ด์ง€์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผํ•œ๋‹ค๋ฉด?

๋ชจ๋‹ฌ๊ณผ ์ผ๋ฐ˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์„œ๋กœ ์†Œํ†ต์„ ํ•ด์•ผํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”? ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ vuex๋ฅผ ๊ฐ€์žฅ ๋จผ์ € ๋– ์˜ฌ๋ฆฌ์‹ค๊ฑฐ ๊ฐ™์•„์š”. ๊ทธ๋Ÿผ vuex์— ๋”๋”์šฑ ์˜์กด์ ์ด๊ฒŒ ๋˜์ง€ ์•Š์„๊นŒ์š”?

๐Ÿšง ๋ฌธ์ œ์  ๋ชจ์•„๋ณด๊ธฐ

  1. vuex์— ์ง€๋‚˜์น˜๊ฒŒ ์˜์กด์ ์ด๊ฒŒ ๋œ๋‹ค.
  2. App.vue ํ˜น์€ ModalContainer๊ฐ€ ์ปค์ง€๊ฒŒ ๋˜์–ด ๊ด€๋ฆฌ ํฌ์ธํŠธ๊ฐ€ ๋Š˜์–ด๋‚˜๊ฒŒ ๋œ๋‹ค. (vuex ๋˜ํ•œ ๋งˆ์ฐฌ๊ฐ€์ง€)
  3. ์–ด๋–ค ๋ชจ๋‹ฌ์ด ์—ด๋ฆฌ๋Š”์ง€ ์ •ํ™•ํ•˜๊ฒŒ ์ฐพ์•„๋ณด๊ธฐ๊ฐ€ ํž˜๋“ค๋‹ค.
  4. ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ด๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ ๋“ฑ๋ก ๋ฐฉ์‹๊ณผ ๋™์ผํ•œ ์‚ฌ์ดํด์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.

๐Ÿ“Œ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ ํ•ด์•ผํ• ๊นŒ? interface ์žก์•„๋ณด๊ธฐ

๊ฒฐ๊ณผ์ ์œผ๋กœ ์ตœ์ข… ์‚ฌ์šฉ๋ฒ•์€ ์ด๋Ÿฐ ํ˜•ํƒœ๊ฐ€ ๋ ๊ฑฐ ๊ฐ™์•„์š”.

vue3 setup

<script setup>
import { useModal } from 'vue3-use-modal';
import SimpleModal from 'components/SimpleModal.vue';

const modal = useModal();

const onClick = async () => {
  const name = await modal.addModal<string>(
    'SimpleModal', 
    SimpleModal,
    { props: { name: 'eddie' } }
    });
  alert(`My name is: ${name}`);
}
</script>

vue3 ์ผ๋ฐ˜ ๋ฌธ๋ฒ•

<script lang="ts">
import SimpleModal from 'components/SimpleModal.vue';

export default {
  methods: {
    async onClick() {
      const name = await this.$modal.addModal<string>(
          'SimpleModal',
          SimpleModal,
          { props: { name: 'eddie' } }
        });
      alert(`My name is: ${name}`);
    }
  },
}
</script>

์ด๋ ‡๊ฒŒ ์‚ฌ์šฉ์ด ๋˜์–ด์ง„๋‹ค๋ฉด ์œ„์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

  1. vuex์— ์ง€๋‚˜์น˜๊ฒŒ ์˜์กด์ ์ด๊ฒŒ ๋œ๋‹ค.

-> vuex๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
2. App.vue ํ˜น์€ ModalContainer๊ฐ€ ์ปค์ง€๊ฒŒ ๋˜์–ด ๊ด€๋ฆฌ ํฌ์ธํŠธ๊ฐ€ ๋Š˜์–ด๋‚˜๊ฒŒ ๋œ๋‹ค. (vuex ๋˜ํ•œ ๋งˆ์ฐฌ๊ฐ€์ง€)
-> App.vue๋‚˜ ModalContainer์— ๋ช…์‹œ์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ™์—ฌ์ฃผ๋Š” ํ˜•ํƒœ๊ฐ€ ์•„๋‹ˆ๋ผ ๋™์  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ด€๋ฆฌ ํฌ์ธํŠธ๋Š” ์‚ฌ์šฉํ•˜๋Š” ์ชฝ์—์„œ๋งŒ ๊ด€๋ฆฌ๋˜์–ด ์ง„๋‹ค.
3. ์–ด๋–ค ๋ชจ๋‹ฌ์ด ์—ด๋ฆฌ๋Š”์ง€ ์ •ํ™•ํ•˜๊ฒŒ ์ฐพ์•„๋ณด๊ธฐ๊ฐ€ ํž˜๋“ค๋‹ค.
-> ํ•ด๋‹น ํ•จ์ˆ˜๋งŒ ๋ณด๊ณ  ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—ด๋ฆฌ๋Š”์ง€ ๋ฐ”๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
4. ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ด๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ ๋“ฑ๋ก ๋ฐฉ์‹๊ณผ ๋™์ผํ•œ ์‚ฌ์ดํด์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
-> key๊ฐ’์œผ๋กœ ์ž์œ  ์ž์žฌ๋กœ ๋™์ž‘์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“Œ ์™œ promise๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๊ฐ€?

Q> ์—๋”” ์™œ ํ•˜ํ•„ promise๋ฅผ ์‚ฌ์šฉํ–ˆ์–ด์š”?

์ฝ”๋“œ๋ฅผ ์ค‘๊ฐ„์— ์ž ์‹œ ๋ฉˆ์ถ”๋Š” promise์˜ ํŠน์„ฑ๊ณผ promise์˜ ๊ณ ์œ ์˜ ํŠน์„ฑ์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์–ด์„œ ์ž…๋‹ˆ๋‹ค.
ํŠนํžˆ reject๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„๊ฑฐ๋ผ๊ณ  ํŒ๋‹จ์„ ํ–ˆ์–ด์š”.
reject๋Š” ์ค‘๊ฐ„์— ์ฝ”๋“œ ์‹คํ–‰์„ ๊ฐ•์ œ์ ์œผ๋กœ ๋ฉˆ์ถ”๊ณ  ๋Œ์•„๊ฐ€๋Š” ํŠน์„ฑ์ด ์žˆ์–ด์š”.

์˜ˆ๋ฅผ ๋“ค์–ด ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณผ๊ฒŒ์š”.

const onClick = async () => {
  const myname: string = await hello<string>();
  console.log(myname)
}

hello(Promise)๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ํŠน์ • ์ƒํ™ฉ์ผ๋•Œ reject๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค๊ณ  ๊ฐ€์ •์„ ํ•œ๋‹ค๋ฉด ๊ทธ๋ฆฌ๊ณ  console.log๋ฅผ ์ฐ์œผ๋ฉด ์•ˆ๋˜๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด reject๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์–ด์š”.

์ข€ ๋” ์‹ค๋ฌด์ ์ธ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด๋ณผ๊ฒŒ์š”. ๋งŒ์•ฝ ์Šน๊ฐ์ด ํƒ์‹œ๋น„๋ฅผ ์ง€๋ถˆํ–ˆ๋‹ค๋ฉด ์Šน๊ฐ๊ณผ ๊ธฐ์‚ฌ๋‹˜์—๊ฒŒ notification์„ ๋ณด๋‚ด์•ผํ•˜๊ณ  ์ง€๋ถˆ์„ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด notification์„ ๋ณด๋‚ด๋ฉด ์•ˆ๋œ๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„์š”.

const onClick = async () => {
  await payKakaoTexi(); // ์Šน๊ฐ์ด ๊ธˆ์•ก์„ ์ง€๋ถˆํ•˜๋ฉด resolve ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด reject
  sendNotifictationToClient();
  sendNotificationToDriver();
}

๐Ÿ“Œ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„์„ ํ•ด์•ผํ• ๊นŒ?

๐Ÿšง ํ•ด๋‹น ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์€ vue3 ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

vue3์—์„œ์˜ createApp์„ ์‚ฌ์šฉํ•˜๊ณ  ์ด๊ฒƒ์„ plugin ํ˜•ํƒœ๋กœ ๊ด€๋ฆฌ๋ฅผ ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์•„์ด๋“ค์ด ํ•„์š”ํ•ด์š”.

  1. ModalContainer (์ƒˆ๋กœ์šด root app)
  2. ๋‚˜์˜ app๊ณผ ์ƒˆ๋กœ์šด root app(modalContainer)๋ฅผ ์—ฐ๊ฒฐํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ
  3. ModalContainer์˜ ํ•จ์ˆ˜๋“ค์„ ์ „์—ญ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ

ModalContainer ๋งŒ๋“ค๊ธฐ

๋จผ์ € Modal์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ModalContainer๋ฅผ ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค. ์ „์ฒด์ ์ธ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

<template>
  <div>
    <component
      v-for="modal in modals"
      :key="modal.key"
      :is="modal.component"
      v-bind="modal.props"
      @resolve="(value) => onResolve(value, modal.key, modal.resolve)"
      @reject="(value) => onReject(value, modal.key, modal.reject)"
      @close="() => closeModal(modal.key)"
    />
  </div>
</template>

<script>
import { markRaw } from 'vue';

export default {
  name: 'ModalContainer',
  data: () => ({
    modals: []
  }),
  methods: {
    addModal(key, component, configs) {
      const props = configs?.props ?? {};
      this.closeModal(key);
      return new Promise((resolve, reject) => {
        this.modals.push({
          key,
          component: markRaw(component),
          props,
          resolve,
          reject
        });
      });
    },
    closeModal(key) {
      this.modals = this.modals.filter(modalInfo => {
        if (modalInfo.key === key) {
          modalInfo.reject();
          return false;
        } else {
          return true;
        }
      });
    },
    onResolve(value, key, resolve) {
      resolve(value);
      this.closeModal(key);
    },
    onReject(value, key, reject) {
      reject(value);
      this.closeModal(key);
    }
  }
};
</script>

์ด์ œ ํ•˜๋‚˜ํ•˜๋‚˜์”ฉ ์‚ดํŽด ๋ณผ๊นŒ์š”? ๋จผ์ € template ๋ถ€๋ถ„์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// Modals ์˜ ํƒ€์ž…
// interface Modal {
//   key: string;
//   component: Vue.Component;
//   resolve: Promise.resolve
//   reject: Promise.reject
//   props: unknown 
// }

<template>
  <div>
    <component
      v-for="modal in modals"
      :key="modal.key"
      :is="modal.component"
      v-bind="modal.props"
      @resolve="(value) => onResolve(value, modal.key, modal.resolve)"
      @reject="(value) => onReject(value, modal.key, modal.reject)"
      @close="() => closeModal(modal.key)"
    />
  </div>
</template>

๋ˆˆ์น˜๋ฅผ ์ฑ„์…จ๋‹ค ์‹ถ์ด @resolve, @reject, @close๋ฅผ ๊ฐ๊ฐ์˜ ๋ชจ๋‹ฌ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ๋Š” ํ˜•ํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์„ ํ•˜๋Š” ์ชฝ์—์„œ resolve, reject, close๋ฅผ emit์œผ๋กœ ๊ฐ๊ฐ์˜ ์ƒํ™ฉ์„ ์„ค์ • ํ•  ์ˆ˜ ์žˆ์–ด์š”.
๋งŒ์•ฝ์— ์–ด๋–ค ๋ชจ๋‹ฌ์—์„œ ์ž…๋ ฅ ๊ฐ’์„ ๋ฐ›๊ณ  ๊ทธ ์ž…๋ ฅ ๊ฐ’์„ ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌ์„ ํ•ด์•ผํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณธ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ๋ชจ๋‹ฌ ์ฝ”๋“œ๋Š” ์ด๋ ‡๊ฒŒ ์ž‘์„ฑ์ด ๋ ๊ฑฐ์˜ˆ์š”.

<template>
   <div>
      <input v-model="myInput" />
      <button @click="$emit('resolve', myInput)">Submit</button
   </div>
</template>

๊ทธ๋ฆฌ๊ณ  ์ด์ œ script ๋ถ€๋ถ„์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

import { markRaw } from 'vue';

export default {
  name: 'ModalContainer',
  data: () => ({
    // Modals ์˜ ํƒ€์ž…
    // interface Modal {
    //   key: string;
    //   component: Vue.Component;
    //   resolve: Promise.resolve
    //   reject: Promise.reject
    //   props: unknown 
    // }
    modals: [] 
  }),
  methods: {
    // ๊ฐ ์ฝ”๋“œ๋ฅผ modals์— ๋„ฃ์–ด์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ Promise๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋Œ€๊ธฐ ์ƒํƒœ๋กœ ๋งŒ๋“ค์–ด์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    // ๋Œ€๊ธฐ ์ƒํƒœ๊ฐ€ ํ’€๋ฆฌ๋Š”๊ฑด ๊ฐ ๋ชจ๋‹ฌ์—์„œ ๊ฒฐ์ •ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ($emit)
    addModal(key, component, configs) {
      const props = configs?.props ?? {};
      this.closeModal(key);
      return new Promise((resolve, reject) => {
        this.modals.push({
          key,
          // markRaw ๋ฅผ ์‚ฌ์šฉํ•ด์ค€ ์ด์œ ๋Š” ๊ทธ๋ƒฅ component๋ฅผ ๋˜์ง€๊ฒŒ ๋˜๋ฉด ์„ฑ๋Šฅ ์ด์Šˆ๊ฐ€ ์žˆ์–ด์„œ raw ํ•œ component๋กœ ๋ณ€๊ฒฝ ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. 
          component: markRaw(component), 
          props,
          resolve,
          reject
        });
      });
    },
    // ํ•ด๋‹น ๋ชจ๋‹ฌ์„ ๋‹ซ์•„ ์ฃผ๊ฒŒ๋ฉ๋‹ˆ๋‹ค.
    closeModal(key) {
      this.modals = this.modals.filter(modalInfo => {
        if (modalInfo.key === key) {
          // ์—ฌ๊ธฐ์„œ๋Š” reject๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์—ˆ์–ด์š”. resolve๋กœ ๋ณ€๊ฒฝํ•˜์…”๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค.
          // reject๋กœ ์‚ฌ์šฉ์„ ํ–ˆ๋˜ ์ด์œ ๋Š” ์œ„์— Promise ๋ถ€๋ถ„๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ 
          // ๋‹ซ๊ฒŒ ๋˜๋ฉด Promise ๋กœ ๋Œ€๊ธฐ ๋˜์–ด์กŒ๋˜ ์ฝ”๋“œ ์•„๋ž˜์˜ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰์ด ๋˜๋Š”๊ฑธ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.
          modalInfo.reject();
          return false;
        } else {
          return true;
        }
      });
    },
    onResolve(value, key, resolve) {
      resolve(value);
      this.closeModal(key);
    },
    onReject(value, key, reject) {
      reject(value);
      this.closeModal(key);
    }
  }
};

ModalPlugin ๋งŒ๋“ค๊ธฐ

๊ทธ๋Ÿผ ์ด์ œ ํ•œ๋ฒˆ ์‹ค์ œ๋กœ ์—ฐ๊ฒฐ์„ ํ•ด๋ณผ๊นŒ์š”?

import { createApp } from 'vue';
import ModalContainer from '@/modal/ModalContainer';

const createModalEl = () => {
  if (!document) throw new Error('Cannot create el in server side');
  const modalEl = document.createElement('div');
  modalEl.setAttribute('id', 'modal');
  document.body.prepend(modalEl);
  return modalEl;
};

export default {
  install(app) {
    const modalEl = createModalEl();
    const modalContainer = createApp(ModalContainer);
    const exposed = modalContainer.mount(modalEl);
    app.config.globalProperties.$modal = exposed;
    // app์˜ globalProperties๋ฅผ ๊ฐ€์ ธ์™€์„œ this๋ฅผ ๋™๊ธฐํ™” ์‹œํ‚จ๋‹ค.
    modalContainer.config.globalProperties = { ...modalContainer.config.globalProperties, ...app.config.globalProperties };
  }
};

์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

๊ทธ๋Ÿผ ์ด์ œ ํ•œ๋ฒˆ ๋ชจ๋‹ฌ์„ ๋„์›Œ๋ณผ๊นŒ์š”? ์ฝ”๋“œ๋กœ ํ‘œํ˜„์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

<template>
  <section>
    <h1>Container1 normal vue</h1>
    <my-button @click="onClick">click me!</my-button>
  </section>
</template>

<script>
import SimpleModal from '../components/SimpleModal.vue';
import MyButton from '../components/MyButton.vue';

export default {
  components: { MyButton },
  methods: {
    async onClick() {
      const name = await this.$modal.addModal(
        'SimpleModal',
        SimpleModal,
        { props: { myName: 'Eddie' } },
      });
      alert(name);
    },
  },
};
</script>

๋™์ž‘ํ•˜๋Š” ๋ชจ์Šต์ž…๋‹ˆ๋‹ค.

๐Ÿ“Œ ๊ทธ๋Ÿผ ํ›…์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ์ด ๋˜์–ด์งˆ๊นŒ?

ํ›…์€ ์ด๋ ‡๊ฒŒ ์ •์˜๋ฅผ ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

import { getCurrentInstance } from 'vue';

// getCurrentInstance๋กœ ํ˜„์žฌ ๋ถˆ๋ฆฌ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฒ€์ƒ‰ ํ•œ๋’ค์— $modal์„ ์ฐพ์•„์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
const useModal = () => getCurrentInstance()?.appContext?.app?.config?.globalProperties?.$modal;

export default useModal;

๊ทธ๋Ÿผ setup ๋ฌธ๋ฒ•์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉ์ด ๋˜์–ด์งˆ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”.

<script setup>
import useModal from '@/modal/useModal';
import SimpleModal from '@/components/SimpleModal';

const modal = useModal();

const onClick = async () => {
  const value = await modal.addModal('SimpleModal', SimpleModal, { props: { name: 'eddie' } });
  alert(value);
};
</script>

๐Ÿ“Œ ๊ฒฐ๋ก 

์ด๋ ‡๊ฒŒ ํ•œ๋ฒˆ vue์—์„œ ๋ชจ๋‹ฌ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. (ํ˜น์‹œ ๋” ์ข‹์€ ์˜๊ฒฌ์žˆ์œผ์‹œ๋‹ค๋ฉด ์ž์œ ๋กญ๊ฒŒ ๋Œ“๊ธ€ ๋‹ฌ์•„์ฃผ์„ธ์š”. ๐Ÿ™‡๐Ÿปโ€โ™‚๏ธ).
ํ˜น์‹œ ํ•ด๋‹น ๊ธ€์ด ์–ด๋ ต๊ณ  ๊ตฌํ˜„ํ•˜๊ธฐ ๊ท€์ฐฎ์œผ์‹œ๋‹ค๋ฉด ์ œ๊ฐ€ ๊ณต๊ฐœํ•œ ์˜คํ”ˆ ์†Œ์Šค vue3-use-modal๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์‹œ๋ฉด ๋ ๊ฑฐ์˜ˆ์š”! ๋งŽ์€ ๊ด€์‹ฌ๊ณผ ์‚ฌ๋ž‘ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค ๐Ÿฆ!

๋ฐ˜์‘ํ˜•

'Vue Study' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

ํšŒ์‚ฌ vue ํ”„๋กœ์ ํŠธ vite ์ ์šฉํ•˜๊ธฐ  (2) 2022.01.01
Vue2 ClientOnly ์ปดํฌ๋„ŒํŠธ ์ œ์ž‘๊ธฐ  (0) 2021.07.29
Vue2 ๋นŒ๋“œ ํƒ€์ž„ ์ตœ์ ํ™”  (0) 2021.07.29
Vue3 - v model  (0) 2020.11.08
Vue3 - teleport  (0) 2020.11.08
  1. ๐Ÿ“Œ ๋ชฉ์ฐจ
  2. ๐Ÿ“Œ ์„œ๋ก 
  3. ๐Ÿ“Œ ๊ธฐ์กด ๋ชจ๋‹ฌ ๊ด€๋ฆฌ
  4. ๐Ÿ“Œ ๊ธฐ์กด ๋ชจ๋‹ฌ ๊ด€๋ฆฌ์˜ ๋ฌธ์ œ์ 
  5. 1. ๋งŒ์•ฝ์— ๊ด€๋ฆฌ๋ฅผ ํ•ด์•ผํ•  ๋ชจ๋‹ฌ์ด ๋งŽ์•„ ์ง„๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
  6. 2. vuex์˜ mutations๋งŒ ๋ณด๊ณ  ์‹ค์ œ๋กœ ์–ด๋–ค ๋ชจ๋‹ฌ์ด ๋›ฐ์–ด์ง€๋Š”์ง€ ํ•œ๋ฒˆ์— ํŒŒ์•…์ด ๊ฐ€๋Šฅํ•œ๊ฐ€?
  7. 3. ๋งŒ์•ฝ์— ๋™์‹œ์— ๊ฐ™์€ ๋ชจ๋‹ฌ์„ ๋„์›Œ์•ผ ํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
  8. 4. ๋งŒ์•ฝ์— ๋ชจ๋‹ฌ์—์„œ ์–ด๋–ค ๊ฐ’์„ ๋ฐ›์•„์„œ ํŽ˜์ด์ง€์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผํ•œ๋‹ค๋ฉด?
  9. ๐Ÿšง ๋ฌธ์ œ์  ๋ชจ์•„๋ณด๊ธฐ
  10. ๐Ÿ“Œ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ ํ•ด์•ผํ• ๊นŒ? interface ์žก์•„๋ณด๊ธฐ
  11. vue3 setup
  12. vue3 ์ผ๋ฐ˜ ๋ฌธ๋ฒ•
  13. ๐Ÿ“Œ ์™œ promise๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๊ฐ€?
  14. ๐Ÿ“Œ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„์„ ํ•ด์•ผํ• ๊นŒ?
  15. ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ
  16. ๐Ÿ“Œ ๊ทธ๋Ÿผ ํ›…์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ์ด ๋˜์–ด์งˆ๊นŒ?
  17. ๐Ÿ“Œ ๊ฒฐ๋ก 
'Vue Study' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • ํšŒ์‚ฌ vue ํ”„๋กœ์ ํŠธ vite ์ ์šฉํ•˜๊ธฐ
  • Vue2 ClientOnly ์ปดํฌ๋„ŒํŠธ ์ œ์ž‘๊ธฐ
  • Vue2 ๋นŒ๋“œ ํƒ€์ž„ ์ตœ์ ํ™”
  • Vue3 - v model
eddie0329
eddie0329
Front-end Developer
๋ฐ˜์‘ํ˜•
eddie0329
Eddie Sunny's Blog
eddie0329
์ „์ฒด
์˜ค๋Š˜
์–ด์ œ
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (100)
    • Summary of Book (0)
    • Vue Study (11)
    • Vue TDD (9)
    • Vue BDD (5)
    • Design Pattern (9)
    • Javascript Study (3)
    • React Study (15)
    • React TDD (1)
    • Vue Storybook (2)
    • Refactoring (0)
    • Graphql_Apollo (3)
    • Svelte (8)
    • Open Source (1)
    • D3 (4)
    • Typescript (1)
    • CSS (2)
    • Android (0)
    • Java (0)
    • Kotlin (0)
    • ์žก๋‹ด (0)
    • Swift (19)
    • Rust (2)
    • ํšŒ์‚ฌ์ด์•ผ๊ธฐ (2)
    • ReactNative Study (2)
    • Vitest (0)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • Home

๊ณต์ง€์‚ฌํ•ญ

์ธ๊ธฐ ๊ธ€

ํƒœ๊ทธ

  • react-component-slot
  • Cypress
  • react useRef
  • javascript pattern
  • Javascript
  • react
  • D3
  • vue3
  • Kotlin
  • storybook6
  • TDD
  • swift
  • vue bdd
  • vue storybook
  • vue cypress
  • vue tdd
  • slot ํŒจํ„ด
  • Vue
  • apollo
  • TypeScript
  • React Native
  • BDD
  • jest
  • svelte
  • Design Pattern
  • client only
  • Vue test
  • CSS
  • swift5
  • Nextjs

์ตœ๊ทผ ๋Œ“๊ธ€

์ตœ๊ทผ ๊ธ€

hELLO ยท Designed By ์ •์ƒ์šฐ.
eddie0329
Vue์—์„œ modal ๊ด€๋ฆฌ ์‰ฝ๊ฒŒํ•˜๊ธฐ
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”

๋‹จ์ถ•ํ‚ค

๋‚ด ๋ธ”๋กœ๊ทธ

๋‚ด ๋ธ”๋กœ๊ทธ - ๊ด€๋ฆฌ์ž ํ™ˆ ์ „ํ™˜
Q
Q
์ƒˆ ๊ธ€ ์“ฐ๊ธฐ
W
W

๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๊ธ€

๊ธ€ ์ˆ˜์ • (๊ถŒํ•œ ์žˆ๋Š” ๊ฒฝ์šฐ)
E
E
๋Œ“๊ธ€ ์˜์—ญ์œผ๋กœ ์ด๋™
C
C

๋ชจ๋“  ์˜์—ญ

์ด ํŽ˜์ด์ง€์˜ URL ๋ณต์‚ฌ
S
S
๋งจ ์œ„๋กœ ์ด๋™
T
T
ํ‹ฐ์Šคํ† ๋ฆฌ ํ™ˆ ์ด๋™
H
H
๋‹จ์ถ•ํ‚ค ์•ˆ๋‚ด
Shift + /
โ‡ง + /

* ๋‹จ์ถ•ํ‚ค๋Š” ํ•œ๊ธ€/์˜๋ฌธ ๋Œ€์†Œ๋ฌธ์ž๋กœ ์ด์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํ‹ฐ์Šคํ† ๋ฆฌ ๊ธฐ๋ณธ ๋„๋ฉ”์ธ์—์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.