장기효

네이버 프런트엔드 개발자
캡틴판교의 프런트엔드 개발 상담소 유튜브 채널 운영
대학생, 실무자를 위한 인프런 멘토링 프로그램 운영
CaptainPangyo
Cracking Vue.js
1 / 59
1

장기효

네이버 프런트엔드 개발자
캡틴판교의 프런트엔드 개발 상담소 유튜브 채널 운영
대학생, 실무자를 위한 인프런 멘토링 프로그램 운영
CaptainPangyo
Cracking Vue.js
2

목차

  • Vue 3의 등장
  • 실무자가 바라본 Vue 3
  • 입문자의 고민
  • 실무자의 고민
  • Vue 3 준비와 도입 시기
3

Vue 3의 등장

4

Vue 3.0 - One Piece

5

Vue 3.0 - One Piece

6

Vue 3.0 - One Piece

7

강화된 타입스크립트 지원

8

코드 재사용을 위한 Composition API

<template>
  <div>{{ message }}</div>
  <button @click="changeMessage">변경</button>
</template>

<script>
import { defineComponent, ref } from 'vue';

export default defineComponent({
  setup() {
    // data 속성
    const message = ref('곧 바뀜');

    // 메서드
    const changeMessage = () => message.value = '바꼈다'

    return { message, changeMessage }
  }
})
</script>
<template>
  <div>{{ message }}</div>
  <button @click="changeMessage">변경</button>
</template>

<script>
import { defineComponent, ref } from 'vue';

export default defineComponent({
  setup() {
    // data 속성
    const message = ref('곧 바뀜');

    // 메서드
    const changeMessage = () => message.value = '바꼈다'

    return { message, changeMessage }
  }
})
</script>
9

Can I use ... Vue 3?

  • Teleport(Vue Portal)
  • Suspense
  • Multi v-model
  • 그외 템플릿 문법들
10

오! 그럼 이제 Vue 3를 써야겠네요?


옆 팀 Vue.js 개발자

11

실무자가 바라본 Vue 3

12

Can I use ... Vue 3?

"Vue 3 나왔다던데 우리 프로젝트에 넣어보죠"




13

현재 프로젝트에서 사용 중인 뷰 라이브러리 목록

  • Vuetify, 스타 32.1K
  • Vuetable, 스타 2.1K
  • Vue-datepicker, 스타 1.3K
  • Vue-lazyload, 스타 7.4K
  • Vue-Chart, 스타 4.5K
14

현재 프로젝트에서 사용 중인 뷰 라이브러리 목록

  • Vuetify, 스타 32.1K
  • Vuetable, 스타 2.1K
  • Vue-datepicker, 스타 1.3K
  • Vue-lazyload, 스타 7.4K
  • Vue-Chart, 스타 4.5K
15

현재 프로젝트에서 사용 중인 뷰 라이브러리 목록

  • Vuetify, 스타 32.1K
  • Vuetable, 스타 2.1K
  • Vue-datepicker, 스타 1.3K
  • Vue-lazyload, 스타 7.4K
  • Vue-Chart, 스타 4.5K

Vue 3를 지원하는 커뮤니티 라이브러리는 없었다…

16

Can I use ... Vue 3?

"그럼 라이브러리 걷어내고 Vue 3로 새로 짜죠 뭐"




17

충격의 발표…

https://github.com/vuejs/rfcs/discussions/296

18

충격의 발표…

https://github.com/vuejs/rfcs/discussions/296

19

충격의 발표…

https://github.com/vuejs/rfcs/discussions/296

20

Can I use ... Vue 3?

우리 아직 는 지원해야 되는데요… (22년 6월 종료 예정인 IE)




21

희망은 있다

https://github.com/vuejs/rfcs/discussions/296

22

선택지가 없는 그들을 위한 은혜

https://github.com/vuejs/rfcs/blob/master/active-rfcs/0038-vue3-ie11-support.md

23

선택지가 없는 그들을 위한 은혜

https://github.com/vuejs/rfcs/blob/master/active-rfcs/0038-vue3-ie11-support.md

24

Can I use ... Vue 3?

한 줄 요약

이미 운영중인 서비스와 가 필요한 사이트는 Vue 2로




25

입문자의 고민

26

Can I use ... Vue 3?

"전 이제 배우려고 하는데 그럼 뭘 배워야 하나요?"

Vue 2 vs Vue 3




27

Can I use ... Vue 3?

당장 배워서 쓸 수 있는 Vue 2를 추천합니다. 왜냐구요?




28

NPM 다운로드 통계

2021년 9월 15일 기준

29

NPM 다운로드 통계

2021년 9월 15일 기준

30

Vue School의 권고

https://vueschool.io/articles/news/which-vue-js-version-to-use-in-2021-and-why/

31

Vue School의 권고

https://vueschool.io/articles/news/which-vue-js-version-to-use-in-2021-and-why/

32

Can I use ... Vue 3?

Vue 2
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
export default {
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
export default {
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
Vue 3
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
33

Can I use ... Vue 3?

Vue 2
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
export default {
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
export default {
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
Vue 3
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
34

Can I use ... Vue 3?

Vue 2
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
export default {
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
export default {
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
Vue 3
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
35

Can I use ... Vue 3?

Vue 2
<template>
  <div>
    <MyChild :message="message" @change="changeMessage" />
  </div>
</template>

<script>
import MyChild from './MyChild.vue';

export default {
  components: { MyChild },
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
<template>
  <div>
    <MyChild :message="message" @change="changeMessage" />
  </div>
</template>

<script>
import MyChild from './MyChild.vue';

export default {
  components: { MyChild },
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
Vue 3
<template>
  <div>
    <MyChild :message="message" @change="changeMessage" />
  </div>
</template>

<script>
import { defineComponent } from 'vue';
import MyChild from './MyChild.vue';

export default defineComponent({
  components: { MyChild },
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
<template>
  <div>
    <MyChild :message="message" @change="changeMessage" />
  </div>
</template>

<script>
import { defineComponent } from 'vue';
import MyChild from './MyChild.vue';

export default defineComponent({
  components: { MyChild },
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
36

Can I use ... Vue 3?

Vue 2
<template>
  <div>
    <MyChild :message="message" @change="changeMessage" />
  </div>
</template>

<script>
import MyChild from './MyChild.vue';

export default {
  components: { MyChild },
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
<template>
  <div>
    <MyChild :message="message" @change="changeMessage" />
  </div>
</template>

<script>
import MyChild from './MyChild.vue';

export default {
  components: { MyChild },
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 2';
    }
  }
}
</script>
Vue 3
<template>
  <div>
    <MyChild :message="message" @change="changeMessage" />
  </div>
</template>

<script>
import { defineComponent } from 'vue';
import MyChild from './MyChild.vue';

export default defineComponent({
  components: { MyChild },
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
<template>
  <div>
    <MyChild :message="message" @change="changeMessage" />
  </div>
</template>

<script>
import { defineComponent } from 'vue';
import MyChild from './MyChild.vue';

export default defineComponent({
  components: { MyChild },
  data() {
    return { message: 'hi' }
  },
  methods: {
    changeMessage() {
      this.message = 'hi Vue 3';
    }
  }
})
</script>
37

Can I use ... Vue 3?

Vue 2
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
import { ref } from '@vue/composition-api'

export default {
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 2';

    return { message, changeMessage }
  },
}
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
import { ref } from '@vue/composition-api'

export default {
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 2';

    return { message, changeMessage }
  },
}
</script>
Vue 3
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 3';

    return { message, changeMessage }
  },
})
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 3';

    return { message, changeMessage }
  },
})
</script>
38

Can I use ... Vue 3?

Vue 2
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
import { ref } from '@vue/composition-api'

export default {
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 2';

    return { message, changeMessage }
  },
}
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
import { ref } from '@vue/composition-api'

export default {
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 2';

    return { message, changeMessage }
  },
}
</script>
Vue 3
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 3';

    return { message, changeMessage }
  },
})
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 3';

    return { message, changeMessage }
  },
})
</script>
39

Can I use ... Vue 3?

Vue 2
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
import { ref } from '@vue/composition-api'

export default {
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 3';

    return { message, changeMessage }
  },
}
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
import { ref } from '@vue/composition-api'

export default {
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 3';

    return { message, changeMessage }
  },
}
</script>
Vue 3
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 3';

    return { message, changeMessage }
  },
})
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

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

export default defineComponent({
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi Vue 3';

    return { message, changeMessage }
  },
})
</script>
40

Can I use ... Vue 3?

한 줄 요약

Vue 2로 배워도 문제 없는 현재의 Vue.js 개발




41

실무자의 고민

42

Can I use ... Vue 3?

Vue 3에 새로 나온 기능들 써보고 싶은데 어떡하죠?




43

Can I use ... Vue 3?

Vue 2의 컴포지션 API와 타입스크립트




44

@vue/composition-api 란?

  • Vue 2에서 컴포넌트의 재사용 가능 로직을 작성할 수 있도록 도와주는 라이브러리
  • 함수 기반의 API 작성 방식 가능으로 타입스크립트 추론 이점 극대화
  • 데이터, 로직 목적별로 관심사 분리 가능
  • 리액트 훅의 방식을 채택하여 뒤늦게 나온 만큼 몇 가지 단점을 보완
    • 분기문, 반복문, 중첩 함수 내에서 사용 가능
    • 컴포넌트 생성 주기에 따라 최초에 한번만 실행
45

@vue/composition-api 예시

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
import { ref } from '@vue/composition-api'

export default {
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi composition';

    return { message, changeMessage }
  },
}
</script>
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">변경</button>
  </div>
</template>

<script>
import { ref } from '@vue/composition-api'

export default {
  setup() {
    const message = ref('hi');
    const changeMessage = () => message.value = 'hi composition';

    return { message, changeMessage }
  },
}
</script>
46

@vue/composition-api 적용 포인트 안내

composition-plugin-sample.vue 파일 참고

47

@vue/composition-api 사용시 주의 사항

  • 기존의 믹스인과 HOC를 이용한 코드 재활용 방식은 가급적 지양
  • 타입스크립트와 같이 사용했을 때 효과 상승
    • 훅에서 정의한 파일을 컴포넌트 안에서 재선언 했을 때 덮어쓰는 실수를 피할 수 있음
  • reactive 보다는 ref 지향
  • Vue 3에서 제공되는 API가 모두 지원되지는 않음
48

VueUse

  • Vue 2와 Vue 3 모두 사용 가능한 컴포지션 라이브러리
  • 148개 유틸 API 지원
  • Web API, Animation, Electron, Firebase, Router 등

49

Can I use ... Vue 3?

<template>
  <p>{{ message }}</p>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  data() {
    return { message: '' }
  },
  methods: {
    changeMessage() {
      this.message = 10; // X, Type Error
    }
  }
})
</script>
<template>
  <p>{{ message }}</p>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  data() {
    return { message: '' }
  },
  methods: {
    changeMessage() {
      this.message = 10; // X, Type Error
    }
  }
})
</script>
  • 클래스 문법보다는 Vue.extend()를 이용한 객체 문법 지향
  • TS 설정 파일에 noImplicitThis: true 옵션 추가
  • computed 속성 반환 타입은 꼭 정의
  • 스토어 및 기타 타입 정의는 d.ts 파일에 정의
50

실무 기존 프로젝트에 타입스크립트 적용하기

  1. CLI 명령어로 타입스크립트 플러그인 추가 or 타입스크립트 기반 새 프로젝트 생성
  2. 타입스크립트 설정 파일에 allowJs, noImplicitThis 등 옵션 추가
  3. 기본적인 타입 에러만 수정하고 any와 같은 약한 타입부터 점진적으로 적용
  4. npm run build가 가능한 수준의 타입 정의 및 수정
  5. strict 레벨을 올려가면서 효용성이 높은 곳에 점진적 타입 정의 진행

Tip!

  • VSCode Vetur 플러그인의 "ts + tab" 단축키를 이용해서 .vue 파일 생성
  • 프롭스 속성을 먼저 정의하고 컴포넌트 태그에서 자동 완성 지원 받기

더 자세한 가이드는 여기에!

51

Can I use ... Vue 3?

52

Can I use ... Vue 3?

한 줄 요약

Vue 2에서도 사용할 수 있는 Vue 3의 장점들

Composition & TypeScript




53

Vue 3 준비와 도입 시기

54

Can I use ... Vue 3?

그럼 Vue 3는 언제 쓰는게 좋을까요?




55

Can I use ... Vue 3?

  • 코어 및 커뮤니티 라이브러리 생태계가 충분히 성숙해 졌을 때
  • 아마도 IE 지원이 끝나는 내년 하반기 이후
  • 사용자 층과 브라우저를 선택할 수 있는 어드민을 개발할 때



56

Can I use ... Vue 3?

그 때까지 Composition과 TypeScript로 재밌게 개발해요




57

Thanks Slidev!

www.sli.dev



  • Vue 3로 개발된 프리젠테이션 도구
  • Thanks to Anthony, LinusBorg
  • 58

    감사합니다.

    Q & A

    https://joshua1988.github.io
    https://bit.ly/3mgTeWZ
    github.com/joshua1988
    59