Vue 3.2 에서 필수로 짚고 넘어가야 할 미래
Tags: javascript, vue, tutorial, korean
Published: 2022-06-21 08:31:18

현재 내가 실무에서는 React를 하고 있지만 너희들이 내 근황 굳이 관심 가지고 싶냐?

Vue 개발자에게 한마디로 어그로 끌어보겠다. 난 Vuex가 매우 싫다.
하는김에 React 개발자에게도 어그로 끌겠다. 난 Redux 도 매우 싫다.
Vuex가 Deprecated 된 거 축하한다. 빠밤.

Vue 3.2가 출시한지 꽤 지났다.
사실 나는 3.2가 나올 때 쯤에도 난 백엔드에만 몰두하고 있었다.
왜냐면 실무에 내 역할은 백엔드 뿐이었거든.
지금은 프론트엔드로 React 하고 있다.
그래서 Vue 근황에 대해서는 딱히 들은 것도 없다. 내가 안 찾아봐서.
그리하여 직접 찾아보고, 너희들에게 일용할 양식이 되어 무료급식소처럼 나눠줄 테니 감사히 먹도록.

## `<script setup>`

내가 가장 기대하던 기능이다. 정식 기능으로 추가된 소식은 이미 알고 있던 터라 대충 커버 이미지같은 흐뭇한 미소가 절로 나올 정도다. 컴포넌트의 정의부터 노출까지 함수로 단 한번에 해결할 수 있다. Vue 에서는 이 태그는 곧 어자피 Composition API의 setup() 함수 본문으로 취급한다고 보면 된다. 하지만 [`<script setup>`](https://vuejs.org/api/sfc-script-setup.html)을 쓰면 기존 API의 속성들을 날로 못 써먹기 때문에 `defineProps()` 같은 기능성 함수를 vue에서 제공한다.
백문이 불여일견. 비교해보자.

```vue
<script>

// 물론 defineComponent 쓰면 좋지만 예제를 위해 생략
export default {
  name: '네컴포넌트',
  props: [...여기에 컴포넌트 속성들],
  components: [...여기에 이 컴포넌트에 사용할 컴포넌트들],
  setup() {
    return {
      ...여기에 부모 컴포넌트에 전달할 이 컴포넌트의 속성들
    }
  }
}
</script>
```

이지랄 했던 것을

```vue
<script setup> 
import 다른컴포넌트 from 'path/to/component.vue'

defineProps([...여기에 컴포넌트 속성들])
// 뭐? component 속성 어디갔냐고? 여긴 필요없단다.
defineExpose({
  ...여기에 부모 컴포넌트에 전달할 이 컴포넌트의 속성들
});
</script>
```

이렇게 할 수 있다. 개인적으로 함수형이라 아주 보기 좋다.

![대충 흐뭇한 짤](http://rgo4.com/files/attach/images/2676751/459/453/010/7d13b33fab67c645a409924ddfb6ef00.jpg)

아 참고로, `defineProps` 같이 기존 속성에 있던 함수들은 `import` 안 해도 된다. [컴파일러 매크로](https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits)기 때문이다.

## `expose`

일단, `setup` 함수 사용법이 좀 달라졌는데,
먼저, 기존에 니들이 많이 쓰는 객체 리턴은 3.2 에서도 먹힌다.
여기서 3.2 업글 시 반드시 너희들이 짚고 넘어가야 할 인자가 있다.
3.2 나온 지 거의 1년 되가는데 설명하는 김치들이 한 마리도 없어서 내가 친절히 설명해 주겠다. 음... 판교 개발자들 너희들만 알려고 한 거 아니지?

바로, [`expose`](https://vuejs.org/api/composition-api-setup.html#exposing-public-properties) 함수다. 대충 카메라에 '노출'이라는 용어로 쓰는 단어다. 발음은 알아서들 하시고.

어쨌든, 이걸로 부모 컴포넌트에게 전달할 수단이 생긴다.
대신 리턴값이 필요없다. 왜그런진 후술.

```vue
<script>
export default {
  setup(props, { expose }) {
    const counter = ref(0);
    const privateFunc = () => { ... };
    const publicFunc = () => void (counter = 0);
    expose({ counter, publicFunc });
  }
}
</script>
```

이 `expose` 함수를 통해 기존 `setup` 함수의 `return` 문을 통해 부모로 속성을 전달할 때 쓰였던 속성들을 전달하면 된다. 이게 다다.
그런데, 왜 이렇게 변했는지 알고싶다면, 렌더링 함수(Render Function)이 그 주인공이다.

[렌더링 함수](https://vuejs.org/api/render-function.html)는 이미 있던 기능이다. 순서 자바스크립트나 타입스크립트, JSX/TSX 를 쓰고 싶은 개발자에게 Vue가 제공해주는 기능이다.

여기서 `setup` 함수에 [변화](https://vuejs.org/api/composition-api-setup.html#usage-with-render-functions)가 생겼는데, return 값을 함수로 뱉어낼 수 있는데, 함수로 뱉어내면 뱉어낸 요소를 렌더링할 것이다.

```js
import { h, ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    return () => h('div', count.value)
  }
}
```

이 문법이 상당히 중요해졌는데, 사소한 변화처럼 보이지만, 이 문법이 어떤 의미냐, JSX/TSX 사용자에겐 엄청나게 접근성이 향상됐다는 소리다. 위 코드를 JSX로 바꾼다면,

```jsx
import { h, ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    return () => <div>{ count.value }</div>
  }
}
```

봐라. React 함수형 컴포넌트 부럽지 않은 문법을 Vue에서도 제공한다는 소리다.
그렇다면 Vue의 강점인 부모 컴포넌트에다가 속성을 전달하는 방법은? 그 역할은 `expose` 함수가 대신해 준다는 얘기다.

차기 vue 버전이 어떻게 변할지는 내가 SFC 좀 봐야 알겠지만, 확실히 Vue에 대한 접근성을 다양화 하려는 노력이 눈물겹다고 할 수 있다.

예전부터 있던 사족인데, 내가 서양에서는 React가 압도적으로, 동양에서는 Vue가 근소하게(중국은 독점 수준) 앞선다고 했었다.
근데 요즘 한국에서는 React가 근소하게 점유율에서 Vue를 제쳤다. 재밌는 일이다.
사실 전자정부에서 프론트엔드를 React 강제할 거라고 어그로 끌었었는데, 이거와는 무관하게 React를 더욱 쓰기 시작했다. 네이버가 분발해야 하나 싶네...
일본의 경우는 Vue를 많이 쓴다. 중국이야 뭐 반강제고.

근데 왜 내가 갑자기 Vue 얘기를 꺼내냐면,

{%github https://github.com/composite/quasar-ssr-nestjs-boilerplate %}

내가 실무로 성공적으로 투입한 경험이 있는 애증의 프레임워크 Quasar 로 프레임워크 구축, 차기 실무에 구축할 계획을 가지고 있기 때문이다. 물론 Vue를 원한다면 말이지.

끗.